A Design System You Can Prove
Hand-picked palettes fail accessibility quietly. Derived ones do not. The gap measured 18 of 22 against 22 of 22.
What
Discovery for a client usually ends with a document describing a design system, and separately some code that is meant to implement it. The two drift the moment either is edited. This generator produces both from one token file: a styled PDF the client reads, and the globals.css their developers drop into the app. The split is judgment against arithmetic. A model chooses the aesthetics, the hue family, the type pairing, whether the system uses glass and why. Scripts do every piece of maths: the OKLCH ramps, the type scale, the full contrast matrix.
The decision that mattered
One token file, many renderers, and the model never writes a colour value. Semantic roles are not pinned to fixed ramp steps either, because WCAG luminance does not track OKLCH lightness evenly across hues. Each role searches its own ramp for the first step that clears its threshold, which is what makes the result correct for any hue rather than for the one it was tuned against.
Deriving a palette means giving up direct control of the exact hex. A client who arrives with one specific blue gets it as the anchor, not as a free choice across all nineteen semantic roles, because the other eighteen still have to stay legible against it.
Good / Bad / Ugly
Three unrelated derived palettes each score 22 of 22 gated contrast pairs. A hand-assembled one, built from a published palette the way a competent developer would, scores 18.
The first version pinned semantic roles to fixed ramp indices. All three test palettes then failed on the same pairs at slightly different ratios, which is the detail that gave it away as a systematic bug rather than a tuning problem.
The shared fixture had 71 of its 93 colours storing a hex that disagreed with its own OKLCH values. The renderer read the hex, the contrast gate reasoned in OKLCH, and for a while the two were quietly measuring different palettes. Nothing surfaced it until two components had to agree on a single number.
Shipped
Brief to PDF to globals.css in one command, gated on WCAG AA, dogfooded on this portal itself and now running in the app.
Next
Per-theme contrast, since one setting currently applies to both light and dark, and anchoring the background to a client's existing brand colour instead of arriving at it by trial.