/* Weather Hub: self-hosted Manrope (Google Fonts, SIL OFL 1.1).
   Plex Mono remains for technical values; legacy faces remain addressable. */
@font-face {
  font-family: "Manrope";
  src: url("/assets/fonts/manrope-variable.91761990.woff2") format("woff2");
  font-style: normal;
  font-weight: 200 800;
  unicode-range: U+0000-10FFFF;
  font-display: swap;
}
/* --- 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%;
}
/* Manrope, the Weather Hub's body face, had no matched fallback until HB-5, and nothing showed
 * it while the homepage's panel arrived after the font: the swap reflowed a "Loading" line. Once
 * the server composed the panel, the swap reflowed every row in it, and the throttled phone
 * profile measured 0.11 of layout shift from nothing else. Derived as the two above, in the
 * browser that renders it (fontTools cannot read the woff2 here without Brotli):
 *
 *   Manrope   ascent 1.066 em, descent 0.300 em, lineGap 0 (canvas font bounding box at 1000px)
 *   advance   101.2% of Liberation Sans (Arial's metric clone), summed over the homepage's own
 *             sixty visible strings at the weights they are set in (400: 101.2%, 600: 98.9%,
 *             700: 100.8%, 800: 101.9%)
 */
@font-face {
  font-family: "Manrope Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 101.2%;
  ascent-override: 105.3%;
  descent-override: 29.6%;
  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;
}
