/* ============================================================
   dive.css — the DIVE shell's chrome: stage, HUD, entry canvas.
   Loaded ONLY by Website/concept/index.html, after the shared
   tokens.css -> base.css chain. NOT topbar.css: this page has no
   top bar, no panel, no status bar; the station rail and one
   PORTAL chip are its only permanent navigation.

   SCOPE: kept local to Website/concept/ rather than styles/, on
   purpose. Every selector is still prefixed .dive / .dive-* /
   #dive-*, so a future move into styles/ (if this page ever
   stabilises enough to join the shared system) is a straight file
   relocation.

   Reuses rather than restates: .t-display / .t-title / .t-micro
   come from base.css — the HUD sizes (24px/500/0.04em for the
   station number, 15px/500/0.06em for the title, 9px/500/0.14em
   uppercase for the kind chip and every other HUD label) are the
   SAME numbers as tokens.css's SCALE 1, which is why this file reads
   those roles directly instead of restating the sizes. The one
   exception is the 11px caption, which has no existing role — see
   its rule below.
   ============================================================ */

html, body { overflow: hidden; } /* the stage fills the viewport; nothing here scrolls */

[data-page="concept-dive"] {
  height: 100%;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   STAGE — the WebGL canvas and the entry-sequence 2D overlay,
   both full-bleed, both owned entirely by shell/main.js.
   ============================================================ */
#dive-stage {
  position: fixed;
  inset: 0;
  background: var(--bg-ground);
}
#dive-canvas,
#dive-entry-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}
/* The entry overlay draws once on arrival and is transparent the rest of
   the time (entry.js clears it every frame it is not actively drawing);
   it must never capture pointer events meant for the canvas beneath it. */
#dive-entry-canvas { pointer-events: none; }

/* ---- the DOM-station layer (station 01 only) ----
   Sits between the WebGL canvas and the entry overlay. shell/main.js sets
   transform/filter/opacity/visibility on the station's own element from
   the same dive-curve numbers the compositor gives a texture; nothing
   here may set those four properties, or a dive would fight the shell. */
#dive-dom-layer {
  position: absolute;
  inset: 0;
  pointer-events: none; /* the station element re-enables its own */
}
.dive-dom-station {
  position: absolute;
  inset: 0;
  /* Scaling happens about the viewport centre, matching the compositor's
     "a smaller picture on the ground" sampling. */
  transform-origin: 50% 50%;
  will-change: transform, opacity, filter;
}

/* ============================================================
   PRELOADER — the one screen shown before the dive starts, when
   DIVE_CONFIG.loading.mode is 'all'. Above everything, including
   the entry overlay, and gone (hidden) the moment it is done.

   It borrows the HUD's vocabulary on purpose — same station
   number treatment, same rail ticks, same amber — so the wait
   reads as the page assembling itself rather than as a different
   screen bolted in front of it.
   ============================================================ */
.dive-preloader {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-ground);
  color: var(--text-1);
}
.dive-preloader[hidden] { display: none; }
.dive-preloader-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  width: min(420px, calc(100vw - 80px));
  text-align: center;
}
.dive-preloader-count {
  color: var(--accent);
  transition: color 200ms linear;
}
/* One breathing line under the station count. It says the same thing for
   the whole wait (DIVE_CONFIG.loading.label), so the PULSE is what carries
   "still working" - which is why it is CSS: nothing in JS has to run for
   the page to look alive, including while the main thread is busy
   decoding an image, which is exactly when a JS-driven animation would
   stutter and read as a hang. */
.dive-preloader-name {
  min-height: 1.4em; /* holds its line so the bar never jumps */
  color: var(--text-2);
  animation: dive-preloader-breathe 2.2s ease-in-out infinite;
}
/* An error message replaces the label and must not pulse: a steady line is
   how it reads as a state rather than as progress. */
.dive-preloader-name.is-static { animation: none; }
@keyframes dive-preloader-breathe {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .dive-preloader-name { animation: none; }
}
/* 1px rule that fills left to right — the whole progress display. */
.dive-preloader-bar {
  width: 100%;
  height: var(--border);
  margin-top: var(--sp-2);
  background: var(--line);
}
.dive-preloader-bar-fill {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 220ms linear;
}
/* Six ticks, one per station, filling in as each one lands. Same
   geometry as the HUD rail, laid on its side. */
.dive-preloader-ticks {
  display: flex;
  gap: 12px;
  margin-top: var(--sp-4);
}
.dive-preloader-tick {
  display: block;
  width: 14px;
  height: 1px;
  background: var(--line-strong);
  transition: background 200ms linear, width 200ms linear;
}
.dive-preloader-tick.is-done { background: var(--text-2); }
.dive-preloader-tick.is-active {
  width: 28px;
  background: var(--accent);
}

/* ============================================================
   HUD — one DOM layer over the stage. Every corner is 20px inset,
   never scrolls, never blocks pointer events except on its own
   interactive children.
   ============================================================ */
.dive-hud {
  position: fixed;
  inset: 0;
  pointer-events: none;
  /* Set every frame by hud.js during a dive/entry/explore — see main.js.
     Default 1 so the HUD is fully visible before the shell's first frame. */
  --dive-hud-opacity: 1;
}

/* Everything except the control corner recedes during a transition or in
   Explore mode — the control corner (Explore/Exit + any slider) must stay
   legible and clickable at all times, so it is deliberately NOT in this
   list. See hud.js's header comment. */
.dive-hud-info,
.dive-rail,
.dive-hud-meta {
  opacity: var(--dive-hud-opacity);
  transition: opacity 80ms linear;
}

/* ---- top-left: station identity ---- */
.dive-hud-info {
  position: absolute;
  top: 20px;
  left: 20px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-width: 360px;
}
.dive-hud-number { color: var(--accent); }
.dive-hud-title { margin: 0; color: var(--text-1); }
.dive-hud-kind {
  align-self: flex-start;
  padding: 2px 6px;
  color: var(--text-2);
  border: var(--border) solid var(--line-strong);
  border-radius: var(--radius);
}
/* 11px is this line's own number — not --fs-hint (10px), which is the
   nearest existing role but a different value by design. One-off
   literal, same treatment as e.g. home.css's .home-step-figure
   background — see this file's header comment. */
.dive-hud-caption {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
}

/* ---- right edge, centred: the station rail ---- */
.dive-rail {
  position: fixed;
  top: 50%;
  right: 20px;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.dive-rail-tick {
  display: block;
  width: 1px;
  height: 14px;
  background: var(--line-strong);
}
.dive-rail-tick--active {
  height: 28px;
  background: var(--accent);
}

/* ---- bottom-left: the station's own control, only if it has one ----
   Explore/Exit chip stacks above the slider card slot. */
.dive-hud-control {
  position: absolute;
  bottom: 20px;
  left: 20px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  pointer-events: none; /* re-enabled per interactive child below */
}
.dive-explore-btn {
  pointer-events: auto;
  padding: 6px 10px;
  color: var(--text-2);
  background: var(--overlay-bg-thin);
  backdrop-filter: var(--overlay-blur);
  border: var(--border) solid var(--line);
  border-radius: var(--radius);
  text-transform: uppercase;
  cursor: pointer;
}
.dive-explore-btn:hover { color: var(--text-1); border-color: var(--line-strong); }
.dive-hud--exploring .dive-explore-btn { color: var(--accent); border-color: var(--accent); }
.dive-hud-control-slot:not(:empty) { pointer-events: auto; }

/* ---- bottom-right: mode hint + the two permanent destinations ---- */
.dive-hud-meta {
  position: absolute;
  bottom: 20px;
  right: 20px;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.dive-hud-hint { color: var(--text-3); }

/* "← HOME" and "PORTAL →" are the same object — a permanent destination
   in the HUD — so they share one rule rather than one rule plus a copy of
   it that happens to match today. */
.dive-hud-dest {
  pointer-events: auto;
  padding: 4px 8px;
  color: var(--text-2);
  border: var(--border) solid var(--line-bright);
  border-radius: var(--radius);
  text-transform: uppercase;
}
.dive-hud-dest:hover { color: var(--text-1); }

/* ============================================================
   Ink flip: ink flips on light grounds. No station currently declares
   `light: true` in js/stations/index.js, but the machinery stays here
   for whichever station needs a light ground next. The dive/entry
   opacity math is unaffected; only colour changes.
   ============================================================ */
.dive-hud--light .dive-hud-title,
.dive-hud--light .dive-hud-kind,
.dive-hud--light .dive-explore-btn,
.dive-hud--light .dive-hud-dest {
  color: #101213;
}
.dive-hud--light .dive-hud-kind,
.dive-hud--light .dive-explore-btn { border-color: rgba(16, 18, 19, 0.35); }
/* --text-3 (#6b7073) is legible on both grounds and does not flip —
   .dive-hud-caption / .dive-hud-hint are untouched here. */

/* ============================================================
   SLIDER CARD — the one control a station may have. Built by
   shell/slider-card.js from whatever the
   station's controls() returned; only 01 (MORPH), 02 (PHASE) and
   05 (STAGE) have one, and the corner is simply empty otherwise.

   The range input is left NATIVE with accent-color — this page
   does not load controls.css, and re-deriving
   that sheet's five-pseudo-element slider here would be a second
   definition of a thing the design system already owns.
   ============================================================ */
.dive-slider-card {
  width: 260px;
  padding: var(--sp-3);
  background: var(--overlay-bg-thin);
  backdrop-filter: var(--overlay-blur);
  border: var(--border) solid var(--line);
  border-radius: var(--radius);
}
.dive-slider-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}
.dive-slider-label {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  color: var(--text-2);
  text-transform: uppercase;
}
/* 11px, like .dive-hud-caption: this line's own number for the live
   value, one step above --fs-hint by design. */
.dive-slider-value {
  font-size: 11px;
  color: var(--accent);
}
.dive-slider-input {
  display: block;
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}

/* ============================================================
   STATION 01 (uhi) — the one DOM station on this page. It opens the
   sequence and sits on a dark ground (#101213, ink #e9e7e2);
   `light: false` in the registry, so the HUD ink-flip machinery
   above is unused until another station needs a light ground.

   Geometry only; every colour the dendrogram itself carries is
   data (impact class, hover lineage) and is set as an attribute
   by js/stations/uhi.js.
   ============================================================ */
.dive-uhi {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding: 56px 20px 20px; /* clears the HUD's top-left identity block */
  background: #101213;
  color: #e9e7e2;
}
.dive-uhi-chart {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  overflow: visible;
}
.dive-uhi-link {
  fill: none;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  stroke-miterlimit: 8;
  transition: stroke 0.15s ease;
}
/* An invisible fat stroke over each 2px link, so hovering a branch does
   not require pixel accuracy. */
.dive-uhi-link-hit {
  fill: none;
  stroke: transparent;
  stroke-width: 18px;
  pointer-events: stroke;
  cursor: pointer;
}
.dive-uhi-dot {
  stroke: #101213;
  stroke-width: 1.25;
  cursor: pointer;
  transition: fill 0.15s ease;
}
.dive-uhi-label {
  font-size: 26px;
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
  /* Halo in the ground colour, so a label crossing a branch stays
     readable without a box behind it. */
  paint-order: stroke fill;
  stroke: #101213;
  stroke-width: 4px;
  stroke-linejoin: round;
  transition: fill 0.15s ease;
}
.dive-uhi-root-circle { fill: #e9e7e2; }
.dive-uhi-root-label {
  fill: #101213;
  font-size: 38px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
}
.dive-uhi-legend {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2) var(--sp-4);
  max-width: 900px;
  font-size: 11px;
}
.dive-uhi-legend-caption {
  width: 100%;
  text-align: center;
  color: #a29d9a;
}
.dive-uhi-legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.dive-uhi-legend-swatch {
  width: 22px;
  height: 3px;
}
