.Colophon / the build record
How this site was made
This site is a small system, and it's built as one. Everything below is true of the page you're reading, and the exhibits are read out of the source at build time, so this record can't drift into fiction.
- Design tokens
- 88
- Magic numbers
- 0
- Type payload
- 566 KB
- Astro
- 6.4.2
The stack
Astro, statically generated. Every page is HTML at build time, served from Vercel with no server, no adapter and no runtime. Content lives in Keystatic and is read once, at build; the editing admin exists only in development and ships nowhere. JavaScript is a scalpel rather than a framework: a handful of small vanilla modules, a clock, one shared observer, one instrument, each of them justified and none of them React.
- Framework
- Astro 6.4.2
- Content
- Keystatic 0.5.50 — read once at build; admin is dev-only
- Output
- Static HTML — no server, no adapter, no runtime
- Deploy
- Vercel, static
- Client JS
- No UI framework shipped — vanilla modules: a clock, the motion runtime, a few section scripts. One exception dominates: the hero mark is WebGL (three.js), and it is most of the payload. See the budget.
- Analytics
- PostHog, cookieless — no cookies, no local storage, no consent banner. Ingestion proxied through this domain; visitor identity is a server-side hash whose salt is destroyed daily, so it cannot be linked across days.
Type
Two faces, three jobs. Tomato Grotesk, the grotesque, carries structure and authority: display, headings, interface. Commit Mono is the instrument voice, used for labels, readouts and indices, and never for body copy; the moment paragraphs go mono, a site becomes a dev tool. The third job, the editorial heart, has no face of its own. The site began with a serif for longform, that serif was never licensed, and rather than ship type we hadn't paid for we gave the role back to the grotesque. The token is still called --font-serif. It resolves to Tomato Grotesk, and this paragraph is set in it.
Tomato Grotesk — structure & authority
- Regular 400
- Medium 500
- Bold 700
- Black 900
- Slanted 400
Licensed · full character set, not yet subset
Commit Mono — labels, readouts, indices
Regular 400 · SIL Open Font License 1.1 · subset to 116 codepoints · never body copy
The editorial voice — no serif face
--font-serif resolves to Tomato Grotesk. The role outlived the face: Tiempos was never licensed, so it does not ship. A role name, not a promise.
26 files · 566 KB WOFF2 · self-hosted · font-display: swap · metric-tuned fallback
Tokens & grid
Every visual value on this site is a named token in one CSS file: every colour, size, space, radius and duration. Components are forbidden magic numbers and may only speak the system's vocabulary. That rule is what makes this page possible, because the exhibit below is not documentation written about the site. It is parsed out of the stylesheet when the site is built. Space runs on a 4px base with an 8px rhythm, and the twelve-column grid is drawn on the page as a visible feature rather than a hidden scaffold.
88 named tokens · 0 magic numbers
- columns
- 12
- gutter
- var(--space-5)
- container-max
- 1440px
- measure
- 68ch
- hairline
- 1px
Colour & inversion
One hue, end to end. The base is a cool, blue-tinted drafting paper, never white, with a blueprint ink for the dark bands and a single brand blue doing the talking: full strength on ink, deepened for text on paper. Inversion is the site's signature gesture, and it works as a semantic token swap rather than a second palette. Inside any inverted scope the same names resolve to flipped values, which is why both modes hold AA contrast without exceptions. This section performs the trick while describing it.
| Token | Paper mode | Ink mode |
|---|---|---|
| --paper | #eef2fa | #0a0d18 |
| --paper-2 | #e3eaf7 | #12172a |
| --ink | #0b0d14 | #eef2fa |
| --ink-2 | #3a404e | #c3cad8 |
| --ink-3 | #61687a | #7e869a |
| --hairline | rgba(11, 13, 20, 0.14) | rgba(238, 242, 250, 0.18) |
| --signal | #7eaaff | #7eaaff |
| --signal-strong | #2c57d6 | #7eaaff |
| --signal-soft | rgba(126, 170, 255, 0.14) | rgba(126, 170, 255, 0.16) |
| --focus | #2c57d6 | #7eaaff |
Same names, flipped values — components never learn a second palette.
Motion
One easing curve, five named durations, three behaviours: staggered reveals on scroll, band inversions at the viewport's centre, and figure and ground swapping on hover and focus. Everything runs on IntersectionObserver and the compositor, transform and opacity only, with no scroll-jacking and no animation library. If you prefer reduced motion, every one of these becomes an instant state change; nothing on the site hides behind an animation.
- [data-reveal]
- scroll into view IntersectionObserver · opacity + transform
- Inversion
- viewport centre band semantic token swap, animated
- Swap
- hover / focus pure CSS figure–ground flip
The instrument
On the homepage there is a panel with a single fader. It isn't a video and it isn't a mock. The control sets one normalised parameter, t, from noise (0) to calm (1), and t drives real CSS custom properties through the same token system as everything else. Type scale, spacing, density and signal dosage all interpolate from the one input. Past the calm threshold, one chip swaps figure and ground as a byproduct of the system resolving. Inversion is an output of coherence, never the control. The full mapping, as shipped, is printed below.
| Output | At t = 0 | Interpolation | At t = 1 |
|---|---|---|---|
| Type ratio | 1.33 | lerp(1.33, 1.20, t) | 1.20 |
| Space | ×0.62 | lerp(0.62, 1.15, t) | ×1.15 |
| Density | 12 bars | round(lerp(12, 4, t)) | 4 bars |
| Signal | 84% | lerp(84, 12, t) | 12% |
| Mode | NOISE | t > 0.33 · t > 0.66 | RESOLVED |
- Past t > 0.66 one chip inverts figure and ground — inversion as a byproduct of the system resolving, never the control.
- On entry the panel sweeps 0 → 1 once, then settles at t = 0.72. With reduced motion it simply starts there.
Performance
Performance is the pitch, so it's budgeted like one: largest contentful paint under 2 seconds on a mid-tier phone over 4G, with 1.5 as the target on the homepage, layout shift under 0.05, less than 40KB of gzipped first-party JavaScript, Lighthouse at 95 or better across the board. Static HTML does most of the work; the type is split by unicode-range so a page fetches only the letters it sets, and the discipline does the rest. The measured figures below are audited against the deployed site, and two of them miss. They are printed anyway. A budget you only publish when you clear it is decoration, not a budget.
| Metric | Budget | Measured |
|---|---|---|
| LCP · homepage, mobile | < 2.0 s · target 1.5 | 2.68 s · 2.1–4.3 |
| LCP · homepage, desktop | < 2.0 s · target 1.5 | 0.51 s |
| LCP · applied 4G throttle | < 2.0 s · target 1.5 | 1.17 s |
| CLS | < 0.05 | 0.000 · 0.001 desktop |
| JS · interface, eager | < 40 KB gzip | 27 KB |
| JS · WebGL hero mark, deferred | none set | 274 KB |
| JS · analytics, async | ≤ 80 KB gzip | 98 KB |
| Fonts · preloaded, first paint | none set | 85 KB · 3 shards |
| Page · total transfer | none set | 648 KB |
| Lighthouse · mobile | ≥ 95 × four categories | 95 · 100 · 100 · 100 |
| Lighthouse · desktop | ≥ 95 × four categories | 100 · 100 · 100 · 100 |
* measured, did not meet its budget. Audited 2026-08-31 against the deployed site, Lighthouse 13.4.1: median of eight mobile runs and three desktop. The mobile LCP range is printed beside its median because the runs are bimodal and one number would hide that. Transfer figures are as served. Lighthouse columns read performance · accessibility · best practices · SEO.
Accessibility
Craft that excludes people isn't craft. The commitments are hard ones: WCAG 2.1 AA contrast in both colour modes, checked at the start, middle and end of every inversion, full keyboard operability with a visible focus ring, honoured reduced-motion preferences, and nothing that flashes. These aren't audit checkboxes bolted on at the end. They are constraints the design was composed inside.
- Contrast
- WCAG 2.1 AA in both modes — held through every inversion
- Keyboard
- everything operable; focus always visible
- Reduced motion
- every animation becomes an instant state change
- No flashing
- bands resolve — they never strobe
- Structure
- real landmarks, one h1, ordered headings, a skip link