/*
 * The webfonts for all three pages, and the second copy of them in this repository.
 *
 * Geist Sans and Geist Mono, self-hosted. They replaced IBM Plex Sans and IBM Plex Mono,
 * which these pages pulled from Google Fonts — one `preconnect` pair plus one stylesheet
 * link in each of the three `<head>`s. **Geist is not on Google Fonts at all**, so there is
 * no equivalent link to swap in: self-hosting is forced rather than chosen.
 *
 * Why the files are duplicated under `public/fonts/` rather than reached from
 * `packages/ui-theme/fonts/`: this directory has no build step, so nothing can be imported
 * or bundled from across the workspace — exactly the cost `legal.css` already accepts for
 * the palette, and `features/042` for `theme.css`. A relative path up out of `public/` would
 * not be served either: `wrangler.jsonc` publishes `./public` and nothing above it. So the
 * two `.woff2` files here are byte-identical copies of the ones in `packages/ui-theme/fonts/`,
 * and **they must be replaced together.** Check with:
 *
 *     shasum -a 256 packages/ui-theme/fonts/geist*.woff2 apps/website/public/fonts/geist*.woff2
 *
 * Why a linked file rather than three inline `@font-face` blocks: there are three pages and
 * they must not drift from each other about which faces they load. That is `legal.css`'s
 * argument, and `legal.css` is the proof it works here — a shared stylesheet in this
 * directory needs no build step and no seam. index.html links this one even though it keeps
 * its palette and its 1400 lines of layout inline, because a *face* is not a colour: two
 * copies of an `@font-face` block are two URLs that can rot independently, and a page
 * rendering in the system sans while its neighbour renders in Geist is the visible failure.
 *
 * The OFL requires the licence to travel with the font, so `fonts/Geist-OFL.txt` sits beside
 * them — one file, because both faces are one project.
 *
 * Two variable files, latin subsets, 52.5 kB together:
 *
 *   fonts/geist-var-latin.woff2        29,400 bytes  (wght 100–900 in one file)
 *   fonts/geist-mono-var-latin.woff2   23,128 bytes  (wght 100–900 in one file)
 *                                      ------------
 *                                      52,528 bytes
 *
 * Smaller than what it replaced, and measured rather than assumed. The Google link declared
 * six latin `@font-face`s but resolved to three files — Plex Sans was one variable file reused
 * for 400/500/600/700, Plex Mono two static cuts — totalling 60,352 bytes, fetched from
 * `fonts.gstatic.com` after a stylesheet round-trip to `fonts.googleapis.com`. So: 7,824 bytes
 * less over one fewer file, and from this origin instead of two of Google's. That is also why the
 * `preconnect` hints went with the link rather than being re-pointed at anything — there is
 * no longer a third-party connection to warm up, and the faces arrive on the one the page has
 * already opened. Plex Mono having been two static cuts is why the mono `@font-face` below is
 * a single variable file where it used to be a pair.
 *
 * No `unicode-range` on either face, deliberately. Google's stylesheet carried one per
 * subset file because it ships many; with one file per family a range can only *prevent*
 * the face being used for a character it actually contains. Missing glyphs still fall back
 * per glyph, which is ordinary font fallback and is what already happened here. Compared
 * rather than assumed: Google's latin subset ran `U+0000-00FF, U+0131, U+0152-0153, ...,
 * U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215`, and the twelve codepoints
 * these pages use outside it (↗ ↩ ↻ ▣ ◆ ◉ ◎ ◐ ☼ ⚿ ✓ ➤) are exactly the twelve Geist's 225
 * glyphs also lack. Same substitutions before and after, on all three pages — this change
 * neither costs nor gains a glyph, which is worth knowing because the mono ones sit in the
 * terminal mockup, where a different advance width would shear the row.
 */

/*
 * Every number below is measured off the two shipped files with fontTools, not copied from a
 * spec sheet or from the sibling stylesheet in `packages/ui-theme`. Both faces report
 * identically, which is the useful part — these pages set mono inline against sans constantly
 * (a count beside a label, a path beside prose) and the pair aligns by construction:
 *
 *     unitsPerEm 1000 | x-height 530 (53.0%) | cap 710 (71.0%)
 *     typo/hhea ascender 1005 | descender -295 | line gap 0
 *     wght axis 100..900, default 400
 */
/*
 * `format('woff2')` on a *variable* file, deliberately, and not the `format('woff2-variations')`
 * that a variable face is often written with. That string is a legacy of CSS Fonts 3 — it was
 * dropped in favour of `tech(variations)` — and a format string a browser does not recognise
 * makes it skip the source entirely, which fails as "the page renders in the system sans" with
 * nothing in the console. Plain `woff2` is the standard spelling and needs no capability
 * detection: a browser new enough to render a variable font is a browser that reads the axis
 * out of the file. Checked here rather than assumed — under Chrome all three spellings load and
 * `font-weight: 900` really does interpolate wider than 400 — and this is the one that is also
 * correct everywhere else.
 */
@font-face {
  font-family: 'Geist';
  src: url('/fonts/geist-var-latin.woff2') format('woff2');
  /* The real axis, so nothing is clamped silently. It reaches 900; the page asks for 400,
     500, 600 and one 700, all inside it. */
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Geist Mono';
  src: url('/fonts/geist-mono-var-latin.woff2') format('woff2');
  /* Variable too, unlike Plex Mono, which shipped here as two static cuts. So the 400/500
     the page asks of its mono are interpolated from one file rather than being two
     downloads, and a weight between them would work if anything wanted one. */
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/*
 * A fallback face carrying Geist's own metrics, so `font-display: swap` moves nothing.
 *
 * Derived rather than transcribed, and the arithmetic is here because it is the part that
 * silently goes wrong. Two locals, and only two, because these are the faces whose metrics
 * were measured on the machine this was written on:
 *
 *     Helvetica Neue   upm 1000  x-height 517  (51.700%)   <- what macOS resolves
 *     Arial            upm 2048  x-height 1062 (51.855%)   <- what Windows resolves
 *
 * `size-adjust` scales the fallback until its x-height matches Geist's 53.0%:
 * 53.0 / 51.7 = 102.5% against Helvetica Neue, and 53.0 / 51.855 = 102.2% against Arial. One
 * number has to serve both, so it is Helvetica Neue's; the residual error on an Arial machine
 * is 0.3% of the em, under a third of a pixel at 16px. A device with neither face skips this
 * `@font-face` entirely — the `src` fails — and lands on the next family in `--sans` with no
 * override at all, which is the honest degradation and the reason nothing unmeasured is
 * listed here.
 *
 * ⚠️ **The overrides are divided by `size-adjust`, and that division is load-bearing.**
 * `size-adjust` multiplies every metric of the face *including* the three overrides, so an
 * `ascent-override` written as the raw 100.5% would render 103.0% once scaled. Verified
 * rather than reasoned about: a probe face with `ascent-override: 100%` and
 * `size-adjust: 200%` produces a 200px line box at `font-size: 100px` in Chrome, not 100px.
 * So each override is the measured ratio divided by 1.025:
 *
 *     ascent-override    100.5% / 1.025 = 98.0%
 *     descent-override    29.5% / 1.025 = 28.8%
 *     line-gap-override      0% / 1.025 = 0%
 *
 * Checked against the real face rather than left as arithmetic. At `font-size: 100px` Chrome
 * gives both 'Geist' and 'Geist Fallback' a 130px line box — which is Geist's own
 * (1005 + 295) / 1000 — and rasterises the same 53.5% x-height for each, where unadjusted
 * Helvetica Neue is a 119px box at 52.0%. Written raw, the ascent would have come out at
 * 133.25px and every line of the page would have moved on swap.
 */
@font-face {
  font-family: 'Geist Fallback';
  src: local('Helvetica Neue'), local('Arial');
  size-adjust: 102.5%;
  ascent-override: 98.0%;
  descent-override: 28.8%;
  line-gap-override: 0%;
}
