Ratios and grades are measured live from the current theme and mode. Body text passes AA on both ivory surfaces. Red on ink fails text contrast, so red stays a non-text signal.
Disabled state lowers opacity to 0.4 and switches stroke to grey-300 — never grey-500 (which would still pass AA and make the control look dimmed but real). Disabled means dead.
§E · Motion · the prefers-reduced-motion contract
SPINNER900ms continuous rotate (default)slows to 4s rotation when prefers-reduced-motion
LIVE DOT1.4s pulse · opacity 1 → 0.4 → 1animation: none · stays at full opacity
SKELETONshimmer · 1.4s linear, infinitestatic --ivory-2 block (no shimmer)
DECK SLIDES280ms ease-out cross-fadeinstant cut · no fade
CHART REVEALSstaggered 60ms per seriesall series appear together · static
SCROLLnative browser smooth-scroll if user has itnever scroll-behavior: smooth in our CSS
Every animation in the system has a @media (prefers-reduced-motion: reduce) branch. We never remove the affordance — a spinner still spins, just slower. The brand stays recognizable; the strobe goes away.
§F · Semantics · what the markup tells the screen reader
§ Required
Headings nest. One h1 per page. Sections use h2 through h4 in order.
Landmarks.main, nav, aside, footer on every page. Skip link targets main.
Labels are real.<label for> on every input. Placeholder is never the label.
Modals trap focus. Tab cycles inside; Esc closes; focus returns to the trigger.
Live regions. Toasts post into role="status" for info/success and role="alert" for warn/error.
Icons are aria-hidden="true" when redundant with text. Standalone (close, search) carry role="img" + <title>.
§ Banned
A div with a click handler — use a button
Color as the only signal — every red item also carries a label, dot, or icon
outline: none without a replacement
Scroll-jacking, parallax, autoplay video
Tooltips for primary content — they're keyboard-hostile
Placeholder text doing the job of a label
Tabindex values higher than 0
Modal opens and focus stays on the page underneath
Body AAA · Captions AA · Focus 2px ink, :focus-visible · Motion honors reduced-motion · DocA11Y.md