12.1 Contrast
Every ratio below is computed from tokens/tokens.json at build time and
rendered live in the colour explorer.
Text on light surfaces
| Pairing | Ratio | Grade |
|---|---|---|
ink on paper | 16.14:1 | AAA |
ink-body on paper | 13.14:1 | AAA |
ink-muted on paper | 5.16:1 | AA |
ink-muted on white | 5.61:1 | AA |
ink-muted on mist | 4.87:1 | AA |
accent #C4602A on white | 4.16:1 | ✗ Fail |
accent-ink #A34A1F on white | 5.90:1 | AA |
accent-ink on paper | 5.43:1 | AA |
accent-ink on accent-light | 4.73:1 | AA |
Buttons
| Pairing | Ratio | Grade |
|---|---|---|
white on accent #C4602A | 4.16:1 | ✗ Fail |
white on accent-ink #A34A1F | 5.90:1 | AA |
white on accent-hover #A84E22 | 5.56:1 | AA |
Dark
| Pairing | Ratio | Grade |
|---|---|---|
on-ink on ink | 15.60:1 | AAA |
accent-lift #E07A38 on ink | 5.86:1 | AA |
accent #C4602A on ink | 4.23:1 | ✗ Fail for body |
dark.muted #98938C on ink | 5.76:1 | AA |
#7A7570 on ink | 3.85:1 | ✗ Fail for body |
Status pairings
All six clear AA: success 5.43:1 · attention 4.98:1 · warning 6.25:1 · error 8.98:1 · info 7.88:1.
The two rules that follow
#C4602Anever carries letterforms on a light surface. Use#A34A1F.#C4602Anever carries letterforms on a dark surface either. Use#E07A38.
12.2 Non-text contrast
WCAG 1.4.11 requires 3:1 for UI component boundaries and meaningful graphics.
| Pairing | Ratio | Verdict |
|---|---|---|
border-strong #D8D5D0 on white | 1.46:1 | Decorative only |
border #E5E2DE on white | 1.29:1 | Decorative only |
accent focus ring on paper | 3.82:1 | ✅ Passes |
Neither border colour identifies a control on its own. That is acceptable under the standard provided the control is identifiable another way — and in this system it always is:
- Inputs have a persistent visible label and a 3.82:1 focus ring.
- Buttons have a fill (
primary,destructive) or a text colour clearing 4.5:1 (secondary,ghost). - Cards are containers, not controls.
Do not ship a control whose only affordance is a #D8D5D0 hairline. If you
need a boundary to carry meaning by itself, darken it to at least #949089.
12.3 Focus
- One ring everywhere:
2px solid #C4602A,outline-offset: 2px. - Global in
tokens/since-brand.csson*:focus-visible. - Never
outline: nonewithout an equivalent replacement in the same rule. - The ring appears instantly — never transition a focus outline.
- Focus moves into a dialog on open and returns to the trigger on close.
- Tab order follows visual order.
12.4 Semantics
| Requirement | Detail |
|---|---|
One h1 per page | The PageHeader title. Never skip levels |
| Landmarks | <main>, <nav aria-label>, <aside>, <header> |
| Buttons vs links | A link navigates; a button acts. <div onClick> is a bug |
| Labels | Every input has a real <label for> |
| Tables | scope="col", and a visually hidden <caption> |
| Lists | Real <ul>/<ol>. Stat tiles are <dl> with dt/dd |
| Icons | aria-hidden="true"; the label goes on the control |
| Dialogs | role="dialog", aria-modal="true", aria-label |
| Current page | aria-current="page" on the active nav row and last crumb |
| Live regions | role="alert" on error and warning alerts only |
| Skip link | First focusable element on the page |
12.5 Colour independence
WCAG 1.4.1 — colour is never the only signal.
- Status chips carry a dot and a word.
- Chart series are labelled directly, not only via a legend swatch.
- Errors carry text, not just a red border.
- Required fields are marked in text.
- Links in prose are underlined, not colour-only.
Test: screenshot the page, desaturate it, and check every state is still readable.
12.6 Motion, targets, zoom
prefers-reduced-motion: reducecollapses every transition to 0.01ms. Ships in the token CSS.- Hit areas are 44×44px minimum, including padding.
- The layout must survive 200% zoom and a 375px viewport without horizontal page scroll. Wide tables scroll inside their own box.
- Text must reflow at 320px CSS width (WCAG 1.4.10).
12.7 Language and content
<html lang="en">;lang="fi"on Finnish passages.- Link text makes sense out of context — never "click here", never a bare URL.
altdescribes the information, not the picture. Decorative images getalt="".- Sentence case is easier to read than Title Case for people with dyslexia — another reason for the rule in verbal identity.
12.8 Review checklist
Before shipping any surface:
- Tab through it. Every control reachable, focus always visible, order sensible
- Desaturate it. Every state still legible
- Zoom to 200%. Nothing clipped, no horizontal page scroll
- 375px viewport. Tables scroll in their box; modals fit
- Every input has a visible label
- Every icon-only button has
aria-label - One h1; heading levels do not skip
- Error messages say what to do
- Text contrast ≥ 4.5:1; boundaries that carry meaning ≥ 3:1
- Reduced motion honoured