/* ============================================================
   PrepArcade typography — ONE definition, self-hosted, for every page.

   THE BUG THIS FILE EXISTS TO FIX (owner, 2026-08-12):
   "the website/landing page temporarily switches from the correct PrepArcade
    typography to a default serif/book-style font… on weak connections and on
    different devices."

   It had two causes, and both are real:

   1. NO FALLBACK WAS DECLARED. 214 rules across 11 files were written as
      `font-family:'Fredoka'` with nothing after the comma — because there was
      no comma. When Fredoka has not arrived, CSS falls through to the browser's
      DEFAULT font, and on Chrome, Edge, Firefox and Safari that default is a
      SERIF (Times New Roman). So the "book-style font" was not a fallback going
      wrong; it was the complete absence of one.

   2. THE FONTS CAME FROM A THIRD PARTY. Every page fetched Fredoka, Nunito,
      JetBrains Mono and Source Serif 4 from fonts.googleapis.com — two round
      trips (the CSS, then the woff2) to a host this product does not control,
      with no preload. On a slow link, a lossy mobile connection, or a network
      where Google Fonts is throttled or blocked, that window is long or never
      closes. Nothing about it is visible in local testing on a fast machine,
      which is why it read as random.

   WHAT REPLACES IT

   · The four faces are SELF-HOSTED from /brand/fonts/, same origin as the page,
     covered by the same connection that already delivered the HTML. They are
     VARIABLE fonts — one file per family instead of one per weight, so the four
     of them are 4 requests and ~226 KB rather than 16 requests.
   · Every family has a METRIC-MATCHED fallback below it. The size-adjust and
     ascent/descent overrides are MEASURED, not copied from a table — see
     `node scratchpad/measure-font-fallbacks.js`, which loads the real files in
     a real browser and compares them against the real system font. Matched this
     way the fallback occupies the same space, so when the webfont lands the
     glyphs change and nothing reflows.
   · The stacks are exposed as custom properties. Rules say `var(--pa-display)`,
     never a bare quoted family, so a fallback can never be forgotten again —
     and `node scratchpad/check-font-fallbacks.js` fails the build if one is.

   `font-display: swap` is kept deliberately. The alternative, `optional`, would
   leave a visitor on a slow link reading the fallback for the whole session;
   with the metrics matched, swap costs a shape change and no movement.
   ============================================================ */

/* ---------- the real faces, self-hosted ---------- */

@font-face {
  font-family: 'Fredoka';
  font-style: normal;
  font-weight: 300 700;
  font-stretch: 100%;
  font-display: swap;
  src: url('/brand/fonts/fredoka-var.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: 'Nunito';
  font-style: normal;
  font-weight: 200 1000;
  font-display: swap;
  src: url('/brand/fonts/nunito-var.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: 100 800;
  font-display: swap;
  src: url('/brand/fonts/jetbrains-mono-var.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: 'Source Serif 4';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('/brand/fonts/source-serif-4-var.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;
}

/* ---------- metric-matched fallbacks ----------
   Measured 2026-08-12 against the system font on Windows/Chromium at 1000px.
   `local()` only — these never download anything; they are a re-scaling of a
   font the device already has. If none of the named faces exists the browser
   drops to the next entry in the stack, which is still a sans-serif. */

@font-face {
  font-family: 'Fredoka Fallback';
  src: local('Segoe UI'), local('Helvetica Neue'), local('Arial');
  size-adjust: 99.6%;
  ascent-override: 97.8%;
  descent-override: 23.7%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Nunito Fallback';
  src: local('Segoe UI'), local('Helvetica Neue'), local('Arial');
  size-adjust: 104.4%;
  ascent-override: 96.8%;
  descent-override: 33.8%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'JetBrains Mono Fallback';
  src: local('Consolas'), local('Menlo'), local('DejaVu Sans Mono');
  size-adjust: 109.1%;
  ascent-override: 93.5%;
  descent-override: 27.5%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Source Serif 4 Fallback';
  src: local('Georgia'), local('Times New Roman');
  size-adjust: 88.3%;
  ascent-override: 117.3%;
  descent-override: 37.9%;
  line-gap-override: 0%;
}

/* ---------- the stacks every rule should use ----------
   The final generic is `sans-serif` on three of the four. That is the whole
   point: even with every named face missing, the page cannot land on Times.
   Only --pa-serif ends in `serif`, because there it is intended. */

:root {
  --pa-display: 'Fredoka', 'Fredoka Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --pa-body:    'Nunito', 'Nunito Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --pa-mono:    'JetBrains Mono', 'JetBrains Mono Fallback', ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', monospace;
  --pa-serif:   'Source Serif 4', 'Source Serif 4 Fallback', Georgia, Cambria, 'Times New Roman', serif;

  /* THE FONT INSIDE A DRAWN FIGURE, and it needs its own name.

     .pa-fig-svg used to say `font-family: var(--pa-body)`, and mathexplain.css
     ALSO uses --pa-body as a BACKGROUND on the explanation blocks
     (.pa-goal, .pa-answer, .pa-vgoal, .pa-vwhy and friends). A custom property
     is substituted textually, so inside any of those a figure's font-family
     resolved to a gradient, which is invalid, and the labels fell back to
     Times New Roman — the one outcome the note above says cannot happen.
     Measured 2026-09-01: 3.0927 em per test string in Nunito, 2.7341 in the
     fallback, so a figure inside a worked solution was set in a serif at a
     different width from every other label in the product.

     A `var(--pa-body, fallback)` cannot fix it: the fallback applies only when
     the property is UNSET, not when it holds a colour. The name has to be one
     nothing else writes to. */
  --pa-fig-font: 'Nunito', 'Nunito Fallback', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
