Color Model: OKLCH
Espalier uses OKLCH as its internal color model. OKLCH describes colors using three axes: L (perceived lightness, 0–1), C (chroma / color intensity, 0–0.37+), and H (hue angle, 0–360).
This model drives the entire palette generation pipeline: seed color input, color-theory variant generation, semantic token derivation, and APCA contrast adjustment use OKLCH. Contrast scoring converts the colors to sRGB for APCA before the final values are emitted as CSS custom properties.
What this means when writing theme colors
The seedColor field accepts opaque OKLCH, hexadecimal, RGB, and HSL colors.
Other CSS color spaces and named keywords are not parsed. See the
guide overview. For example:
// Any of these are valid seed colors
{ seedColor: 'oklch(0.65 0.18 240)' } // OKLCH — direct
{ seedColor: '#3b82f6' } // hex — converted internally
{ seedColor: 'hsl(217 91% 60%)' } // HSL — converted internally
Using OKLCH directly gives you the most predictable results because the numbers you write correspond to perceived brightness (L) and color intensity (C) rather than hardware channel values.
OKLCH in application CSS
Because --esp-color-* tokens are emitted as OKLCH values, you can use
Relative Color Syntax
to derive related values in your own CSS:
/* Lighten a token by shifting its L channel */
background: oklch(from var(--esp-color-primary) calc(l + 0.05) c h);
/* Desaturate by reducing chroma */
color: oklch(from var(--esp-color-text) l calc(c * 0.5) h);
Lightness ramp tokens
Espalier also exposes the raw lightness values it uses internally as
--esp-l-* tokens (e.g. --esp-l-surface, --esp-l-text). These are useful
when you need to apply the same perceptual lightness levels to custom colors
that are outside the standard palette.