/* Self-hosted fonts (variable) — no CDN contact, GDPR-clean, same pattern as the previous
   Inter setup. Files are from @fontsource-variable/*; one variable woff2 per subset covers the
   whole weight range. Roles (see app.css tokens):
     Nunito    — interface + headings (--fd)
     Manrope   — digits, prices, data (--fn; tabular-nums applied per component)
     Unbounded — the logo wordmark only (--fl)
   To update: replace the files under /fonts and adjust paths here.

   ---- Vertical metrics are overridden on purpose; do not drop these ----
   A box centres the font's EM box, but the eye centres the INK. Nunito reserves 35.3% of the em
   below the baseline for descenders while its caps rise only 71.9% above it, so in every centred
   box — badge, pill, tab, button — the label sat visibly HIGH: measured asymmetry
   101.1 − 71.9 − 35.3 = −6.07% of the em, i.e. ~2px on the "Nintendo Switch 2" tag, ~0.8px on a
   sale pill. Manrope errs the OTHER way (+4.7%), which is why per-component padding fudges kept
   fighting each other and landing on opposite sides.

   Overriding ascent/descent so the cap box is symmetric fixes it ONCE, for every element on the
   site, in every browser (Chrome 87+/FF 89+/Safari 17+) — including elements nobody remembers to
   annotate. It is preferred over `text-box-trim: trim-both` here because that is Chrome/Safari-only
   AND it changes every badge's height, forcing all the paddings to be re-tuned.

   Each pair KEEPS the font's original ascent+descent sum (Nunito 136.4%, Manrope 136.6%), so
   `line-height: normal` and every box height are byte-identical to before — only the baseline
   moves, by ~3% of the em, which is the whole point. Values are derived, not guessed:
       ascent = (sum + inkAscent) / 2,  descent = (sum − inkAscent) / 2
   Nunito's caps, digits and ascenders all sit at exactly 71.9%, so cap-centring is exact for it.
   Manrope's caps are 71.9% and digits 73.4%; it is used for both, so we target their midpoint.
   Unbounded is already cap-symmetric (asymmetry 0.0000) and is deliberately left untouched.
   Re-derive with scratchpad metrics2.mjs if a font file is ever replaced. */

/* ---- Nunito ---- */
@font-face {
    font-family: 'Nunito';
    font-style: normal;
    font-display: swap;
    font-weight: 200 1000;
    ascent-override: 104.1%;
    descent-override: 32.3%;
    line-gap-override: 0%;
    src: url('/fonts/nunito-latin-wght-normal.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+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Nunito';
    font-style: normal;
    font-display: swap;
    font-weight: 200 1000;
    ascent-override: 104.1%;
    descent-override: 32.3%;
    line-gap-override: 0%;
    src: url('/fonts/nunito-latin-ext-wght-normal.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: 'Nunito';
    font-style: normal;
    font-display: swap;
    font-weight: 200 1000;
    ascent-override: 104.1%;
    descent-override: 32.3%;
    line-gap-override: 0%;
    src: url('/fonts/nunito-cyrillic-wght-normal.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* ---- Manrope ---- */
@font-face {
    font-family: 'Manrope';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    ascent-override: 104.6%;
    descent-override: 32.0%;
    line-gap-override: 0%;
    src: url('/fonts/manrope-latin-wght-normal.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+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Manrope';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    ascent-override: 104.6%;
    descent-override: 32.0%;
    line-gap-override: 0%;
    src: url('/fonts/manrope-latin-ext-wght-normal.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: 'Manrope';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    ascent-override: 104.6%;
    descent-override: 32.0%;
    line-gap-override: 0%;
    src: url('/fonts/manrope-cyrillic-wght-normal.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* ---- Unbounded (logo only) ---- */
@font-face {
    font-family: 'Unbounded';
    font-style: normal;
    font-display: swap;
    font-weight: 200 900;
    src: url('/fonts/unbounded-latin-wght-normal.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+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Unbounded';
    font-style: normal;
    font-display: swap;
    font-weight: 200 900;
    src: url('/fonts/unbounded-cyrillic-wght-normal.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}


/* ---- Country flags, on the platforms that ship none ----
   WINDOWS HAS NO FLAG GLYPHS. A flag emoji is a PAIR of regional-indicator letters that a font is
   supposed to ligate into one picture; Segoe UI Emoji does not, so Chrome draws the letters and the
   language pickers read "GB English" instead of "🇬🇧 English". Measured on this box 2026-08-30:
   U+1F1EC U+1F1E7 is 32px wide, exactly the sum of its two halves — no ligature — while a plain
   emoji (🌐) is 44px, so it is flags specifically and not emoji in general.

   **The flag cannot be an image, and that is why this is a font at all.** The pickers are native
   <select> elements and an <option> carries TEXT, not markup: no <img>, no inline <svg>, and
   `background-image` on an option is ignored in Chrome. A font is the only thing that reaches
   inside one. Replacing the <select> with a custom listbox would reach it too, and would cost the
   OS picker that phones give us for free.

   **`unicode-range` is what makes this safe to put first, globally.** The font is used ONLY for
   U+1F1E6–1F1FF, so it can never touch a letter, a digit or another emoji, and no selector has to
   be kept in step with wherever a flag is printed next.

   **Loaded only where it is needed**: index.html measures the pair against its halves before first
   paint and stamps `<html class="needs-flag-font">` when the platform has no flags, so macOS, iOS
   and Android — which have them — never fetch these 76 KB.

   Not subsetted, on purpose. Cutting it to the nine flags in use today would drop it to 29 KB and
   close the alphabet: 🇳🇱 for a future Dutch needs an L this file would no longer carry, and the failure
   would be one language silently showing letters while the rest show flags. 76 KB, fetched by one
   platform and cached, is not worth that trap.

   Twemoji Country Flags, built from Twemoji — graphics (C) Twitter, Inc and other contributors,
   CC-BY 4.0, which permits modification with attribution and a note of what changed; /legal carries
   both. Upstream: country-flag-emoji-polyfill 0.1.8, sha256 9f04f14429bb6a9f415c7a4dd902a918…,
   78,292 bytes. **The shipped file is that one with every glyph lowered 32 units and nothing else
   touched** — same colour layers, same ligatures, same code points. Rebuild it from the upstream
   file with `analysis/flag_font_baseline.py`, which derives the shift from the scale below. */
/* `size-adjust` is why the Union Jack is a flag here and not a smudge. The pickers render at
   13.44px, and at that size 🇬🇧 loses: its white fimbriations along the diagonals are thinner than a
   pixel, so it collapses into a blue-red blur — while 🇩🇪 🇫🇷 🇯🇵 🇷🇺, which are two or three flat
   bands, stay perfectly legible. It is a detail problem, not a font problem, and it belongs to the
   handful of busy flags (🇺🇸 goes the same way).

   Scaling the FLAGS without scaling the text is the only fix that keeps the pickers their size, and
   `size-adjust` on the face is the one tool that does it — it multiplies this family's glyphs alone,
   and `unicode-range` has already confined this family to flags.

   **BLURRING IT WAS TRIED AS AN IDEA AND IS THE WRONG DIRECTION — do not reach for it.** The art is
   COLR/CPAL vector, so there is nothing to soften but the rasteriser's own antialiasing, and the
   fimbriations are already a faint grey wash at this size: taking their last edge away leaves an
   even-toned smear. What a detailed picture needs at 13px is more pixels or thicker features, not
   fewer edges. (`filter` could not reach the character anyway — it lives inside an `<option>`.)

   **115%, and the number is paired with the font file.** Read off a ladder rendered at the real
   13.44px: 140 (the first attempt) is legible but visibly outweighs the word beside it, 110 loses
   the diagonals again, and 115 is where the flag's height matches the label's capitals. The glyphs
   are shifted DOWN by 32 units in the shipped file to match — the flag is drawn on the baseline like
   a letter, so every extra percent of scale pushes it further above the text's own centre, and at
   140% it floated 2.2px high. **`analysis/flag_font_baseline.py` computes that shift FROM this
   number; change one and re-run it, or the flag drifts off centre.** CSS cannot do it —
   `ascent-override` moves the line box, not the glyph on its baseline.

   **It costs no layout, which was the thing to check rather than assume**: with the scale applied,
   the dialog's own language select measured 27.375px, the plan row 20.39px, the plan list 118.03px
   and the whole dialog 440px — identical to 100%, to the hundredth of a pixel. */
@font-face {
    font-family: 'Twemoji Country Flags';
    font-style: normal;
    font-display: swap;
    font-weight: normal;
    src: url('/fonts/twemoji-country-flags.woff2') format('woff2');
    unicode-range: U+1F1E6-1F1FF;
    size-adjust: 115%;
}
/* The stack that USES it is next to the font tokens in app.css, deliberately: prepending this
   family means restating those stacks, and two copies three lines apart cannot drift unseen. */
