/* PANTAU landing page.
   Loaded after public.css, which owns the tokens and the shared chrome.
   The concept, the arc and the motion budget are documented in DIRECTION.md.
   Everything here belongs to the landing page and to no other template. */

.quiet-link {
  display: inline-flex; align-items: center;
  min-height: 44px;
  font: 600 var(--step-0)/1 var(--text);
  color: var(--teal-ink);
  border-bottom: 1px solid var(--teal);
  padding-bottom: 1px;
  transition: border-bottom-width 120ms var(--ease), color 120ms var(--ease);
}
.quiet-link:hover { border-bottom-width: 2px; color: var(--ink); }

/* ------------------------------------------------------------------ 1. Hero
   Three planes over one dark ground: the archipelago, a live field of signal
   drawn onto it from the artwork's own pixels, and the type. The page opens
   inside the instrument and stays there for three screens. */

/* The masthead and nav sit inside the hero's ground, not on a cream band above
   it: the seam that band created was the first thing the eye landed on. */
body { background: var(--ink); }
.research-banner { position: relative; z-index: 2; background: var(--ink-deep); }
.landing-nav { position: relative; z-index: 3; background: var(--ink); color: var(--paper); }
.landing-nav .brand small { color: #8FA8B8; }
.landing-nav .navlinks a { color: #C3D3DC; }
.landing-nav .navlinks a:hover { color: var(--mint); border-bottom-color: var(--mint); }
.landing-nav .text-link { color: var(--paper); }
.landing-nav .text-link:hover { color: var(--mint); }

.hero {
  position: relative;
  isolation: isolate;
  background: var(--ink);
  color: var(--paper);
  min-height: clamp(560px, calc(100dvh - 150px), 880px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(40px, 5vw, 76px) 0 0;
}

.hero-world { position: absolute; inset: -150px 0 0; z-index: -1; overflow: hidden; }
.hero-map {
  position: absolute; inset: 0;
  background: url("../img/login-background.d451488c55c2.webp") right center / cover no-repeat;
}
.hero-field { position: absolute; inset: 0; display: block; }
/* A directional scrim, not a blanket: it is dense where the headline sits and
   clears entirely over the field. */
.hero-scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(97deg, var(--ink) 0 16%, rgba(11, 31, 51, .93) 34%, rgba(11, 31, 51, .58) 62%, rgba(11, 31, 51, .12) 100%),
    linear-gradient(180deg, rgba(8, 25, 42, .72), transparent 26%, transparent 58%, rgba(8, 25, 42, .94) 88%, var(--ink) 100%);
}

.hero-copy { position: relative; z-index: 1; }
.hero-copy > * { max-width: min(820px, 66%); }
.hero-copy .section-kicker { display: block; margin-bottom: clamp(18px, 2vw, 30px); }
.hero-copy h1 {
  font-size: clamp(46px, 7.4vw, 112px);
  line-height: .98;
  letter-spacing: -.045em;
}
.hero-copy h1 .ln { display: block; overflow: hidden; padding-bottom: .04em; }
.hero-copy h1 .ln i { display: block; font-style: normal; }
.hero-copy .lead {
  margin-top: clamp(22px, 2.6vw, 34px);
  color: #B9CBD6;
  font-size: clamp(17px, 1.4vw, 20px);
  line-height: 1.6;
  max-width: 44ch;
}
.hero-actions {
  display: flex; align-items: center; gap: 28px;
  margin-top: clamp(28px, 3vw, 42px);
}

/* One orchestrated load: the headline rises behind its own mask, then the rest
   settles. Nothing on the page animates on entry after this. */
.js .hero-copy h1 .ln i,
.js .hero-copy .section-kicker,
.js .hero-copy .lead,
.js .hero-actions,
.js .hero-foot { will-change: transform, opacity; }
.js .hero-copy h1 .ln i { transform: translateY(106%); }
.js .hero-copy .section-kicker,
.js .hero-copy .lead,
.js .hero-actions,
.js .hero-foot { opacity: 0; transform: translateY(14px); }

.js .hero.is-in .hero-copy h1 .ln i {
  transform: none;
  transition: transform 1150ms cubic-bezier(.16, 1, .3, 1);
}
.js .hero.is-in .hero-copy h1 .ln:nth-child(2) i { transition-delay: 110ms; }
.js .hero.is-in .hero-copy .section-kicker,
.js .hero.is-in .hero-copy .lead,
.js .hero.is-in .hero-actions,
.js .hero.is-in .hero-foot {
  opacity: 1; transform: none;
  transition: opacity 760ms var(--ease), transform 760ms var(--ease);
}
.js .hero.is-in .hero-copy .section-kicker { transition-delay: 120ms; }
.js .hero.is-in .hero-copy .lead { transition-delay: 520ms; }
.js .hero.is-in .hero-actions { transition-delay: 640ms; }
.js .hero.is-in .hero-foot { transition-delay: 760ms; }

/* The field leaves the map as a single line and carries into the page. */
.hero-trace { position: relative; z-index: 1; margin-top: clamp(40px, 6vw, 82px); }
.hero-trace svg { display: block; width: 100%; height: clamp(52px, 5.4vw, 78px); }
.trace-line {
  fill: none;
  stroke: var(--mint);
  stroke-width: 2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.js .trace-line { stroke-dasharray: 1; stroke-dashoffset: 1; }
.js .trace-line.is-drawn { stroke-dashoffset: 0; }

.hero-foot {
  position: relative; z-index: 1;
  border-top: 1px solid var(--rule-dark);
  padding: 16px 0 clamp(22px, 3vw, 34px);
  font-size: var(--step-0);
  color: #B9CBD6;
}

.quiet-link {
  display: inline-flex; align-items: center;
  min-height: 44px;
  font: 600 var(--step-0)/1 var(--text);
  color: var(--teal-ink);
  border-bottom: 1px solid var(--teal);
  padding-bottom: 1px;
  transition: border-bottom-width 120ms var(--ease), color 120ms var(--ease);
}
.quiet-link:hover { border-bottom-width: 2px; color: var(--ink); }
.quiet-link.light { color: var(--mint); border-bottom-color: var(--mint); }
.quiet-link.light:hover { color: var(--paper); }

/* --------------------------------------------------------------- 2. Tension
   The quietest screen on the page, and the only one with nothing to look at.
   Same ground as the hero, stripped of every image. */

.tension {
  background: var(--ink);
  color: var(--paper);
  padding: clamp(96px, 13vw, 200px) 0;
}
.tension-grid {
  display: grid;
  grid-template-columns: minmax(0, 5.6fr) minmax(0, 6.4fr);
  column-gap: clamp(32px, 5vw, 88px);
  row-gap: clamp(40px, 5vw, 74px);
}
.tension-grid h2 {
  grid-column: 1; grid-row: 1;
  font-size: clamp(34px, 4.6vw, 64px);
  max-width: 11ch;
}
.tension-body { grid-column: 2; grid-row: 1; display: grid; gap: 22px; max-width: 54ch; align-self: end; }
.tension-body p { color: #A9BDC9; font-size: var(--step-2); line-height: 1.72; }
.tension-claim {
  grid-column: 1; grid-row: 2;
  align-self: end;
  max-width: 20ch;
  padding-left: 24px;
  border-left: 2px solid var(--mint);
  color: var(--paper);
  font-family: var(--display);
  font-weight: 600;
  font-size: var(--step-4);
  letter-spacing: -.02em;
  line-height: 1.28;
}

/* ------------------------------------------- 3. The peak: anatomy of a spike */

.anatomy {
  position: relative;
  isolation: isolate;
  background: var(--ink-deep);
  color: var(--paper);
  border-top: 1px solid var(--rule-dark);
  padding: clamp(72px, 9vw, 116px) 0 clamp(40px, 5vw, 68px);
}

.anatomy-head { margin-bottom: clamp(40px, 5vw, 72px); }
.anatomy-head h2 { font-size: var(--step-5); max-width: 20ch; }
.anatomy-head p {
  margin-top: 16px;
  color: #A9BDC9;
  font-size: var(--step-2);
  line-height: 1.65;
  max-width: 52ch;
}

.anatomy-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.34fr) minmax(0, .8fr);
  column-gap: clamp(32px, 5vw, 72px);
}

.figure {
  margin: 0;
  position: sticky;
  top: clamp(96px, 33vh, 268px);
}
.diagram { display: block; width: 100%; height: auto; }

.dg-frame line { stroke: #35576E; stroke-width: 1; }
.dg-frame .dg-grid { stroke: #2B4A62; stroke-dasharray: 2 7; }
.dg-axis {
  fill: #7F97A8;
  font: 500 16px var(--text);
  letter-spacing: .06em;
}
.dg-axis-end, .dg-anchor-end { text-anchor: end; }
.dg-anchor-mid { text-anchor: middle; }
.dg-note { fill: #A9BDC9; font: 500 17px var(--text); }
.dg-note-neg { fill: #E2837B; }
.dg-note-cluster { fill: #E0A93E; }
.dg-note-vol { fill: var(--mint); }
.dg-note-thresh { fill: #8FA8B8; }

.dg-ghost-vol { fill: none; stroke: #4A7290; stroke-width: 1.5; }
.dg-ghost-thresh { stroke: #2B4A62; stroke-width: 1; stroke-dasharray: 5 5; }
.dg-ticks path { stroke: #4E7B93; stroke-width: 2; fill: none; }
.dg-vol { fill: none; stroke: var(--mint); stroke-width: 2.5; stroke-linejoin: round; }
.dg-neg { fill: none; stroke: #D9675E; stroke-width: 2; stroke-linejoin: round; }
.dg-arc { fill: none; stroke: #E0A93E; stroke-width: 1.5; }
.dg-node { fill: #E0A93E; }
.dg-thresh { stroke: #7F97A8; stroke-width: 1; stroke-dasharray: 5 5; }
.dg-fire line { stroke: var(--paper); stroke-width: 1; }
.dg-fire circle { fill: var(--paper); }

/* Layers are painted only once the reader has arrived at the step that explains
   them. Without JS, and under reduced motion, every layer is simply on. */
.js .dg-layer { opacity: 0; transition: opacity 420ms var(--ease); }
.js .dg-vol, .js .dg-neg { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 900ms var(--ease); }
.js .figure.is-1 .dg-ticks { opacity: 1; }
.js .figure.is-2 .dg-volume { opacity: 1; }
.js .figure.is-2 .dg-vol { stroke-dashoffset: 0; }
.js .figure.is-3 .dg-sentiment { opacity: 1; }
.js .figure.is-3 .dg-neg { stroke-dashoffset: 0; }
.js .figure.is-4 .dg-cluster { opacity: 1; }
.js .figure.is-5 .dg-threshold { opacity: 1; }

.anatomy-steps { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.anatomy-steps li {
  min-height: 46vh;
  display: flex; flex-direction: column; justify-content: center;
  padding-left: 26px;
  border-left: 1px solid var(--rule-dark);
  position: relative;
}
.anatomy-steps li::before {
  content: ""; position: absolute; left: -1px; top: 0; bottom: 0;
  width: 2px; background: var(--mint);
  transform: scaleY(0); transform-origin: top;
  transition: transform 420ms var(--ease);
}
.anatomy-steps li.is-on::before { transform: scaleY(1); }
.anatomy-steps h3 {
  font-size: var(--step-4);
  letter-spacing: -.025em;
  margin-bottom: 14px;
  color: #7F97A8;
  transition: color 420ms var(--ease);
}
.anatomy-steps li.is-on h3 { color: var(--paper); }
.anatomy-steps p {
  color: #A9BDC9;
  font-size: var(--step-2);
  line-height: 1.65;
  max-width: 46ch;
}

/* --------------------------------------------------------------- The turn
   Three screens of dark end here. Everything from the index down states its
   own ground, so the change of light is a designed event and not a leak. */

.index, .missions, .ramp, .close { background: var(--paper); color: var(--ink); }
.reading { background: var(--paper-2); }

/* ----------------------------------------------------- 4. Capability index */

.index {
  padding: clamp(96px, 12vw, 156px) 0 clamp(56px, 7vw, 90px);
  /* Daylight arrives at the seam rather than at a hard edge. */
  background-image: linear-gradient(180deg, #E7E9E2, var(--paper) 220px);
}
.index-head { font-size: var(--step-5); margin-bottom: clamp(32px, 4vw, 56px); max-width: 18ch; }

.index-group {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
  column-gap: clamp(24px, 4vw, 64px);
  border-top: 1px solid var(--rule);
  padding: 38px 0;
}
.index-phase {
  font: 600 var(--step-0)/1 var(--display);
  letter-spacing: .1em;
  color: var(--teal-ink);
  position: sticky; top: 26px;
  align-self: start;
}
.index-list { margin: 0; display: grid; gap: 26px; }
.index-list > div {
  display: grid;
  grid-template-columns: minmax(0, 226px) minmax(0, 1fr);
  column-gap: clamp(20px, 3vw, 44px);
  row-gap: 6px;
  align-items: baseline;
}
.index-list dt { font: 600 var(--step-3)/1.24 var(--display); letter-spacing: -.02em; }
.index-list dd { margin: 0; color: var(--muted); font-size: var(--step-1); line-height: 1.66; max-width: 54ch; }

/* --------------------------------------------------------- 5. Two missions */

.missions { padding: clamp(56px, 7vw, 90px) 0 clamp(80px, 10vw, 128px); }
.missions-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(32px, 5vw, 80px);
}
.missions-grid h2 {
  grid-column: 1; grid-row: 1;
  font-size: var(--step-5);
  margin-bottom: clamp(36px, 4vw, 58px);
}
.mission { border-top: 2px solid var(--ink); padding-top: 26px; }
/* The heading and the first mission stack in one column; the second sits
   beside them and lands on the same baseline. */
.mission:first-of-type { grid-column: 1; grid-row: 2; }
.mission:last-of-type { grid-column: 2; grid-row: 1 / span 2; align-self: end; }
.mission h3 { font-size: var(--step-4); margin-bottom: 16px; max-width: 16ch; }
.mission p { color: var(--muted); font-size: var(--step-2); line-height: 1.68; max-width: 42ch; margin-bottom: 24px; }

/* ---------------------------------------------------------- 6. Reading list */

.reading {
  background: var(--paper-2);
  border-top: 1px solid var(--rule);
  padding: clamp(72px, 9vw, 116px) 0;
}
.reading-head { font-size: var(--step-5); margin-bottom: clamp(36px, 4vw, 58px); max-width: 22ch; }
.reading-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(32px, 5vw, 80px);
  align-items: start;
}

.reading-lead {
  display: block;
  border-top: 2px solid var(--ink);
  padding-top: 24px;
}
.reading-lead .article-tag { margin-bottom: 14px; }
.reading-lead h3 { font-size: var(--step-4); line-height: 1.16; margin-bottom: 16px; }
.reading-lead p { color: var(--muted); font-size: var(--step-2); line-height: 1.66; max-width: 42ch; margin-bottom: 20px; }
.reading-lead:hover h3 { color: var(--teal-ink); }
.reading-time { font: 600 var(--step-0)/1 var(--text); color: var(--teal-ink); }

.reading-list { list-style: none; margin: 0; padding: 0; }
.reading-list li { border-top: 1px solid var(--rule); }
.reading-list li:first-child { border-top: 2px solid var(--ink); }
.reading-list a {
  display: grid; gap: 7px;
  padding: 19px 0;
  transition: padding-left 160ms var(--ease);
}
.reading-list a:hover { padding-left: 10px; }
.reading-list a:hover .reading-title { color: var(--teal-ink); }
.reading-title { font: 600 var(--step-2)/1.34 var(--display); letter-spacing: -.02em; }
.reading-meta { font-size: var(--step-0); color: var(--muted); }
.reading-empty { color: var(--muted); font-size: var(--step-2); }

/* ------------------------------------------------------------ 7. The ramp */

.ramp { padding: clamp(80px, 10vw, 130px) 0 clamp(72px, 9vw, 110px); }
.ramp h2 { font-size: var(--step-5); margin-bottom: clamp(40px, 5vw, 70px); }
.ramp-row {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(28px, 4vw, 64px);
  border-top: 1px solid var(--teal);
}
.ramp-row li { position: relative; padding-top: 30px; }
.ramp-row li::before {
  content: ""; position: absolute; left: 0; top: -5px;
  width: 9px; height: 9px; background: var(--teal);
}
.ramp-n { display: block; font: 600 var(--step-0)/1 var(--display); color: var(--teal-ink); margin-bottom: 26px; }
.ramp-row h3 { font-size: var(--step-3); margin-bottom: 12px; }
.ramp-row p { color: var(--muted); font-size: var(--step-1); line-height: 1.68; max-width: 34ch; }

/* -------------------------------------------------------------- 8. The end */

.close { padding-bottom: clamp(80px, 10vw, 132px); }
.close-trace svg { display: block; width: 100%; height: clamp(64px, 7vw, 92px); }
.close-copy {
  border-top: 1px solid var(--ink);
  padding-top: clamp(36px, 4vw, 58px);
}
.close-copy h2 { font-size: var(--step-6); max-width: 19ch; }
.close-copy p {
  color: var(--muted);
  font-size: var(--step-2);
  line-height: 1.66;
  max-width: 46ch;
  margin: 22px 0 34px;
}

/* ------------------------------------------------------------- Composition
   below 900px. This is a re-composition, not the desktop layout narrowed:
   the trace shortens, the diagram is cropped to the burst, and the index
   loses its column structure. */

@media (max-width: 900px) {
  /* The map is the wrong shape for a phone: it goes to a band at the foot of the
     hero with the field over it, and the type takes the space it vacates. */
  .hero { min-height: 0; padding-bottom: 0; }
  .hero-world { inset: auto 0 0 0; height: 46vh; min-height: 260px; }
  .hero-map { background-position: 72% center; }
  .hero-scrim {
    background:
      linear-gradient(180deg, var(--ink) 0 8%, rgba(11, 31, 51, .74) 34%, rgba(11, 31, 51, .34) 72%, rgba(8, 25, 42, .9)),
      linear-gradient(90deg, rgba(11, 31, 51, .78), transparent 58%);
  }
  .hero-copy > * { max-width: none; }
  /* Each line has to survive as one line: the mask only reads as a reveal when
     the thing behind it is a line. */
  .hero-copy h1 { font-size: clamp(30px, 9.4vw, 56px); }
  .hero-copy .section-kicker { font-size: 10px; letter-spacing: .16em; }
  .hero-copy .lead { max-width: 42ch; }
  .hero-actions { gap: 20px; flex-wrap: wrap; }
  .hero-trace { margin-top: 30vh; }
  .hero-foot { padding-bottom: 26px; }

  .tension { padding: clamp(72px, 16vw, 120px) 0; }
  .tension-grid { grid-template-columns: minmax(0, 1fr); row-gap: 26px; }
  .tension-grid h2, .tension-body, .tension-claim { grid-column: 1; grid-row: auto; max-width: none; }

  .anatomy-grid { grid-template-columns: minmax(0, 1fr); }
  /* A pinned band, cropped to the burst: at this width the left half of the
     axis is empty by construction, and the annotations belong to the step
     text beside it rather than to a 7px label inside the drawing. */
  .anatomy-stage {
    position: sticky; top: 0; z-index: 2;
    margin: 0 calc(var(--gutter) * -1) 4px;
    padding: 10px var(--gutter) 14px;
    background: var(--ink-deep);
    box-shadow: 0 16px 24px -16px rgba(3, 11, 20, .95);
  }
  .anatomy-stage .figure {
    position: static;
    height: 27vh; min-height: 168px;
    margin: 0;
    overflow: hidden;
  }
  /* The svg slices itself to the right of the frame, which is where the burst
     is. The narrower the screen, the tighter the crop. */
  .anatomy-stage .diagram { height: 100%; }
  .dg-note, .dg-axis { display: none; }
  .anatomy-steps li { min-height: 0; padding: 30px 0 30px 20px; }
  .anatomy-steps p { max-width: none; }

  .index-group { grid-template-columns: minmax(0, 1fr); row-gap: 22px; padding: 30px 0; }
  .index-phase { position: static; }
  .index-list > div { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .index-list dd { max-width: none; }

  .missions-grid { grid-template-columns: minmax(0, 1fr); row-gap: 42px; }
  .missions-grid h2,
  .missions-grid .mission:first-of-type,
  .missions-grid .mission:last-of-type { grid-column: 1; grid-row: auto; align-self: auto; }

  .reading-grid { grid-template-columns: minmax(0, 1fr); row-gap: 42px; }

  .ramp-row { grid-template-columns: minmax(0, 1fr); row-gap: 30px; border-top: 0; }
  .ramp-row li { padding: 24px 0 0 22px; border-left: 1px solid var(--teal); }
  .ramp-row li::before { left: -5px; top: 24px; }
  .ramp-n { margin-bottom: 14px; }
  .ramp-row p { max-width: none; }

  .close-copy h2 br { display: none; }
}

@media (max-width: 420px) {
  .hero-actions { flex-direction: column; align-items: flex-start; }
  .hero-actions .button { width: 100%; }
}

/* ------------------------------------------------------------ Reduced motion
   Everything is drawn, nothing dims, nothing animates. The page still reads
   top to bottom exactly as intended. */

@media (prefers-reduced-motion: reduce) {
  /* The hero arrives composed rather than assembling itself. */
  .js .hero-copy h1 .ln i { transform: none; }
  .js .hero-copy .section-kicker,
  .js .hero-copy .lead,
  .js .hero-actions,
  .js .hero-foot { opacity: 1; transform: none; }
  .js .hero-copy h1 .ln i,
  .js .hero-copy .section-kicker,
  .js .hero-copy .lead,
  .js .hero-actions,
  .js .hero-foot { transition: none; }
  .js .trace-line,
  .js .dg-vol,
  .js .dg-neg { stroke-dasharray: none; stroke-dashoffset: 0; }
  .js .dg-layer { opacity: 1; }
  .anatomy-steps li::before { transform: scaleY(1); }
  .anatomy-steps h3 { color: var(--paper); }
  .quiet-link, .button, .reading-list a, .dg-layer, .anatomy-steps h3, .anatomy-steps li::before {
    transition: none;
  }
}
