/* site.css: Phase 3 shared design system, loaded by every page before its
   own page.css. Sections: 0 tokens + reset; 1 type scale; 2 nav (fixed
   pill); 3 footer; 4 primitives (skip link, eyebrow, buttons, ghost
   control, rule, reveal-line, count-up, parallax planes, sticky card
   stack); 5 test guard.
   Extracted from the Phase 2 homepage (index.html inline style + home.css)
   so every inner page can load one system instead of re-declaring it. */

/* --------------------------------------------------- 0. tokens + reset */
:root {
  --navy: #0a0e1a;
  --lime: #39FF14;
  --lime-read: #b8e62e;
  --cyan: #00e3e4;
  --surface: #11162a;
  --surface-elev: #161c33;
  --border: #1f2742;
  --text: #ecf0fa;
  --text-dim: #7a85a8;
  --text-faint: #7c859b;
  --ink: #0a0e1a;
  caret-color: var(--lime);
  accent-color: var(--lime);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--navy); }
body {
  position: relative;
  background: var(--navy);
  color: var(--text);
  font-family: Inter, -apple-system, 'Helvetica Neue', sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
svg { max-width: 100%; }
::selection { background: var(--lime); color: var(--navy); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
@supports (scrollbar-color: auto) {
  html { scrollbar-color: color-mix(in oklab, var(--text) 26%, transparent) transparent; scrollbar-width: thin; }
}
a { color: var(--cyan); text-decoration: none; }
a:hover { text-decoration: underline; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.wrap { width: min(1280px, 92%); margin: 0 auto; }

/* --------------------------------------------------------- 1. type scale
   Inter 400-800 for everything read, H1 included; JetBrains Mono for
   numbers/ticks/codes lives on the components that use it (eyebrow, count,
   footer copyright below). A page's own H1/H2 layout (max-width, margin,
   forced breaks) stays with the page -- this is base typography only. */
h1 { font-family: Inter, sans-serif; font-weight: 800; font-size: clamp(2.75rem, 4.75vw, 4.25rem); line-height: 1.04; letter-spacing: -1px; color: var(--text); text-wrap: balance; }
h2 { font-family: Inter, sans-serif; font-weight: 600; font-size: clamp(1.6rem, 2.3vw, 2rem); line-height: 1.2; letter-spacing: -0.015em; color: var(--text); max-width: 30ch; }

/* --------------------------------------------------- 2. nav (fixed pill)
   QuietNav: one slim bar, hairline, text links only, the four-dot mark.
   Blur + hairline after 40px, hide on scroll-down, return on scroll-up
   (site.js). Under 600px a single "Menu" button opens the links as a
   vertical list. aria-current="page" marks the page you're on. */
.navbar {
  width: min(1280px, 92%); margin: 0 auto;
  height: 64px; padding: 0 24px;
  display: flex; align-items: center; justify-content: space-between;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px;
  position: relative; z-index: 5;
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); }
.brand:hover { text-decoration: none; }
.mark { display: grid; grid-template-columns: repeat(2, 5px); gap: 3px; width: 13px; }
.mark i { width: 5px; height: 5px; border-radius: 50%; background: var(--lime); }
.mark i:nth-child(4) { opacity: 0.35; }
.word { font: 600 0.78rem Orbitron, sans-serif; letter-spacing: 0.1em; text-transform: uppercase; }
.nav-right { display: flex; align-items: center; gap: 32px; }
.nav-links { display: flex; gap: 32px; list-style: none; }
.nav-links a { color: var(--text-dim); font-size: 14px; font-weight: 500; }
.nav-links a:hover { color: var(--text); text-decoration: none; }
.nav-links a[aria-current="page"] { color: var(--text); }

.navbar {
  position: fixed;
  top: 20px; left: 0; right: 0; margin-left: auto; margin-right: auto;
  /* Easing curve hardcoded (not a CSS variable) so it can't silently fall
     back to a different curve if a variable definition goes missing. */
  transition: transform .3s cubic-bezier(0.23, 1, 0.32, 1), background-color .25s ease, border-color .25s ease;
  will-change: transform;
}
.navbar.is-scrolled {
  background: rgba(17, 22, 42, 0.82);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-color: var(--border);
}
.navbar.is-hidden { transform: translateY(-130%); }
@media (prefers-reduced-motion: reduce) { .navbar { transition: background-color .25s ease, border-color .25s ease; } }

/* The nav is fixed (out of flow), so body's padding-top supplies the
   clearance an in-flow nav would otherwise give: nav top offset (20px) +
   nav height (64px desktop / 56px <=860px) + a small gap. */
body { padding-top: 104px; }
@media (max-width: 860px) { body { padding-top: 92px; } }

.nav-menu-btn {
  display: none;
  background: transparent; border: 1px solid var(--border); border-radius: 8px;
  color: var(--text); font: 600 13px/1 Inter, sans-serif;
  padding: 9px 14px; cursor: pointer;
}
.nav-menu-btn:hover, .nav-menu-btn:focus-visible { border-color: var(--cyan); color: var(--cyan); outline: none; }

@media (max-width: 860px) {
  .wrap, .navbar { width: calc(100% - 40px); }
  .navbar { height: 56px; padding: 0 16px; }
  .nav-right { gap: 18px; }
  .nav-links { gap: 16px; }
  .nav-links a { font-size: 13px; }
  .word { font-size: 0.7rem; }
}
@media (max-width: 600px) {
  .nav-links { display: none; }
  .nav-menu-btn { display: inline-block; }
  /* Anchored to .navbar (already position: fixed everywhere), not
     .nav-right: .nav-right shrinks to the Menu button's own width once
     .nav-links is display: none, so left:0/right:0 against it squeezed
     the open panel down to the button's ~66px and wrapped every link
     onto two or three lines. .navbar spans the full pill at every
     width, so the panel now opens edge-to-edge with it. */
  .nav-links {
    position: absolute; top: calc(100% + 8px); left: 0; right: 0;
    flex-direction: column; gap: 2px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    padding: 16px; z-index: 60;
  }
  .nav-links.is-open { display: flex; }
  .nav-links a { font-size: 16px; padding: 12px 8px; display: block; }   /* block, or the 12px padding paints and takes taps without laying out, and each row's hit box overlaps the next */
}

/* -------------------------------------------------------------- 3. footer */
.rule { border-top: 1px solid var(--border); }
footer { padding: 28px 0 40px; display: flex; flex-direction: column; gap: 18px; }
.foot-links { display: flex; flex-wrap: wrap; gap: 8px 22px; list-style: none; }
.foot-links a { color: var(--text-dim); font-size: 13px; font-weight: 500; }
.foot-links a:hover { color: var(--text); text-decoration: none; }
/* Scoped to footer: unscoped `.copy` collided with a page's own hero
   container of the same class (thank-you.html's `<div class="copy">`),
   pulling its two paragraphs of running prose into this mono footer
   typeface. Every footer copyright line is a descendant of <footer>, so
   this reaches exactly the same elements as before and nothing else. */
footer .copy { color: var(--text-faint); font: 500 0.7rem 'JetBrains Mono', monospace; letter-spacing: 0.04em; }

/* ------------------------------------------ 3b. the footer scene (the bookend)
   The page ends where it began: the homepage hero's three cut-out ridges
   return under every page's close, at night, and the footer sits on the
   dark ground. The sky is a linear gradient (no second radial: the one-glow
   rule holds), brightest at the horizon; the far ridge silhouettes against
   it, the mid darker, the near rocks darkest, dissolving into the footer
   navy through the scene's own floor fade. Desktop geometry (scene 540px,
   top = 0): far crest ~141, mid ~231, near median ~315 (every page, the
   homepage's hero rules reset below); the footer overlaps the last 150px.
   The planes carry
   data-rate for site.js section 2b (they rise into place as the page end
   approaches; the near is fixed); reduced motion leaves them at rest. */
/* One visible distance from the close's last ink to the scene, on every
   page: the close's own bottom padding goes, the whole gap lives on the
   band (96px desktop, 64px phone, the site's rhythm). */
main:has(+ .foot-scene) > :last-child { padding-bottom: 0 !important; margin-bottom: 0 !important; }
main.legaldoc:has(+ .foot-scene) { padding-bottom: 0; }   /* the legal pages: main itself carries the column's padding */
.foot-scene {
  position: relative; overflow: hidden; height: 540px; margin-top: 96px;
  /* The sky is bright from scene-y ~65 down, so every point of the far
     crest (it runs 49 to 230 across the width, higher on the right) sits
     under lit sky and silhouettes, as in the hero; below the crest the
     land covers the sky. The horizon colour leans a few degrees toward the
     hero's teal so the close echoes the front door without a second glow. */
  background: linear-gradient(180deg, #0a0e1a 0%, #111a36 6%, #233a5e 12%, #233a5e 100%);
}
/* The homepage's hero rules (home.css) style bare .plane-* selectors: a
   navy body in the near plane's padding, its own floor fade, a load
   animation. None of that belongs to the footer scene, on any page, so it
   is reset here at higher specificity. */
.foot-scene .plane-far, .foot-scene .plane-mid, .foot-scene .plane-near {
  height: auto; padding: 0 !important; background: none !important; animation: none !important;
}
.foot-scene .plane-near::after { content: none; }
.foot-scene img { display: block; width: 100%; height: auto; }
/* Offsets counter the plates' growth with the viewport so the crests hold
   at fixed heights in the band at every desktop width (far ~399 above the
   band's bottom, mid ~309, near ~225). */
.foot-scene .plane-far  { z-index: 0; bottom: calc(399px - 24.4vw); }
.foot-scene .plane-mid  { z-index: 1; bottom: calc(309px - 20.96vw); left: -5%; right: auto; width: 110%; }
.foot-scene .plane-near { z-index: 2; bottom: calc(225px - 20.28vw); left: -3.6%; right: auto; width: 120%; }
/* Two fades. The first is the floor: the whole width dissolves into the
   page navy over the last 70px so the plate's cut never shows. The second
   is the footer's ground: the left part, where the links sit, goes to
   solid navy over the last 300px (solid from 45% of that height, above
   the link row), and the right stays rock, so the footer stands on the
   ground with the near rocks beside it (the one occlusion the hero taught
   us). The solid edge is the larger of 58% and 780px: the link row ends
   near x 690 at every width from 861px up, so no glyph is ever over rock. */
.foot-scene::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 300px; z-index: 3;
  background: linear-gradient(to bottom, transparent, #0a0e1a 45%, #0a0e1a);
  -webkit-mask-image: linear-gradient(to right, #000 max(58%, 780px), transparent max(80%, 980px));
          mask-image: linear-gradient(to right, #000 max(58%, 780px), transparent max(80%, 980px));
  pointer-events: none;
}
.foot-scene::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 70px; z-index: 3;
  background: linear-gradient(to bottom, transparent, #0a0e1a); pointer-events: none;
}
/* The footer overlaps the band's ground: no hairline, no top padding, the
   links on the navy the left fade made. */
.foot-wrap.rule { border-top: 0; }
.foot-wrap { position: relative; z-index: 4; margin-top: -150px; }
.foot-wrap footer { padding-top: 0; }
@media (max-width: 860px) {
  /* Phone (band 320px): the links wrap the full width, so the footer sits
     under the band and the whole width fades; far crest ~58, mid ~120,
     near median ~190, so the band is mostly picture. */
  main:has(+ .foot-scene) > :last-child { padding-bottom: 0 !important; }
  .foot-scene { height: 320px; margin-top: 64px;
    background: linear-gradient(180deg, #0a0e1a 0%, #111a36 4%, #233a5e 9%, #233a5e 100%); }
  .foot-scene .plane-far  { width: 130%; left: -15%; right: auto; bottom: 136px; }
  .foot-scene .plane-mid  { width: 145%; left: -22%; bottom: 92px; }
  .foot-scene .plane-near { width: 170%; left: -7.4%; bottom: 18px; }
  .foot-scene::before { display: none; }
  .foot-scene::after { height: 90px; }
  .foot-wrap { margin-top: 0; }
  .foot-wrap footer { padding-top: 12px; }
}

/* ---------------------------------------------------------- 4. primitives */

/* Skip-to-content link, owned centrally so no page has to remember it
   (several already carried their own copy of this before it moved here).
   Hidden by the standard 1px-clip technique -- absolute, 1px box, clipped,
   no overflow -- so it takes no layout space and is never paint-visible
   until it is the focused element; then it becomes a fixed block pinned
   top left, above the nav (.navbar is z-index 5) and above the open mobile
   menu (z-index 60). Covers both class names in use across pages, `.skip`
   and `.skip-link`, with one rule set. Cyan-on-ink matches the site's own
   focus-visible colour (see `a:focus-visible` above). */
.skip, .skip-link {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.skip:focus-visible, .skip-link:focus-visible {
  position: fixed; top: 12px; left: 12px; z-index: 300;
  width: auto; height: auto; margin: 0; overflow: visible;
  clip: auto; white-space: normal;
  background: var(--cyan); color: var(--ink);
  padding: 10px 16px; border-radius: 8px;
  font: 600 14px Inter, sans-serif;
}

/* One eyebrow style for the whole site: Orbitron, 12px, 0.18em, muted, one
   cyan dot. Selector is the class doubled (specificity 0,2,0, matching the
   exact same elements as a single `.eyebrow`) so a page's own descendant
   rule, e.g. `.legaldoc p` (0,1,1), can never outrank it by specificity --
   the bug this fixes did not depend on source order, so a tie-breaking
   rewrite would not have been reliable. */
.eyebrow.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font: 600 12px Orbitron, sans-serif;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--text-dim); margin-bottom: 20px;
}
.eyebrow::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--cyan); flex: none; }

.btn-lime {
  display: inline-block; text-align: center;
  background: var(--lime); color: var(--ink);
  font-family: Inter, sans-serif; font-size: 15px; font-weight: 600;
  line-height: 1.4; padding: 14px 28px; border-radius: 8px;
  text-decoration: none; white-space: nowrap;
}
.btn-lime:hover { text-decoration: none; opacity: 0.9; }
/* One filled lime control per view (brand law): a repeat of a lime CTA
   lower on the same page goes ghost -- cyan outline, transparent fill,
   same label, same link. */
.btn-outline {
  display: inline-block; text-align: center;
  background: transparent; color: var(--cyan);
  font-family: Inter, sans-serif; font-size: 15px; font-weight: 600;
  line-height: 1.4; padding: 13px 27px; border: 1px solid var(--cyan); border-radius: 8px;
  text-decoration: none; white-space: nowrap;
}
.btn-outline:hover { text-decoration: none; background: var(--cyan); color: var(--ink); }
/* Must stay after the base .btn-lime rule above: same specificity, so an
   earlier position (e.g. inside the nav's own @media 600 block) would lose
   the cascade to the later, unscoped base rule despite the media match. */
@media (max-width: 600px) {
  .btn-lime { font-size: 14px; font-weight: 700; line-height: 40px; padding: 0 18px; }
}

/* The ghost control: quieter than .btn-outline, for a secondary in-flow
   toggle or submit (e.g. "reveal this form", "send it"). Named .ghost, not
   .btn-ghost: gc-events.js's CTA tracker matches class names on \bbtn\b,
   which a hyphenated "btn-" prefix still satisfies, and a ghost control is
   not always a CTA. A page's own button keeps its layout (align-self,
   margin) and any :disabled state. */
.ghost {
  cursor: pointer; background: transparent; color: var(--cyan);
  border: 1px solid var(--cyan); border-radius: 8px; padding: 9px 16px;
  font: 600 13px/1.3 Inter, sans-serif; transition: background .2s, color .2s;
}
.ghost:hover:not(:disabled), .ghost:focus-visible:not(:disabled) { background: var(--cyan); color: var(--ink); outline: none; }

/* Line reveal (transition, not keyframes): opacity .25->1, 8px translateY,
   IntersectionObserver threshold .6, 60ms stagger that resets per group
   (nearest section/article/header/footer or [data-reveal-group]
   ancestor, not the whole page), capped at 300ms per group (site.js). */
.reveal-line {
  opacity: .25; transform: translateY(8px);
  transition: opacity .5s ease, transform .5s ease;
}
.reveal-line.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal-line { opacity: 1; transform: none; transition: none; }
}

/* Count-up target: a number that counts up once on scroll (site.js drives
   the animation; this only fixes digit width so it doesn't jitter). */
.count { font-variant-numeric: tabular-nums; }

/* Hero parallax planes: a .planes wrapper (position, clip) holding up to
   three depth layers. Rates 0.10 / 0.25 / 0.60 of scrollY, clamped at
   900px (site.js); a page's own plane supplies its shape, height and
   z-index via its own selector on top of this. */
.planes { position: relative; overflow: hidden; }
.plane-far, .plane-mid, .plane-near {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: auto; max-width: none;
  pointer-events: none; will-change: transform;
}
/* Floor fade: the near plane (fastest rate, 0.60 of scrollY) can end up
   sitting mid-photo instead of at the hero's own bottom edge once it's
   scrolled past its resting position, and its own edge then shows as a
   dead-straight clip line with no fade to hide it. This overlay fades the
   last 240px of every .planes hero to the page ground so that line is
   never bare, at any scroll position. A linear gradient to the ground,
   not a radial one -- it must not read as a second glow. Every page's
   planes sit at z-index 0/1 and its copy (.hero-inner) at z-index 2, so
   z-index 1 here (painted after those siblings) clears every plane and
   still sits under the copy. */
.planes::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0; height: 240px;
  background: linear-gradient(to bottom, transparent, #0a0e1a);
  pointer-events: none;
  z-index: 1;
}

/* Sticky sibling card stack (Fora's move, zero JS): cards are flex
   siblings, each 68px lower and one z-index higher than the last, so each
   slides up over the one before it. A page sets --i (0, 1, 2 ...) per
   card. Flat below 600px. */
.stack { display: flex; flex-direction: column; gap: 24px; }
.stack > .card { position: sticky; top: calc(96px + 68px * var(--i, 0)); z-index: calc(var(--i, 0) + 1); overflow: hidden; }
@media (max-width: 600px) { .stack > .card { position: static; } }

/* --------------------------------------------------------- 5. test guard
   Headless capture guard: desktop-class Chrome cannot go narrower than
   500px. Real phones report hover: none. */
@media (max-width: 600px) and (hover: hover) and (pointer: fine) {
  html { max-width: 390px; }
}
