/* Fonts, reset, type scale. The design styles live in css/design. */
/* The faces (D-192): Outfit for interface text, JetBrains Mono for every
   figure, time, address and code, Space Grotesk for page titles only.
   All self-hosted from /static/fonts (D-205), the latin subset from the
   @fontsource packages (docs/STACK.md), under the OFL beside them.
   Declaring a face costs nothing: a browser downloads a file only when
   something on the page is set in it, so each layout preloads the faces its
   first screen is set in and the rest arrive when asked for. */
@font-face { font-family: "Outfit"; font-weight: 400; font-style: normal; font-display: optional; src: url("/static/fonts/outfit-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "Outfit"; font-weight: 500; font-style: normal; font-display: optional; src: url("/static/fonts/outfit-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "Outfit"; font-weight: 600; font-style: normal; font-display: optional; src: url("/static/fonts/outfit-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-weight: 400; font-style: normal; font-display: optional; src: url("/static/fonts/jetbrains-mono-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-weight: 500; font-style: normal; font-display: optional; src: url("/static/fonts/jetbrains-mono-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-weight: 600; font-style: normal; font-display: optional; src: url("/static/fonts/jetbrains-mono-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-weight: 500; font-style: normal; font-display: optional; src: url("/static/fonts/space-grotesk-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-weight: 600; font-style: normal; font-display: optional; src: url("/static/fonts/space-grotesk-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-weight: 700; font-style: normal; font-display: optional; src: url("/static/fonts/space-grotesk-latin-700-normal.woff2") format("woff2"); }
/* The serif is the headline option a status page may ask for (D-150),
   Source Serif 4 in the design. Only a page that carries the class below
   downloads it. */
@font-face { font-family: "Source Serif 4"; font-weight: 600; font-style: normal; font-display: swap; src: url("/static/fonts/source-serif-4-latin-600-normal.woff2") format("woff2"); }

/* Metric-matched fallbacks (#895). While a face downloads, the text is set
   in a local system font; when the face arrives the text swaps. With
   different widths and line heights that swap rewraps headings and moves
   everything under them. Each rule below is a local font stretched to the
   web face's measurements, so the swap keeps the line breaks and heights.
   The numbers come from the woff2 files and the system fonts' OS/2 and
   hhea tables (fontTools), then one correction from the page itself:
   - size-adjust starts as the web face's average advance width over
     English letter frequencies and the space, divided by the fallback's,
     so the fallback is drawn as wide as the face it stands in for. The
     average misses by up to a few percent on real words, which is a line
     that wraps differently, so Outfit and Space Grotesk are divided once
     more by the width ratio measured on the text of /, /pricing, /docs and
     /sign-in (the fallback's width over the face's, 1.007 to 1.054 before
     the correction). JetBrains Mono needed none: the ratio was 1.000.
   - ascent-override, descent-override, line-gap-override: the web face's
     ascender, descender and line gap (the typo metrics, all three faces
     set USE_TYPO_METRICS, gap 0) as a share of its em, divided by the
     final size-adjust because the browser applies size-adjust to the
     overrides too.
   Outfit and Space Grotesk fall back to Arial (Arial Bold for the heavier
   weights, whose widths differ); JetBrains Mono to Courier New. A machine
   without those fonts skips the rule and uses the next family in the
   stack, as it did before. Source Serif 4 is left out: only a status page
   asks for it.
   The three site faces are font-display: optional, not swap. The match
   above is within about one percent over a page, but a single heading
   near a line break (a 72px title a few pixels from its max-width) still
   wraps differently in the two fonts, and a swap then moves the page by a
   whole line: 0.10 on /docs at 1440 even after the match. With optional a
   face that is not ready for the first paint (the layouts preload the
   ones the page uses, so on a normal connection it is) is not swapped in
   under the reader; this page keeps the fallback and the next one, with
   the file cached, gets the real face. */
@font-face { font-family: "Outfit Fallback"; font-weight: 400; src: local("Arial"), local("ArialMT"); size-adjust: 98.87%; ascent-override: 101.14%; descent-override: 26.30%; line-gap-override: 0%; }
@font-face { font-family: "Outfit Fallback"; font-weight: 500; src: local("Arial"), local("ArialMT"); size-adjust: 99.64%; ascent-override: 100.36%; descent-override: 26.09%; line-gap-override: 0%; }
@font-face { font-family: "Outfit Fallback"; font-weight: 600; src: local("Arial Bold"), local("Arial-BoldMT"); size-adjust: 93.59%; ascent-override: 106.84%; descent-override: 27.78%; line-gap-override: 0%; }
@font-face { font-family: "Space Grotesk Fallback"; font-weight: 500; src: local("Arial"), local("ArialMT"); size-adjust: 109.51%; ascent-override: 89.86%; descent-override: 26.67%; line-gap-override: 0%; }
@font-face { font-family: "Space Grotesk Fallback"; font-weight: 600; src: local("Arial Bold"), local("Arial-BoldMT"); size-adjust: 97.44%; ascent-override: 100.99%; descent-override: 29.97%; line-gap-override: 0%; }
@font-face { font-family: "Space Grotesk Fallback"; font-weight: 700; src: local("Arial Bold"), local("Arial-BoldMT"); size-adjust: 101.43%; ascent-override: 97.01%; descent-override: 28.79%; line-gap-override: 0%; }
@font-face { font-family: "JetBrains Mono Fallback"; font-weight: 400 500; src: local("Courier New"), local("CourierNewPSMT"); size-adjust: 99.98%; ascent-override: 102.02%; descent-override: 30%; line-gap-override: 0%; }
@font-face { font-family: "JetBrains Mono Fallback"; font-weight: 600; src: local("Courier New Bold"), local("CourierNewPS-BoldMT"); size-adjust: 99.98%; ascent-override: 102.02%; descent-override: 30%; line-gap-override: 0%; }

/* The stacks put each fallback between its face and the next family. They
   are set here, on html:root, because tokens.css and design-site/tokens.css
   are held byte for byte to the design's files (TestEveryUsedTokenIsDefined,
   TestSiteKitMatchesTheExploration) and the extra specificity wins over
   either whichever order the sheets load in. Same names, same faces. */
html:root {
  --font-ui: "Outfit", "Outfit Fallback", system-ui, sans-serif;
  --font-data: "JetBrains Mono", "JetBrains Mono Fallback", ui-monospace, monospace;
  --font-title: "Space Grotesk", "Space Grotesk Fallback", "Outfit", system-ui, sans-serif;
  --font-display: "Space Grotesk", "Space Grotesk Fallback", "Outfit", system-ui, sans-serif;
  --font-text: "Outfit", "Outfit Fallback", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", "JetBrains Mono Fallback", ui-monospace, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

/* Everything is sized in rem on a 16px base, so the browser's font-size
   setting scales the whole product. Wide monitors get a larger base so the
   1440px design does not look small on a 27-inch screen (D-34). */
html { font-size: 100%; }
@media (min-width: 1920px) { html { font-size: 112.5%; } }
@media (min-width: 2560px) { html { font-size: 125%; } }
/* The signed-in app takes the design's scaling root (card 282, from
   design/explorations/dashboard tokens.css): 1rem runs from 16px on a
   phone to 19px on a wide screen. The shell sets the density every app
   screen inherits; the site, the sign-in pages and a customer's status
   page keep the root above until their own cards redraw them. */
html:has(body > [data-app]) { font-size: clamp(100%, 0.75rem + 0.35vw, 118.75%); }

/* The ground and the ink come from the theme (tokens.css), so a page
   turns with its data-theme. Interface text in the app is the design's
   15 on a 16 root; the pages outside it stay on the 14 they were drawn
   on. */
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.875rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
body:has(> [data-app]) { font-size: var(--t-body); line-height: var(--lh); text-rendering: optimizeLegibility; }

/* The element resets the old kit had are gone (card 433, D-310): the
   margins of headings, paragraphs, lists and figures, the list markers,
   the heading faces, the link colour and underline, the fields' font,
   the button's pointer, the code face and block images. The design sets
   none of them and draws on the browser's defaults and its own element
   rules (css/design/components.css), so its screens sit as the
   prototype does; the old screens differ until their cards redraw them. */

button { font: inherit; color: inherit; }

/* The focus ring is the design kit's :focus-visible outline, in
   css/design/components.css (D-310). The old kit drew a box-shadow here
   as well, which showed as a second ring beside the design's. */

/* HTMX indicator classes, since we disable its injected stylesheet. */
.htmx-indicator { opacity: 0; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }

/* Visible to a screen reader, to nothing else. The strip's live region
   uses it (card 083). */
.u-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
