Accessible by default ← Back to the site

Style guide

The visual language of this project, rendered live from the same tokens the site uses — so what you see here is exactly what ships. Colours follow your system's light/dark preference.

Color

Every colour is a semantic token declared once with light-dark(light, dark), so themes flip with no duplication. Hex pairs below read light · dark.

Brand

  • --color-primary #2563eb · #3b82f6
  • --color-primary-hover #1d4ed8 · #60a5fa
  • --color-accent #7c3aed · #a78bfa

--gradient-accent — primary → accent, used by demo components and image fallbacks. The logo itself uses flat ink and accent tokens (see Logo & naming below).

Surfaces

  • --color-bg #ffffff · #0f0f0f
  • --color-bg-subtle #f5f5f5 · #1a1a1a
  • --color-surface #ffffff · #1e1e1e
  • --color-border #e0e0e0 · #2e2e2e

Text

  • --color-text #111111 · #f0f0f0
  • --color-text-subtle #555555 · #a0a0a0

Status

  • --color-success #16a34a · #4ade80
  • --color-warning #d97706 · #fbbf24
  • --color-error #dc2626 · #f87171
  • --color-info #0284c7 · #38bdf8

Site chrome

The page chrome (paper, grid, frame, registration ticks, title block) reads its own token set, derived from the semantic tokens above in blueprint.css — so every theme preset, CVD variant, and contrast setting re-inks it with no extra rules.

  • --bp-sheet = --color-surface
  • --bp-ink = --color-text
  • --bp-accent = --color-primary
  • --bp-frame primary 42% mix
  • --bp-redline = --color-error

Theming

A theme is two OKLCH seeds — --seed-surface and --seed-accent — plus optional --mix-* contrast strengths; theming/engine.css derives the full contrast-safe palette from them (text flips to black or white against its seed, greys mix toward the text). The cards below render from their real .theme-* classes, so this page can't drift from the shipped values.

  • Default .surface
  • Ocean .theme-ocean
  • Midnight .theme-midnight
  • Sunset .theme-sunset
  • Cobalt .theme-cobalt
  • Teal .theme-teal
  • Amber .theme-amber
  • Contrast light .theme-contrast-light
  • Contrast dark .theme-contrast-dark

Cobalt, Teal, and Amber are tuned for colour-vision deficiency — lightness carries the signal, never hue alone. The Contrast pair raises the engine's --mix-* strengths and widens the focus ring: high contrast as data, not a duplicate palette. All eight ship in the site header's theme panel, persisted with a no-flash reload.

Typography

System sans for prose, JetBrains Mono for code and labels. Display sizes are fluid (clamp()) so headings scale with the viewport — no breakpoints.

Sans
system-ui — the platform's own UI typeface
Mono
JetBrains Mono — code, tokens, eyebrows
  • Display--text-display · 800
  • Heading 4xl--text-4xl · 2.25rem
  • Heading 3xl--text-3xl · 1.875rem
  • Heading 2xl--text-2xl · 1.5rem
  • Heading xl--text-xl · 1.25rem
  • Large body--text-lg · 1.125rem
  • Base body--text-base · 1rem
  • Small / captions--text-sm · 0.875rem

Spacing

A rem-based scale (token = rem × 4). The same rhythm drives gaps, padding, and the generous section breaks.

  • --space-1 · 0.25rem
  • --space-2 · 0.5rem
  • --space-3 · 0.75rem
  • --space-4 · 1rem
  • --space-6 · 1.5rem
  • --space-8 · 2rem
  • --space-12 · 3rem
  • --space-16 · 4rem
  • --space-24 · 6rem

Radius & elevation

  • sm · 0.25rem
  • md · 0.5rem
  • lg · 0.75rem
  • xl · 1rem
  • full
  • --shadow-sm
  • --shadow-md
  • --shadow-lg

Motion

Durations and easings are tokens so reduced-motion overrides work from one source. Hover the swatch to feel each curve; it holds still if you've asked your system to reduce motion.

  • fast · 150ms
  • normal · 250ms
  • slow · 400ms

Focus & elements

Bare elements, styled only by the foundation. Tab through them — the focus ring (--focus-ring-*) is consistent and never removed.

A text link inline code

Principles

  • Accessibility wins the cascade. User-preference layers (reduced motion, high contrast, forced colours) sit last in the @layer order, so they always override aesthetics.
  • Built in, not bolted on. Reach for the platform first; add JavaScript only when CSS and semantic HTML genuinely can't.
  • One source of truth. Colours, spacing, type, and motion are tokens — never hard-coded values.
  • Progressive enhancement. Modern features are wrapped in @supports so unsupported browsers degrade, never break.
  • Never remove focus. The focus ring is part of the brand, not an eyesore to suppress.

The mark is the numeronym a11y drawn with drafting instruments: a compass-drawn single-storey a (its center prick left in), two ruled lines standing in for the 11, and a straightedge y. Read fast, it also says ally — both readings are intended. Strokes overshoot only where they end in open air; everything sits on a shared baseline and x-height.

In the site header the mark is inline SVG on the ink and accent tokens, so it re-inks with every theme and flattens to a single color in forced-colors mode. The favicon adapts to light and dark with its own media query, and every raster asset (app icons, the link-preview image) is generated from one definition in scripts/gen-icons.mjs.

The name is Accessible by default — a11y-foundation is the repository, not the brand.