Press
Next.js App Router on Vercel. Server components throughout; the client leaves are the edition toggle, the letters slip, the weather strip and the controls on this page.
The Back Shop · Surat, Gujarat
A colophon is where a paper admits how it was made. This one is unusual only in that the sheet was measured rather than picked: the colour is solved backwards out of a printing standard, the grain is built in the frequency domain so that it cannot show a seam, and the share card is fitted against a line box that was read off pixels because the documented one was wrong.
Monday, 28 September 2026 · every number below is computed on this page or measured from a file in the repository.
Colour·A1
Nearly every “newspaper” theme on the web is the colour of an old letter: warm, tea-stained, faintly amber. Real newsprint is not. It is a pale, almost neutral grey-cream, and it only reads as yellow when you put it next to office white.
ISO 12647-3, newsprint paper white states it exactly — L* 85 ±4, a* 1 ±2, b* 5 ±2. So rather than choose a hex value and argue about it, this site converted the sheet it was already shipping back into CIELAB and compared.
It measured b* 13.7. Against a target of 5 with a ceiling of 7, the yellow axis was nearly three times the standard’s figure and almost double what it permits. That is parchment. The sheet was rebuilt from Lab targets instead, and now measures b* 5.5.
Where the honesty goes
The shipped sheet sits at L* 92.5, which misses the standard’s L* 85 ±4 by 7.5. That is deliberate and it is not a pass. Paper reflects light; a screen emits it, and a literal L* 85 reads as dirty grey on a monitor. The b* axis is the one that decides whether a sheet looks like newsprint or like parchment, so b* is held to the standard and L* is not. ΔE*ab from the target is 7.6 for the shipped sheet and 10.3 for the one it replaced.
Repaint this page
The sheet under this page is being repainted as you press these. The numbers are computed from the value actually set on --paper.
| Token | sRGB | L* | a* | b* | Role |
|---|---|---|---|---|---|
| --paper | #eee9df | 92.5 | 0.5 | 5.5 | the sheet |
| --stock | #e1dbce | 87.6 | 0.5 | 7.2 | panels and boxes |
| --ink | #2b2723 | 16.0 | 1.3 | 3.4 | body text |
| --faded | #676055 | 41.1 | 1.4 | 7.4 | secondary text |
| --rule | #463f36 | 27.2 | 1.8 | 6.7 | rules and borders |
| --spot | #b93830 | 44.0 | 52.1 | 35.9 | the second colour |
| --press | #5e5346 | 36.1 | 3.0 | 9.4 | subheads |
| --desk | #9c8f7a | 60.1 | 2.4 | 13.1 | the desk beneath |
Static values; the live reading replaces them once the page hydrates.
Texture·A2
A flat colour does not read as paper. Paper has fibre in it, and fibre has to repeat across the page without ever showing where the repeat happens.
The usual approach is to make some noise, tile it, look at it, and blur the edges until the seam stops being obvious. This tile is built in the frequency domain instead: an amplitude spectrum is shaped, random phase is applied, and the inverse FFT is taken. The output of an inverse FFT is periodic by construction — it wraps because that is what the transform produces, not because anything was smoothed. There is no seam to hide.
It carries only high frequencies. Anything slow enough to be recognised across 256px would give the repeat away, so the slow blotching lives in CSS as viewport-fixed radial gradients and never tiles at all.
The seam, measured
If the wrap is genuinely continuous, the average step across the join must look like any other step inside the tile.
Within one per cent of the interior in x and four per cent in y. The generator asserts this on every run and refuses to write a tile that fails it.
256×256, repeated. 40 KB.
Type fitting·A3
The image that appears when this site is pasted into Slack is rendered by Satori, which lays text out itself and reports nothing back. To fit a headline to its hole, the renderer has to know how tall the block will be before it draws it.
Two guesses failed. An average advance width of 0.46 em is wrong because Bodoni’s capitals are far wider than its lowercase; real advances read out of the font’s hmtx table fixed the width but not the height, because the height model assumed fontSize × lineHeight.
Satori does not do that. It scales an explicit numeric line-height again by a factor of its own. Rather than read source, single lines were rendered at known sizes with a rule under each and the block heights read off the pixels.
The factor is close to 1.27 and it does not depend on size, so a headline can now be fitted by stepping down until the wrapped block fits the height that is actually left for it. The ceiling of the measurements is used rather than the mean: over-stating a line only sets the headline one step smaller, while under-stating it prints the headline through the standfirst, which is exactly what the first version did.
| Face | Size | line-height | Measured | Ratio |
|---|---|---|---|---|
| Bodoni Moda 700 | 100px | 1.00 | 127px | 1.270 |
| Bodoni Moda 700 | 100px | 1.06 | 135px | 1.274 |
| Bodoni Moda 700 | 100px | 1.60 | 203px | 1.269 |
| Bodoni Moda 700 | 50px | 1.06 | 67px | 1.264 |
| Oswald 500 | 20px | 1.20 | 30px | 1.250 |
| Oswald 500 | 40px | 1.20 | 59px | 1.229 |
| Spectral 400 | 25px | 1.36 | 44px | 1.294 |
| Spectral 400 | 50px | 1.36 | 86px | 1.265 |
CSS would put every ratio at 1.000. The probe that produced this is tools/og-line-probe.mjs.
Stack·A4
Press
Next.js App Router on Vercel. Server components throughout; the client leaves are the edition toggle, the letters slip, the weather strip and the controls on this page.
Composition
Tailwind over CSS custom properties written as space-separated RGB triples, so one token serves every opacity. Type on a fluid clamp() scale computed from a slope, not chosen per breakpoint.
Faces
Bodoni Moda for headlines, Spectral for body, Oswald for the condensed furniture, Grenze Gotisch for the nameplate, Special Elite for the typewriter. Three are subset to 84 KB for the share card.
Motion
GSAP with ScrollTrigger, batched, and reverted through useGSAP so nothing outlives its component. Everything answers to prefers-reduced-motion.
Sheen
One fullscreen quad in Three.js drawing a single exponential falloff under the pointer. It refuses to start on a phone, on a slow device, on a saved-data connection, or without hover.
Measurement
Chrome DevTools Protocol driven from Node: width sweeps for overflow, console and network for errors, and the pixel probes behind sections II and III.
No cookies and no third-party trackers. The only analytics are Vercel’s, which are cookieless and store no identifier. Source: github.com/BondeYash.