OKLCH, contrast, harmonies, gamut, and the dumb little pitfalls that quietly kill a design. Drag every slider. The page itself is a proof of the rules.
Color on the web is not pigment. It is math, biology, and a long chain of assumptions about the sRGB display you are probably not looking at. Most of the “that palette feels off” moments come from one of four places — uneven perceived lightness, failed contrast, simultaneous-contrast vibration, and pure-white halation.
This page demonstrates the fixes instead of describing them. Every slider, swatch, and wheel is live. The companion write-up at COLOR-SCIENCE.md has the theory and citations; this is the playground.
Sweep the hue wheel at one fixed “lightness.” In HSL, yellow blows out and blue goes midnight — L is a math trick on RGB, not perceived brightness. In OKLCH, L is perceptually uniform. Move the slider. Watch the top row flicker; watch the bottom stay calm.
The WCAG 2 contrast formula compares relative luminance. Body text wants 4.5:1. Large text wants 3:1. Non-text UI wants 3:1. AAA wants 7:1. Pick two colors, test a preset, feel the math.
A starting pose: 60% dominant surface, 30% secondary, 10% accent. This page runs the pink-dominant version. Flip to blue-dominant and feel the room change from spa to lagoon.
True complementaries sit 180° apart and physically vibrate at a shared edge (simultaneous contrast: your cones don't like it). Split-complement shifts the opposite hue by ±30° and loses the buzz without losing the punch. Click the wheel to reseat the source.
Maximum drama. Will vibrate at full chroma — desaturate one side.
Most illustrated UIs you admire use this. Same energy, no buzz.
Warm & cozy, low contrast. Great for mood; add a value jump for hierarchy.
OKLCH is a color-appearance space, not a display space. Ask for a chroma that falls outside sRGB and the value gets clamped to something representable. Each card shows the ideal (as the CSS engine would render it on a wide-gamut display) beside the nearest sRGB fallback we computed by clamping.
@media (color-gamut: p3) and keep the sRGB hex as a fallback — progressive enhancement, zero cost to older devices.
No sliders here — just side-by-side. The left pane is the bad idea your eye “feels” as wrong even when it can't articulate why. The right pane is the considered version. Look for five seconds each; you'll feel the difference.
A designer's bookmark. Hex, OKLCH, role, and a WCAG-checked pairing for each. The page itself uses these values — if anything on this page passes your own contrast checker at 4.5:1, it's because of this table.
| Token | Hex | OKLCH | Role | Pairs with (AA) |
|---|---|---|---|---|
| --bg | #FAF4EE | oklch(0.96 0.014 75) | Surface (60%) | ink, blue-deep, pink-deep |
| --ink | #2A2320 | oklch(0.24 0.012 40) | Body copy | bg (13.5:1 AAA) |
| --muted | #9A8A84 | oklch(0.62 0.016 35) | Labels, captions | bg — large text only |
| --pink | #E89B89 | oklch(0.74 0.11 35) | Surfaces / cards | ink (7.2:1 AAA) |
| --pink-deep | #C96F5C | oklch(0.62 0.14 32) | Section headings, CTA | bg (3.4:1 large) |
| --blue | #3FBFB5 | oklch(0.72 0.11 188) | Surfaces / cards | ink (6.5:1 AA+) |
| --blue-deep | #1F7C78 | oklch(0.51 0.09 190) | Links, buttons | bg (4.8:1 AA) |
| --sun | #F2C94C | oklch(0.83 0.13 88) | Rare accent | ink (8.1:1 AAA) |