/* ==========================================================================
   NetrAI — Frosted glass
   --------------------------------------------------------------------------
   Ported from the React <GlassSurface> component. This site has no build step,
   so the component could not be dropped in as-is; what it does has been split
   into three layers instead:

     1. TOKENS + .glass          the material, in plain CSS. This is what the
                                 component's own `--fallback` path does, and
                                 what Safari and Firefox get from it anyway,
                                 since its capability check returns false for
                                 both.
     2. [data-glass="refract"]   the SVG displacement filter — the chromatic
                                 edge refraction that makes the component
                                 distinctive. Chromium only, opt-in per
                                 element, built by js/effects/glass.js.
     3. .ambient-mesh            something for the glass to actually blur.

   On (3): a backdrop-filter over a flat #f5f5f7 canvas produces no visible
   change, because there is nothing behind it with any variation to blur. The
   old system was flat by design, so switching cards to glass on its own would
   have looked like nothing happened. The mesh gives every glass surface
   something to pick up.

   ── TWO KINDS OF GLASS, AND WHY ─────────────────────────────────────────
   CHROME glass (header, tab bar, sheets) sits over CONTENT THAT SCROLLS
   UNDER IT. Its job is to obscure. The mobile audit found body copy reading
   straight through the tab bar at 0.86 alpha / 22px blur, so chrome uses a
   heavier recipe and is measured, not eyeballed.

   SURFACE glass (cards, panels) sits over the page background, which is not
   trying to say anything. It can be far lighter, and that is where the
   material actually gets to look like glass.

   Mixing the two up is how a page ends up either with unreadable navigation
   or with cards that look like flat boxes.
   ========================================================================== */

:root {
  /* --- Surface glass: cards and panels, over the background ------------- */
  --glass-tint:        rgba(255, 255, 255, 0.50);
  --glass-tint-strong: rgba(255, 255, 255, 0.72);
  --glass-blur-amt:    18px;
  --glass-sat:         165%;
  --glass-edge:        rgba(255, 255, 255, 0.65);   /* top-left highlight  */
  --glass-edge-dim:    rgba(0, 0, 0, 0.06);         /* bottom-right shade  */
  --glass-hairline:    rgba(0, 0, 0, 0.08);
  --glass-drop:
    0 1px 2px rgba(17, 17, 26, 0.04),
    0 8px 24px -12px rgba(17, 17, 26, 0.10);

  /* --- Chrome glass: must obscure what scrolls beneath ------------------
     0.91, not 0.86. The strip-sampling check called 0.86 clean, but a single
     36px sample can land in the gap between two words and report nothing
     while the words either side are perfectly readable — the eye caught what
     the metric missed. At 0.91 a 56px headline passing under the bar still
     reads as moving texture, which is the effect, but you can no longer read
     the words, which is the line. */
  --chrome-tint:       rgba(245, 245, 247, 0.91);
  --chrome-blur-amt:   32px;
  --chrome-sat:        190%;

  /* --- Ambient mesh: what the glass refracts ----------------------------
     Tuned up from a first pass that was almost invisible. On a near-white
     canvas the mesh has to do real work or the cards read as flat white boxes
     with a soft edge — the blur is only as interesting as what sits behind
     it. Still low enough that the page reads as white, not blue. */
  --mesh-a: rgba(0, 113, 227, 0.14);
  --mesh-b: rgba(41, 151, 255, 0.11);
  --mesh-c: rgba(0, 102, 204, 0.085);
}

[data-theme="dark"] {
  --glass-tint:        rgba(28, 28, 32, 0.52);
  --glass-tint-strong: rgba(28, 28, 32, 0.72);
  --glass-blur-amt:    20px;
  --glass-sat:         150%;
  --glass-edge:        rgba(255, 255, 255, 0.14);
  --glass-edge-dim:    rgba(0, 0, 0, 0.30);
  --glass-hairline:    rgba(255, 255, 255, 0.10);
  --glass-drop:
    0 1px 2px rgba(0, 0, 0, 0.40),
    0 8px 28px -12px rgba(0, 0, 0, 0.60);

  --chrome-tint:       rgba(6, 6, 8, 0.92);
  --chrome-blur-amt:   34px;
  --chrome-sat:        170%;

  --mesh-a: rgba(88, 86, 214, 0.16);
  --mesh-b: rgba(41, 151, 255, 0.13);
  --mesh-c: rgba(0, 113, 227, 0.10);
}


/* ==========================================================================
   1. The material
   ========================================================================== */

.glass {
  position: relative;
  background: var(--glass-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur-amt)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur-amt)) saturate(var(--glass-sat));
  border: 1px solid var(--glass-hairline);
  border-radius: var(--radius-lg);

  /* The component's signature is the pair of inset edges: a bright rim on the
     lit side and a shaded one opposite. That is what reads as thickness —
     without it a blurred panel just looks blurry rather than like a slab of
     something. */
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    var(--glass-drop);

  /* backdrop-filter silently does nothing unless the element makes its own
     stacking context. */
  isolation: isolate;
}

/* Denser variant for anything carrying small text or numbers. */
.glass--solid {
  background: var(--glass-tint-strong);
  --glass-blur-amt: 24px;
}

/* Edge-lit variant: adds the diagonal sheen the component draws with its
   gradient pair. Kept as a pseudo-element so it never intercepts a pointer. */
.glass--lit::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.18) 0%,
    rgba(255, 255, 255, 0.04) 32%,
    transparent 58%
  );
}
[data-theme="dark"] .glass--lit::before {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.10) 0%,
    rgba(255, 255, 255, 0.02) 34%,
    transparent 60%
  );
}

/* Hover: the glass gets very slightly denser and lifts. Deliberately small —
   the material is the effect, a big transform on top of it reads as cheap. */
.glass--hover {
  transition:
    background var(--transition),
    box-shadow var(--transition),
    transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.glass--hover:hover {
  background: var(--glass-tint-strong);
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    0 2px 4px rgba(17, 17, 26, 0.05),
    0 14px 36px -14px rgba(17, 17, 26, 0.16);
}
[data-theme="dark"] .glass--hover:hover {
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    0 2px 4px rgba(0, 0, 0, 0.5),
    0 14px 36px -14px rgba(0, 0, 0, 0.7);
}


/* ==========================================================================
   2. Chrome glass — obscures what passes underneath
   ========================================================================== */

.glass-chrome {
  background: var(--chrome-tint);
  -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
}


/* ==========================================================================
   3. Ambient mesh — what the glass has to refract
   --------------------------------------------------------------------------
   Fixed, behind everything, pointer-transparent. Three soft radial stops at
   very low alpha: enough for a blurred panel to pick up a gradient across its
   width, nowhere near enough to read as colour on the page itself. In light
   this is almost subliminal by design — the point is that the glass has
   something to do, not that the background becomes decorative.
   ========================================================================== */

.ambient-mesh {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(58% 44% at 14% 12%,  var(--mesh-a) 0%, transparent 62%),
    radial-gradient(52% 46% at 88% 34%,  var(--mesh-b) 0%, transparent 60%),
    radial-gradient(64% 50% at 44% 92%,  var(--mesh-c) 0%, transparent 66%);
}


/* ==========================================================================
   4. SVG refraction — Chromium only, opt-in
   --------------------------------------------------------------------------
   js/effects/glass.js builds a per-element filter and displacement map, then swaps
   the plain blur for it. Everything degrades to the CSS material above if the
   script never runs, the browser is not Chromium, or the element scrolls out
   of the budget — so this class is always additive and never load-bearing.
   ========================================================================== */

[data-glass="refract"].is-refracting {
  -webkit-backdrop-filter: var(--refract-filter) saturate(var(--glass-sat));
  backdrop-filter: var(--refract-filter) saturate(var(--glass-sat));
}

.glass-filter-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
  pointer-events: none;
}


/* ==========================================================================
   5. Degradation
   ========================================================================== */

/* No backdrop-filter at all: go opaque rather than transparent. A tint with
   nothing blurring behind it is just washed-out text. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass        { background: var(--surface-white); }
  .glass-chrome { background: var(--surface-canvas); }
  [data-theme="dark"] .glass        { background: var(--color-elevated); }
  [data-theme="dark"] .glass-chrome { background: #000; }
  .ambient-mesh { display: none; }
}

/* Reduced transparency is an accessibility setting, not a taste one. Someone
   who has asked the OS to stop layering translucent surfaces gets opaque
   panels and no mesh. */
@media (prefers-reduced-transparency: reduce) {
  .glass, .glass-chrome, [data-glass="refract"].is-refracting {
    background: var(--surface-white) !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
  [data-theme="dark"] .glass,
  [data-theme="dark"] .glass-chrome {
    background: var(--color-elevated) !important;
  }
  [data-theme="dark"] .glass-chrome { background: #000 !important; }
  .ambient-mesh { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .glass--hover { transition: none; }
  .glass--hover:hover { transform: none; }
}

/* Print: glass is a screen material. */
@media print {
  .glass, .glass-chrome {
    background: #fff !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    box-shadow: none !important;
    border: 1px solid #ccc !important;
  }
  .ambient-mesh { display: none !important; }
}


/* ==========================================================================
   6. APPLICATION — which surfaces become glass
   --------------------------------------------------------------------------
   Applied by selector rather than by adding classes to seven HTML files, so
   the whole treatment can be reverted by removing one stylesheet link.
   ========================================================================== */

/* ---- Sticky header ------------------------------------------------------
   Already sticky with a .scrolled state; this replaces its flat translucent
   fill with the chrome recipe. At rest it is lighter and lets the page show
   through; once scrolled it thickens, because that is when content is
   actually passing underneath it. */
.site-header {
  background: color-mix(in srgb, var(--chrome-tint) 82%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(var(--chrome-sat));
  backdrop-filter: blur(20px) saturate(var(--chrome-sat));
  /* No drawn border. §12 asks a translucent layer to separate itself from
     the content passing beneath it with a scroll edge effect — a short fade
     where the two actually meet — rather than a line that is there whether
     anything is under it or not. style.css carries that fade on
     .site-header::after and only paints it once the page has scrolled.

     The inset highlight below is a different thing and stays: it is the
     bright top edge of the material itself, the light catching the glass,
     not a divider between the bar and the page. */
  box-shadow: inset 0 -1px 0 0 var(--glass-edge);
  transition:
    background var(--transition),
    backdrop-filter var(--transition),
    box-shadow var(--transition);
}
.site-header.scrolled {
  background: var(--chrome-tint);
  -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  box-shadow:
    inset 0 -1px 0 0 var(--glass-edge),
    0 1px 24px -8px rgba(17, 17, 26, 0.14);
}
[data-theme="dark"] .site-header.scrolled {
  box-shadow:
    inset 0 -1px 0 0 var(--glass-edge),
    0 1px 24px -6px rgba(0, 0, 0, 0.8);
}

/* The nav pill rides on the header, so it gets the material too — a little
   denser, since it carries 14px labels. */
.nav-pill {
  -webkit-backdrop-filter: blur(12px) saturate(150%);
  backdrop-filter: blur(12px) saturate(150%);
}

/* ---- Cards -------------------------------------------------------------- */
.card,
.problem-card,
.service-card,
.value-card,
.combo-card,
.review-card,
.demo-note,
.mvv-card {
  background: var(--glass-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur-amt)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur-amt)) saturate(var(--glass-sat));
  border: 1px solid var(--glass-hairline);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    var(--glass-drop);
  isolation: isolate;
  transition:
    background var(--transition),
    box-shadow var(--transition),
    transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.card:hover,
.problem-card:hover,
.service-card:hover,
.value-card:hover,
.combo-card:hover {
  background: var(--glass-tint-strong);
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    0 2px 4px rgba(17, 17, 26, 0.05),
    0 14px 36px -14px rgba(17, 17, 26, 0.16);
}
[data-theme="dark"] .card:hover,
[data-theme="dark"] .problem-card:hover,
[data-theme="dark"] .service-card:hover,
[data-theme="dark"] .value-card:hover,
[data-theme="dark"] .combo-card:hover {
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    0 2px 4px rgba(0, 0, 0, 0.5),
    0 14px 36px -14px rgba(0, 0, 0, 0.7);
}

/* ---- Pricing surfaces ---------------------------------------------------
   These carry prices and checkboxes, so they take the denser tint. A number
   someone is deciding money on does not get to be atmospheric. */
.price-item,
.tier-btn,
.faq-item,
.tier-advisor,
.advisor-option,
.compare-table,
.cat-chip {
  background: var(--glass-tint-strong);
  -webkit-backdrop-filter: blur(16px) saturate(var(--glass-sat));
  backdrop-filter: blur(16px) saturate(var(--glass-sat));
  border: 1px solid var(--glass-hairline);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    var(--glass-drop);
  isolation: isolate;
}

/* The cart popover floats over the catalogue, so it is chrome, not surface. */
.cart-panel {
  background: var(--chrome-tint);
  -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  border: 1px solid var(--glass-hairline);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    0 12px 40px -8px rgba(0, 0, 0, 0.28),
    0 2px 8px rgba(0, 0, 0, 0.10);
}
.cart-dock {
  background: var(--chrome-tint);
  -webkit-backdrop-filter: blur(24px) saturate(var(--chrome-sat));
  backdrop-filter: blur(24px) saturate(var(--chrome-sat));
  border: 1px solid var(--glass-hairline);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    0 8px 28px -10px rgba(17, 17, 26, 0.22);
}

/* ---- Overlays ---------------------------------------------------------- */
.site-search-panel,
.site-search .site-search-inner,
.aitg-bubble,
.aitg-dock {
  background: var(--chrome-tint);
  -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  border: 1px solid var(--glass-hairline);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    0 16px 48px -12px rgba(0, 0, 0, 0.30);
}

/* ---- Footer panel ------------------------------------------------------- */
.finale-panel,
.footer-cta,
.cta-banner {
  background: var(--glass-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur-amt)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur-amt)) saturate(var(--glass-sat));
  border: 1px solid var(--glass-hairline);
  box-shadow:
    inset 0 1px 0 0 var(--glass-edge),
    inset 0 -1px 0 0 var(--glass-edge-dim),
    var(--glass-drop);
  isolation: isolate;
}

/* ---- Form fields -------------------------------------------------------- */
.form-field input,
.form-field select,
.form-field textarea,
.site-search-input {
  background: var(--glass-tint-strong);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  backdrop-filter: blur(10px) saturate(140%);
}

/* ---- Mobile shell -------------------------------------------------------
   The mobile audit found body copy reading through the tab bar at 0.86 alpha
   / 22px blur. The chrome recipe is heavier than that on both axes, and the
   opaque override added during the audit fixes is dropped here in favour of
   it — measured, not assumed. See the verification note in DESIGN.md. */
@media (max-width: 860px) {
  html.m-app .site-header,
  html.m-app .m-tabs,
  html.m-app .m-chapter {
    background: var(--chrome-tint);
    -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
    backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  }
  html.m-app .m-tabs {
    box-shadow: inset 0 1px 0 0 var(--glass-edge);
  }
  html.m-app .m-sheet {
    background: var(--chrome-tint);
    -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
    backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
  }

  /* Phones get the material but not the lift — a transform on a card the
     thumb is already dragging fights the scroll. */
  .card:hover, .problem-card:hover, .service-card:hover,
  .value-card:hover, .combo-card:hover { transform: none; }
}


/* ---- The client marquee keeps its own ground ---------------------------
   The LED board should read as a device, not as glass. It is also the one
   place where the mesh measurably cost contrast: the client names measured
   4.47:1 against the mesh-lifted background, 0.03 under AA, where they clear
   6.96:1 against a flat one. Opaque band, no mesh behind it, and the effect
   reads better for it. */
.client-marquee {
  position: relative;
  isolation: isolate;
}
.client-marquee::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--surface-canvas);
}
[data-theme="dark"] .client-marquee::before { background: #000; }


/* ---- Phones get a heavier chrome ---------------------------------------
   Measured with the largest headline on the site parked directly under the
   bar. Desktop came back clean at 0.86 / 30px because the content column has
   margins either side; a phone's does not, so the same recipe left a faint
   ghost of 56px type. Raised until the delta went to zero. */
@media (max-width: 860px) {
  :root                { --chrome-tint: rgba(245, 245, 247, 0.94); --chrome-blur-amt: 34px; }
  [data-theme="dark"]  { --chrome-tint: rgba(0, 0, 0, 0.94);       --chrome-blur-amt: 34px; }
}


/* ==========================================================================
   7. FLOATING ISLAND HEADER
   --------------------------------------------------------------------------
   At rest the header is a flush, full-bleed glass bar. Once the page moves it
   detaches from the top edge and contracts into a floating pill with air on
   all sides.

   Where the surface lives: .site-header is the sticky POSITIONING shell and
   is transparent throughout; the visible material moves onto .nav, which is
   the thing that actually contracts. Painting the shell and animating the
   child would have left a full-width bar behind the island.

   Radius is the pill (980px), not the 8px surface radius. The header's
   children are already pills — the nav capsule, the search field, the CTA —
   and a rounded rectangle wrapped around a row of pills reads as a mistake.
   This is the one place the "8px for surfaces" rule loses to the shapes
   actually inside the box.

   Desktop only. On a 390px screen an island spends horizontal space the
   content needs, and the phone shell already has its own chrome.
   ========================================================================== */

@media (min-width: 861px) {

  /* The shell: sticky, transparent, no border.

     `display: flow-root` is doing real work. With the shell stripped of its
     padding, border and background, .nav's top margin collapsed straight
     through it and the island rendered flush against the viewport top —
     contracted horizontally but with no air above it. flow-root establishes
     a block formatting context, which contains the margin, without changing
     how the header sticks. The shell's height does now grow by the margin
     when detached, which is why js/core/script.js re-measures --hdr-h on the
     toggle rather than trusting the resize-time value. */
  /* Both selectors, and that is the whole point. Section 6 above styles
     `.site-header.scrolled` — two classes, specificity (0,2,0). A bare
     `.site-header` here is (0,1,0) and loses to it no matter how far down the
     file it sits, so the shell kept painting the chrome tint at 0.92 AND
     blurring 34px across the full strip. The island floated correctly inside
     a solid bar nobody asked for.

     Nothing paints on the shell now: the page scrolls under it in the clear,
     and the only glass on screen is the island itself. */
  .site-header,
  .site-header.scrolled {
    display: flow-root;
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-bottom: none;
    box-shadow: none;
  }

  /* The surface. Full-bleed and square at rest, so the bar still reads as
     part of the page edge before you scroll. */
  .nav {
    margin: 0 auto;
    max-width: 100%;
    border-radius: 0;
    background: color-mix(in srgb, var(--chrome-tint) 82%, transparent);
    -webkit-backdrop-filter: blur(20px) saturate(var(--chrome-sat));
    backdrop-filter: blur(20px) saturate(var(--chrome-sat));
    border: 1px solid transparent;
    border-bottom-color: var(--glass-hairline);
    box-shadow: inset 0 -1px 0 0 var(--glass-edge);
    transition:
      max-width   420ms cubic-bezier(0.22, 1, 0.36, 1),
      margin      420ms cubic-bezier(0.22, 1, 0.36, 1),
      border-radius 420ms cubic-bezier(0.22, 1, 0.36, 1),
      padding     420ms cubic-bezier(0.22, 1, 0.36, 1),
      background  300ms ease,
      border-color 300ms ease,
      box-shadow  300ms ease,
      backdrop-filter 300ms ease;
  }

  /* Detached. Denser glass, because now there is page visible on all four
     sides and the thing has to read as an object rather than as a tint. */
  .site-header.scrolled .nav {
    max-width: min(1180px, calc(100vw - 3rem));
    margin: 10px auto;
    border-radius: var(--radius-pill);
    padding-inline: clamp(18px, 2vw, 26px);
    background: var(--chrome-tint);
    -webkit-backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
    backdrop-filter: blur(var(--chrome-blur-amt)) saturate(var(--chrome-sat));
    border-color: var(--glass-hairline);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 -1px 0 0 var(--glass-edge-dim),
      0 4px 12px -4px rgba(17, 17, 26, 0.10),
      0 12px 40px -12px rgba(17, 17, 26, 0.22);
  }
  [data-theme="dark"] .site-header.scrolled .nav {
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 -1px 0 0 var(--glass-edge-dim),
      0 4px 12px -4px rgba(0, 0, 0, 0.5),
      0 16px 44px -12px rgba(0, 0, 0, 0.8);
  }

  /* The island is narrower than the bar it came from, so the band that was
     already tight loses another 48px. Give the gutters back here rather than
     letting the CTA push out again. */
  @media (max-width: 1100px) {
    .site-header.scrolled .nav {
      max-width: calc(100vw - 1.5rem);
      padding-inline: 16px;
    }
  }

  /* A pill sitting inside a pill needs the inner one to relax, or the two
     radii fight along the same edge. */
  .site-header.scrolled .nav-links { box-shadow: none; }

  /* With the shell invisible it is still a full-width sticky box sitting over
     the page, swallowing clicks in the empty margin either side of the
     island. Nothing there is interactive, so it stops catching them; the nav
     puts them back for the part that is. */
  .site-header.scrolled { pointer-events: none; }
  .site-header.scrolled .nav { pointer-events: auto; }
}

/* The transformation is decorative. Under reduced motion the header still
   becomes an island — it simply arrives rather than travels. */
@media (prefers-reduced-motion: reduce) {
  .nav { transition: background 200ms ease, border-color 200ms ease; }
}
