/* =========================================================================
   AInnect dashboard — SHELL LAYER
   Tokens, reset, background, chrome (nav / menu / dots), hero + orb card.
   Pane-level layout lives in deck.css. No selector is defined in both files.
   ========================================================================= */

/* ---------- design tokens ---------- */
:root {
  color-scheme: light;
  /* TEXT — three weights, all verified >= 4.5:1 (WCAG AA body text) against
     every surface below, in BOTH themes. Never colour text with the --line-*
     tokens; they are decoration and fail contrast by design. */
  --text-1:   #0d1117;
  --text-2:   #2c343f;
  --text-3:   #444e59;

  --ink:      #0d1117;
  --line:        rgba(13, 17, 23, 0.10);
  --line-strong: rgba(13, 17, 23, 0.42);
  --ink-12:   rgba(13, 17, 23, 0.12);
  --ink-08:   rgba(13, 17, 23, 0.08);
  --ink-05:   rgba(13, 17, 23, 0.05);

  --pos:      #0a5c39;
  --neg:      #8f1a10;
  --link:     #4c1d95;

  --page:     #eef1f4;
  --scrim:    rgba(245, 247, 249, 0.62);
  --wash:     238, 241, 244;          /* hero copy wash, as an rgb triplet */
  --orb-opacity: 1;

  --glass-1:  rgba(255, 255, 255, 0.30);
  --glass-2:  rgba(255, 255, 255, 0.46);
  --glass-3:  rgba(255, 255, 255, 0.66);
  --glass-hi: rgba(255, 255, 255, 0.45);
  --frost:    rgba(255, 255, 255, 0.34);
  --frost-strong: rgba(255, 255, 255, 0.62);   /* surfaces over the raw orb */

  /* spacing scale (4px base) */
  --s-1: 0.25rem; --s-2: 0.5rem;  --s-3: 0.75rem; --s-4: 1rem;
  --s-5: 1.25rem; --s-6: 1.5rem;  --s-7: 2rem;    --s-8: 3rem;

  /* radii */
  --r-sm: 12px; --r-md: 16px; --r-lg: 22px; --r-xl: 30px; --r-orb: 48px;
  --r-pill: 999px;

  /* Type scale. Nothing below 12px: the previous floor was 10.9px, which is
     under the practical minimum for body-adjacent text on the web. */
  --fs-micro: 0.88rem;  /* 14.1px */
  --fs-kick:  0.92rem;  /* 14.7px */
  --fs-xs:    1.00rem;  /* 16.0px */
  --fs-sm:    1.07rem;  /* 17.1px */
  --fs-md:    1.15rem;  /* 18.4px */
  --fs-lg:    1.30rem;  /* 20.8px */
  --fs-title: 1.9rem;
  --fs-hero:  2.5rem;

  /* elevation */
  --sh-tile: 0 4px 18px -10px rgba(20, 30, 40, 0.28);
  --sh-pane: 0 12px 40px -18px rgba(20, 30, 40, 0.30);
  --sh-inset: inset 0 1.5px 2px rgba(255, 255, 255, 0.40),
              inset 0 -1px 2px rgba(0, 0, 0, 0.06);

  /* motion */
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* content measure — keeps wide screens from stranding data at the edges */
  --measure: 1560px;
}

/* ---------- dark theme ----------
   Same token names, different values, so no component needs to know which
   theme it is in. The orb is a bright clip, so it is dimmed here rather than
   left to glare against a dark page. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --text-1:   #f4f7fa;
  --text-2:   #ccd5df;
  --text-3:   #9dabb9;

  --ink:      #f4f7fa;
  --line:        rgba(255, 255, 255, 0.12);
  --line-strong: rgba(255, 255, 255, 0.38);
  --ink-12:   rgba(255, 255, 255, 0.12);
  --ink-08:   rgba(255, 255, 255, 0.09);
  --ink-05:   rgba(255, 255, 255, 0.06);

  --pos:      #5fd39b;
  --neg:      #ff8f85;
  --link:     #c3b0f5;

  --page:     #0d1014;
  --scrim:    rgba(13, 16, 20, 0.74);
  --wash:     13, 16, 20;
  --orb-opacity: 0.72;

  --glass-1:  rgba(255, 255, 255, 0.05);
  --glass-2:  rgba(255, 255, 255, 0.08);
  --glass-3:  rgba(255, 255, 255, 0.13);
  --glass-hi: rgba(255, 255, 255, 0.14);
  --frost:    rgba(13, 16, 20, 0.52);
  --frost-strong: rgba(13, 16, 20, 0.78);

  --sh-tile: 0 4px 18px -10px rgba(0, 0, 0, 0.7);
  --sh-pane: 0 12px 40px -18px rgba(0, 0, 0, 0.8);
  --sh-inset: inset 0 1.5px 2px rgba(255, 255, 255, 0.10),
              inset 0 -1px 2px rgba(0, 0, 0, 0.35);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --text-1: #f4f7fa; --text-2: #ccd5df; --text-3: #9dabb9;
    --ink: #f4f7fa;
    --line: rgba(255,255,255,.12); --line-strong: rgba(255,255,255,.38);
    --ink-12: rgba(255,255,255,.12); --ink-08: rgba(255,255,255,.09); --ink-05: rgba(255,255,255,.06);
    --pos: #5fd39b; --neg: #ff8f85; --link: #c3b0f5;
    --page: #0d1014; --scrim: rgba(13,16,20,.74); --wash: 13,16,20; --orb-opacity: .72;
    --glass-1: rgba(255,255,255,.05); --glass-2: rgba(255,255,255,.08);
    --glass-3: rgba(255,255,255,.13); --glass-hi: rgba(255,255,255,.14);
    --frost: rgba(13,16,20,.52); --frost-strong: rgba(13,16,20,.78);
    --sh-tile: 0 4px 18px -10px rgba(0,0,0,.7);
    --sh-pane: 0 12px 40px -18px rgba(0,0,0,.8);
    --sh-inset: inset 0 1.5px 2px rgba(255,255,255,.10), inset 0 -1px 2px rgba(0,0,0,.35);
  }
}

/* ---------- reset / base ---------- */
* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  background: var(--page);
  color: var(--text-1);
  font-family: 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon { flex: none; }

/* Visible keyboard focus. Every interactive element gets one ring, one style. */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

/* ---------- background video ---------- */
/* `cover` fills the box so there is never a letterbox band, and the feathered
   mask below dissolves the box's own edge into the page. Together they
   let the orb be scaled freely by the deck scroll (see glass-card.js) without
   either a visible video rectangle or exposed page edges. */
.bg-video {
  position: fixed; top: 0; left: 0;
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
  opacity: var(--orb-opacity);
  transform-origin: 50% 50%;
  will-change: transform;
  /* Feathered so the video's rectangular edge never reads as an edge. */
  -webkit-mask-image: radial-gradient(ellipse 58% 58% at 50% 50%, #000 52%, rgba(0,0,0,0.55) 70%, transparent 84%);
  mask-image: radial-gradient(ellipse 58% 58% at 50% 50%, #000 52%, rgba(0,0,0,0.55) 70%, transparent 84%);
}

/* Portrait stacks the copy and the mood card straight over the orb, where the
   desktop layout keeps them side by side. Lifting the orb toward the top and
   easing it back keeps the stacked content legible. */
@media (max-width: 767px) {
  .bg-video {
    opacity: 0.55;
    -webkit-mask-image: radial-gradient(ellipse 72% 42% at 50% 30%, #000 45%, rgba(0,0,0,0.5) 68%, transparent 85%);
    mask-image: radial-gradient(ellipse 72% 42% at 50% 30%, #000 45%, rgba(0,0,0,0.5) 68%, transparent 85%);
  }
}

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

/* ---------- editorial vertical rules (>=768px) ---------- */
.rule { position: absolute; top: 0; bottom: 0; display: none; flex-direction: column; align-items: center; }
.rule--left  { left: var(--s-5); }
.rule--right { right: var(--s-5); }
.rule__seg { width: 1px; background: var(--text-3); }
.rule__seg--end { height: 15%; }
.rule__seg--mid { flex: 1 1 0%; }
.rule__plus { font-size: var(--fs-xs); line-height: 1; color: var(--text-2); padding: var(--s-1) 0; }
@media (min-width: 768px) { .rule { display: flex; } }

/* ---------- top nav ---------- */
/* Fixed, not per-pane: it used to live inside the hero, so once you swiped
   into a section there was no way back to the top level except swiping. */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s-5);
}
.nav__item {
  display: inline-flex; align-items: center; gap: 0.625rem;
  color: var(--text-1); background: none; border: 0; font: inherit;
  text-decoration: none; cursor: pointer; pointer-events: auto;
  transition: opacity 300ms;
}
.nav__item:hover { opacity: 0.6; }
.nav__label { font-size: 0.875rem; line-height: 1.25rem; letter-spacing: 0.025em; }
.nav__label--menu { display: none; }
.nav::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(to bottom, var(--page) 20%, transparent);
  opacity: 0.92;
}
.nav__home { gap: var(--s-3); }
.nav__wordmark {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: -0.01em; color: var(--text-1);
}
.nav__section {
  font-size: var(--fs-micro); color: var(--text-2);
  padding-left: var(--s-3); border-left: 1px solid var(--line);
}
.nav__section:empty { display: none; }
@media (max-width: 639px) { .nav__wordmark { display: none; } .nav__section { border-left: 0; padding-left: 0; } }

.nav__right { display: flex; align-items: center; gap: var(--s-5); }
.nav__link { gap: 7px; }
.nav__badge {
  padding: 1px 7px; border-radius: var(--r-pill);
  background: var(--pos); color: var(--page);
  font-size: var(--fs-micro); font-weight: 700; font-variant-numeric: tabular-nums;
}
@media (max-width: 639px) { .nav__link { display: none; } }
.nav__icon { padding: 6px; border-radius: var(--r-pill); }
.nav__icon:hover { opacity: 1; background: var(--glass-2); }
/* one icon per theme; the other is removed from the box entirely */
.icon--moon { display: none; }
:root[data-theme="dark"] .icon--sun { display: none; }
:root[data-theme="dark"] .icon--moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .icon--sun { display: none; }
  :root:not([data-theme="light"]) .icon--moon { display: block; }
  :root[data-theme="light"] .icon--sun { display: block; }
}
.nav__dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--ink); }
@media (min-width: 640px) { .nav { padding: var(--s-5) var(--s-6); } .nav__label--menu { display: inline; } }
@media (min-width: 768px) { .nav { padding: var(--s-6) var(--s-8); } }

/* ---------- hero (pane 1) type ---------- */
.lede { position: relative; z-index: 1; max-width: 27rem; pointer-events: auto; }
/* the orb drifts behind this column; a soft wash keeps the copy legible
   without drawing a visible panel edge around it */
.lede::before {
  content: ''; position: absolute; z-index: -1;
  inset: -6rem -12rem -6rem -14rem;
  background: radial-gradient(ellipse 52% 42% at 30% 50%,
              rgba(var(--wash), 0.96) 0%,
              rgba(var(--wash), 0.86) 42%,
              rgba(var(--wash), 0.45) 66%,
              rgba(var(--wash), 0) 84%);
  pointer-events: none;
}
.lede__kick {
  font-size: var(--fs-kick); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--text-3);
}
.lede__title {
  margin-top: var(--s-2);
  font-size: 1.6rem; font-weight: 300; line-height: 1.2;
  letter-spacing: -0.025em; color: var(--text-1);
}
.lede__body {
  margin-top: var(--s-3); max-width: 300px;
  font-size: var(--fs-sm); line-height: 1.625; color: var(--text-2);
}
@media (min-width: 640px)  { .lede__title { font-size: 1.875rem; } }
@media (min-width: 768px)  { .lede__title { font-size: 2rem; } .lede__body { margin-top: var(--s-4); font-size: 0.875rem; } }
@media (min-width: 1024px) { .lede__title { font-size: var(--fs-hero); } }

/* ---------- lead story ---------- */
.lead {
  display: flex; flex-direction: column; gap: var(--s-1);
  margin-top: var(--s-5); padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--ink-08);
  border-left: 3px solid var(--link);
  background: var(--glass-3);
  text-decoration: none; color: var(--text-1);
  transition: background 220ms, transform 220ms var(--ease), box-shadow 220ms;
}
.lead:hover {
  background: rgba(255, 255, 255, 0.85);
  transform: translateX(3px);
  box-shadow: var(--sh-tile);
}
.lead__kick {
  font-size: var(--fs-micro); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--link); font-weight: 700;
}
.lead__title {
  font-size: 1.08rem; font-weight: 600; line-height: 1.35; letter-spacing: -0.012em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.lead__meta {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  margin-top: var(--s-1);
  font-size: var(--fs-micro); color: var(--text-3);
}
.lead__go { opacity: 0; transform: translateX(-4px); transition: opacity 220ms, transform 220ms; }
.lead:hover .lead__go { opacity: 1; transform: translateX(0); }

/* ---------- chamfered CTA ---------- */
.chamfer {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  width: 220px; height: 44px; margin-top: var(--s-6); padding: 0 var(--s-5);
  color: var(--text-1); background: none; border: 0; font: inherit;
  text-decoration: none; cursor: pointer; pointer-events: auto;
  transition: opacity 300ms;
}
.chamfer__glass, .chamfer__outline, .chamfer__label, .chamfer .icon {
  transition: background 220ms, border-color 220ms, color 220ms, transform 220ms var(--ease);
}
.chamfer:hover .chamfer__glass { background: var(--text-1); border-color: var(--text-1); }
.chamfer:hover .chamfer__outline { color: var(--text-1); }
.chamfer:hover .chamfer__label,
.chamfer:hover .icon { color: #fff; }
.chamfer:hover .icon { transform: translateX(4px); }
.chamfer:active { transform: scale(0.985); }
.chamfer__glass {
  position: absolute; inset: 0;
  background: var(--glass-3);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--line-strong);
  clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
}
.chamfer__outline { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.chamfer__label { position: relative; font-size: var(--fs-xs); letter-spacing: 0.025em; }
.chamfer .icon { position: relative; }
@media (min-width: 640px) {
  .chamfer { width: 260px; height: 48px; padding: 0 var(--s-6); }
  .chamfer__label { font-size: 0.875rem; }
  /* at rest the outline alone carries the shape; hover fills it in */
  .chamfer__glass { background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; border-color: transparent; }
}
@media (min-width: 768px) { .chamfer { margin-top: var(--s-7); } }

/* ---------- orb card (refracted video window) ---------- */
.card {
  position: relative; flex: none;
  display: flex; flex-direction: column; justify-content: space-between;
  width: 340px; max-width: 100%; height: 460px;
  transition: width 300ms var(--ease);
  padding: var(--s-7);
  border-radius: var(--r-orb);
  overflow: hidden;
  background: transparent;
  border: 1px solid var(--line-strong);
  pointer-events: auto;
  animation: fade-slide-up-card 900ms var(--ease-out) both;
}
@keyframes fade-slide-up-card {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* height tracks the brief: four label/value rows at the larger type scale
   need the room, and a clipped final row is worse than a taller card */
@media (min-width: 1024px) { .card { width: 430px; height: 585px; } }
@media (min-width: 1280px) { .card { width: 510px; height: 610px; } }
@media (min-width: 1600px) { .card { width: 560px; } }

/* ---------- shared liquid-glass surface ----------
   glass-card.js prepends .glass-dup (the refracted duplicate) and .glass-frost
   to every [data-glass] element. Real content is lifted above both. */
[data-glass] { position: relative; overflow: hidden; isolation: isolate; }
[data-glass] > .glass-dup { position: absolute; left: 0; top: 0; z-index: 0; overflow: hidden; pointer-events: none; }
[data-glass] > .glass-dup > canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  filter: url(#liquid-glass-refraction);
}
[data-glass] > .glass-frost {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  /* 34%, not the original 5%: the card's text sits over a moving orb, and at
     5% its legibility changed frame to frame. The refraction concentrates at
     the edges, so this steadies the copy without flattening the glass. */
  background: var(--frost);
  box-shadow: var(--sh-inset);
  transition: background 400ms, filter 400ms;
}
[data-glass] > *:not(.glass-dup):not(.glass-frost) { position: relative; z-index: 2; }
.card.group:hover > .glass-frost { filter: brightness(1.06); }

.card__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
  padding-bottom: var(--s-3); border-bottom: 1px solid var(--line);
}
.card__title { font-size: var(--fs-lg); font-weight: 500; letter-spacing: -0.025em; }
.card__index { font-size: var(--fs-xs); color: var(--text-1); font-variant-numeric: tabular-nums; }
.card__body { display: flex; flex-direction: column; gap: var(--s-3); margin-top: var(--s-4); }
.card__loading { font-size: var(--fs-xs); color: var(--text-2); }
@media (min-width: 768px) {
  .card__head { padding-bottom: var(--s-4); }
  .card__body { gap: var(--s-4); margin-top: var(--s-5); }
}

/* Portrait stacks nav + copy + lead story + CTA + the mood card into one
   viewport. The standfirst repeats what the lead story already says and the
   sparkline note is supplementary, so both give way before the card does. */
@media (max-width: 767px) {
  .card { padding: var(--s-5); }
  .card__spark { display: none; }
  .lede__body { display: none; }
  .card { height: 280px; }
}

/* ---------- daily brief (hero card) ----------
   The card used to restate the mood chart that section 02 draws in full and
   the ticker now carries too. It answers different questions instead, as
   label/value pairs — the earlier stacked version read as loose fragments. */
.brief { display: flex; flex-direction: column; gap: var(--s-4); }

.brief__lede {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding-bottom: var(--s-3); border-bottom: 1px solid var(--line);
}
.brief__num {
  font-size: 2.1rem; font-weight: 300; line-height: 1;
  letter-spacing: -0.03em; color: var(--text-1);
  font-variant-numeric: tabular-nums;
}
.brief__ledeText { font-size: var(--fs-sm); line-height: 1.4; color: var(--text-2); }

.brief__rows { display: flex; flex-direction: column; }
.brief__row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline; gap: var(--s-2) var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
}
.brief__row:last-child { border-bottom: 0; }
.brief__k {
  grid-column: 1; font-size: var(--fs-xs); color: var(--text-2);
}
.brief__name {
  grid-column: 1; font-size: var(--fs-md); font-weight: 600;
  color: var(--text-1); letter-spacing: -0.012em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.brief__val {
  grid-column: 2; grid-row: 1 / span 2; align-self: center;
  font-size: var(--fs-lg); font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--text-1);
}
.brief__val.up { color: var(--pos); }
.brief__val.down { color: var(--neg); }
a.brief__row:hover .brief__name { text-decoration: underline; }
.brief__why {
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px;
  padding: 0 0 var(--s-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-micro);
}

/* Portrait has room for the headline count and two rows once the lead story
   and CTA are stacked above. The scoring detail, the most-discussed row and
   the model row each have a full section of their own, so they give way here
   rather than clipping. These must sit after the base rules above — an
   earlier media query would lose the cascade to them. */
@media (max-width: 767px) {
  .brief { gap: var(--s-2); }
  .brief__num { font-size: 1.6rem; }
  .brief__lede { padding-bottom: var(--s-2); gap: var(--s-2); }
  .brief__ledeText { font-size: var(--fs-xs); }
  .brief__row { padding: var(--s-2) 0; }
  .brief__why,
  .brief__row--discussed,
  .brief__row--model,
  .brief__row--agents { display: none; }
  /* :last-child is a hidden row here, so the last VISIBLE row keeps its rule */
  .brief__rows > .brief__row:nth-child(2) { border-bottom: 0; }
}

/* ---------- trend chips (shared: orb card + mood pane) ---------- */
.trend {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-micro); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.trend.up   { color: var(--pos); }
.trend.down { color: var(--neg); }
.trend.flat { color: var(--text-3); }

/* ---------- section dots ---------- */
.dots {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px; z-index: 40;
}
/* base state was missing entirely — inactive dots rendered as grey squares */
.dot {
  width: 7px; height: 7px; padding: 0; border: 0;
  border-radius: var(--r-pill);
  background: var(--text-3);
  cursor: pointer; pointer-events: auto;
  transition: width 300ms var(--ease), background 300ms;
}
.dot:hover { background: var(--text-1); }
.dot.is-active { width: 22px; background: var(--ink); }

/* ---------- slide-out menu ---------- */
.menu {
  /* above the fixed nav (z-index 60) — at 50 the nav painted over the panel
     and its close button was unclickable */
  position: fixed; inset: 0; z-index: 70;
  visibility: hidden; pointer-events: none;
  transition: visibility 0s linear 500ms;
}
.menu.is-open { visibility: visible; pointer-events: auto; transition-delay: 0s; }
.menu__backdrop {
  position: absolute; inset: 0; background: rgba(0, 0, 0, 0.40);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  opacity: 0; transition: opacity 500ms;
}
.menu.is-open .menu__backdrop { opacity: 1; }
.menu__panel {
  position: absolute; top: 0; left: 0;
  display: flex; flex-direction: column;
  width: 100%; height: 100%; padding: var(--s-6) var(--s-7);
  background: var(--page);
  transform: translateX(-100%);
  transition: transform 500ms var(--ease-out);
}
.menu.is-open .menu__panel { transform: translateX(0); }
@media (min-width: 640px) { .menu__panel { width: 380px; padding: var(--s-6) 2.5rem; } }

.menu__close {
  display: inline-flex; align-items: center; gap: 0.625rem; align-self: flex-start;
  margin-bottom: var(--s-8); background: none; border: 0; font: inherit;
  font-size: 0.875rem; color: var(--text-1); cursor: pointer; transition: opacity 300ms;
}
.menu__close:hover { opacity: 0.6; }
.menu__nav { display: flex; flex-direction: column; }
.menu__legal {
  margin-top: auto; padding: var(--s-6) 0 var(--s-7);
  display: flex; gap: var(--s-5);
  border-top: 1px solid var(--line);
  opacity: 0; transform: translateY(20px);
  transition: opacity 500ms, transform 500ms;
}
.menu.is-open .menu__legal { opacity: 1; transform: translateY(0); transition-delay: 600ms; }
.menu__legal a {
  font-size: var(--fs-xs); color: var(--text-2); text-decoration: none;
}
.menu__legal a:hover { color: var(--text-1); text-decoration: underline; }
.menu__link {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s-4) 0; border-bottom: 1px solid var(--line);
  color: var(--text-1); text-decoration: none;
  opacity: 0; transform: translateY(20px);
  transition: opacity 500ms, transform 500ms;
}
.menu__linkText { font-size: var(--fs-title); font-weight: 300; letter-spacing: -0.025em; transition: transform 300ms; }
.menu__link:hover .menu__linkText { transform: translateX(8px); }
.menu__arrow { opacity: 0; transform: translateX(8px); transition: opacity 300ms, transform 300ms; }
.menu__link:hover .menu__arrow { opacity: 1; transform: translateX(0); }
@media (min-width: 640px) { .menu__linkText { font-size: 1.875rem; } }
.menu.is-open .menu__link { opacity: 1; transform: translateY(0); }
.menu.is-open .menu__link:nth-child(1) { transition-delay: 150ms; }
.menu.is-open .menu__link:nth-child(2) { transition-delay: 225ms; }
.menu.is-open .menu__link:nth-child(3) { transition-delay: 300ms; }
.menu.is-open .menu__link:nth-child(4) { transition-delay: 375ms; }
.menu.is-open .menu__link:nth-child(5) { transition-delay: 450ms; }
.menu.is-open .menu__link:nth-child(6) { transition-delay: 525ms; }
.menu.is-open 
/* ---------- reduced motion ----------
   Also stops the orb rAF loop + background video (see ui.js), not just transitions. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
