/* Self-hosted webfonts.
 *
 * These used to arrive through a `@import url(https://fonts.googleapis.com/...)` at the
 * top of tokens.css, which is the worst place to put a third-party dependency: an @import
 * inside a stylesheet blocks rendering until it resolves, and it resolves over a network
 * we do not control. Google Fonts is unreachable from some networks entirely — including
 * this project's own build sandbox, where it fails with ERR_CONNECTION_RESET and every
 * page falls back to system fonts. A site that renders differently depending on whether a
 * third party is reachable is a site with an availability dependency nobody chose.
 *
 * ## One superfamily, two registers
 *
 * The two faces are one type family — **IBM Plex** — drawn as a system so the sans and the
 * mono share a skeleton, a set of proportions and the same terminals. That is the whole
 * point of the pairing, and it is what the pairing before it did not have: Public Sans (a
 * Franklin-lineage signage sans) and Inconsolata (a printed-code-listing mono) came from two
 * unrelated worlds, and set together — a mono headline over a sans sentence — they read as
 * two eras on one page. Plex Sans over Plex Mono reads as one voice at two widths.
 *
 *   IBM Plex Sans   the whole interface and all prose: the page title, section headings,
 *                   system names, navigation, controls and running text. A humanist
 *                   grotesque — a signage face, which is the register a transit board is
 *                   lettered in — legible from the title down to an 11px label, and
 *                   unmistakably contemporary, which is what keeps the page from reading as
 *                   a terminal. Variable, weights 400-700 in one file per subset.
 *
 *   IBM Plex Mono   values, and only values: winds, pressures, coordinates, timestamps,
 *                   IDs, ATCF codes, endpoint paths and code. The register a reader compares
 *                   down a column — tabular figures keep digits aligned, and a `LABEL...VALUE`
 *                   field line only tracks if the value advances at a fixed rate. It is
 *                   demoted from the headings it used to carry; a monospace is for data.
 *                   Static, weights 400 and 600 (IBM ships no variable mono), two files each.
 *
 * That is **6 files and ~135 KB**; the latin subsets that carry the critical path are the
 * variable sans (one file, every weight) and the 400 mono, ~60 KB preloaded, and the
 * latin-ext subsets and the 600 mono are fetched only when a page needs them.
 *
 * Both families are SIL Open Font License 1.1, which permits redistribution. The whole
 * superfamily ships under one licence; see site/assets/fonts/OFL-IBMPlex.txt.
 *
 * Only `latin` and `latin-ext` are vendored, and their `unicode-range` values are byte
 * identical to the ones the retired families used — the ranges are the subsetter's, not the
 * family's, so they carry across a family change unchanged. A character outside these ranges
 * falls back to the system font for that character alone, which is the graceful behaviour.
 *
 * `font-display: swap` throughout: text is readable in the fallback immediately and reflows
 * once the face lands. shell.js re-measures the sticky bars on `document.fonts.ready`
 * precisely because that swap changes their height.
 */

/* --- The metric-matched fallbacks -----------------------------------------------------
 *
 * `font-display: swap` keeps text readable while the face loads, and then reflows it. That
 * reflow is a measurable cost: the storm overview scored a Cumulative Layout Shift of 0.113
 * attributable to nothing but this swap, because the fallback and the webfont set the same
 * sentence at different widths and every block below it moved.
 *
 * The fix is a fallback face that occupies the webfont's space. There are two — a sans and a
 * mono — because both registers carry text that shifts: the sans holds the headings, the
 * prose and the interface, and the mono holds every value on the page.
 *
 * Derived, not guessed. Metrics from fontTools; the sans advance measured in the browser
 * that renders it, against five real strings taken from this site rather than an alphabet:
 *
 *   IBM Plex Sans   unitsPerEm 1000, ascender 1025, descender -275, lineGap 0
 *   IBM Plex Mono   unitsPerEm 1000, ascender 1025, descender -275, lineGap 0
 *
 *   size-adjust      = target advance / local advance
 *   ascent-override  = (ascender / unitsPerEm)  / size-adjust
 *   descent-override = (|descender| / unitsPerEm) / size-adjust
 *
 * The two are derived differently on purpose, and this is the part worth reading:
 *
 *   The **mono** ratio is exact. Every glyph in a monospace face has one advance, and IBM
 *   Plex Mono is 0.600 em per character — the same advance as Courier New, the primary
 *   local fallback — so 0.600 / 0.600 = 100% is arithmetic, not an estimate.
 *
 *   The **sans** ratio is statistical, and the obvious estimator is wrong. Deriving it from
 *   the average advance over a-z would overshoot real prose, because real sentences are not
 *   uniform alphabets: they are letter-frequency weighted and full of spaces, capitals and
 *   punctuation. Swept against actual site copy, IBM Plex Sans sets ~91.7% of Arial's width,
 *   so 91.7% is the size-adjust that makes the fallback occupy the webfont's box.
 *
 * `local()` only: neither face downloads anything. Each renames a font the reader already
 * has into one that measures like ours, so the first paint and the swapped paint occupy the
 * same box. Arial and Helvetica cover Windows and macOS and Liberation Sans is the metric
 * clone most Linux distributions ship; Courier New and Liberation Mono are the same
 * arrangement for the mono. Where none is present the stack falls through and the swap costs
 * what it always did.
 *
 * To re-derive after a font update: read unitsPerEm/ascender/descender with fontTools, then
 * sweep the sans size-adjust in a browser against real strings from the site. Do not derive
 * the sans value from an alphabet — that is the mistake this comment exists to stop being
 * repeated.
 */
@font-face {
  font-family: "IBM Plex Sans Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 91.7%;
  ascent-override: 111.8%;
  descent-override: 30.0%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono Fallback";
  src: local("Courier New"), local("Liberation Mono"), local("DejaVu Sans Mono");
  size-adjust: 100%;
  ascent-override: 102.5%;
  descent-override: 27.5%;
  line-gap-override: 0%;
}

/* IBM Plex Sans 400-700, variable */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-variable-latin-ext.d160e209.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-variable-latin.e2291e84.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* IBM Plex Mono 400, static */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-400-latin-ext.6bc0f226.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-400-latin.08949f72.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* IBM Plex Mono 600, static — emphasised values */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-600-latin-ext.32057cf5.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-600-latin.0d1f0b8d.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
