/* ============================================================================
   VARIANT F — "THE LINE"
   ----------------------------------------------------------------------------
   Concept: the whole business is one unbroken line of trust — someone you
   trust → you → Brandon's number. So the page IS a single plumb line of light
   with SEVEN stations on it. It drops from the top edge and the lion hangs on
   it like a pendant (§1). Through §2 the line breaks into dim dashes — the
   stretch where somebody was paying for a line and couldn't see it. At §3 it
   comes back solid and the station node FILLS: the line is handed back,
   owned — six assets converge onto one node. At §4 it runs as two parallel
   tracks and merges into one rail that stays lit, because that half never
   stops. Through §5 it turns teal (goes live) and threads the LuxOps phone.
   §6 returns it to silver, and it terminates heated to flame in the phone
   number (§7). The referral line becomes the phone line. One line, one call.

   All colour via tokens.css vars + color-mix. No hardcoded hexes.
   ========================================================================== */

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

html {
  overflow-x: clip;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  overflow-x: clip;
  background: var(--bg);
  color: var(--ink-body);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; }

::selection {
  background: var(--accent);
  color: var(--accent-ink);
}

/* --- Monument display voice — Archivo wdth 125 / 800, uppercase ---------- */
h1,
h2,
.cta__label,
.contact-tel {
  font-family: var(--font-display);
  font-weight: var(--disp-weight);
  font-variation-settings: var(--disp-width);
  text-transform: uppercase;
  letter-spacing: var(--track-hero);
  line-height: 0.98;
  color: var(--ink);
  margin: 0;
}

/* --- Skip link ------------------------------------------------------------ */
.skip {
  position: absolute;
  top: var(--s-3);
  left: var(--s-3);
  z-index: 100;
  padding: var(--s-2) var(--s-4);
  background: var(--bg-elev-2);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-sm);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  text-decoration: none;
  transform: translateY(-300%);
}
.skip:focus-visible { transform: none; }

/* ============================================================================
   HEADER — quiet chrome floating over the hero
   ========================================================================== */

.site-head {
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: clamp(1rem, 3vw, 1.75rem) var(--gutter);
}

/* The header CTA is a REAL tel: link, not an anchor to #contact.
   Measured across the bake-off: every hero h1 renders ~101px, which pushes the
   hero CTA below the fold at 1440x900 — so with a #contact anchor here, the
   number was not visible OR dialable anywhere on first paint. On a page whose
   only success metric is calls started, that's the whole game. The number rides
   along at all times; on narrow screens the label drops and the number stays,
   because the number is the thing that has to survive. */
.head-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink-muted);
  text-decoration: none;
  padding-block: var(--s-2);
  transition: color var(--dur-fast) var(--ease-out);
}
.head-cta:hover,
.head-cta:focus-visible { color: var(--ink); }

.head-cta__num { color: var(--accent); }
.head-cta:hover .head-cta__num { color: var(--ink); }

@media (max-width: 560px) {
  .head-cta__label { display: none; }
}

/* ============================================================================
   THE LINE — thread segments. Centered 2px plumb line; nodes at stations.
   ========================================================================== */

.thread {
  --thread-a: color-mix(in srgb, var(--metal) 38%, transparent);
  --thread-b: color-mix(in srgb, var(--metal) 38%, transparent);
  --thread-dash: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--metal) 34%, transparent) 0,
    color-mix(in srgb, var(--metal) 34%, transparent) 5px,
    transparent 5px,
    transparent 13px
  );
  position: relative;
  width: 2px;
  height: clamp(5rem, 13vh, 8.5rem);
  margin-inline: auto;
}

.thread__line {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  /* fallback first: if color-mix is unsupported the line is still there */
  background: var(--hairline-strong);
  background: linear-gradient(to bottom, var(--thread-a), var(--thread-b));
  transform-origin: top center;
}

/* Station node — a small silver diamond at the foot of each segment */
.thread::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 7px;
  height: 7px;
  transform: translate(-50%, 50%) rotate(45deg);
  background: var(--bg);
  border: 1px solid color-mix(in srgb, var(--metal) 70%, transparent);
}

/* t0 — top edge → lion. Fades in from nothing; the lion is its node. */
.thread--t0 {
  --thread-a: transparent;
  flex: 1 0 clamp(3.5rem, 9vh, 7rem);
  height: auto;
}
.thread--t0::after { content: none; }

/* --- §2 the dark stretch: silver dissolves into dim DASHES — a line the
       reader was paying for but couldn't follow. Node goes hollow-dim. ---- */
.thread--to-dark {
  --thread-b: color-mix(in srgb, var(--metal) 7%, transparent);
  height: clamp(6rem, 15vh, 9.5rem);
}
.thread--to-dark .thread__line::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--thread-dash);
  -webkit-mask-image: linear-gradient(to bottom, transparent 30%, #000 78%);
  mask-image: linear-gradient(to bottom, transparent 30%, #000 78%);
}
.thread--to-dark::after {
  border-color: color-mix(in srgb, var(--metal) 28%, transparent);
}

/* --- §3 the handover: dashes dissolve, the line comes back solid, and the
       station node FILLS — ownership, handed back. ------------------------ */
.thread--relight {
  --thread-a: color-mix(in srgb, var(--metal) 7%, transparent);
  --thread-b: color-mix(in srgb, var(--metal) 62%, transparent);
  height: clamp(6.5rem, 16vh, 10rem);
}
.thread--relight .thread__line::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--thread-dash);
  -webkit-mask-image: linear-gradient(to bottom, #000 18%, transparent 62%);
  mask-image: linear-gradient(to bottom, #000 18%, transparent 62%);
}
.thread--relight::after {
  width: 9px;
  height: 9px;
  background: var(--metal);
  border-color: var(--metal);
  box-shadow: 0 0 16px color-mix(in srgb, var(--metal) 45%, transparent);
}

/* §3 handover — full-strength silver line with the node FILLED. Replaces
   thread--relight now that §2 is a welcome rather than a dark stretch: there's
   no dimness above it to climb out of, so relight's dim --thread-a would have
   shown up as a seam. The filled node is the part that mattered. */
.thread--handover {
  height: clamp(6.5rem, 16vh, 10rem);
}
.thread--handover::after {
  width: 9px;
  height: 9px;
  background: var(--metal);
  border-color: var(--metal);
  box-shadow: 0 0 16px color-mix(in srgb, var(--metal) 45%, transparent);
}

/* silver → teal: the line goes live entering LuxOps */
.thread--to-live {
  --thread-b: color-mix(in srgb, var(--live) 60%, transparent);
}
.thread--to-live::after {
  border-color: color-mix(in srgb, var(--live) 75%, transparent);
}

/* fully live stub that plugs into the phone */
.thread--live {
  --thread-a: color-mix(in srgb, var(--live) 60%, transparent);
  --thread-b: color-mix(in srgb, var(--live) 60%, transparent);
}
.thread--stub { height: clamp(3rem, 7vh, 4.5rem); }
.thread--stub::after { content: none; }

/* teal → silver leaving the system */
.thread--from-live {
  --thread-a: color-mix(in srgb, var(--live) 60%, transparent);
}

/* the final run heats up and terminates in a flame node — the destination */
.thread--end {
  --thread-b: color-mix(in srgb, var(--accent) 75%, transparent);
  height: clamp(6rem, 15vh, 10rem);
}
.thread--end::after {
  width: 11px;
  height: 11px;
  border: 0;
  border-radius: var(--r-pill);
  transform: translate(-50%, 50%);
  background: var(--accent);
  box-shadow: var(--glow-accent);
}

/* Scroll-drawn state (JS arms these; without JS the line is simply there) */
.thread--armed .thread__line {
  transform: scaleY(0);
  transition: transform var(--dur-slow) var(--ease-out);
}
.thread--armed::after {
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out) 420ms;
}
.thread--drawn .thread__line { transform: scaleY(1); }
.thread--drawn::after { opacity: 1; }

/* ============================================================================
   SECTIONS — one idea per screen, everything hung on the centre axis
   ========================================================================== */

main > section {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-inline: var(--gutter);
  padding-bottom: var(--section-y);
}

main > section > h2 {
  font-size: var(--step-5);
  text-align: center;
  text-wrap: balance;
  margin-top: var(--s-8);
  max-width: var(--shell);
}

.prose {
  max-width: 52ch;
  margin-top: var(--s-12);
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

.prose p {
  margin: 0;
  font-size: var(--step-1);
  line-height: 1.65;
  color: var(--ink-body);
}

.hl {
  font-style: normal;
  color: var(--ink);
}

.prose strong,
.hero-referral strong {
  font-weight: 650;
  color: var(--ink);
}

/* Station lead — each new beat opens on one plain thesis line */
.prose .lead {
  font-size: var(--step-2);
  font-weight: 600;
  line-height: 1.4;
  color: var(--ink);
  text-wrap: balance;
}

.prose--center { text-align: center; }
.prose--merge { margin-top: var(--s-8); }

.talk-link {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
  transition: color var(--dur-fast) var(--ease-out);
}
.talk-link:hover { color: var(--accent); }

/* ============================================================================
   §1 HERO — pendant lion on the line, monument statement, one CTA
   ========================================================================== */

#hero {
  min-height: 100vh;
  min-height: 100svh;
  justify-content: flex-start;
  padding-bottom: var(--s-24);
}

.hero-mark { --mark-size: clamp(2.5rem, 1.4rem + 4.5vw, 4.75rem); }

.hero-note {
  margin: var(--s-6) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  text-align: center;
}

.hero-statement {
  margin-top: clamp(2.5rem, 7vh, 4.5rem);
  font-size: var(--step-6);
  text-align: center;
  text-wrap: balance;
  max-width: var(--shell);
}

.hero-statement__line { display: block; }

/* The statement's rule — the one gradient accent, echoing the lockup's rule */
.hero-statement::after {
  content: '';
  display: block;
  width: clamp(9rem, 34vw, 19rem);
  height: 2px;
  margin: var(--s-6) auto 0;
  background: var(--lux-gradient);
}

.hero-referral {
  margin: var(--s-8) 0 0;
  max-width: 44ch;
  font-size: var(--step-1);
  line-height: 1.6;
  color: var(--ink-body);
  text-align: center;
  text-wrap: balance;
}

.hero-cta {
  margin-top: clamp(2rem, 5vh, 3.25rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-6);
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  padding: 1.05em 1.5em;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: var(--r-sm);
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.cta:hover {
  transform: translateY(-2px);
  box-shadow: var(--glow-accent);
}
.cta:active { transform: none; }

.cta__label {
  color: var(--accent-ink);
  font-size: var(--step-0);
  letter-spacing: 0.03em;
  line-height: 1;
}

.cta__arrow { line-height: 1; }

.cta__num {
  font-family: var(--font-mono);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1;
}

.hero-email {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
  padding-bottom: 0.2em;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.hero-email:hover {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--metal) 60%, transparent);
}

/* Hero load sequence — CSS only, so it runs without JS */
@keyframes f-rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}
@keyframes f-draw {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}

.thread--t0 .thread__line { animation: f-draw 900ms var(--ease-out) both; }
.hero-mark       { animation: f-rise var(--dur-slow) var(--ease-out) 250ms both; }
.hero-note       { animation: f-rise var(--dur-slow) var(--ease-out) 400ms both; }
.hero-statement  { animation: f-rise var(--dur-slow) var(--ease-out) 550ms both; }
.hero-referral   { animation: f-rise var(--dur-slow) var(--ease-out) 700ms both; }
.hero-cta        { animation: f-rise var(--dur-slow) var(--ease-out) 850ms both; }

/* ============================================================================
   §4 HOW — TWO TRACKS that merge into one lit rail.

   The old wishbone split the line from a point and then rejoined it, which put
   the section's whole argument into two hairlines and left the two branches
   visibly unequal. Now: two equal-height cards, each running on its own silver
   rail, converging into a single ACCENT rail that carries the payload. The
   split is gone — the heading already says "two ways in", so drawing it twice
   was decoration. Only the merge is drawn, because only the merge is the point.
   ========================================================================== */

.tracks {
  width: min(58rem, 100%);
  margin-top: var(--s-8);
}

.tracks__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-6);
  align-items: stretch; /* equal heights: neither branch is the lesser option */
}

.track {
  position: relative;
  padding: var(--s-6) var(--s-6) var(--s-6) var(--s-8);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--metal) 3.5%, transparent);
}

/* The rail is a real element, not a border, so it can host the travelling
   highlight without a stacking-context fight with the card's own background. */
.track__rail {
  position: absolute;
  left: 0;
  top: var(--s-4);
  bottom: var(--s-4);
  width: 2px;
  overflow: hidden;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--metal) 20%, transparent);
}
.track__rail::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 38%;
  background: linear-gradient(
    to bottom,
    transparent,
    color-mix(in srgb, var(--metal) 90%, transparent),
    transparent
  );
  transform: translateY(-140%);
}
/* One pass down each rail as the card arrives — staggered so the eye reads
   left then right. Not a loop: the tracks are options, not live systems. */
.track[data-revealed] .track__rail::after {
  animation: track-run 1500ms var(--ease-out) both;
  animation-delay: calc(320ms + var(--t) * 260ms);
}
@keyframes track-run {
  from { transform: translateY(-140%); }
  to   { transform: translateY(300%); }
}

/* A real chip, not a muted eyebrow. This is the element that has to let someone
   pick their branch without reading either body, so it gets border, fill and
   full-strength ink — --ink-muted mono at --step--1 was invisible. */
.track__tag {
  display: inline-block;
  margin-bottom: var(--s-6);
  padding: 0.5em 0.9em;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1;
  text-transform: uppercase;
}

.track__lead {
  margin: 0 0 var(--s-3);
  font-family: var(--font-display);
  font-variation-settings: var(--disp-width);
  font-weight: 700;
  font-size: var(--step-2);
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}

.track p:not(.track__lead) {
  margin: 0;
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink-body);
}

/* The merge — the only wishbone left on the page. It terminates on a filled
   node at dead centre, and the payload hangs off that node. The first build put
   the payload's rail at the left edge while the wishbone converged to centre,
   which snapped the one line the whole page is built on. */
.tracks__merge {
  position: relative;
}
/* Narrower than the card pair on purpose. Spanning the full width made the
   x-scale ~3x the y-scale, and a curve with vertical end-tangents under that
   much horizontal stretch renders as a long flat dash with two tiny hooks. At
   half width the two axes scale within ~20% of each other, so the drawn shape
   is close to the authored one — and the tips still land under their own card. */
.tracks__merge svg {
  display: block;
  width: min(50%, 30rem);
  margin-inline: auto;
  height: clamp(4rem, 9vh, 6rem);
}
.tracks__merge svg path {
  fill: none;
  stroke: color-mix(in srgb, var(--metal) 38%, transparent);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}
.tracks__merge::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 9px;
  height: 9px;
  transform: translate(-50%, 50%) rotate(45deg);
  background: var(--accent);
  box-shadow: var(--glow-accent);
}

/* ---- the merged rail: where the payload lives ----------------------------
   Centred, because the merge point is centred and the section's station and
   h2 already are. Everything from the node down is one column. */
.railway {
  max-width: var(--measure);
  margin-inline: auto;
  text-align: center;
}

/* In flow rather than absolutely positioned: it IS the line continuing out of
   the node, so it should push the payload down, not float beside it. */
.railway__rail {
  display: block;
  width: 2px;
  height: clamp(3rem, 7vh, 4.5rem);
  margin: 0 auto var(--s-8);
  overflow: hidden;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 26%, transparent);
}
/* This one DOES loop — it stands for the measurement that keeps running. */
.railway__rail::after {
  content: '';
  display: block;
  width: 100%;
  height: 40%;
  background: linear-gradient(
    to bottom,
    transparent,
    var(--accent),
    transparent
  );
  transform: translateY(-140%);
}
.railway[data-revealed] .railway__rail::after {
  animation: track-run 3200ms var(--ease-in-out) 500ms infinite;
}

.railway__intro {
  margin: 0 auto var(--s-6);
  max-width: 46ch;
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink-muted);
  text-wrap: balance;
}

/* The section's actual point, finally sized like it. It was the eighth clause
   of a paragraph before. */
.railway__big {
  margin: 0 0 var(--s-6);
  font-family: var(--font-display);
  font-variation-settings: var(--disp-width);
  font-weight: var(--disp-weight);
  font-size: var(--step-5);
  line-height: 1;
  letter-spacing: var(--track-hero);
  color: var(--ink);
}
.railway__big::after {
  content: '';
  display: block;
  width: 5rem;
  height: 2px;
  margin: var(--s-6) auto 0;
  background: var(--lux-gradient);
}

.railway__body {
  margin: 0 auto;
  max-width: 52ch;
  font-size: var(--step-0);
  line-height: 1.7;
  color: var(--ink-body);
  text-wrap: pretty;
}

/* Scroll-drawn wishbones (JS arms these; without JS they're simply there) */
.draw-armed path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset var(--dur-slow) var(--ease-out);
}
.draw-done path { stroke-dashoffset: 0; }

/* ============================================================================
   §5 SYSTEM — the live station: a phone threaded onto the line.
   Everything inside is abstract, neutral, visibly generic. No numerals.
   ========================================================================== */

.prose--system { text-align: center; }

.phone-wrap { display: flex; justify-content: center; }

/* the live stub needs air above it so it reads as line, not border */
#system .thread--stub { margin-top: var(--s-8); }

.phone {
  width: min(19.5rem, 100%);
  padding: 0.6rem;
  background: linear-gradient(180deg, var(--bg-elev-2), var(--bg-elev));
  border: 1px solid var(--hairline-strong);
  border-radius: 2.4rem;
  box-shadow:
    0 40px 90px -40px color-mix(in srgb, var(--bg) 92%, transparent),
    0 0 70px -28px color-mix(in srgb, var(--live) 30%, transparent);
}

.phone__screen {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 1rem 0.95rem 0.75rem;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 1.85rem;
}

.ph-status {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding-inline: 0.2rem;
}

.ph-status__name {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
}

.ph-chip {
  margin-left: auto;
  padding: 0.18rem 0.55rem;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--live);
  background: color-mix(in srgb, var(--live) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--live) 32%, transparent);
  border-radius: var(--r-pill);
}

.ph-panel {
  padding: 0.7rem 0.75rem;
  background: var(--bg-elev);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
}

.ph-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* Rankings — a generic climbing area, no axes, no figures */
.ph-chart {
  position: relative;
  height: 5rem;
  margin-top: 0.6rem;
  background: repeating-linear-gradient(
    to bottom,
    var(--hairline) 0,
    var(--hairline) 1px,
    transparent 1px,
    transparent 1.2rem
  );
}
.ph-chart__area {
  position: absolute;
  inset: 0;
  clip-path: polygon(
    0 80%, 9% 72%, 18% 76%, 28% 58%, 38% 63%, 50% 42%,
    62% 48%, 74% 28%, 86% 33%, 100% 12%, 100% 100%, 0 100%
  );
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--live) 45%, transparent),
    color-mix(in srgb, var(--live) 4%, transparent)
  );
}
.ph-chart__dot {
  position: absolute;
  top: 12%;
  right: 0;
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--live);
  box-shadow: var(--glow-live);
  transform: translate(-1px, -50%);
}

.ph-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem;
}

/* Map pack — three lit in the grid */
.ph-dots {
  display: grid;
  grid-template-columns: repeat(3, 8px);
  gap: 6px;
  margin-top: 0.65rem;
}
.ph-dots i {
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--hairline-strong);
  background: color-mix(in srgb, var(--metal) 16%, transparent);
}
.ph-dots i.on { background: var(--live); }

/* Site health — a filled meter, no percentage shown */
.ph-meter {
  height: 6px;
  margin-top: 1rem;
  border-radius: var(--r-pill);
  background: var(--hairline);
  background: color-mix(in srgb, var(--metal) 13%, transparent);
  overflow: hidden;
}
.ph-meter i {
  display: block;
  height: 100%;
  width: 78%;
  border-radius: var(--r-pill);
  background: var(--live);
}

/* AI visibility — presence pips, some lit */
.ph-panel--row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}
.ph-pips { display: flex; gap: 0.5rem; }
.ph-pips i {
  width: 7px;
  height: 7px;
  transform: rotate(45deg);
  border: 1px solid color-mix(in srgb, var(--live) 55%, transparent);
}
.ph-pips i.on { background: var(--live); border-color: var(--live); }

/* Leads — deliberately redacted rows: the sanitization is the aesthetic */
.ph-lead {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
  padding: 0.5rem 0.55rem;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
}
.ph-lead--new {
  border-color: color-mix(in srgb, var(--live) 35%, transparent);
}
.ph-lead__dot {
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--metal) 12%, transparent);
}
.ph-lead__lines {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  flex: 1;
}
.ph-lead__lines i {
  display: block;
  height: 5px;
  border-radius: var(--r-pill);
  background: var(--hairline-strong);
  background: color-mix(in srgb, var(--metal) 15%, transparent);
}

.ph-home {
  width: 5.5rem;
  height: 4px;
  margin: 0.35rem auto 0;
  border-radius: var(--r-pill);
  background: var(--hairline-strong);
  background: color-mix(in srgb, var(--metal) 22%, transparent);
}

.phone-caption {
  margin: var(--s-8) 0 0;
  max-width: 46ch;
  font-size: var(--step-0);
  color: var(--ink-body);
  text-align: center;
  text-wrap: balance;
}

/* ============================================================================
   §7 CONTACT — the line ends here. The number is the destination.
   ========================================================================== */

#contact { padding-bottom: var(--s-24); }

#contact h2 {
  font-size: var(--step-2);
  color: var(--ink-muted);
  letter-spacing: var(--track-caps);
}

.contact-tel {
  margin-top: var(--s-8);
  font-size: var(--step-5);
  text-align: center;
  /* The closing CTA. As a bare inline <a> its hit box was the text line only —
     34px at 390px, under the 44px touch floor, on the last thing a visitor
     taps. inline-block + padding grows the target without touching the type. */
  display: inline-block;
  min-height: 44px;
  padding-block: 0.08em;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--metal) 35%, transparent);
  text-decoration-thickness: 3px;
  text-underline-offset: 0.16em;
  transition: color var(--dur-fast) var(--ease-out),
              text-decoration-color var(--dur-fast) var(--ease-out);
  overflow-wrap: anywhere;
  max-width: 100%;
}
.contact-tel:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

.contact-email {
  margin-top: var(--s-6);
  font-family: var(--font-mono);
  font-size: var(--step-1);
  color: var(--ink-body);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
  padding-bottom: 0.15em;
  overflow-wrap: anywhere;
  max-width: 100%;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.contact-email:hover {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--metal) 60%, transparent);
}

.contact-note {
  margin: var(--s-12) 0 0;
  max-width: 40ch;
  font-size: var(--step-0);
  color: var(--ink-body);
  text-align: center;
  text-wrap: balance;
}

/* ============================================================================
   FOOTER — the seal signs the page off
   ========================================================================== */

.site-foot {
  display: grid;
  place-items: center;
  padding: var(--s-16) var(--gutter);
  border-top: 1px solid var(--hairline);
}

/* ============================================================================
   Responsive
   ========================================================================== */

/* The tracks stack. The merge wishbone can't span two stacked cards, so it
   becomes a single plumb stub — the same grammar as the rest of the page —
   and the cards keep their rails, which is what carries the "two tracks" read
   once they're one above the other. */
@media (max-width: 767px) {
  .tracks__pair { grid-template-columns: 1fr; }
  .tracks__merge { height: 3.75rem; }
  .tracks__merge svg { display: none; }
  .tracks__merge::before {
    content: '';
    position: absolute;
    top: 0.4rem;
    bottom: 0.5rem;
    left: 50%;
    width: 2px;
    transform: translateX(-50%);
    background: color-mix(in srgb, var(--metal) 38%, transparent);
  }
}

/* NOTE: the .vault stacked layout is NOT here. Its base rules live at the foot
   of this file, so a media query up here loses every specificity tie to them.
   It sits immediately after those rules instead — see "§3 THE HANDOVER". */

@media (max-width: 640px) {
  .cta {
    flex-direction: column;
    gap: 0.55em;
    padding: 1em 1.6em;
    text-align: center;
  }
  .contact-tel { font-size: var(--step-4); }
}

/* Below ~480px the header CTA collides with the lockup. It used to be hidden
   here — correct when it was just a #contact anchor, WRONG now that it carries
   the phone number: mobile is precisely where a tappable number matters most,
   and the hero CTA is a full screen away. So the number stays and the header
   WORDMARK goes instead — the hero restates the name immediately below, so
   nothing is actually lost. */
/* Every contact link is a touch target, not just the phone. The email links
   measured 26px and 37px — both under the 44px floor on the device where
   they're actually tapped. */
@media (max-width: 767px) {
  .hero-email,
  .contact-email {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

@media (max-width: 479px) {
  .site-head .lux-mark__text { display: none; }
  /* 44px min touch target (Apple HIG). Measured at 39px before — under the
     floor, on the page's primary conversion element, on the device where it
     gets tapped. */
  .head-cta {
    letter-spacing: 0.06em;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
}

/* ============================================================================
   Reduced motion — silence everything this variant animates.
   tokens.css zeroes durations; these kill delays, transforms and armed states
   so nothing pops, staggers, or hides.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .thread--t0 .thread__line,
  .hero-mark,
  .hero-note,
  .hero-statement,
  .hero-referral,
  .hero-cta {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .thread__line {
    transform: none !important;
    transition: none !important;
  }
  .thread::after { opacity: 1 !important; transition: none !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .draw-armed path {
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
    transition: none !important;
  }
  .cta:hover { transform: none; }
}

/* ============================================================================
   MERGE (G) — B Command's chapter numbers + ownership cards, grafted onto F's line.
   Brandon 2026-07-31: "the look of fable… with the sections of command… we are almost
   telling a story here." So the numbers are CHAPTER MARKS ON THE THREAD, not module
   IDs floating beside it — F's whole argument is that the line never breaks, and a
   stack of detached boxes would make the line decorative. The word "Module" is dropped:
   it's B's instrument voice, wrong register for a story.
   ========================================================================== */

.station {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: var(--s-3);
  margin: calc(var(--s-3) * -1) 0 var(--s-5);
  /* pulls up so the number sits ON the node F draws at the thread's foot */
}

.station__num {
  font-family: var(--font-mono);
  font-size: var(--step-1);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--accent);
  letter-spacing: 0.02em;
}

.station__name {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* The dark stretch (§2) and the relight (§3) are the story's low and turn. The
   number dims with the line and comes back with it, so the chapter marks are part
   of the arc rather than a constant overlay on top of it. */
.thread--to-dark + .station .station__num {
  color: color-mix(in srgb, var(--accent) 42%, transparent);
}
.thread--live + .station .station__num,
.thread--to-live + .station .station__num {
  color: var(--accent);
}
/* ---- §3 THE HANDOVER — cards flow into the vault -------------------------
   Brandon, on the first attempt: "now it's just white text to orange with
   animated lines. I was hoping to have the orange cards flowing into a YOURS
   box." So the cards ARE the subject here, and the colour carries the argument:
   the six inputs are accent-OUTLINED, the destination is accent-FILLED. What
   moves left to right is ownership, and it gets heavier when it lands.

   Alignment holds without any SVG: .vault__assets and .vault__wires are both
   grids of six equal rows sharing one gap value, so wire i is always centred on
   card i no matter how the labels wrap. Nothing to keep in sync by hand.
   ------------------------------------------------------------------------ */
.vault {
  /* a diagram earns more width than the text measure; .prose is a flex column,
     so this needs an explicit width, and symmetric negative margins to bleed
     past the measure while staying centred. Zeroed in the stacked layout. */
  --vault-bleed: clamp(0rem, 4vw, 3.5rem);
  --vault-gap: var(--s-3);
  align-self: stretch;
  width: calc(100% + 2 * var(--vault-bleed));
  margin: var(--s-8) calc(-1 * var(--vault-bleed)) var(--s-8);
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(2.5rem, 7vw, 4.5rem) minmax(0, 0.62fr);
  align-items: stretch;
}

/* ---- the six inputs ---- */
.vault__assets {
  display: grid;
  grid-template-rows: repeat(6, 1fr);
  gap: var(--vault-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.asset {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  /* Black cards, orange only on the leading edge and the arrow. Brandon: the
     tinted fill was "too much orange" — and it also flattened the contrast
     against the destination, which is the one thing here that earns the fill. */
  border: 1px solid var(--hairline-strong);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--bg-elev);
  color: var(--ink);
  font-size: var(--step-0);
  line-height: 1.25;
}
/* Points at the box. Short labels ("Domain") left a lot of dead card without
   it, and the direction of travel is the whole point of the diagram. */
.asset::after {
  content: '→';
  flex: none;
  color: var(--accent);
  line-height: 1;
}

/* Flown in from the left, staggered. `both` holds the from-state until the
   delay elapses; under reduced motion tokens.css zeroes the duration so this
   resolves straight to the settled state, which is the default styling above. */
.vault[data-revealed] .asset {
  animation: asset-in 620ms var(--ease-out) both;
  animation-delay: calc(160ms + var(--i) * 95ms);
}
@keyframes asset-in {
  from { opacity: 0; transform: translateX(-28px); }
  to   { opacity: 1; transform: none; }
}

/* ---- the wires ---- */
.vault__wires {
  display: grid;
  grid-template-rows: repeat(6, 1fr);
  gap: var(--vault-gap);
}

.wire {
  position: relative;
  align-self: center;
  width: 100%;
  height: 2px;
  overflow: hidden;
  background: color-mix(in srgb, var(--accent) 30%, transparent);
}
/* the charge: a short bright segment running card → box, forever, because the
   ownership doesn't expire. Staggered so it reads as six separate handoffs. */
.wire::after {
  content: '';
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 46%;
  background: linear-gradient(to right, transparent, var(--accent), transparent);
  transform: translateX(-120%);
}
.vault[data-revealed] .wire::after {
  animation: wire-run 2400ms linear infinite;
  animation-delay: calc(620ms + var(--i) * 120ms);
}
@keyframes wire-run {
  from { transform: translateX(-120%); }
  to   { transform: translateX(340%); }
}

/* ---- the destination ---- */
.vault__box {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-6) var(--s-4);
  border-radius: var(--r-md);
  /* Solid flame is the DEFAULT state, and the arrival animation only fades the
     whole box up from dim. Crossfading a transparent box to a filled one would
     put accent text on part-accent ground for ~300ms — a real contrast dip.
     This way accent-ink sits on flame the entire time: 8.1:1, never less. */
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: var(--glow-accent);
  text-align: center;
}
.vault[data-revealed] .vault__box {
  animation: vault-land 900ms var(--ease-out) both;
  animation-delay: 700ms;
}
@keyframes vault-land {
  0%   { opacity: 0.18; transform: scale(0.96); }
  70%  { opacity: 1;    transform: scale(1.02); }
  100% { opacity: 1;    transform: none; }
}

.vault__word {
  font-family: var(--font-display);
  font-variation-settings: var(--disp-width);
  font-weight: var(--disp-weight);
  font-size: var(--step-3);
  line-height: 1;
  letter-spacing: var(--track-hero);
  text-transform: uppercase;
  color: var(--accent-ink);
}

.vault__sub {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  line-height: 1.2;
  /* on flame, not on the page background — mixing toward the ink keeps it a
     deliberate step down instead of an opacity fade that drops below AA */
  color: color-mix(in srgb, var(--accent-ink) 78%, var(--accent));
}

/* Stacked layout. The wires can't run horizontally once the box is below the
   cards, so they turn into one plumb feed into the top of the box — the same
   grammar as the page's own thread.
   ⚠️ This block must stay directly under the base rules above: the responsive
   section higher up the file would lose the specificity tie to them. */
@media (max-width: 719px) {
  .vault {
    --vault-bleed: 0rem;
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
  }

  .vault__wires {
    grid-template-rows: none;
    justify-items: center;
    height: 3.25rem;
  }
  /* one feed line, not six stacked hairlines */
  .wire { display: none; }
  .wire:first-child {
    display: block;
    align-self: stretch;
    width: 2px;
    height: 100%;
  }
  .wire:first-child::after {
    inset-block: auto;
    inset-inline: 0;
    top: 0;
    width: 100%;
    height: 46%;
    background: linear-gradient(to bottom, transparent, var(--accent), transparent);
    transform: translateY(-120%);
  }
  .vault[data-revealed] .wire:first-child::after {
    animation: wire-drop 2400ms linear infinite;
    animation-delay: 620ms;
  }

  /* the flow is downward now, so the arrows have to be too */
  .asset::after { transform: rotate(90deg); }

  .vault__box { padding: var(--s-6); }
}
@keyframes wire-drop {
  from { transform: translateY(-120%); }
  to   { transform: translateY(340%); }
}

@media (prefers-reduced-motion: reduce) {
  .station { transition: none; }
  /* No stalled travelling marks anywhere — hide them, don't freeze them. */
  .wire::after,
  .track__rail::after,
  .railway__rail::after { display: none; }
  .asset,
  .vault__box { animation: none !important; opacity: 1 !important; transform: none !important; }
}
