/* =========================================================
   Flowie Exchange — Documentation Design System
   ========================================================= */

:root {
  /* type scale */
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace;

  /* light palette (default) */
  --bg: #ffffff;
  --bg-soft: #f8fafc;
  --bg-muted: #f1f5f9;
  --bg-code: #0b1220;
  --bg-code-soft: #0f172a;
  --border: #e2e8f0;
  --border-strong: #cbd5e1;
  --text: #0f172a;
  --text-soft: #475569;
  --text-muted: #64748b;
  --text-faint: #94a3b8;
  --accent: #6d28d9;
  --accent-soft: #ede9fe;
  --accent-hover: #5b21b6;
  /* Background of solid buttons that carry white text. Separate from --accent
     because --accent doubles as a text/link colour, and the two have opposite
     contrast needs: link text must be light on a dark page, while a background
     under white text must be dark. Light theme already passes, so these match. */
  --accent-solid: #6d28d9;        /* white on this: 7.10:1 */
  --accent-solid-hover: #5b21b6;  /* white on this: 8.98:1 */
  --success: #047857;
  --success-soft: #d1fae5;
  --warning: #b45309;
  --warning-soft: #fef3c7;
  --danger: #b91c1c;
  --danger-soft: #fee2e2;
  --info: #1d4ed8;
  --info-soft: #dbeafe;

  /* http methods */
  --m-get:    #0369a1;
  --m-post:   #047857;
  --m-patch:  #b45309;
  --m-delete: #b91c1c;
  --m-put:    #7c3aed;

  /* layout */
  --nav-w: 280px;
  --code-w: 460px;
  --topbar-h: 60px;
  --radius: 8px;
  --radius-sm: 6px;
  --radius-lg: 14px;

  /* shadows */
  --shadow-sm: 0 1px 2px rgba(15,23,42,0.04);
  --shadow: 0 2px 8px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
  --shadow-lg: 0 12px 40px rgba(15,23,42,0.12);
}

:root[data-theme="dark"] {
  --bg: #0a0e1a;
  --bg-soft: #0f1524;
  --bg-muted: #161c2d;
  --bg-code: #05080f;
  --bg-code-soft: #0a0f1c;
  --border: #1e2638;
  --border-strong: #2a3349;
  --text: #e6eaf2;
  --text-soft: #a8b1c4;
  --text-muted: #7a8399;
  --text-faint: #565f73;
  --accent: #a78bfa;
  --accent-soft: #2e1d5b;
  --accent-hover: #c4b5fd;
  /* #a78bfa is right for link text on a dark page but fails badly as a button
     background: white on it is 2.72:1, well under the 4.5:1 minimum. */
  --accent-solid: #7c3aed;        /* white on this: 5.70:1 */
  --accent-solid-hover: #6d28d9;  /* white on this: 7.10:1 */
  --success: #34d399;
  --success-soft: #064e3b;
  --warning: #fbbf24;
  --warning-soft: #78350f;
  --danger: #f87171;
  --danger-soft: #7f1d1d;
  --info: #60a5fa;
  --info-soft: #1e3a8a;

  --m-get:    #60a5fa;
  --m-post:   #34d399;
  --m-patch:  #fbbf24;
  --m-delete: #f87171;
  --m-put:    #c4b5fd;

  --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
  --shadow: 0 2px 8px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
  --shadow-lg: 0 12px 40px rgba(0,0,0,0.6);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--topbar-h) + 16px); }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-feature-settings: "cv11", "ss01";
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; text-underline-offset: 2px; }
h1, h2, h3, h4, h5, h6 {
  font-weight: 660;
  letter-spacing: -0.011em;
  color: var(--text);
  margin-top: 2.4em;
  margin-bottom: 0.5em;
  line-height: 1.25;
  scroll-margin-top: calc(var(--topbar-h) + 16px);
}
h1 { font-size: 34px; letter-spacing: -0.025em; margin-top: 0; }
h2 { font-size: 24px; letter-spacing: -0.015em; padding-top: 12px; border-top: 1px solid var(--border); }
h3 { font-size: 18px; }
h4 { font-size: 15px; color: var(--text-soft); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }
p { margin: 0 0 1em; color: var(--text-soft); }
hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; }

/* Inline code only — :not(pre code) keeps Prism token spans inside <pre> clean */
:not(pre) > code,
:not(pre) > * > code {
  font-family: var(--font-mono);
  font-size: 0.87em;
  background: var(--bg-muted);
  /* Padding is em-based and deliberately small. An inline chip's padding and
     border do NOT grow the line box, so at 2px/6px the chip measured 21px tall
     inside a 24px line: two chips on consecutive lines came within 2px of
     touching and a prose paragraph carrying them read as if its leading had
     collapsed. Sideways, 6px read as a whole word space — it detached a chip
     from its own punctuation ("<code>203/204</code>)," looked like "203/204 ),")
     and, when a chip wrapped to the start of a line, pushed its text past the
     left rag of every other line. 0.1em/0.35em keeps the chip legible and
     leaves ~2px of air above and below it. */
  padding: 0.1em 0.35em;
  border-radius: 5px;
  color: var(--text);
  border: 1px solid var(--border);
  /* A chip is one token to the reader, so it must not be split across two
     lines. The default inline wrapping broke "BR-FR-09" after its hyphen and
     "209 Complétée" after its space, and each half then rendered as its own
     half-bordered box on its own line — 46 chips on the API Reference and 10
     on the France refusal page were split that way at 1280px.

     inline-block, not `white-space: nowrap`: an inline-block is shrink-to-fit,
     so a chip that does not fit the rest of the line moves to the next line
     whole instead of splitting, while `max-width: 100%` keeps one that cannot
     fit *any* line inside its container, where `overflow-wrap` below wraps it
     into a single multi-line chip. nowrap has no such release valve — it
     suppresses every wrap opportunity, and the prose column is capped at 68ch
     (~504px at 1280px) whatever the viewport, so the Reference's 101-character
     Party shape (~800px) escaped its paragraph by 300px at 1280px and scrolled
     the page sideways at 1000px. */
  display: inline-block;
  max-width: 100%;
}
/* Code inside <pre> never gets borders, padding or backgrounds — Prism handles it */
pre code,
pre code * {
  background: none !important;
  border: 0 !important;
  padding: 0 !important;
  border-radius: 0 !important;
}

/* ---------- topbar ---------- */
.topbar {
  position: sticky; top: 0; z-index: 40;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 16px;
  padding: 0 20px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--border);
  min-width: 0;
}
.topbar > .brand { flex-shrink: 0; }
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); font-weight: 700; letter-spacing: -0.01em; }
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 28px; height: 28px; border-radius: 7px;
  display: block; object-fit: contain;
}
img.brand-mark { background: transparent; }
.brand-name { font-size: 15px; }

.topnav {
  display: flex; align-items: center; gap: 2px;
  margin-left: 12px;
  flex-wrap: nowrap;
  flex-shrink: 0;          /* never let the right cluster eat into nav links */
}
.topnav a {
  color: var(--text-soft); font-size: 14px; font-weight: 500;
  padding: 7px 12px; border-radius: 7px;
  white-space: nowrap;        /* never wrap "API Reference" onto two lines */
  flex-shrink: 0;
}
.topnav a:hover { background: var(--bg-muted); color: var(--text); text-decoration: none; }
.topnav a.active { color: var(--accent); background: var(--accent-soft); }
/* For every section that owns a dropdown, the hover / active highlight wraps
   the whole .topnav-item — the section link AND its "v" caret — so the
   chevron sits inside the pill instead of beside it. This applies to ALL
   dropdown sections, not just the current one: the pill is driven from the
   item, and the inner link/caret backgrounds are dropped so the single item
   pill shows through. (Sections without a dropdown — Docs, Changelog — keep
   the plain .topnav a pill above; they have no caret.) */
.topnav-item { border-radius: 7px; }
.topnav-item > a:hover,
.topnav-item > .topnav-caret:hover { background: none; }
.topnav-item:hover { background: var(--bg-muted); }
.topnav-item:hover > a,
.topnav-item:hover > .topnav-caret { color: var(--text); }
.topnav-item:has(> a.active),
.topnav-item:has(> a.active):hover { background: var(--accent-soft); }
.topnav-item:has(> a.active) > a.active { background: none; }
.topnav-item:has(> a.active) > a.active,
.topnav-item:has(> a.active) > .topnav-caret,
.topnav-item:has(> a.active):hover > a,
.topnav-item:has(> a.active):hover > .topnav-caret { color: var(--accent); }

/* Section dropdowns — each .topnav-item wraps the section link, a caret
   button and a .topnav-menu panel listing the section's pages, so every page
   is directly reachable from the top menu. Opens on hover / keyboard focus;
   app.js toggles .open for click + touch. */
.topnav-item { position: relative; display: flex; align-items: center; flex-shrink: 0; }
.topnav-item > a { padding-right: 5px; }
.topnav-caret {
  display: flex; align-items: center; justify-content: center;
  width: 18px; height: 26px; padding: 0; margin: 0 2px 0 0;
  background: none; border: none; border-radius: 6px;
  color: var(--text-muted); cursor: pointer;
}
.topnav-caret:hover { background: var(--bg-muted); color: var(--text); }
.topnav-caret svg { transition: transform 0.15s ease; }
.topnav-menu {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 264px;
  display: none; flex-direction: column; gap: 2px; padding: 8px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.06), 0 18px 44px rgba(0, 0, 0, 0.16);
  z-index: 50;
}
/* invisible bridge so the pointer can cross the 6px gap without closing */
.topnav-menu::before { content: ""; position: absolute; top: -8px; left: 0; right: 0; height: 8px; }
.topnav-item:hover .topnav-menu,
.topnav-item:focus-within .topnav-menu,
.topnav-item.open .topnav-menu {
  display: flex;
  animation: topnav-menu-in 0.14s ease-out;
}
@keyframes topnav-menu-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .topnav-item:hover .topnav-menu,
  .topnav-item:focus-within .topnav-menu,
  .topnav-item.open .topnav-menu { animation: none; }
}
.topnav-item:hover .topnav-caret svg,
.topnav-item.open .topnav-caret svg { transform: rotate(180deg); }
/* Two-line menu entries: page name + a one-line "what you'll find there". */
.topnav-menu a {
  display: flex; flex-direction: column; gap: 1px;
  padding: 8px 10px; border-radius: 8px;
  border-left: 2px solid transparent;
}
.topnav-menu a:hover { background: var(--bg-muted); }
.topnav-menu a.active {
  background: var(--accent-soft);
  border-left-color: var(--accent);
}
.topnav-menu .mi-label {
  font-size: 13.5px; font-weight: 600; color: var(--text);
  white-space: nowrap;
}
.topnav-menu a.active .mi-label { color: var(--accent); }
.topnav-menu .mi-desc {
  font-size: 11.5px; font-weight: 400; color: var(--text-muted);
  white-space: nowrap;
}
/* Journey group headers inside a dropdown ("Integrate fast", "🇫🇷 France…") */
.topnav-menu .mg-title {
  padding: 10px 10px 3px; font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted);
  white-space: nowrap;
}
.topnav-menu .mg-title:not(:first-child) { border-top: 1px solid var(--border); margin-top: 6px; }

/* Multi-column panel — one column per group, side by side (e.g. Compliance:
   All countries | 🇫🇷 France | 🇮🇹 Italy). */
.topnav-menu--cols { flex-direction: row; align-items: stretch; gap: 4px; padding: 10px; }
.topnav-menu--cols .mg-col { display: flex; flex-direction: column; gap: 2px; min-width: 216px; }
.topnav-menu--cols .mg-col + .mg-col { border-left: 1px solid var(--border); padding-left: 10px; margin-left: 6px; }
.topnav-menu--cols .mg-title { padding-top: 4px; }
.topnav-menu--cols .mg-title:not(:first-child) { border-top: none; margin-top: 0; }
/* Flip to right-aligned when the panel would overflow the viewport
   (app.js measures on open and toggles .flip). */
.topnav-menu.flip { left: auto; right: 0; }
/* A panel can never be wider than the window, whatever JS decides about which
   edge to anchor to. On desktop the multi-column panels stay side by side
   (nowrap) — that's the intended layout; the narrow-window stacking that keeps
   a column from clipping off the left edge is scoped to the < 1000px query
   below, not forced on every width. */
.topnav-menu { max-width: calc(100vw - 16px); }
.topnav-menu--cols { flex-wrap: nowrap; }

/* Nested deep-dive pages under a country in the compliance sidebar */
.nav-items .nav-sub { list-style: none; margin: 2px 0 4px; padding-left: 22px; }
.nav-items .nav-sub a { font-size: 12.5px; color: var(--text-muted); display: block; padding: 3px 8px; border-radius: 6px; }
.nav-items .nav-sub a:hover { color: var(--text); background: var(--bg-muted); text-decoration: none; }
.nav-items .nav-sub a.active { color: var(--accent); background: var(--accent-soft); }

/* Right cluster — keeps a sensible spacing rhythm and prevents wrap. */
.topbar-right {
  margin-left: auto;
  display: flex; gap: 8px; align-items: center;
  flex-shrink: 0;
}
.topbar-right > * { flex-shrink: 0; white-space: nowrap; }

.search-trigger {
  display: flex; align-items: center; gap: 10px;
  background: var(--bg-soft); border: 1px solid var(--border);
  padding: 7px 12px; border-radius: 8px; color: var(--text-muted);
  font-size: 13px; cursor: pointer;
  width: 220px; max-width: 220px; transition: all 0.15s;
  white-space: nowrap;
}
.search-trigger:hover { border-color: var(--border-strong); color: var(--text-soft); }
.search-trigger .kbd-hint { margin-left: auto; display: flex; gap: 3px; }

/* Language switcher — narrower, no awkward extra padding. */
#lang-switcher {
  height: 32px; padding: 0 8px; font-size: 13px;
  background: var(--bg-soft); color: var(--text-soft);
  border: 1px solid var(--border); border-radius: 7px;
  cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
                    linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: calc(100% - 14px) 14px, calc(100% - 9px) 14px;
  background-size: 5px 5px; background-repeat: no-repeat;
  padding-right: 22px;
}
#lang-switcher:hover { border-color: var(--border-strong); color: var(--text); }
.kbd {
  font-family: var(--font-mono); font-size: 11px;
  background: var(--bg-muted); border: 1px solid var(--border);
  padding: 2px 5px; border-radius: 4px; color: var(--text-muted);
  box-shadow: 0 1px 0 var(--border);
}

.icon-btn {
  width: 34px; height: 34px; border-radius: 8px;
  display: grid; place-items: center;
  background: transparent; border: 1px solid var(--border);
  color: var(--text-soft); cursor: pointer; transition: all 0.15s;
}
.icon-btn:hover { background: var(--bg-muted); color: var(--text); border-color: var(--border-strong); }
.icon-btn svg { width: 16px; height: 16px; }

.cta {
  padding: 7px 14px; background: var(--accent-solid); color: white;
  border-radius: 7px; font-size: 13px; font-weight: 600; border: 0; cursor: pointer;
  white-space: nowrap;
}
.cta:hover { background: var(--accent-solid-hover); color: white; text-decoration: none; }

/* Auth widget (Sign in / Sign up / signed-in pill) — sits left of the CTA. */
.auth-widget { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.auth-widget a {
  font-size: 13px; font-weight: 500; color: var(--text-soft);
  padding: 6px 10px; border-radius: 7px; white-space: nowrap;
}
.auth-widget a:hover { color: var(--text); background: var(--bg-muted); text-decoration: none; }
.auth-widget .auth-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  background: var(--success-soft); color: var(--success);
  font-size: 12.5px; font-weight: 600;
  border: 1px solid color-mix(in srgb, var(--success) 25%, transparent);
}
.auth-widget .auth-pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--success); }
.auth-widget .auth-pill button {
  background: transparent; border: 0; color: var(--text-muted);
  font-size: 11.5px; cursor: pointer; padding: 0 0 0 4px;
  font-family: inherit; text-decoration: underline; text-underline-offset: 2px;
}
.auth-widget .auth-pill button:hover { color: var(--danger); }

/* Sandbox status badge — green dot if reachable, amber if degraded. */
.sandbox-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600;
  background: var(--bg-soft); border: 1px solid var(--border); color: var(--text-muted);
  white-space: nowrap;
}
.sandbox-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-faint); }
.sandbox-badge.up   { color: var(--success); border-color: color-mix(in srgb, var(--success) 30%, transparent); background: color-mix(in srgb, var(--success) 8%, var(--bg-soft)); }
.sandbox-badge.up   .dot { background: var(--success); }
.sandbox-badge.down { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 30%, transparent); background: color-mix(in srgb, var(--warning) 8%, var(--bg-soft)); }
.sandbox-badge.down .dot { background: var(--warning); }

/* Active-organization picker — sits in the auth pill next to the email +
   Logout link. Theme-aware: in dark mode the native <select> would render
   with a white system background, so we force the page palette. The
   visible chrome is the same pill the auth-pill wears, just less saturated
   so the org chip reads as a child of the auth pill rather than competing.
   The popover that opens on click still uses the OS palette (browsers
   refuse to style that), which is fine — it lasts a click and dismisses. */
.auth-widget .auth-org-picker,
.auth-widget select.auth-org-picker {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  display: inline-flex; align-items: center;
  margin: 0 0 0 8px; padding: 3px 22px 3px 8px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--success) 25%, transparent);
  background-color: color-mix(in srgb, var(--success) 5%, var(--bg-soft));
  color: var(--text);
  font: inherit; font-size: 11.5px; font-weight: 600;
  line-height: 1.4;
  max-width: 180px; min-width: 0;
  cursor: pointer; text-overflow: ellipsis; white-space: nowrap;
  /* Caret on the right — drawn in `currentColor` so dark mode flips it. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 20 20' fill='%23999'><path d='M6 8l4 4 4-4'/></svg>");
  background-position: right 6px center;
  background-repeat: no-repeat;
}
.auth-widget .auth-org-picker:hover,
.auth-widget select.auth-org-picker:hover {
  border-color: color-mix(in srgb, var(--success) 45%, transparent);
  background-color: color-mix(in srgb, var(--success) 10%, var(--bg-soft));
}
.auth-widget .auth-org-picker:focus-visible,
.auth-widget select.auth-org-picker:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--success) 35%, transparent);
  outline-offset: 1px;
}
.auth-widget .auth-org-picker option {
  /* The dropdown popover IS subject to native palette in most browsers,
     but Chrome+Firefox at least respect color-scheme to pick the right
     dark/light system tray automatically — this keeps that working. */
  background: var(--bg);
  color: var(--text);
}

/* Responsive — NEVER hide nav items. The decoration on the right cluster
   gets sacrificed first; nav links are the whole point of the topbar.

   Only the very last fallback (narrow phones, < 860 px) hides the topnav
   entirely behind the hamburger drawer. */

/* < 1620 — the lang pill drops its chevron, and the nav gives back 2px a side.
   (.topbar-lang is injected by auth-widget.js; like .session-pill below, its
   responsive ladder stays here with the rest of the topbar's.) Together these
   buy back most of the ~73px the pill costs, which is why adding it did not
   push the bar wider than it already was. */
@media (max-width: 1619px) {
  /* Only `display` is settable from here: auth-widget.js appends its own
     <style> to document.head after this file, at the same specificity, so its
     .tl-pill padding wins at every rung. The pill's own metrics live there. */
  .topbar-lang .tl-chev { display: none; }
  .topnav a { padding: 7px 10px; }
  /* Restate the caret gap: the shorthand above matches .topnav-item > a with
     the same specificity and later in the file, so without this the section
     links get their full padding back on the right and the trim nets out to
     nothing. Every rung below that touches .topnav a inherits this one. */
  .topnav-item > a { padding-right: 5px; }
}

/* 1500–1619 — the one band where the search box is still 220px wide AND the
   full nav is showing, so the pill collapses to its globe here and comes back
   below 1500, where the search box is already down to an icon. The globe alone
   still reads as "language" and the menu it opens names the current one; the
   pill's tooltip carries it too. (The same collapse returns for good at 1400,
   see below.) */
@media (min-width: 1500px) and (max-width: 1619px) {
  .topbar-lang .tl-name { display: none; }
}

/* < 1500 — collapse "Search docs" label first; keep magnifier icon. */
@media (max-width: 1499px) {
  .search-trigger { width: 36px; max-width: 36px; padding: 7px 8px; }
  .search-trigger span:not(.kbd-hint):not(.kbd) { display: none; }
  .search-trigger .kbd-hint { display: none; }
}

/* < 1399 — sandbox status badge becomes a single coloured dot. */
@media (max-width: 1399px) {
  .sandbox-badge { padding: 4px; font-size: 0; gap: 0; border-radius: 50%; }
  .sandbox-badge .dot { width: 8px; height: 8px; }
  /* From here down the pill is its globe alone, for good. */
  .topbar-lang .tl-name { display: none; }
  .topnav a { padding: 7px 9px; }
  .topnav-item > a { padding-right: 5px; }   /* see the 1620 rung */
}

/* < 1280 — drop "Sign in" link. Topnav stays full, on tighter padding. */
@media (max-width: 1279px) {
  .auth-widget a:not(.auth-up) { display: none; }
  .topnav a { padding: 7px 6px; font-size: 13px; }
  .topnav-item > a { padding-right: 5px; }   /* see the 1620 rung */
}

/* < 1140 — hide sandbox dot + auth-widget signup link; keep topnav + CTA. */
@media (max-width: 1139px) {
  .sandbox-badge { display: none; }
  .auth-widget { display: none; }
  /* index.html carries a second, standalone signup link next to the CTA —
     auth-widget.js swaps it for the session pill once it runs, so this is the
     script-off render: nothing in the ladder was dropping it, and the landing
     page's top bar overflowed the page without it. */
  .topbar-right > .btn-secondary { display: none; }
  .topnav a { padding: 6px 5px; font-size: 12.5px; }
}

/* < 1070 — the band where the right-hand cluster is still near full width
   (the search button only drops below 1000) and the longest localized topnav
   no longer fits beside it: 900px used to overflow the page by ~30px, and the
   1000–1004px sliver by ~5px. Trim the nav's own padding instead of dropping
   a link — this rung also carries down to the 861px edge, where the FR/IT
   navs are the widest thing in the topbar. */
@media (max-width: 1069px) {
  .topnav a { padding: 6px 3px; font-size: 12px; }
  /* Same trade as the sandbox badge at 1399px: the session pill's coloured
     dot already says which environment you are on, so the "Stg ·" prefix is
     the first thing to go. (.session-pill is injected by auth-widget.js; the
     responsive ladder stays here, where the rest of the topbar's is.) */
  .session-pill .sp-env, .session-pill .sp-sep { display: none; }
  /* The theme toggle goes one rung earlier than it used to (it was 999) to
     find the 36px the language pill costs this band. It is the toggle rather
     than the search button because search has no other entry point on a
     touch device — no keyboard for ⌘K, and the hamburger only appears at
     860 — while the theme still follows prefers-color-scheme on its own. */
  #theme-toggle { display: none; }
  /* index.html is the only page with a topbar CTA, and it sits a few hundred
     pixels above the hero's own "Get a test key" button. Below 1070 the
     French and Italian navs need that width more than the duplicate does. */
  .topbar-right > .cta { display: none; }
}

/* < 1000 — the topnav moves into the hamburger drawer, and the search button
   stays. The ladder used to do the opposite (drop search, keep the nav), which
   left every touch device below 1000px with no way into search at all: the
   trigger was the only entry point there, since ⌘K and "/" both need a
   keyboard and the drawer only appeared at 860. It also did not fit — the
   longest (FR/IT) navs overflowed the topbar by up to 64px across the whole
   861–999 band, so the nav that was kept was the thing running off the page.
   Handing it to the drawer here fixes both and makes the note the 860 rung
   used to carry ("even the longest nav still fits") actually true.
   Multi-column dropdown panels are moot once .topnav is hidden, so the wrap
   rule that used to live here went with it. */
@media (max-width: 999px) {
  .topnav { display: none; }
}
/* The rest of this rung — the hamburger, the drawer, the off-canvas sidebar —
   lives further down, next to the 860px one. A media query adds no
   specificity, so those rules have to come after the base `.menu-toggle` and
   `.sidebar` declarations below to win against them. */

.menu-toggle { display: none; }

/* ---------- layout: three column ---------- */
.shell {
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr) var(--code-w);
  max-width: 1600px;
  margin: 0 auto;
}
.shell--two { grid-template-columns: var(--nav-w) minmax(0, 1fr); }
.shell--one { grid-template-columns: minmax(0, 1fr); max-width: 920px; }

/* ---------- sidebar ---------- */
.sidebar {
  position: sticky; top: var(--topbar-h);
  height: calc(100vh - var(--topbar-h));
  overflow-y: auto;
  border-right: 1px solid var(--border);
  padding: 24px 12px 80px 24px;
  scrollbar-width: thin;
}
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

.nav-group { margin-bottom: 16px; }
.nav-title {
  font-size: 11px; font-weight: 700;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.09em;
  padding: 6px 10px; margin-bottom: 4px;
  display: flex; align-items: center; gap: 6px;
}
.nav-title .chev { transition: transform 0.15s; opacity: 0.6; }
.nav-group.collapsed .chev { transform: rotate(-90deg); }
.nav-group.collapsed .nav-items { display: none; }

/* app.js splits the title into a chevron button and a link to the <h2> the
   group names, so the chevron folds the group and the label goes to it. */
.nav-chev {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex: none;
  padding: 0; margin-left: -3px;
  background: none; border: 0; border-radius: 4px;
  color: inherit; cursor: pointer;
}
.nav-chev:hover { background: var(--bg-muted); color: var(--text); }
.nav-title-link {
  flex: 1; min-width: 0;
  color: inherit; font: inherit; letter-spacing: inherit;
  cursor: pointer;
}
a.nav-title-link:hover { color: var(--accent); text-decoration: none; }

/* Type-to-filter, added by app.js to any menu long enough to need it. */
/* Sticky, so the filter is still there after you have scrolled the menu.
   The -24px offset and matching padding put its background over the
   sidebar's own 24px top padding, which it would otherwise scroll under. */
.nav-filter { position: sticky; top: -24px; z-index: 2; background: var(--bg); margin: -24px 0 12px; padding: 24px 0 10px; }
.nav-filter-input {
  width: 100%; box-sizing: border-box;
  padding: 7px 10px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--bg-muted);
  color: var(--text); font-family: inherit; font-size: 13px;
}
.nav-filter-input::placeholder { color: var(--text-muted); }
.nav-filter-input:focus { outline: none; border-color: var(--accent); background: var(--bg); }
.nav-filter-input::-webkit-search-cancel-button { cursor: pointer; }
.nav-filter-empty { margin: 8px 2px 0; font-size: 12.5px; color: var(--text-muted); }
/* While filtering, the group titles are context for the hits under them —
   not something to fold away. */
.sidebar.filtering .nav-chev { visibility: hidden; }
.nav-items { list-style: none; margin: 0; padding: 0; }
.nav-items a {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 10px; border-radius: 6px;
  font-size: 13.5px; color: var(--text-soft);
  border-left: 2px solid transparent;
  transition: all 0.1s;
}
.nav-items a:hover { color: var(--text); background: var(--bg-muted); text-decoration: none; }
.nav-items a.active { color: var(--accent); background: var(--accent-soft); font-weight: 500; }
.nav-items .method { font-size: 9.5px; }

/* Site-level nav mirrored into the mobile drawer by app.js. The top-level
   .topnav is hidden on phones, so this is the only way to reach other
   sections there. Hidden on desktop (the .topnav handles it); revealed
   inside the drawer at mobile widths. */
.sidebar-sitenav { display: none; }

/* A drawer synthesized by app.js on pages with no in-page .sidebar (e.g. the
   landing index.html), purely to host the mirrored site nav on phones. Hidden
   on desktop, where the .topnav handles navigation; revealed as the off-canvas
   drawer at mobile widths (below). */
.sidebar--drawer-only { display: none; }

/* ---------- main content ---------- */
.content { padding: 40px 48px 120px; min-width: 0; }
/* Prose keeps a readable measure; anything *tabular* or widget-shaped
   (tables, code, the interactive explorers) spans the whole content column.
   Tables used to be capped at 68ch too, which on a 1600px shell left a
   700px void beside a 529px table whose cells wrapped JSON payloads over
   three lines — the widest content on the page was the narrowest box. */
.content p, .content ul, .content ol { max-width: 68ch; }
.content ul, .content ol { color: var(--text-soft); padding-left: 22px; }
.content li { margin: 4px 0; }
.content li::marker { color: var(--text-faint); }
/* An inline <code> is regularly one unbreakable token — "POST
   /v1/documents/{documentId}/lifecycle" is 41 characters with nowhere to
   wrap — and on a 360px phone a single one of those used to push the whole
   document sideways. `break-word`, deliberately not `anywhere`: `anywhere`
   also lowers the min-content width fed to table layout, which let the memo
   table's Code column shrink until it broke "200" across two lines. Block
   code keeps its own scroll — white-space: pre ignores this anyway. */
.content code { overflow-wrap: break-word; }

.eyebrow {
  display: inline-block; font-size: 12px; font-weight: 600;
  color: var(--accent); letter-spacing: 0.05em; text-transform: uppercase;
  padding: 3px 10px; background: var(--accent-soft); border-radius: 999px;
  margin-bottom: 16px;
}

/* ---------- code column (sticky right) ---------- */
.code-col {
  position: sticky; top: var(--topbar-h);
  height: calc(100vh - var(--topbar-h));
  overflow-y: auto;
  border-left: 1px solid var(--border);
  padding: 24px 24px 80px;
  background: var(--bg-soft);
  scrollbar-width: thin;
}
.code-col::-webkit-scrollbar { width: 6px; }
.code-col::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
.code-col h5 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--text-muted); margin: 18px 0 8px; font-weight: 700;
}
.code-col h5:first-child { margin-top: 0; }

/* ---------- code blocks ---------- */
pre.code {
  margin: 0 0 16px; padding: 14px 16px;
  background: var(--bg-code);
  color: #e2e8f0;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.6;
  border-radius: var(--radius);
  overflow-x: auto;
  border: 1px solid var(--border);
  position: relative;
  tab-size: 2;
}
pre.code code { background: none; border: 0; padding: 0; color: inherit; font-size: inherit; }

.code-block {
  position: relative; margin: 0 0 16px;
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; background: var(--bg-code);
}
.code-head {
  display: flex; align-items: center;
  background: var(--bg-code-soft);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  padding: 4px 8px 4px 4px;
  font-size: 12px;
}
.code-tabs { display: flex; gap: 2px; flex: 1; overflow-x: auto; }
.code-tab {
  padding: 6px 10px; border-radius: 5px;
  color: #94a3b8; cursor: pointer; border: 0; background: transparent;
  font-family: var(--font-sans); font-size: 12px; font-weight: 500;
  white-space: nowrap;
}
.code-tab:hover { color: #e2e8f0; background: rgba(255,255,255,0.04); }
.code-tab.active { color: #fff; background: rgba(255,255,255,0.1); }
.code-copy {
  padding: 5px 9px; background: transparent; border: 1px solid rgba(255,255,255,0.12);
  color: #94a3b8; border-radius: 5px; font-size: 11px; cursor: pointer;
  font-family: var(--font-sans); font-weight: 500;
  display: flex; align-items: center; gap: 5px;
  transition: all 0.15s;
}
.code-copy:hover { color: #fff; background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.2); }
.code-copy.copied { color: #34d399; border-color: #065f46; background: rgba(6,95,70,0.2); }
.code-copy svg { width: 12px; height: 12px; }
.code-block pre { margin: 0; padding: 14px 16px; border: 0; border-radius: 0; background: var(--bg-code); }
.code-panes > pre:not([data-pane-active]) { display: none; }

/* Floating copy button for standalone <pre> blocks (curl/code samples
   scattered across the docs). The wrapper is injected by app.js so the
   button can be absolutely positioned relative to the pre. The wrapper
   carries the pre's bottom margin so block flow is unchanged. */
.pre-wrap { position: relative; margin: 0 0 16px; }
.pre-wrap > pre { margin-bottom: 0; }
.pre-copy {
  position: absolute; top: 8px; right: 8px;
  opacity: 0; pointer-events: none;
  background: rgba(15, 23, 42, 0.85);
  backdrop-filter: blur(4px);
}
.pre-wrap:hover .pre-copy,
.pre-copy:focus-visible,
.pre-copy.copied { opacity: 1; pointer-events: auto; }
@media (hover: none) {
  .pre-copy { opacity: 1; pointer-events: auto; }
}

/* Prism tokens — overrides for consistency */
/* #64748b gave 4.21:1 on the #05080f code background, under the 4.5:1 minimum,
   so code comments were the one thing left failing contrast. #707f95 is 4.92:1
   and still reads as a muted comment. */
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: #707f95; font-style: italic; }
.token.punctuation { color: #94a3b8; }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: #fbbf24; }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: #86efac; }
.token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string { color: #93c5fd; }
.token.atrule, .token.attr-value, .token.keyword { color: #c4b5fd; }
.token.function, .token.class-name { color: #f9a8d4; }
.token.regex, .token.important, .token.variable { color: #fdba74; }

/* ---------- method badges ---------- */
.method {
  display: inline-block; padding: 2px 7px;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.04em; border-radius: 4px; text-transform: uppercase;
  min-width: 46px; text-align: center;
}
.method.get    { color: var(--m-get);    background: color-mix(in srgb, var(--m-get)    12%, transparent); }
.method.post   { color: var(--m-post);   background: color-mix(in srgb, var(--m-post)   12%, transparent); }
.method.patch  { color: var(--m-patch);  background: color-mix(in srgb, var(--m-patch)  15%, transparent); }
.method.put    { color: var(--m-put);    background: color-mix(in srgb, var(--m-put)    12%, transparent); }
.method.delete { color: var(--m-delete); background: color-mix(in srgb, var(--m-delete) 12%, transparent); }

/* ---------- endpoint panels ---------- */
.endpoint {
  margin: 40px 0;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.endpoint:first-of-type { border-top: 0; padding-top: 0; }
.endpoint-path {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-mono); font-size: 14px;
  margin-bottom: 6px; color: var(--text);
  word-break: break-all;
}
/* endpoint-actions.js wraps the base + path in .url so they select as one
   string. Keep them in a single inline run: a flex gap between them would put
   whitespace in the middle of a copied URL. */
.endpoint-path .url { display: inline; min-width: 0; word-break: break-all; }
/* The base collapses to a "\22EF" chip: every endpoint on the page shares the
   same host, and spelling it out on each line buried the part that differs.
   Hover or focus the chip to expand it in place, click it to copy the absolute
   URL; the full URL is also the .url title, and endpoint-actions.js rewrites
   the clipboard so a copied line always carries its host. */
.endpoint-path .base {
  display: inline-flex; align-items: baseline;
  color: var(--text-muted); font-weight: 400;
  cursor: pointer; border-radius: 6px;
}
.endpoint-path .base::before {
  content: "\22EF";
  display: inline-block; overflow: hidden;
  max-width: 3em; padding: 0 5px;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg-soft);
  font-size: 0.85em; line-height: 1.4;
  transition: max-width 160ms ease, padding 160ms ease, opacity 120ms ease;
}
.endpoint-path .base-text {
  display: inline-block; max-width: 0; overflow: hidden;
  white-space: nowrap; opacity: 0;
  transition: max-width 200ms ease, opacity 160ms ease;
}
.endpoint-path .base:hover::before,
.endpoint-path .base:focus-visible::before,
.endpoint-path .base.is-open::before {
  max-width: 0; padding: 0; opacity: 0; border-color: transparent;
}
.endpoint-path .base:hover .base-text,
.endpoint-path .base:focus-visible .base-text,
.endpoint-path .base.is-open .base-text {
  /* Capped at the line width as well as at 32em: an expanded host must never
     be wider than its container, or the whole page scrolls sideways on a
     phone. The path wraps to the next line instead. */
  max-width: min(32em, 100%); opacity: 1;
}
.endpoint-path .base:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.endpoint-path .base.is-copied::after { content: "\2713"; color: var(--success); margin-left: 6px; font-size: 0.85em; }
.endpoint-path .base.is-failed::after { content: "\26A0"; color: var(--danger); margin-left: 6px; font-size: 0.85em; }
@media (prefers-reduced-motion: reduce) {
  .endpoint-path .base::before,
  .endpoint-path .base-text { transition: none; }
}
.endpoint-path .path { font-weight: 500; }
.endpoint-title { margin: 0 0 6px; font-size: 22px; }
.endpoint-desc { color: var(--text-soft); margin-bottom: 20px; max-width: 68ch; }

/* ---------- params / schema tables ---------- */
.params { list-style: none; padding: 0; margin: 0 0 24px; border-top: 1px solid var(--border); }
.param {
  padding: 14px 0; border-bottom: 1px solid var(--border);
  display: grid;
  /* minmax(0, 1fr), not the implicit `auto` track: an `auto` track grows to
     the widest min-content among its items, and a param whose description
     carries a code block ("to": "registration:91110302621705062U@CN…") grew
     the row to 414px inside a 254px column — the row, and with it the whole
     document, scrolled sideways on every phone. A 0-floor track lets the
     code block scroll inside its own box instead. */
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
}
.param-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* A flex item's automatic minimum size is its min-content, and these are
   single mono tokens (documentTypeCode, transmissionMethod) with no break
   opportunity — so on a phone they overflowed the row they sit in. Let them
   shrink and break; a wrapped identifier beats a sideways-scrolling page. */
.param-head > * { min-width: 0; }
.param-name { font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.param-type { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-muted); overflow-wrap: anywhere; }
.param-flag {
  font-size: 10.5px; font-weight: 600; padding: 1px 7px; border-radius: 4px;
  letter-spacing: 0.03em; text-transform: uppercase;
}
.param-flag.required { color: var(--danger); background: var(--danger-soft); }
.param-flag.optional { color: var(--text-muted); background: var(--bg-muted); border: 1px solid var(--border); }
.param-flag.deprecated { color: var(--warning); background: var(--warning-soft); }
.param-desc { font-size: 13.5px; color: var(--text-soft); margin: 0; max-width: 68ch; }
.param-desc code { font-size: 12px; }
.param-enum { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.param-enum code { font-size: 11.5px; }
.param-children { margin-top: 10px; padding-left: 14px; border-left: 2px solid var(--border); }

/* ---------- collapsible nested params (expand / fold) ---------- */
/* param-interactive.js tags every .param that has a nested object schema with
   .has-children and injects a .param-toggle caret into its head. Default state
   is expanded so all fields stay visible/scannable; click to fold. */
.param.has-children > .param-head { cursor: pointer; }
.param-toggle {
  appearance: none; -webkit-appearance: none; background: none; border: 0;
  padding: 0; margin: 0 2px 0 -2px; width: 14px; height: 14px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted); cursor: pointer; transition: transform .15s ease;
}
.param-toggle svg { width: 11px; height: 11px; }
.param-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.param.has-children > .param-head:hover .param-toggle { color: var(--text); }
.param.collapsed > .param-head .param-toggle { transform: rotate(-90deg); }
.param.collapsed > .param-children { display: none; }
/* breadcrumb hint that a folded row hides nested fields */
.param.has-children.collapsed > .param-head .param-type::after {
  content: " · " attr(data-folded-count) " fields"; color: var(--text-muted); font-style: italic;
}

/* ---------- callouts ---------- */
.callout {
  margin: 20px 0; padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  background: var(--bg-soft);
  font-size: 14px;
  color: var(--text-soft);
}
.callout > :last-child { margin-bottom: 0; }
.callout.info    { border-left-color: var(--info);    background: color-mix(in srgb, var(--info)    7%, var(--bg-soft)); }
.callout.warn    { border-left-color: var(--warning); background: color-mix(in srgb, var(--warning) 7%, var(--bg-soft)); }
.callout.success { border-left-color: var(--success); background: color-mix(in srgb, var(--success) 7%, var(--bg-soft)); }
.callout.danger  { border-left-color: var(--danger);  background: color-mix(in srgb, var(--danger)  7%, var(--bg-soft)); }
.callout-title { font-weight: 600; color: var(--text); margin-bottom: 4px; display: flex; align-items: center; gap: 8px; }

/* ---------- tables ---------- */
.content table {
  width: 100%; border-collapse: collapse;
  font-size: 14px; margin: 16px 0 24px;
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden;
}

/* A table cannot be laid out narrower than its own min-content width, so a
   7-column matrix (the FR lifecycle referential, the country tables) used to
   push the *whole page* sideways on any viewport under ~1050px: both the
   table and the topbar ran off the right edge and the body grew a horizontal
   scrollbar. app.js wraps every content table in .table-scroll, so the table
   scrolls inside its own box at every width while still stretching to fill
   the column when there is room. */
.table-scroll {
  max-width: 100%;
  margin: 16px 0 24px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Reaching the end of a table must not start scrolling the page behind it. */
  overscroll-behavior-x: contain;
}
.table-scroll > table { margin: 0; }
/* app.js makes a wrapper focusable only while it actually has hidden columns,
   so the focus ring here always means "these are the arrow keys you want". */
.table-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* No-JS fallback for the same problem: the table itself becomes the scroll
   box. It shrink-wraps to its content instead of filling the column, which is
   why the wrapper above is the preferred path. */
.content table:not(.table-scroll > table) {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.content th {
  text-align: left; font-weight: 600; color: var(--text);
  background: var(--bg-soft); padding: 10px 14px; font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.content td {
  padding: 10px 14px; color: var(--text-soft);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.content tr:last-child td { border-bottom: 0; }
.content td code { font-size: 12px; }

/* ---------- responses ---------- */
.response-tabs { display: flex; gap: 4px; margin-bottom: 8px; }
.response-tab {
  padding: 4px 10px; font-size: 11.5px; font-weight: 600;
  font-family: var(--font-mono); border-radius: 5px;
  color: var(--text-muted); background: var(--bg-muted);
  border: 1px solid var(--border); cursor: pointer;
}
.response-tab:hover { color: var(--text); }
.response-tab.active { color: var(--text); background: var(--bg); border-color: var(--border-strong); }
.response-tab.success { color: var(--success); }
.response-tab.success.active { background: var(--success-soft); border-color: var(--success); }
.response-tab.error   { color: var(--danger); }
.response-tab.error.active { background: var(--danger-soft); border-color: var(--danger); }

/* ---------- command palette ---------- */
.cmdk-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(10, 14, 26, 0.6);
  backdrop-filter: blur(4px);
  display: none;
  align-items: flex-start; justify-content: center;
  padding-top: 12vh;
}
.cmdk-backdrop.open { display: flex; }
.cmdk {
  width: min(680px, 92vw);
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: var(--shadow-lg);
  overflow: hidden; display: flex; flex-direction: column;
  max-height: 70vh;
}
.cmdk-input-wrap { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.cmdk-input-wrap svg { width: 18px; height: 18px; color: var(--text-muted); flex-shrink: 0; }
.cmdk-input {
  flex: 1; border: 0; background: transparent; outline: none;
  color: var(--text); font-size: 16px; font-family: inherit;
  /* type="search" (for the mobile keyboard's Go key) otherwise inherits
     WebKit's searchfield chrome — its own border, inset and clear button.
     16px is also the threshold below which iOS Safari zooms on focus. */
  appearance: none; -webkit-appearance: none; min-width: 0;
}
.cmdk-input::-webkit-search-decoration,
.cmdk-input::-webkit-search-cancel-button { -webkit-appearance: none; }
.cmdk-input::placeholder { color: var(--text-muted); }
.cmdk-results { overflow-y: auto; padding: 8px; }
.cmdk-group-title {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--text-muted); padding: 10px 10px 4px;
}
.cmdk-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px; cursor: pointer;
  color: var(--text-soft); font-size: 14px;
}
.cmdk-item:hover, .cmdk-item.sel { background: var(--bg-muted); color: var(--text); }
.cmdk-item .desc { font-size: 12px; color: var(--text-muted); margin-left: auto; }
.cmdk-empty { padding: 24px; text-align: center; color: var(--text-muted); font-size: 14px; }
/* The ESC affordance is a real button, not a decorative hint: on a phone there
   is no Escape key, and a near-full-height palette leaves almost no backdrop
   left to tap outside of. It keeps the .kbd class, and there is deliberately no
   `font:` reset here — .kbd's own mono family and 11px size both beat the UA's
   button font, so the chip renders exactly as the <span> it replaced did. */
.cmdk-close { cursor: pointer; flex-shrink: 0; line-height: 1.4; }
.cmdk-close:hover { color: var(--text); border-color: var(--border-strong); }

/* Phone palette. The desktop dialog floats 12vh down the viewport and caps at
   70vh, which on a phone leaves a ~250px results list with the on-screen
   keyboard over the bottom half of it. Here it starts just below the topbar and
   stretches to whatever height the viewport actually has — no vh maths, so the
   browser's own collapsing chrome is never double-counted. */
@media (max-width: 620px) {
  .cmdk-backdrop { padding: calc(var(--topbar-h) + 8px) 8px 8px; align-items: stretch; }
  .cmdk { width: 100%; max-height: none; }
  .cmdk-input-wrap { padding: 12px 14px; }
  .cmdk-results { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  /* Titles win the row; the description drops to its own line rather than
     being squeezed to a couple of characters by `margin-left: auto`. */
  .cmdk-item { flex-wrap: wrap; row-gap: 2px; padding: 10px; }
  .cmdk-item .desc { margin-left: 0; flex-basis: 100%; }
  .cmdk-item .method { flex-shrink: 0; }
  /* The chip itself stays a 32x21 keycap — it reads as one, and blowing it up
     would make the header look like it has a second button in it. Grow the hit
     area instead, to a 44px square, so it is a thumb target rather than a
     keycap you have to aim at. */
  .cmdk-close { position: relative; }
  .cmdk-close::after { content: ''; position: absolute; inset: -12px -6px; }
}

/* ---------- footer ---------- */
.footer {
  border-top: 1px solid var(--border);
  padding: 40px 24px; margin-top: 80px;
  font-size: 13px; color: var(--text-muted);
  text-align: center;
}
.footer a { color: var(--text-soft); }

/* ---------- landing page specifics ---------- */
.hero {
  padding: 80px 24px 60px;
  text-align: center;
  max-width: 860px; margin: 0 auto;
}
.hero h1 {
  font-size: 56px; font-weight: 720; letter-spacing: -0.035em;
  line-height: 1.05; margin-bottom: 18px;
  background: linear-gradient(180deg, var(--text) 35%, color-mix(in srgb, var(--text) 55%, var(--accent)) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.hero p { font-size: 19px; color: var(--text-soft); max-width: 640px; margin: 0 auto 32px; }
.hero-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.btn-primary {
  padding: 11px 20px; font-weight: 600; font-size: 14px;
  background: var(--accent-solid); color: white; border-radius: 8px; border: 0; cursor: pointer;
  box-shadow: 0 1px 2px rgba(109,40,217,0.3), 0 2px 8px rgba(109,40,217,0.15);
}
.btn-primary:hover { background: var(--accent-solid-hover); color: white; text-decoration: none; }
.btn-secondary {
  padding: 11px 20px; font-weight: 600; font-size: 14px;
  background: var(--bg-soft); color: var(--text); border: 1px solid var(--border-strong); border-radius: 8px; cursor: pointer;
}
.btn-secondary:hover { background: var(--bg-muted); text-decoration: none; color: var(--text); }

.feature-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px; max-width: 1120px; margin: 40px auto; padding: 0 24px;
}
.feature-card {
  padding: 24px; background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: var(--radius-lg); transition: all 0.2s;
}
.feature-card:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow); }
.feature-icon {
  width: 36px; height: 36px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
  margin-bottom: 14px;
}
.feature-icon svg { width: 18px; height: 18px; }
.feature-card h3 { margin: 0 0 6px; font-size: 16px; }
.feature-card p { margin: 0; font-size: 14px; color: var(--text-soft); }

.section { padding: 64px 24px; max-width: 1120px; margin: 0 auto; }
.section-lead { max-width: 720px; margin: 0 auto 40px; text-align: center; }
.section-lead h2 { border-top: 0; padding-top: 0; margin-top: 0; font-size: 32px; letter-spacing: -0.02em; }
.section-lead p { color: var(--text-soft); font-size: 17px; }

.split {
  display: grid; grid-template-columns: 1fr 1fr; gap: 32px; align-items: center;
}
.split-code { background: var(--bg-code); border-radius: var(--radius-lg); padding: 20px; font-size: 13px; }

/* ---------- badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600;
  border: 1px solid var(--border);
  background: var(--bg-soft); color: var(--text-soft);
}
.badge.new { color: var(--success); background: var(--success-soft); border-color: color-mix(in srgb, var(--success) 30%, transparent); }
.badge.beta { color: var(--warning); background: var(--warning-soft); border-color: color-mix(in srgb, var(--warning) 30%, transparent); }
.badge.deprecated { color: var(--danger); background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }

/* ---------- steps ---------- */
.steps { counter-reset: step; padding: 0; list-style: none; margin: 24px 0; }
.steps > li {
  counter-increment: step; position: relative;
  padding-left: 44px; padding-bottom: 24px;
  border-left: 2px solid var(--border); margin-left: 14px;
}
.steps > li:last-child { border-left-color: transparent; }
.steps > li::before {
  content: counter(step);
  position: absolute; left: -15px; top: -2px;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent); color: white;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700;
  border: 4px solid var(--bg);
}
.steps h3 { margin-top: 0; }

/* ---------- anchor link ---------- */
.anchor {
  margin-left: 8px; opacity: 0; color: var(--text-faint);
  font-size: 0.9em; transition: opacity 0.15s;
}
/* app.js appends the anchor straight after the heading text, with no space to
   break at, so on a 320px screen a full-width heading pushed its (invisible)
   "#" past the viewport and the page scrolled. break-word gives the line a
   break opportunity there — and lets a long compound heading word wrap
   instead of overflowing. */
.content h1, .content h2, .content h3, .content h4 { overflow-wrap: break-word; }
h1:hover .anchor, h2:hover .anchor, h3:hover .anchor, h4:hover .anchor { opacity: 1; }

/* ---------- per-endpoint CTAs (Try in Playground / Copy curl / Permalink) ---------- */
.endpoint-actions { user-select: none; }
.endpoint-cta {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  background: var(--bg); color: var(--text-soft);
  border: 1px solid var(--border); border-radius: 7px;
  cursor: pointer; text-decoration: none;
  transition: all 0.15s;
  white-space: nowrap;
}
.endpoint-cta:hover {
  background: var(--bg-muted); color: var(--text);
  border-color: var(--border-strong); text-decoration: none;
}
.endpoint-cta.primary {
  background: var(--accent); color: white; border-color: var(--accent);
}
.endpoint-cta.primary:hover {
  background: var(--accent-hover); border-color: var(--accent-hover); color: white;
}

/* ---------- per-endpoint 2-col grid ---------- */
.endpoint-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 500px);
  gap: 48px;
  align-items: start;
}
.endpoint-layout > .endpoint-prose { min-width: 0; }
.endpoint-layout > .endpoint-code { min-width: 0; position: sticky; top: calc(var(--topbar-h) + 24px); }
@media (max-width: 1180px) {
  .endpoint-layout { grid-template-columns: 1fr; gap: 16px; }
  .endpoint-layout > .endpoint-code { position: static; }
}

/* When the page-level try-it rail is active (added by reference-dock.js
   on viewports >= 1241px), the per-endpoint 2-col layout has no room
   to breathe — the rail already shows the live code + response panel.
   Stack prose + code samples vertically so the prose can use the full
   content-column width. The static code samples stay useful as a
   reference for the per-language tabs (cURL/Python/Node/Go). */
body.has-tryit-rail .endpoint-layout { grid-template-columns: 1fr; gap: 24px; }
body.has-tryit-rail .endpoint-layout > .endpoint-code { position: static; }

.content.reference { max-width: none; padding-right: 48px; }
.content.reference p, .content.reference ul, .content.reference ol { max-width: none; }

/* object schema cards */
.object-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-soft);
  padding: 14px 18px;
  margin: 16px 0 24px;
}
.object-card-title {
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em;
  margin-bottom: 4px;
}
.object-card > h3 { margin: 0 0 10px; font-size: 16px; }

.inline-path { font-family: var(--font-mono); font-size: 13.5px; color: var(--text); }

.toc {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 8px 20px; list-style: none; padding: 0;
  margin: 20px 0 32px;
}
.toc a {
  display: block; padding: 6px 10px; border-radius: 6px;
  font-size: 13.5px; color: var(--text-soft);
  border-left: 2px solid var(--border);
}
.toc a:hover { color: var(--accent); background: var(--bg-muted); text-decoration: none; border-left-color: var(--accent); }
/* The reference's section map (scripts/build_reference_index.py): every
   section, with how many endpoints are in it. */
.toc-sections a { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.toc-count {
  flex: none; font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--text-muted); background: var(--bg-muted);
  padding: 1px 6px; border-radius: 999px;
}
.toc a:hover .toc-count { color: var(--accent); }

/* ---------- code-rail: sticky try-it panel on reference.html ---------- */
.code-rail {
  position: sticky;
  top: var(--topbar-h);
  height: calc(100vh - var(--topbar-h));
  border-left: 1px solid var(--border);
  background: var(--bg-muted);
  display: flex; flex-direction: column;
  overflow: hidden;
}
/* When the rail is active the page grid uses --code-w. The default
   460px was visibly too wide on 1366px laptops (rail dominated the
   page); 400px gives the docs column more breathing room while still
   fitting the (now single-column) embedded Playground. */
body.has-tryit-rail { --code-w: 400px; }
.code-rail .rail-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-soft);
}
.code-rail .rail-method {
  display: inline-block; padding: 2px 8px; border-radius: 4px;
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-size: 11px; font-weight: 700; color: white;
}
.code-rail .rail-method.get    { background: #16a34a; }
.code-rail .rail-method.post   { background: #2563eb; }
.code-rail .rail-method.put    { background: #ea580c; }
.code-rail .rail-method.patch  { background: #ea580c; }
.code-rail .rail-method.delete { background: #dc2626; }
.code-rail .rail-path {
  flex: 1; min-width: 0;
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-size: 12.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.code-rail .rail-popout {
  font-size: 11px; color: var(--text-muted);
  text-decoration: underline;
}
.code-rail iframe { flex: 1; width: 100%; border: 0; background: var(--bg); }
.code-rail .rail-empty {
  flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 20px; color: var(--text-muted); font-size: 13px; text-align: center;
}

/* ---------- mobile drawer ---------- */
@media (max-width: 1240px) {
  .shell:not(.shell--one) { grid-template-columns: var(--nav-w) minmax(0, 1fr); }
  .code-col { position: static; height: auto; border-left: 0; border-top: 1px solid var(--border); padding: 32px 24px; }
  .shell { grid-template-rows: auto auto; }
  .code-col { grid-column: 2 / 3; }
  /* Below 1240px the rail collapses — fall back to slide-up dock. */
  .code-rail { display: none; }
}
/* < 1000, part two — the drawer half of the rung declared up in the topbar
   ladder. With .topnav hidden from 1000px down, the hamburger drawer is the
   only way to the other sections, so the sidebar has to go off-canvas at the
   same width the nav moves into it. */
@media (max-width: 999px) {
  .menu-toggle { display: grid; }
  /* Match the specificity of the .shell:not(.shell--one) rule in the 1240px
     query above, otherwise it wins and the off-canvas sidebar's grid track
     traps .content in a narrow nav-width column. */
  .shell:not(.shell--one) { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; top: var(--topbar-h); left: 0; z-index: 30;
    width: 280px; background: var(--bg);
    transform: translateX(-100%); transition: transform 0.2s;
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar--drawer-only { display: block; }
  .sidebar-sitenav {
    display: block; margin-bottom: 18px;
    padding-bottom: 14px; border-bottom: 1px solid var(--border);
  }
  .code-col { grid-column: 1 / -1; }
}

/* < 861 — phone layout. The topnav, the drawer and the off-canvas sidebar all
   moved up to the 1000px rung; what is left here is the typography and padding
   pass. */
@media (max-width: 860px) {
  :root { --nav-w: 260px; }
  /* The trigger has been its 36px magnifier since the 1500px rung. Round it up
     to a 40px square here: on a phone it is the only way into search, and it
     sits between two other tap targets in the topbar. (It used to be given
     `width: 160px` at this width, which was dead — the 1000px rung had already
     set `display: none` and nothing turned it back on.) */
  .search-trigger { width: 40px; max-width: 40px; height: 40px; justify-content: center; padding: 0; }
  .content { padding: 28px 22px 80px; }
  /* Reference pages set an asymmetric padding-right: 48px (specificity 0,2,0)
     that survives the mobile .content override above and leaves a lopsided
     right margin on phones. Reset it to match the mobile left padding. */
  .content.reference { padding-right: 22px; }
  .hero { padding: 48px 22px 40px; }
  .hero h1 { font-size: 38px; }
  .split { grid-template-columns: 1fr; }
}

/* < 401 — the smallest phones still in the wild (iPhone SE 1st gen at 320px).
   The topbar there is hamburger + mark + search + language + session with
   nothing left to drop: search is the entry point this rung exists to protect,
   and the session pill is the only thing that says which environment you are
   about to fire a request at. So buy the last few pixels back from the bar's
   own padding and gaps instead — at 320px the 20px/16px rhythm overflowed by
   3px once the search button was no longer being hidden here. */
@media (max-width: 400px) {
  .topbar { padding: 0 14px; gap: 10px; }
}

/* ---------- compliance pages ---------- */
p.lead {
  font-size: 17px;
  line-height: 1.55;
  color: var(--text-soft);
  margin: 0 0 24px;
  max-width: 80ch;
}
.callout-pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
  margin-left: 8px;
}
.callout-pill.success { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.callout-pill.warn    { background: color-mix(in srgb, var(--warning) 14%, transparent); color: var(--warning); }
.callout-pill.info    { background: color-mix(in srgb, var(--info)    14%, transparent); color: var(--info); }
.callout-pill.danger  { background: color-mix(in srgb, var(--danger)  14%, transparent); color: var(--danger); }
table.matrix { font-size: 13.5px; }
table.matrix th, table.matrix td { vertical-align: top; }
table.matrix td a { white-space: nowrap; }

/* ---------- twemoji-rendered flag images ----------
   Twitter's open emoji set. Every flag and other emoji glyph in the body
   gets replaced with an SVG <img class="emoji">. Sized to the surrounding
   text so the layout doesn't shift. */
img.emoji {
  height: 1em;
  width: 1em;
  margin: 0 0.05em 0 0.1em;
  vertical-align: -0.1em;
  display: inline-block;
}

/* ---------- sortable tables ---------- */
th.sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
}
th.sortable:hover { background: var(--bg-soft); }
th.sortable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
th.sortable .sort-arrow {
  display: inline-block;
  font-size: 0.85em;
  opacity: 0.55;
  margin-left: 4px;
  font-family: var(--font-mono);
}
th.sortable[aria-sort="ascending"] .sort-arrow,
th.sortable[aria-sort="descending"] .sort-arrow {
  opacity: 1;
  color: var(--accent);
}

/* ---------- mandate timeline ----------
   Shown on docs/compliance/index.html. Each row is one country; the bar is
   a rough span of mandate phasing, individual markers are colored dots at
   key dates. Years are a header row. Pure CSS Grid — no chart library.
*/
.timeline {
  margin: 24px 0 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-soft);
  padding: 16px;
  overflow-x: auto;
}
.timeline-controls {
  display: flex;
  gap: 8px;
  align-items: center;
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.timeline-legend { display: inline-flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.timeline-legend span { display: inline-flex; align-items: center; gap: 4px; }
.timeline-legend .dot {
  width: 10px; height: 10px; border-radius: 50%; display: inline-block;
}
.timeline-legend .dot.live    { background: var(--success); }
.timeline-legend .dot.phasing { background: var(--warning); }
.timeline-legend .dot.future  { background: var(--info); }
.timeline-legend .dot.now     { background: var(--accent); }

.timeline-grid {
  display: grid;
  /* Sticky country column (left) + 17 year columns (2014..2030).
     min-content for label, equal-fr for year cells. */
  grid-template-columns: 200px repeat(17, minmax(48px, 1fr));
  align-items: center;
  font-size: 12px;
  min-width: 1100px;
}
.timeline-grid > .yr-head {
  font-family: var(--font-mono);
  font-weight: 600;
  text-align: center;
  border-bottom: 1px solid var(--border);
  padding: 4px 0;
  color: var(--text-muted);
  position: relative;
}
.timeline-grid > .yr-head.now {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.timeline-grid > .yr-head.now::after {
  content: "now";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-size: 10px;
  color: var(--accent);
  background: var(--bg-soft);
  padding: 0 4px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.timeline-grid > .row-label {
  padding: 6px 8px 6px 0;
  font-size: 12.5px;
  border-bottom: 1px dashed var(--border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: sticky;
  left: 0;
  background: var(--bg-soft);
  z-index: 1;
}
.timeline-grid > .row-label a { color: inherit; text-decoration: none; }
.timeline-grid > .row-label a:hover { color: var(--accent); }
.timeline-grid > .row-cell {
  height: 100%;
  border-bottom: 1px dashed var(--border);
  border-left: 1px dashed transparent;
  position: relative;
  min-height: 30px;
}
.timeline-grid > .row-cell.tick { border-left-color: var(--border); }
.timeline-grid > .row-cell.now-col { background: color-mix(in srgb, var(--accent) 5%, transparent); }
.timeline-marker {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 12px;
  height: 12px;
  border-radius: 50%;
  cursor: help;
  z-index: 2;
  border: 2px solid var(--bg);
  box-shadow: 0 0 0 1px var(--border);
}
.timeline-marker.live    { background: var(--success); }
.timeline-marker.phasing { background: var(--warning); }
.timeline-marker.future  { background: var(--info); }
.timeline-marker:hover, .timeline-marker:focus {
  transform: translate(-50%, -50%) scale(1.4);
  outline: none;
}
.timeline-marker[data-when][title]:hover::after {
  content: attr(title);
  position: absolute;
  bottom: 130%;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 11px;
  white-space: nowrap;
  pointer-events: none;
  font-family: var(--font-mono);
  z-index: 10;
}

.timeline-list {
  margin-top: 16px;
  border-top: 1px solid var(--border);
  padding-top: 16px;
}
.timeline-list table th, .timeline-list table td { padding: 6px 10px; }
.timeline-list table td.date { font-family: var(--font-mono); white-space: nowrap; }

/* ---------- print ---------- */
@media print {
  .topbar, .sidebar, .code-col, .cmdk-backdrop { display: none; }
  .shell { grid-template-columns: 1fr; }
  .content { padding: 0; max-width: 100%; }
  /* On paper there is nothing to scroll: a clipped table is a lost table. Let
     it print at whatever width it needs and take the overflow on the page. */
  .table-scroll { overflow: visible; }
}

/* Use-case payload tester — reference/document-types.html.
   Progressive-enhancement toolbar (.uc-actions) is injected by
   assets/usecase-tester.js after each example's <pre>. */
.uc-lib { margin: 18px 0 8px; display: flex; flex-direction: column; gap: 10px; }
.uc-case {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-soft);
  padding: 2px 16px;
}
.uc-case > summary {
  cursor: pointer;
  font-weight: 600;
  padding: 12px 0;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 10px;
}
.uc-case > summary::-webkit-details-marker { display: none; }
.uc-case > summary::before {
  content: "\25B8";
  color: var(--text-faint);
  transition: transform .15s ease;
}
.uc-case[open] > summary::before { transform: rotate(90deg); }
.uc-badge {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 4px;
  padding: 1px 7px;
}
.uc-note { color: var(--text-muted); margin: 0 0 10px; }
.uc-actions { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 16px; }

/* Kept in the DOM, out of the visual design. The banner landmark duplicates the
   main navigation below it: sighted users get the real nav, while crawlers and
   assistive tech still see a plain, JS-free list of the top-level sections.
   Not display:none — that would drop it from the accessibility tree too.
   Revealed on focus so a keyboard user never lands on an invisible link. */
.visually-hidden:not(:focus-within) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Links inside running text carry an underline, not colour alone.
   The accent against body text is 1.26:1 — far below the 3:1 needed for colour
   to be the sole signal — so anyone with reduced colour vision could not tell
   these were links. An underline is independent of hue and fixes it outright.
   Scoped to prose: buttons and cards that happen to be anchors keep their own
   styling. */
main p a:not(.btn-primary):not(.btn-secondary):not(.cta):not(.feature-card) {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Touch targets reach the 24x24 CSS-pixel minimum (WCAG 2.2 target size).
   The handoff <summary> was 23.7px tall and the note link inside it 17.6px,
   both of which are awkward on a phone and fail the audit. */
#agent-handoff summary {
  min-height: 24px;
  align-items: center;
}
#agent-handoff summary a,
#agent-handoff details a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}
