Colophon
What this site is made of, and which of its decisions are load-bearing.
What this site is made of. The five sections below are the five axes the stylesheet itself is organised on — type, colour, measure, motion, machinery — so this page and the file it describes cannot fall out of step.
Every number here is measured rather than estimated. Where a decision has a reason, the reason is the part in italics.
Type
Nunito
Weights 400–700. One family, no pairing.
0 1 2 3 4 5 6 7 8 9
- Family
- Nunito alone, committed 2026-08-03. Chosen for the character its rounded terminals give the display sizes; the consequence is that every scale decision has to make that character an asset rather than reach for a second face.
- Numerals
-
ui-monospace, at 13.8px. Mono is the numbering system and nothing else — section numerals in the article gutter, counts in the hero ledger. The moment it touches words it stops reading as instrumentation and starts reading as a second font. - Prose
-
One size, flat, hierarchy carried by weight. Under it sits an apparatus tier at 14px and
--gray-1000for captions, dates and filing lines — the rule being that nothing which carries argument may use it.
Colour
- Ramp
- Radix Sand, twelve steps, zero chroma. Warm gray rather than neutral, which is what lets a vermillion accent sit on it without the page splitting into two temperatures.
- Accent
-
#d55e00at 3.80:1 for marks and rules,#b04d00at 5.28:1 for text. One colour cannot do both jobs: the lighter step clears the 3:1 bar for non-text and fails the 4.5:1 bar for small type, so the darker step exists only to carry words. - Spending rule
- Interaction only — link hover, figure hover, focus ring, the active rail mark. At rest the page is monochrome, so colour reads as a response rather than as decoration.
- Tertiary text
-
#6f6f69at 4.97:1. It was#82827cat 3.80:1, which failed AA while carrying every caption, date and timestamp on the site. One Radix step darker, same hue and chroma.
Measure
- Column
- ~646px of prose, declared in rem. So the column widens on a large display while the line stays near 75 characters — the width, not the character count, is what scales.
- Root
- 16px below ~880px, 17px at 1440px, 19px at 2560px. Every rhythm number in the stylesheet was calibrated at 17px/1440, where the fluid site is pixel-identical to the fixed one it replaced.
- Rail budget
-
Section headings fit one line in the TOC rail: ~25 characters, floor 20. Measured against the live rail — a 184px label box, Nunito running 7.4–8.0px per character. The rail sets
text-overflow: ellipsisas a tripwire, so an ellipsis appearing there is a bug report about the heading, not about the rail. - Audit
- Zero automated violations, zero horizontal overflow, 2026-08-05.
Motion
- Navigation
- Cross-document view transitions, two lines and no JavaScript. The masthead name is the shared element, so it holds still while the page changes under it.
- Hero
- A staggered entrance: three headline beats, then the role, links, status and ledger. It runs once per session — a repeat visit within the same session renders the resting page directly, because an entrance that plays on every navigation stops being an entrance.
- Rail
- The TOC collapses to hairlines on scroll-down and restores its words on scroll-up, hover or focus.
- Everything
-
Transform and opacity only, and all of it cancelled under
prefers-reduced-motion. Including the transitions the browser generates itself, which the media query does not cover on its own.
Machinery
- Maths
-
KaTeX 0.18.1, vendored and pinned. The default emits
katex@latestfrom a CDN, which is two problems in one script tag: a floating version that can retypeset every equation here without a commit, and a third party in the critical path of a page whose maths renders client-side. - Résumé
- One TOML file compiles to both the web page and the PDF. The page body regenerates on every render, so the two surfaces cannot drift; the PDF’s only difference is the private fields the page is not given.
- Figures
-
compute.pyruns the model once and caches every number;plot.pydraws from the cache and needs only numpy and matplotlib. A post’s entire visual language can be reworked in seconds instead of a two-thousand-forward-pass rerun, and the figures stay reproducible by someone without the model. - Build
- Four post-render passes: image dimensions read from the files themselves, accessibility repairs to the generated chrome, a listings manifest, and the icon-set removal. The last one re-proves on every render that the icon set is still unused and fails the build rather than serving a page a missing glyph — 273 KB that this site had been shipping for an icon it never had.
- Published
- Quarto to GitHub Pages, built by Actions. Every branch renders and reports whether the site still builds; merging to main is the act of publishing, and built HTML never enters the history.