/* ============================================================================
   fonts.css — THE FACES EVERY PAGE MAY USE, SERVED FROM THIS SITE (#2166, #2025).

   Every page used to take these from a render-blocking Google Fonts stylesheet in <head>, before a
   synchronous script. A synchronous script waits for every stylesheet ahead of it, so the page could
   not paint until Google answered - and when Google did not answer (a filtered office network, a
   country that blocks it, a bad minute) the guest saw a BLANK page. Measured 2026-09-25: with Google
   held, page.goto timed out at 20 s with no body at all; with it answering, 200 ms. Gautam, 2026-09-25:
   keep the fonts on our own site.

   ⚠️ THE SAME CUT AS THE RASTERIZER. Each woff2 is the woff2 of the .ttf beside it in
   static/vendor/fonts, which v12/markrender.mjs reads with loadSystemFonts false - so a studio mark
   drawn by the server and the same words drawn by the browser are one typeface, not two (the reason
   themes.css gives for the theme faces, #2037). Spline Sans Mono is the exception: nothing draws it
   on the server, so only its woff2 ships.

   ⚠️ LAZY. An @font-face downloads nothing until text on the page uses that family, so declaring a
   face here costs a page that never draws in it nothing.

   The theme families' own faces (Fraunces, Space Grotesk, Archivo, Cormorant Garamond, Playfair
   Display) are in themes.css, which only the themed pages load. Weights are the RANGE each variable
   file really holds, so a 600 is the drawn 600 and never a synthesised one.

   ⚠️ EVERY url CARRIES ?v=<its own content hash> (app.py::_asset_digest, sha1[:10]). Without it a font
   is an "unversioned static" to sw.js, which re-asks the network for it on EVERY page open - the text
   flashes the fallback and swaps each time - and to serve_asset, which lets the edge keep it a week
   under a name whose bytes may change. With it, serve_asset freezes the file for a year and sw.js keeps
   it once. CHANGE A FILE, CHANGE ITS ?v=: qa/test_mark_typeface.py [1.9] reds on a hash that is not the
   file's own, because a stale token would pin the OLD bytes on every phone that already has them.
   ============================================================================ */
@font-face{font-family:"Marcellus";font-style:normal;font-weight:400;font-display:swap;
  src:url(/vendor/fonts/Marcellus.woff2?v=020acd05df) format("woff2")}
@font-face{font-family:"Hanken Grotesk";font-style:normal;font-weight:100 900;font-display:swap;
  src:url(/vendor/fonts/HankenGrotesk.woff2?v=9116d14f02) format("woff2")}
/* Italic only: no page asks for an upright Cormorant, and none exists in vendor/fonts. */
@font-face{font-family:"Cormorant";font-style:italic;font-weight:300 700;font-display:swap;
  src:url(/vendor/fonts/Cormorant-Italic.woff2?v=b3fa20c51d) format("woff2")}
/* The HERO face for keepsake and blush. Moved here from themes.css: the guest gallery, the console's
   keepsake preview (#1410) and the design pages all draw in it, and only two of those load themes.css. */
@font-face{font-family:"Great Vibes";font-style:normal;font-weight:400;font-display:swap;
  src:url(/vendor/fonts/GreatVibes.woff2?v=63876f9720) format("woff2")}
/* The console's numbers and tags (console.css --font-mono). */
@font-face{font-family:"Spline Sans Mono";font-style:normal;font-weight:300 700;font-display:swap;
  src:url(/vendor/fonts/SplineSansMono.woff2?v=be8b63156e) format("woff2")}
