/* ============================================================
   SPG — "Crest Forge" design system
   The crest as architecture: midnight navy ground, chrome type with
   the crest letters' hard horizon line, faceted (chamfered) plates cut
   from the crest's shield-cube silhouette, and cyan light that lives
   ONLY inside one circuit trace running down the page. Violet is the
   under-glow on the lowest bevels and the Survival Ascended marker.
   No red anywhere. No rounded cards, no soft drop shadows, no glow
   haze, no grain, no particles, no looping motion.

   HOW TO USE (page agents read this first)
   - Page CSS goes in /assets/css/pages/<page>.css, linked after this
     file. Reuse the vocabulary below; never redefine palette tokens.
   - Tokens (all on :root):
       palette  --void --hull --hull-2 --facet --steel --silver --chrome
                --trace --trace-hot --violet --violet-deep
       roles    --bg --surface --raised --fg --fg-soft --fg-strong --link
                --rule --rule-strong --focus-a --focus-b --live --ase --asa
       material --chrome-grad (type) --chrome-plate (primary button)
                --bevel (portal frame) --plate (raised facet plate)
       facets   --cut-xl 22px (portals, section plates) --cut-l 16px
                (panels, asides) --cut-m 12px (rows, cards) --cut-s 8px
                (buttons, inputs) --cut-xs 5px (chips, pads). Set --cut on
                any .plate / .btn / .chip to override.
       type     --font-display (Tektur) --font-text (IBM Plex Sans)
                --font-mono (JetBrains Mono: chat commands in <code> only)
                --fs-fine 14 --fs-small 15 --fs-ui 16 --fs-body 18
                --fs-lede 21 --fs-h3 24 --fs-h2 36..60 --fs-h1 44..96
       space    --s-1..--s-10 (4 8 12 16 24 32 48 64 96 128)
                --chapter-pad (section padding) --measure 66ch
       layout   --container-max 1440 --gut (side gutter, 16 at 320px)
                --lane (the spine lane: 88px >=720, 0 below) --nav-h
       motion   --ease (forge: arrivals) --ease-seam (openings)
                --ease-press (the only spring; hover/press) --dur-ui .42s
   - Layout: .container (1440 max + gutters). .container.laned adds the
     spine lane on the left; section heads inside it put their via
     (i.pad[data-node]) in the lane. .split (5/7 head/body >=960),
     .stack (vertical rhythm), .sec (a chapter on the spine: padding +
     static lane line when motion is off), .sec-head (alias
     .section-head): i.pad + h2.h2 + optional .sec-note side copy.
   - Type: h1/.h1 and h2/.h2 are Tektur 800 in sentence case; wrap the
     words in span.chrome for the crest's chrome face (one per heading).
     h3/.h3 Tektur 700. Everything else is Plex. .lede .small .sub
     .fine-print .mono (tabular figures; IP:port, workshop IDs) .num
     (Tektur numerals). Line masks: span.ln-mask > span.ln (one per
     authored line) for load-sequence headlines.
   - Plates: .plate (+ .plate-xl/-l/-m/-s) paints a chamfered facet on
     ::before (so focus rings are never clipped). .card = plate-m.
   - Buttons: .btn + .btn-primary (chrome plate), .btn-ghost (navy plate,
     cyan underline grows from the centre on hover), .btn-dim (quiet),
     .btn-join (compact chrome, for rows), .btn-sm, .btn-block.
     .copy-ip copies data-copy (main.js announces); .copied swaps the
     icon to a check. .label-tag = a status label that is NOT a button.
   - Status: .badge(-online/-offline/-demo/-accent/-violet/-gold),
     .chip(-white/-ink/-hot/-mute/-line),
     .dot (diamond pip; .dot-pulse is styled static on purpose),
     .stat-chip > .num + .lbl (live strip cells). Status is always a
     word; colour only repeats it.
   - Blocks: .notice(.warn) .skeleton .table-wrap(.tall) > table (rows
     are facet plates; th.sortable > button gets aria-sort chevrons),
     .tabs > .tab (roving tabindex is JS's job; .active or
     [aria-selected=true] lights it), input/select/.search,
     details/summary (.faq-item: plus/minus in cyan), .prose (legal),
     .steps > .step > span.n (REAL sequences only), .players-bar > i.
   - Environment (night scenes): .env > .env-layer[data-depth] (img or
     picture inside, absolutely filled) + .env-scrim + .env-veil.
     data-depth 0..1 = distance from the camera (motion.js parallax);
     .env-mist uses screen blending (art rendered on black).
   - Portal (the crest silhouette as a window): see the markup in
     index.html. .portal > .portal-win (layers inside) + svg.portal-frame
     (two-tone chrome bevel, faceted wing shards, cyan apex) +
     i.portal-seam + .cast > img.cast-body + img.cast-rim. Sizes by
     context: .hero .portal, .page-band .portal.
   - Spine (motion.js builds it): every i.pad[data-node] on the page is a
     via. data-node="" section (its h2 gets one chrome sheen when lit),
     "row" (rack/ledger row stub), "led" (ledger plate extrudes),
     "plinth" (relic plinth), "end" (footer crest glint). Static/no-motion:
     every via is lit and a still 1px trace runs the lane.
   - Page header bands: .page-band (inner pages: env + portal + text),
     .page-head (legal: title + updated line on a trace).
     .cta-band = closing band (heading + actions + optional cast).
   - Motion contract (end of file): prefers-reduced-motion AND
     html[data-motion=off] neutralise every transition, animation and
     view transition; html.motion is set by motion.js only while the
     motion system runs (motion-only layout lives behind it);
     html[data-open] is the 2s pre-hide armed by open.js for the load
     sequence ([data-intro] header pieces only; the nav is never hidden).
   ============================================================ */

/* Tektur, IBM Plex Sans, JetBrains Mono — SIL Open Font License 1.1; notices + licence text: /assets/fonts/OFL.txt */
@font-face {
  font-family: "Tektur";
  font-style: normal;
  font-weight: 400 900;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("/assets/fonts/tektur-latin-var.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin-var.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url("/assets/fonts/jetbrains-mono-latin-var.woff2") format("woff2");
}

/* ============================================================
   TOKENS
   ============================================================ */

:root {
  /* palette, sampled from /assets/img/logo-512.png (contrast on --void) */
  --void: #03061A;        /* page ground: the crest's shadow navy */
  --hull: #0A1230;        /* raised plates, scrolled nav, footer */
  --hull-2: #101C3E;      /* hover plate, zebra, track */
  --facet: #163A5D;       /* bevel edges and rules — decorative only, never text (1.9) */
  --steel: #7E98AC;       /* secondary text (6.7; 6.0 on hull) */
  --silver: #CBD7DC;      /* body text (13.7) */
  --chrome: #F5F8F8;      /* headings, active text (18.8) */
  --trace: #46D2F5;       /* LIGHT only: traces, vias, focus, live state, Survival Evolved (11.3) */
  --trace-hot: #A6EEFF;   /* the moving tip of the trace, sheen core */
  --violet: #9B85FF;      /* Survival Ascended marker + text, under-glow (6.9) */
  --violet-deep: #6D55B3; /* under-glow on the lowest bevels — decorative only */

  /* roles (one ground: everything sits on navy) */
  --bg: var(--void);
  --surface: var(--hull);
  --raised: var(--hull-2);
  --fg: var(--silver);
  --fg-soft: var(--steel);
  --fg-strong: var(--chrome);
  --link: var(--chrome);
  --rule: rgba(126, 152, 172, 0.22);
  --rule-strong: rgba(126, 152, 172, 0.45);
  --focus-a: var(--trace);   /* ring */
  --focus-b: var(--void);    /* the gap between ring and control */
  --live: var(--trace);
  --ase: var(--trace);
  --asa: var(--violet);

  /* legacy names still referenced by data.js rule colours (category accents only, never a text ground) */
  --ink: var(--steel);
  --signal: var(--violet);
  --evolved: var(--trace);

  /* materials */
  /* the horizon band's floor stays light enough (#6F879B: 5.4:1 on --void) that chrome type keeps 3:1 over night art */
  --chrome-grad: linear-gradient(180deg, #F5F8F8 0%, #DDE5E9 28%, #B8C6CF 45%, #6F879B 50%, #8CA2B3 55%, #C9D3DA 74%, #EEF2F4 100%);
  --chrome-plate: linear-gradient(180deg, #F5F8F8 0%, #DCE4E8 46%, #A7B6C1 52%, #C8D3DA 70%, #EEF2F4 100%);
  --plate: linear-gradient(180deg, rgba(203, 215, 220, 0.16) 0 1px, transparent 1px calc(100% - 1px), rgba(0, 0, 0, 0.5) calc(100% - 1px)),
           linear-gradient(180deg, #0D1736, #0A1230 60%, #091029);
  --plate-2: linear-gradient(180deg, rgba(203, 215, 220, 0.2) 0 1px, transparent 1px calc(100% - 1px), rgba(0, 0, 0, 0.5) calc(100% - 1px)),
             linear-gradient(180deg, #14244C, #101C3E 60%, #0D1736);

  /* facets: chamfer size encodes hierarchy */
  --cut-xl: 22px;
  --cut-l: 16px;
  --cut-m: 12px;
  --cut-s: 8px;
  --cut-xs: 5px;

  /* type */
  --font-display: "Tektur", "Bahnschrift", "Arial Narrow", sans-serif;
  --font-text: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, Consolas, monospace;
  --fs-fine: 0.875rem;   /* 14: legal fine print and chip floor */
  --fs-small: 0.9375rem; /* 15 */
  --fs-ui: 1rem;         /* 16 */
  --fs-body: 1.125rem;   /* 18 */
  --fs-lede: 1.3125rem;  /* 21 */
  --fs-h4: 1.1875rem;    /* 19 */
  --fs-h3: 1.5rem;       /* 24 */
  --fs-h2: clamp(2.25rem, 1.45rem + 2.4vw, 3.75rem);   /* 36 -> 60 */
  --fs-h1: clamp(2.75rem, 1.35rem + 4.6vw, 6rem);      /* 44 -> 96 */
  --fs-num: clamp(2.25rem, 1.6rem + 2.4vw, 3.5rem);
  --measure: 66ch;

  /* space: 4 8 12 16 24 32 48 64 96 128 */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px; --s-10: 128px;
  --chapter-pad: clamp(64px, 8vw, 112px);

  /* layout */
  --container-max: 1440px;
  --gut: clamp(16px, 3.4vw, 48px);
  --lane: 0px;
  --pad: 18px;
  --nav-h: 64px;

  /* motion */
  --ease: cubic-bezier(0.16, 0.84, 0.24, 1);
  --ease-seam: cubic-bezier(0.7, 0, 0.18, 1);
  --ease-press: cubic-bezier(0.22, 1, 0.36, 1); /* ease-out-quint: settles without overshoot */
  --dur-ui: 0.42s;

  color-scheme: dark;
}
@media (min-width: 720px) { :root { --lane: 88px; } }
@media (min-width: 961px) { :root { --nav-h: 76px; } }

/* ============================================================
   BASE
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--nav-h) + var(--s-4));
  background: var(--bg);
}
body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font: 400 var(--fs-body)/1.6 var(--font-text);
  font-variant-numeric: tabular-nums;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
  overflow-anchor: none; /* late renders correct the scroll themselves (main.js keepPlace), never twice */
}
@media (max-width: 719.98px) { body { font-size: 1.0625rem; } }
img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
button { cursor: pointer; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-color: var(--trace); }
h1, h2, h3, h4, h5, h6 { margin: 0; color: var(--fg-strong); font-weight: 700; }
ul, ol { padding-left: 1.2em; }
hr { border: 0; height: 1px; background: var(--rule); margin: var(--s-6) 0; }
::selection { background: var(--trace); color: var(--void); }
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--focus-a);
  outline-offset: 3px;
}
main:focus-visible, [tabindex="-1"]:focus-visible { outline: none; }

.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: absolute;
  z-index: 100;
  left: var(--s-4);
  top: -80px;
  padding: 12px 18px;
  background: var(--chrome);
  color: var(--void);
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus, .skip-link:focus-visible { top: var(--s-3); outline: 2px solid var(--trace); outline-offset: 2px; }
noscript .notice { margin: var(--s-5) var(--gut); }

/* ============================================================
   LAYOUT
   ============================================================ */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gut);
}
.container.laned { padding-left: calc(var(--gut) + var(--lane)); }
main { position: relative; display: block; }
.sec { position: relative; padding-block: var(--chapter-pad); }
.stack > * + * { margin-top: var(--s-5); }
.split { display: grid; gap: var(--s-6) var(--s-8); }
@media (min-width: 960px) {
  .split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: start; }
  .sticky-head { position: sticky; top: calc(var(--nav-h) + var(--s-5)); }
}

/* section head: via in the lane, h2 left, side note right */
.sec-head, .section-head {
  position: relative;
  display: grid;
  gap: var(--s-4) var(--s-8);
  align-items: end;
  margin-bottom: var(--s-7);
}
@media (min-width: 960px) {
  .sec-head, .section-head { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
  .sec-head > :only-child, .section-head > :only-child { grid-column: 1 / -1; }
}
.sec-note { max-width: 56ch; color: var(--fg); }
/* a head with no side note: the heading takes the full row (the via is out of flow) */
.sec-head > :is(h1, h2, .h2):last-child, .section-head > :is(h1, h2, .h2):last-child { grid-column: 1 / -1; }
.sec-note .sub { display: block; margin-top: var(--s-2); }

/* ============================================================
   TYPE
   ============================================================ */

h1, .h1 {
  font: 800 var(--fs-h1)/0.94 var(--font-display);
  font-stretch: 86%;
  letter-spacing: -0.01em;
  color: var(--fg-strong);
  text-wrap: balance;
}
h2, .h2 {
  position: relative;
  font: 800 var(--fs-h2)/1 var(--font-display);
  font-stretch: 88%;
  letter-spacing: -0.005em;
  color: var(--fg-strong);
  text-wrap: balance;
}
h3, .h3 {
  font: 700 var(--fs-h3)/1.2 var(--font-display);
  font-stretch: 92%;
  color: var(--fg-strong);
}
h4, .h4 { font: 600 var(--fs-h4)/1.35 var(--font-text); color: var(--fg-strong); }
.h-sm { font: 800 clamp(1.75rem, 1.3rem + 1.4vw, 2.5rem)/1.05 var(--font-display); font-stretch: 88%; }
.display { font-family: var(--font-display); font-weight: 800; font-stretch: 88%; }
.lede { max-width: 48ch; font-size: var(--fs-lede); line-height: 1.5; color: var(--fg); }
@media (max-width: 719.98px) { .lede { font-size: 1.1875rem; } }
.small, .sub { font-size: var(--fs-small); line-height: 1.55; color: var(--fg-soft); }
.fine-print { font-size: var(--fs-fine); line-height: 1.6; color: var(--fg-soft); }
.mono { font-family: var(--font-text); font-variant-numeric: tabular-nums slashed-zero; letter-spacing: 0.01em; }
code, kbd { font-family: var(--font-mono); font-size: 0.92em; color: var(--chrome); }
.mod-id { font-family: var(--font-mono); font-size: var(--fs-fine); color: var(--steel); letter-spacing: 0; }
.numeral, .stat-chip .num, .pack .num { font-family: var(--font-display); font-weight: 800; font-stretch: 86%; font-variant-numeric: tabular-nums; color: var(--fg-strong); }
.num.gold { color: var(--chrome); }
.grad { color: var(--trace); } /* contract class: a flat colour now, never gradient text */

/* the crest's chrome face: hard horizon at 50%, one horizon per line */
.chrome {
  background-image: var(--chrome-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
/* a block of chrome text gets one horizon per line (inline spans get theirs from box-decoration-break) */
.ln.chrome { background-size: 100% 1lh; }
/* line masks for authored headline lines (load sequences); padding gives Tektur's ascenders and descenders room.
   Only the vertical axis clips (all the rise needs), so widened letter/word spacing (WCAG 1.4.12) never cuts a
   word's end; a line too wide for a phone wraps inside its mask instead of running off the page */
.ln-mask { position: relative; display: block; overflow-x: visible; overflow-y: clip; padding: 0.04em 0 0.1em; margin: -0.04em 0 -0.1em; }
.ln { display: block; overflow-wrap: anywhere; }
/* sheen: a bright copy of a heading, revealed only inside a moving slanted band (motion.js creates it) */
.sheen-copy {
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  color: #FFFFFF;
  -webkit-text-fill-color: #FFFFFF;
  background: none;
  pointer-events: none;
  clip-path: polygon(-30% 0, -18% 0, -26% 100%, -38% 100%);
}
.ln-mask > .sheen-copy { top: 0.04em; }

/* ============================================================
   PLATES (facets painted on ::before so focus rings never clip)
   ============================================================ */

.plate, .card {
  --cut: var(--cut-l);
  position: relative;
  isolation: isolate;
}
.plate::before, .card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--plate);
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
}
.plate-xl { --cut: var(--cut-xl); }
.plate-l { --cut: var(--cut-l); }
.plate-m, .card { --cut: var(--cut-m); }
.plate-s { --cut: var(--cut-s); }
.card { padding: var(--s-5); }

/* ============================================================
   BUTTONS
   ============================================================ */

.btn {
  --cut: 10px;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 26px;
  border: 0;
  background: none;
  color: var(--chrome);
  font: 600 var(--fs-ui)/1.1 var(--font-text);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 0.38s var(--ease-press);
}
.btn::before, .btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(0.97); transition-duration: 0.12s; }
.btn .icon { flex: none; width: 18px; height: 18px; }

/* primary: a chrome plate, navy text; a band of light crosses it on hover */
.btn-primary, .btn-join { color: var(--void); overflow: hidden; }
.btn-primary::before, .btn-join::before { background: var(--chrome-plate); }
.btn-primary::after, .btn-join::after {
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.95) 50%, transparent 62%);
  transform: translateX(-110%);
  transition: transform 0.7s var(--ease);
}
.btn-primary:hover::after, .btn-join:hover::after { transform: translateX(110%); }
.btn-primary:focus-visible, .btn-join:focus-visible { outline-color: var(--trace); }

/* ghost: a navy plate with a lit top bevel; a cyan underline grows from the centre on hover */
.btn-ghost::before { background: linear-gradient(180deg, rgba(203, 215, 220, 0.28) 0 1px, transparent 1px), linear-gradient(180deg, #13214A, #0C1636); }
.btn-ghost::after {
  inset: auto 0 0 0;
  height: 2px;
  clip-path: none;
  background: var(--trace);
  transform: scaleX(0);
  transition: transform var(--dur-ui) var(--ease);
}
.btn-ghost:hover::after { transform: scaleX(1); }
.btn-ghost:hover { color: var(--chrome); }

/* dim: quiet, outlined in steel (log out, secondary row actions) */
.btn-dim { color: var(--silver); }
.btn-dim::before { background: transparent; box-shadow: inset 0 0 0 1px var(--rule-strong); clip-path: none; }
.btn-dim::after { display: none; }
.btn-dim:hover { color: var(--chrome); }

.btn-join { min-height: 40px; padding: 0 18px; --cut: 7px; font-size: var(--fs-small); }
.btn-sm { --cut: 7px; min-height: 40px; padding: 0 16px; font-size: var(--fs-small); gap: 8px; }
.btn-block { display: flex; width: 100%; }
.btn[aria-disabled="true"], .btn:disabled { opacity: 0.5; pointer-events: none; }

/* copy address: label (or the address itself) + copy icon; .copied shows a check */
.copy-ip {
  --cut: 7px;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 14px;
  border: 0;
  background: none;
  color: var(--chrome);
  font: 600 var(--fs-small)/1 var(--font-text);
  cursor: pointer;
  transition: transform 0.38s var(--ease-press);
}
.copy-ip::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(203, 215, 220, 0.24) 0 1px, transparent 1px), linear-gradient(180deg, #13214A, #0C1636);
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
}
.copy-ip:hover { transform: translateY(-2px); }
.copy-ip:active { transform: scale(0.97); transition-duration: 0.12s; }
.copy-ip .icon { width: 16px; height: 16px; flex: none; color: var(--trace); }
.copy-ip .i-check { display: none; }
.copy-ip.copied .i-copy { display: none; }
.copy-ip.copied .i-check { display: block; }
.copy-ip .mono { font-weight: 600; }
.copy-hint { display: block; margin-top: var(--s-2); font-size: var(--fs-small); color: var(--fg); }
/* a status label, never a button: plain violet text behind a small diamond, no box, no button height */
.label-tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--violet);
  font-size: var(--fs-fine);
  font-weight: 600;
  white-space: nowrap;
}
.label-tag::before { content: ""; flex: none; width: 6px; height: 6px; transform: rotate(45deg); background: var(--violet); }

/* ============================================================
   CHIPS, BADGES, DOTS, LIVE CELLS
   ============================================================ */

.chip, .badge {
  --cut: var(--cut-xs);
  --chip-fg: var(--silver);
  --chip-edge: var(--rule-strong);
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 28px;
  padding: 3px 10px;
  color: var(--chip-fg);
  font: 600 var(--fs-fine)/1.25 var(--font-text);
  white-space: nowrap;
}
.chip::before, .badge::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--hull);
  box-shadow: inset 0 0 0 1px var(--chip-edge);
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
}
.chip-white, .chip-line { --chip-fg: var(--chrome); --chip-edge: rgba(203, 215, 220, 0.5); }
.chip-ink { --chip-fg: var(--silver); --chip-edge: transparent; }
.chip-mute { --chip-fg: var(--steel); --chip-edge: var(--rule); }
.chip-hot { --chip-fg: var(--trace-hot); --chip-edge: rgba(70, 210, 245, 0.55); } /* "hot" story: alpha live, busiest map */
.badge-online::after, .badge-violet::after, .badge-accent::after {
  content: "";
  order: -1;
  width: 7px; height: 7px;
  flex: none;
  transform: rotate(45deg);
  background: var(--trace);
}
.badge-violet::after { background: var(--violet); }
.badge-online { --chip-fg: var(--chrome); --chip-edge: rgba(70, 210, 245, 0.45); }
.badge-offline { --chip-fg: var(--steel); --chip-edge: var(--rule); }
.badge-demo { --chip-fg: var(--violet); --chip-edge: rgba(155, 133, 255, 0.5); }
.badge-accent { --chip-fg: var(--trace); --chip-edge: rgba(70, 210, 245, 0.45); }
.badge-violet { --chip-fg: var(--violet); --chip-edge: rgba(155, 133, 255, 0.45); }
.badge-gold { --chip-fg: var(--void); --chip-edge: transparent; }
.badge-gold::before { background: var(--chrome-plate); }

.dot, .dot-pulse {
  display: inline-block;
  flex: none;
  width: 8px; height: 8px;
  background: var(--trace);
  transform: rotate(45deg);
}
.dot.is-off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--steel); }

/* live cell: big numeral + label (hero live strip, My Stats) */
.stat-chip { display: inline-flex; flex-direction: column; gap: 2px; min-width: 0; }
.stat-chip .num { font-size: 1.75rem; line-height: 1; }
.stat-chip .lbl { font-size: var(--fs-fine); line-height: 1.35; color: var(--steel); font-weight: 500; }

/* meter (only shown at/above data.js liveThreshold) */
.players-bar { position: relative; height: 4px; background: var(--hull-2); overflow: hidden; }
.players-bar > i { position: absolute; inset: 0 auto 0 0; background: var(--trace); }

/* ============================================================
   NOTICE, SKELETON, ICONS
   ============================================================ */

.notice {
  position: relative;
  isolation: isolate;
  padding: 16px 20px 16px 22px;
  color: var(--fg);
  font-size: var(--fs-ui);
}
.notice::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, var(--trace) 0 2px, transparent 2px), var(--plate);
}
.notice.warn::before { background: linear-gradient(90deg, var(--violet) 0 2px, transparent 2px), var(--plate); }
.notice a { color: var(--chrome); }

.skeleton {
  --cut: var(--cut-m);
  position: relative;
  min-height: 72px;
  background: rgba(16, 28, 62, 0.55);
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
}
tr.skeleton td { height: 56px; background: rgba(16, 28, 62, 0.55); }

.icon { width: 20px; height: 20px; flex: none; }

/* ============================================================
   TABLES
   ============================================================ */

.table-wrap {
  position: relative; /* sr-only spans in cells get their containing block here, so the scroller clips them (else they widen a phone's layout viewport) */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  outline-offset: 4px;
}
.table-wrap.tall { max-height: 70vh; overflow-y: auto; }
table { width: 100%; border-collapse: separate; border-spacing: 0 6px; font-size: var(--fs-ui); }
caption { text-align: left; }
th, td { padding: 14px 16px; text-align: left; vertical-align: middle; }
thead th {
  padding-block: 6px;
  font: 600 var(--fs-fine)/1.3 var(--font-text);
  color: var(--steel);
  white-space: nowrap;
}
/* rows are facet plates: the end cells carry the chamfers as gradient corners (no clip seams between cells) */
tbody td, tbody th { --cell: var(--hull); background: var(--cell); color: var(--silver); }
tbody th { color: var(--chrome); font-weight: 600; }
tbody tr > :first-child { background: linear-gradient(135deg, transparent 7px, var(--cell) 7.5px); }
tbody tr > :last-child { background: linear-gradient(315deg, transparent 7px, var(--cell) 7.5px); }
tbody tr > :only-child { background: var(--cell); clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px); }
tbody tr:hover > td, tbody tr:hover > th { --cell: var(--hull-2); }
th.num, td.num, .num-col { text-align: right; }
td.rank { font: 800 1.375rem/1 var(--font-display); font-stretch: 86%; color: var(--steel); width: 4.5rem; }
tr.rank-1 td.rank { color: var(--trace); }
tr.rank-2 td.rank, tr.rank-3 td.rank { color: var(--silver); }
td.score { font-weight: 600; color: var(--chrome); }
/* sortable headers: leaderboard.js injects a real <button>; aria-sort draws the chevron */
th.sortable button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
}
th.sortable button::after {
  content: "";
  width: 8px; height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  opacity: 0.35;
}
th[aria-sort="ascending"] button::after { transform: rotate(-135deg) translate(-2px, -2px); opacity: 1; color: var(--trace); }
th[aria-sort="descending"] button::after { opacity: 1; color: var(--trace); }
th.sortable button:hover { color: var(--chrome); }

/* ============================================================
   TABS, INPUTS, DISCLOSURES
   ============================================================ */

.tabs { display: inline-flex; flex-wrap: wrap; gap: 4px; padding: 4px; background: var(--hull); }
.tab {
  position: relative;
  min-height: 44px;
  padding: 0 22px;
  border: 0;
  background: transparent;
  color: var(--steel);
  font: 600 var(--fs-ui)/1 var(--font-text);
  cursor: pointer;
}
.tab::after {
  content: "";
  position: absolute;
  left: 12px; right: 12px; bottom: 6px;
  height: 2px;
  background: var(--trace);
  transform: scaleX(0);
  transition: transform var(--dur-ui) var(--ease);
}
.tab:hover { color: var(--chrome); }
.tab.active, .tab[aria-selected="true"] { color: var(--chrome); background: var(--hull-2); }
.tab.active::after, .tab[aria-selected="true"]::after { transform: scaleX(1); }

input[type="search"], input[type="text"], input[type="email"], .search, select {
  min-height: 48px;
  width: 100%;
  max-width: 420px;
  padding: 0 16px;
  border: 0;
  border-radius: 0;
  background: var(--hull);
  box-shadow: inset 0 0 0 1px var(--steel); /* resting edge: 5.6:1 on hull, 6.7:1 on void (WCAG 1.4.11) */
  color: var(--chrome);
  font-size: var(--fs-ui);
  -webkit-appearance: none;
  appearance: none;
}
input::placeholder { color: var(--steel); opacity: 1; }
input:focus-visible, select:focus-visible { outline-offset: 2px; background: linear-gradient(0deg, var(--trace) 0 2px, transparent 2px), var(--hull-2); }
select {
  padding-right: 40px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237E98AC' stroke-width='2.4'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") right 12px center / 18px no-repeat,
              var(--hull);
}
input[type="search"]::-webkit-search-cancel-button { filter: invert(0.7); }

details > summary { cursor: pointer; }
.faq-item { box-shadow: inset 0 1px var(--rule-strong); }
.faq-item:last-child { box-shadow: inset 0 1px var(--rule-strong), inset 0 -1px var(--rule-strong); }
.faq-item > summary {
  position: relative;
  display: block;
  padding: 22px 48px 22px 0;
  list-style: none;
  font: 600 1.1875rem/1.35 var(--font-text);
  color: var(--chrome);
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::before, .faq-item > summary::after {
  content: "";
  position: absolute;
  right: 8px; top: 50%;
  width: 16px; height: 2px;
  margin-top: -1px;
  background: var(--trace);
  transition: transform var(--dur-ui) var(--ease);
}
.faq-item > summary::after { transform: rotate(90deg); }
.faq-item[open] > summary::after { transform: rotate(0deg); }
.faq-item > summary:hover { color: #FFFFFF; }
.faq-item > p, .faq-item > .ans { margin: 0; padding: 0 48px 24px 0; max-width: 62ch; color: var(--silver); }

/* ============================================================
   PROSE (legal pages), STEPS
   ============================================================ */

.prose { max-width: var(--measure); color: var(--silver); }
.prose h2 { font-size: clamp(1.75rem, 1.4rem + 1vw, 2.25rem); margin: var(--s-8) 0 var(--s-4); }
.prose h3 { font-size: 1.375rem; margin: var(--s-6) 0 var(--s-3); }
.prose p, .prose ul, .prose ol { margin: 0 0 var(--s-4); }
.prose li { margin-bottom: var(--s-2); }
.prose li::marker { color: var(--trace); }
.prose a { color: var(--chrome); text-decoration: underline; text-decoration-color: var(--trace); }
.prose strong { color: var(--chrome); }
.prose .table-wrap { margin: var(--s-5) 0; }
.prose table { font-size: var(--fs-small); }

.steps { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.step { position: relative; padding: 0 0 var(--s-5) 48px; }
.step > .n {
  position: absolute;
  left: 0; top: -2px;
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  font: 800 1rem/1 var(--font-display);
  color: var(--void);
  background: var(--chrome-plate);
  clip-path: polygon(30% 0, 100% 0, 100% 70%, 70% 100%, 0 100%, 0 30%);
}
.step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 15px; top: 36px; bottom: 6px;
  width: 2px;
  background: var(--facet);
}
.step > :is(h3, h4) { font: 600 1.0625rem/1.35 var(--font-text); color: var(--chrome); margin-bottom: 6px; }
.step > p { font-size: var(--fs-small); line-height: 1.55; color: var(--silver); margin-bottom: var(--s-3); }
.step .addr { display: flex; flex-wrap: wrap; gap: var(--s-2); }
/* the address wraps inside its button rather than pushing the page sideways (320px with widened text spacing) */
.step .addr .copy-ip { max-width: 100%; }
.step .addr .copy-ip .mono { min-width: 0; overflow-wrap: anywhere; line-height: 1.25; }

/* ============================================================
   ENVIRONMENT (layered night scenes) + CAST
   ============================================================ */

.env { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.env-layer { position: absolute; inset: 0; }
.env-layer > img, .env-layer > picture > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}
.env-mist > img, .env-mist > picture > img { opacity: 0.8; }
/* fog plates fade out at their top and bottom, so a band never ends in a hard horizontal line */
.env-mist > img, .env-mist > picture > img, .legal-haze > img {
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 30%, #000 70%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 30%, #000 70%, transparent);
}
.env-scrim, .env-veil { position: absolute; inset: 0; }
.env-veil { background: var(--void); opacity: 0; }

.cast { position: absolute; pointer-events: none; }
.cast > img { display: block; width: 100%; height: auto; max-width: none; }
.cast-rim { position: absolute; inset: 0; }
/* a cut-out is three registered layers: contact shadow (the dark it stands in), body, rim light */
.cast > .cast-shadow { position: absolute; left: 0; top: 0; width: 100%; height: auto; } /* top-registered; it runs on below the feet */

/* relic art (home vault, Exclusive): share of the transparent square left empty under the object (--sink), the
   object's height (--h) and a per-object scale (--k), measured from the 2026-10-14 exports' alpha bounds, so every
   relic stands on its surface whatever its shape */
[data-relic] { --sink: 0.15; --h: 0.7; --k: 1; }
[data-relic="settler"] { --sink: 0.15; --h: 0.7; }
[data-relic="vanguard"] { --sink: 0.133; --h: 0.74; }
[data-relic="overseer"] { --sink: 0.271; --h: 0.46; }
[data-relic="prism"] { --sink: 0.043; --h: 0.92; --k: 0.8; }
[data-relic="supreme"] { --sink: 0.244; --h: 0.52; }
[data-relic="booster"] { --sink: 0.043; --h: 0.92; --k: 0.86; }
/* the art's empty square overlaps the text under it (the sink): it never takes the pointer from that text */
.relic img { pointer-events: none; }

/* ============================================================
   PORTAL — the crest silhouette as a window (hero, page bands)
   apex 50,0 / shoulders 62,10 + 94,14 / flanks 100,20..78 / V base 54,99.5
   ============================================================ */

.portal {
  --win: polygon(50% 1.8%, 61.4% 11.4%, 93.4% 15.4%, 98.6% 20.8%, 98.6% 77.2%, 53.7% 97.9%, 46.3% 97.9%, 1.4% 77.2%, 1.4% 20.8%, 6.6% 15.4%, 38.6% 11.4%);
  --seam: polygon(50% 1.8%, 50% 11.4%, 50% 15.4%, 50% 20.8%, 50% 77.2%, 50% 97.9%, 50% 97.9%, 50% 77.2%, 50% 20.8%, 50% 15.4%, 50% 11.4%);
  position: relative;
  z-index: 2;
}
.portal-win {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--hull);
  clip-path: var(--win);
}
.portal-win > .env-layer > img, .portal-win > .env-layer > picture > img { object-position: 50% 42%; }
.portal-veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(3, 6, 26, 0.22) 0%, rgba(3, 6, 26, 0) 28%, rgba(3, 6, 26, 0.3) 62%, rgba(3, 6, 26, 0.88) 100%);
}
.portal-dark { position: absolute; inset: 0; background: var(--void); opacity: 0; }
.portal-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.portal-frame .bevel { fill: url(#bevelGrad); }
.portal-frame .bevel-lit { fill: none; stroke: rgba(245, 248, 248, 0.75); stroke-width: 1; vector-effect: non-scaling-stroke; }
.portal-frame .bevel-edge { fill: none; stroke: #02040F; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.portal-frame .under { fill: none; stroke: var(--violet); stroke-width: 1.5; vector-effect: non-scaling-stroke; opacity: 0.8; }
.portal-frame .wing-lit { fill: #5E7A92; }
.portal-frame .wing-mid { fill: #2A4462; }
.portal-frame .wing-dark { fill: #0C1636; }
.portal-frame .wing-edge { fill: none; stroke: var(--trace); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
.portal-frame .apex { fill: none; stroke: var(--trace); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.portal-frame .apex-core { fill: var(--trace-hot); opacity: 0.85; }
.portal-seam {
  position: absolute;
  left: 50%; top: 1.8%;
  width: 2px; height: 96%;
  margin-left: -1px;
  background: linear-gradient(180deg, var(--trace-hot), var(--trace) 70%, rgba(70, 210, 245, 0));
  transform-origin: 50% 0;
  opacity: 0;
}

/* ============================================================
   SPINE — one circuit trace down the page (built by motion.js)
   ============================================================ */

.spine { position: absolute; inset: 0 0 auto 0; z-index: 3; pointer-events: none; transition: opacity 0.25s linear; }
html.intro .spine, html[data-open] .spine { opacity: 0; } /* data-open: the load sequence has not taken over yet */
.spine-mask, .spine-inner { position: absolute; inset: 0; }
.spine-mask { overflow: hidden; }
.spine-svg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; }
.spine-svg path, .trace-svg path { fill: none; stroke-linejoin: miter; }
.halo { stroke: rgba(70, 210, 245, 0.16); stroke-width: 7; }
.core { stroke: var(--trace); stroke-width: 1.6; }
.spine-tip {
  position: absolute;
  left: 0; top: 0;
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  background: radial-gradient(circle, #FFFFFF 0 2px, var(--trace-hot) 3px, rgba(70, 210, 245, 0.35) 5px, rgba(70, 210, 245, 0) 11px);
  opacity: 0;
}

/* vias: chamfered pads on the trace */
.pad {
  position: absolute;
  z-index: 4;
  width: var(--pad);
  height: var(--pad);
  background: var(--hull-2);
  clip-path: polygon(30% 0, 100% 0, 100% 70%, 70% 100%, 0 100%, 0 30%);
}
.pad::before { content: ""; position: absolute; inset: 3px; background: var(--facet); clip-path: inherit; }
.pad::after {
  content: "";
  position: absolute;
  inset: 3px;
  clip-path: inherit;
  background: radial-gradient(circle, #FFFFFF 0 18%, var(--trace-hot) 30%, var(--trace) 62%);
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease);
}
.pad.lit::after, html:not(.motion):not([data-open]) .pad::after { opacity: 1; }
.pad-sm { --pad: 12px; }
.stub {
  position: absolute;
  z-index: 4;
  top: 50%;
  left: calc(var(--lane) * -0.5);
  width: calc(var(--lane) * 0.5);
  height: 1px;
  background: var(--trace);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--dur-ui) var(--ease);
}
:has(> .pad.lit) > .stub, html:not(.motion):not([data-open]) .stub { transform: scaleX(1); }
/* section heads put their via in the lane, level with the first line of the h2 */
.sec-head > .pad, .section-head > .pad { left: calc(var(--lane) * -0.5 - var(--pad) / 2); top: calc(var(--fs-h2) * 0.5 - var(--pad) / 2); }
.sec-head { align-items: start; }
@media (max-width: 719.98px) { .pad, .stub { display: none; } }

/* static trace (motion off, reduced, no JS): one still line down the lane so the vias read as connected */
@media (min-width: 720px) {
  html:not(.motion):not([data-open]) .sec::before, html:not(.motion):not([data-open]) .footer::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0;
    z-index: 3;
    width: 1px;
    left: calc(max(0px, (100% - var(--container-max)) / 2) + var(--gut) + var(--lane) * 0.5);
    background: rgba(70, 210, 245, 0.45);
    pointer-events: none;
  }
  html:not(.motion) .footer::before { bottom: auto; height: calc(var(--s-8) + 48px); }
}

/* crest glint: one band of light clipped to the crest's own alpha */
.crest { position: relative; display: block; flex: none; line-height: 0; }
.glint {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask: url("/assets/img/logo-192.png") center / contain no-repeat;
  mask: url("/assets/img/logo-192.png") center / contain no-repeat;
}
.glint > i {
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 28%, rgba(166, 238, 255, 0) 36%, rgba(240, 253, 255, 0.95) 50%, rgba(166, 238, 255, 0) 64%, transparent 72%);
  transform: translateX(-101%);
}

/* ============================================================
   NAV (main.js renderNav)
   ============================================================ */

.nav { position: fixed; inset: 0 0 auto; z-index: 40; height: var(--nav-h); }
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 18, 48, 0.97), rgba(10, 18, 48, 0.93));
  box-shadow: inset 0 -1px var(--rule);
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease);
}
.nav.scrolled::before, .nav:has(.nav-links.open)::before { opacity: 1; }
.nav-inner { position: relative; height: 100%; display: flex; align-items: center; gap: var(--s-4); }
.nav-brand { display: inline-flex; align-items: center; gap: 12px; color: var(--chrome); text-decoration: none; border-radius: 0; }
.nav-brand img { width: 40px; height: 40px; }
.nav-word { font: 800 1.375rem/1 var(--font-display); font-stretch: 88%; letter-spacing: 0.01em; color: var(--chrome); white-space: nowrap; }
.nav-word.chrome { background-size: 100% 1lh; padding: 0.08em 0; }
.nav-links { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.nav-links a {
  position: relative;
  padding: 10px 14px;
  color: var(--silver);
  font-size: var(--fs-ui);
  font-weight: 500;
  text-decoration: none;
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 14px; right: 14px; bottom: 4px;
  height: 2px;
  background: var(--trace);
  transform: scaleX(0);
  transition: transform var(--dur-ui) var(--ease);
}
.nav-links a:hover { color: var(--chrome); }
.nav-links a:hover::after, .nav-links a.active::after, .nav-links a[aria-current="page"]::after { transform: scaleX(1); }
.nav-links a.active, .nav-links a[aria-current="page"] { color: var(--chrome); }
.nav-cta { display: inline-flex; align-items: center; gap: var(--s-2); margin-left: var(--s-2); }
.nav-cta .btn-sm { padding: 0 14px; }
.login-discord svg { flex: none; }
.login-pending { opacity: 0; }
.login-chip { display: inline-flex; align-items: center; gap: 10px; }
.login-chip img { width: 28px; height: 28px; clip-path: polygon(25% 0, 100% 0, 100% 75%, 75% 100%, 0 100%, 0 25%); }
.login-name { max-width: 14ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--chrome); font-size: var(--fs-small); }
.nav-toggle { display: none; }
.nav-toggle .icon { width: 22px; height: 22px; }
.nav-toggle .i-close { display: none; }
.nav-toggle[aria-expanded="true"] .i-menu { display: none; }
.nav-toggle[aria-expanded="true"] .i-close { display: block; }

@media (max-width: 960.98px) {
  .nav-toggle {
    order: 3;
    display: inline-grid;
    place-items: center;
    width: 48px; height: 48px;
    border: 0;
    background: var(--hull);
    color: var(--chrome);
    clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  }
  .nav-toggle:focus-visible { clip-path: none; }
  .nav-cta { order: 2; margin-left: auto; }
  .nav-links {
    position: absolute;
    top: var(--nav-h);
    left: 0; right: 0;
    margin: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--s-3) var(--gut) var(--s-5);
    background: var(--hull);
    box-shadow: inset 0 -1px var(--rule), inset 0 1px var(--rule);
    visibility: hidden;
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 0.3s var(--ease), transform var(--dur-ui) var(--ease), visibility 0s var(--dur-ui);
  }
  .nav-links.open { visibility: visible; opacity: 1; transform: none; transition-delay: 0s; }
  .nav-links a { padding: 14px 4px; font-size: 1.125rem; }
  .nav-links a::after { left: 4px; right: auto; width: 40px; }
}
@media (max-width: 479.98px) {
  .login-discord { width: 44px; min-height: 44px; padding: 0; }
  .login-discord .login-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .login-name { display: none; }
}

/* ============================================================
   FOOTER (main.js renderFooter) — the spine ends at the crest
   ============================================================ */

.footer {
  position: relative;
  background: var(--hull);
  box-shadow: inset 0 1px var(--rule);
  padding: var(--s-8) 0 var(--s-6);
}
.footer-inner { display: grid; gap: var(--s-7) var(--s-8); }
.footer-crest { position: relative; width: 96px; height: 96px; }
.footer-crest img { width: 96px; height: 96px; }
.footer-crest > .pad { left: calc(var(--lane) * -0.5 - var(--pad) / 2); top: calc(48px - var(--pad) / 2); }
.cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-5) var(--s-6); }
.col { display: flex; flex-direction: column; align-items: flex-start; }
.col-title { margin-bottom: var(--s-3); font: 600 var(--fs-ui)/1.3 var(--font-text); color: var(--steel); }
.col a { display: block; padding: 6px 0; color: var(--silver); text-decoration: none; font-size: var(--fs-ui); }
.col a:hover { color: var(--chrome); text-decoration: underline; text-decoration-color: var(--trace); }
.fine {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-5) var(--s-7);
  padding-top: var(--s-6);
  box-shadow: inset 0 1px var(--rule);
}
.fine p { max-width: 92ch; margin: 0; font-size: var(--fs-fine); line-height: 1.6; color: var(--steel); }
.motion-toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0 16px;
  border: 0;
  background: transparent;
  color: var(--silver);
  font: 500 var(--fs-small)/1.2 var(--font-text);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
  cursor: pointer;
}
.motion-toggle::before {
  content: "";
  flex: none;
  width: 16px; height: 16px;
  box-shadow: inset 0 0 0 1.5px var(--steel);
}
.motion-toggle:hover { color: var(--chrome); box-shadow: inset 0 0 0 1px var(--trace); }
.motion-toggle[aria-pressed="true"]::before {
  background: var(--trace) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2303061A' stroke-width='2.2'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E") center / 14px no-repeat;
  box-shadow: none;
}
@media (min-width: 640px) { .cols { grid-template-columns: repeat(3, minmax(0, max-content)); gap: var(--s-5) var(--s-9); } }
@media (min-width: 960px) { .footer-inner { grid-template-columns: auto minmax(0, 1fr); } }

/* ============================================================
   PAGE HEADER BANDS (inner pages) + LEGAL HEAD + CLOSING BAND
   ============================================================ */

/* .page-band > .env (optional) + .container.laned.page-band-inner > .page-band-text (h1 + .lede) + .portal (optional) */
.page-band {
  position: relative;
  isolation: isolate;
  overflow: clip;
  padding: calc(var(--nav-h) + var(--s-7)) 0 var(--s-8);
}
.page-band-inner { position: relative; z-index: 2; display: grid; gap: var(--s-7) var(--s-8); align-items: end; }
.page-band-text { position: relative; min-width: 0; }
.page-band-text > .pad { left: calc(var(--lane) * -0.5 - var(--pad) / 2); top: calc(var(--fs-h1) * 0.45 - var(--pad) / 2); }
.page-band h1 { margin-bottom: var(--s-5); }
.page-band .lede { margin-bottom: 0; }
/* the stage: a crest portal with a cast cut-out standing on a rock ledge in front of it. Tune per page with
   --cast-x / --cast-y / --cast-w (cast position and width as % of the stage) */
.page-band-stage { position: relative; width: min(100%, 560px); aspect-ratio: 1.12; justify-self: end; margin-bottom: var(--s-5); }
.page-band-stage > .portal { position: absolute; inset: 0; }
.page-band-stage > .cast { z-index: 4; left: var(--cast-x, -24%); bottom: var(--cast-y, 2%); width: var(--cast-w, 86%); }
.stage-ledge { position: absolute; z-index: 3; left: -34%; right: -14%; bottom: -14%; pointer-events: none; }
.stage-ledge > img {
  display: block; width: 100%; height: auto; max-width: none;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 30%, #000 80%, transparent 100%), linear-gradient(90deg, transparent 0%, #000 16%, #000 90%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(180deg, transparent 0%, #000 30%, #000 80%, transparent 100%), linear-gradient(90deg, transparent 0%, #000 16%, #000 90%, transparent 100%);
  mask-composite: intersect;
}
@media (min-width: 960px) {
  .page-band { min-height: clamp(460px, 64svh, 660px); display: flex; align-items: flex-end; }
  .page-band-inner { grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); }
}
@media (max-width: 959.98px) { .page-band-stage { justify-self: center; width: min(86%, 480px); margin-top: var(--s-4); } }

/* legal: title, 'Last updated', then a trace rule the spine can enter */
.page-head { position: relative; padding: calc(var(--nav-h) + var(--s-8)) 0 var(--s-6); }
.page-head h1 { font-size: clamp(2.5rem, 1.6rem + 3vw, 4.5rem); margin-bottom: var(--s-4); }
.page-head p { color: var(--steel); font-size: var(--fs-small); margin: 0; }
.page-head .container { position: relative; }
.page-head .pad { left: calc(var(--lane) * -0.5 - var(--pad) / 2); top: calc(clamp(2.5rem, 1.6rem + 3vw, 4.5rem) * 0.45 - var(--pad) / 2); }

/* closing band (home static; config + rules via main.js renderCtaBand): heading + actions over a night
   ground, the raptor stalking through the ferns on the right, a via on the spine */
.cta-band { position: relative; isolation: isolate; overflow: clip; }
.cta-band.sec { padding: var(--s-10) 0 calc(var(--s-10) + 40px); }
.cta-env { z-index: 0; }
.cta-mist { top: auto; height: 70%; }
.cta-mist > img { object-position: 50% 100%; opacity: 0.4; }
.cta-env .env-scrim { background: linear-gradient(180deg, var(--void) 0%, rgba(3, 6, 26, 0) 40%); }
.cta-stage { position: absolute; z-index: 1; right: -3%; bottom: 0; width: min(58vw, 820px); aspect-ratio: 1.9; pointer-events: none; }
.cta-ledge { position: absolute; left: -12%; right: -12%; bottom: -8%; }
.cta-ledge > img { display: block; width: 100%; height: auto; max-width: none; }
/* ground strips fade into the night at their top and ends, so they never read as a pasted rectangle */
.cta-ledge > img, .ground-fade {
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 34%, #000 80%, transparent 100%), linear-gradient(90deg, transparent 0%, #000 14%, #000 86%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(180deg, transparent 0%, #000 34%, #000 80%, transparent 100%), linear-gradient(90deg, transparent 0%, #000 14%, #000 86%, transparent 100%);
  mask-composite: intersect;
}
.cta-raptor { left: 4%; bottom: 16%; width: 90%; }
/* ferns in front of the raptor: its feet are lost in them, so it stalks through the undergrowth rather than
   standing on a pasted strip */
.cta-ferns { position: absolute; z-index: 2; left: -8%; right: -10%; bottom: -3%; pointer-events: none; }
.cta-ferns > img { display: block; width: 100%; height: auto; max-width: none; -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 16%, #000 90%, transparent 100%); mask-image: linear-gradient(90deg, transparent 0%, #000 16%, #000 90%, transparent 100%); }
/* settings: the raptor lurks, a close crop of head and shoulders rising out of the ferns at the band's edge */
.cta-lurk { right: 0; width: min(50vw, 720px); aspect-ratio: 1.45; overflow: clip; }
.cta-lurk .cta-raptor { left: 10%; bottom: -30%; width: 165%; }
.cta-lurk .cta-ferns { left: -4%; right: -4%; bottom: -6%; }
/* rules: a quiet close, no creature; the heath runs along the band's foot under the mist */
.cta-quiet { left: 0; right: 0; width: auto; aspect-ratio: auto; height: 60%; }
.cta-quiet .cta-ledge { left: 40%; right: -8%; bottom: -16%; opacity: 0.8; }
.cta-band .container { position: relative; z-index: 3; }
.cta-head { margin-bottom: var(--s-5); }
.cta-band h2 { max-width: 14ch; }
.cta-band #cta-band-body, .cta-band .cta-body { max-width: 44ch; font-size: var(--fs-lede); color: var(--silver); margin-bottom: var(--s-6); }
/* the copy always ends 24px+ short of where the raptor starts (the stage is pinned to the band's right edge); on
   laptops the two buttons stack under it for the same reason */
@media (min-width: 960px) {
  .cta-band #cta-band-body, .cta-band .cta-body { max-width: min(44ch, calc(103% + 1.06 * var(--gut) + 0.03 * var(--lane) - 0.96 * min(58vw, 820px) - 24px)); }
}
@media (min-width: 960px) and (max-width: 1179.98px) { .cta-actions { flex-direction: column; align-items: flex-start; } }
.cta-actions { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-4); }
/* tablets and phones: the raptor stalks in below the copy, never beside it */
@media (max-width: 959.98px) {
  .cta-band.sec { padding-bottom: 0; display: flex; flex-direction: column; }
  .cta-band .container { order: 1; }
  .cta-stage { order: 2; position: relative; right: auto; width: 84%; margin: var(--s-4) 0 0 auto; }
}
@media (max-width: 719.98px) { .cta-stage { width: 112%; margin: var(--s-6) 0 0 -6%; } }
@media (max-width: 959.98px) {
  .cta-stage.cta-quiet { width: 100%; height: auto; aspect-ratio: 3.4; margin: 0; }
  .cta-quiet .cta-ledge { left: -10%; right: -10%; }
}

/* ============================================================
   MOTION CONTRACT
   - prefers-reduced-motion AND html[data-motion=off] neutralise every
     animation, transition and view transition (main.js sets the
     attribute from localStorage 'spg-motion' before rendering; the
     footer toggle fires 'spg:motion-off' and motion.js reverts GSAP,
     destroys Lenis and removes its classes).
   - html[data-open]: armed by open.js in <head> (2s safety timeout),
     removed by motion.js once GSAP holds the load sequence.
   ============================================================ */

/* Lenis (lenis.css 1.3.26, MIT, inlined) — Lenis needs native smooth scrolling off while it runs */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis:not(.lenis-autoToggle).lenis-stopped { overflow: clip; }
.lenis [data-lenis-prevent], .lenis [data-lenis-prevent-wheel], .lenis [data-lenis-prevent-touch],
.lenis [data-lenis-prevent-vertical], .lenis [data-lenis-prevent-horizontal] { overscroll-behavior: contain; }
.lenis.lenis-smooth iframe { pointer-events: none; }
.lenis.lenis-autoToggle { transition-property: overflow; transition-duration: 1ms; transition-behavior: allow-discrete; }

/* the nav is never pre-hidden; only the header pieces the load sequence animates wait for it */
html[data-open] [data-intro] { visibility: hidden; }

@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  /* the nav is the same on every page: it stays put while the page under it changes */
  .nav { view-transition-name: site-nav; }
  ::view-transition-group(site-nav) { animation-duration: 0s; }
  html:not([data-motion="off"]) { scroll-behavior: smooth; }
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 220ms; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion="off"] *::after {
  animation: none !important;
  transition: none !important;
  scroll-behavior: auto !important;
}
html[data-motion="off"]::view-transition-group(*),
html[data-motion="off"]::view-transition-old(*),
html[data-motion="off"]::view-transition-new(*) { animation: none !important; }

/* ============================================================
   FORCED COLOURS (Windows High Contrast): gradient text and ::before
   fills vanish, so text and selected states are repainted in system colours
   ============================================================ */

@media (forced-colors: active) {
  .chrome { color: CanvasText; -webkit-text-fill-color: CanvasText; background: none; }
  .btn, .copy-ip, .tab, .motion-toggle, .chip, .badge { border: 1px solid ButtonText; }
  .pad::after { background: Highlight; }
  .tab[aria-selected="true"], .tab.active, .motion-toggle[aria-pressed="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .nav-links a.active::after, .nav-links a[aria-current="page"]::after { forced-color-adjust: none; background: Highlight; }
}
