/* ==========================================================================
   workspace-ui - the fourteen @font-face declarations, and nothing else.

   ONE FILE, ONE FAMILY. Every block below points at the same 63,068-byte
   variable woff2. `Swinston Sans` is the text family; `Swinston Sans Display`
   is the same file at a different scale and weight, reached through `--font-serif`.
   ~~used by exactly one element, the home hero~~ - that element was removed on
   2026-09-08 (`_handoff/DIVERGENCES.md` §24) and `--font-serif` now has NO consumer
   in source: `git grep -nE "\bfont-serif\b" -- "*.tsx" "*.ts"` returns 0, against
   403 for `font-bold`. The blocks stay - they cost nothing unloaded, and deleting a
   face is a separate decision from deleting the element that used it.

   WHY THIS FILE EXISTS - unchanged from round 104A and still load-bearing.
   tokens/theme.css is pulled in by app/globals.css, which app/layout.tsx
   imports, so declarations placed there are compiled into layout.css and
   page.css. next dev serves those with a ?v=<Date.now()> cache-buster; React
   de-duplicates stylesheets BY HREF, so a fresh ?v= is a DIFFERENT sheet and
   both copies are live for one frame. Under the second copy every face
   registers again as a new, un-loaded FontFace, font-display: swap paints that
   frame in the fallback stack, and the whole document - sidebar, composer,
   every paragraph - re-measures and shifts sideways for one screen frame
   before snapping back. That is the "at the end of a message it shoots to the
   right or left and then finishes" in the operator spec, section 2.

   Measured by round 97 and re-measured by round 104A on dev server 5941,
   run before1, window = the actions row to the end of capture:
       document.fonts.size    4 -> 8 -> 4      (now 14 -> 28 -> 14)
       character 120        +42.36 px, then exactly -42.36
       character 360       +141.25 px
       last word            +99.40 px
       the answer's BOX          0 px   - which is why round 85 read zero
       displaced for           6.8 ms   one screen frame

   A file under public/ is served as a static asset. It belongs to NO route
   segment CSS chunk, so nothing can re-insert it under a second href and the
   faces are registered once for the life of the document. It is linked from
   the <head> in app/layout.tsx.

   DO NOT @import this from theme.css or from globals.css, and do not add a
   face to theme.css. Either puts the declarations back inside the bundled CSS
   graph and the defect returns.

   THE FOUR DESCRIPTORS THAT DO THE CONVERSION, and why each number is what it
   is. Swinston Sans is not the reference sans: it is smaller on the body, lighter on
   the stem, and it has no optical-size axis.

     size-adjust: 113.929%
       510.4 / 448 - the reference face's RENDERED x-height at the 14px step over Swinston's
       ink x-height. Both numbers are ink, which is what gets painted.

       NOT 517 / 444. The reference face's OS/2 sxHeight of 517 describes optical size 14,
       and optical size 14 is the 12px step; the opsz axis lowers the x-height
       as the text grows, 517 -> 510.4 -> 503.8 -> 497.2 -> 492.7 -> 491.3 ->
       489.0 across the seven steps. A factor built on 517/444 renders 521.6,
       which is taller than the reference face at ANY optical size, so it overshoots every
       step in the product. 14px is where the type is - text-sm is 665 of the
       953 type-step utility uses - so that is where the x-heights are made
       equal, exactly, and the other six steps take the residual.

       What this costs: cap height. The reference face's cap is 710 at every optical size and
       no single factor can match both. This one renders 690.4, 2.8% short.
       x-heights exact where 70% of the type lives is the right way round.

       It is a descriptor and NOT the font-size-adjust property on purpose: the
       scale then travels with the face, so var(--font-mono), emoji and the
       fallback stack are untouched by construction, and canvas measureText -
       which cannot see font-size-adjust, because ctx.font is a `font`
       shorthand and the shorthand resets it - measures correctly.
       components/chat/follow-ups.tsx sizes the follow-up pills with
       measureText and would otherwise clip them.

       Accepted cost: Safari 16.4 to 16.6 supports the property and not this
       descriptor, and renders 12.2% small there. Chrome only shipped the
       property in 127, so the property's hole is wider and more recent.

     ascent-override / descent-override / line-gap-override
       83.39 / 21.94 / 17.55 = the reference face's 0.95 / 0.25 / 0.20 em box divided by the
       size-adjust factor, because the percentages resolve against the adjusted
       em. They reproduce the reference face's box exactly, including line-height: normal =
       1.4em: 0.833851 x 14 x 1.139286 = 13.30px of ascent, and the reference face's is
       0.95 x 14 = 13.30px. Without them Swinston's own 800/-200/0 box sits the
       baseline high, which crosses a pixel at the 24px step: baseline offsets
       measured 11/14/17/20/23/25/31 for the reference face and 11/14/17/20/23/24/31 for
       un-overridden Swinston. The display family uses the reference Serif's box,
       0.92 / 0.28 / 0, for the same reason.

       Headroom, in case anyone worries about usWinAscent 1050: Swinston's
       tallest accented capital is Aring at 804 units, clearing the 950 ascent
       by 146 units. The reference face's Aring is 973 and overhangs its own 950.

     font-variation-settings: "wght" N
       The weight map. The reference face's CSS weights carry a stroke-to-x-height ratio that
       Swinston reaches at a DIFFERENT axis value, so each declared CSS weight
       gets its own face pinned to the matching design weight:

           CSS 300 -> 400   CSS 400 -> 474   CSS 450 -> 520
           CSS 500 -> 565   CSS 600 -> 592   CSS 700 -> 624

       Solved as the mean of two rendered-stroke rulers, the vertical bar of
       `l` and the left stroke of the round `o`, against the reference face at optical size
       15.1 and after the 113.929% scale: the reference face at 400 is stem 89.5 and round 91.4,
       which need 78.56 and 80.22 of Swinston stroke, which land at wght 468.3
       and 479.2. The round ruler matters because that is where the two faces
       diverge and the gap widens with weight. This is what lets the 121
       literal font-weights in component CSS and the six weight tokens in
       theme.css stay exactly as they are.

       THIS DESCRIPTOR IS THE ONLY THING PINNING THE AXIS. A variable face
       takes its wght from the resolved CSS weight, clamped to the font-weight
       descriptor's range; font-synthesis: none only blocks synthetic bold.
       Measured: a face declaring `font-weight: 100 900` at CSS 500 rendered
       498.703, which is design 500. Lose this line and the product renders
       Swinston's own ramp, stem/x 0.132 against the reference face's 0.174, a 24% light
       stroke on 20,956 declarations. It is not a graceful degradation.

       The descriptor survives an element-level font-variation-settings that
       names a DIFFERENT axis - measured, 491.156 with and without
       `"opsz" 15.1` - which is the only reason this works at all, because
       theme.css section 7 puts `"opsz" N` on every .text-* utility. An
       element-level setting that names "wght" WOULD override it. There are
       none today. Do not add one.

     "ital" 1 on the italic faces
       Chrome does not drive the ital axis from font-style on its own: the ink
       of a 140px `l` stays 9px wide with font-style: italic alone and goes to
       27px with this descriptor. Same mechanism the reference faces used. The
       italic is a real 10.01-degree slant with its own outlines, and its
       advance widths are identical to the roman at every weight, so an italic
       run costs zero width.

   Swinston Sans has no tnum, and no other GSUB feature in this font touches a
   digit either. font-variant-numeric: tabular-nums is inert at the 15 sites
   that carry it. Two of those sites depended on it structurally and are fixed
   in the same change: the OTP field (auth-stage.css, now var(--font-mono) on
   the input and the ghost, because six digits of a real code drift 16.83px
   off the cell grid the caret is drawn on) and the stamp sizer
   (authentication-section.tsx, now "8888-88-88", because '8' is wider than
   '0' without the table). The other declarations stay: they cost nothing and
   they light up if the face ever gains the feature.
   ========================================================================== */

/* -- text family: roman ---------------------------------------------------- */

@font-face {
  font-family: "Swinston Sans";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 400;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 474;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: normal;
  font-weight: 450;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 520;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 565;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 592;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 624;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}

/* -- text family: italic, driven by the ital axis --------------------------- */

@font-face {
  font-family: "Swinston Sans";
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 400, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 474, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: italic;
  font-weight: 450;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 520, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 565, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 592, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  size-adjust: 113.929%;
  ascent-override: 83.39%;
  descent-override: 21.94%;
  line-gap-override: 17.55%;
  font-variation-settings: "wght" 624, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}

/* -- display family: the home hero, and nothing else ------------------------
   Same file, scaled to the reference Serif's INK x-height (489/448 = 109.152%) and
   carrying that serif's em box, because it replaces the serif rather than the
   sans.

   WEIGHT 466, SOLVED ON INK AND NOT ON STROKE. The two faces cannot be matched
   on stroke: the reference Serif runs a thick of 104.5 against a thin of 35.4,
   contrast 2.95, where Swinston is monolinear - matching the thick gives
   design 537 and matching the mean of thick and thin gives 412. Matching the
   mass on the line gives 466: ink area per unit advance is 176.53, and
   176.53 x 1.091518 = 192.68 against the serif's 192.66, which is +0.01%.
   Design 400, an earlier answer here, is 160.26, or 16.8% less ink.

   That earlier answer came from measuring `Serif` in the calibration page,
   which never loaded: `style.fontFamily = "Serif"` is the CSS generic keyword,
   keywords are case-insensitive, and the span rendered in Times New Roman.
   calib/server.log never fetched serif.woff2, result.json records
   `Serif/normal/400:unloaded`, and shaped Times at 48px is 630.539 against the
   630.547 the page measured. The real the reference serif line is 627.600.

   Width, with the -0.015em on .font-serif in tokens/theme.css:
       the reference serif                                  627.600
       this face, bare                             651.140    +3.75%
       this face, tracked                          628.820    +0.19%

   Cap height is what this spends: 606 x 1.091518 = 661.5 against 710, 6.8%
   short. A sans matched to a serif on x-height is the standard substitution.

   ONE WEIGHT ON PURPOSE, AND THE DESCRIPTOR IS WHAT HOLDS IT. The base layer
   asks h1 { font-weight: 500 }. A variable face takes its wght from the
   resolved CSS weight clamped to this block's font-weight descriptor, so the
   clamp helps, but the font-variation-settings line is the thing pinning the
   axis. The whole point of a separate family is that Swinston HAS a 500 and
   the serif did not: a naive swap would have promoted the hero to design 565,
   +12% wide and far darker.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Swinston Sans Display";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 109.152%;
  ascent-override: 84.29%;
  descent-override: 25.65%;
  line-gap-override: 0%;
  font-variation-settings: "wght" 466;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
@font-face {
  font-family: "Swinston Sans Display";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  size-adjust: 109.152%;
  ascent-override: 84.29%;
  descent-override: 25.65%;
  line-gap-override: 0%;
  font-variation-settings: "wght" 466, "ital" 1;
  src: url("/fonts/swinston-sans-variable.woff2") format("woff2");
}
