One hue, two modes
How Kyndium's color system generates every neutral from a single hue in OKLCH, keeps text readable in light and dark, and why the nav band is the same color in both.
Kyndium's redesign replaced a thousand hard-coded colors with a few dozen tokens. The interesting part is not the number. It is that every neutral in the system comes from one hue and one chroma, so the whole palette can be re-tinted by changing two values.
Why OKLCH
In OKLCH, lightness means what it says: two colors with the same L look equally bright to a person, whichever hue they are. That lets the system fix a lightness step for each role (canvas, surface, lines, three levels of ink) once, choose them for contrast once, and know the contrast holds whatever hue is set. Light mode puts the canvas at 94.5% and the darkest ink at 25%; dark mode puts the canvas at 18% and the brightest ink at 95%. The steps were chosen so every text role meets the AA ratio against the surfaces it sits on.
One declaration, two modes
Each token is declared once with CSS light-dark(), which picks the light or dark value from the element's color-scheme. The mode is therefore just an attribute: data-k-mode="light", "dark" or "system" on any element, and everything inside follows. A dialog portalled out of the page carries its own attribute and gets its own mode. There is no second stylesheet and no class that has to reach every rule.
The band across the top is the one surface that is dark in both modes, at a lightness between dark mode's canvas and surface. Switching to dark reads as the band spreading down the page rather than a different theme loading, which is the effect we wanted.
Accent and labels
The accent is a lilac, chosen to be the only saturated brand color in the interface. Status colors (green, amber, coral) carry meaning and are used for nothing else. The label palette for tags and lane colors avoids the accent's hue and the risk red, so a label never reads as a button or an error. In dark mode the coral is light enough that white text fails on it, so there is a dedicated "text on risk" token.
What people can change
Appearance lets a person pick the canvas color, the accent, card style, corners and density. A custom canvas keeps the hue and chroma they chose but takes the system's lightness for each mode, so a loud color in light mode becomes a deep version of itself in dark mode and the text stays readable either way. The choice is written to a cookie and rendered on the server, so the first paint is already right.
Comments