The season's design system — colour, type, space, motion. Every
value on this page is read out of assets/css/hollow.css and
site/assets/css/moral-gray.css at runtime, and every contrast
figure is computed here rather than typed. If a token moves in those
files, this page moves with it. It cannot go stale, and it cannot lie.
Two colourways. The season is a blown-out bone ground with a wine-black ink; the 2016 half of the Moral Gray page is its negative — a pale figure on midnight. Contrast is measured against each colourway's own ground. PASS is 4.5:1; roles marked large only are held to 3:1 because nothing wears them below about 24px.
Four slots, assigned in fixed order and never cycled. Highlight marks in
running text are the all-pairs case — any two can end up
side by side — and past four, no set clears the perceptual floors.
Two are reserved globally (violet /aɪ/, orange
/eɪ/); two are re-assigned per section. Both sets were
validated against their own ground, and the midnight set is not the light
set darkened: the reference dark violet collides with the dark blue at
CVD ΔE 1.9 and had to be replaced.
| Ground | Worst all-pairs CVD | Worst normal-vision | Verdict |
|---|---|---|---|
| bone #f2f1ef | ΔE 9.2 (deutan) | ΔE 16.3 | all pass |
| midnight #131826 | ΔE 8.8 (deutan) | ΔE 16.5 | all pass |
Two families and nothing else. Sizes below are the computed
values at this viewport — every one is a clamp(), so
resize the window and the numbers move. The specimens are real elements
wearing the real classes, measured where they stand.
| Family | Weights | Role | Stack |
|---|
Tracking is the system's accent. Mono is always
letter-spaced — 0.14em on chips, up to 0.52em on section labels
— and always uppercase. Where tracking is heavy, an equal
text-indent follows it: tracking adds a trailing space after
the last letter, which throws a centred line off by half that amount.
Serif is never tracked.
Everything fluid, nothing stepped. The gutter and the measure are the only two spacing tokens; section rhythm is written as clamps at the point of use rather than a scale, because there are six sections in the whole site and a scale would be ceremony.
| Token | Declared | Computed here | What it does |
|---|
One curve. Everything that eases uses --ease; anything that
should feel mechanical uses steps(1) instead, which is how
the tear and the grain read as faults rather than animations.
Durations cluster in three bands: 260–520ms for anything answering a pointer, 900–1200ms for content arriving, and 90s+ for the fog, which should never be caught moving. The split is the one exception at 1900ms, because it is the page's only narrative beat.
The rule that holds the whole thing together: nothing has a hard edge. Rules are gradients that fade at both ends, sections bleed into one another, the figure dissolves into a bank of haze rather than being cropped. The two deliberate exceptions are the seam on the Moral Gray page — where the split is the content — and the focus ring, which has to be unambiguous.
Tokens declared in both stylesheets with different values. The two sheets deploy separately and neither imports the other, so drift here is real and worth seeing rather than assuming away.
| Token | hollow.css | moral-gray.css |
|---|