/* ============================================================================
   Chief Of — shared base
   ----------------------------------------------------------------------------
   Tokens, reset, layout, nav, buttons and type scale. Extracted from the 33
   HTML files that each carried their own copy of this, which had already drifted.

   Design rules this file enforces. Rules 3-6 were rewritten during the visual
   refresh — see ops/design/REFRESH-PLAN.md for the measurements behind each.

     1. Orange (#FF4500) is NEVER body text. As a FILL it is legal two ways:
        with an --ink label at any size (5.49:1), or with a white label only at
        display sizes >=24px (3.44:1, which clears the large-text tier but fails
        AA for body copy). Italic emphasis inside h1/h2 is also legal.
     2. Text is the dark-grey family (--ink / --ink-soft / --muted) on light
        ground, or white on an ink or accent band.
     3. A fill must MEAN something — a category chip, an active state, a
        recommended tier, a band. Decoration is not a reason for a fill. What
        separates content is hairlines, alignment and whitespace, not boxes.
     4. Fills POLARIZE. Either a barely-there tint (--tint, luminance delta
        0.05 from white, and only on a full-bleed band) or fully committed
        (--surface-ink, or an accent band twice a page at most). The old pastel
        sat at delta 0.19 — the muddy middle — and was applied 238 times.
     5. Figtree carries every heading and all prose. --mono is a metadata layer
        only: eyebrows, chips, tags, stat captions, form labels, numeric values.
        Never prose. No serif anywhere.
     6. Full-bleed bands are how sections separate, and a dark band is legal in
        exactly two roles: governance/risk/security content, and the conversion
        band. A dark panel must be a full-bleed band, never a floating card in a
        light section, and the light-to-dark transition wants a mediating strip.

   Whitespace does the work a border used to: keep the gap BETWEEN modules
   2-3x the spacing INSIDE one (--section-y against --space-6).

   Palette: `chiefof` in ops/dither/palettes.json. Verified by
   `node ops/design/contrast.js`.

   Migration note: the legacy aliases this file used to carry are gone — every
   reference was rewritten onto the canonical tokens. signup.html is the one page
   that still loads neither this file nor logo.css; it is folded in at phase 5.
   ========================================================================== */

:root {
  /* ---- text: dark grey only ---- */
  --ink: #0F0F0F;        /* headlines and body copy — 19.17:1 on white */
  --ink-soft: #3D3D3D;   /* subheads and secondary copy — 10.86:1 */
  --muted: #5A5A5A;      /* eyebrows, small caps, meta — 6.90:1 */

  /* ---- surfaces ----
     Per rule 4 a fill is either almost invisible or fully committed. The two
     legal band fills are --tint and --surface-ink; --accent is the third, used
     twice a page at most. Nothing lives between them.

     Measured against the reference set: their faint tints sit 0.06-0.08 from
     the page ground in luminance and their committed panels sit at 0.95-1.0.
     Our old pastel sat at 0.19, which is why it read as boxy but timid. */
  --ground: #FFFFFF;       /* page background, everywhere */
  --tint: #FAF9F5;         /* warm paper, delta 0.053 — full-bleed bands only */
  --surface-ink: #121212;  /* committed dark band, delta 0.99 */

  /* Hairlines. --line is already in the right register: 1.27:1 against white,
     which matches the faintest rules in the reference set (1.24-1.47:1). It is
     under-used, not wrong — structure should lean on it far more. */
  --line: #E4E4E4;
  --line-strong: #C9C9C9;  /* 1.72:1 — for a rule that has to carry a table */

  /* Quiet action fill for secondary buttons. Not a card surface — it marks an
     action, so it is a legal fill under rule 3. */
  --btn-quiet: #EAEDF2;
  --btn-quiet-hover: #DCE1E9;

  /* The legacy pastels (--surface, --surface-warm, --surface-cool) are gone.
     All 238 .card/.panel instances that used them have been converted to
     lattices, hairline lists, figures and bands. A fill is now either --tint on
     a full-bleed band, --surface-ink, --accent, or a semantic chip. */

  /* ---- accent ----
     Orange is a FILL colour and a display-emphasis colour, never body text,
     never a label, never an eyebrow. Measured on white: the orange itself is
     3.44:1, --ink on orange is 5.49:1, white on orange is 3.44:1.

     So the three legal uses are:
       - italic emphasis inside h1/h2 (>=24px clears the 3:1 large-text tier)
       - a fill with an --ink label, at any size
       - a fill with a WHITE label at display sizes only (>=24px), which is why
         reversed-out type on an accent band is legal and the same thing at body
         size is not. */
  --accent: #FF4500;
  --accent-quiet: #FFE8E0; /* orange at band strength — a wash, not a pastel card */

  /* ---- reintroduced brand accents ----
     These predate the refresh and were dropped; Callen wants them back, used as
     sparingly as orange. Blue is the PRODUCT-UI accent — live/active states and
     callouts inside the artifact windows, and the .callout component — which
     keeps orange for the marketing brand and blue for "this is the app", so the
     two never fight. --accent-blue is a pale tint, so it always takes an --ink
     label (ink clears >14:1; white would be ~1.2:1 and is never used on it).
     --accent-blue-quiet is the even-paler wash. Pale yellow is a highlight only —
     a highlighter pass over a chosen row, never a surface. */
  --accent-blue: #C4EDFF;
  --accent-blue-quiet: #E1F5FE;
  --accent-yellow: #FFFDE6;

  /* ---- type ---- */
  --sans: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  /* Rule 5: metadata only. A system stack for now so it costs no extra request;
     swapping in a webfont later is this one line plus the <head> link. */
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

  /* Few steps, wide gaps. The jump from body to h2 IS the hierarchy — that is
     what lets a section hold together with no box around it. */
  --step-display: clamp(2.4rem, 4.8vw, 3.9rem);
  --step-h2: clamp(1.75rem, 2.8vw, 2.5rem);
  --step-stat: clamp(2.2rem, 3.2vw, 2.8rem); /* prices and stat numerals */
  --step-h3: 1.2rem;
  --step-body-lg: 1.06rem;
  --step-body: 1rem;
  --step-small: 0.92rem;
  --step-micro: 0.82rem;  /* legal lines, captions, table meta */
  --step-eyebrow: 0.72rem;

  /* Measures. Type is held short deliberately — a narrow column enforces its
     own line length without anyone remembering a max-width. */
  --measure-prose: 62ch;
  --measure-lede: 52ch;

  /* ---- rhythm ---- */
  --gutter: 24px;
  --measure: 1320px;
  /* The tool pages are form-shaped and read better narrower. This was a magic
     1100px declared twice in css/tools.css; it is one token now. */
  --measure-narrow: 1100px;
  --section-y: clamp(64px, 8vw, 112px);

  /* One scale. ~200 hardcoded gap/padding values are being migrated onto it. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;

  /* ---- radius: mapped to ROLE, not picked per component ----
     And per rule 6, a dark surface takes --radius-flat or --radius-pill only,
     never --radius-row, so light and dark objects differ by silhouette alone. */
  --radius-flat: 0;      /* large structural panels, bands, lattice cells */
  --radius-row: 4px;     /* interactive rows, inputs, small inner objects */
  --radius-panel: 12px;  /* image and artifact panels */
  --radius-pill: 999px;  /* buttons and chips */

  /* ---- motion ----
     Every reference site animates named properties at 0.15s on this curve.
     `transition: all` is banned — it repaints things you did not mean to move. */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast: 0.15s;
  --dur: 0.25s;
  --dur-slow: 0.4s;

  /* ---- deprecated radius aliases — phase 2 removes the components using them ---- */
  --radius: var(--radius-panel);
  --radius-lg: 20px;

  /* The legacy aliases (--navy, --cream, --text-mid, --border, --gold, --serif …)
     are gone. All 82 references were rewritten onto the canonical tokens above.
     signup.html still uses those names, but it declares its own palette and
     loads no base.css, so it is unaffected — it gets folded in at phase 5. */
}

/* The section rhythm is tuned for a wide viewport, where 8vw is real air. On a
   phone the clamp bottoms out at its 64px floor, which stacks to 128px of dead
   space between every pair of sections — a third of a screen. Overriding the
   token rather than the ~40 rules that consume it keeps one source of truth, so
   `section`, `.hero` and `.final-cta` all condense together.
   Measured on the homepage: section-to-section gaps of 134-193px become 90-125px. */
@media (max-width: 880px) {
  :root { --section-y: 52px; }
}
@media (max-width: 560px) {
  :root { --section-y: 44px; }
}

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

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

body {
  font-family: var(--sans);
  font-size: var(--step-body);
  color: var(--ink);
  background: var(--ground);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

/* Rule 4: this is the only width. Nothing escapes it. */
.container { max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter); }

/* ---------------------------------------------------------------- typography */

/* No generic <a> rule existed before this, so any inline text link in body
   copy (prose, FAQ answers, terms/privacy content) fell back to the
   browser's default link blue. Classed links (.nav-link, .btn-primary,
   .logo, etc.) all set their own color and win on specificity, so this only
   affects plain, unclassed links. */
/* Links are not underlined by default. Most links on the site are structural —
   nav, buttons, cards, CTAs — and underlining all of them (plus darkening on
   hover) read as noise. Genuine inline prose links keep an underline so they
   stay distinguishable inside body copy. */
a { color: var(--ink); text-decoration: none; }
.content a, article a, .lede a { text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 2px; }
.content a:hover, article a:hover, .lede a:hover { text-decoration-color: currentColor; }

/* Explicit on every level, not just h1/h2 — an h3/h4 nested in a card link
   (very common: the whole card is an <a>) otherwise falls back to the
   browser's default link-blue instead of inheriting ink. */
h1, h2, h3, h4 { font-family: var(--sans); line-height: 1.1; color: var(--ink); }

h1 {
  font-size: var(--step-display);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink);
}
h2 {
  font-size: var(--step-h2);
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--ink);
}
h3 { font-size: var(--step-h3); font-weight: 600; letter-spacing: -0.01em; line-height: 1.35; }

/* Rule 1, the one place orange is allowed as text. Display sizes only. */
h1 em, h2 em { font-style: italic; color: var(--accent); }

.eyebrow {
  font-size: var(--step-eyebrow);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 16px;
}

.lede { font-size: var(--step-body-lg); color: var(--ink-soft); line-height: 1.65; max-width: 62ch; }
h1 + .lede, h2 + .lede { margin-top: 16px; }

p { color: var(--ink-soft); }

h1 { margin-bottom: 20px; }
h1:last-child { margin-bottom: 0; }

/* The recurring hero button row (eyebrow → h1 → lede → buttons). Pages that
   need a different arrangement can still declare their own `.cta-group` —
   page-specific styles load after this file, so theirs wins. */
.cta-group { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }

/* Used near-identically on every FAQ section site-wide. Roughly half the
   pages that define their own max-width forgot to also center it, leaving a
   narrow question column stranded at the left edge of a 1320px section with
   nothing on the right to balance it. A page overriding max-width doesn't
   need to redeclare margin — this still applies underneath it. */
.faq-list { max-width: 760px; margin: 0 auto; }
/* Every current `.faq-list` lives inside `.anchored` now, whose own grid
   column already sizes it — this max-width was fighting that column instead
   of a bare `.container`, and on a wide viewport it silently shrank the
   closed `<details>` rows to less than the column width (the open row's
   longer answer content happened to size closer to the cap, so only the
   closed state looked broken). Cancelled here rather than deleted outright,
   in case `.faq-list` is ever used standalone again. */
.anchored .faq-list { max-width: none; margin: 0; }

/* -------------------------------------------------------------------- layout */

section { padding: var(--section-y) 0; background: var(--ground); }

/* The hero is a section immediately followed by another section, so full
   padding on both sides double-stacks into a much bigger gap than any other
   section boundary on the page. Halving the bottom side is the default for
   every inner-page hero; a page only needs its own `.hero` rule when it wants
   something more specific (the homepage removes the top side entirely, since
   the nav sits flush above its hero art). */
.hero { padding: var(--section-y) 0 calc(var(--section-y) * 0.6); }
/* .subtitle is retired. All 75 instances became `.section-head`, which puts the
   same copy in its own column beside the heading instead of stacked under it —
   the section-opening archetype now has one implementation, not one per page.
   Deliberately not kept as a fallback: nothing in the markup uses it, and a
   surviving rule would let it drift back in. */

/* .panel is retired along with .card. Emphasis is a full-bleed .band now (rules
   4 and 6), so a contained pastel block has no role left. Kept as spacing only,
   so stray markup degrades to bare type instead of inheriting a stale fill. */
.panel {
  background: none;
  border-radius: 0;
  padding: clamp(32px, 4vw, 56px) 0;
}

/* ----------------------------------------------------------------------- nav */

.site-nav { background: var(--ground); }
.site-nav .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 20px;
  padding-bottom: 20px;
}
/* The wordmark lives in css/logo.css, not here — it has to work on the 32 pages
   that cannot adopt this stylesheet yet, so it must not depend on these tokens.
   Link both files; logo.css reads --ink from here when present. */

.nav-links { display: flex; align-items: center; gap: 28px; }
.nav-links a.nav-link {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: var(--step-small);
  font-weight: 500;
  transition: color 0.18s;
}
.nav-links a.nav-link:hover { color: var(--ink); }

/* ------------------------------------------------------------------- buttons */

.btn-primary, .btn-ghost, .nav-cta {
  display: inline-block;
  font-family: var(--sans);
  font-size: var(--step-small);
  font-weight: 600;
  text-decoration: none;
  padding: 14px 26px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  transition: background 0.18s, color 0.18s, border-color 0.18s;
  white-space: nowrap;
}

/* The fill is ink; orange arrives on hover. An orange fill would need an --ink
   label, since white on orange is 3.44:1. */
.btn-primary { background: var(--ink); color: var(--ground); }
.btn-primary:hover { background: var(--accent); color: var(--ink); }

/* Secondary was a transparent pill with a --line border, which at 1.27:1 barely
   read as a control at all. It is a quiet FILL now — a fill is legal here because
   it marks an action, which is exactly what rule 3 asks of it. */
.btn-ghost { background: var(--btn-quiet); color: var(--ink); border-color: transparent; }
.btn-ghost:hover { background: var(--btn-quiet-hover); }

.nav-cta { padding: 10px 20px; background: transparent; color: var(--ink); border-color: var(--line); }
.nav-cta:hover { background: var(--ink); color: var(--ground); border-color: var(--ink); }

/* A filled chip is a legal orange use — the label is --ink, not white. */
.chip-accent {
  display: inline-block;
  background: var(--accent);
  color: var(--ink);
  font-size: var(--step-eyebrow);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
}

/* -------------------------------------------------------------------- cards */
/* .card is retired. It was a pastel fill applied 199 times as pure decoration,
   which rule 3 no longer permits. Use .lattice for a grid of cells,
   .hairline-list for rows, .figure for anything with art, or .band for a whole
   section. Kept as a no-op guard so stray markup degrades to bare type. */

.card { background: none; border: 0; border-radius: 0; padding: 0; }

/* --------------------------------------------------------------- final CTA */
/* The closing conversion band, centered. Every page puts its copy straight in
   `.container` (the old rule targeted a `.panel` wrapper no page actually
   used, so the band had been silently left-aligning everywhere). The homepage
   layers its own copy/button arrangement on top in its page CSS. */

.final-cta { background: var(--ground); padding: var(--section-y) 0; }
.final-cta .container { text-align: center; }
.final-cta h2 { margin-bottom: 12px; }
.final-cta p { max-width: 52ch; margin: 0 auto 28px; font-size: var(--step-body-lg); line-height: 1.6; }

/* ------------------------------------------------------------------ a11y */

/* Deliberately NOT wrapped in :where() — that gives zero specificity, so any
   component that touches `outline` silently wins and the ring disappears. This
   needs to beat component rules, so it keeps its own weight and uses !important
   for the outline itself. Components that want a different ring should override
   :focus-visible explicitly rather than setting `outline: none`. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ink) !important;
  outline-offset: 3px;
}

/* Pressed feedback. Nothing on the site had an :active state, so every button
   felt dead on click. Transform only — no layout, no repaint of neighbours. */
.btn-primary:active,
.btn-ghost:active,
.nav-cta:active,
button:not(:disabled):active {
  transform: translateY(1px);
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

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

/* nowrap keeps a button on one line, but a long label on a narrow screen has
   nowhere to go and pushes the page sideways. Below this width, let it wrap. */
@media (max-width: 560px) {
  .btn-primary, .btn-ghost, .nav-cta {
    white-space: normal;
    text-align: center;
    max-width: 100%;
  }

  /* Page-level CTAs go full-width and stack. Left to shrink-wrap they came out
     at 44-85% of the container depending on label length, so a column of them
     read as a ragged left edge with no shared alignment.
     Scoped to the CTA containers on purpose: the buttons inside the agent
     workbench and scenario widgets (.aw__toolbar, .aw__opts) are a simulated
     product UI, where a full-width button would misrepresent the interface. */
  .cta-group, .ctas, .scn-foot {
    flex-direction: column;
    align-items: stretch;
  }
  .cta-group > .btn-primary, .cta-group > .btn-ghost,
  .ctas > .btn-primary, .ctas > .btn-ghost,
  .scn-foot > .btn-primary, .scn-foot > .btn-ghost,
  .final-cta .container > .btn-primary,
  .plan > .btn-primary, .plan > .btn-ghost {
    display: block;
    width: 100%;
  }
  /* A centered hero row has nothing left to center once the buttons fill the
     width, and `justify-content` on a column axis would push them apart. */
  .hero--centered .cta-group { justify-content: flex-start; }
}

/* ------------------------------------------------------------- mobile nav */

/* Above 880px there is no drawer at all: the toggle and scrim are gone, and
   `display: contents` dissolves the drawer wrapper so .nav-links and .nav-cta
   remain direct flex items of the row. The desktop nav is byte-identical to the
   version before the drawer existed. */
.nav-toggle,
.nav-scrim,
.nav-branch,
.nav-back,
.nav-home { display: none; }
/* Above 880px the drawer and the root pane dissolve, so .nav-links stays a flex
   item of the row and the desktop bar is byte-identical to the version before
   any of this existed. The subpanes and the branch buttons are display:none up
   there — without that they would spill straight into the bar. */
.nav-drawer,
.nav-pane--root { display: contents; }
/* After the rule above, not merged into the display:none list before it — same
   specificity, so source order decides and this has to win. */
.nav-pane:not(.nav-pane--root) { display: none; }

@media (max-width: 880px) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 44px is the minimum comfortable touch target. */
    width: 44px; height: 44px;
    margin-left: auto;
    padding: 0;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    color: var(--ink);
    cursor: pointer;
    /* Above the drawer, so the bars morph into the X that closes it. */
    position: relative;
    z-index: 60;
  }
  .nav-toggle__bars,
  .nav-toggle__bars::before,
  .nav-toggle__bars::after {
    display: block;
    width: 18px; height: 1.5px;
    background: currentColor;
    transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
  }
  .nav-toggle__bars { position: relative; }
  .nav-toggle__bars::before,
  .nav-toggle__bars::after { content: ""; position: absolute; left: 0; }
  .nav-toggle__bars::before { top: -6px; }
  .nav-toggle__bars::after  { top: 6px; }

  /* Open: the middle bar drops out and the outer two cross into an X. */
  .site-nav.is-open .nav-toggle__bars { background: transparent; }
  .site-nav.is-open .nav-toggle__bars::before { transform: translateY(6px) rotate(45deg); }
  .site-nav.is-open .nav-toggle__bars::after  { transform: translateY(-6px) rotate(-45deg); }

  /* ---- the drawer ----
     Off-canvas to the right, full height, sliding in over the page. Capped so
     a sliver of the page stays visible on a phone (the drawer reads as a layer
     over the page rather than a new screen) but never wider than the viewport. */
  .nav-drawer {
    display: block;
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(340px, 82vw);
    z-index: 50;
    background: var(--ground);
    border-left: 1px solid var(--line);
    /* Only transform is animated — an off-canvas panel that animates width or
       left would relayout on every frame. The transition itself is withheld
       until .nav-ready (see below), so the initial jump to off-canvas when JS
       enhances the no-JS fallback does not animate into view on load. */
    transform: translateX(100%);
    /* visibility, not just the transform: a translated panel is still in the
       tab order, so without this the links stay keyboard-reachable while parked
       off-screen. It flips discretely at the end of the close. */
    visibility: hidden;
    /* The panes are absolutely positioned inside this box and scroll
       individually, so the drawer itself must not scroll — otherwise the pane
       waiting off to the right would drag out a horizontal scrollbar. */
    overflow: hidden;
  }
  .site-nav.is-open .nav-drawer {
    transform: none;
    visibility: visible;
  }

  /* ---- the drill-down panes ----
     Every pane fills the drawer and carries its own scroll. The root sits at
     rest; subpanes wait one full width to the right. Opening one slides the
     root out to the left and the subpane into its place, so the two move as a
     single track rather than one sliding over the other. */
  .nav-pane {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    /* 20px top matches the bar's own padding-top, so every pane's header row —
       the wordmark on the root, the back heading on a subpane — lands in the
       same 44px band as the close button. */
    padding: 20px var(--space-5) var(--space-6);
    background: var(--ground);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  /* Same reasoning as the drawer: an off-screen pane that is merely translated
     is still tabbable, so the inactive pane's links would sit in the tab order
     behind the one on screen. */
  .nav-pane:not(.nav-pane--root) {
    display: flex;
    transform: translateX(100%);
    visibility: hidden;
  }
  .nav-drawer.is-sub .nav-pane--root {
    transform: translateX(-100%);
    visibility: hidden;
  }
  .nav-pane.is-active {
    transform: none;
    visibility: visible;
  }

  /* .nav-ready is added by js/nav.js one frame AFTER .is-enhanced. Withholding
     the slide transitions until then means the one-time jump from the no-JS
     fallback (drawer in normal flow) to the enhanced off-canvas state happens
     instantly instead of animating a phantom close on every page load. */
  .site-nav.nav-ready .nav-drawer {
    transition: transform var(--dur-slow) var(--ease), visibility var(--dur-slow);
  }
  .site-nav.nav-ready .nav-pane {
    transition: transform var(--dur-slow) var(--ease), visibility var(--dur-slow);
  }
  .site-nav.nav-ready .nav-scrim {
    transition: opacity var(--dur-slow) var(--ease), visibility var(--dur-slow);
  }

  /* Stacked rows, hairline-separated so the list reads as an index. These are
     touch targets now, not the desktop's inline text row. */
  .nav-drawer .nav-links {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  /* The desktop half of each branch pair — see the note below the row primitive
     for why this cannot simply be `.nav-link--bar`. */

  /* ---- one row primitive ----
     A leaf row (<a class="nav-link">) and a branch row (<button class="nav-branch">)
     have to be indistinguishable apart from the caret — they are the same rung
     of the same list. They were not: the bar's own `.nav-links a.nav-link` is
     (0,2,1) and quietly beat the drawer's (0,2,0) `.nav-drawer .nav-link`, so
     leaf rows kept the bar's --step-small while branches used --step-body-lg.
     Hence `a.nav-link` here, to clear that, and hence one declaration block for
     both — separate blocks are what let them drift apart in the first place.
     line-height is pinned so a <button> and an <a> resolve to the same row
     height rather than each taking its own default. */
  .nav-drawer .nav-links a.nav-link,
  .nav-drawer .nav-branch {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    /* Full-bleed divider: the row's border box reaches both drawer edges via a
       negative inline margin equal to the pane padding, while the matching
       inline padding keeps the label on the text column. Set here in the
       primitive rather than a later override block — an override at lower
       specificity had the margin apply but the padding lose, which left the
       labels jammed against the edge. */
    margin-inline: calc(var(--space-5) * -1);
    padding: var(--space-4) var(--space-5);
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--line);
    font-family: var(--sans);
    font-size: var(--step-body-lg);
    font-weight: 500;
    line-height: 1.4;
    color: var(--ink-soft);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
  }
  .nav-drawer .nav-links a.nav-link:hover,
  .nav-drawer .nav-branch:hover { color: var(--ink); }

  /* Hiding the desktop half of each branch pair has to out-specify the row
     primitive above, which sets `display: flex` at (0,3,1) — a plain
     `.nav-link--bar { display: none }` is (0,1,0) and loses, which put both a
     "Tools" link and a "Tools" branch in the drawer as two identical rows. */
  .nav-drawer .nav-links a.nav-link--bar { display: none; }

  /* ---- pane header row (back heading on a subpane, wordmark on the root) ----
     Both are the pane's title, typed as a heading: h3 scale, ink, semibold. The
     back heading names the section just opened; the root's is the "Chief Of
     Life" wordmark that the footer uses, linking home. They share this block so
     the two headers sit in exactly the same band across every pane. */
  .nav-back,
  .nav-drawer .nav-home {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    /* flex:none so a long name cannot let the row absorb the pane's free space
       and push the links down. */
    flex: none;
    /* Shares the top bar's row with the close button: min-height matches the
       toggle's 44px and the pane's 20px top padding matches the toggle's top,
       so the header centres on the same band. padding-right clears the toggle
       (44px wide, 24px gutter) so a long label never runs under it. */
    min-height: 44px;
    /* Bleeds to the edges for alignment with the rows, but carries no divider
       of its own — the header and its list read as one block. */
    margin-inline: calc(var(--space-5) * -1);
    padding: 0 calc(var(--space-8) + var(--space-4)) 0 var(--space-5);
    background: transparent;
    border: 0;
    font-family: var(--sans);
    font-size: var(--step-h3);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.3;
    color: var(--ink);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
  }
  /* The wordmark keeps the footer wordmark's own weight and tracking (500 /
     -0.02em) rather than the back heading's 600 — it is the brand mark, not a
     section title, and should read the same as it does in the footer. */
  .nav-drawer .nav-home {
    font-weight: 500;
    letter-spacing: -0.02em;
  }
  .nav-drawer .nav-home:hover { color: var(--ink); }
  /* Muted against the ink heading, so the caret reads as the affordance and the
     name reads as the title. The hover lands on the caret rather than the label:
     the label is already --ink, the strongest text colour there is, and --accent
     is 3.4:1 on this ground so it cannot legally take text this size. */
  .nav-back__caret { color: var(--muted); transition: color 0.18s; }
  .nav-back:hover .nav-back__caret { color: var(--ink); }

  /* Chevrons drawn from two borders rather than shipping an icon — the forward
     and back carets are the same shape at different rotations. */
  .nav-caret,
  .nav-back__caret {
    display: block;
    flex: none;
    width: 7px; height: 7px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
  }
  .nav-caret { transform: rotate(-45deg); }
  .nav-back__caret { transform: rotate(135deg); }

  .nav-sublinks { display: flex; flex-direction: column; }
  .nav-sublink {
    display: block;
    /* Same full-bleed divider as the root rows. */
    margin-inline: calc(var(--space-5) * -1);
    padding: var(--space-4) var(--space-5);
    font-size: var(--step-body);
    color: var(--ink-soft);
    text-decoration: none;
    border-bottom: 1px solid var(--line);
  }
  .nav-sublink:hover { color: var(--ink); }

  /* margin-top:auto pins the CTA to the bottom of the drawer when the links do
     not fill it, which is where a thumb actually rests.
     It also takes the PRIMARY fill here, not the bar's outlined treatment: in
     the bar it is one control competing with six links, so it stays quiet, but
     in the drawer it is the only action on the pane and the outline left it
     looking like a seventh menu row. Same ink fill and orange hover as
     .btn-primary — border-color moves with the background, which .btn-primary
     does not need because its border is transparent. */
  .nav-drawer .nav-cta {
    margin-top: auto;
    width: 100%;
    text-align: center;
    padding: var(--space-3) var(--space-5);
    background: var(--ink);
    color: var(--ground);
    border-color: var(--ink);
  }
  .nav-drawer .nav-cta:hover {
    background: var(--accent);
    color: var(--ink);
    border-color: var(--accent);
  }

  /* ---- the scrim ----
     Dims the page behind the drawer and is the pointer dismissal target. */
  .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 40;
    /* iOS Safari does not reliably honour `overflow: hidden` on html/body for
       touch scrolling, so a drag starting on the dimmed area can still scroll
       the page behind the drawer. This stops the gesture at the scrim. Paired
       with overscroll-behavior on the drawer, which stops a scroll that reaches
       the drawer's end from chaining through to the page. */
    touch-action: none;
    /* Literal first, color-mix second: nothing else in this codebase uses
       color-mix, so a browser below its support line (pre-2023) drops that
       declaration and keeps a real dim instead of a transparent scrim that
       looks like the drawer failed. --ink is #0F0F0F. */
    background: rgba(15, 15, 15, 0.46);
    background: color-mix(in srgb, var(--ink) 46%, transparent);
    opacity: 0;
    visibility: hidden;
    /* transition withheld until .nav-ready — see the drawer note above. */
  }
  .site-nav.is-open .nav-scrim { opacity: 1; visibility: visible; }

  /* ---- no-JS fallback ----
     The drawer is only parked off-canvas once js/nav.js has confirmed it can
     bring it back. Without the class the links return to normal flow as a plain
     stacked menu, so a blocked or failed script leaves the nav usable instead of
     unreachable. The toggle goes away with it — a button that cannot open
     anything is worse than no button. */
  .site-nav:not(.is-enhanced) .nav-toggle { display: none; }
  /* The bar is a flex row, so the drawer needs to wrap onto its own line and
     claim the full width; `width: auto` would shrink-wrap it into a narrow
     column sitting beside the logo. */
  .site-nav:not(.is-enhanced) .container { flex-wrap: wrap; row-gap: var(--space-4); }
  .site-nav:not(.is-enhanced) .nav-drawer {
    position: static;
    width: 100%;
    transform: none;
    visibility: visible;
    overflow: visible;
    border-left: 0;
    padding: 0 0 var(--space-2);
    z-index: auto;
  }
}

/* Scroll lock. On the drawer's own class rather than a bare `overflow: hidden`
   on html, because book-a-call.html sets `html { overflow-x: hidden }` and a
   class beats a type selector. */
html.nav-open, html.nav-open body { overflow: hidden; }

/* ----------------------------------------------------- desktop nav (881px+) */

@media (min-width: 881px) {
  /* Centre the link cluster on the page. A three-column grid (1fr auto 1fr)
     puts the logo hard left, the CTA hard right, and the links in a middle
     column that is centred because the two 1fr rails balance — which
     justify-content: space-between could not do, since it centres the GAPS,
     not the link group, whenever the logo and CTA differ in width (they do).
     The dropdown panels and the hidden toggle/wordmark are out of flow or
     display:none, so the grid still sees exactly these three items. */
  .site-nav .container {
    display: grid;
    /* minmax(0, 1fr), not a bare 1fr: 1fr means minmax(auto, 1fr), so the CTA
       rail — wider than the logo — grows past its share and shoves the middle
       column off-centre by a few px. A 0 minimum forces the two rails equal, so
       the link cluster lands on the true page centre. */
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  }
  .site-nav .logo { justify-self: start; }
  .site-nav .nav-drawer .nav-links { justify-self: center; }
  .site-nav .nav-cta { justify-self: end; }

  /* Light-grey pill behind a top-level item on hover. Every pill is the SAME
     height as the nav CTA (46px): a plain <a> resolved to ~40px and a <button>
     to ~34px (buttons default to line-height:normal), so the row was a jumble.
     inline-flex + align-items:center + a shared min-height take height out of
     the hands of line-height and tag type, so links, branch buttons and the CTA
     all read as one row of equal-height pills. The gap tightens to compensate
     for the horizontal padding. */
  .site-nav .nav-drawer .nav-links { gap: var(--space-2); }
  .site-nav .nav-drawer .nav-links a.nav-link,
  .site-nav.is-enhanced .nav-branch {
    display: inline-flex;
    align-items: center;
    min-height: 46px;
    padding: 0 16px;
    border-radius: var(--radius-pill);
    transition: background 0.16s, color 0.16s;
  }
  .site-nav .nav-drawer .nav-links a.nav-link:hover,
  .site-nav.is-enhanced .nav-branch:hover,
  .site-nav.is-enhanced .nav-branch[aria-expanded="true"] {
    background: var(--btn-quiet);
    color: var(--ink);
  }

  /* Anchor for the fixed dropdown panels' stacking, and the outside-click layer. */
  .site-nav { position: relative; }

  /* On desktop the branch buttons ARE the top-level items for sections that
     have a submenu (Tools, Services, Blog); their plain-link twins hide. Gated
     on .is-enhanced so that without JS — where a button that opens nothing is a
     dead end — the plain links show instead and still reach /tools, /blog, etc.
     The roles branch has no desktop home, so it stays hidden either way. */
  /* Must out-specify the pill rule above, which now sets display:inline-flex on
     every a.nav-link at (0,4,1) — the bar-link twins are a.nav-link too, so a
     lower-specificity hide let them reappear as duplicates beside their branch
     buttons. */
  .site-nav.is-enhanced .nav-drawer .nav-links a.nav-link--bar { display: none; }
  .site-nav.is-enhanced .nav-branch {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* padding + radius come from the shared pill rule above; setting padding:0
       here (a later rule at equal specificity) used to cancel it, so the branch
       buttons had no pill while the plain links did. */
    background: transparent;
    border: 0;
    font-family: var(--sans);
    font-size: var(--step-small);
    font-weight: 500;
    color: var(--ink-soft);
    cursor: pointer;
  }
  /* Must out-specify the .is-enhanced show rule above (0,3,0), or the roles
     branch would appear in the desktop bar. */
  .site-nav.is-enhanced .nav-branch--drawer-only { display: none; }

  /* A small down-caret beside the label, flipping when the panel is open. Same
     two-border glyph as the mobile carets. */
  .nav-branch .nav-caret {
    display: block;
    width: 6px; height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: translateY(-1px) rotate(45deg);
    transition: transform 0.18s;
  }
  .nav-branch[aria-expanded="true"] .nav-caret { transform: translateY(1px) rotate(-135deg); }

  /* ---- floating dropdown panels ----
     The mobile subpanes are reused: on desktop their back heading is already
     display:none, so a panel is just its list of sublinks. position:fixed (JS
     sets top/left from the trigger's rect each open) keeps them out of the
     container grid — otherwise the display:contents flattening would drag them
     in as stray grid items. Hidden until .is-dropdown-open. */
  .nav-pane:not(.nav-pane--root) {
    display: block;
    position: fixed;
    z-index: 60;
    min-width: 200px;
    max-width: 280px;
    padding: var(--space-2);
    background: var(--ground);
    /* No border — the shadow alone lifts the panel off the page. Rounded to the
       panel radius so it reads as a floating card, not a boxed menu. */
    border: 0;
    border-radius: var(--radius-panel);
    box-shadow: 0 12px 32px rgba(15, 15, 15, 0.12);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 0.16s var(--ease), transform 0.16s var(--ease), visibility 0.16s;
  }
  .nav-pane.is-dropdown-open {
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  .nav-pane .nav-sublinks { display: flex; flex-direction: column; gap: 2px; }
  .nav-pane .nav-sublink {
    display: block;
    padding: var(--space-2) var(--space-3);
    font-size: var(--step-small);
    line-height: 1.3;
    color: var(--ink-soft);
    text-decoration: none;
    border-radius: var(--radius-row);
    white-space: nowrap;
    transition: background 0.14s, color 0.14s;
  }
  .nav-pane .nav-sublink:hover { background: var(--btn-quiet); color: var(--ink); }
}

/* --------------------------------------------------------------- footer */

footer { background: var(--ground); color: var(--muted); padding: 72px 0 32px;
         font-size: var(--step-small); border-top: 1px solid var(--line); }
footer .footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr 1fr; gap: 40px;
                       max-width: var(--measure); margin: 0 auto 40px; padding: 0 var(--gutter); }
/* Plain text, not the icon — the mark alone doesn't carry the name at this
   scale. Sans, not the nav's hexagon. */
footer .col-brand .wordmark { display: inline-block; margin-bottom: 12px;
                               font-family: var(--sans); font-weight: 500;
                               font-size: 2rem; letter-spacing: -0.02em;
                               color: var(--ink); text-decoration: none; }
footer .col-brand p { color: var(--muted); font-size: var(--step-micro); line-height: 1.6; max-width: 300px; }
footer h4 { color: var(--ink); font-size: var(--step-micro); letter-spacing: 0.12em; text-transform: uppercase;
            margin-bottom: 16px; font-weight: 700; }
footer ul { list-style: none; display: flex; flex-direction: column; gap: 10px; }
footer ul li a { color: var(--ink-soft); text-decoration: none; font-size: var(--step-small); transition: color 0.2s; }
footer ul li a:hover { color: var(--ink); }
/* An index row rather than a fifth column: the 18 role pages need a route in, but
   as a column they would turn the footer into a link farm. Mono and small, so it
   reads as an index. */
footer .footer-index {
  /* Same measure and gutter as .footer-grid, or it sits outside the page's edges. */
  max-width: var(--measure);
  margin: 40px auto 0;
  padding: 28px var(--gutter) 36px;
  border-top: 1px solid var(--line);
}
footer .footer-index ul {
  list-style: none;
  display: flex;
  /* `footer ul` sets column above; without resetting it these 18 links stack. */
  flex-direction: row;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-top: 14px;
}
footer .footer-index a { font-family: var(--mono); font-size: var(--step-eyebrow); letter-spacing: 0.04em; color: var(--muted); }
footer .footer-index a:hover { color: var(--ink); }

footer .footer-bottom { border-top: 1px solid var(--line); padding: 24px var(--gutter) 0;
                         max-width: var(--measure); margin: 0 auto; display: flex; flex-wrap: wrap;
                         justify-content: space-between; align-items: center; gap: 12px;
                         color: var(--muted); font-size: var(--step-micro); }

@media (max-width: 880px) {
  footer .footer-grid { grid-template-columns: 1fr 1fr; }
  footer .footer-index ul { gap: 8px 16px; }
}
@media (max-width: 520px) {
  footer .footer-grid { grid-template-columns: 1fr; }
}
