token layer:
- split destructive into three roles (text / surface / on-surface). dark
`text-destructive` measured 1.50–1.93:1 against the surface ladder — form
errors were near-unreadable. now 4.82–6.19 dark, 4.56–5.53 light. fills keep
their old values so buttons and badges render identically.
- add `brand-text`; `brand` as text was 3.42:1 on white.
- drop the dead `--font-pixel` token (silkscreen was never loaded) and the two
unimported fontsource deps it implied.
accessibility:
- motion is opt-in: MotionConfig reducedMotion="user" for framer, a media query
for css keyframes. the spinner is exempt.
- add the `main` landmark and a skip link — the app had neither.
- inset dialog gains a focus trap, focus restore, and an accessible name; its
backdrop is no longer a viewport-sized tab stop. same for the palette.
- skeletons are aria-hidden; route transitions announce once instead.
- inputs render at 16px under sm so ios stops zooming on focus.
- restore focus rings on three controls that killed them outright.
- name every nav landmark, chip remove, and rule toggle.
fixes:
- workflow cards were entirely unclickable: the stretched link had no z-index,
so the header and body painted over it. link to z-10, controls to z-20.
- the skip link rendered as a visible blob — react-grab writes an inline
clip-path that beats sr-only. park it off-screen by transform instead.
- switch `tone` prop replaces a dead `data-[state=checked]` class that never
matched base-ui's `data-checked`.
also: remove the redundant view-raw disclosure from rule cards, feedback form
gets real labels and keeps submit enabled, and commitlint now guards commit-msg
(see DECISIONS.md — the config accepts the `TRP-123 ` prefix, which stock
conventional-commits rejects).