@charset "utf-8";

/* ==========================================================================
   MJOLNIR FORGE - mjolnirforge.com
   A product of Forge & Frequency LLC

   Design tokens are lifted directly from the shipping iOS app
   (Views/Brand.swift + Views/NorseDesign.swift) so the website and the
   application share one visual language rather than resembling each other.

   Contents
     01  Fonts
     02  Tokens
     03  Reset & base
     04  Environment (the Forge Hall)
     05  Typography
     06  Surfaces (glass / steel)
     07  Buttons & links
     08  Navigation
     09  Section 1  The Gate
     10  Section 2  The Central Forge
     11  Section 3  The Implement Hall
     12  Section 4  The War Table
     13  Section 5  The Forge Ledger
     14  Section 6  Local-first
     15  Section 7  FAQ
     16  Section 8  The Archive
     17  Footer
     18  Legal pages
     19  Motion & print
   ========================================================================== */


/* 01  FONTS ---------------------------------------------------------------
   The same two families the iOS app bundles. Self-hosted: no third-party
   request, no external tracking vector, no CDN dependency.
   Both SIL Open Font License 1.1 - see assets/fonts/licenses/.
   ------------------------------------------------------------------------ */

@font-face {
  font-family: "Cinzel";
  src: url("assets/fonts/cinzel-var.woff2") format("woff2-variations"),
       url("assets/fonts/cinzel-var.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "InterVar";
  src: url("assets/fonts/inter-var.woff2") format("woff2-variations"),
       url("assets/fonts/inter-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}


/* 02  TOKENS -------------------------------------------------------------- */

:root {
  /* Surfaces - NorseTheme.ColorToken */
  --bg-0: #05090c;
  --bg-1: #071018;
  --bg-2: #0a161d;
  --card: #071017;
  --card-raised: #0d171d;
  --card-overlay: rgba(16, 30, 39, 0.74);

  /* Edges */
  --stroke: #355b66;
  --stroke-soft: rgba(143, 178, 191, 0.20);
  --stroke-hair: rgba(143, 178, 191, 0.11);

  /* Forge energy */
  --cyan: #20d7ff;
  --cyan-soft: #10bfe3;
  --cyan-deep: #0b4452;
  --brand: #34d6ff;

  /* Ember - used sparingly, as warmth not as a second brand colour */
  --ember: #ff9a35;
  --bronze: #c79a56;
  --bronze-deep: #7c5a2e;

  /* Text */
  --text: #f4f7fa;
  --text-2: #b9c4cd;
  --text-3: #93a0aa;

  /* Type */
  --font-display: "Cinzel", "Iowan Old Style", "Palatino Linotype", Palatino,
                  "Times New Roman", serif;
  --font-ui: "InterVar", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;

  /* Fluid scale */
  --step--1: clamp(0.82rem, 0.79rem + 0.13vw, 0.89rem);
  --step-0:  clamp(1rem, 0.96rem + 0.19vw, 1.12rem);
  --step-1:  clamp(1.19rem, 1.11rem + 0.38vw, 1.44rem);
  --step-2:  clamp(1.41rem, 1.27rem + 0.68vw, 1.86rem);
  --step-3:  clamp(1.67rem, 1.45rem + 1.12vw, 2.4rem);
  --step-4:  clamp(1.98rem, 1.63rem + 1.76vw, 3.1rem);
  --step-5:  clamp(2.35rem, 1.8rem + 2.72vw, 4rem);
  --step-6:  clamp(2.8rem, 1.92rem + 4.35vw, 5.4rem);

  /* Space */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;
  --sp-9: 6rem;
  --sp-10: 8rem;

  /* Geometry - MjolnirDesign radius scale */
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-pill: 999px;

  --shell: 1240px;
  --shell-wide: 1440px;
  --shell-text: 68ch;

  --nav-h: 68px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

@media (min-width: 900px) {
  :root { --nav-h: 76px; }
}


/* 03  RESET & BASE -------------------------------------------------------- */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchor targets clear the sticky masthead. */
  scroll-padding-top: calc(var(--nav-h) + var(--sp-5));
}

body {
  min-height: 100svh;
  background-color: var(--bg-0);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.65;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

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

input, button, textarea, select { font: inherit; color: inherit; }

:target { scroll-margin-top: calc(var(--nav-h) + var(--sp-5)); }

/* Focus: a forge-cyan ring that clears every surface it can land on. */
:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}
:focus:not(:focus-visible) { outline: none; }

::selection {
  background: rgba(32, 215, 255, 0.28);
  color: var(--text);
}

.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 200;
  transform: translate(-50%, -140%);
  padding: var(--sp-3) var(--sp-5);
  background: var(--cyan);
  color: #03161c;
  font-weight: 650;
  font-size: var(--step--1);
  letter-spacing: 0.02em;
  text-decoration: none;
  border-radius: 0 0 var(--r-md) var(--r-md);
  transition: transform 0.18s var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: clamp(1.15rem, 4vw, 2.5rem);
}
.shell--wide { max-width: var(--shell-wide); }


/* 04  ENVIRONMENT --------------------------------------------------------- */
/* Layer 1 of the build. A single fixed plate of the Forge Hall sits behind
   the whole document; content descends into it as you scroll. Product
   artwork (Layer 3) mounts on top of this later without touching it. */

.env {
  position: fixed;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  pointer-events: none;
}

.env__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 58%;
  /* The plate is a lit interior; pull it toward the app's colder key. */
  filter: saturate(0.92) contrast(1.04);
}

/* Vignette + floor falloff, fixed so the hall reads as a real room. */
.env__scrim {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 78% at 50% 44%,
      rgba(5, 9, 12, 0) 0%,
      rgba(5, 9, 12, 0.30) 52%,
      rgba(5, 9, 12, 0.80) 100%),
    linear-gradient(180deg,
      rgba(5, 9, 12, 0.86) 0%,
      rgba(5, 9, 12, 0.30) 22%,
      rgba(5, 9, 12, 0.34) 60%,
      rgba(5, 9, 12, 0.92) 100%);
}

/* Everything below the hero sits deeper in the hall, where it is darker.
   The plate stays faintly perceptible - timbers, torchlight - but never
   competes with copy. */
.deep { position: relative; isolation: isolate; }
.deep::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(90% 40% at 50% 0%,
      rgba(11, 68, 82, 0.20) 0px,
      rgba(5, 9, 12, 0) 460px),
    /* Pixel stops, not percentages. A percentage stop would stretch this
       ramp over ~700px on a long page, leaving the first section head
       under-protected. 220px lands the full alpha before any copy. */
    linear-gradient(180deg,
      rgba(5, 9, 12, 0.60) 0px,
      rgba(5, 9, 12, 0.93) 220px,
      rgba(5, 9, 12, 0.95) 100%);
}


/* 05  TYPOGRAPHY ---------------------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: 0.005em;
  text-wrap: balance;
  color: var(--text);
}

h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { text-wrap: pretty; }

.lede {
  font-size: var(--step-1);
  line-height: 1.6;
  color: var(--text-2);
  max-width: 58ch;
}

/* Uppercase section label, exactly the app's treatment. */
.eyebrow {
  display: block;
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 620;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: var(--sp-4);
}
.eyebrow--muted { color: var(--text-3); }

/* Hairline rule with a forge-lit centre. */
.rule {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg,
    transparent,
    var(--stroke-soft) 18%,
    rgba(32, 215, 255, 0.42) 50%,
    var(--stroke-soft) 82%,
    transparent);
}


/* 06  SURFACES ------------------------------------------------------------ */
/* The app's translucent panel: dark glass, steel edge, one small cyan
   highlight along the top edge where the forge light catches it. */

.panel {
  position: relative;
  background: var(--card-overlay);
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 3vw, 2.1rem);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.045) inset,
    0 18px 44px -28px rgba(0, 0, 0, 0.95);
}

/* Forge light along the leading edge. */
.panel::before {
  content: "";
  position: absolute;
  inset-inline: 12%;
  top: -1px;
  height: 1px;
  background: linear-gradient(90deg,
    transparent, rgba(32, 215, 255, 0.5), transparent);
  pointer-events: none;
}

.panel--raised { background: rgba(13, 23, 29, 0.86); }
.panel--flush  { padding: 0; overflow: hidden; }

/* Interactive panels lift toward the light. */
.panel--lift { transition: border-color 0.25s var(--ease), transform 0.25s var(--ease), box-shadow 0.25s var(--ease); }
.panel--lift:hover,
.panel--lift:focus-within {
  border-color: rgba(32, 215, 255, 0.34);
  transform: translateY(-3px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 24px 52px -28px rgba(0, 0, 0, 0.98),
    0 0 0 1px rgba(32, 215, 255, 0.08);
}

/* Section rhythm. */
.section { padding-block: clamp(3.5rem, 8vw, var(--sp-10)); }
.section--tight { padding-block: clamp(2.5rem, 5vw, var(--sp-8)); }

.section__head { margin-bottom: clamp(2rem, 4vw, var(--sp-7)); }
.section__head--center {
  text-align: center;
  margin-inline: auto;
  max-width: 60ch;
}
.section__head--center .lede { margin-inline: auto; }
.section__head h2 + .lede { margin-top: var(--sp-4); }


/* 07  BUTTONS & LINKS ----------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  min-height: 48px;
  padding: var(--sp-3) var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-family: var(--font-ui);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease),
              color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn svg { width: 1.15em; height: 1.15em; flex: none; }

.btn--primary {
  background: linear-gradient(180deg, var(--cyan), var(--cyan-soft));
  color: #02161d;
  font-weight: 680;
  box-shadow: 0 10px 30px -14px rgba(32, 215, 255, 0.75);
}
.btn--primary:hover { background: linear-gradient(180deg, #4ce1ff, var(--cyan)); }

.btn--ghost {
  background: rgba(16, 30, 39, 0.6);
  border-color: var(--stroke-soft);
  color: var(--text);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.btn--ghost:hover {
  border-color: rgba(32, 215, 255, 0.5);
  background: rgba(16, 40, 52, 0.7);
}

.link {
  color: var(--cyan);
  text-decoration: none;
  border-bottom: 1px solid rgba(32, 215, 255, 0.32);
  padding-bottom: 1px;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.link:hover { color: #6fe6ff; border-bottom-color: currentColor; }

/* Inline links inside prose need an underline, not just colour. */
.prose a, .legal-body a { color: var(--cyan); text-underline-offset: 3px; }
.prose a:hover, .legal-body a:hover { color: #6fe6ff; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  color: var(--cyan);
  font-weight: 560;
  font-size: var(--step--1);
  letter-spacing: 0.02em;
  text-decoration: none;
}
.link-arrow::after {
  content: "\2192";
  transition: transform 0.2s var(--ease);
}
.link-arrow:hover { text-decoration: underline; text-underline-offset: 4px; }
.link-arrow:hover::after { transform: translateX(4px); }

/* App Store: real badge when APP_STORE_URL is set, pending state until then. */
.appstore {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 52px;
  padding: 0.6rem var(--sp-5);
  border-radius: var(--r-md);
  border: 1px solid var(--stroke-soft);
  background: rgba(6, 14, 19, 0.82);
  color: var(--text);
  text-decoration: none;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.appstore:hover { border-color: rgba(32, 215, 255, 0.5); background: rgba(10, 26, 34, 0.9); }
.appstore svg { width: 26px; height: 26px; flex: none; fill: currentColor; }
.appstore__text { display: grid; text-align: left; line-height: 1.18; }
.appstore__sm {
  font-size: 0.63rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-3);
}
.appstore__lg { font-size: 1.06rem; font-weight: 620; letter-spacing: 0.005em; }

.appstore--pending { cursor: default; border-style: dashed; }
.appstore--pending:hover { border-color: var(--stroke-soft); background: rgba(6, 14, 19, 0.82); }
.appstore--pending .appstore__lg { color: var(--text-2); }

/* Apple's official badge is 119.66 x 40 pt — a 2.9915:1 ratio. The pending
   control is locked to that ratio and height so the hero layout is already
   final: dropping in Apple's supplied SVG changes the artwork and nothing
   else. Deliberately NOT a lookalike — Apple's guidelines require their
   own artwork, and an approximation is the kind of thing App Review flags. */
.appstore {
  box-sizing: border-box;
  height: 52px;
  min-height: 52px;
  padding-inline: calc(52px * 0.34);
}
.appstore--pending {
  aspect-ratio: 119.66 / 40;
  justify-content: center;
}

/* When APP_STORE_URL is set, site.js swaps in a real link. If you have
   replaced this with Apple's official badge image, .appstore--official
   strips the chrome so the artwork stands alone as Apple requires. */
.appstore--official {
  padding: 0;
  border: 0;
  background: none;
  height: 52px;
}
.appstore--official img { height: 100%; width: auto; display: block; }
.appstore--official:hover { background: none; border: 0; }


/* 08  NAVIGATION ---------------------------------------------------------- */

.masthead {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(4, 9, 12, 0.72);
  border-bottom: 1px solid var(--stroke-hair);
  backdrop-filter: blur(18px) saturate(1.2);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: var(--nav-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
  color: var(--text);
  flex: none;
}
.brand__mark {
  width: 34px; height: 34px;
  border-radius: 9px;
  border: 1px solid rgba(32, 215, 255, 0.28);
  object-fit: cover;
  flex: none;
}
.brand__word {
  font-family: var(--font-display);
  font-size: 1.16rem;
  font-weight: 600;
  letter-spacing: 0.085em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
}
.brand__o { color: var(--cyan); }
.brand__sub {
  display: block;
  font-family: var(--font-ui);
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-top: 3px;
}

.nav { display: none; }
.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 1.6vw, 1.4rem);
  list-style: none;
  padding: 0; margin: 0;
}
.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 0.4rem;
  font-size: 0.93rem;
  font-weight: 500;
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.18s var(--ease);
}
.nav__link:hover { color: var(--text); }
.nav__link[aria-current="page"] { color: var(--cyan); }

.masthead__cta { display: none; }

/* Mobile disclosure button. Links are never simply hidden - they move
   into the panel below and stay reachable by keyboard and screen reader. */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: auto;
  min-width: 48px;
  min-height: 44px;
  padding-inline: 0.85rem;
  background: rgba(16, 30, 39, 0.7);
  border: 1px solid var(--stroke-soft);
  border-radius: var(--r-pill);
  color: var(--text);
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}
.nav-toggle__bars {
  display: grid;
  gap: 4px;
  width: 17px;
}
.nav-toggle__bars span {
  display: block;
  height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.22s var(--ease), opacity 0.18s var(--ease);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

.nav-panel {
  border-top: 1px solid var(--stroke-hair);
  background: rgba(4, 9, 12, 0.96);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  max-height: min(72svh, 640px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.nav-panel[hidden] { display: none; }
.nav-panel__list {
  list-style: none;
  padding: var(--sp-3) 0 var(--sp-5);
  margin: 0;
}
.nav-panel__list a {
  display: flex;
  align-items: center;
  min-height: 52px;
  padding: 0 var(--sp-2);
  color: var(--text);
  font-size: 1.02rem;
  text-decoration: none;
  border-bottom: 1px solid var(--stroke-hair);
}
.nav-panel__list li:last-child a { border-bottom: 0; }
.nav-panel__list a[aria-current="page"] { color: var(--cyan); }
.nav-panel__cta { padding: var(--sp-2) 0 var(--sp-5); }
.nav-panel__cta .btn { width: 100%; }

@media (min-width: 1000px) {
  .nav { display: block; }
  .nav-toggle, .nav-panel { display: none !important; }
  .masthead__cta { display: inline-flex; }
}


/* 09  THE GATE ------------------------------------------------------------ */

.gate {
  position: relative;
  display: flex;
  align-items: center;
  min-height: clamp(560px, calc(100svh - var(--nav-h)), 900px);
  padding-block: clamp(3rem, 9vw, 6.5rem);
}

/* Reading scrim.
   The brazier is the brightest thing in the plate (near rgb 236,247,242), so
   hero copy laid straight over it fails AA. This darkens the side the copy
   occupies and releases toward the side that stays vivid, which is also where
   the Stage 2 anvil and device composition will mount.
   Alpha over the copy band never drops below 0.86 - see tools/verify-build.py,
   which measures against that figure. Change one, change the other. */
.gate::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(5, 9, 12, 0.72) 0%,
    rgba(5, 9, 12, 0.88) 16%,
    rgba(5, 9, 12, 0.88) 84%,
    rgba(5, 9, 12, 0.70) 100%);
}

@media (min-width: 980px) {
  /* Cinematic split: dark where you read, lit where the product will stand. */
  .gate::before {
    background: linear-gradient(96deg,
      rgba(5, 9, 12, 0.94) 0%,
      rgba(5, 9, 12, 0.86) 58%,
      rgba(5, 9, 12, 0.40) 74%,
      rgba(5, 9, 12, 0.18) 100%);
  }
}

.gate__inner {
  display: grid;
  gap: clamp(2.5rem, 6vw, 4rem);
  width: 100%;
}

.gate__title {
  font-size: var(--step-6);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.02;
}
.gate__title .brand__o { color: var(--cyan); }

.gate__tagline {
  margin-top: var(--sp-4);
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
}
.gate__tagline em {
  font-style: normal;
  color: var(--cyan);
}

.gate__lede {
  margin-top: var(--sp-5);
  max-width: 52ch;
  font-size: var(--step-1);
  color: var(--text-2);
}

.gate__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: clamp(1.8rem, 4vw, 2.6rem);
}

.gate__note {
  margin-top: var(--sp-4);
  font-size: var(--step--1);
  color: var(--text-3);
}

/* STAGE 2 — the product composition.
   Layer 1 is the Forge Hall. This is layer 3: the real anvil plate cropped
   from the app's own AnvilWorkoutBackground asset, with the device standing
   on its face. Every dimension derives from --plinth-w, so the whole
   composition scales as one object and the device never drifts off the
   anvil's surface. */
.gate__stage {
  --dev-w: clamp(190px, 19vw, 282px);

  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
}

/* Forge light blooming behind the device. This is what keeps it from
   reading as a sticker: the light sits behind the object, in the room. */
.gate__stage::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: -1;
  width: calc(var(--dev-w) * 2.4);
  height: calc(var(--dev-w) * 2.4);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(32, 215, 255, 0.20),
    rgba(32, 215, 255, 0.07) 46%,
    transparent 72%);
  filter: blur(14px);
  pointer-events: none;
}

/* --- the device ------------------------------------------------------- */

.device {
  position: relative;
  z-index: 2;
  width: var(--dev-w);
  /* iPhone 15/16 Pro: 393 x 852 pt. */
  aspect-ratio: 393 / 852;
  padding: calc(var(--dev-w) * 0.028);
  border-radius: calc(var(--dev-w) * 0.148);
  /* Brushed titanium rail. */
  background:
    linear-gradient(150deg, #6c737a 0%, #2b3136 18%, #1a1e22 48%, #343a40 78%, #7b8288 100%);
  /* Shadow is thrown down and away rather than tight underneath — a tight
     shadow implies a surface directly below, which is what we just removed. */
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.85),
    0 2px 1px rgba(255, 255, 255, 0.14) inset,
    0 46px 90px -30px rgba(0, 0, 0, 0.95),
    0 0 90px -20px rgba(32, 215, 255, 0.38);
  animation: device-float 7s ease-in-out infinite;
}

/* A slow idle drift. Small enough to register as "suspended" rather than
   as an animation the reader has to watch. */
@keyframes device-float {
  0%, 100% { transform: translateY(-0.8%); }
  50%      { transform: translateY(0.8%); }
}

.device__screen {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: calc(var(--dev-w) * 0.125);
  background: var(--bg-0);
}

.device__screen img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* Dynamic Island. */
.device__island {
  position: absolute;
  top: calc(var(--dev-w) * 0.030);
  left: 50%;
  z-index: 3;
  width: calc(var(--dev-w) * 0.28);
  height: calc(var(--dev-w) * 0.082);
  transform: translateX(-50%);
  border-radius: var(--r-pill);
  background: #000;
  pointer-events: none;
}

/* Glass sheen across the panel. */
.device__glare {
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  background: linear-gradient(122deg,
    rgba(255, 255, 255, 0.10) 0%,
    rgba(255, 255, 255, 0.03) 22%,
    transparent 42%,
    transparent 100%);
  pointer-events: none;
}

@media (min-width: 980px) {
  .gate__inner {
    grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
    align-items: center;
  }
}

/* Mobile: the composition still shows, smaller, beneath the copy. Hiding
   the product on phones would be an odd choice for an iPhone app. */
@media (max-width: 979px) {
  .gate__stage {
    --dev-w: clamp(180px, 52vw, 248px);
    margin-top: var(--sp-5);
  }
}

@media (prefers-reduced-transparency: reduce) {
  .device__glare { display: none; }
}

/* The float is decoration. Anyone who has asked for less motion gets none —
   the global reduced-motion rule caps animation duration, but an infinite
   loop still needs switching off explicitly. */
@media (prefers-reduced-motion: reduce) {
  .device { animation: none; }
}

/* Scroll cue */
.gate__cue {
  display: none;
  position: absolute;
  left: 50%;
  bottom: clamp(1rem, 3vw, 2rem);
  transform: translateX(-50%);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--text-3);
  text-decoration: none;
}
.gate__cue::after {
  content: "";
  display: block;
  width: 1px;
  height: 34px;
  margin: 0.7rem auto 0;
  background: linear-gradient(180deg, rgba(32, 215, 255, 0.55), transparent);
}
.gate__cue:hover { color: var(--text-2); }
@media (min-width: 980px) and (min-height: 720px) { .gate__cue { display: block; } }


/* 10  THE CENTRAL FORGE --------------------------------------------------- */

.forge-grid {
  display: grid;
  gap: clamp(1rem, 2vw, 1.4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 660px) { .forge-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .forge-grid { grid-template-columns: repeat(3, 1fr); } }

.forge-card { display: flex; flex-direction: column; gap: var(--sp-3); }
.forge-card h3 { font-size: var(--step-1); }
.forge-card p { color: var(--text-2); font-size: 0.97rem; }

/* Recessed steel plate holding a Forge Journal glyph.
   52px, not 46px: the glyphs are 1000-unit line drawings at stroke-width 45,
   so the rendered stroke is size x 0.045. At 46px the plate gave the glyph
   38px x 0.68 = 26px and a 1.16px stroke; at 52px it gets 38px and 1.71px,
   which is the difference between a crisp line and a grey smear. */
.slot {
  /* MUST declare its own display. This is a <span>, so it is inline by
     default. In .forge-card the parent is flex and blockifies it, but
     .ledger-card is not — there the span stayed inline, width/height were
     ignored, and the child img's percentage width resolved against the
     PANEL instead of the plate. Result: enormous glyphs pushing the card
     text out. Never rely on a parent's display to size this. */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  flex: none;
  margin-bottom: var(--sp-2);
  border-radius: 12px;
  border: 1px solid var(--stroke-hair);
  background:
    linear-gradient(160deg, rgba(32, 215, 255, 0.10), transparent 62%),
    linear-gradient(180deg, rgba(13, 23, 29, 0.95), rgba(6, 13, 18, 0.95));
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.05) inset,
    0 -1px 0 rgba(0, 0, 0, 0.55) inset;
}
.slot--wide { width: 100%; height: 84px; border-radius: var(--r-md); }

/* Forge Journal glyph seated in the recessed plate. The plate reads as
   struck metal, so the glyph sits slightly inset rather than filling it. */
/* 66%, and no margin. The old 13.5% margin was a percentage of the
   containing block's WIDTH, which is exactly the fragile coupling that
   broke above. The flex centring on .slot handles placement now.
   66% of 52px = 34px glyph, stroke 34 x 0.045 = 1.53 CSS px — still
   comfortably over the one-pixel floor, with more air in the plate. */
.slot img {
  width: 66%;
  height: 66%;
  margin: 0;
  opacity: 0.95;
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
}
.panel--lift:hover .slot img { opacity: 1; transform: scale(1.06); }
@media (prefers-reduced-motion: reduce) {
  .panel--lift:hover .slot img { transform: none; }
}

.spec-list {
  list-style: none;
  padding: 0;
  margin: var(--sp-2) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.spec-list li {
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.015em;
  color: var(--text-2);
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-pill);
  background: rgba(8, 18, 24, 0.7);
}

/* Base / Build / Peak / Taper */
.phases {
  display: grid;
  gap: var(--sp-3);
  margin-top: clamp(1.2rem, 2.5vw, 1.6rem);
  grid-template-columns: 1fr;
  counter-reset: phase;
}
@media (min-width: 720px) { .phases { grid-template-columns: repeat(4, 1fr); } }

.phase {
  position: relative;
  padding: var(--sp-5) var(--sp-4) var(--sp-4);
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-md);
  background: rgba(8, 18, 24, 0.66);
  overflow: hidden;
}
/* Heat rises across the four phases: cool base to bright peak, then back. */
.phase::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: var(--phase-tint, var(--stroke));
}
.phase:nth-child(1) { --phase-tint: #2a6070; }
.phase:nth-child(2) { --phase-tint: #10bfe3; }
.phase:nth-child(3) { --phase-tint: #20d7ff; }
.phase:nth-child(4) { --phase-tint: #c79a56; }

.phase__name {
  font-family: var(--font-display);
  font-size: 1.14rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin-bottom: var(--sp-2);
}
.phase p { font-size: 0.9rem; color: var(--text-2); line-height: 1.55; }


/* 11  THE IMPLEMENT HALL -------------------------------------------------- */

.implements {
  display: grid;
  gap: clamp(0.75rem, 1.6vw, 1.1rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 244px), 1fr));
  list-style: none;
  padding: 0;
  margin: 0;
}

.implement {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-md);
  background: rgba(9, 19, 25, 0.66);
  transition: border-color 0.22s var(--ease), background 0.22s var(--ease);
}
.implement:hover {
  border-color: rgba(32, 215, 255, 0.3);
  background: rgba(12, 28, 36, 0.74);
}
.implement .slot { width: 40px; height: 40px; margin: 0; flex: none; }
.implement__body { min-width: 0; }
.implement__name {
  font-family: var(--font-display);
  font-size: 1.02rem;
  letter-spacing: 0.045em;
  line-height: 1.25;
}

/* Movement-pattern tags. The primary is the event's defining demand; the
   rest are the other patterns it trains. Both are carried by markup, not
   by colour alone — the primary is also first in source order and labelled
   for assistive tech, so the distinction survives without colour vision. */
.implement__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 7px;
}
.tag {
  font-family: var(--font-ui);
  font-size: 0.63rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.32em 0.6em;
  border: 1px solid var(--stroke-hair);
  border-radius: 4px;
  color: var(--text-3);
  white-space: nowrap;
}
.tag--primary {
  border-color: rgba(32, 215, 255, 0.42);
  background: rgba(11, 68, 82, 0.55);
  color: var(--cyan);
}

.hall-note {
  margin-top: clamp(1.5rem, 3vw, 2rem);
  font-size: var(--step--1);
  color: var(--text-3);
  max-width: 74ch;
}


/* 12  THE WAR TABLE ------------------------------------------------------- */

.war-table { position: relative; }

.war-steps {
  display: grid;
  gap: clamp(1rem, 2vw, 1.4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 700px)  { .war-steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .war-steps { grid-template-columns: repeat(4, 1fr); } }

.war-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: clamp(1.3rem, 2.4vw, 1.7rem);
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-md);
  background:
    linear-gradient(180deg, rgba(16, 30, 39, 0.78), rgba(7, 16, 23, 0.86));
}
.war-step__num {
  font-family: var(--font-display);
  font-size: 1.9rem;
  font-weight: 500;
  line-height: 1;
  color: var(--cyan);
  letter-spacing: 0.04em;
}
.war-step h3 { font-size: var(--step-1); }
.war-step p { font-size: 0.95rem; color: var(--text-2); }

/* Etched rail linking the four stations, like a planning table surface. */
@media (min-width: 1080px) {
  .war-steps { position: relative; }
  .war-steps::before {
    content: "";
    position: absolute;
    left: 6%;
    right: 6%;
    top: -1.6rem;
    height: 1px;
    background: linear-gradient(90deg,
      transparent,
      rgba(32, 215, 255, 0.34) 12%,
      rgba(32, 215, 255, 0.34) 88%,
      transparent);
  }
  .war-step::before {
    content: "";
    position: absolute;
    top: -1.65rem;
    left: 50%;
    width: 7px; height: 7px;
    transform: translateX(-50%) rotate(45deg);
    background: var(--bg-0);
    border: 1px solid rgba(32, 215, 255, 0.55);
  }
}


/* 13  THE FORGE LEDGER ---------------------------------------------------- */

.ledger-grid {
  display: grid;
  gap: clamp(1rem, 2vw, 1.4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 680px)  { .ledger-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1060px) { .ledger-grid { grid-template-columns: repeat(3, 1fr); } }

/* Matches .forge-card. Both card types hold the same slot + heading + body
   structure and should lay out identically; the earlier mismatch is what
   exposed the inline-span bug in the first place. */
.ledger-card { display: flex; flex-direction: column; gap: var(--sp-3); }
.ledger-card h3 { font-size: var(--step-1); }
.ledger-card p { color: var(--text-2); font-size: 0.96rem; }

/* --- Forge Marks + Club medallions -------------------------------------
   Both are real app artwork on opaque near-black plates. They sit directly
   on the panel with no frame — the artwork already carries its own border,
   and adding another would double it up. */

.marks, .clubs { margin-top: clamp(1.5rem, 3vw, 2rem); }

.marks__row,
.clubs__row {
  display: grid;
  list-style: none;
  padding: 0;
  margin: var(--sp-5) 0 0;
}

/* Fixed column counts, not auto-fill.
   auto-fill sized tracks to the container and produced 11 columns for 16
   marks (one full row plus five orphans) and 9 tracks for 6 clubs (three
   dead tracks shoving the row left). Both counts below divide their item
   count exactly, so every row is full at every breakpoint. */
.marks__row {
  grid-template-columns: repeat(4, 1fr);   /* 16 = 4 x 4 */
  gap: clamp(1rem, 2vw, 1.5rem) var(--sp-3);
}
.clubs__row {
  grid-template-columns: repeat(3, 1fr);   /* 6 = 2 x 3 */
  gap: clamp(1.2rem, 2.4vw, 1.9rem) var(--sp-4);
}

/* 760, not 620: six across below this squeezes each medallion under 80px,
   where the struck-anvil detail in the artwork stops being legible. */
@media (min-width: 760px) {
  .clubs__row { grid-template-columns: repeat(6, 1fr); }  /* one clean row */
}
@media (min-width: 900px) {
  .marks__row { grid-template-columns: repeat(8, 1fr); }  /* 16 = 2 x 8 */
}

.mark, .club {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.4rem;
}

.mark img, .club img {
  width: 100%;
  height: auto;
  /* The plates are near-black at the edge; a hairline keeps them from
     dissolving entirely into the panel behind them. */
  box-shadow: 0 0 0 1px var(--stroke-hair), 0 10px 24px -14px rgba(0, 0, 0, 0.9);
  transition: box-shadow 0.25s var(--ease), transform 0.25s var(--ease);
}

/* Two different artworks, two different crops.
   Club medallions are struck coins — round objects on a dark square plate,
   so a full circle clips only the dead corners.
   Forge Marks are square SCENES (an anvil in a room, a hammer mid-strike).
   Circling those would slice the composition, so they get a rounded square
   matching the app's card radius. */
.club img { border-radius: 50%; }
.mark img { border-radius: 14%; }
.mark:hover img, .club:hover img {
  box-shadow: 0 0 0 1px rgba(32, 215, 255, 0.34), 0 14px 30px -14px rgba(0, 0, 0, 0.95);
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .mark:hover img, .club:hover img { transform: none; }
}

/* Names run from "Unbroken" to "Keeper of the Forge". Left alone, a one-line
   caption next to a three-line one makes the row look broken. Reserving two
   lines keeps the artwork on a common baseline; balance stops a lone orphan
   word on line two. */
.mark__name {
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.015em;
  color: var(--text-2);
  text-wrap: balance;
  min-height: 2.6em;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
@media (max-width: 619px) {
  /* Four columns on a phone is a narrow measure; ease the type down rather
     than let the longest names stack four words deep. */
  .mark__name { font-size: 0.62rem; min-height: 3.9em; }
}


.club__weight {
  font-family: var(--font-display);
  font-size: 1.02rem;
  letter-spacing: 0.05em;
  color: var(--text);
  margin-top: 0.15rem;
}
.club__name {
  font-size: 0.68rem;
  font-weight: 550;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-3);
  line-height: 1.3;
  /* Same reason as .mark__name: "Cold Forged Steel" wraps, "Red Flame"
     does not, and unequal caption heights break the row's baseline. */
  min-height: 2.6em;
}


/* 14  LOCAL-FIRST --------------------------------------------------------- */

.local {
  display: grid;
  gap: clamp(1.6rem, 4vw, 3rem);
  align-items: start;
}
@media (min-width: 940px) {
  .local { grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr); }
}

.local__points {
  list-style: none;
  padding: 0;
  margin: var(--sp-5) 0 0;
  display: grid;
  gap: var(--sp-4);
}
.local__points li {
  position: relative;
  padding-left: 1.7rem;
  color: var(--text-2);
}
.local__points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px; height: 8px;
  transform: rotate(45deg);
  border: 1px solid var(--cyan);
  background: rgba(32, 215, 255, 0.18);
}
.local__points strong { color: var(--text); font-weight: 600; }

.local__aside p { color: var(--text-2); font-size: 0.96rem; }
.local__aside p + p { margin-top: var(--sp-4); }
.local__aside .link-arrow { margin-top: var(--sp-5); }


/* 15  FAQ ----------------------------------------------------------------- */

.faq { display: grid; gap: var(--sp-3); max-width: 56rem; margin-inline: auto; }

.faq__item {
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-md);
  background: rgba(9, 19, 25, 0.68);
  overflow: hidden;
  transition: border-color 0.2s var(--ease);
}
.faq__item[open] { border-color: rgba(32, 215, 255, 0.26); }
.faq__item:hover { border-color: rgba(143, 178, 191, 0.22); }

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: 60px;
  padding: var(--sp-4) clamp(1rem, 2.4vw, 1.5rem);
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { color: #d9f6ff; }

.faq__sign {
  /* Declares its own display for the same reason .slot does — it currently
     sits in a flex parent, but a sized <span> should never depend on that. */
  display: block;
  position: relative;
  flex: none;
  width: 16px; height: 16px;
}
.faq__sign::before,
.faq__sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1.5px;
  background: var(--cyan);
  border-radius: 2px;
  transition: transform 0.24s var(--ease);
}
.faq__sign::after { transform: rotate(90deg); }
.faq__item[open] .faq__sign::after { transform: rotate(0deg); }

.faq__a {
  padding: 0 clamp(1rem, 2.4vw, 1.5rem) var(--sp-5);
  color: var(--text-2);
  font-size: 0.97rem;
}
.faq__a > * + * { margin-top: var(--sp-3); }
.faq__a ul { padding-left: 1.15rem; }
.faq__a li + li { margin-top: var(--sp-2); }


/* 16  THE ARCHIVE --------------------------------------------------------- */

.archive-grid {
  display: grid;
  gap: clamp(0.85rem, 1.8vw, 1.15rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
}

.archive-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-5);
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-md);
  background: rgba(9, 19, 25, 0.7);
  color: inherit;
  text-decoration: none;
  transition: border-color 0.22s var(--ease), transform 0.22s var(--ease),
              background 0.22s var(--ease);
}
.archive-card:hover {
  border-color: rgba(32, 215, 255, 0.34);
  background: rgba(13, 30, 39, 0.8);
  transform: translateY(-2px);
}
.archive-card h3 {
  font-size: 1.06rem;
  letter-spacing: 0.03em;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.archive-card h3::after {
  content: "\2192";
  color: var(--cyan);
  font-family: var(--font-ui);
  transition: transform 0.2s var(--ease);
}
.archive-card:hover h3::after { transform: translateX(4px); }
.archive-card p { font-size: 0.9rem; color: var(--text-2); }

.support-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  margin-top: clamp(1.5rem, 3vw, 2rem);
}
.support-strip__copy { max-width: 46ch; }
.support-strip__copy p { color: var(--text-2); font-size: 0.96rem; margin-top: var(--sp-2); }


/* 17  FOOTER -------------------------------------------------------------- */

.site-footer {
  position: relative;
  border-top: 1px solid var(--stroke-hair);
  background: rgba(3, 7, 10, 0.95);
  padding-block: clamp(2.5rem, 6vw, 4rem);
}

.footer__grid {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
}
@media (min-width: 780px) {
  .footer__grid { grid-template-columns: minmax(0, 1.2fr) repeat(2, minmax(0, 1fr)); }
}

.footer__about p {
  margin-top: var(--sp-4);
  font-size: 0.9rem;
  color: var(--text-3);
  max-width: 38ch;
}
.footer__publisher {
  margin-top: var(--sp-4);
  font-size: 0.88rem;
  color: var(--text-2);
}
.footer__publisher strong { color: var(--text); font-weight: 600; }

.footer__col h2 {
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 620;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: var(--sp-4);
}
.footer__col ul { list-style: none; padding: 0; margin: 0; }
.footer__col li + li { margin-top: 2px; }
.footer__col a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  color: var(--text-2);
  font-size: 0.93rem;
  text-decoration: none;
  transition: color 0.18s var(--ease);
}
.footer__col a:hover { color: var(--cyan); }

.footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--stroke-hair);
  font-size: 0.83rem;
  color: var(--text-3);
}
.footer__legal p { max-width: 62ch; }


/* 18  LEGAL PAGES --------------------------------------------------------- */
/* Readability outranks atmosphere here. No environmental texture sits behind
   running legal copy - only a dark header band above it. */

.legal-page { background: var(--bg-0); }

.legal-hero {
  position: relative;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  border-bottom: 1px solid var(--stroke-hair);
  overflow: hidden;
}
.legal-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(80% 120% at 22% 0%, rgba(11, 68, 82, 0.42), transparent 62%),
    linear-gradient(180deg, var(--bg-1), var(--bg-0));
}
.legal-hero > * { position: relative; z-index: 1; }
.legal-hero h1 { font-size: var(--step-4); }
.legal-hero .lede { margin-top: var(--sp-4); font-size: var(--step-0); }

.legal-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
  margin-top: var(--sp-5);
  font-size: 0.86rem;
  color: var(--text-3);
}
.legal-meta strong { color: var(--text-2); font-weight: 600; }

.legal-layout {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-block: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}
@media (min-width: 1000px) {
  .legal-layout { grid-template-columns: 250px minmax(0, 1fr); }
}

.legal-toc { font-size: 0.9rem; }
@media (min-width: 1000px) {
  .legal-toc {
    position: sticky;
    top: calc(var(--nav-h) + var(--sp-5));
    max-height: calc(100svh - var(--nav-h) - var(--sp-8));
    overflow-y: auto;
  }
}
.legal-toc h2 {
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 620;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: var(--sp-3);
}
.legal-toc ol { list-style: none; padding: 0; margin: 0; }
.legal-toc a {
  display: block;
  padding: 0.55rem 0.75rem;
  border-left: 2px solid var(--stroke-hair);
  color: var(--text-2);
  text-decoration: none;
  line-height: 1.35;
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.legal-toc a:hover {
  color: var(--text);
  border-left-color: rgba(32, 215, 255, 0.5);
  background: rgba(16, 30, 39, 0.4);
}

/* On mobile the TOC collapses so it never buries the document. */
.legal-toc__disclosure {
  border: 1px solid var(--stroke-hair);
  border-radius: var(--r-md);
  background: rgba(9, 19, 25, 0.7);
  padding: var(--sp-2) var(--sp-4);
}
.legal-toc__disclosure > summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
}
@media (min-width: 1000px) {
  .legal-toc__disclosure {
    border: 0;
    background: none;
    padding: 0;
  }
  .legal-toc__disclosure > summary { display: none; }
}

/* Article body: measured line length, generous leading, high contrast. */
.legal-body {
  max-width: var(--shell-text);
  font-size: 1.02rem;
  line-height: 1.72;
  color: var(--text-2);
}
.legal-body > section + section { margin-top: clamp(2rem, 4vw, 2.8rem); }
.legal-body h2 {
  font-size: var(--step-2);
  color: var(--text);
  margin-bottom: var(--sp-4);
  scroll-margin-top: calc(var(--nav-h) + var(--sp-5));
}
.legal-body h3 {
  font-size: var(--step-0);
  color: var(--text);
  margin: var(--sp-5) 0 var(--sp-3);
}
.legal-body p + p { margin-top: var(--sp-4); }
.legal-body ul, .legal-body ol { margin: var(--sp-4) 0; padding-left: 1.35rem; }
.legal-body li + li { margin-top: var(--sp-3); }
.legal-body li::marker { color: var(--stroke); }

.callout {
  margin: var(--sp-5) 0;
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--stroke-hair);
  border-left: 2px solid var(--cyan);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: rgba(11, 68, 82, 0.18);
  font-size: 0.96rem;
}
.callout p + p { margin-top: var(--sp-3); }

.legal-footnote {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--stroke-hair);
  font-size: 0.88rem;
  color: var(--text-3);
}

/* Conspicuous disclosures — UCC sec. 2-316(2).
   To exclude the implied warranty of merchantability the disclaimer must
   name it AND be conspicuous. Courts have accepted capitals, bold, larger
   type, contrasting colour, or a bordered block; plain running text is the
   paradigm case of what fails. This applies four of those at once so the
   test is met even if a court discounts any single signal.

   Deliberately NOT relying on text-transform: uppercase alone — that
   changes only the rendering, so a screen reader still receives sentence
   case, and a court reading the source could find the underlying text
   unchanged. The markup itself carries the emphasis. */
.conspicuous {
  margin: var(--sp-5) 0;
  padding: clamp(1rem, 2.2vw, 1.4rem) clamp(1rem, 2.4vw, 1.5rem);
  border: 2px solid var(--stroke);
  border-left-width: 4px;
  border-radius: var(--r-sm);
  background: rgba(16, 30, 39, 0.55);
  font-size: 1.04rem;
  font-weight: 600;
  line-height: 1.62;
  letter-spacing: 0.012em;
  color: var(--text);
}
.conspicuous > * + * { margin-top: var(--sp-4); }
.conspicuous p { color: var(--text); }

/* Uppercase lead-in label so the block is scannable as a legal notice. */
.conspicuous__label {
  display: block;
  margin-bottom: var(--sp-3);
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ember);
}

/* Unresolved drafting placeholders.
   Deliberately ugly. These must never reach production, so they are styled
   to be impossible to miss in review, and tools/verify-build.py fails the
   build while any remain. */
.placeholder {
  display: inline-block;
  padding: 0.1em 0.45em;
  border: 2px dashed #ff4c5e;
  border-radius: 4px;
  background: rgba(255, 76, 94, 0.16);
  color: #ffd9de;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 0.9em;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Print: the conspicuousness must survive on paper, where the dark
   background is dropped. Keep the border and the weight. */
@media print {
  .conspicuous {
    background: none;
    border: 2px solid #000;
    border-left-width: 4px;
    color: #000;
    font-weight: 700;
  }
  .conspicuous p { color: #000; }
  .conspicuous__label { color: #000; }
}


/* 19  MOTION & PRINT ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .panel--lift:hover, .archive-card:hover { transform: none; }
}

/* Honour reduced-transparency and forced-colors users. */
@media (prefers-reduced-transparency: reduce) {
  .panel, .masthead, .nav-panel, .btn--ghost, .appstore {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background-color: rgba(7, 16, 23, 0.97);
  }
  .env { display: none; }
}

@media (forced-colors: active) {
  .panel, .implement, .war-step, .faq__item, .archive-card, .phase {
    border: 1px solid CanvasText;
  }
  .env, .env__scrim { display: none; }
}

@media print {
  .env, .env__scrim, .masthead, .nav-panel, .gate__cue,
  .site-footer, .legal-toc { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .deep::before { display: none; }
  .legal-body, .legal-body h2, .legal-body h3 { color: #000; max-width: none; }
  .legal-hero::before { display: none; }
  .legal-hero h1 { color: #000; }
  a { color: #000; text-decoration: underline; }
  .legal-body a::after { content: " (" attr(href) ")"; font-size: 9pt; }
  .callout { border: 1px solid #666; background: none; }
}
