A hue painted as text on a color-mix tint of itself sits close to the
surface under it. On Minstrel's surfaces the raw accent on its 15% tint
measures 1.97:1 at worst (dark mode, hover surface), against AA's 4.5.
- tokens.json gains colors.fg: the five FabledSword -fg formulas (accent
45%, success 45%, warning, error and info 50%), each mixed toward
parchment so one declaration serves both modes. Success is Minstrel's
moss. tokens-to-css emits them in :root.
- Tailwind exposes them as text-accent-fg, text-warning-fg, text-error-fg
and text-info-fg.
- 23 sites swapped: 14 Tailwind class strings (PlayerBar and the admin
count pills) and 9 CSS rules (StatusPill's four tones and five accent
chips). Worst case after: accent-fg 5.03, error-fg 4.75, warning-fg
4.92, success-fg 4.85.
- scripts/check-tint-contrast.js finds the pair in either spelling. Its
test scans src in the web Vitest lane and fails on any new site, with
fixture cases showing it can fail.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Flutter client (#356) needs to consume the same FabledSword tokens
the web SPA uses. Move the data into a structured tokens.json file and
generate tokens.generated.css from it on every Vite build. The Flutter
side gets its own generator pointed at the same JSON.
No visual change — generated CSS matches the previous hand-written file.
Also installs @types/node devDependency: tsconfig already declared
"types": ["node"] but no Node builtins were referenced in TS until now,
so the missing types were latent. The new vite.config.ts plugin imports
node:child_process, surfacing the gap.