Make every publication theme clear WCAG AA contrast
The eight sky-phase presets only had body-text and button-text contrast under
test, but the themed reader renders accent as the link colour (accent-on-
background) and derives muted/secondary text and the button-hover fill — none of
which were checked. Auditing every text pairing found 5 of 8 themes with
effectively unreadable links and 5 of 8 with sub-AA muted text.
Fix it at both layers:
- Bake contrast-safe raw colours into the 5 failing presets. The stored
basicTheme record carries only 4 colours and other standard.site readers map
accent -> link directly (Decision 0012 interop), so the stored accent must
itself clear AA on its background. Each failing accent's lightness is adjusted
on-hue until it clears 4.5:1, with accentForeground re-chosen accordingly.
dusk/sunrise/midnight were already compliant and are unchanged.
- Make themeToCssVars derivations contrast-aware via a new ensureContrast helper
(HSL-lightness, hue preserved): links, link-hover, muted, ink-soft, and the
button-hover fill are clamped to AA against their worst-case surface. This also
protects arbitrary custom themes, not just the curated presets.
Decorative hairline borders stay low-contrast (as in the base design) and are
documented as WCAG-exempt. No CSS changes: the reader already consumes these
token names. Extends themes.test.ts with a per-preset audit over every text
pairing plus ensureContrast unit tests.