utwordSystem v3.25.7
Decisions

Two grounds whose roles swap

Light and dark are one system with the roles exchanged, not two palettes.

D-001 · v2

Context

Outword needed a light and a dark mode. Two separately tuned palettes would double every contrast check and drift apart with each new screen.

Options

OptionWhy it lost
Dark onlyNo mode for players who want a light screen
Two palettes, tuned per modeEvery new component needs two sets of values and two contrast checks; drift is guaranteed
One set of roles, swappedChosen

Decision

Define each colour once as a role (--ground, --fg, --tile…) with a baked dark and light value. Components use only roles. The page of one mode is the ink of the other, and one attribute, data-mode, swaps them all.

Evidence

PairDarkLight
--fg on --ground
body text on the page
12.70AAA12.70AAA
PairDarkLight
--tile-ink on --tile
a letter on its tile
12.70AAA12.70AAA

Contrast is identical in both modes because the pair is the same two colours exchanged. Computed from the tokens on every build.

Consequences

  • A new screen needs one contrast check, not two.
  • A hardcoded colour is always wrong in one mode, which is why the rule against literals is absolute and the release check counts them.
  • The two semantic hues (green, rose) can't simply invert; they get their own dark and light values, tuned to pass on both grounds.