/* ============================================================================
   base.css — reset, document defaults, the vendored faces, and the handful of
   single-purpose utilities the prototype leans on everywhere.

   Depends on tokens.css. Defines no colour of its own.
   ========================================================================= */

/* ---------------------------------------------------------------- fonts --
   Self-hosted, not fetched from fonts.googleapis.com as the prototype does.
   Three reasons, heaviest first: the CSP is `default-src 'none'` and a remote
   origin in font-src would be the only hole in it; a third party would
   otherwise see every customer's IP on every page load; and a CDN outage would
   take the app's typography down with it.

   Source Sans 3 and JetBrains Mono are the attempt-4 pairing (spec 012 R2).
   They replaced Instrument Sans and IBM Plex Mono, whose directories were
   deleted on 2026-09-05 — 640KB the deploy no longer copies. The prototypes
   under docs/designs/ still name the old pairing in their own --sans / --mono
   and are meant to: they are a record of what was designed, not something this
   stylesheet has to keep serving.

   Files are fontsource 5.3.0, vendored under wwwroot/vendor/fonts/ with their
   licences beside them. woff2 only — every browser this app supports reads it,
   so the .woff siblings fontsource ships would be bytes nothing requests.

   `font-display: swap` so text is readable on first paint. What shows during
   the swap is the fallback in --sans / --mono, which is why those are real
   stacks rather than a bare `sans-serif`.

   Two subsets each. latin-ext is not padding: a decoded IDN label can carry
   latin-ext characters, and a domain name renders in mono — without the subset
   a customer's own domain would fall back mid-string. Ranges are fontsource's
   own, unmodified. */

@font-face {
  font-family: 'Source Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  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 Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-ext-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Source Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  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 Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-ext-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Source Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  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 Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-ext-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Source Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  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 Sans 3';
  src: url('/vendor/fonts/source-sans-3/files/source-sans-3-latin-ext-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  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';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-ext-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  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';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-ext-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  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';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-ext-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  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';
  src: url('/vendor/fonts/jetbrains-mono/files/jetbrains-mono-latin-ext-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------- reset -- */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
}

/* color-scheme used to be pinned to `dark` here. It now lives in tokens.css,
   where it does two jobs at once: it still tells the browser which way to
   render a native <select> or a scrollbar, and it is also what decides which
   half of every light-dark() token applies. Setting it in two files would mean
   the later one silently won — and this file loads after tokens.css. */

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
}

/* NOT SET HERE: -webkit-font-smoothing: antialiased.
   It was, copied from the prototype, and it is the wrong call on a dark
   app. Antialiased turns off subpixel rendering and drops each glyph to
   greyscale coverage, which thins the stroke; light text on a dark ground
   is already thinned by the way the eye blooms the background into it. The
   two compound, and Source Sans 3 at the 11-13px this app uses for table
   data comes out looking a weight lighter than it is. The browser default
   is subpixel-antialiased and it is what ships. */

/* The prototype colours links by context rather than globally, so the
   default is inherit and each component states its own. */
a {
  color: inherit;
}

h1,
h2,
h3 {
  font-weight: 600;
  letter-spacing: -.015em;
}

/* ------------------------------------------------------------ keyboard --
   Not in the prototype, which shows no focus states at all. Removing the
   browser default without replacing it would make the app unusable by
   keyboard, so the accent ring is applied globally here and components
   override it only where they need a different offset. :focus-visible, so a
   pointer click does not draw it. */
:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- motion --
   Every transition in components.css is a colour fade of ~120ms, so honouring
   the OS preference costs nothing and removes them all in one place. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------- utilities --
   Deliberately few. Each marks a meaning, not a look: .mono says "this is
   data", .dim says "this is secondary". */

.mono {
  font-family: var(--mono);
}

.mid {
  color: var(--ink-2);
}

.dim {
  color: var(--ink-3);
}

/* Section marker — the small uppercase mono label above a heading. */
.kicker {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--green);
}

/* The dashed rule is a recurring motif; a solid <hr> is not the same mark. */
.rule {
  border: 0;
  border-top: 1px dashed var(--line-2);
  margin: 32px 0;
}

/* Available to assistive technology, invisible on screen. Used for the
   headings that give each landmark a name and for form labels the visual
   design carries in the placeholder instead. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Standard skip link: off-screen until focused, then pinned top-left. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 10px 16px;
  background: var(--bg-2);
  border: 1px solid var(--green);
  border-radius: 0 0 var(--r) 0;
  font: 500 13px var(--sans);
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
}

/* The one width the whole app is laid out inside. */
.wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px;
}
