the thinking behind datum · a living doc — changes when the palette does

The ideas

datum isn't picked, it's derived. Here's the short version of why every color sits where it does.

The whole trick

Every token gets a color — but how loud that color is tracks how often the token shows up. The rare, meaningful stuff (strings, numbers, constants, types, definitions) runs at full chroma. The ~75% that's just glue — variables, calls, parameters, operators — gets a quieter version of the same hue. Colorful, without turning into soup.

Derived, not vibed

The colors fall out of a script, not my eyeballs. They live in OKLCH, so "equally bright" actually means equally bright. Every one clears WCAG 4.5:1 plus an APCA check, then the whole set runs through a colorblindness simulator. When a color fails, the math says so and I move it — no guessing. The receipts are on the palette page, computed live in your browser.

Which colors, and why

The hues come from Okabe–Ito, a set built to stay distinct for colorblind folks. The mapping has a story:

Light and dark aren't opposites

A dark theme isn't a light one flipped upside down — that reads wrong, because your eyes don't work that way. Same hue in both modes, but lightness and chroma retuned for the background. Light green is a deep pine; dark green a bright mint. Still the same "green." Hit the ☀/☾ up top to watch it swap.

Where it's honest

Under the hood

One file — tools/derive.py — is the source of truth. It emits the palette as JSON, and every port (Ghostty, Kitty, WezTerm, VS Code, tmux, fzf, the shell, all of them) is generated from it. Change a color once and everything follows, so nothing drifts.

Go deeper

The research it leans on: OKLCH (Ottosson) · Solarized · APCA · Okabe–Ito / Wong · light vs dark reading · tonsky on syntax highlighting.