/* nightwatch — PriceSmart TP Risk Index
   Grammar: continuous world (worldflight), filmless. One canvas, one take.
   Ground travels night -> paper once, during the descent. Two-stop accent, one
   hue, keyed to the ground, because a page that crosses from #06080C to #F2EEE4
   cannot clear 4.5:1 on both with a single stop. */

/* ---------------------------------------------------------------- tokens -- */
:root {
  /* The night ground. Off-black, blue-tinted. Never #000. */
  --nw-night:        #06080C;
  --nw-night-2:      #0C111A;
  --nw-night-ink:    #E9E6DE;
  --nw-night-soft:   #8C93A2;

  /* The paper ground. Bone, warm, engraved-chart stock. */
  --nw-paper:        #F2EEE4;
  --nw-paper-2:      #E7E1D3;
  --nw-paper-ink:    #14120E;
  --nw-paper-soft:   #57513F;

  /* Live ground. globe.js owns the dawn and publishes every derived colour
     here, per frame, as plain rgb()/rgba().

     These are deliberately NOT color-mix(). Chrome returns a color-mix result
     from getComputedStyle as `oklab(0.92 ...)`, and the verification harness
     parses colour by pulling the numbers out of that string and reading them as
     0-255 RGB (shoot.mjs:402). An oklab lightness of 0.92 therefore measures as
     near-black, and the contrast pass reported 1.04:1 on a line that actually
     renders at roughly 15:1. Publishing rgb() keeps the harness able to grade
     the page, and it collapses the palette to one mix function shared by the
     canvas and the DOM instead of two that can drift. */
  --nw-dawn: 0;
  --nw-canvas:  #06080C;
  --nw-surface: #0C111A;
  --nw-ink:     #E9E6DE;
  --nw-soft:    #B6BCC8;
  --nw-rule:    rgba(233, 230, 222, 0.18);
  --nw-rule-2:  rgba(233, 230, 222, 0.34);
  --nw-panel:   rgba(12, 17, 26, 0.82);
  --nw-track:   rgba(233, 230, 222, 0.08);
  --nw-fill:    rgba(233, 230, 222, 0.46);
  --nw-scrim:   rgba(6, 8, 12, 0.66);
  --nw-scrim-hi: rgba(6, 8, 12, 0.92);

  /* The one accent. Admiralty-chart magenta: on a nautical chart magenta is
     the caution ink, which is exactly the job it does here. Two lightnesses of
     one hue, keyed to the ground so both clear contrast. Spent ONCE, on the
     refutation, and nowhere else in the design. */
  --nw-flag-night: #FF4FA3;
  --nw-flag-paper: #A8005E;
  --nw-flag: #FF4FA3;
  --nw-flag-ink: #14060E;

  /* Tier ink. Data encoding, not accent: four muted stops, none saturated, so
     the refutation stays the only loud colour on the page. */
  --nw-tier-low:      #5F7C68;
  --nw-tier-moderate: #8A7F5C;
  --nw-tier-elevated: #9E6636;
  --nw-tier-high:     #92352C;

  --nw-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Engine tokens, themed. */
  --sc-canvas: var(--nw-canvas);
  --sc-surface: var(--nw-surface);
  --sc-ink: var(--nw-ink);
  --sc-ink-soft: var(--nw-soft);
  --sc-accent: var(--nw-flag);
  --sc-accent-ink: var(--nw-flag-ink);
  --sc-font-display: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --sc-font-text: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --sc-shadow-color: 220 30% 4%;
}

html { background: var(--nw-canvas); }
body {
  background: var(--nw-canvas);
  color: var(--nw-ink);
  font-family: var(--sc-font-text);
  font-variant-numeric: tabular-nums;
  transition: none;
}
::selection { background: var(--nw-flag); color: var(--nw-flag-ink); }

/* Focus is themed to the accent and always visible. */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--nw-flag);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------- the world -- */
/* The canvas is a direct child of the fixed stage and OUTSIDE every segment, so
   the engine never touches its opacity. It is the single take: it does not cut,
   dissolve, or unmount for the whole page. */
#globe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  z-index: 0;
}

/* Segments sit above the world and carry the instruments. Empty of media, so
   the engine's poster and clip paths never engage. */
.sc-world__seg { z-index: 100; }

.alt {
  position: absolute; inset: 0;
  display: grid;
  align-content: center;
  padding-inline: var(--sc-gutter);
  /* Top padding clears the fixed dossier; without it a tall act centres its
     heading straight through the corridor line. */
  padding-block: clamp(6rem, 13vh, 9rem) clamp(3.5rem, 8vh, 6rem);
  max-width: 1500px;
  margin-inline: auto;
}
/* This is the cue the verification pass measures, so it is bounded to the
   copy rather than to the frame. */
.alt__inner { width: 100%; max-width: 74ch; }

/* --------------------------------------------------------------- typography -- */
.nw-display {
  font-family: var(--sc-font-display);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: var(--sc-track-tight);
  text-wrap: balance;
  color: var(--nw-ink);
  margin: 0;
}
.nw-h1 { font-size: clamp(2.4rem, 1.4rem + 4.4vw, 5.2rem); }
.nw-h2 { font-size: clamp(1.7rem, 1.2rem + 2.1vw, 3rem); }
.nw-lede {
  max-width: 46ch;
  font-size: var(--sc-t-lg);
  line-height: 1.5;
  color: var(--nw-soft);
  text-wrap: pretty;
  margin: 0;
}
.nw-body { max-width: 62ch; line-height: 1.62; color: var(--nw-soft); text-wrap: pretty; margin: 0; }

/* One label style, used for every instrument caption on the page. */
.nw-label {
  font-family: var(--nw-mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nw-soft);
  margin: 0;
}
.nw-mono { font-family: var(--nw-mono); font-variant-numeric: tabular-nums; }

/* Citation markers. Every figure on this page carries one. */
.cite {
  font-family: var(--nw-mono);
  font-size: 0.62em;
  vertical-align: super;
  line-height: 0;
  color: var(--nw-soft);
  text-decoration: none;
  padding-inline: 0.12em;
  border-bottom: 1px solid transparent;
}
.cite:hover { color: var(--nw-ink); border-bottom-color: var(--nw-rule-2); }

/* ------------------------------------------------------------------ chrome -- */
/* The nav IS a map: a waypoint list with a live position marker, and it jumps.
   Grammar 2.4 requires a world you can skip around in, because a world you
   cannot navigate is a video. */
.rail {
  position: fixed;
  right: clamp(0.75rem, 2.2vw, 2rem);
  top: 50%; transform: translateY(-50%);
  z-index: 60;
  pointer-events: auto;
  display: grid;
  gap: 2px;
  font-family: var(--nw-mono);
  /* The globe travels under this at every altitude, so the rail carries its own
     ground rather than relying on whatever happens to be behind it. */
  background: var(--nw-scrim);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  padding: 0.5rem 0.6rem;
  border-radius: 3px;
}
.rail__leg {
  display: grid;
  grid-template-columns: 2.9rem 1fr;
  align-items: center;
  gap: 0.6rem;
  background: none; border: 0;
  padding: 0.32rem 0.1rem;
  cursor: pointer;
  color: var(--nw-soft);
  font-family: inherit;
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
  opacity: 0.5;
  transition: opacity 160ms var(--sc-ease-out), color 160ms var(--sc-ease-out);
}
.rail__leg:hover { opacity: 0.9; color: var(--nw-ink); }
.rail__leg[aria-current="true"] { opacity: 1; color: var(--nw-ink); }
.rail__alt { text-align: right; font-variant-numeric: tabular-nums; }
.rail__tick {
  display: block; height: 1px; width: 100%;
  background: var(--nw-rule-2);
  position: relative;
}
.rail__leg[aria-current="true"] .rail__tick { background: var(--nw-ink); height: 2px; }
.rail__name { display: none; }
@media (min-width: 1080px) { .rail__name { display: block; } }

/* The dossier header arrives when the cell does and holds to the close: the
   chart stays pinned while the instruments over it change. */
.dossier {
  position: fixed;
  left: var(--sc-gutter); top: clamp(1rem, 3vh, 2rem);
  z-index: 60;
  font-family: var(--nw-mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--nw-soft);
  opacity: 0;
  pointer-events: none;
  display: grid; gap: 0.25rem;
  max-width: min(46ch, 60vw);
}
.dossier strong { color: var(--nw-ink); font-weight: 600; letter-spacing: 0.04em; }

/* The wordmark and the one account link ride together as the page's fixed
   chrome. The wrapper owns the position so the pair moves as a unit at the
   mobile breakpoint, where it swaps corners with the rail. */
.chrome {
  position: fixed;
  left: var(--sc-gutter); bottom: clamp(1rem, 3vh, 2rem);
  z-index: 60;
  display: flex; align-items: center; gap: 0.9rem;
}
.wordmark {
  display: flex; align-items: center; gap: 0.55rem;
  font-family: var(--nw-mono);
  font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--nw-soft);
  text-decoration: none;
}
.chrome__link {
  font-family: var(--nw-mono);
  font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--nw-soft);
  text-decoration: none;
  padding-left: 0.9rem;
  border-left: 1px solid var(--nw-rule-2);
  transition: color 160ms var(--sc-ease-out);
}
.chrome__link:hover { color: var(--nw-ink); }
.wordmark__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--nw-ink); }

/* ------------------------------------------------------------- instruments -- */
.panel {
  background: var(--nw-panel);
  border: 1px solid var(--nw-rule);
  border-radius: 3px;
  box-shadow: var(--sc-e2);
  backdrop-filter: blur(6px);
}

/* Altitude 2: the cell asserts itself, flatly and early. */
.cellhead { display: grid; gap: clamp(1.2rem, 3vh, 2.2rem); max-width: 62ch; }
.cellhead__corridor {
  font-family: var(--sc-font-display);
  font-size: clamp(1.5rem, 1rem + 2vw, 2.7rem);
  font-weight: 600; line-height: 1.14; letter-spacing: var(--sc-track-snug);
  color: var(--nw-ink); margin: 0;
}
.cellhead__corridor .arrow { color: var(--nw-soft); font-weight: 400; }
.scoreline { display: flex; align-items: baseline; gap: clamp(0.8rem, 2vw, 1.6rem); flex-wrap: wrap; }
.scoreline__n {
  font-family: var(--sc-font-display);
  font-size: clamp(3.4rem, 2rem + 6vw, 7rem);
  font-weight: 700; line-height: 0.86; letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--nw-ink);
}
.tierchip {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--nw-mono); font-size: 0.72rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--nw-ink);
  padding: 0.34rem 0.6rem;
  border: 1px solid currentColor;
  border-radius: 2px;
}
.tierchip__swatch { width: 9px; height: 9px; border-radius: 1px; background: var(--tier, var(--nw-ink)); }
.metaline { display: flex; gap: clamp(1rem, 3vw, 2.4rem); flex-wrap: wrap; }
.metaline > div { display: grid; gap: 0.22rem; }
.metaline b { font-family: var(--nw-mono); font-weight: 500; font-size: 0.86rem; color: var(--nw-ink); }

/* Altitude 3: the arithmetic, open, checkable. */
.decomp { display: grid; gap: clamp(1.4rem, 3vh, 2.4rem); max-width: 72ch; }
.decomp__rows { display: grid; gap: 0.55rem; }
.drow {
  display: grid;
  grid-template-columns: minmax(9rem, 15ch) 1fr auto;
  align-items: center;
  gap: clamp(0.6rem, 1.6vw, 1.2rem);
  font-family: var(--nw-mono); font-size: 0.78rem;
  color: var(--nw-soft);
}
.drow__name { color: var(--nw-ink); letter-spacing: 0.02em; }
.drow__bar { position: relative; height: 10px; background: var(--nw-track); border-radius: 1px; overflow: hidden; }
.drow__fill {
  position: absolute; top: 0; bottom: 0; left: 0; width: 100%;
  background: var(--nw-fill);
  transform-origin: 0 50%;
  transform: scaleX(0);
}
.drow__math { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--nw-soft); }
.drow__math b { color: var(--nw-ink); font-weight: 500; }
.decomp__sum {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  border-top: 1px solid var(--nw-rule-2); padding-top: 0.7rem;
  font-family: var(--nw-mono); font-size: 0.82rem; color: var(--nw-soft);
}
.decomp__sum b { font-size: 1.15rem; color: var(--nw-ink); font-weight: 600; }

/* The published band ruler. */
.bands { display: grid; gap: 0.4rem; }
.bands__track { position: relative; height: 26px; display: flex; border: 1px solid var(--nw-rule-2); border-radius: 2px; margin-top: 1.6rem; }
.bands__seg { display: grid; place-items: center; font-family: var(--nw-mono); font-size: 0.58rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--nw-soft); border-right: 1px solid var(--nw-rule); }
.bands__seg:last-child { border-right: 0; }
.bands__needle { position: absolute; top: -5px; bottom: -5px; width: 2px; background: var(--nw-ink); }
.bands__needle::after {
  content: attr(data-score);
  position: absolute; top: -1.4rem; left: 50%; transform: translateX(-50%);
  font-family: var(--nw-mono); font-size: 0.72rem; font-weight: 600; color: var(--nw-ink);
}

/* ------------------------------------------------ altitude 4: the peak -- */
/* The only saturated colour on the page lives in this block and nowhere else. */
.correct { display: grid; gap: clamp(0.8rem, 1.8vh, 1.3rem); max-width: 66ch; }

.claimcard { padding: clamp(0.9rem, 2vw, 1.3rem); display: grid; gap: 0.7rem; }
.claimcard__head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.claimcard__path { font-family: var(--nw-mono); font-size: 0.66rem; color: var(--nw-soft); letter-spacing: 0.04em; }

.pipe { display: grid; gap: 0.4rem; }
.pipe__measure { font-size: 0.98rem; line-height: 1.45; color: var(--nw-ink); }
.pipe__status {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--nw-mono); font-size: 0.8rem; letter-spacing: 0.06em;
  position: relative; width: fit-content;
  color: var(--nw-ink);
}
/* The strike is a pseudo-element on a wrapper, drawn by clip-path from --strike
   so it travels with scroll rather than transitioning on a timer. */
.strike { position: relative; display: inline-block; }
.strike::after {
  content: "";
  position: absolute; left: -0.1em; right: -0.1em; top: 52%;
  height: 2px; background: var(--nw-flag);
  transform-origin: 0 50%;
  transform: scaleX(var(--strike, 0));
}
.pipe__was { opacity: calc(1 - (var(--strike, 0) * 0.45)); }

.verdict {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--nw-mono); font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--nw-flag-ink); background: var(--nw-flag);
  padding: 0.26rem 0.55rem; border-radius: 2px;
  opacity: var(--verdict-op, 0);
  transform: scale(calc(0.94 + var(--verdict-op, 0) * 0.06));
}

.evidence {
  border-left: 1px solid var(--nw-flag);
  padding-left: clamp(0.7rem, 1.6vw, 1rem);
  display: grid; gap: 0.4rem;
  opacity: var(--evi-op, 0);
}
.evidence__q { font-size: 0.88rem; line-height: 1.5; color: var(--nw-ink); max-width: 58ch; margin: 0; }
.evidence__src { font-family: var(--nw-mono); font-size: 0.68rem; color: var(--nw-soft); }
.evidence__src a { color: var(--nw-ink); text-underline-offset: 3px; text-decoration-thickness: 1px; }

.becomes { display: grid; gap: 0.25rem; opacity: var(--after-op, 0); }
.becomes__status {
  font-family: var(--nw-mono); font-size: 0.86rem; font-weight: 500;
  color: var(--nw-flag);
  letter-spacing: 0.04em;
}

/* The loop stages closing. Real stage names from the real sidecar. */
.stages { display: flex; flex-wrap: wrap; gap: 0.34rem; opacity: var(--stage-op, 0); }
.stages__s {
  font-family: var(--nw-mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.24rem 0.5rem; border: 1px solid var(--nw-rule-2); border-radius: 2px;
  color: var(--nw-soft);
}
.stages__s[data-on="1"] { color: var(--nw-ink); border-color: var(--nw-ink); }

/* --------------------------------------------------- altitude 5: ledger -- */
.ledger { display: grid; gap: clamp(1rem, 2.4vh, 1.7rem); max-width: 104ch; }
/* Eight delivered cells. auto-fit resolved to three columns and left a ninth
   slot empty, which rendered as a grey tile: the taste floor's 'the grid was
   planned wrong' case. Eight divides by four, two and one, never three. */
.ledger__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--nw-rule); border: 1px solid var(--nw-rule); }
@media (min-width: 1080px) { .ledger__grid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 560px)  { .ledger__grid { grid-template-columns: 1fr; } }
.lcell { background: var(--nw-canvas); padding: 0.8rem 0.9rem; display: grid; gap: 0.3rem; }
.lcell__top { display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; }
.lcell__j { font-family: var(--nw-mono); font-size: 0.76rem; color: var(--nw-ink); letter-spacing: 0.02em; }
.lcell__s { font-family: var(--nw-mono); font-size: 0.95rem; font-weight: 600; color: var(--nw-ink); }
.lcell__c { font-family: var(--nw-mono); font-size: 0.62rem; color: var(--nw-soft); }
.lcell__tier { height: 2px; background: var(--tier, var(--nw-rule-2)); }
.tally { display: flex; gap: clamp(1rem, 3vw, 2.6rem); flex-wrap: wrap; }
.tally > div { display: grid; gap: 0.2rem; }
.tally b { font-family: var(--nw-mono); font-size: clamp(1.3rem, 1rem + 1vw, 1.9rem); font-weight: 600; color: var(--nw-ink); }

/* ---------------------------------------------------- altitude 6: close -- */
.close { display: grid; gap: clamp(1.4rem, 3.4vh, 2.4rem); max-width: 58ch; }
.cta {
  display: inline-flex; align-items: center; gap: 0.6rem;
  justify-self: start;
  font-family: var(--sc-font-display); font-size: 1rem; font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--nw-canvas); background: var(--nw-ink);
  padding: 0.85rem 1.4rem; border-radius: 2px;
  text-decoration: none; white-space: nowrap;
  border: 1px solid var(--nw-ink);
  transition: transform 140ms var(--sc-ease-out), background-color 140ms var(--sc-ease-out);
}
.cta:hover { transform: translateY(-1px); }
.cta:active { transform: translateY(1px); }
.provenance {
  font-family: var(--nw-mono); font-size: 0.66rem; line-height: 1.7;
  color: var(--nw-soft); max-width: 74ch;
}
.provenance a { color: var(--nw-soft); text-underline-offset: 3px; }
.provenance a:hover { color: var(--nw-ink); }

.closelinks {
  display: flex; flex-wrap: wrap;
  gap: 0.5rem clamp(0.9rem, 2.4vw, 1.8rem);
  font-family: var(--nw-mono);
  font-size: 0.66rem; letter-spacing: 0.08em;
}
.closelinks a {
  color: var(--nw-soft);
  text-decoration: none;
  border-bottom: 1px solid var(--nw-rule-2);
  padding-bottom: 1px;
  transition: color 160ms var(--sc-ease-out), border-color 160ms var(--sc-ease-out);
}
.closelinks a:hover { color: var(--nw-ink); border-bottom-color: var(--nw-ink); }

/* ------------------------------------------------------------ responsive -- */
@media (max-width: 860px) {
  .alt { padding-block: clamp(5.5rem, 14vh, 9rem); align-content: end; }
  .rail { top: auto; bottom: 0.6rem; right: auto; left: 50%; transform: translateX(-50%);
          display: flex; gap: 0.55rem; background: var(--nw-panel);
          padding: 0.4rem 0.6rem; border-radius: 2px; backdrop-filter: blur(6px); }
  .rail__leg { grid-template-columns: 1fr; gap: 0.15rem; padding: 0.3rem 0.15rem; min-width: 2.6rem; }
  .rail__alt { text-align: center; font-size: 0.58rem; white-space: nowrap; }
  .chrome { bottom: auto; top: clamp(1rem, 3vh, 2rem); left: auto; right: var(--sc-gutter); }
  .dossier { max-width: 70vw; font-size: 0.62rem; }
  .drow { grid-template-columns: 1fr; gap: 0.2rem; }
  .drow__bar { height: 7px; }
  .nw-h1 { font-size: clamp(1.85rem, 1.2rem + 3.2vw, 2.4rem); line-height: 1.08; }
}

/* --------------------------------------------------------- reduced motion -- */
/* Fewer and gentler, not zero. The world stops flying and holds one legible
   frame per altitude; every state the scroll would have driven is resolved to
   its finished value, so the whole story still reads. */
@media (prefers-reduced-motion: reduce) {
  /* The resolved state is driven from page.js, not forced here. Pinning these
     to opacity 1 in CSS lit them while the card itself was still fading in,
     which the contrast pass correctly caught at 2.6:1. Under reduced motion the
     page now resolves the whole correction the instant the card is fully
     opaque: nothing to follow, nothing shown at an unreadable alpha. */
  .verdict { transform: none; }
  .cta,
  .chrome__link,
  .closelinks a { transition: none; }
}

/* Every act anchors its copy to the left while the globe sits right of centre,
   so the density belongs in a COLUMN under the text rather than in a band across
   the whole frame (taste.md, Text over media, shape 3). The stock band left the
   descent lede sitting on the globe's bright limb at 4.36:1; a column clears it
   and leaves the lattice and the marks on the right at full contrast. */
.sc-world__scrim {
  background: linear-gradient(90deg,
    var(--nw-scrim-hi) 0%,
    var(--nw-scrim-hi) 34%,
    var(--nw-scrim) 48%,
    transparent 62%);
}

/* On a phone the copy spans the full frame and sits over the brightest part of
   the globe, and the stock band tops out at 58% of the frame, which is above
   where phone copy actually sits. Its own gradient, shaped to the copy, took the
   descent lede from 3.48:1 to clear. That line is ~19.5px regular, so 4.5:1 is
   its bar and the large-text exemption does not apply to it. */
@media (max-width: 860px) {
  .sc-world__scrim {
    background: linear-gradient(180deg,
      transparent 0%,
      transparent 44%,
      var(--nw-scrim) 54%,
      var(--nw-scrim-hi) 66%,
      var(--nw-scrim-hi) 100%);
  }
}
