← Living Brand index

The Living Styleguide

Accessibility · WCAG 2.1 AA, with the system's real values
Accessibility
01

Contrast — the measured floor

Every text/background pair is verified, not eyeballed. Body ≥4.5:1, large text ≥3.0:1. The system's darkened -ink token variants exist specifically so small text clears the bar — raw accents don't.
PairRatioVerdict
ink on paper15.99Body ✓
ink-soft on paper8.00Body ✓
teal-ink on paper4.44Body ✓*
yellow-ink on paper4.71Body ✓
green-ink on paper5.07Body ✓
white on teal button2.57Large only
white on indigo button6.29Body ✓
Contrast

The floor

Body ≥ 4.5:1
Large (≥24px / ≥18.66px bold) ≥ 3.0:1
Non-text (borders, icons) ≥ 3.0:1
Small UI text → use the darkened -ink token, never the raw accent.

*teal-ink 4.44 is a hair under 4.5 — fine for large/medium, use ink-soft for dense small body.

02

The white-on-accent trap

White on teal is only 2.57:1 — it fails for body text and passes only because buttons use large bold type. The rule this forces: white-on-accent is a large-text-only move. Small white text on a bright accent is a real failure.
Start free →
✓ large bold white on teal — passes (large-text bar)
✕ small teal text like this on paper fails at 13px
✓ darkened teal-ink at the same size passes
White-on-accent

Large only

White on a bright accent passes only at large sizes. It is not a general-purpose pairing.

Button labels are ≥17px bold on purpose — that's what makes white-on-teal legal.
Small badge on accent? Darken the field or switch to ink text.
03

Focus — always visible

Keyboard users need to see where they are. Every interactive element gets a visible focus ring: 3px indigo, offset so it clears the shape. Tab through these — the ring only shows for keyboard, not mouse, via :focus-visible.
A link
↹ Tab through these to see the ring. Click them with a mouse — no ring (focus-visible).
Focus ring

3px indigo, offset

Visible on every interactive element, keyboard-only via focus-visible.

Never outline:none without a replacement — the #1 a11y failure.
:focus-visible{
  outline:3px solid #4F46E5;
  outline-offset:3px;
}
04

Motion — respect the setting

Motion can trigger nausea and migraines for people with vestibular conditions. The system honors prefers-reduced-motion everywhere, and every animation has a still state that loses no meaning. (Full detail lives in the Motion styleguide.)

The contract:

One media query disables all animation and transition. No motion is ever the sole carrier of information — a drawn line shows complete, a walking figure stands still, a counter shows its final value. Freezing the page loses delight, never meaning.

Motion policy

Not optional

Vestibular safety, not preference. Honored system-wide.

Meaning survives frozen — see the Motion styleguide's reduced-motion table.
@media(prefers-reduced-motion:
  reduce){ *{
  animation:none!important;
  transition:none!important}}
05

Touch targets — 44px minimum

On touch screens, a target smaller than about 44×44px is a miss-tap waiting to happen. A control can look small but must have a 44px hit area via padding.
✓ 44×44 — comfortable ✕ 26×26 — too small to reliably tap
Touch targets

44 × 44 floor

Every tappable control clears 44px, padding out a small glyph if needed.

Small icon? Keep the glyph small, pad the hit area to 44px.
min-width:44px;
min-height:44px;
06

Color is never the only signal

Roughly 1 in 12 men can't reliably tell red from green. So color never carries meaning alone — it's always backed by an icon, a label, or a shape. Red-with-an-✕ and green-with-a-✓, not just red and green.
✓ Passed — icon + label + colour
✕ Failed — icon + label + colour
Even in greyscale, the ✓/✕ and the words carry it. Colour is reinforcement, not the message.
Redundant coding

Never color alone

Every color signal is backed by icon, text, or shape.

Test: does it still read in greyscale? The wrong/right cards, statuses, and charts all must.
07

Semantics first, ARIA to fill gaps

A real <button> is accessible for free; a <div> pretending to be one is work. Use native HTML for its built-in semantics, and reach for ARIA only where HTML genuinely falls short — icon-only buttons, live regions, decorative SVGs.
SituationThe right move
A clickable thing<button> / <a>, not a div
Icon-only controlaria-label="Add"
Meaningful illustrationrole="img" + aria-label
Decorative illustrationaria-hidden="true"
Page structureh1→h2→h3 in order, nav/main
Form field<label for> tied to input
Semantics & ARIA

HTML does the work

Native elements first; ARIA only for real gaps.

First rule of ARIA: don't use ARIA if HTML already conveys it.
SVGs: role="img"+label if meaningful, aria-hidden if decorative.
Created for you, with ❤️ by Robert Evans · The AI Design Architect