/* ==========================================================================
   SURVEY — night survey terrain, real data
   ========================================================================== */

/* The theme surface. Every dial the theme editor (tools/themer) writes lives
   in this :root block; static/css/theme.css (generated, optional) overrides
   these same names and nothing else. Page CSS consumes tokens, never
   redefines them. */
:root {
  --benthic: #0D1412;   /* ground / page background */
  --strata: #131C19;    /* raised panels */
  --tan: #A89A7E;       /* contour lines */
  --paper: #E9E4D6;     /* headlines, body */
  --fir: #6E7B72;       /* secondary text, ticks */
  --label: #8C988E;     /* border furniture text — slightly brighter fir */
  --flag: #FF6B35;      /* the single accent */

  /* The same inks as R,G,B triplets for the alpha washes (panel borders,
     backings, glows). Each pair moves in lockstep — the theme editor
     derives the triplet from the hex; hand edits must keep them matched. */
  --benthic-rgb: 13, 20, 18;
  --strata-rgb: 19, 28, 25;
  --tan-rgb: 168, 154, 126;
  --paper-rgb: 233, 228, 214;
  --fir-rgb: 110, 123, 114;
  --label-rgb: 140, 152, 142;
  --flag-rgb: 255, 107, 53;

  --font-display: "Zodiak", Georgia, serif;
  --font-body: "Supreme", "Helvetica Neue", sans-serif;
  --font-mono: "Fragment Mono", "Courier New", monospace;

  /* Type scale — named for their primary role; several are shared across
     roles of the same size (the schema in tools/themer lists every use).
     --fs-furniture is the 10px map-furniture floor (DESIGN.md §4 — do not
     go below); --fs-micro is the hero meta line's sanctioned exception. */
  --fs-micro: 9px;
  --fs-furniture: 10px;
  --fs-ui: 11px;
  --fs-meta: 12px;
  --fs-small: 13px;
  --fs-note: 14px;
  --fs-prose: 15px;
  --fs-role: 15.5px;    /* hero role line; 14.5px under 720px (media block) */
  --fs-body: 16px;
  --fs-lead: 17px;
  --fs-pull: 19px;
  --fs-display-hero: clamp(2.5rem, 5.2vw, 3.7rem);
  --fs-display-stub: clamp(2.2rem, 5vw, 3.4rem);
  --fs-display-page: clamp(2.2rem, 5vw, 3.2rem);
  --fs-display-post: clamp(2rem, 5vw, 2.9rem);
  --fs-display-about: clamp(2rem, 4.2vw, 2.9rem);

  /* Letter-spacing roles (a few true one-offs stay literal in page CSS) */
  --ls-display: -0.015em;
  --ls-kicker: 0.22em;
  --ls-wide: 0.18em;
  --ls-cta: 0.16em;
  --ls-label: 0.14em;
  --ls-snug: 0.12em;
  --ls-meta: 0.1em;
  --ls-tight: 0.08em;

  /* Case + reading rhythm */
  --tt-label: uppercase;  /* every mono label/caption; the editor's case toggle */
  --lh-body: 1.55;
  --lh-prose: 1.6;
  --lh-reading: 1.75;

  /* Hero dials */
  --torch-glow: 0.45;   /* torch light-pool strength — Ben's pick, 2026-07-05 */
  --band-hot: 0.13;     /* active elevation-band fill (DESIGN.md §10.4) */

  --frame-inset: 14px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { height: 100%; }

body {
  height: 100%;
  background: var(--benthic);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

::selection { background: var(--flag); color: var(--benthic); }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--flag);
  outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   The sheet (landing hero)
   -------------------------------------------------------------------------- */

.sheet {
  position: relative;
  height: 100dvh;
  min-height: 540px;
  overflow: hidden;
  cursor: crosshair;
}

.sheet a { cursor: pointer; }

/* Touch devices drag the station marker directly: keep single-finger gestures
   on the sheet for that (two-finger pinch zoom still works). */
@media (pointer: coarse) {
  .sheet { touch-action: pinch-zoom; }
}

/* Terrain layers */
.terrain,
.terrain .terrain-fallback,
.terrain svg.scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.terrain { transition: opacity 350ms ease; }
.sheet.relocating .terrain { opacity: 0; }

.terrain .terrain-fallback { object-fit: cover; opacity: 0.9; }
.sheet.live .terrain-fallback { display: none; }

/* Elevation bands: quiet hypsometric shading; the band under the cursor (and
   every other region at the same elevation) lifts toward the accent. */
svg.scene .band { transition: fill-opacity 300ms ease, fill 300ms ease; }
svg.scene .band.active { fill: var(--flag); fill-opacity: var(--band-hot, 0.13); }

/* Contour lines; the pair bounding the active band picks up the accent */
svg.scene .c { transition: stroke 200ms ease, stroke-opacity 200ms ease; }
svg.scene .c.lit { stroke: var(--flag); stroke-opacity: 0.95; }

/* Streets hide under the torch mask; in static mode they show plainly.
   streets-rest was the interim Q1 fix (streets resting at the poster's
   0.45, no moving reveal) — superseded as the Apple-WebKit touch default
   by the window mode below (LEDGER Q6), kept forceable via ?reveal=rest
   for A/B and measurement. */
.sheet.static svg.scene .streets { opacity: 0.45; }
.sheet.streets-rest svg.scene .streets { opacity: 0.45; }

/* The street window — the Apple-WebKit touch default (LEDGER Q6, closed
   2026-07-05: iPad-measured pass + Ben's feel sign-off; ?reveal=window
   forces it anywhere). An HTML porthole OUTSIDE the scene SVGs:
   .torch-win is a circular clip moved by transform, .torch-streets the
   full-crop streets image counter-translated inside it. The radial mask is
   STATIC (rasterized once with the layer) and mirrors the SVG torch-grad's
   1 / 0.6@60% / 0 falloff. Scene streets rest fully hidden — desktop
   parity per Ben (2026-07-05, after the measured round): the window is
   the only street rendering, exactly like the desktop beam. The resting
   opacity is a per-load style, not a per-frame write, so this value is
   freely tunable without re-measuring. */
.sheet.streets-window svg.scene .streets { opacity: 0; }

.torch-overlay {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.torch-win {
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 50%;
  overflow: hidden;
  -webkit-mask-image: radial-gradient(closest-side,
    #000 0%, rgba(0, 0, 0, 0.6) 60%, transparent 100%);
  mask-image: radial-gradient(closest-side,
    #000 0%, rgba(0, 0, 0, 0.6) 60%, transparent 100%);
  will-change: transform;
}

/* The light pool: a warm wash on the ground inside the beam, under the
   streets (::before paints below the img), so the window reads as torch
   LIGHT, not just streets appearing. Same grammar as the hero lamp
   (flag-to-tan radial, a sanctioned orange use); the pool rides the
   window and shares its mask, so light and streets fade out together.
   --torch-glow scales it 0..1; the baked 0.45 is Ben's pick from the
   live-dial round (2026-07-05). ?glow=<0..1> previews any other value,
   and this custom property is a planned theme-editor dial. */
.torch-win::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(closest-side,
    rgba(var(--flag-rgb), 0.20) 0%,
    rgba(var(--tan-rgb), 0.12) 45%,
    rgba(var(--tan-rgb), 0) 100%);
  opacity: var(--torch-glow, 0.45);
}

.torch-streets {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
}

.sheet.static .torch-overlay { display: none; }

/* Station marker — the visible focal point on touch devices (created by
   survey.js only in drift mode). Tan instrument furniture, not an accent. */
svg.scene .station {
  stroke: var(--tan);
  stroke-width: 1.5;
  fill: none;
  opacity: 0.9;
  pointer-events: none;
}

svg.scene .station .station-dot {
  fill: var(--paper);
  stroke: none;
}

.sheet.static svg.scene .station { display: none; }

/* Neatline — the quadrangle border */
.neatline {
  position: absolute;
  inset: var(--frame-inset);
  border: 1px solid rgba(var(--tan-rgb), 0.30);
  pointer-events: none;
}

.neatline::before {
  content: "";
  position: absolute;
  inset: 3px;
  border: 1px solid rgba(var(--tan-rgb), 0.12);
}

/* Graticule ticks along the top edge */
.graticule {
  position: absolute;
  top: var(--frame-inset);
  left: var(--frame-inset);
  right: var(--frame-inset);
  height: 10px;
  pointer-events: none;
  background: repeating-linear-gradient(
    90deg,
    rgba(var(--fir-rgb), 0.55) 0 1px,
    transparent 1px 48px
  );
  background-size: auto 6px;
  background-repeat: no-repeat;
}

.graticule-label {
  position: absolute;
  top: 9px;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-tight);
  color: var(--label);
}

/* Plate mark, top-left */
.plate-mark {
  position: absolute;
  top: calc(var(--frame-inset) + 38px);
  left: calc(var(--frame-inset) + 22px);
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-wide);
  text-transform: var(--tt-label);
  color: var(--label);
}

/* Nav, top-right — kept clear of the graticule labels above. The faint panel
   keeps the labels readable where a heavy contour passes beneath. */
.map-nav {
  position: absolute;
  top: calc(var(--frame-inset) + 34px);
  right: calc(var(--frame-inset) + 22px);
  display: flex;
  /* wrap + max-width: the label row must survive ANY editor-pickable font
     and the conditional fifth item (05 Participate) — links may never
     escape the panel, the panel never the neatline (2026-07-06, caught by
     Ben on the Fold at ~390px with Martian Mono) */
  flex-wrap: wrap;
  max-width: calc(100vw - 2 * var(--frame-inset) - 44px);
  gap: 2px 30px;
  padding: 8px 20px;
  background: rgba(var(--benthic-rgb), 0.66);
  border: 1px solid rgba(var(--tan-rgb), 0.45);
}

.map-nav::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid rgba(var(--tan-rgb), 0.16);
  pointer-events: none;
}

.map-nav a {
  font-family: var(--font-mono);
  font-size: var(--fs-ui);
  letter-spacing: var(--ls-label);
  text-transform: var(--tt-label);
  text-decoration: none;
  color: var(--paper);
  padding: 6px 2px;
  transition: color 140ms ease;
}

.map-nav a span {
  color: var(--fir);
  margin-right: 7px;
  transition: color 140ms ease;
}

.map-nav a:hover,
.map-nav a:hover span {
  color: var(--flag);
}

/* Title block, bottom-left — like a real quadrangle sheet */
.title-block {
  position: absolute;
  left: calc(var(--frame-inset) + 26px);
  bottom: calc(var(--frame-inset) + 26px);
  max-width: 540px;
  padding: 26px 30px 24px;
  background: rgba(var(--strata-rgb), 0.88);
  border: 1px solid rgba(var(--tan-rgb), 0.45);
}

.title-block::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid rgba(var(--tan-rgb), 0.16);
  pointer-events: none;
}

.tb-kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-kicker);
  text-transform: var(--tt-label);
  color: var(--fir);
  margin-bottom: 14px;
}

/* The sheet selector, disguised as part of the kicker line */
#loc-select {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 1px dotted rgba(var(--tan-rgb), 0.55);
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-kicker);
  text-transform: var(--tt-label);
  color: var(--tan);
  cursor: pointer;
  padding: 0 2px 1px;
  transition: color 140ms ease, border-color 140ms ease;
}

#loc-select:hover {
  color: var(--flag);
  border-bottom-color: var(--flag);
}

#loc-select option {
  background: var(--strata);
  color: var(--paper);
}

.title-block h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-display-hero);
  line-height: 1.02;
  letter-spacing: var(--ls-display);
  color: var(--paper);
  margin-bottom: 12px;
}

.tb-role {
  font-size: var(--fs-role);
  line-height: var(--lh-prose);
  color: rgba(var(--paper-rgb), 0.78);
  max-width: 44ch;
  margin-bottom: 22px;
}

.tb-foot {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

.tb-meta {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: var(--tt-label);
  color: var(--fir);
}

/* The one orange thing */
.cta {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-ui);
  letter-spacing: var(--ls-cta);
  text-transform: var(--tt-label);
  text-decoration: none;
  color: var(--benthic);
  background: var(--flag);
  padding: 11px 20px 10px;
  transition: transform 140ms ease, background 140ms ease;
}

.cta::after {
  content: " →";
  letter-spacing: 0;
}

.cta:hover {
  background: #FF8255;
  transform: translateY(-1px);
}

/* Scale bar, bottom-right — computed from the real bbox by survey.js */
.scalebar {
  position: absolute;
  right: calc(var(--frame-inset) + 24px);
  bottom: calc(var(--frame-inset) + 22px);
  width: 200px;
  pointer-events: none;
}

.scalebar-caption {
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-label);
  text-transform: var(--tt-label);
  color: var(--label);
  margin-bottom: 6px;
  text-align: right;
}

.scalebar-track {
  display: flex;
  height: 5px;
  border: 1px solid rgba(var(--tan-rgb), 0.7);
  margin-left: auto;
}

.scalebar-track span { flex: 1; }
.scalebar-track span:nth-child(odd) { background: rgba(var(--tan-rgb), 0.7); }

.scalebar-labels {
  display: flex;
  justify-content: space-between;
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-tight);
  color: var(--label);
  margin-top: 4px;
}

/* Live coordinate + elevation readout near the cursor */
.coords {
  position: fixed;
  top: 0;
  left: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-meta);
  color: var(--tan);
  background: rgba(var(--benthic-rgb), 0.72);
  border: 1px solid rgba(var(--tan-rgb), 0.3);
  padding: 3px 8px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 300ms ease;
  will-change: transform;
}

.coords.visible { opacity: 1; }

/* Source credit, bottom-centre inside the neatline */
.attribution {
  position: absolute;
  bottom: calc(var(--frame-inset) + 6px);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-meta);
  color: rgba(var(--label-rgb), 0.9);
  pointer-events: none;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Load reveal
   -------------------------------------------------------------------------- */

@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

.title-block { animation: rise-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.15s backwards; }
.map-nav     { animation: rise-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.30s backwards; }
.scalebar    { animation: rise-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.45s backwards; }

@media (prefers-reduced-motion: reduce) {
  .title-block, .map-nav, .scalebar { animation: none; }
  .coords { display: none; }
  .terrain { transition: none; }
  svg.scene .band, svg.scene .c { transition: none; }
}

/* --------------------------------------------------------------------------
   Stub pages
   -------------------------------------------------------------------------- */

.stub-page {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 14px;
  padding: 48px clamp(24px, 8vw, 120px);
}

.stub-page h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-display-stub);
  line-height: 1.05;
}

.stub-note { color: var(--fir); margin-bottom: 14px; }

/* --------------------------------------------------------------------------
   Mobile
   -------------------------------------------------------------------------- */

@media (max-width: 720px) {
  :root { --frame-inset: 9px; --fs-role: 14.5px; }

  .plate-mark { display: none; }

  .map-nav {
    left: calc(var(--frame-inset) + 14px);
    right: calc(var(--frame-inset) + 14px);
    /* pinned both sides: the pins bound the panel, the desktop cap would
       only fall short of the right pin */
    max-width: none;
    justify-content: space-between;
    gap: 2px 8px;
  }

  .map-nav a { font-size: var(--fs-furniture); letter-spacing: var(--ls-meta); }
  .map-nav a span { display: none; }

  .graticule-label { display: none; }

  .title-block {
    left: calc(var(--frame-inset) + 12px);
    right: calc(var(--frame-inset) + 12px);
    bottom: calc(var(--frame-inset) + 12px);
    max-width: none;
    padding: 22px 22px 20px;
  }

  .scalebar, .coords, .attribution { display: none; }
}
