Why this typeface? Two families retired, budget up 27.5%.
Choosing a typeface is also a performance decision: the file delays first paint, it changes your metrics, and if it is calibrated wrong it turns into layout shift.
On 27 August 2026 this site retired two typeface families in a single round. Archivo and Spline Sans Mono went; Newsreader and IBM Plex Mono took their place. The typeface payload of a typical page rose from 82.6 KB to 105.3 KB — an increase of 27.5%. This article explains why that increase was accepted, and describes the three silent defects the round uncovered on the way.
The brief contradicted the font itself
The design brief said “Newsreader variable font: wght 300..500”. The font’s actual axis is 200–800. My first report repeated that error verbatim, and the budget decision was taken against a ceiling that did not exist. Once the axis was read from the font’s own fvar table the numbers changed and the decision was put again. With the corrected options, 400–800 was chosen: the site’s 92 weight declarations carried over almost exactly, whereas a ceiling of 500 would have flattened every one of them to mid-weight.
The narrower range produced the larger file
Three variants were measured while choosing the optical-size range, and the result ran against intuition:
- opsz 6–72 → 119.9 KB
- opsz 16–72 → 126.6 KB
- opsz 24–72 → 103.9 KB
A floor of 16 costs more than a floor of 6, because 16 is not a master in the font: the subsetter interpolates a new master at that point. A floor of 24 was chosen — it is both a real master and the sweep floor of the focus gesture.
The mono switch paid money back into the budget
- before Archivo 69.3 + Spline 13.3 = 82.6 KB
- after Newsreader 96.8 + Plex 8.5 = 105.3 KB
- pilot routes 312.2 → 152.1 KB
Subset to the glyph set this site actually uses, IBM Plex Mono dropped from 132.4 KB to 8.5 KB — smaller than Spline’s 13.3. The brief’s expectation of “roughly 50 KB more” was for two unsubsetted static weights. The brief’s own criterion, meanwhile, could not be met in any configuration: Newsreader’s roman cut alone is larger than the old pair. That was reported with this table and the increase was accepted deliberately. The subsetting tool is open source: woff2-axis-subsetter.
Three separate defects were one defect
The round’s first verification run produced eighteen failures, and most of them had their root in a single line: the animation library was handed a letter-spacing value of 0.200px and wrote 18.72px to the screen. The engine was computing correctly; the library’s CSS plugin did not recognise the input.
- mobile scroll CLS 0.3249 · 0.1996 · 0.4156 → 0.0008 · 0.0006 · 0.0012
- h1 swap @390 112.8 → 75.2px → 0.0px
- horizontal overflow 145px → 0
So three separate “defects” were one. The fix was to stop handing the value to the library at all: it is now written by hand from the tween’s own progress — one writer, one unit. The lesson went on the record: when you hand a layout property to a library, measure the output rather than the input, because the conversion can quietly produce a different value.
The signature gesture was dead for a whole round, and no eye could see it
On the third run a counter-evidence guard went red. Alignment was perfect, but the axis the focus effect drives had taken a single value across eighty frames. Four forms were tried in the browser:
- "opsz" 24.0 → 72 read back: "opsz" 24 frozen
- "opsz" 24 → 72 read back: "opsz" 43.2 flowing
- "wdth" 97 → 125 read back: "wdth" 108.452 flowing
- "opsz" 24, "wght" 800 → 72, 800 flowing
The cause: the library treats font-variation-settings as a complex string, and the numeric skeletons at both ends have to match exactly. The decimal point in 24.0 makes it parse as two numbers, the skeleton does not hold, and the library passes through without interpolating and without erroring. My own rounding call had created the defect. Every axis value was pulled to an integer; the measurement went from one distinct value to eighty.
The real weight of the lesson is this: nothing looked broken on screen. The blur was flowing, the opacity was flowing, only the signature axis was dead. Neither the eye, nor the layout-shift measurement, nor the accessibility audit, nor the test that measures alignment could have seen it. Only the reverse guard that asks “did the axis actually move?” saw it.
Optical sizing was pinned and the swap difference went to zero
Letting the browser pick optical size from the font size made a metric fallback impossible: Newsreader’s string width is 94.25% of Georgia’s at opsz 24 and 102.07% at opsz 72 — an 8.3% spread that no single size-adjust value can close. Optical size is now fixed and every role writes its own calibration value. The result: a typeface swap difference of 0.0px across six routes.
The fallbacks are no longer hand-calibrated either. A tool measures every weight and optical-size pair against Georgia and writes the ratio to a ledger; the output is deterministic, and the verification suite can re-derive those values from source and compare. Twenty-one Archivo fallbacks became six Newsreader fallbacks, with a measured size-adjust band of 91.92–102.07%.
Two gestures that reversed direction
The breathing gesture applied on hover said “floor plus five”. Under the new floor those five units land above the axis ceiling, so the font clips them silently and the gesture never appears at all. The relationship is inverted as well: as optical size drops, the letter widens. The gesture became minus five. The arrow glyph reversed too — up, down and bidirectional arrows exist in Plex but not in Newsreader, the exact opposite of the Archivo era.
If an axis is not moving there is no gesture — and only a test that measures the axis moving will see it.