/* ============================================================
   FBGM24 — layout.css
   Header / mega-nav / footer / section flow / reveal choreography.
   ============================================================ */

@layer layout, reveal;

@layer layout {

  /* ---------- Ticker rail ---------- */
  .rail {
    position: relative;
    z-index: 40;
    border-bottom: 1px solid var(--hairline);
    background: linear-gradient(180deg, rgba(2, 6, 15, 0.86), rgba(2, 6, 15, 0.55));
    backdrop-filter: blur(18px) saturate(150%);
    overflow: hidden;
  }
  .rail-track {
    display: flex;
    gap: 2.6rem;
    padding: 0.5rem 0;
    width: max-content;
    animation: rail-scroll 64s linear infinite;
  }
  .rail:hover .rail-track { animation-play-state: paused; }
  @keyframes rail-scroll { to { transform: translate3d(-50%, 0, 0); } }
  .rail-item {
    display: inline-flex;
    align-items: baseline;
    gap: 0.55rem;
    font-family: var(--font-mono);
    font-size: var(--step--2);
    white-space: nowrap;
    color: var(--fg-faint);
  }
  .rail-item b { color: var(--paper-300); font-weight: 500; letter-spacing: 0.04em; }
  .rail-item .num { color: var(--paper-100); }
  .rail-item[data-dir='up'] .chg { color: var(--up); }
  .rail-item[data-dir='down'] .chg { color: var(--down); }

  /* ---------- Header ---------------------------------------------
     Floating capsules instead of a bar: logo, navigation, language
     and CTA each sit in their own glass pill over the page.
  ---------------------------------------------------------------- */
  :root { --pill-h: 52px; }

  .site-head {
    position: sticky;
    top: 0;
    z-index: 50;
    padding-block: 0.85rem 0.5rem;
    pointer-events: none;                 /* only the pills catch input */
  }
  .site-head.is-stuck { padding-top: 0.6rem; }
  .head-inner {
    display: flex;
    align-items: center;
    gap: clamp(0.6rem, 1.2vw, 1rem);
    min-height: var(--pill-h);
  }
  .head-inner > *, .nav-list { pointer-events: auto; }

  /* shared capsule surface */
  .brandmark, .nav-list, .lang-switch, .burger {
    border: 1px solid var(--hairline-2);
    border-radius: 999px;
    background: rgba(6, 16, 32, 0.52);
    backdrop-filter: blur(22px) saturate(160%);
    box-shadow: 0 18px 44px -26px rgba(0, 0, 0, 0.85), inset 0 1px 0 rgba(180, 225, 255, 0.10);
    transition: background 0.35s var(--ease-out), border-color 0.35s, box-shadow 0.35s;
  }
  .site-head.is-stuck .brandmark, .site-head.is-stuck .nav-list, .site-head.is-stuck .lang-switch, .site-head.is-stuck .burger {
    background: rgba(4, 10, 22, 0.80);
    border-color: rgba(150, 195, 255, 0.30);
  }

  .brandmark {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    height: var(--pill-h);
    padding: 0 1.15rem 0 0.7rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.16rem;
    letter-spacing: -0.03em;
    color: var(--paper-100);
    flex: 0 0 auto;
  }
  .brandmark svg { width: 30px; height: 30px; overflow: visible; }
  .brandmark .mark-ring { transform-origin: center; animation: mark-spin 14s linear infinite; }
  @keyframes mark-spin { to { transform: rotate(360deg); } }

  /* ---------- Primary nav capsule ---------- */
  .nav { margin-inline: auto; }
  /* Drawer furniture: rendered on every viewport, inert above 1120px where
     this same <nav> is the header capsule. */
  .nav-scroll { display: contents; }
  .nav-sky, .nav-foot, .nav-lang, .nav-clip { display: none; }
  .nav-list {
    display: flex;
    align-items: center;
    gap: 0.1rem;
    list-style: none;
    padding: 0.3rem;
    height: var(--pill-h);
  }
  .nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    height: calc(var(--pill-h) - 0.6rem - 2px);
    padding: 0 0.95rem;
    border-radius: 999px;
    font-size: var(--step--1);
    font-weight: 500;
    color: var(--fg-dim);
    letter-spacing: 0.005em;
    transition: color 0.22s var(--ease-out), background 0.22s var(--ease-out);
    white-space: nowrap;
  }
  .nav-link:hover, .nav-link[aria-expanded='true'], .nav-link[aria-current='page'], .nav-link[data-active='true'] {
    color: var(--paper-100);
    background: rgba(255, 255, 255, 0.08);
  }
  .nav-link .caret {
    width: 8px; height: 8px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    transition: transform 0.28s var(--ease-out);
    opacity: 0.6;
  }
  .nav-link[aria-expanded='true'] .caret { transform: rotate(-135deg) translate(-2px, -2px); }

  .nav-item { position: relative; }
  .nav-panel {
    position: absolute;
    top: calc(100% + 14px);
    left: -0.4rem;
    min-width: 220px;
    padding: 0.45rem;
    border-radius: var(--radius-l);
    border: 1px solid var(--hairline-2);
    background: linear-gradient(165deg, rgba(10, 24, 48, 0.96), rgba(4, 10, 22, 0.97));
    backdrop-filter: blur(26px);
    box-shadow: 0 34px 90px -34px rgba(0, 0, 0, 0.9), var(--glow);
    opacity: 0;
    visibility: hidden;
    transform: translate3d(0, -8px, 0) scale(0.985);
    transition: opacity 0.28s var(--ease-out), transform 0.34s var(--ease-out), visibility 0.34s;
  }
  /* invisible bridge so the pointer can travel from pill to panel */
  .nav-panel::before { content: ''; position: absolute; left: 0; right: 0; top: -16px; height: 16px; }
  .nav-item.is-open .nav-panel { opacity: 1; visibility: visible; transform: none; }
  .nav-panel a {
    display: block;
    padding: 0.62rem 0.85rem;
    border-radius: var(--radius-m);
    font-size: var(--step--1);
    color: var(--fg-dim);
    transition: background 0.2s, color 0.2s, transform 0.24s var(--ease-out);
  }
  .nav-panel a:hover { background: var(--surface-2); color: var(--paper-100); transform: translateX(3px); }

  /* ---------- Head actions ---------- */
  .head-actions { display: flex; align-items: center; gap: 0.55rem; flex: 0 0 auto; }

  .lang-switch {
    display: inline-flex;
    align-items: center;
    height: var(--pill-h);
    padding: 0.3rem;
  }
  .lang-switch a {
    display: inline-flex; align-items: center;
    height: 100%;
    padding: 0 0.9rem;
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.08em;
    color: var(--fg-faint);
    transition: background 0.24s, color 0.24s;
  }
  .lang-switch a[aria-current='true'] { background: rgba(255, 255, 255, 0.10); color: var(--paper-100); }
  .lang-switch a:hover { color: var(--paper-100); }

  .btn {
    --btn-bg: var(--surface-2);
    --btn-fg: var(--paper-100);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
    padding: 0.72rem 1.35rem;
    border-radius: 999px;
    border: 1px solid var(--hairline-2);
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-size: var(--step--1);
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    overflow: hidden;
    isolation: isolate;
    transition: transform 0.3s var(--ease-out), border-color 0.3s, box-shadow 0.3s;
  }
  /* The inline icons ship as <svg viewBox> with no width/height. Inside a
     shrink-to-fit button that resolves to 0x0 — every CTA arrow on the site
     was rendering at zero — and inside a stretched one (the contact form's
     submit is a grid item) it resolved to the full column, which is how Send
     became a 471px disc. Give the icon a real, text-relative size. */
  .btn svg { width: 1.05em; height: 1.05em; flex: 0 0 auto; }

  .btn::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: radial-gradient(120% 160% at 50% 120%, rgba(111, 212, 255, 0.4), transparent 62%);
    opacity: 0;
    transition: opacity 0.34s var(--ease-out);
  }
  .btn:hover { transform: translateY(-2px); border-color: var(--ice-400); box-shadow: var(--glow); }
  .btn:hover::after { opacity: 1; }
  .btn:active { transform: translateY(0); }

  .btn-primary {
    --btn-fg: #02060f;
    border-color: transparent;
    background: linear-gradient(120deg, var(--ice-300), var(--ice-400) 42%, var(--sig-500));
    background-size: 180% 180%;
    animation: btn-shift 9s var(--ease-in-out) infinite alternate;
    font-weight: 700;
  }
  @keyframes btn-shift { to { background-position: 100% 50%; } }
  .btn-ghost { border-color: var(--hairline); background: transparent; }
  .btn-sm { padding: 0.5rem 1rem; font-size: var(--step--2); }
  .head-actions .btn-primary { height: var(--pill-h); padding: 0 1.5rem; font-size: var(--step--1); box-shadow: 0 18px 44px -22px rgba(46, 109, 255, 0.9); }

  /* ---------- Mobile nav ---------- */
  /* Flex column, not grid: grid's auto rows stretch to fill the 52px pill, so
     the three bars ended up ~17px apart and the translateY(5.5px) that is
     meant to fold them into an X left a visible chevron instead. With an
     explicit 4px gap each outer bar sits exactly 5.5px off centre, which is
     what the open-state transforms below already assume. */
  .burger {
    display: none;
    width: var(--pill-h); height: var(--pill-h);
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
  }
  .burger i { display: block; width: 17px; height: 1.5px; background: var(--paper-200); transition: transform 0.34s var(--ease-out), opacity 0.24s; }
  .burger[aria-expanded='true'] i:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
  .burger[aria-expanded='true'] i:nth-child(2) { opacity: 0; }
  .burger[aria-expanded='true'] i:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

  @media (max-width: 1500px) {
    .nav-link { padding: 0 0.7rem; font-size: 0.82rem; }
  }
  @media (max-width: 1120px) {
    /* The drawer is z-index 45 inside .site-head's stacking context and, on a
       phone, covers the full viewport — so the burger has to be lifted above
       it or it is buried the moment the menu opens and there is no way back
       out. It already animates into an X on aria-expanded; it was simply
       being painted underneath. */
    .burger { display: flex; position: relative; z-index: 46; }

    /* Two controls for one setting: the header pill and the drawer's copy.
       Below 1120px the row has to hold a logo, a language pill, a CTA and a
       burger, and the language pill is the one of the four that already has
       a home one tap away. The drawer keeps it; the row drops it. */
    .head-actions .lang-switch { display: none; }

    /* What holds the burger against the right edge above 1120px is the nav
       capsule's `margin-inline: auto` — but down here the nav is the fixed
       drawer and takes no room in the row. The pills used to span the width
       on their own; with the language pill gone (and the CTA gone again at
       640px) the row is short enough to bunch up on the left. */
    .head-actions { margin-left: auto; }

    /* The burger doubles as the drawer's close button, but it lives in the
       page header, which is `position: sticky`. Locking the page with
       `overflow: hidden` takes the header out of its sticky context, so
       wherever the visitor happened to be on the page the header could end up
       scrolled part-way off — and the X with it. While the drawer is open the
       header is pinned to the viewport instead, so the way out is always in
       the same place. */
    html.nav-locked .site-head {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
    }

    /* Second way out, and the only one at tablet widths where the drawer is
       420px wide and the page is still visible beside it. */
    .nav-scrim {
      position: fixed;
      inset: 0;
      z-index: 44;
      background: rgba(2, 6, 15, 0.64);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.42s var(--ease-out);
    }
    body.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

    /* The drawer itself no longer scrolls: .nav-scroll does. That is what
       lets the sky and the clip stay pinned to the panel while the links
       move over them — an absolutely positioned child of a scroll container
       scrolls away with the content, and sizes to the visible box, not the
       scrollable one. The old backdrop-filter is gone with it: the panel
       paints its own sky at full opacity, so blurring the page behind it
       was a full-screen filtered surface producing nothing visible. */
    .nav {
      position: fixed;
      inset: 0 0 0 auto;
      width: min(100%, 420px);
      padding: 0;
      overflow: hidden;
      background: linear-gradient(180deg, #061225 0%, #08203c 34%, #061a30 62%, #020812 100%);
      border-left: 1px solid var(--hairline);
      transform: translate3d(100%, 0, 0);
      visibility: hidden;                    /* closed drawer is not tabbable */
      transition: transform 0.52s var(--ease-out), visibility 0s linear 0.52s;
      z-index: 45;
    }
    /* Hairline lit from the top, so the panel edge reads as an lit seam
       rather than a border. */
    .nav::before {
      content: '';
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      width: 1px;
      background: linear-gradient(180deg, rgba(111, 212, 255, 0.55), rgba(111, 212, 255, 0.06) 42%, transparent 78%);
      z-index: 3;
    }
    .nav-scroll {
      display: flex;
      flex-direction: column;
      position: relative;
      z-index: 2;
      height: 100%;
      overflow-y: auto;
      overscroll-behavior: contain;          /* no scroll chaining to the page */
      -webkit-overflow-scrolling: touch;
      padding:
        calc(5.5rem + env(safe-area-inset-top, 0px))
        max(var(--gutter), env(safe-area-inset-right, 0px))
        calc(1.6rem + env(safe-area-inset-bottom, 0px));
    }

    /* ---------- Drawer sky ----------
       The page's own field (gradient + wells + the WebGL dust) sits at
       z-index 0/1 and the drawer at 45, so none of it can show through.
       Rather than punch a hole in the panel, the panel grows its own sky in
       the same palette: two static light wells and three star layers at
       different depths, each drifting on transform alone so the whole thing
       stays on the compositor and never repaints. */
    .nav-sky {
      display: block;
      position: absolute;
      inset: 0;
      z-index: 0;
      overflow: hidden;
      pointer-events: none;
    }
    .nav-sky::after {
      content: '';
      position: absolute;
      inset: 0;
      /* The second glow used to sit low and left, and like the page's light
         wells it ramped straight to zero part-way out — the kink at the end of
         that ramp is what read as a lit patch with a visible edge near the
         bottom of the drawer. It is gone; the one that stays is eased over its
         whole radius so it has no edge to see. */
      background:
        radial-gradient(78% 42% at 82% 4%,
          rgba(111, 212, 255, 0.18) 0%,
          rgba(111, 212, 255, 0.153) 22%,
          rgba(111, 212, 255, 0.099) 44%,
          rgba(111, 212, 255, 0.05) 64%,
          rgba(111, 212, 255, 0.016) 82%,
          rgba(111, 212, 255, 0) 100%);
    }
    .nav-sky > i {
      position: absolute;
      inset: -30% -10%;
      display: block;
      /* No will-change here. Three permanently promoted layers sitting behind
         a scrolling list is a standard way to get stale tiles on mobile — the
         running animation promotes them while it needs to be promoted, which
         is enough. */
    }
    .nav-stars-1 { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Ccircle cx='76.4' cy='292.3' r='0.86' fill='%23d6f0ff' opacity='0.48'/%3E%3Ccircle cx='273.9' cy='115.5' r='0.58' fill='%236fd4ff' opacity='0.24'/%3E%3Ccircle cx='311.3' cy='170.0' r='0.78' fill='%23d6f0ff' opacity='0.37'/%3E%3Ccircle cx='248.8' cy='249.5' r='0.76' fill='%236fd4ff' opacity='0.35'/%3E%3Ccircle cx='116.0' cy='154.1' r='0.60' fill='%236fd4ff' opacity='0.43'/%3E%3Ccircle cx='114.6' cy='57.2' r='1.04' fill='%23d6f0ff' opacity='0.25'/%3E%3Ccircle cx='146.0' cy='34.6' r='0.61' fill='%236fd4ff' opacity='0.39'/%3E%3Ccircle cx='27.1' cy='193.8' r='1.01' fill='%23d6f0ff' opacity='0.29'/%3E%3Ccircle cx='112.9' cy='100.1' r='0.81' fill='%23d6f0ff' opacity='0.42'/%3E%3Ccircle cx='50.6' cy='279.7' r='0.86' fill='%236fd4ff' opacity='0.33'/%3E%3Ccircle cx='155.1' cy='57.0' r='0.68' fill='%23d6f0ff' opacity='0.48'/%3E%3Ccircle cx='157.7' cy='56.0' r='0.77' fill='%23d6f0ff' opacity='0.27'/%3E%3Ccircle cx='221.3' cy='243.2' r='0.62' fill='%236fd4ff' opacity='0.37'/%3E%3Ccircle cx='282.5' cy='118.8' r='0.75' fill='%236fd4ff' opacity='0.40'/%3E%3Ccircle cx='161.2' cy='154.2' r='0.94' fill='%23d6f0ff' opacity='0.49'/%3E%3Ccircle cx='283.1' cy='66.3' r='0.69' fill='%23d6f0ff' opacity='0.49'/%3E%3Ccircle cx='66.8' cy='16.7' r='0.70' fill='%236fd4ff' opacity='0.45'/%3E%3Ccircle cx='67.4' cy='163.0' r='0.93' fill='%23d6f0ff' opacity='0.34'/%3E%3Ccircle cx='112.7' cy='65.8' r='0.99' fill='%23d6f0ff' opacity='0.28'/%3E%3Ccircle cx='223.9' cy='140.9' r='0.68' fill='%23d6f0ff' opacity='0.37'/%3E%3Ccircle cx='32.2' cy='123.5' r='0.78' fill='%236fd4ff' opacity='0.43'/%3E%3Ccircle cx='247.6' cy='74.1' r='0.89' fill='%23d6f0ff' opacity='0.38'/%3E%3Ccircle cx='237.6' cy='263.3' r='0.83' fill='%23d6f0ff' opacity='0.46'/%3E%3Ccircle cx='239.0' cy='139.4' r='1.05' fill='%23d6f0ff' opacity='0.48'/%3E%3Ccircle cx='90.2' cy='271.3' r='0.96' fill='%236fd4ff' opacity='0.50'/%3E%3Ccircle cx='9.4' cy='282.8' r='0.67' fill='%23d6f0ff' opacity='0.49'/%3E%3Ccircle cx='295.8' cy='266.9' r='0.87' fill='%23d6f0ff' opacity='0.38'/%3E%3Ccircle cx='59.5' cy='8.6' r='0.55' fill='%236fd4ff' opacity='0.26'/%3E%3C/svg%3E"); animation: nav-drift 150s linear infinite; }
    .nav-stars-2 { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='440' height='440'%3E%3Ccircle cx='107.5' cy='80.7' r='1.02' fill='%23d6f0ff' opacity='0.44'/%3E%3Ccircle cx='142.4' cy='174.0' r='1.43' fill='%236fd4ff' opacity='0.36'/%3E%3Ccircle cx='143.0' cy='52.2' r='0.98' fill='%236fd4ff' opacity='0.58'/%3E%3Ccircle cx='133.2' cy='406.5' r='1.28' fill='%23d6f0ff' opacity='0.51'/%3E%3Ccircle cx='16.6' cy='158.9' r='1.19' fill='%23d6f0ff' opacity='0.54'/%3E%3Ccircle cx='239.1' cy='250.5' r='1.33' fill='%23d6f0ff' opacity='0.45'/%3E%3Ccircle cx='300.4' cy='123.1' r='1.26' fill='%23d6f0ff' opacity='0.34'/%3E%3Ccircle cx='1.3' cy='262.9' r='1.16' fill='%23d6f0ff' opacity='0.57'/%3E%3Ccircle cx='267.4' cy='337.7' r='1.11' fill='%236fd4ff' opacity='0.46'/%3E%3Ccircle cx='64.1' cy='190.1' r='0.91' fill='%236fd4ff' opacity='0.48'/%3E%3Ccircle cx='77.9' cy='94.9' r='1.48' fill='%23d6f0ff' opacity='0.58'/%3E%3Ccircle cx='109.5' cy='302.4' r='1.10' fill='%23d6f0ff' opacity='0.45'/%3E%3Ccircle cx='329.8' cy='256.0' r='0.98' fill='%23d6f0ff' opacity='0.53'/%3E%3Ccircle cx='43.3' cy='239.8' r='1.27' fill='%23d6f0ff' opacity='0.45'/%3E%3Ccircle cx='417.8' cy='304.8' r='1.33' fill='%23d6f0ff' opacity='0.39'/%3E%3Ccircle cx='356.4' cy='317.0' r='1.05' fill='%23d6f0ff' opacity='0.32'/%3E%3Ccircle cx='386.3' cy='69.5' r='0.93' fill='%23d6f0ff' opacity='0.50'/%3E%3Ccircle cx='170.6' cy='68.7' r='0.94' fill='%236fd4ff' opacity='0.59'/%3E%3C/svg%3E"); animation: nav-drift 96s linear infinite reverse; opacity: 0.9; }
    .nav-stars-3 { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Ccircle cx='164.7' cy='154.9' r='1.95' fill='%23d6f0ff' opacity='0.57'/%3E%3Ccircle cx='387.1' cy='9.8' r='1.71' fill='%23d6f0ff' opacity='0.75'/%3E%3Ccircle cx='429.3' cy='320.4' r='1.69' fill='%23d6f0ff' opacity='0.49'/%3E%3Ccircle cx='394.9' cy='522.0' r='2.13' fill='%23d6f0ff' opacity='0.78'/%3E%3Ccircle cx='565.5' cy='157.1' r='2.08' fill='%23d6f0ff' opacity='0.57'/%3E%3Ccircle cx='2.8' cy='190.2' r='1.90' fill='%23d6f0ff' opacity='0.67'/%3E%3Ccircle cx='309.5' cy='227.6' r='2.06' fill='%23d6f0ff' opacity='0.59'/%3E%3Ccircle cx='586.5' cy='246.2' r='1.90' fill='%23d6f0ff' opacity='0.77'/%3E%3Ccircle cx='445.7' cy='95.1' r='2.29' fill='%236fd4ff' opacity='0.77'/%3E%3C/svg%3E"); animation: nav-drift 64s linear infinite; }
    /* One tile height per cycle, so the loop is seamless. */
    @keyframes nav-drift {
      from { transform: translate3d(0, 0, 0); }
      to   { transform: translate3d(0, -320px, 0); }
    }
    .nav-stars-2 { animation-name: nav-drift-2; }
    @keyframes nav-drift-2 {
      from { transform: translate3d(0, 0, 0); }
      to   { transform: translate3d(0, -440px, 0); }
    }
    .nav-stars-3 { animation-name: nav-drift-3; }
    @keyframes nav-drift-3 {
      from { transform: translate3d(0, 0, 0); }
      to   { transform: translate3d(0, -600px, 0); }
    }

    /* ---------- Drawer footer ----------
       The header CTA is hidden below 640px, so on a phone this is the only
       place "Open an account" appears above the fold of the menu. */
    .nav-foot {
      display: grid;
      gap: 0.55rem;
      margin-top: auto;
      padding-top: 1.5rem;
      padding-bottom: 2rem;
      border-top: 1px solid var(--hairline);
    }
    .nav-cta { width: 100%; justify-content: center; }
    /* The header no longer carries a switch at these widths (see below), so
       this is the only one. It sits directly under the last link, aligned to
       the same edge, which reads as the tail of the list rather than as part
       of the call to action it used to sit beneath. */
    .nav-lang {
      display: flex;
      margin: 1.15rem 0 0 0.6rem;
    }

    /* ---------- Drawer clip ----------
       Same ambient frame the market sections use, on the same screen blend:
       the footage sits on black, so the plate falls away and only the object
       floats over the drawer's sky. */
    .nav-clip {
      display: block;
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: min(52vw, 230px);
      z-index: 1;
      overflow: hidden;
      pointer-events: none;
    }
    .nav-clip video {
      position: absolute;
      right: 0;
      bottom: -6%;
      width: min(82%, 310px);
      height: auto;
      mix-blend-mode: screen;
      /* Low enough that a scrolled-up link reads cleanly straight over it. */
      opacity: 0.44;
      filter: hue-rotate(198deg) saturate(0.8) brightness(0.95);
      mask-image: radial-gradient(closest-side, #000 54%, transparent 100%);
      -webkit-mask-image: radial-gradient(closest-side, #000 54%, transparent 100%);
    }

    /* ---------- Row entrance ----------
       The panel used to slide in with every link already in place. Each row
       now arrives just behind the panel edge, 38ms apart. */
    .nav-list > .nav-item + .nav-item { border-top: 1px solid rgba(255, 255, 255, 0.055); }
    .nav-list > .nav-item { position: relative; }
    /* A lit tick on the row you are already on. */
    .nav-item:has(> [aria-current='page'])::before,
    .nav-item:has(> [data-active='true'])::before {
      content: '';
      position: absolute;
      left: -0.6rem;
      top: 50%;
      width: 2px;
      height: 18px;
      margin-top: -9px;
      border-radius: 2px;
      background: var(--ice-400);
      box-shadow: 0 0 12px rgba(111, 212, 255, 0.55);
    }
    .nav-list > .nav-item {
      opacity: 0;
      transform: translate3d(18px, 0, 0);
      transition:
        opacity 0.42s var(--ease-out) calc(var(--i, 0) * 38ms + 120ms),
        transform 0.52s var(--ease-out) calc(var(--i, 0) * 38ms + 120ms);
    }
    body.nav-open .nav-list > .nav-item { opacity: 1; transform: none; }
    body.nav-open .nav {
      transform: none;
      visibility: visible;
      transition: transform 0.52s var(--ease-out), visibility 0s;
    }
    /* Both of these have to out-specify `.site-head.is-stuck .nav-list`, which
       is what dresses the capsule once the page is scrolled. The drawer's list
       is a descendant of the header too, so that rule was landing on it: open
       the menu anywhere but the top of the page and the links sat on a dark
       plate with a pill radius and a border. That is the "menu glitches
       sometimes" — it was never intermittent, it was scroll position. */
    .nav-list,
    .site-head.is-stuck .nav-list {
      flex-direction: column;
      align-items: stretch;
      gap: 0.1rem;
      height: auto;
      padding: 0;
      border: 0;
      background: none;
      backdrop-filter: none;
      box-shadow: none;
      border-radius: 0;
    }
    .nav-link { justify-content: space-between; height: auto; padding: 0.85rem 0.6rem; font-size: var(--step-0); border-radius: var(--radius-s); }
    .nav-panel {
      position: static;
      opacity: 1;
      visibility: visible;
      transform: none;
      display: none;
      border: 0;
      background: none;
      box-shadow: none;
      backdrop-filter: none;
      min-width: 0;
      padding: 0 0 0.6rem 0.9rem;
      border-left: 1px solid var(--hairline);
      margin-left: 0.6rem;
    }
    .nav-item.is-open .nav-panel { display: grid; }
  }
  .head-actions .btn .short { display: none; }
  @media (max-width: 640px) {
    .head-actions .btn-primary { display: none; }
    .head-inner { gap: 0.7rem; }
  }

  /* Every in-page jump — the skip link to #main, the anchor rail, #contracts,
     #chart, #faq — lands the target's top at viewport 0. The header is sticky
     and about 70px tall, so whatever sits in the first rows of that section
     (the instrument table's filter and group controls, for one) was parked
     underneath it. scroll-margin-top holds the jump clear of the header. */
  [id] { scroll-margin-top: calc(var(--pill-h) + 2.6rem); }

  /* ---------- Section flow --------------------------------------
     Sections are pure rhythm. No borders, no backgrounds — the
     separation is done by the fixed field behind them.
  ---------------------------------------------------------------- */
  main { display: block; }
  /* Each band owns half the gap, so two adjacent bands sit exactly --flow apart. */
  .band { position: relative; padding-block: calc(var(--flow) * 0.5); }
  .band-tight { padding-block: calc(var(--flow) * 0.32); }
  .band-flush { padding-block: 0 calc(var(--flow) * 0.5); }

  .band-head { display: grid; gap: 0.9rem; max-width: 74ch; margin-bottom: clamp(1.4rem, 2.6vw, 2.4rem); }
  .band-head.is-centered { margin-inline: auto; text-align: center; justify-items: center; }
  .band-head.is-centered .lede { margin-inline: auto; }
  .band-head.is-split {
    max-width: none;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
    align-items: end;
    gap: clamp(1.5rem, 4vw, 4rem);
  }
  @media (max-width: 860px) { .band-head.is-split { grid-template-columns: 1fr; align-items: start; } }

  /* ---------- Footer ----------------------------------------------
     A rounded island that mirrors the primary nav column-for-column,
     with the brand name rendered as a cursor-revealed SVG outline.
  ---------------------------------------------------------------- */
  .site-foot {
    position: relative;
    margin: calc(var(--flow) * 0.6) var(--gutter) 1.25rem;
    border-radius: var(--radius-xl);
    border: 1px solid var(--hairline);
    overflow: hidden;
    isolation: isolate;
    background: rgba(6, 16, 32, 0.28);
    backdrop-filter: blur(18px);
  }
  .foot-bg {
    position: absolute; inset: 0; z-index: 0;
    background: radial-gradient(125% 125% at 50% 10%, rgba(6, 16, 32, 0.45) 45%, rgba(46, 109, 255, 0.28) 100%);
  }
  .foot-inner {
    position: relative; z-index: 3;
    width: min(100%, var(--shell));
    margin-inline: auto;
    padding: clamp(2.4rem, 4.5vw, 4rem) clamp(1.4rem, 4vw, 3.5rem) 0;
  }
  .foot-grid {
    display: grid;
    /* Columns take their natural width and the free space is distributed
       between them, so the visual distance between neighbouring lists is
       identical regardless of how long each column's labels are. */
    grid-template-columns: minmax(220px, 300px) repeat(5, max-content);
    justify-content: space-between;
    gap: clamp(1.6rem, 3vw, 3rem) clamp(1.2rem, 2vw, 2.2rem);
  }
  .foot-col { max-width: 190px; }
  @media (max-width: 1240px) { .foot-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); justify-content: stretch; } .foot-brand { grid-column: 1 / -1; } .foot-col { max-width: none; } }
  @media (max-width: 720px) { .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 460px) { .foot-grid { grid-template-columns: 1fr; } }

  .foot-brand { display: grid; gap: 1.1rem; align-content: start; max-width: 38ch; }
  .foot-blurb { font-size: var(--step--1); color: var(--fg-dim); line-height: 1.7; }
  .foot-contact { display: grid; gap: 0.7rem; font-size: var(--step--1); color: var(--fg-dim); }
  .foot-contact li { display: flex; gap: 0.7rem; align-items: flex-start; }
  .foot-contact a:hover { color: var(--ice-300); }

  .foot-col h5 {
    font-family: var(--font-display);
    font-size: var(--step-0);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--paper-100);
    margin-bottom: 1.1rem;
  }
  .foot-col ul { display: grid; gap: 0.6rem; }
  .foot-col a {
    font-size: var(--step--1); color: var(--fg-dim);
    display: block; line-height: 1.5;
    transition: color 0.2s, transform 0.24s var(--ease-out);
  }
  .foot-col a:hover { color: var(--ice-300); transform: translateX(3px); }

  .foot-inner-bottom { padding-top: 0; padding-bottom: clamp(1.6rem, 3vw, 2.4rem); }
  .foot-rule { border: 0; height: 1px; margin-block: 0 1.4rem;
    background: linear-gradient(90deg, transparent, var(--hairline-2) 15%, var(--hairline-2) 85%, transparent); }
  .foot-bottom { display: grid; gap: 0.7rem; font-size: var(--step--2); color: var(--fg-faint); line-height: 1.7; }
  .foot-risk { max-width: 110ch; color: var(--fg-dim); }
  .foot-risk strong { color: var(--warn); }
  .foot-copy { color: var(--fg-faint); }

  /* Giant brand outline. Hidden on small screens like the reference. */
  .foot-hover {
    position: relative; z-index: 2;
    display: none;
    height: clamp(12rem, 26vw, 28rem);
    margin-top: calc(clamp(12rem, 26vw, 28rem) * -0.12);
    margin-bottom: calc(clamp(12rem, 26vw, 28rem) * -0.2);
    cursor: pointer;
  }
  @media (min-width: 900px) { .foot-hover { display: block; } }
  @media (max-width: 899px) { .foot-inner-bottom { padding-top: 2.2rem; } }
  .foot-hover svg { width: 100%; height: 100%; user-select: none; overflow: visible; }
  .foot-hover .ft {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 78px;
    letter-spacing: -0.04em;
    fill: transparent;
    stroke-width: 0.35;
    text-transform: uppercase;
  }
  .foot-hover .ft-base { stroke: rgba(165, 230, 255, 0.45); opacity: 0; transition: opacity 0.4s; }
  .foot-hover svg.is-hot .ft-base { opacity: 0.7; }
  .foot-hover .ft-draw { stroke: var(--sig-400); stroke-dasharray: 1000; stroke-dashoffset: 1000; }
  .js-ready .foot-hover.is-in .ft-draw { animation: foot-draw 4s var(--ease-in-out) forwards; }
  html:not(.js-ready) .foot-hover .ft-draw { stroke-dashoffset: 0; }
  @keyframes foot-draw { to { stroke-dashoffset: 0; } }
  .foot-hover .ft-glow { stroke-width: 0.45; opacity: 0; transition: opacity 0.35s; }
  .foot-hover svg.is-hot .ft-glow { opacity: 1; }

  /* ---------- Breadcrumb ---------- */
  .crumbs {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem;
    font-family: var(--font-mono); font-size: var(--step--2);
    color: var(--fg-faint); padding-top: 2.2rem;
  }
  .crumbs a { color: var(--fg-faint); transition: color 0.2s; }
  .crumbs a:hover { color: var(--ice-300); }
  .crumbs li { display: inline-flex; align-items: center; gap: 0.45rem; list-style: none; }
  .crumbs li + li::before { content: '/'; color: rgba(140, 180, 230, 0.32); }

  /* Page scroll lock while the drawer is open. Declared in @layer layout so
     it wins over `html { overflow-x: clip }` in @layer reset. */
  html.nav-locked, html.nav-locked body { overflow: hidden; }

  /* ---------- Scroll progress ---------- */
  .progress {
    position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
    background: linear-gradient(90deg, var(--ice-400), var(--sig-500));
    transform-origin: 0 50%;
    transform: scaleX(var(--scroll));
    pointer-events: none;
  }
}

/* ============================================================
   REVEAL CHOREOGRAPHY
   Every element carries data-reveal="<variant>". The observer in
   js/reveal.js flips .is-in. Variants deliberately differ per
   section so the page never repeats the same entrance twice.
   ============================================================ */
@layer reveal {
  .js-ready [data-reveal] {
    --rv-delay: 0ms;
    opacity: 0;
    /* No will-change here on purpose: it would promote every reveal target
       on the page — 48 of them on the home page — to its own compositor
       layer for the whole session. js/reveal.js applies the hint to one
       element at a time, for the length of its entrance only. */
    transition:
      opacity var(--dur-2) var(--ease-out) var(--rv-delay),
      transform var(--dur-3) var(--ease-out) var(--rv-delay),
      filter var(--dur-2) var(--ease-out) var(--rv-delay),
      clip-path var(--dur-3) var(--ease-out) var(--rv-delay);
  }
  .js-ready [data-reveal].is-in { opacity: 1; transform: none; filter: none; clip-path: inset(0 0 0 0); }

  .js-ready [data-reveal='up']     { transform: translate3d(0, 46px, 0); }
  .js-ready [data-reveal='down']   { transform: translate3d(0, -38px, 0); }
  .js-ready [data-reveal='left']   { transform: translate3d(-72px, 14px, 0) rotate(-1.4deg); }
  .js-ready [data-reveal='right']  { transform: translate3d(72px, 14px, 0) rotate(1.4deg); }
  .js-ready [data-reveal='far-left']  { transform: translate3d(-160px, 40px, 0) scale(0.9) rotate(-3deg); filter: blur(6px); }
  .js-ready [data-reveal='far-right'] { transform: translate3d(160px, 40px, 0) scale(0.9) rotate(3deg); filter: blur(6px); }

  /* "grows from a small tile" — the signature entrance */
  .js-ready [data-reveal='grow']   { transform: translate3d(0, 60px, 0) scale(0.62); filter: blur(9px); }
  .js-ready [data-reveal='grow-tl']{ transform: translate3d(-90px, 70px, 0) scale(0.55) rotate(-5deg); filter: blur(10px); transform-origin: top left; }
  .js-ready [data-reveal='grow-tr']{ transform: translate3d(90px, 70px, 0) scale(0.55) rotate(5deg); filter: blur(10px); transform-origin: top right; }

  .js-ready [data-reveal='rise']   { transform: translate3d(0, 90px, 0) scale(0.94); filter: blur(4px); }
  .js-ready [data-reveal='tilt']   { transform: perspective(1400px) rotateX(16deg) translate3d(0, 70px, 0) scale(0.93); transform-origin: 50% 100%; }
  .js-ready [data-reveal='swing-l']{ transform: perspective(1600px) rotateY(26deg) translate3d(-80px, 24px, 0); transform-origin: left center; }
  .js-ready [data-reveal='swing-r']{ transform: perspective(1600px) rotateY(-26deg) translate3d(80px, 24px, 0); transform-origin: right center; }

  /* The wipes run as keyframes, not as a transition off a resting clip-path.
     Chrome folds clip-path into the rect IntersectionObserver measures, so an
     element parked at inset(100%) reports intersectionRatio 0 no matter where
     it sits on screen — it hides from the very observer that adds .is-in and
     stays invisible for good. (Measured: ratio 0 clipped, 0.38 unclipped, same
     element, same scroll position.) Only the first screen escaped it, because
     those are revealed without the observer. The hidden state now leans on
     opacity alone, which IO ignores by spec. */
  .js-ready [data-reveal='wipe-r'] { transform: translate3d(-24px, 0, 0); }
  .js-ready [data-reveal='wipe-l'] { transform: translate3d(24px, 0, 0); }
  .js-ready [data-reveal='wipe-u'] { transform: translate3d(0, 24px, 0); }

  .js-ready [data-reveal='wipe-r'].is-in { animation: wipe-r var(--dur-3) var(--ease-out) var(--rv-delay) both; }
  .js-ready [data-reveal='wipe-l'].is-in { animation: wipe-l var(--dur-3) var(--ease-out) var(--rv-delay) both; }
  .js-ready [data-reveal='wipe-u'].is-in { animation: wipe-u var(--dur-3) var(--ease-out) var(--rv-delay) both; }

  @keyframes wipe-r { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
  @keyframes wipe-l { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }
  @keyframes wipe-u { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }

  .js-ready [data-reveal='fade']   { transform: none; }
  .js-ready [data-reveal='zoom-out']{ transform: scale(1.14); filter: blur(8px); }

  /* Word-level headline reveal, built by js/reveal.js */
  .split-line { display: block; overflow: hidden; padding-bottom: 0.08em; }
  .split-word { display: inline-block; }
  .js-ready .split-word {
    transform: translate3d(0, 110%, 0) rotate(4deg);
    transition: transform 1.05s var(--ease-out) var(--w-delay, 0ms);
  }
  .js-ready .is-in .split-word, .js-ready [data-split].is-in .split-word { transform: none; }

  @media (max-width: 760px) {
    .js-ready [data-reveal='left']      { transform: translate3d(-34px, 12px, 0); }
    .js-ready [data-reveal='right']     { transform: translate3d(34px, 12px, 0); }
    .js-ready [data-reveal='far-left']  { transform: translate3d(-48px, 30px, 0) scale(0.94); filter: blur(4px); }
    .js-ready [data-reveal='far-right'] { transform: translate3d(48px, 30px, 0) scale(0.94); filter: blur(4px); }
    .js-ready [data-reveal='grow-tl']   { transform: translate3d(-30px, 50px, 0) scale(0.7); }
    .js-ready [data-reveal='grow-tr']   { transform: translate3d(30px, 50px, 0) scale(0.7); }
    .js-ready [data-reveal='swing-l']   { transform: perspective(1200px) rotateY(14deg) translate3d(-30px, 18px, 0); }
    .js-ready [data-reveal='swing-r']   { transform: perspective(1200px) rotateY(-14deg) translate3d(30px, 18px, 0); }
  }

  @media (prefers-reduced-motion: reduce) {
    [data-reveal] { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; }
    .split-word { transform: none !important; }
    .rail-track { animation: none; }
    .nav-sky > i { animation: none; }
    .nav-clip { display: none; }
    .nav-list > .nav-item { opacity: 1 !important; transform: none !important; transition: none; }
  }
}
