DEV Community

J Now
J Now

Posted on

WCAG lies on dark ground — and it cost me a readable terminal

WCAG contrast ratios break on dark backgrounds. A 4.5:1 pair that passes on white can be functionally invisible on a near-black ground because WCAG's formula treats luminance as symmetric — it doesn't account for the human visual system's asymmetric response to light-on-dark versus dark-on-light text.

This matters for terminal themes because terminals are almost always dark. When I built klein-void — four Terminal.app themes for Claude Code tuned around Yves Klein's IKB blue — I switched to APCA (Accessible Perceptual Contrast Algorithm) midway and had to throw out several color choices that looked fine by WCAG.

The clearest example: pure IKB (hex 002FA7) on my dark ground scores Lc -12 in APCA. Effectively invisible as body text. WCAG would report a ratio, assign a grade, and move on. APCA flags it immediately because Lc values below ~45 at body size are non-starters.

So IKB gets split across two ANSI slots. ansi:blue gets pure IKB — used only for decorative borders and highlights where it reads as a color field, not a text color. ansi:blueBright gets a lifted Klein-family blue (A8BEF0) that clears Lc 60 for accent text and hits Lc 90+ for body slots. The palette stays Klein without making Claude Code's permission prompts unreadable.

The per-role gate structure in V3 Prot, the strictest of the four variations:

body text:    Lc >= 90
subtitle:     Lc >= 75
muted/meta:   Lc >= 45
accent text:  Lc >= 60
border/deco:  unconstrained
Enter fullscreen mode Exit fullscreen mode

V1 and V2 relax the accent gate to let the aesthetic breathe. V3 is the one where every slot passes strict APCA thresholds. V4 maximizes the void feeling at the cost of some accent contrast.

The other Claude Code-specific wrinkle: ansi:redBright is where Claude Code renders its claude-sand brand color. Sand & Sea accepts it as a second hero; Refined neutralizes it so IKB has no competition. Both are intentional answers to the same question about how much color you want on screen.

Four .terminal profiles, installed via install.sh, fully rollback-able. Requires Claude Code's /theme picker set to dark-ansi or the ANSI slots are ignored entirely.

https://github.com/robertnowell/klein-void

Top comments (0)