Palette
Every hue carries three layers: a chip value for pickers, a body ink per colour scheme, and a gradient pair for static avatars.
Three layers per hue
A picker chip and a rendered character have opposite problems. The chip is a 20-pixel square that has to be told apart from its neighbours. The character is a large filled silhouette that has to stay readable on both a white and a near-black page. One value cannot do both jobs: tuned for the chip it makes the bodies glaring, tuned for the body it makes the chips muddy.
So each hue carries three layers.
Automatic light and dark
Ink is emitted as a light-dark() pair and written into a CSS custom property once:
The browser re-resolves it when color-scheme changes. That is the whole theme-switching mechanism — no listener, no re-render, no flash, and it costs the same for one character as for a thousand.
black inverts
black is the only hue whose dark-mode ink is not a darker version of its light-mode ink — it becomes white. The neutral character is meant to be the one with the most contrast against the page, and on a dark page that means going the other way.
Variables beyond the ink
The body ink is --aora-fg, but the face and a couple of variants need colours of their own. When you style a character yourself, write them all with getInkVars(color) rather than --aora-fg alone; CharacterMark and StagedMark do exactly that.
getInkVars('blue') | --aora-fg, --aora-face |
getInkVars('pink') | --aora-fg, --aora-face, --aora-ink2 |
getInkVars('black') | --aora-fg, --aora-face-soft, --aora-face-sticker, --aora-hair-shade |
Deterministic assignment
Any string maps to a stable colour and shape.
Assignment uses FNV-1a followed by an avalanche step, so keys that differ by one character land far apart in the pool rather than adjacent to each other. black is excluded from assignment — it is reserved as the explicit default, so an assigned character is always visibly "chosen".
Halo
haloBackground composes a soft multi-stop wash from a hue, for use behind an avatar.
Next
- Rendering structure — one SVG, every attribute written by hand
- Theming — the two variables that draw a character