/**
 * Ponoki brand fonts — self-hosted, loaded by every page.
 *
 * Why self-hosted: Google Fonts cost 2 extra origins (DNS + TLS each) and 3
 * serial requests, because the font URLs are not known until the render
 * blocking CSS comes back. Same-origin WOFF2 plus a <link rel="preload"> in
 * the page head starts both fetches immediately on the connection that is
 * already open, and no visitor IP reaches a third party (PRIVACY_POLICY.md
 * section 8).
 *
 * Why the *Fallback faces: with font-display: swap the browser paints in a
 * fallback first. If that fallback has different metrics the text re-wraps when
 * the real font lands and everything below it moves (measured 0.1014 CLS on
 * thought-untangler). The metric-matched faces below occupy identical space, so
 * the layout is the same before the font arrives, after it arrives, and in the
 * case where it never arrives at all. Only the glyph shapes differ, never the
 * box.
 *
 * The files are latin-subset variable fonts (one file covers every weight the
 * app uses, 200-800), taken from the same Google build the app used to link.
 *
 * This file must load AFTER each page's own stylesheet so its :root wins; it is
 * the last <link> in every head. Per-file @import of fonts is deliberately not
 * used (docs/DESIGN.md).
 */

@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/assets/fonts/dm-sans-latin.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
}

/* Metric-matched stand-ins. size-adjust starts from the measured width ratio of
   the real face against Arial over a sample of the app's own copy (DM Sans
   0.9195, Inter 1.0627) and, for Inter, was then moved to the value that
   measured 0 CLS on the Air Mode overlays, which were the last blocks still
   re-wrapping (1.0627 -> 0.0133, 1.08 -> 0, 1.10 -> 0.0006, so 1.08 is a
   basin and not a fitted edge). The ascent/descent overrides are the real
   face's own metrics divided back through size-adjust, so the line box height
   matches too. local() only, so these never cost a request.
   ponytail: one size-adjust per family, tuned on the 400 weight, which is the
   body copy. Headings at 600 sit a few percent off, during the swap window
   only. If that ever shows, split into per-weight fallback faces. */
@font-face {
  font-family: 'DM Sans Fallback';
  src: local('Arial'), local('Helvetica'), local('Roboto');
  size-adjust: 91.95%;
  ascent-override: 107.88%;
  descent-override: 33.71%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial'), local('Helvetica'), local('Roboto');
  size-adjust: 108.00%;
  ascent-override: 89.70%;
  descent-override: 22.33%;
  line-gap-override: 0%;
}

/* The single definition of the brand font stacks. Games consume these tokens
   and must not restate the family names, so a new game gets the metric-matched
   fallback without having to know it exists. */
:root {
  --font-display: 'DM Sans', 'DM Sans Fallback', sans-serif;
  --font-body: 'Inter', 'Inter Fallback', sans-serif;
}
