/* =====================================================================
   cian.build — IBM Carbon Design System, themed to the CIAN brand.
   =====================================================================

   WHAT THIS IS, and the two decisions that shape all of it.

   The site is built on Carbon's DESIGN LANGUAGE — the 2x Grid, the type
   scale, the spacing scale, the motion curves, the square-cornered surface
   treatment, the interaction and focus model, and the component anatomy of
   Carbon's tile / notification / tag / button / data-table. That is what
   makes an enterprise layout read as one, and it is what "implement Carbon"
   means here.

   DECISION 1 — HAND-AUTHORED, NOT `@carbon/styles`, AND NOT A CDN.
   The Worker's Content-Security-Policy is `default-src 'self'` with
   `font-src 'self'` and `script-src 'self'` and no 'unsafe-inline' (see
   worker/index.ts; a test asserts it). So Carbon cannot be pulled from a
   CDN — it would simply be blocked. The alternative, `@carbon/styles`, is
   Sass, and this repo's build is deliberately zero-dependency
   ("a build toolchain would be more moving parts than the thing it
   builds", scripts/build.mjs). Vendoring a Sass pipeline to style eight
   static pages is the wrong trade. So Carbon's published token VALUES are
   implemented directly as custom properties below, named after their
   Carbon counterparts so the lineage is checkable rather than asserted.

   DECISION 2 — CARBON'S STRUCTURE, CIAN'S BRAND.
   Carbon's own theme is IBM Blue 60 on IBM Gray 100 in IBM Plex. Adopting
   that wholesale would make a Shannon Cyber product look like an IBM one,
   which is a trademark problem as much as a brand one. Carbon is built to
   be re-themed — `$button-primary`, `$link-primary` and the rest are
   tokens precisely so a non-IBM product can point them somewhere else — so
   every Carbon token here resolves to a CIAN brand value from the SHA-814
   palette. Typography stays Fira Sans / JetBrains Mono: both are already
   self-hosted under the CSP, and the Machine/UI split they encode is a
   comprehension aid carried over from the product (.claude/skills/
   cian-brand). IBM Plex would mean committing new binaries to gain a
   typeface whose main property here is looking like IBM.

   WHAT CARBON CHANGED about this site's own prior conventions, recorded
   because the brand skill said the opposite and has been updated to match:
     * Buttons are now FILLED for the primary action (Carbon
       `$button-primary`). The old rule was "never colour-filled". Carbon's
       button hierarchy is load-bearing — primary/secondary/tertiary/ghost
       is how Carbon expresses action rank — and an unfilled primary
       collapses that hierarchy. Contrast is measured, not assumed:
       scripts/check-contrast.mjs puts white on Rust at 4.81:1 (dark) and
       6.76:1 (light), both over the 4.5:1 floor.
     * Corners are square. `--radius` is gone; Carbon's surfaces are
       rectangular and the 6px radius was the single biggest visual tell
       that this was not an enterprise system.

   Contrast: every token pair painted as text is checked by
   `npm run check:contrast` — 38 pairs, all at or above their floor. Add a
   pair there when you add one here.
   ===================================================================== */

/* --- Typefaces. Self-hosted, OFL-1.1; never a font CDN (font-src 'self'). */
@font-face {
  font-family: "Fira Sans";
  src: url("/assets/fonts/fira-sans-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fira Sans";
  src: url("/assets/fonts/fira-sans-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fira Sans";
  src: url("/assets/fonts/fira-sans-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/jetbrains-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* =====================================================================
   TOKENS
   ===================================================================== */

:root {
  /* Dark is the default and does NOT follow the OS setting — CIAN is
     night-first (UI Guidelines: "Night is the default, not a theme"). Light
     is an explicit opt-in via the header toggle, which theme.js sets as
     `data-theme="light"` on <html> before first paint. In Carbon's terms
     the default is the Gray 100 theme and the opt-in is the White theme. */
  color-scheme: dark;

  /* --- Carbon spacing scale (@carbon/layout). Exact values. ---------- */
  --spacing-01: 0.125rem; /*  2px */
  --spacing-02: 0.25rem;  /*  4px */
  --spacing-03: 0.5rem;   /*  8px */
  --spacing-04: 0.75rem;  /* 12px */
  --spacing-05: 1rem;     /* 16px */
  --spacing-06: 1.5rem;   /* 24px */
  --spacing-07: 2rem;     /* 32px */
  --spacing-08: 2.5rem;   /* 40px */
  --spacing-09: 3rem;     /* 48px */
  --spacing-10: 4rem;     /* 64px */
  --spacing-11: 5rem;     /* 80px */
  --spacing-12: 6rem;     /* 96px */
  --spacing-13: 10rem;    /* 160px */

  /* --- Carbon motion. Durations and the two productive easing curves.
     Carbon's rule: entrance is fast in, exit is fast out, and nothing on a
     page like this needs longer than moderate-02. */
  --duration-fast-01: 70ms;
  --duration-fast-02: 110ms;
  --duration-moderate-01: 150ms;
  --duration-moderate-02: 240ms;
  --ease-standard: cubic-bezier(0.2, 0, 0.38, 0.9);
  --ease-entrance: cubic-bezier(0, 0, 0.38, 0.9);
  --ease-exit: cubic-bezier(0.2, 0, 1, 0.9);

  /* --- Carbon 2x Grid. 16 columns at lg and up, 32px gutters, 16px
     margins (24px at max). --grid-max is Carbon's `max` breakpoint. */
  --grid-columns: 16;
  --grid-gutter: 2rem;      /* 32px */
  --grid-margin: 1rem;      /* 16px */
  --grid-max: 99rem;        /* 1584px — Carbon `max` */
  /* Content ceiling. Raised from 82rem (1312px) to 96rem (1536px): 82rem
     left 304px of dead gutter each side at 1920px, and Carbon's own `max`
     breakpoint is 1584px, so 1536px sits just inside the grid's designed
     maximum rather than inventing a wider one. */
  --grid-content: 96rem;    /* 1536px */

  /* --- Carbon UI Shell ---------------------------------------------- */
  --shell-header-height: 3rem; /* 48px, Carbon's header is exactly this */

  /* --- CIAN brand palette (SHA-814). The identity, unchanged by theme. */
  --brand-rust: #c94436;
  --brand-rust-deep: #a8301f;
  --brand-aqua: #4fa89c;
  --brand-base: #0a1418;

  /* --- Carbon layer model, CIAN "Evening" surfaces.
     Carbon names surfaces $background, $layer-01, $layer-02: a stack you
     step UP as you nest. The CIAN tokens map one-to-one, and the old
     --bg/--bg-subtle/--bg-raised names are kept as aliases so nothing that
     referenced them breaks. */
  --background: #060e11;
  --layer-01: #0a1418;
  --layer-02: #0f1d22;
  --layer-hover: #14262c;
  --bg: var(--background);
  --bg-subtle: var(--layer-01);
  --bg-raised: var(--layer-02);

  /* Carbon $border-subtle / $border-strong. */
  --border-subtle: #1a2f36;
  --border-strong: #26454e;
  --border: var(--border-subtle);

  /* Carbon $text-primary / $text-secondary / $text-on-color. */
  --text-primary: #ccd8db;
  --text-secondary: #8ba0a6;
  --text-on-color: #ffffff;
  --text: var(--text-primary);
  --text-muted: var(--text-secondary);

  /* Carbon $link-primary / $focus. Rust lightened to clear 4.5:1 as
     link-sized text on the dark ground (canonical Rust is ~3.9:1 there —
     right for the mark, short for small text). */
  --link-primary: #d96a52;
  --accent: var(--link-primary);
  --focus: #d96a52;
  --accent-subtle: #241310;
  --accent-text: #04090b;

  /* Carbon $button-primary / $button-primary-hover / $button-primary-active.
     Canonical Rust, because a filled button is a GRAPHIC carrying a label,
     and the label's contrast on it is what matters (4.81:1, measured). */
  --button-primary: var(--brand-rust);
  --button-primary-hover: #b3392c;
  --button-primary-active: #9c3025;

  /* Carbon $support-error / $support-success / $support-warning. Reserved:
     these mean something in CIAN's state language and are never decorative.
     BLOCKED / HEALTHY / AWAITING-a-human, respectively. */
  --support-error: #d6607a;
  --support-success: #3cc2a8;
  --support-warning: #c9871f;
  --danger: var(--support-error);
  --success: var(--support-success);
  --warn: var(--support-warning);
  --danger-subtle: #2a161a;
  --success-subtle: #0d211c;
  --warn-subtle: #241c08;

  /* Carbon is square. Kept as a token at 0 rather than deleted, because
     component rules still reference it and a single override is how you
     would soften the system later if that were ever wanted. */
  --radius: 0;

  --wrap: var(--grid-content);
  --measure: 42rem;
}

:root[data-theme="light"] {
  /* Carbon's White theme, in CIAN's cool-teal hue family. */
  color-scheme: light;

  --background: #f6f9fa;
  --layer-01: #eef3f4;
  --layer-02: #ffffff;
  --layer-hover: #e2eaec;

  --border-subtle: #d3dde0;
  --border-strong: #a9bcc1;

  --text-primary: #10191c;
  --text-secondary: #4d6167;
  --text-on-color: #ffffff;

  /* Rust Deep — itself a brand token (the mark's ring) — because canonical
     Rust sits at ~4.35:1 on this near-white ground, just under AA. */
  --link-primary: #a8301f;
  --focus: #a8301f;
  --accent-subtle: #f7e6e2;
  --accent-text: #ffffff;

  --button-primary: var(--brand-rust-deep);
  --button-primary-hover: #8f2819;
  --button-primary-active: #7a2115;

  --support-error: #8c2b3c;
  --support-success: #0a6c5c;
  --support-warning: #8f5c11;
  --danger-subtle: #fbe9ec;
  --success-subtle: #e3f3ef;
  --warn-subtle: #fbf1e0;
}

/* =====================================================================
   BASE + CARBON TYPE SCALE

   Carbon's scale is two families: PRODUCTIVE (dense, for UI and reading)
   and EXPRESSIVE (fluid, for marketing moments). Both are used here, which
   is exactly Carbon's guidance for a product marketing site: expressive
   for the hero and section openers, productive for everything that is
   actually read. Values are Carbon's own px/line-height/letter-spacing.
   ===================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  /* A long unbroken token (a URL, an identifier in mono) must wrap rather
     than push the page sideways on a 320px screen. */
  overflow-wrap: break-word;
  /* Carbon body-02: 16px / 24px / 0 tracking. */
  font-family: "Fira Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 1rem;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--text-primary);
  background: var(--background);
  /* Carbon's shell is fixed; the body is offset by its height. */
  padding-top: var(--shell-header-height);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Carbon heading roles. Weight 600 tops out the shipped family (no 700+),
   and Carbon's larger headings are LIGHTER, not heavier — heading-06/07 are
   300 in Carbon. With only 400–600 available, the large sizes use 400 so
   they still read as Carbon's "big and light" rather than a bold stack. */
h1,
h2,
h3,
h4 {
  margin: 0 0 var(--spacing-05);
  font-weight: 600;
  letter-spacing: 0;
  text-wrap: balance;
}

/* fluid-heading-05 → expressive, 32px climbing to 60px. */
h1 {
  font-size: clamp(2rem, 1.25rem + 3.2vw, 3.75rem);
  line-height: 1.15;
  font-weight: 400;
  letter-spacing: -0.02em;
}

/* fluid-heading-04 → 28px climbing to 40px. */
h2 {
  font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem);
  line-height: 1.25;
  font-weight: 400;
  letter-spacing: -0.01em;
}

/* heading-03: 20px / 28px. */
h3 {
  font-size: 1.25rem;
  line-height: 1.4;
  font-weight: 600;
}

/* heading-02: 16px / 24px. */
h4 {
  font-size: 1rem;
  line-height: 1.5;
  font-weight: 600;
}

p {
  margin: 0 0 var(--spacing-05);
  max-width: var(--measure);
}

/* Carbon $link-primary: underlined by default. Carbon underlines links in
   body copy — colour alone is not a link affordance. */
a {
  color: var(--link-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: color var(--duration-fast-02) var(--ease-standard);
}

a:hover {
  color: var(--text-primary);
  text-decoration-thickness: 2px;
}

/* Carbon's focus indicator: a 2px SOLID border in $focus, not a soft glow.
   Square, high contrast, and never removed without a replacement. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

::selection {
  background: var(--brand-aqua);
  color: #04090b;
}

/* Carbon code-02: 14px / 20px / 0.32px, mono. Machine text only — literal
   things the system says. Never body copy, never headings. */
code {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", monospace;
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.32px;
  background: var(--layer-01);
  border: 1px solid var(--border-subtle);
  padding: 0.1em 0.35em;
}

strong {
  font-weight: 600;
  color: var(--text-primary);
}

ul,
ol,
dl {
  max-width: var(--measure);
}

li + li {
  margin-top: var(--spacing-03);
}

img,
svg {
  max-width: 100%;
}

hr {
  border: 0;
  border-top: 1px solid var(--border-subtle);
  margin: var(--spacing-09) 0;
}

/* Carbon label-01: 12px / 16px / 0.32px. */
.small {
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
}

.muted {
  color: var(--text-secondary);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =====================================================================
   LAYOUT — Carbon 2x Grid
   ===================================================================== */

.wrap {
  width: 100%;
  max-width: var(--grid-content);
  margin-inline: auto;
  /* Carbon grid margin. At least 16px of gutter at every width, which is
     also what keeps the page off the edge of a phone. */
  padding-inline: var(--grid-margin);
}

@media (min-width: 99rem) {
  .wrap {
    /* Carbon's `max` breakpoint widens the margin to 24px. */
    padding-inline: var(--spacing-06);
  }
}

/* A Carbon grid row: 16 equal columns with 32px gutters. Children opt into
   a span with .col-N. Collapses to one column below Carbon's `md`. */
.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  gap: var(--grid-gutter);
}

.col-4 { grid-column: span 4; }
.col-5 { grid-column: span 5; }
.col-6 { grid-column: span 6; }
.col-7 { grid-column: span 7; }
.col-8 { grid-column: span 8; }
.col-10 { grid-column: span 10; }
.col-12 { grid-column: span 12; }
.col-16 { grid-column: span 16; }

/* Collapse at Carbon `lg` (1056px), NOT at `md`.
   
   This is the faithful Carbon reading rather than a judgement call: Carbon's
   grid is 16 columns at lg and up, 8 at md, 4 at sm. A `.col-8` means "half"
   only at lg — at md the grid is 8 wide, so 8 columns IS full width, and at
   sm it is double. Since these spans are declared once rather than per
   breakpoint, full width below lg is what they actually mean.
   
   It is also the better result on a tablet: two prose columns at 834px are
   ~385px each, which is a cramped measure for body copy. Stacking them gives
   one comfortable column instead of two poor ones. */
@media (max-width: 65.999rem) {
  .grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-08);
  }
  .col-4,
  .col-5,
  .col-6,
  .col-7,
  .col-8,
  .col-10,
  .col-12,
  .col-16 {
    grid-column: 1 / -1;
  }
}

/* Reading column for prose pages (the build wraps non-fullWidth pages in
   `.wrap.page`). Carbon's own docs sites cap measure the same way. */
/* The default prose page keeps a CENTRED reading column, because the long
   legal documents are numbered clauses read top to bottom and a 1536px
   measure would be unreadable. Widened from 54rem to 64rem, which is as far
   as a single column of 16px text should go. */
.page {
  padding-block: var(--spacing-10) var(--spacing-12);
  max-width: 64rem;
}

/* =====================================================================
   FULL-WIDTH DOCUMENT PAGES  (body class `doc-wide`)

   Features and Methodology were capped at 54rem, which left 288px of dead
   gutter each side at 1440px and 528px at 1920px — 60% and 45% of the
   viewport used. They now run the full content width.

   THE PART THAT IS NOT JUST REMOVING THE CAP. You cannot fill 1536px with
   one column of prose and keep it readable — that is ~200 characters a
   line. So the width is used by LAYOUT, in Carbon's own documentation
   pattern: the section heading sits in a narrow left column and its body in
   a wide right one. The prose column stays at a readable measure, the
   leftover space is occupied by the heading rather than by margin, and the
   wide components (tile grids, the pipeline) get the full body column
   instead of being squeezed into 864px.

   Collapses to one column below Carbon `lg`, where there is no width to
   split.
   ===================================================================== */

/* `.wrap` and `.page` are the SAME element (the build emits
   `<div class="wrap page">`), so this restores `.wrap`'s own ceiling rather
   than removing the cap. `max-width: none` was measured running the content
   to 1888px at a 1920px viewport — past Carbon's 1584px `max` breakpoint,
   which is not "using the width", it is having none. */
.doc-wide .page {
  max-width: var(--grid-content);
}

/* The page header uses the same split, so the h1 sits in the left rail with
   every section heading beneath it and the lede occupies the body column.
   Without this the top of the page was a title and a lede at the far left
   with the whole right half empty, which read as a layout that had failed
   rather than one that had a wide page. */
.doc-intro {
  display: grid;
  grid-template-columns: 4fr 12fr;
  gap: var(--grid-gutter);
  align-items: start;
}

.doc-wide .page > h1 {
  /* Sized for the 4-column rail. The fluid h1 clamp tops out at 60px, which
     wraps "Acceptable Use Policy" into five lines at this width. */
  font-size: clamp(1.75rem, 1.3rem + 1.4vw, 2.5rem);
  line-height: 1.15;
  margin-bottom: var(--spacing-05);
}

.doc-intro .doc-body > :first-child {
  margin-block-start: 0;
}

@media (max-width: 65.999rem) {
  .doc-intro {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-05);
  }
}

.doc-section {
  display: grid;
  /* 4 and 12 of Carbon's 16 columns. */
  grid-template-columns: 4fr 12fr;
  gap: var(--grid-gutter);
  align-items: start;
  margin-block-start: var(--spacing-10);
}

.doc-section:first-of-type {
  margin-block-start: var(--spacing-09);
}

.doc-head h2 {
  /* Already positioned by the grid; the generic `.page > h2` top margin
     would double the section rhythm. */
  margin-block: 0 var(--spacing-04);
  /* A heading in a 4-column well needs a tighter size than a full-width one
     or it wraps to four or five lines. heading-04 rather than fluid. */
  font-size: clamp(1.375rem, 1.1rem + 0.9vw, 1.75rem);
  line-height: 1.25;
  /* Optically aligns the heading's cap-height with the body's first line. */
  padding-block-start: var(--spacing-01);
}

.doc-head {
  position: sticky;
  /* Under the fixed 48px shell, with a little air. */
  top: calc(var(--shell-header-height) + var(--spacing-06));
}

.doc-body > :first-child {
  margin-block-start: 0;
}

.doc-body > :last-child {
  margin-block-end: 0;
}

/* Prose inside the body column: a readable measure, not the column's full
   width. `ch` rather than `rem` because the limit is about characters per
   line, which is what the unit means. */
/* 72ch, measured at ~700px for this face. The ideal measure is 45-75
   characters; 72 sits at the top of it, which is the right trade here
   because a narrower column would put the reclaimed width straight back
   into margin. */
.doc-body p,
.doc-body ul:not(.card-grid):not(.pipeline):not(.status-list),
.doc-body ol:not(.pipeline),
.doc-body dl {
  max-width: 72ch;
}

/* Components take the whole body column — this is where the reclaimed width
   actually goes. */
.doc-body .card-grid,
.doc-body .pipeline,
.doc-body .status-list,
.doc-body .fact-list,
.doc-body .notice {
  max-width: none;
}

@media (max-width: 65.999rem) {
  .doc-section {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-05);
    margin-block-start: var(--spacing-09);
  }
  .doc-head {
    position: static;
    top: auto;
  }
}

.page > h1 {
  margin-bottom: var(--spacing-06);
}

.page > h2 {
  margin-top: var(--spacing-10);
}

.page > h3 {
  margin-top: var(--spacing-07);
}

/* =====================================================================
   UI SHELL — Carbon's header

   Carbon's header is 48px, full-bleed, sits on $layer-01 with a
   $border-subtle underline, and holds the product name at the left. It is
   fixed, which is why <body> carries matching top padding.
   ===================================================================== */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--spacing-04) var(--spacing-05);
  background: var(--button-primary);
  color: var(--text-on-color);
  text-decoration: none;
  font-weight: 600;
}

.skip-link:focus {
  left: var(--spacing-05);
  top: var(--spacing-03);
}

.site-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 50;
  height: var(--shell-header-height);
  background: var(--layer-01);
  border-bottom: 1px solid var(--border-subtle);
}

/* The shell header is full-bleed: Carbon's header content starts at the
   edge, not inside a centred container, so the brand sits in the corner. */
.header-inner {
  display: flex;
  align-items: stretch;
  gap: 0;
  height: 100%;
  max-width: none;
  padding-inline: 0;
}

/* Carbon's brand cell: 16px in from the edge, name in 600. */
.brand {
  display: flex;
  align-items: center;
  gap: var(--spacing-03);
  padding-inline: var(--spacing-05);
  color: var(--text-primary);
  text-decoration: none;
  flex: 0 0 auto;
}

.brand:hover {
  color: var(--text-primary);
  background: var(--layer-hover);
}

.brand-mark {
  display: block;
  width: 1.5rem;
  height: 1.5rem;
  flex: 0 0 auto;
}

.brand-name {
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.01em;
}

.site-nav {
  display: flex;
  align-items: stretch;
  min-width: 0;
  flex: 1 1 auto;
}

.site-nav-links {
  display: flex;
  align-items: stretch;
  overflow-x: auto;
  scrollbar-width: none;
}

.site-nav-links::-webkit-scrollbar {
  display: none;
}

/* Carbon header nav items: full-height hit target, no underline, a 3px
   $border-interactive bar on the active item. The bar is driven off
   aria-current so the visual and the announced state cannot disagree. */
.site-nav-links a {
  display: flex;
  align-items: center;
  white-space: nowrap;
  padding-inline: var(--spacing-05);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  color: var(--text-secondary);
  text-decoration: none;
  border-block-end: 3px solid transparent;
  transition: background var(--duration-fast-01) var(--ease-standard),
    color var(--duration-fast-01) var(--ease-standard);
}

.site-nav-links a:hover {
  background: var(--layer-hover);
  color: var(--text-primary);
}

.site-nav-links a[aria-current="page"] {
  color: var(--text-primary);
  border-block-end-color: var(--button-primary);
  font-weight: 600;
}

/* Carbon header action: a square 48x48 cell at the shell's right edge. */
.theme-toggle {
  flex: 0 0 auto;
  margin-inline-start: auto;
  width: var(--shell-header-height);
  height: var(--shell-header-height);
  display: grid;
  place-items: center;
  background: transparent;
  border: 0;
  border-inline-start: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: 1rem;
  cursor: pointer;
  transition: background var(--duration-fast-01) var(--ease-standard);
}

.theme-toggle:hover {
  background: var(--layer-hover);
  color: var(--text-primary);
}

.theme-toggle[hidden] {
  display: none;
}

.theme-icon {
  display: none;
  line-height: 1;
}

.theme-icon-light {
  display: block;
}

/* =====================================================================
   THE SHELL ON A PHONE

   Carbon's header is fixed and 48px, and it stays that way on a tablet. On a
   phone it cannot be: four nav items do not fit across 320px, so the header
   was a horizontal scroller with "Support" simply off-screen and no
   affordance saying so. Hiding a primary nav item behind an undiscoverable
   sideways scroll is worse than any layout cost.

   Carbon's own answer at this width is a hamburger and a slide-over side
   nav. That needs JavaScript, and the CSP forbids inline script — so it
   would mean a new script file and a nav that does not open without JS, to
   hold four links. Not worth it.

   So instead, on a phone: the nav gets its OWN full-width row and wraps, and
   the header stops being fixed. Every link is visible and every one is a
   full-height target. The header scrolls away because a wrapped two-row
   header pinned to the top would eat a fifth of a phone screen for the whole
   session. Nothing is hidden and no script is required.
   ===================================================================== */

@media (max-width: 41.999rem) {
  .site-header {
    position: static;
    height: auto;
  }

  body {
    /* Nothing is overlapping the top of the document any more. */
    padding-top: 0;
  }

  .header-inner {
    flex-wrap: wrap;
  }

  .site-nav {
    /* Its own row, below the brand and the theme toggle. */
    order: 3;
    flex: 1 1 100%;
    border-block-start: 1px solid var(--border-subtle);
  }

  .site-nav-links {
    width: 100%;
    /* Wrap rather than scroll: this is the whole point of the change. */
    flex-wrap: wrap;
    overflow-x: visible;
  }

  .site-nav-links a {
    /* Share the row evenly, and keep a 44px+ touch target. */
    flex: 1 1 auto;
    justify-content: center;
    min-height: 2.75rem;
    padding-inline: var(--spacing-04);
  }

  .brand {
    /* Leave the toggle its square at the right of the first row. */
    flex: 1 1 auto;
  }
}

.theme-toggle[data-theme-state="light"] .theme-icon-dark {
  display: block;
}

.theme-toggle[data-theme-state="light"] .theme-icon-light {
  display: none;
}

/* =====================================================================
   SECTIONS AND BANDS
   ===================================================================== */

.section {
  padding-block: var(--spacing-12);
  border-block-start: 1px solid var(--border-subtle);
}

/* Carbon alternates $background and $layer-01 to separate bands rather
   than using shadows. */
.section-alt {
  background: var(--layer-01);
}

.section-tight {
  padding-block: var(--spacing-09);
}

/* Carbon's vertical rhythm is generous by design, but spacing-12 (96px)
   between every band on a phone is most of a screen height of nothing. Step
   the bands down rather than keeping desktop rhythm on a 375px viewport. */
@media (max-width: 65.999rem) {
  .section {
    padding-block: var(--spacing-10);
  }
  .section-head {
    margin-bottom: var(--spacing-07);
  }
}

@media (max-width: 41.999rem) {
  .section {
    padding-block: var(--spacing-09);
  }
  .section-tight {
    padding-block: var(--spacing-07);
  }
  .page {
    padding-block: var(--spacing-08) var(--spacing-10);
  }
  .page > h2 {
    margin-top: var(--spacing-08);
  }
}

.section-head {
  max-width: 42rem;
  margin-bottom: var(--spacing-09);
}

.section-head h2 {
  margin-bottom: var(--spacing-05);
}

.section-head > :last-child {
  margin-bottom: 0;
}

/* Carbon's eyebrow / kicker: label-01 in mono, uppercase, tracked out. Mono
   because it is machine vocabulary, not prose. */
.eyebrow {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--link-primary);
  margin-bottom: var(--spacing-05);
}

/* Carbon fluid-heading-03 for a lede: 20px → 28px, weight 400. */
.lede {
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
  line-height: 1.45;
  color: var(--text-primary);
  max-width: 44rem;
}

/* =====================================================================
   HERO
   ===================================================================== */

.hero {
  position: relative;
  background: var(--layer-01);
  border-block-end: 1px solid var(--border-subtle);
  overflow: hidden;
}

/* Carbon's grid is visible in its marketing work as a faint column rule.
   This is that, at 1/16th steps, and it is the one decorative flourish on
   the page — no glow, no bloom (both are off-brand and bloom badly on
   OLED). */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    to right,
    var(--border-subtle) 0 1px,
    transparent 1px calc(100% / 16)
  );
  opacity: 0.5;
}

/* Carbon's grid is 8 columns at `md` and 4 at `sm`. Sixteen rules across a
   375px screen is a 23px stripe pattern, which reads as noise rather than as
   a grid — so the decoration follows the real column count down. */
@media (max-width: 65.999rem) {
  .hero::before {
    background-image: repeating-linear-gradient(
      to right,
      var(--border-subtle) 0 1px,
      transparent 1px calc(100% / 8)
    );
  }
}

@media (max-width: 41.999rem) {
  .hero::before {
    background-image: repeating-linear-gradient(
      to right,
      var(--border-subtle) 0 1px,
      transparent 1px calc(100% / 4)
    );
    opacity: 0.35;
  }
}

.hero-inner {
  position: relative;
  padding-block: var(--spacing-12) var(--spacing-11);
  max-width: var(--grid-content);
}

@media (max-width: 41.999rem) {
  .hero-inner {
    padding-block: var(--spacing-09) var(--spacing-08);
  }
  .hero h1 {
    /* 22ch at a 32px display size overflows a 375px screen's measure. */
    max-width: none;
  }
  .hero .button-row,
  .hero .lede {
    margin-bottom: var(--spacing-07);
  }
}

.hero h1 {
  max-width: 22ch;
  margin-bottom: var(--spacing-06);
}

.hero .lede {
  margin-bottom: var(--spacing-08);
}

.hero .button-row {
  margin-bottom: var(--spacing-10);
}

/* =====================================================================
   BUTTONS — Carbon's hierarchy

   Carbon buttons are 48px tall (field-02), square, and the label is LEFT
   aligned with a wide right gutter — that asymmetry is one of Carbon's
   most recognisable details, and it exists so an icon can occupy the right
   without the label shifting.
   ===================================================================== */

.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-03);
}

.button {
  display: inline-flex;
  align-items: center;
  min-height: 3rem;
  padding: var(--spacing-04) var(--spacing-10) var(--spacing-04) var(--spacing-05);
  border: 1px solid transparent;
  background: var(--button-primary);
  color: var(--text-on-color);
  font-family: inherit;
  font-size: 0.875rem;
  line-height: 1.29;
  letter-spacing: 0.16px;
  font-weight: 400;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--duration-fast-01) var(--ease-standard);
}

.button:hover {
  background: var(--button-primary-hover);
  color: var(--text-on-color);
}

.button:active {
  background: var(--button-primary-active);
}

.button[disabled] {
  background: var(--layer-02);
  color: var(--text-secondary);
  cursor: not-allowed;
}

/* Carbon secondary/tertiary: outlined, transparent, fills on hover. */
.button-secondary {
  background: transparent;
  color: var(--link-primary);
  border-color: var(--link-primary);
}

.button-secondary:hover {
  background: var(--link-primary);
  color: var(--text-on-color);
  border-color: var(--link-primary);
}

/* Carbon's own guidance for small screens: buttons go full width and stack.
   Two 48px buttons side by side at 320px leaves ~150px each, which truncates
   a label like "Get in touch". */
@media (max-width: 29.999rem) {
  .button-row {
    flex-direction: column;
    align-items: stretch;
    gap: var(--spacing-02);
  }
  .button {
    /* The wide right gutter is a desktop affordance; at full width the label
       should simply sit at the left inset. */
    padding-inline-end: var(--spacing-05);
    justify-content: flex-start;
  }
}

/* =====================================================================
   TILES — Carbon's tile, standing in for .card

   Square, $layer-02 on a $border-subtle hairline, and on hover the border
   goes interactive rather than the tile lifting. Carbon does not use drop
   shadows for this.
   ===================================================================== */

/* Explicit column counts per breakpoint rather than `auto-fit`. auto-fit
   packs as many tiles per row as will fit, which left TWO EMPTY CELLS in the
   six-tile band at 1440px — and an empty grid cell here shows the
   border-coloured ground behind the mosaic, so it read as an unfinished
   block rather than as whitespace. Caught by rendering at 1440, not by
   reading the CSS. Three columns divides both the 6- and 3-tile bands
   cleanly, and is 5 of Carbon's 16 columns per tile. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
  /* The hairline mosaic is drawn by the CARDS, not by a coloured container.
     
     It used to be a 1px gap over a border-coloured background, which is
     tidy right up until the item count does not divide by the column count:
     4 tiles in 3 columns leaves 2 EMPTY CELLS, and an empty cell showed the
     container's border colour as a solid block. That is the same defect the
     six-tile band had at 1440px, and widening these pages exposed it again
     on the four-tile band.
     
     `outline` rather than `border` on each card: an outline is drawn outside
     the box and does not affect layout, so adjacent cards' outlines meet in
     the 1px gap and render as ONE hairline - the mosaic look, with empty
     cells simply drawing nothing. */
  background: transparent;
}

.card {
  margin: 0;
  padding: var(--spacing-06);
  background: var(--layer-02);
  outline: 1px solid var(--border-subtle);
  transition: background var(--duration-fast-02) var(--ease-standard);
}

.card + .card,
.card-grid .card + .card {
  margin-top: 0;
}

.card:hover {
  background: var(--layer-hover);
}

/* Carbon `md`: two up. Carbon `sm`: one up. */
@media (max-width: 65.999rem) {
  .card-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 41.999rem) {
  .card-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.card h3 {
  margin-bottom: var(--spacing-04);
  font-size: 1rem;
  line-height: 1.5;
}

.card p,
.card li {
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
}

.card p:last-child {
  margin-bottom: 0;
}

/* A single raised panel — Carbon's tile at one-up size. */
.panel {
  padding: var(--spacing-07);
  background: var(--layer-02);
  border: 1px solid var(--border-subtle);
  /* Carbon marks an informational panel with a 3px interactive edge. */
  border-inline-start: 3px solid var(--button-primary);
}

.panel h3 {
  margin-top: 0;
  margin-bottom: var(--spacing-05);
}

.panel > :last-child {
  margin-bottom: 0;
}

/* Two-column split, on the 16-column grid: 8 + 8 at lg, stacked below md. */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--grid-gutter);
  align-items: start;
}

.split > :first-child > :first-child {
  margin-top: 0;
}

/* Same reasoning as `.grid` above: a 50/50 prose split below Carbon `lg`
   gives two columns too narrow to read comfortably. */
@media (max-width: 65.999rem) {
  .split {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-08);
  }
}

/* =====================================================================
   STATS — Carbon's "big numbers" band
   ===================================================================== */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  gap: 1px;
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
  /* See .card-grid: outlines on the items, so an orphaned last row does not
     paint an empty block. */
  background: transparent;
}

.stat {
  margin: 0;
  padding: var(--spacing-07) var(--spacing-06);
  background: var(--background);
  outline: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-03);
}

.stat + .stat {
  margin-top: 0;
}

/* Carbon fluid-display-01 territory: large and LIGHT, not bold. */
.stat-figure {
  font-size: clamp(2.5rem, 2rem + 2vw, 3.75rem);
  line-height: 1;
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--link-primary);
  font-variant-numeric: tabular-nums;
}

.stat-label {
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
  color: var(--text-secondary);
}

/* =====================================================================
   STEPS / PIPELINE — Carbon's progress-indicator vocabulary
   ===================================================================== */

.steps {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  max-width: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: var(--grid-gutter);
}

.steps li {
  counter-increment: step;
  margin: 0;
  padding-block-start: var(--spacing-05);
  /* Carbon's progress indicator draws a rule across the top of each step. */
  border-block-start: 2px solid var(--border-strong);
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  color: var(--link-primary);
  margin-bottom: var(--spacing-04);
}

.steps h3 {
  font-size: 1rem;
  line-height: 1.5;
  margin-bottom: var(--spacing-03);
}

.steps p {
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
  margin-bottom: 0;
}

.pipeline {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
  display: grid;
  gap: 1px;
  background: var(--border-subtle);
  border: 1px solid var(--border-subtle);
}

/* NOT a grid, and that is the fix for a real rendering bug rather than a
   style preference.
   
   These <li>s are written as `<strong>Label</strong> description text…`, so
   the description is a BARE TEXT NODE. CSS Grid wraps loose text in an
   ANONYMOUS GRID ITEM, so a `grid-template-columns: auto 1fr` li laid out as
   ::before -> (1,1), <strong> -> (1,2), description -> (2,1). The `auto`
   first column then sized itself to the full description, which squeezed the
   `1fr` second column down to a narrow strip and wrapped the label into it
   one or two words per line, far to the right of its own text. On an iPad it
   looked completely broken.
   
   Flow layout with an absolutely-positioned marker cannot have that problem:
   there are no grid items, so a text node is just text. */
.pipeline li {
  position: relative;
  margin: 0;
  padding: var(--spacing-05) var(--spacing-06);
  /* Room for the marker, which is out of flow. */
  padding-inline-start: calc(var(--spacing-06) + var(--spacing-05));
  background: var(--layer-02);
  font-size: 0.875rem;
  line-height: 1.43;
  color: var(--text-secondary);
}

.pipeline li::before {
  content: "";
  position: absolute;
  inset-inline-start: var(--spacing-06);
  /* Aligned to the first line's optical centre rather than its box. */
  inset-block-start: calc(var(--spacing-05) + 0.45em);
  width: 0.5rem;
  height: 0.5rem;
  background: var(--border-strong);
}

/* The one place hard-gate crimson is correct: a gate is BLOCKED-coloured
   because that is what it does. Never decorative. */
.pipeline li.is-gate::before {
  background: var(--support-error);
}

/* The label is the row's heading, so it gets its own line. Inline, it ran
   straight into the description with only a space between them. */
.pipeline strong {
  display: block;
  margin-bottom: var(--spacing-02);
  font-weight: 600;
  color: var(--text-primary);
}

/* A tag inside the label (the HARD GATE marker) must not be forced onto its
   own line by the block above, and must not stretch. */
.pipeline strong .tag {
  margin-inline-start: var(--spacing-02);
  vertical-align: baseline;
}

/* =====================================================================
   NOTIFICATIONS — Carbon's inline notification

   Carbon's anatomy: a 3px status-coloured left edge on $layer-02, square,
   with the status carried by a word as well as the colour.
   ===================================================================== */

.notice {
  padding: var(--spacing-05) var(--spacing-06);
  background: var(--layer-02);
  border: 1px solid var(--border-subtle);
  border-inline-start: 3px solid var(--border-strong);
  margin-block: var(--spacing-07);
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
}

.notice > :last-child {
  margin-bottom: 0;
}

/* h2 as well as h3: the legal pages' draft banner uses an <h2>, which was
   picking up the global fluid heading clamp and rendering at 40px - as large
   as the page title, inside a notice. A notice heading is a label. */
.notice h2,
.notice h3 {
  font-size: 0.875rem;
  line-height: 1.43;
  font-weight: 600;
  letter-spacing: 0.16px;
  margin-bottom: var(--spacing-03);
}

.notice-status {
  border-inline-start-color: var(--button-primary);
  background: var(--accent-subtle);
}

.notice-warn,
.notice-draft {
  border-inline-start-color: var(--support-warning);
  background: var(--warn-subtle);
}

/* =====================================================================
   TAGS — Carbon's tag

   Carbon tags are small, square-ish, and filled at low opacity. Kept
   hollow-with-tint here so the state colour reads at small size without
   becoming a solid block, and always paired with a word (state is never
   colour alone).
   ===================================================================== */

.tag {
  display: inline-flex;
  align-items: center;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: var(--spacing-01) var(--spacing-03);
  border: 1px solid currentColor;
  color: var(--text-secondary);
  background: var(--layer-01);
  white-space: nowrap;
}

.tag-built {
  color: var(--support-success);
  background: var(--success-subtle);
}

.tag-progress {
  color: var(--support-warning);
  background: var(--warn-subtle);
}

.tag-planned {
  color: var(--text-secondary);
  background: var(--layer-01);
}

/* =====================================================================
   STATUS LIST — Carbon's structured-list / data-table rhythm

   A two-column list of tag + claim. Carbon's structured list is ruled
   between rows, which is what makes a long status list scannable.
   ===================================================================== */

.status-list {
  list-style: none;
  margin: var(--spacing-06) 0 0;
  padding: 0;
  max-width: none;
  border-block-start: 1px solid var(--border-subtle);
}

.status-list li {
  margin: 0;
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: var(--spacing-05);
  align-items: start;
  padding-block: var(--spacing-05);
  border-block-end: 1px solid var(--border-subtle);
  font-size: 0.9375rem;
  line-height: 1.47;
}

@media (max-width: 41.999rem) {
  .status-list li {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-03);
  }
}

/* =====================================================================
   FACT LIST — Carbon's definition/structured list
   ===================================================================== */

.fact-list {
  margin: var(--spacing-06) 0;
  max-width: none;
  border-block-start: 1px solid var(--border-subtle);
}

.fact-list div {
  display: grid;
  grid-template-columns: 12rem 1fr;
  gap: var(--spacing-05);
  padding-block: var(--spacing-05);
  border-block-end: 1px solid var(--border-subtle);
}

.fact-list div:last-child {
  border-block-end: 1px solid var(--border-subtle);
}

.fact-list dt {
  font-weight: 600;
  font-size: 0.875rem;
  line-height: 1.43;
}

.fact-list dd {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.43;
}

@media (max-width: 47.999rem) {
  .fact-list div {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-02);
  }
}

/* =====================================================================
   WATCH BAR — the product's own status strip, quoted on the page
   ===================================================================== */

.watch-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-05);
  padding: var(--spacing-04) var(--spacing-05);
  background: var(--background);
  border: 1px solid var(--border-subtle);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}

.watch-item {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-02);
  white-space: nowrap;
}

.watch-bar b {
  color: var(--text-primary);
  font-weight: 400;
}

.dot {
  width: 0.5rem;
  height: 0.5rem;
  background: currentColor;
  flex: 0 0 auto;
}

.state-building {
  color: var(--link-primary);
}

.state-awaiting {
  color: var(--support-warning);
}

.watch-caption {
  margin-top: var(--spacing-04);
  font-size: 0.875rem;
  line-height: 1.43;
  color: var(--text-secondary);
  max-width: 42rem;
}

/* =====================================================================
   CTA BAND
   ===================================================================== */

.cta-band {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--grid-gutter);
  align-items: center;
  padding: var(--spacing-09) var(--spacing-07);
  background: var(--layer-02);
  border: 1px solid var(--border-subtle);
  border-inline-start: 3px solid var(--button-primary);
}

.cta-copy h2 {
  margin-top: 0;
  margin-bottom: var(--spacing-04);
}

.cta-copy p {
  margin-bottom: 0;
  color: var(--text-secondary);
}

@media (max-width: 55.999rem) {
  .cta-band {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--spacing-07) var(--spacing-06);
  }
}

/* =====================================================================
   FORMS — Carbon's text input

   Carbon inputs are 48px, square, filled with $field-01, and carry a 1px
   bottom rule that goes interactive on focus. No rounded corners, and the
   label sits above in label-01.
   ===================================================================== */

.form {
  max-width: 38rem;
  margin-block: var(--spacing-07);
}

.field {
  margin-bottom: var(--spacing-06);
}

.field label {
  display: block;
  margin-bottom: var(--spacing-03);
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.32px;
  color: var(--text-secondary);
}

.field input,
.field textarea,
.field select,
textarea,
select {
  width: 100%;
  min-height: 3rem;
  padding: var(--spacing-04) var(--spacing-05);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--layer-01);
  border: 0;
  border-block-end: 1px solid var(--border-strong);
  transition: background var(--duration-fast-01) var(--ease-standard);
}

.field textarea,
textarea {
  min-height: 9rem;
  resize: vertical;
}

.field input:hover,
.field textarea:hover,
.field select:hover {
  background: var(--layer-hover);
}

.field input:focus-visible,
.field textarea:focus-visible,
.field select:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

select option {
  background: var(--layer-02);
  color: var(--text-primary);
}

.field .hint {
  margin-top: var(--spacing-03);
  margin-bottom: 0;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.32px;
  color: var(--text-secondary);
}

/* Carbon's invalid state: the field's bottom rule turns $support-error and
   the message sits beneath in helper-text-01. */
textarea[aria-invalid="true"],
.field input[aria-invalid="true"],
.field select[aria-invalid="true"] {
  border-block-end-color: var(--support-error);
}

.field-error {
  margin-top: var(--spacing-03);
  margin-bottom: 0;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.32px;
  color: var(--support-error);
}

.field-error:empty {
  display: none;
}

.checkbox-field {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--spacing-04);
  align-items: start;
  margin-bottom: var(--spacing-06);
}

.checkbox-field input[type="checkbox"] {
  width: 1.125rem;
  height: 1.125rem;
  margin: 0.2rem 0 0;
  accent-color: var(--button-primary);
}

.checkbox-field label {
  font-size: 0.875rem;
  line-height: 1.43;
  color: var(--text-primary);
}

.turnstile-holder {
  margin-bottom: var(--spacing-06);
  min-height: 4.25rem;
}

/* Carbon notification, reused for form results. */
.form-status {
  margin-block: var(--spacing-06);
  padding: var(--spacing-05) var(--spacing-06);
  background: var(--layer-02);
  border: 1px solid var(--border-subtle);
  border-inline-start: 3px solid var(--border-strong);
  font-size: 0.875rem;
  line-height: 1.43;
}

.form-status:empty {
  display: none;
}

.form-status h2 {
  font-size: 1rem;
  line-height: 1.5;
  font-weight: 600;
  margin-bottom: var(--spacing-03);
}

.form-status > :last-child {
  margin-bottom: 0;
}

.form-status a {
  color: var(--link-primary);
}

.form-status-success {
  border-inline-start-color: var(--support-success);
  background: var(--success-subtle);
}

.form-status-error {
  border-inline-start-color: var(--support-error);
  background: var(--danger-subtle);
}

.no-js-warning {
  padding: var(--spacing-05) var(--spacing-06);
  background: var(--warn-subtle);
  border: 1px solid var(--border-subtle);
  border-inline-start: 3px solid var(--support-warning);
  margin-block: var(--spacing-06);
  font-size: 0.875rem;
  line-height: 1.43;
}

.no-js-warning > :last-child {
  margin-bottom: 0;
}

.placeholder {
  color: var(--text-secondary);
  font-style: normal;
}

.legal-meta {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  text-transform: uppercase;
}

/* =====================================================================
   FOOTER — Carbon's site footer
   ===================================================================== */

.site-footer {
  background: var(--layer-01);
  border-block-start: 1px solid var(--border-subtle);
  padding-block-start: var(--spacing-10);
}

.footer-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 2fr);
  gap: var(--grid-gutter);
  padding-block-end: var(--spacing-10);
}

@media (max-width: 55.999rem) {
  .footer-inner {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-09);
  }
}

.footer-brand {
  max-width: 26rem;
}

.footer-brand-link {
  padding-inline: 0;
  margin-bottom: var(--spacing-05);
}

.footer-brand-link:hover {
  background: transparent;
}

.footer-note {
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
}

.footer-address {
  font-style: normal;
  color: var(--text-secondary);
  font-size: 0.875rem;
  line-height: 1.6;
}

.footer-address strong {
  color: var(--text-primary);
  font-weight: 600;
}

.footer-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
  gap: var(--grid-gutter);
}

.footer-col {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-03);
}

/* Carbon's footer column headers: label-01, uppercase, tracked. */
.footer-col h2 {
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.32px;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 var(--spacing-02);
}

.footer-col a {
  color: var(--text-primary);
  text-decoration: none;
  font-size: 0.875rem;
  line-height: 1.43;
  letter-spacing: 0.16px;
}

.footer-col a:hover {
  color: var(--link-primary);
  text-decoration: underline;
}

.footer-social {
  display: flex;
  gap: var(--spacing-03);
  margin-top: var(--spacing-05);
}

.social-link {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
}

.social-link:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
  background: var(--layer-hover);
}

.social-link svg {
  width: 1.25rem;
  height: 1.25rem;
}

.footer-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--spacing-04);
  padding-block: var(--spacing-06);
  border-block-start: 1px solid var(--border-subtle);
}

.footer-legal {
  margin: 0;
  max-width: none;
  font-size: 0.75rem;
  line-height: 1.33;
  letter-spacing: 0.32px;
  color: var(--text-secondary);
}

.footer-legal a {
  color: var(--text-secondary);
}

.footer-legal a:hover {
  color: var(--link-primary);
}

/* =====================================================================
   MOTION PREFERENCE — Carbon requires honouring it.
   ===================================================================== */

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