One foundation, two faces
The foundation is shared so the properties read as one hand; the faces are inverted so they are never mistaken for each other. Workshop — this site — is a cold accent on a warm ground: a tool laid on paper. Observatory — caelum.agency — is a warm signal on a cold ground: an instrument lit at night. Neither is another dark starfield, because that is The Hidden Door's and it should stay theirs.
| ground | Workshop #EDEFEC cool paper · Observatory #0D1218 blue-black |
| accent | Workshop #26685F verdigris · Observatory #E0A458 instrument amber |
| second | Workshop #964E29 oxide · Observatory #6FA8C7 cold blue — each face's second colour is the other's temperature |
| display | Instrument Serif |
| body | Newsreader, optical sizing on |
| data | Spline Sans Mono, tabular numerals wherever a figure appears |
| structure | hairline rules, no rounded corners, no shadows, no cards |
| motion | one 8px rise on entry; none if you asked for reduced motion |
Three files, in order
<link rel="stylesheet" href="https://caelum.codes/rule/tokens.css">
<link rel="stylesheet" href="https://caelum.codes/rule/workshop.css"> <!-- or observatory.css -->
<link rel="stylesheet" href="https://caelum.codes/rule/base.css">
- tokens.css — type, scale, measure, structure, and the colour slots. The reasoning is in the comments.
- workshop.css — the light face. Fills every slot.
- observatory.css — the dark face. Fills every slot.
- base.css — the dozen components: wrap, headings, label, links, masthead, nav, index, facts, code, aside, section, colophon. Reads slots only.
Swapping a face is swapping one line. Nothing in base.css knows which face it is wearing.
The numbers were wrong once already
The first palette for this face shipped with an accent at 4.23:1 on the ground and a label grey at 2.76:1 — both under the 4.5 floor for body text, both written down as passing. The fix is procedural, not cosmetic: the repo carries a contrast gate, tests/contrast.py, that fails the build when any text pair is under 4.8 (the house margin over the 4.5 floor, because a value that grazes the line drifts under it through rounding or a colour profile). It checks its own instrument first — black on white must return exactly 21:1 — before it trusts any other reading.
Hairline rules are decorative and exempt from WCAG 1.4.11; they are tuned for visibility, not compliance, and the gate reports them as information only.
Light on the Workshop is an open question. Everything else in the estate is dark. It is the strongest differentiator the face has and the biggest departure from the house, and it is token-driven so that ruling costs one file.