/* GlideAPI canonical product system.
   Source: brand-spec.md, DESIGN-HANDOFF.md, DESIGN-MANIFEST.json,
   and Final-Glide-API-Website.html. Keep this file last in the cascade. */

/* No @import here. This file used to pull Inter + JetBrains Mono + Space Grotesk
   from Google Fonts, three families no declaration in this repo has asked for
   since the 2026-08-25 type change - so nearly every page was blocking on a
   stylesheet request for fonts it never drew with. The two families the tokens
   below actually name (Geist and Geist Mono) are requested by each
   page's own <link>, after a preconnect, which is what an @import cannot do:
   an @import inside a stylesheet cannot start downloading until that stylesheet
   itself has arrived. test/typography.test.js keeps the two in step. */

:root {
  color-scheme: dark;
  /* Blue-ink carbon, kept in step with the :root block in public/landing.html.
     Chroma is deliberately high for a "black" field (0.022–0.028 on the
     surfaces, 0.048–0.072 on the tinted plates) at hue 265–268. The previous
     0.008–0.017 read as flat neutral grey on an sRGB display, which is why the
     non-landing pages looked washed out next to the home page: same L, a third
     of the colour. Tonal separation between surfaces is carried by the L
     channel, not by desaturating them. test/paletteConsistency asserts this
     ramp matches landing.html token for token. */
  --bg: oklch(0.170 0.026 260);
  --bg-deep: oklch(0.124 0.028 260);
  --bg-raise: oklch(0.210 0.028 260);
  --surface: oklch(0.242 0.030 260);
  --surface-2: oklch(0.200 0.028 260);
  --surface-3: oklch(0.298 0.032 259);
  --fg: oklch(0.982 0.005 259);
  --body: oklch(0.856 0.014 259);
  --muted: oklch(0.688 0.022 259);
  --border: oklch(0.322 0.030 260);
  --border-2: oklch(0.400 0.032 259);
  --border-3: oklch(0.492 0.032 258);
  --accent: oklch(0.720 0.148 252);
  --accent-fill: oklch(0.558 0.198 258);
  --accent-hi: oklch(0.665 0.170 255);
  --accent-ink: oklch(0.985 0.006 252);
  --accent-dim: color-mix(in oklch, var(--accent) 14%, transparent);
  --accent-line: color-mix(in oklch, var(--accent) 34%, transparent);
  --good: oklch(0.810 0.160 156);
  --warn: oklch(0.832 0.150 84);
  --bad: oklch(0.700 0.190 24);
  --good-dim: color-mix(in oklch, var(--good) 11%, transparent);
  --warn-dim: color-mix(in oklch, var(--warn) 11%, transparent);
  --bad-dim: color-mix(in oklch, var(--bad) 11%, transparent);
  --field-paper: oklch(0.170 0.026 260);
  --field-sunk: oklch(0.120 0.030 260);
  --field-tint: oklch(0.222 0.058 258);
  --field-brand: oklch(0.256 0.086 258);
  --ink-bg: oklch(0.132 0.028 260);
  --ink-surface: oklch(0.206 0.030 260);
  --ink-surface-2: oklch(0.164 0.028 260);
  --ink-surface-3: oklch(0.252 0.032 259);
  --ink-fg: oklch(0.982 0.005 259);
  --ink-body: oklch(0.862 0.014 259);
  --ink-muted: oklch(0.688 0.022 259);
  --ink-border: oklch(0.306 0.032 260);
  --ink-border-2: oklch(0.376 0.034 259);
  --ink-border-3: oklch(0.464 0.032 258);
  --gap-xs: 8px;
  --gap-sm: 16px;
  --gap-md: 24px;
  --gap-lg: 32px;
  --gap-xl: 48px;
  /* Radius scale, widened 2026-09-01 in step with landing.html - see the long
     note at its own declaration for why 4/8/12 became 6/10/16. It is repeated
     here because these two sheets and docs.css each declare the ramp
     independently, and a shared token name carrying two different values is
     worse than two names: the landing page would round its table wraps and
     boards at 10/16 while the twelve pages it links to rounded the same
     materials at 8/12, on the same site, for no reason a visitor could see.
     The consumers here are exactly those materials - .table-wrap,
     .finance-table-wrap, .finance-kpi-board, and the four --ds-radius-*
     aliases. --r-xl and --r-pill are deliberately NOT copied: nothing in this
     sheet uses them, and a token declared in two files is a token the drift
     test then has to keep in step forever. test/paletteConsistency asserts the
     copies that DO exist agree. */
  --r-sm: 6px;
  --r: 10px;
  --r-lg: 16px;
  --maxw: 1200px;
  /* Full fallback chains, copied from landing.html. These used to stop at the
     generic family ('Inter', sans-serif), so whenever the webfont was slow,
     blocked, or absent the landing page fell back through system-ui/Segoe UI
     while every other page dropped straight to the browser's default sans -
     two different typefaces on the same site for the same reason.
     test/paletteConsistency asserts the three copies agree.

     The stack itself changed on 2026-08-25: Inter + Space Grotesk + JetBrains
     Mono is the default pairing of every AI product shipped since 2023, and it
     read as exactly that. Geist carries both the body and the UI headings and
     Geist Mono carries code and numerals. A third family - Instrument Serif -
     carried the display tier from 2026-08-27 to 2026-08-28 and is gone: an
     editorial serif over this palette made the marketing pages read as a
     different product from the console they hand off to, and the console is
     where a customer spends their time. Display hierarchy is size, weight and
     tracking now, which is how the console draws it.

     Repaired in the same pass: three families were named in stacks that no page
     ever loaded. landing.css asked for "IBM Plex Mono", site-pages.css and
     story-pages.css asked for "DM Sans" and "IBM Plex Mono", and none of them
     appeared in any <link>, so those surfaces silently rendered in the
     browser's default mono (Courier New on Windows) and default sans.
     test/typography now fails if a stack's first family is not actually served. */
  --font-display: Geist, system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --font-body: Geist, system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Compatibility aliases: every legacy surface resolves to the source palette.
     Trimmed 2026-09-01 from 83 names to 33. Five whole naming generations had
     piled up here - --ds-*, --ap-*, --s-*, --docs-* and half of --glide-* - and
     of the 83, fifty were read by nothing: no var() in any stylesheet, page or
     script under public/, and not one of the eight names portal/app.js resolves
     at runtime through getPropertyValue. They were not harmless. An alias layer
     is a menu, so the next person to style a panel picks --ds-surface as
     readily as --surface and cannot tell from here that one of them is what the
     site actually uses; and the four --ds-radius-* entries meant the radius
     scale appeared to have two spellings on the very sheet that was about to be
     re-scaled.

     What survives is what something reads today. --link and --green are the
     exception: nothing on a brand-system page reads either, but they name a live
     contract - syncThemeColors() in portal/app.js pulls --ink, --body, --mute,
     --faint, --hairline, --link, --green and --error off the root element to
     colour the dashboard sparklines. The portal gets its own copies from
     portal/style.css:73-76 and does not load this sheet, so these two are kept
     deliberately: --error beside them IS read here, and deleting two thirds of a
     documented trio invites someone to re-add them wrongly.

     Verified with `grep -rn "var(--token[,)]"` plus a sweep of every
     getPropertyValue('--…') call in public/. One casualty turned up on the way:
     docs.html:70 set `color:var(--docs-muted)` inline, and the docs page loads
     only docs.css, which never declared that name - test/docsLayout asserts it
     must not load this sheet either. An unresolvable custom property is invalid
     at computed-value time, so `color` inherited and the word between the two
     Anthropic routes drew in the route's own colour instead of a muted one. It
     reads var(--muted) now, which docs.css does declare. */
  --ink: var(--bg);
  --ink-2: var(--surface-2);
  --panel: var(--surface);
  --line: var(--border);
  --paper: var(--body);
  --white: var(--fg);
  --text: var(--fg);
  --text-secondary: var(--body);
  --text-tertiary: var(--muted);
  --surface-hover: var(--surface-3);
  --surface-raised: var(--bg-raise);
  --border-strong: var(--border-2);
  --primary: var(--accent);
  --success: var(--good);
  --warning: var(--warn);
  --danger: var(--bad);
  --mint: var(--accent);
  --glide-ink: var(--bg);
  --glide-panel: var(--surface);
  --glide-line: var(--border);
  --glide-text: var(--fg);
  --glide-muted: var(--muted);
  --glide-mint: var(--accent);
  --glide-cyan: var(--accent);
  --accent-hover: var(--accent-hi);
  --bg-subtle: var(--bg-deep);
  /* Read off the root by portal/app.js:161-163, not through var() here. */
  --link: var(--accent);
  --green: var(--good);
  --error: var(--bad);
  --btn-primary-bg: var(--accent-fill);
  --btn-primary-hover: var(--accent-hi);
  --btn-primary-text: var(--accent-ink);
  --focus-ring: 0 0 0 3px var(--accent-dim), 0 0 0 1px var(--accent);
}

*, *::before, *::after { box-sizing: border-box; }
html { min-width: 0; overflow-x: clip; background: var(--bg); scroll-padding-top: 88px; }
body {
  min-width: 0;
  min-height: 100vh;
  margin: 0;
  overflow-x: clip;
  background: var(--bg) !important;
  background-image: none !important;
  color: var(--body) !important;
  font: 400 14px/1.6 var(--font-body) !important;
  letter-spacing: 0 !important;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
html body { background-color: var(--bg) !important; }
body::before, body::after { pointer-events: none; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; letter-spacing: 0; }
img, svg, canvas { max-width: 100%; }
h1, h2, h3, h4, h5, h6, .page-hero h1, .admin-workspace h1 {
  margin-top: 0;
  color: var(--fg) !important;
  font-family: var(--font-display) !important;
  font-weight: 600;
  letter-spacing: 0 !important;
}
p, li, small, .subtitle, .page-lede, .help-text { color: var(--muted); }
code, pre, kbd, samp, time,
.price, .stat-value, .metric-value, .finance-kpi-value,
[data-metric], [data-price], .chip, .badge, .status-pill {
  font-family: var(--font-mono) !important;
  font-variant-numeric: tabular-nums;
}
::selection { background: var(--accent-line); color: var(--fg); }
:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--accent) !important;
  outline-offset: 3px;
  box-shadow: none !important;
}

/* Navigation: a single instrument bar across public, portal, and admin. */
.site-nav, .top-bar, .mobile-console-bar, .glide-nav {
  background: color-mix(in oklch, var(--bg-deep) 94%, transparent) !important;
  border-color: var(--border) !important;
  box-shadow: none !important;
  backdrop-filter: blur(16px);
}
.site-nav { min-height: 68px; height: 68px; border-bottom: 1px solid var(--border); }
.nav-inner { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: 24px; }
.nav-links, .nav-actions { align-items: center; }
.nav-links a, .nav-login, .portal-sidebar a, .admin-sidebar a,
.glide-nav__links a, .glide-nav__signin {
  color: var(--muted) !important;
  font-size: 13px;
  font-weight: 500;
}
.nav-links a:hover, .nav-links a.active, .nav-links a[aria-current='page'],
.portal-sidebar a:hover, .portal-sidebar a.active,
.admin-sidebar a:hover, .admin-sidebar a.active,
.glide-nav__links a:hover, .glide-nav__links a[aria-current='page'],
.glide-nav__signin:hover { color: var(--fg) !important; }
.brand-mark, .logo-mark { flex: 0 0 auto; }
.brand-mark img, .logo-mark img { display: block; object-fit: contain; object-position: left center; }
.site-nav .brand-mark {
  width: 158px !important;
  height: 38px !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 0 !important;
  overflow: visible !important;
}
.site-nav .brand-mark img {
  position: static !important;
  display: block !important;
  width: 158px !important;
  height: 38px !important;
  max-width: 158px !important;
  max-height: 38px !important;
  object-fit: contain !important;
  object-position: left center !important;
  transform: none !important;
}
.site-nav .brand-mark::after { content: none !important; }

/* One explicit lockup for console, authentication, and standalone pages. */
.logo-mark {
  width: auto !important;
  height: 38px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: flex-start !important;
  gap: 10px !important;
  overflow: visible !important;
}
.logo-mark::after { content: none !important; }
/* A bare lockup image inside .logo-mark. Height is pinned and width follows the
   artwork, because the 260:64 wordmark is the only image any .logo-mark in this
   codebase actually contains.

   This block used to force 30x30 on every axis with !important, on the premise
   that .logo-mark held a square app mark. No such asset ships. The consequences
   were that login.html and admin/index.html both had to opt back out through
   .full-brand-lockup below, and that the two bare lockups in
   public/portal/index.html were one stylesheet link away from being squashed
   into squares - which matters, because the portal does not load this sheet yet
   and adding it is on the list. Nothing rendered at 30x30 before this change
   (measured on /login.html, /portal/login and /portal/: 130x32, 130x32, 130x36),
   so pinning the height instead of the box is a no-op today and a trap removed.
   test/siteAlignment asserts no rule pins the lockup to a square again. */
.logo-mark img,
.portal-sidebar .logo-mark img,
.admin-sidebar .logo-mark img,
.mobile-console-bar .logo-mark img {
  position: static !important;
  display: block !important;
  width: auto !important;
  height: 30px !important;
  max-width: 100% !important;
  object-fit: contain !important;
  object-position: left center !important;
  clip-path: none !important;
  filter: none !important;
  transform: none !important;
}
.portal-sidebar .brand .logo-mark,
.admin-sidebar .admin-brand .logo-mark,
.mobile-console-bar .brand .logo-mark {
  width: auto !important;
  height: 38px !important;
}
.docs-identity { gap: 10px !important; }
.docs-identity img {
  width: 30px !important;
  height: 30px !important;
  min-width: 30px !important;
  object-fit: contain !important;
  object-position: center !important;
}
.docs-identity span {
  color: var(--fg) !important;
  font: 600 18px/1 var(--font-display) !important;
  letter-spacing: 0 !important;
  white-space: nowrap !important;
}

/* Buttons: command surfaces, not decorative pills. */
.btn, .button, .primary-action, .secondary-action, .nav-cta,
button.primary, button.secondary, .glide-nav__cta {
  min-height: 38px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--border-2) !important;
  border-radius: var(--r-sm) !important;
  box-shadow: none !important;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}
.btn-primary, .button.primary, .primary-action, .nav-cta,
button.primary, .glide-nav__cta {
  background: var(--accent-fill) !important;
  border-color: var(--accent-fill) !important;
  color: var(--accent-ink) !important;
}
.btn-primary:hover, .button.primary:hover, .primary-action:hover, .nav-cta:hover,
button.primary:hover {
  background: var(--accent-hi) !important;
  border-color: var(--accent-hi) !important;
  color: var(--accent-ink) !important;
}
.glide-nav__cta:hover {
  background: var(--accent-hi) !important;
  border-color: var(--accent-hi) !important;
  color: var(--accent-ink) !important;
  transform: none !important;
}
.btn-ghost, .btn-secondary, .button.secondary, .secondary-action, button.secondary {
  background: var(--surface-2) !important;
  border-color: var(--border-2) !important;
  color: var(--fg) !important;
}
.btn-ghost:hover, .btn-secondary:hover, .button.secondary:hover, .secondary-action:hover, button.secondary:hover {
  background: var(--surface-3) !important;
  border-color: var(--border-3) !important;
  color: var(--fg) !important;
}
.btn-icon { width: 38px; padding: 0; }
button:disabled, .btn:disabled { opacity: .46; cursor: not-allowed; }

/* Forms. */
input, select, textarea, .compact-select {
  max-width: 100%;
  border: 1px solid var(--border-2) !important;
  border-radius: var(--r-sm) !important;
  background: var(--field-sunk) !important;
  color: var(--fg) !important;
  box-shadow: none !important;
}
input, select, .compact-select { min-height: 38px; }
input, textarea { padding: 9px 12px; }
select { padding-inline: 12px 34px; }
input::placeholder, textarea::placeholder { color: var(--muted); opacity: .82; }
input:hover, select:hover, textarea:hover { border-color: var(--border-3) !important; }
input:focus, select:focus, textarea:focus { border-color: var(--accent) !important; outline: 1px solid var(--accent) !important; outline-offset: 0; }

/* Composite fields: the wrapper is the control, and the input inside it is not.
   Four places wrap a bare input in a padded, bordered, backgrounded box - the
   status catalogue's model search, admin's customer and ledger searches, the
   portal's top-up amount - and each of those wrappers draws its own border and
   its own focus state on `:focus-within`. The block above then drew a *second*
   box inside the first: `border: 1px solid var(--border-2) !important` plus a
   `--field-sunk` background plus a 38px min-height and 9px/12px of padding, on
   an element already inset inside its wrapper's padding. So every one of those
   fields rendered as a small rectangle floating inside a larger one, and the
   two state rules directly above lit that inner rectangle up on hover
   (`--border-3`) and on focus (accent border plus a 1px accent outline) while
   the wrapper around it lit up separately. A user reported it on 2026-08-28 as
   "the hover effect + the input box is smaller than the box around it".

   The inner element is therefore stripped of every box of its own, in both the
   resting and the interactive states. Naming the states in a second selector
   list raises it to (0,2,1) against `input:hover`/`input:focus` at (0,1,1), so
   this holds by specificity rather than by source order - it does not matter
   which sheet the wrapper's own rules live in. A wrapper added later has to be
   named in these three lists; `test/stylesheetIntegrity.test.js` fails until it
   is, and `test/siteAlignment.test.js` forbids parking a speculative hook here
   for one that does not exist yet. */
:is(.status-model-search, .finance-search, .customer-search, .topup-amount-field) :is(input, select, textarea),
:is(.status-model-search, .finance-search, .customer-search, .topup-amount-field) :is(input, select, textarea):is(:hover, :focus, :focus-visible) {
  min-height: 0;
  padding: 0;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  outline: none !important;
  box-shadow: none !important;
}
/* The wrappers all draw their ring with `box-shadow`, which forced-colors mode
   erases, and the rule above has just removed the outline that would have
   survived it. Give the wrapper one back, flush to its own border. */
@media (forced-colors: active) {
  :is(.status-model-search, .finance-search, .customer-search, .topup-amount-field):focus-within {
    outline: 2px solid Highlight;
    outline-offset: -1px;
  }
}
label { color: var(--body); font-size: 13px; font-weight: 500; }

/* Flat plates and racks. */
.card, .panel, .topup-panel, .model-card, .legal-panel,
.info-page-card, .stat-card, .table-wrap,
.activity-modal, .auth-card,
.legal-summary, .finance-kpi, .finance-balance-board {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--r) !important;
  box-shadow: none !important;
}
.card::before, .panel::before, .model-card::before {
  background: none !important;
  box-shadow: none !important;
}
.panel-header {
  padding: 18px 20px;
  border-bottom: 1px solid var(--border) !important;
}
.panel-header h2 { margin: 0; font-size: 16px; line-height: 1.3; }
.chip, .badge, .status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 24px;
  padding: 3px 8px;
  border: 1px solid var(--border-2) !important;
  border-radius: var(--r-sm) !important;
  background: var(--surface-2) !important;
  color: var(--body) !important;
  font-size: 11px;
  line-height: 1.2;
}
.live, .online, .success, .positive { color: var(--good) !important; }
.warning, .slow, .degraded { color: var(--warn) !important; }
.error, .danger, .offline, .down, .negative { color: var(--bad) !important; }
.status-tile-value { color: var(--accent) !important; }

/* Tables and data lists. */
.table-wrap, .finance-table-wrap { max-width: 100%; overflow: auto; border-radius: var(--r); }
table { width: 100%; border-collapse: collapse; border-spacing: 0; }
thead, th { background: var(--surface-2) !important; }
th {
  height: 42px;
  padding: 10px 14px !important;
  border-bottom: 1px solid var(--border-2) !important;
  color: var(--muted) !important;
  font: 500 10px/1.3 var(--font-mono) !important;
  letter-spacing: .08em !important;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}
td {
  padding: 13px 14px !important;
  border-bottom: 1px solid var(--border) !important;
  background: var(--surface) !important;
  color: var(--body) !important;
  vertical-align: middle;
}
tbody tr:last-child td { border-bottom: 0 !important; }
tbody tr:hover td { background: var(--surface-3) !important; }

/* Public page frame. */
.doc-page, .page {
  width: min(100%, calc(var(--maxw) + 48px));
  max-width: none;
  margin-inline: auto;
  padding: clamp(56px, 7vw, 88px) 24px clamp(80px, 10vw, 128px);
}
.page-hero, .page-header { max-width: 820px; }
.page-hero { padding: 0 0 clamp(48px, 7vw, 76px); border-bottom: 1px solid var(--border); }
.eyebrow, .admin-eyebrow, .finance-section-label {
  color: var(--accent) !important;
  font: 500 10px/1.4 var(--font-mono) !important;
  letter-spacing: .1em !important;
  text-transform: uppercase;
}
/* ---------- display tier: the page heads, off the landing page ----------
   An editorial serif carried this tier for one day (2026-08-27 to 2026-08-28) and
   is gone with `--font-serif`: it made these pages read as a different product
   from the console they hand off to. What a single-family hierarchy needs is a
   size and a tracking, and that is all this block states now. The family and the
   weight come from the `h1..h6` rule above (Geist, 600, both `!important`), so
   restating them here would be noise - and the tracking has to be shouted for the
   same reason, because that rule pins `letter-spacing: 0 !important`.

   -.038em at 42-76px continues the console's own ramp upward: it tracks -.022em at
   17px and -.032em at 24-30px, so display size wants the counters pulled in
   further. That is the opposite of what the serif wanted (-.015em, tracking let
   out), which is why every number in this block moved rather than just the family.
   `line-height` returns to 1 from the 1.02 a serif's extenders needed.

   Un-shouting the `h1..h6` rule means auditing every heading on thirteen pages
   and is its own pass - recorded, not attempted here. */
.page-hero h1, .page-header h1 {
  margin: 14px 0 18px;
  font-size: clamp(42px, 7vw, 76px) !important;
  line-height: 1 !important;
  letter-spacing: -.038em !important;
}

/* The other display headings this sheet can reach: 404's headline and the portal
   gate's marketing headline sit in the same 44-78px band as the page heads above,
   so they take the same tracking. About's card heads (28px flat) and contact's two
   panel heads (clamp(28px, 3vw, 42px) and a flat 25px) sit a tier down, where
   -.038em starts closing the counters at the floor - so they track a step wider.
   Sizes and line-heights stay with the page sheets that own them; only the
   tracking is stated here, and only
   because the `h1..h6` rule above pins it to 0 with `!important` - which is also
   why `.glide-contact__prepare h2` is named: without it, one of a pair of twin
   panel heads on /contact tracked at -.03em and the other at 0. The portal gate's
   sign-in card head (28px, /portal/login.html) is named for the same reason:
   measured at 0 while the marketing headline beside it tracked -.038em, on the one
   page whose only job is handing a customer to the console. login.css states
   `letter-spacing` on it no longer - the value it stated was inert against this
   rule, and its 560px override drops the size to 24px, which this tier still
   suits. `.legal-panel h2` (25px, /terms and /privacy, seventeen of them per page)
   is the third: site-pages.css:152 has asked for -.03em on it all along and lost
   to this sheet, so naming it here does not pick a new number, it makes the number
   the sheet already states the one the browser draws. */
.not-found-copy h1,
.login-context h1 {
  letter-spacing: -.038em !important;
}
.info-page-card h2,
.glide-contact__discord h2,
.glide-contact__prepare h2,
.auth-card-heading h2,
.legal-panel h2 {
  letter-spacing: -.03em !important;
}
.page-hero > p:last-child, .page-lede { max-width: 720px; margin: 0; color: var(--body) !important; font-size: clamp(16px, 2vw, 18px); line-height: 1.7; }
.info-page-layout {
  gap: 16px !important;
  border: 0 !important;
  background: transparent !important;
}
.legal-layout { gap: clamp(32px, 6vw, 84px); }
.legal-panel a { color: var(--accent) !important; }
pre, code, .code-block {
  border-color: var(--border) !important;
  background: var(--field-sunk) !important;
  color: var(--ink-body) !important;
}

/* Product consoles. */
.admin-shell { background: var(--bg) !important; }
.portal-sidebar, .admin-sidebar {
  background: var(--bg-deep) !important;
  border-color: var(--border) !important;
  box-shadow: none !important;
}
.main-content, .admin-workspace { min-width: 0; background: var(--bg) !important; }
.admin-workspace .top-bar { padding: 24px clamp(20px, 3vw, 36px); }
.admin-workspace .grid, .main-content > main { padding: clamp(20px, 3vw, 36px) !important; }
.stat-row { gap: 12px !important; }
.stat-card, .finance-kpi { min-width: 0; padding: 18px !important; }
.stat-label, .finance-kpi-label { color: var(--muted) !important; font: 500 10px/1.4 var(--font-mono) !important; letter-spacing: .08em !important; text-transform: uppercase; }
.stat-value, .finance-kpi-value { margin-top: 10px; color: var(--fg) !important; font-size: clamp(22px, 3vw, 32px) !important; line-height: 1 !important; }
.chart-container { min-height: 260px; padding: 16px 20px 20px; }
.finance-overview { gap: 16px !important; }
.finance-kpi-board { gap: 1px; overflow: hidden; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--border); }
.finance-kpi-board .finance-kpi { border: 0 !important; border-radius: 0 !important; }
.finance-balance-board { padding: 16px 18px !important; }
.finance-control-panel, .finance-ledger-panel, .finance-discounts-panel { overflow: hidden; }
.finance-coverage, .finance-timeline, .finance-ledger-toolbar { margin: 0 20px 20px !important; }

/* Footer is one complete carbon rack on every page. */
.site-footer, body > footer {
  width: 100%;
  max-width: none !important;
  margin: 0 !important;
  border-top: 1px solid var(--ink-border) !important;
  background: var(--ink-bg) !important;
  color: var(--ink-body) !important;
  box-shadow: none !important;
}
.glide-site-footer {
  display: block !important;
  min-height: 0 !important;
  padding: 0 !important;
  align-items: initial !important;
  justify-content: initial !important;
  gap: 0 !important;
}
.glide-site-footer__inner {
  width: min(100%, 1248px) !important;
  margin: 0 auto !important;
  padding: 56px 24px 48px !important;
  display: grid !important;
  grid-template-columns: minmax(230px, 1.2fr) minmax(0, 2fr) !important;
  gap: clamp(40px, 8vw, 96px) !important;
}
.glide-site-footer__nav {
  width: 100% !important;
  min-width: 0 !important;
  grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
}
.glide-site-footer__bottom {
  width: min(100%, 1248px) !important;
  margin: 0 auto !important;
}

/* Theme switches may change density, never brand color. */
[data-theme='light'] {
  color-scheme: dark;
  --background: var(--bg) !important;
  --text: var(--fg) !important;
  /* No --surface override here. It used to re-declare a hard-coded copy of the
     old pale value, so flipping the theme silently desaturated every surface
     back to the neutral grey the :root ramp deliberately moved away from.
     Inheriting :root is the whole intent - "never brand color". */
}

@media (max-width: 1024px) {
  .nav-inner { padding-inline: 20px; }
  .admin-workspace .grid, .main-content > main { padding: 24px !important; }
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}

@media (max-width: 760px) {
  html { scroll-padding-top: 72px; }
  .site-nav { min-height: 64px; height: 64px; }
  .doc-page, .page { padding: 48px 18px 80px; }
  .page-hero h1, .page-header h1 { font-size: clamp(38px, 12vw, 54px) !important; }
  .page-hero { padding-bottom: 44px; }
  .info-page-layout { grid-template-columns: 1fr !important; gap: 12px !important; }
  .legal-layout { grid-template-columns: 1fr; gap: 28px; }
  .legal-summary { position: static; }
  .portal-sidebar, .admin-sidebar { background: var(--bg-deep) !important; }
  .admin-workspace .top-bar { padding: 20px 18px; }
  .admin-workspace .grid, .main-content > main { padding: 18px !important; }
  .stat-row { grid-template-columns: 1fr !important; }
  .panel-header { align-items: flex-start !important; padding: 16px; }
  .panel-header, .panel-actions { gap: 12px; flex-wrap: wrap; }
  .chart-container { min-height: 230px; padding: 12px 14px 16px; }
  .finance-overview { grid-template-columns: 1fr !important; }
  .finance-kpi-board { grid-template-columns: 1fr 1fr !important; }
  .finance-coverage, .finance-timeline, .finance-ledger-toolbar { margin: 0 14px 16px !important; }
  .table-wrap, .finance-table-wrap { border-radius: 0; }
}

@media (max-width: 430px) {
  .doc-page, .page { padding-inline: 16px; }
  .admin-workspace .grid, .main-content > main { padding: 14px !important; }
  .finance-kpi-board { grid-template-columns: 1fr !important; }
  .btn, .button, .primary-action, .secondary-action, .nav-cta { max-width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

/* Complete 260:64 brand artwork. Never squeeze it into the square mark slot. */
.logo-mark img.full-brand-lockup {
  width: 130px !important;
  height: 32px !important;
  min-width: 130px !important;
  max-width: 130px !important;
  min-height: 32px !important;
  max-height: 32px !important;
  flex: 0 0 130px !important;
  object-fit: contain !important;
  object-position: left center !important;
}

/* The documentation workspace block that used to sit here - 52 rules plus three
   media blocks, 197 lines - was removed on 2026-08-27. docs.html links
   /docs.css and /polish.css and nothing else, so not one of those rules had a
   page to apply to; every class token in them (.docs-shell, .docs-grid,
   .docs-nav, .docs-toc, .docs-content, .docs-hero, .doc-section*, .doc-body,
   .compat-card, .code-card, .integration-card, .os-tab*, .callout, .docs-search*,
   .doc-page-nav, .route, .status, .endpoint-method) was checked token-exact
   against the thirteen pages that do link this sheet and against every script
   under public/ that builds markup, and none of them appears. docs.css owns the
   docs page and always did.

   This mattered beyond the dead bytes: `.doc-section-head h2` here sized a
   display-tier heading at `clamp(24px, 3vw, 30px) !important`, four pixels under
   the serif floor, and `.docs-hero h1` still asked for `600 … var(--font-display)`.
   Both were invisible in review precisely because they were unreachable, and both
   would have started rendering the moment anyone added brand-system.css to
   docs.html. The `!important`s docs.css carries on those same two selectors were
   written to beat these rules and have been beating nothing. */

/* Second cut, same day and same method: 5 whole rules and 59 selector parts that
   named a class no markup in this repo carries. A class token counted as live only
   where markup can put it on an element - a class/id attribute in an HTML file, or
   a string literal in a script that builds markup - so no stylesheet vouched for
   another, and a token that survives here is one an element can really have.
   Removed: .glide-brand-word and .glide-brand-lockup (the lockup is an <img>
   now, and the text span it styled is gone from every page), .site-footer-inner /
   .global-footer-inner / .footer-inner and .global-footer (shared-footer.js
   replaces the footer's innerHTML wholesale and sets className to
   'glide-site-footer', so the inner wrappers this sheet was centring never exist),
   .docs-index / .doc-panel / .doc-code-grid / .doc-kicker / .docs-layout (docs.css
   owns that page, as above), .contact-layout / .contact-card (contact.html has been
   .glide-contact__* since the rebuild), .content-card / .section-card / .hero-card /
   .balance-card / .pricing-card / .modal-content / .card-header / .section-header /
   .data-table-wrap / .app-shell / .topbar / .admin-topbar / .content-area /
   .sidebar-nav / .search-input / .search-box / .submit-btn / .action-button /
   .page-title / .admin-title / .balance-amount / .muted / .healthy / .status-live
   (pre-rebuild console and page vocabularies; the consoles use .panel,
   .admin-workspace, .main-content, .top-bar, .portal-sidebar, .admin-sidebar,
   .btn, .table-wrap and the .finance-* family, all of which are live and stay).

   Every one of these was a cosmetic override in a sheet that only restyles what
   other sheets build, so nothing rendered differently before and after - which is
   exactly why they accumulated. The scan that produced the list is not kept: it is
   reproducible from this note, and a scanner left on disk rots against the markup
   it audits. One bug in it is worth recording, though, because it hid seven of
   these parts through two passes: it skipped any selector containing `>`, so every
   `.main-content > .topbar`-shaped rule went unaudited. */

@media (max-width: 980px) {
  .glide-site-footer__inner { grid-template-columns: 1fr !important; }
  .glide-site-footer__nav { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
}
@media (max-width: 600px) {
  .glide-site-footer__inner { padding: 44px 18px 36px !important; }
  .glide-site-footer__nav { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (max-width: 360px) {
  .glide-site-footer__nav { grid-template-columns: 1fr !important; }
}
