/* =========================================================================
   3D PROTAGON PUZZLES — WEBFONT LAYER
   -------------------------------------------------------------------------
   Self-hosted variable fonts. Replaces the previous render-blocking
   `@import url('https://fonts.googleapis.com/...')` inside tokens.css, which
   cost a DNS lookup + TLS handshake + two serial round trips to a third-party
   origin before the first text could paint.

   Everything below is same-origin, so the font bytes travel in the same
   connection as the document and are discovered as soon as this file is
   parsed. Callers emit <link rel="preload" as="font"> for the two faces used
   above the fold (see Navigation::injectNavStyles()).

   Families and axes (verified from the shipped binaries with fontTools):
     Fraunces        variable  wght 100-900, opsz 9-144   (display)
     Figtree         variable  wght 300-900               (body / UI)
     JetBrains Mono  variable  wght 400-800               (puzzle grids)

   Layout stability
   ----------------
   Swapping a fallback font for a webfont normally shifts text because the two
   faces have different advance widths and different ascent/descent metrics.
   Each family therefore ships a metric-matched synthetic fallback built from
   `size-adjust` + `ascent-override` + `descent-override` + `line-gap-override`.

   The values are CALIBRATED BY MEASUREMENT, not copied from the OS/2
   xAvgCharWidth field — that field is a poor predictor of how a real sentence
   lays out (using it directly left the fallback ~9% too narrow for Figtree and
   ~8% too narrow for Fraunces). Instead each pair is rendered side by side in
   Chromium across a set of representative strings and the width ratio is
   measured directly:

       size-adjust      = mean(realWidth / fallbackWidth) at weight 400
       ascent-override  = (realAscender  / realUnitsPerEm) / sizeAdjust
       descent-override = (realDescender / realUnitsPerEm) / sizeAdjust

   Because the two overrides are divided by size-adjust, the resulting line box
   equals (realAscender + realDescender) / realUnitsPerEm of the webfont's em at
   any size, so both the horizontal and the vertical metrics line up and the
   swap contributes ~0 CLS.

   Targets and residual width error (lower is better):
     Figtree        vs Arial            (calibrated on Liberation Sans) +/-0.32%
     Fraunces       vs Georgia          (calibrated on Gelasio)         +/-1.26%
     Fraunces       vs Times New Roman  (calibrated on Liberation Serif) +/-2.34%
     JetBrains Mono vs Courier New      (calibrated on Liberation Mono)  +/-0.01%

   Note that `local()` performs exact family-name matching and does NOT consult
   fontconfig aliases, so the open metric clones (Liberation/Arimo/Tinos/
   Gelasio/Cousine) are listed explicitly alongside the commercial names. Windows
   and macOS users match the commercial faces; Linux and ChromeOS users match the
   clones; both give the same calibrated metrics.

   The fallbacks only engage via local() — on a machine with none of the named
   faces the browser simply falls through to the system stack.
   ========================================================================= */

/* ── Figtree — body & UI text ─────────────────────────────────────────── */
@font-face {
    font-family: 'Figtree';
    font-style: normal;
    font-weight: 300 900;
    font-display: swap;
    src: url('../fonts/figtree-latin.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;
}

@font-face {
    font-family: 'Figtree';
    font-style: normal;
    font-weight: 300 900;
    font-display: swap;
    src: url('../fonts/figtree-latin-ext.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;
}

/* Metric-matched fallback: Arial / Helvetica / Liberation Sans / Arimo.
   Calibrated by measurement against Liberation Sans (metric-compatible with
   Arial): size-adjust 100.561%, residual width error only +/-0.32% across six
   representative strings at weight 400. */
@font-face {
    font-family: 'Figtree Fallback';
    font-style: normal;
    font-weight: 300 900;
    src: local('Arial'), local('Helvetica Neue'), local('Helvetica'), local('Liberation Sans'), local('Arimo');
    size-adjust: 100.56%;
    ascent-override: 94.47%;
    descent-override: 24.86%;
    line-gap-override: 0%;
}

/* ── Fraunces — display & headings ───────────────────────────────────── */
@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 100 900;
    font-stretch: normal;
    font-display: swap;
    src: url('../fonts/fraunces-latin.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;
}

@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 100 900;
    font-stretch: normal;
    font-display: swap;
    src: url('../fonts/fraunces-latin-ext.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;
}

/* Metric-matched fallback: Georgia (and its open metric clone Gelasio).
   Calibrated by measurement against Gelasio: size-adjust 102.808%, residual
   width error +/-1.26%. */
@font-face {
    font-family: 'Fraunces Fallback';
    font-style: normal;
    font-weight: 100 900;
    src: local('Georgia'), local('Gelasio');
    size-adjust: 102.81%;
    ascent-override: 95.13%;
    descent-override: 24.8%;
    line-gap-override: 0%;
}

/* Metric-matched fallback: Times New Roman (and its open clones Tinos and
   Liberation Serif). Calibrated against Liberation Serif: size-adjust
   111.508%, residual width error +/-2.34%. */
@font-face {
    font-family: 'Fraunces Serif Fallback';
    font-style: normal;
    font-weight: 100 900;
    src: local('Times New Roman'), local('Tinos'), local('Liberation Serif');
    size-adjust: 111.51%;
    ascent-override: 87.71%;
    descent-override: 22.87%;
    line-gap-override: 0%;
}

/* ── JetBrains Mono — puzzle grids, counters, timers ─────────────────── */
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
    src: url('../fonts/jetbrains-mono-latin.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;
}

@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
    src: url('../fonts/jetbrains-mono-latin-ext.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;
}

/* Metric-matched fallback: Courier New (and its open clone Cousine). */
@font-face {
    font-family: 'JetBrains Mono Fallback';
    font-style: normal;
    font-weight: 400 800;
    src: local('Courier New'), local('Cousine'), local('Liberation Mono');
    size-adjust: 99.98%;
    ascent-override: 102.02%;
    descent-override: 30%;
    line-gap-override: 0%;
}
