Introduction to OKLCH
OKLCH is a cylindrical (polar coordinate) representation of the Oklab color space. The name stands for:Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ OKLCH COMPONENTS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ O = Oklab (the underlying perceptual color space) │
│ L = Lightness (0-100%, perceptually uniform) │
│ C = Chroma (0-0.4, saturation/colorfulness) │
│ H = Hue (0-360 degrees, color wheel angle) │
│ │
│ OKLCH vs Oklab: │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ Oklab (Cartesian) OKLCH (Polar) │ │
│ │ ───────────────── ───────────── │ │
│ │ L (Lightness) <--> L (Lightness) │ │
│ │ a (Green-Red axis) <--> C (Chroma = sqrt(a^2 + b^2)) │ │
│ │ b (Blue-Yellow axis) <--> H (Hue = atan2(b, a)) │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
The Gravity Field Metaphor
In the Gestalt Color System, we use a gravitational lensing metaphor to understand color relationships:Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ OKLCH AS THE CORE GRAVITY FIELD │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ PHYSICAL ANALOGY: │
│ ───────────────── │
│ │
│ In general relativity, a massive object (like a star) creates a │
│ gravitational field that bends spacetime around it. Light rays │
│ passing near this object curve toward it. │
│ │
│ Similarly, in OKLCH: │
│ - The CORE HUE acts as the "massive object" (gravity center) │
│ - Other colors are "light rays" that curve toward the Core │
│ - The polar coordinate system (L, C, H) naturally represents │
│ distance and angle FROM the center │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Core Hue │ │
│ │ * │ │
│ │ / \ │ │
│ │ / \ Frame Drag │ │
│ │ / \ (blend_hue) │ │
│ │ / \ │ │
│ │ / \ │ │
│ │ o─────────/─────────────────────\──────────o │ │
│ │ color A (dragged toward Core) color B │ │
│ │ │ │
│ │ Hue rotation in OKLCH = orbital path around Core │ │
│ │ Chroma (C) = distance from the center (orbital radius) │ │
│ │ Lightness (L) = perpendicular dimension (elevation) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Why OKLCH for Core Colors?
OKLCH provides three core benefits that make it ideal for defining color identity:- Perceptual Uniformity:
L=50%appears equally bright regardless of hue - Golden Angle Rotation: Produces visually equal color steps
- Hue-Independent Chroma: Yellow does not require special saturation handling (unlike HSL)
OKLCH Value Ranges
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ OKLCH VALUE RANGES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Component Range Unit Description │
│ ───────────────────────────────────────────────────────────────────────── │
│ Lightness (L) 0 - 100 % 0% = black, 100% = white │
│ Chroma (C) 0 - 0.4 unitless 0 = gray, 0.4 = maximum color │
│ Hue (H) 0 - 360 degrees Color wheel position │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ HUE COLOR WHEEL │ │
│ │ │ │
│ │ 0/360 │ │
│ │ Red │ │
│ │ │ │ │
│ │ 330 │ 30 │ │
│ │ Pink \ │ / Orange │ │
│ │ \ │ / │ │
│ │ 300 ────────────┼──────────── 60 │ │
│ │ Magenta Core │ Yellow │ │
│ │ Hue │ │ │
│ │ Violet / │ \ Yellow-Green │ │
│ │ 270 │ 90 │ │
│ │ Blue │ │
│ │ 180 │ │
│ │ Cyan │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ PRACTICAL CHROMA VALUES: │
│ ───────────────────────── │
│ DEFAULT_CHROMA = 0.12 (UI elements - subtle, professional) │
│ MAX_SAFE_CHROMA = 0.15 (maximum before sRGB clipping) │
│ Theoretical max = 0.4 (may clip in sRGB gamut) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Golden Angle Constants
The Gestalt Color System uses two golden angle values for different purposes:Copy
┌───────────────────────────────────────────────────────────────────────┐
│ GOLDEN ANGLE CONSTANTS │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ GOLDEN_ANGLE = 137.5077640500378 │
│ │ │
│ └──► 360 / phi² where phi = (1 + √5) / 2 │
│ Maximum hue separation for file types, syntax colors │
│ │
│ AGENT_GOLDEN_ANGLE = 27.5 │
│ │ │
│ └──► 137.5 / 5 (fifth of golden angle) │
│ Subtle variation for terminal sessions, agent tabs │
│ │
│ DEFAULT_CHROMA = 0.12 ──► Standard saturation for UI elements │
│ MAX_SAFE_CHROMA = 0.15 ──► Maximum before sRGB gamut clipping │
│ │
└───────────────────────────────────────────────────────────────────────┘
Copy
/** Golden angle for maximum color distribution */
export const GOLDEN_ANGLE = 137.5077640500378;
/** Agent color golden angle (smaller for subtle variation) */
export const AGENT_GOLDEN_ANGLE = 27.5;
/** Default chroma for UI elements */
export const DEFAULT_CHROMA = 0.12;
/** Maximum chroma before clipping in sRGB */
export const MAX_SAFE_CHROMA = 0.15;
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ GOLDEN ANGLE DISTRIBUTION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ MATHEMATICAL FOUNDATION: │
│ ──────────────────────── │
│ Golden Ratio (phi) = (1 + sqrt(5)) / 2 = 1.6180339887 │
│ Golden Angle = 360 / phi^2 = 137.5077640500378 │
│ │
│ WHY 137.5? │
│ ────────── │
│ This angle provides MAXIMUM DISTRIBUTION on a circle. │
│ Each new point is maximally separated from all previous points. │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Color Distribution Pattern (Golden Angle 137.5): │ │
│ │ │ │
│ │ Index 1: 0 + (1 x 137.5) = 137.5 │ │
│ │ Index 2: 0 + (2 x 137.5) = 275.0 │ │
│ │ Index 3: 0 + (3 x 137.5) = 412.5 -> 52.5 │ │
│ │ Index 4: 0 + (4 x 137.5) = 550.0 -> 190.0 │ │
│ │ Index 5: 0 + (5 x 137.5) = 687.5 -> 327.5 │ │
│ │ Index 6: 0 + (6 x 137.5) = 825.0 -> 105.0 │ │
│ │ │ │
│ │ Result: Colors are evenly distributed, never clustering! │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ TWO GOLDEN ANGLES IN MONOLEX: │
│ ───────────────────────────── │
│ GOLDEN_ANGLE = 137.5 For maximum distinction (file types, etc.) │
│ AGENT_GOLDEN_ANGLE = 27.5 For subtle variation (agent colors) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Color Conversion Pipeline
The system provides complete conversion between color spaces:Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ COLOR CONVERSION PIPELINE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────┐ ┌───────────┐ ┌───────┐ ┌─────────┐ │
│ │ RGB │ ---> │ Linear RGB│ ---> │ Oklab │ ---> │ OKLCH │ │
│ │(0-255)│ │ (gamma) │ │ (L,a,b)│ │ (L,C,H) │ │
│ └───────┘ └───────────┘ └───────┘ └─────────┘ │
│ FLOW Space CORE Space │
│ (Cartesian) (Polar) │
│ │
│ HEX -> RGB: │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ hexToRgb("#FF5733") -> { r: 255, g: 87, b: 51 } │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
│ RGB -> Linear RGB (sRGB gamma removal): │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ v = c / 255 │ │
│ │ if (v <= 0.04045): │ │
│ │ linear = v / 12.92 │ │
│ │ else: │ │
│ │ linear = ((v + 0.055) / 1.055) ^ 2.4 │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
│ Oklab -> OKLCH (Cartesian to Polar): │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ C = sqrt(a^2 + b^2) <- Distance from center (gravity well) │ │
│ │ H = atan2(b, a) x (180 / pi) <- Angle (orbital position) │ │
│ │ if (H < 0) H += 360 │ │
│ │ L = L x 100 (convert to percentage) │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
CSS Generation Functions
OKLCH CSS String Generation
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ toOklchCSS() - OKLCH to CSS String Conversion │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ INPUT: OKLCH { l: 55, c: 0.15, h: 230 } │
│ │ │ │ │
│ V V V │
│ FORMAT: oklch( L.00% C.000 H.00 ) │
│ │ │ │ │
│ V V V │
│ OUTPUT: "oklch(55.00% 0.150 230.00)" │
│ │
│ NOTE: toFixed(2) for L and H, toFixed(3) for C (higher precision) │
│ │
└───────────────────────────────────────────────────────────────────────┘
Copy
export function toOklchCSS(oklch: OKLCH): string {
return `oklch(${oklch.l.toFixed(2)}% ${oklch.c.toFixed(3)} ${oklch.h.toFixed(2)})`;
}
Color Mix CSS Generation
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ colorMix() - CSS color-mix() String Generator │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ INPUTS: │
│ ─────── │
│ color1: First color (CSS value or variable) │
│ color2: Second color (CSS value or variable) │
│ space: Color space (oklch, oklab, srgb) - default: oklch │
│ percent: Weight of color1 (0-100) - default: 50 │
│ │
│ FORMULA: │
│ ──────── │
│ "color-mix(in {space}, {color1} {percent}%, {color2})" │
│ │
│ EXAMPLE: │
│ ──────── │
│ colorMix("#FF0000", "#0000FF", "oklab", 70) │
│ │ │
│ └──► "color-mix(in oklab, #FF0000 70%, #0000FF)" │
│ Result: 70% red + 30% blue in OKLAB space │
│ │
└───────────────────────────────────────────────────────────────────────┘
Copy
export function colorMix(
color1: string,
color2: string,
space: ColorMixSpace = "oklch",
percent: number = 50
): string {
return `color-mix(in ${space}, ${color1} ${percent}%, ${color2})`;
}
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ CSS OUTPUT FORMAT COMPARISON │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ FUNCTION OUTPUT EXAMPLE │
│ ─────────────────────────────────────────────────────────────────────── │
│ │
│ toOklchCSS() oklch(55.00% 0.150 230.00) │
│ (CORE - identity) oklch(65.00% 0.120 85.00) │
│ │
│ colorMix() color-mix(in oklch, #FF0000 50%, #0000FF) │
│ (FLOW - transition) color-mix(in oklab, var(--primary) 70%, white) │
│ │
│ colorTransparent() color-mix(in oklab, #FF0000, transparent 50%) │
│ (FLOW - transparency) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ KEY INSIGHT: Color Space Choice │ │
│ │ │ │
│ │ toOklchCSS() -> OKLCH (polar) = CORE Space │ │
│ │ Identity colors, fixed "gravity centers" │ │
│ │ │ │
│ │ colorTransparent() -> OKLAB (cartesian) = FLOW Space │ │
│ │ colorDarker() Transitions between gravity fields │ │
│ │ colorLighter() Linear paths avoiding gravitational distort │ │
│ │ │ │
│ │ OKLCH = Core Colors (Identity, Hue-based, Anchor Points) │ │
│ │ OKLAB = Flow Colors (Derivations, Linear mixing, Free space) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Accessibility Functions
The system includes built-in accessibility checking:Copy
┌───────────────────────────────────────────────────────────────────────┐
│ ACCESSIBILITY FUNCTIONS │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ hasEnoughContrast(textOklch, bgOklch) │
│ │ │
│ └──► │text.L - bg.L│ > 40 → true/false │
│ WCAG-inspired lightness difference check │
│ │
│ getContrastText(bgOklch) │
│ │ │
│ ├──► bg.L > 60 → "black" (dark text on light bg) │
│ └──► bg.L ≤ 60 → "white" (light text on dark bg) │
│ │
│ getAccessibleTextColor(bgOklch) │
│ │ │
│ ├──► bg.L > 60 → { l: 20, c: 0.02, h: bg.h } (dark text) │
│ │ Preserves background hue, minimal chroma │
│ │ │
│ └──► bg.L ≤ 60 → { l: 95, c: 0.01, h: bg.h } (light text) │
│ Preserves background hue, near-white │
│ │
└───────────────────────────────────────────────────────────────────────┘
Copy
export function hasEnoughContrast(textOklch: OKLCH, bgOklch: OKLCH): boolean {
return Math.abs(textOklch.l - bgOklch.l) > 40;
}
export function getContrastText(bgOklch: OKLCH): "white" | "black" {
return bgOklch.l > 60 ? "black" : "white";
}
export function getAccessibleTextColor(bgOklch: OKLCH): OKLCH {
if (bgOklch.l > 60) {
return { l: 20, c: 0.02, h: bgOklch.h };
} else {
return { l: 95, c: 0.01, h: bgOklch.h };
}
}
THE CENTER
How OKLCH Helps Humans Parse Information Flow
Copy
Connection to Core-Flow:
├── The color IDENTITY tells humans what type of information this is
├── Before reading text, color communicates: "This is a primary action"
└── Polar coordinates (L, C, H) map naturally to human perception
- Lightness: How prominent is this information?
- Chroma: How important/attention-grabbing is it?
- Hue: What category does it belong to?
- Equal perceived brightness - A yellow warning is not louder than a red error
- Consistent categorization - Hue reliably maps to meaning
- Predictable transitions - Flow colors derived from Core colors maintain identity
Complete API Reference
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ OKLCH COLOR UTILS - COMPLETE API │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ CONSTANTS: │
│ ────────── │
│ GOLDEN_ANGLE 137.5077640500378 (maximum distribution) │
│ AGENT_GOLDEN_ANGLE 27.5 (subtle agent variation) │
│ DEFAULT_CHROMA 0.12 (UI elements) │
│ MAX_SAFE_CHROMA 0.15 (sRGB safe maximum) │
│ │
│ CONVERSIONS: │
│ ──────────── │
│ hexToRgb(hex) HEX -> RGB │
│ rgbToOklch(rgb) RGB -> OKLCH │
│ oklchToRgb(oklch) OKLCH -> RGB │
│ hexToOklch(hex) HEX -> OKLCH │
│ oklchToHex(oklch) OKLCH -> HEX │
│ hslToOklch(hsl) HSL -> OKLCH │
│ │
│ CSS GENERATION: │
│ ─────────────── │
│ toOklchCSS(oklch) -> "oklch(L% C H)" │
│ colorMix(c1, c2, space, %) -> "color-mix(in space, c1 %, c2)" │
│ colorTransparent(c, opacity) -> "color-mix(in oklab, c, transparent %)" │
│ colorDarker(c, amount) -> "color-mix(in oklab, c %, black)" │
│ colorLighter(c, amount) -> "color-mix(in oklab, c %, white)" │
│ │
│ COLOR GENERATION: │
│ ───────────────── │
│ getAgentColorOklch(idx, base, dark) -> OKLCH for agent N │
│ getExtensionColorOklch(hue, dark) -> OKLCH for file type │
│ generatePalette(base, count, step) -> OKLCH[] │
│ adjustOklch(color, {l?, c?, h?}) -> adjusted OKLCH │
│ │
│ ACCESSIBILITY: │
│ ────────────── │
│ hasEnoughContrast(text, bg) -> boolean (delta L > 40) │
│ getContrastText(bg) -> "white" │ "black" │
│ getAccessibleTextColor(bg) -> OKLCH │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
CSS Variables Architecture
Learn how Core Colors are defined as CSS variables using the SMPC hierarchy