Public: anyone can read this; the crew can change it.

The look holds up under a keyboard, a thumb and poor light: contrast, focus and 44px, proved by a test #52

open not picked up yet opened this
opened this

Intent. static/app.css opens by claiming a 360px page with no horizontal scroll, every control 44px on a side and a visible focus ring on everything the keyboard reaches — and nothing in bun test checks any of it, so the first careless palette tweak takes it away silently.

Done looks like

  • [ ] src/pages/look.test.ts (new): one file, no dependency, no browser. It reads static/app.css and the HTML /style and / actually render, and every failure names the rule that broke and the number that broke it.
  • [ ] Contrast. The two palettes are parsed out of :root and the dark block, and every text colour over every background it is used on is at least 4.5:1. Measured on main today, all of them pass — muted 4.67 light / 6.57 dark, good 4.63, danger 4.78, accent 5.10, accent-fg on accent 5.52 — so this is a guard, not a repair, and the test should fail if any pair drops under. Non-text UI (--line, the focus ring) is 3:1 or is listed as a deliberate exception with its reason beside it.
  • [ ] Focus. A :focus-visible rule exists and reaches buttons, links, inputs and .choice; no rule anywhere sets outline: none or outline: 0 without a visible replacement in the same rule.
  • [ ] Targets. Every interactive selector resolves to at least var(--tap) (44px) of height — by min-height, or by line-height plus padding computed in the test — and the test lists the selectors it considers interactive, so a new control that is not in the list is a missing line rather than a silent pass.
  • [ ] Landmarks. src/pages/layout.ts starts with a skip link to #main that is invisible until focused; every page has exactly one <h1> and one <main>; every form control rendered at /style has a label or an aria-label.
  • [ ] Motion. Any transition or animation is off under prefers-reduced-motion: reduce.
  • [ ] /style gains one small section showing the focus ring, a 44px target and the skip link, so the claim can be seen at 360px and not only asserted.

Files src/pages/look.test.ts (new), static/app.css, src/pages/layout.ts, src/pages/style.ts, one line in AGENTS.md under the bar.

Risks This is not #32: that one guards bytes, dependencies and milliseconds, this one guards contrast, focus and reach — keep them two files and say so in both. The CSS reading must stay dumb and honest: a small regex over declarations is fine, and a rule the test cannot see truthfully is left out and named in the pull rather than half-asserted. static/app.css is also touched by the table page in flight (#40), so rebase before pushing.

Who @mason to build; @juniper is the brief this issue is written from and should review the result on a phone.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs