Fix accessibility and performance issues across the page set - #123
Merged
Merged
Conversation
Answer grading was conveyed by background color alone and never announced, which made the product's central action unreadable for screen-reader users and unreliable for red-green colorblind students: the correct and wrong fills sit at 1.36:1 against each other. Accessibility - Label each feedback cell "✓ correct" / "✗ try again" alongside the fill. Black on either fill holds 7.1:1 and 5.3:1. - Announce outcomes via a role="status" aria-live region. - Name the answer inputs, the like/dislike buttons, and the language nav. - Add meta charset, promote the wordmark to the page's single h1, and give every image alt text and intrinsic dimensions. - Make the sign-in modal close control a real button; it was a span with an onClick and could not be reached by keyboard. Contrast (hue and saturation preserved, lightness reduced until AA passes) - Chalk Blue heading #419DC1 -> #337E9C (3.08:1 -> 4.56:1) - Success text -> #3E862E (2.22:1 -> 4.51:1) - Error text -> #ED0000 (3.81:1 -> 4.56:1) - a:hover underlines instead of turning red, so red means only "wrong" The accent was also emitted as an inline style on elements that already carried text-rb-header, so the inline value won and darkening the token alone would have had no effect. HEADER_COLOR and all 13 call sites are gone. Performance - Thumbs-up/down were 1600x1600 rendered at 30x30: 345 KB -> 12 KB, on every challenge page. - Replace the Font Awesome CDN stylesheet with an .rb-spinner rule that honors prefers-reduced-motion. The like/dislike and admin spinners used fa-spin on pages that never loaded Font Awesome, so they were invisible. - Error-page photographs stored as PNG converted to JPEG: 241 KB -> 36 KB and 200 KB -> 35 KB. Also declares a fixed width=1024 viewport rather than width=device-width, which without responsive CSS would trade a zoomed-but-coherent phone rendering for horizontal-scroll breakage; raises sub-24px hit areas; removes dead td.ok/td.no rules; and routes message colors through Message.colorClass instead of inline hex. DESIGN.md and PRODUCT.md record the design system and product context this work was measured against. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
.impeccable/ is otherwise a tracked output directory: design.json is the design-system sidecar and belongs in the repo. Two things in there do not. config.local.json records one developer's hook consent, and live/sessions/ is an append-only recovery journal for an in-progress editing session. Neither describes the project, and config.local.json was already showing up as untracked after the previous commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
hook.cache.json and hook.pending.json are keyed by session id and hold absolute paths from a single machine. The tooling excludes them via .git/info/exclude, which is local to one clone, so they surfaced as untracked for everyone else. Duplicate the rules here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
This was referenced Aug 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Runs the vendored
impeccabledesign workflow end to end against the page set — document, audit, then all six remediation actions — and lands the resulting fixes.Accessibility
checkAnswerspainted a cell green or red and nothing else, so a screen-reader user got no result at all and a colorblind user got two fills measuring 1.36:1 against each other. Feedback cells now carry✓ correct/✗ try againtext, and the status cell is arole="status"/aria-live="polite"region reportingN of M correct.aria-label="Return value for <invocation>"— previously they were unlabeled.alt="".spanwith anonClick— now a realbuttonwitharia-label="Close sign-in dialog"at 28×28.bodyTitle()emits the wordmark ash1; the language nav gotaria-label="Languages".<meta charset>and a viewport tag.Contrast
The pass/fail green and red met contrast as fills but not as text. Added
rb-correct-text(#3E862E) andrb-wrong-text(#ED0000) as separate tokens for text use, and darkenedrb-headerto#337E9Cfor AA at its size.HEADER_COLORwas being emitted as an inline style on the same elements that already carriedtext-rb-header, so the inline value won and darkening the token alone would have been a silent no-op. The constant and all 13 call sites are gone.Link hover was
color: red, which collided with the wrongness signal — now an underline.Performance
nervous.png/panic.png→ JPEG, ~450 KB → ~72 KB.imgsites got explicitwidth/height(no layout shift) andloadinghints.Latent bug fixed
The like/dislike and admin spinners used
fa-spin, but Font Awesome is not loaded on those pages — the spinners were invisible. Replaced with a CSS.rb-spinner, including aprefers-reduced-motionbranch.Design record
PRODUCT.md,DESIGN.md, and.impeccable/design.jsoncapture the product context and the design system the audit was run against. Per-machine.impeccable/state is gitignored; the durable output is tracked.One deliberate departure
The audit recommended
width=device-width. This shipswidth=1024instead. With no responsive CSS anywhere in the page set,device-widthwould trade a zoomed-but-coherent phone rendering for horizontal-scroll breakage. Worth revisiting once responsive work lands.Not included
Deferred and each worth its own change:
<main>/<header>landmarks (needs aBODY→FlowContentreceiver refactor across 27 pages), a custom:focus-visibletreatment, and deleting the orphanedtw-safelist.html.Verification
make build,make lint, and./gradlew checkall pass.🤖 Generated with Claude Code