/* ==========================================================================
   ABOUT — the route strip map (replaced the night drive, 2026-07-02)
   A static survey strip: winding road, real street-layer medallions at each
   stop, milestone ticks in the margins, branch spurs with marginalia.
   All geometry is server-rendered; the only scripted behaviour is the
   IntersectionObserver "current stop" emphasis in about.js.
   ========================================================================== */

.about {
  --strip-w: min(480px, calc(100vw - 56px));
  padding: 96px 0 72px;
}

/* --------------------------------------------------------------------------
   Recruiter card
   -------------------------------------------------------------------------- */

.recruiter {
  max-width: 660px;
  margin: 48px auto 40px;
  padding: 30px 34px 34px;
  text-align: center;
}

.recruiter h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-display-about);
  line-height: 1.05;
  letter-spacing: var(--ls-display);
  color: var(--paper);
  margin: 10px 0 12px;
}

.recruiter-pitch {
  font-size: var(--fs-prose);
  line-height: var(--lh-prose);
  color: var(--paper);
  max-width: 56ch;
  margin: 0 auto 18px;
}

.strip-title {
  text-align: center;
  color: var(--label);
  margin: 46px 0 26px;
}

/* --------------------------------------------------------------------------
   Strip grid: legs and stops share one column template so the road,
   medallions and marginalia all align to the same centred strip
   -------------------------------------------------------------------------- */

.leg,
.stop {
  display: grid;
  grid-template-columns: minmax(20px, 1fr) var(--strip-w) minmax(20px, 1fr);
}

.leg { position: relative; }

.leg > svg {
  grid-column: 2;
  display: block;
  width: 100%;
  height: auto;
}

/* --------------------------------------------------------------------------
   Road linework (cartographic casing + surface, as the night drive drew it)
   -------------------------------------------------------------------------- */

.road-c {
  fill: none;
  stroke: #070c0a;                /* casing: a cut darker than the ground */
  stroke-width: 7;
  stroke-linecap: round;
}

.road-s {
  fill: none;
  stroke: var(--tan);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-opacity: 0.92;
}

/* the strip's bounding rules — the plate frame of the road-strip genre */
.strip-rule {
  stroke: rgba(var(--tan-rgb), 0.18);
  stroke-width: 1;
}

/* duration rail: a margin bracket for events that took time (`until:`) */
.span-rail,
.span-cap {
  stroke: var(--tan);
  stroke-width: 1.4;
  stroke-dasharray: 2 6;
  stroke-opacity: 0.6;
  transition: stroke 200ms ease;
}

.span-cap { stroke-dasharray: none; }

.spur {
  fill: none;
  stroke: var(--tan);
  stroke-width: 1.6;
  stroke-dasharray: 6 5;
  stroke-opacity: 0.75;
  transition: stroke 200ms ease, stroke-opacity 200ms ease;
}

.junction,
.spur-end {
  fill: var(--benthic);
  stroke: var(--tan);
  stroke-width: 1.5;
  transition: stroke 200ms ease;
}

.spur-g.lit .spur { stroke: var(--flag); stroke-opacity: 1; }
.spur-g.lit .junction,
.spur-g.lit .spur-end,
.spur-g.lit .span-rail,
.spur-g.lit .span-cap { stroke: var(--flag); }

/* --------------------------------------------------------------------------
   Marginalia: milestone labels and branch notes.
   Desktop: in the gutters beside the strip. Mobile: tucked inside its edges
   on a benthic backing plate (labels knock out linework, like the captions).
   -------------------------------------------------------------------------- */

.ev {
  position: absolute;
  top: var(--top);            /* anchored just below its spur terminus */
  font-family: var(--font-mono);
  max-width: 250px;
}

.ev-left  { right: calc(50% + var(--strip-w) / 2 + 18px); text-align: right; }
.ev-right { left:  calc(50% + var(--strip-w) / 2 + 18px); text-align: left; }

.ev .ev-year {
  display: block;
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-label);
  color: var(--fir);
}

.ev .ev-label {
  display: block;
  font-size: var(--fs-meta);
  letter-spacing: 0.06em;
  text-transform: var(--tt-label);
  color: var(--tan);
  margin-top: 2px;
  transition: color 200ms ease;
}

.ev .ev-note {
  display: block;
  font-size: var(--fs-meta);
  line-height: 1.5;
  color: var(--fir);
  margin-top: 4px;
}

.ev:hover .ev-label,
.ev.lit .ev-label { color: var(--flag); }

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

/* Links Ben writes into the About prose ([text](url) in content/about.md,
   rendered by app.py's `links` filter): quiet tan underline, flag on hover */
.recruiter-pitch a,
.stop-body a,
.ev-note a,
.route-afterword a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: rgba(var(--tan-rgb), 0.6);
  text-underline-offset: 3px;
  transition: color 140ms ease;
}

.recruiter-pitch a:hover,
.stop-body a:hover,
.ev-note a:hover,
.route-afterword a:hover { color: var(--flag); }

/* --------------------------------------------------------------------------
   Stops: medallion plate + chapter card on alternating sides
   -------------------------------------------------------------------------- */

.stop { position: relative; align-items: center; }

.stop-plate {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  margin: 0;
}

.stop-plate > svg {
  display: block;
  width: 100%;
  height: auto;
}

.med-ring {
  fill: none;
  stroke: rgba(var(--tan-rgb), 0.5);
  stroke-width: 1.6;
}

.med-ring-in {
  fill: none;
  stroke: rgba(var(--tan-rgb), 0.16);
  stroke-width: 1;
}

/* Resting dim: only when JS is present to brighten the current stop; without
   JS (or with reduced motion) streets stay comfortably lit and the overlays
   are off. Q1b's law, measured twice (testing/reports/2026-07-03-ipad-traces
   .md + the 2026-07-04 ablation round): on iPadOS Safari ANY style change
   inside the medallion SVG — masked or not; the old streets fade, an unmasked
   gradient circle, even the ring's stroke flip — re-rasterizes the whole
   masked medallion (~110ms p95). So the warm/cool game lives entirely OUTSIDE
   the SVG: .med-veil and .med-ring-hot are HTML overlays on .stop-plate whose
   opacity transitions Safari runs on the compositor; the SVG is never
   restyled after load. Geometry: the medallion circle is cx 240 cy 210 r 150
   in the 480x500 viewBox → left 18.75% / top 12% / width 62.5% / height 60%
   (a square, so the radial-gradient's closest-side is the SVG gradient's
   r=150; the 62% solid stop mirrors the mask's fade profile). Arithmetic over
   the flat benthic ground: veil 0.55 over streets 1 = the old resting 0.45;
   veil 0.05 = the old current 0.95. */
.med-streets { opacity: 0.82; }
.js .med-streets { opacity: 1; }

.med-veil,
.med-ring-hot {
  position: absolute;
  left: 18.75%;
  top: 12%;
  width: 62.5%;
  height: 60%;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}

.med-veil {
  background: radial-gradient(closest-side, var(--benthic) 62%, transparent);
}

.med-ring-hot {
  box-sizing: border-box;
  border: 1.5px solid var(--flag);
}

.js .med-veil { opacity: 0.55; transition: opacity 900ms ease; }
.js .stop.current .med-veil { opacity: 0.05; }
.js .med-ring-hot { transition: opacity 600ms ease; }
.js .stop.current .med-ring-hot { opacity: 1; }

/* Dev ablation (?abl=veil,ring,all on /about — TESTING.md §2): pins a named
   moving part so the cost of the others can be measured on-device. Inert
   without the query param (the template only sets these classes then). */
.abl-veil .med-veil { opacity: 0.55 !important; transition: none !important; }
.abl-ring .med-ring-hot { opacity: 0 !important; transition: none !important; }

.stop-caption {
  position: absolute;
  top: 73.5%;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  background: var(--benthic);     /* label plate knocks out the road line */
  padding: 6px 14px 7px;
  font-family: var(--font-mono);
  /* Single line whenever it fits (max-content keeps the abs-centred box
     from wrapping at half the plate width); a theme font wide enough to
     exceed the plate wraps to centred lines instead of overflowing the
     viewport (Martian Mono at 390px, the 2026-07-05 theme session). The
     .stop-inset hiding below 380px still trims the narrowest cases. */
  width: max-content;
  max-width: 100%;
}

.stop-no {
  display: block;
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-kicker);
  text-transform: var(--tt-label);
  color: var(--fir);
  transition: color 400ms ease;
}

.js .stop.current .stop-no { color: var(--flag); }

.stop-name {
  display: block;
  font-size: var(--fs-prose);
  letter-spacing: var(--ls-snug);
  text-transform: var(--tt-label);
  color: var(--paper);
  margin: 3px 0 2px;
}

.stop-meta {
  display: block;
  font-size: var(--fs-furniture);
  letter-spacing: var(--ls-meta);
  color: var(--label);
}

.stop-card {
  grid-row: 1;
  align-self: center;
  max-width: 380px;
  padding: 22px 26px 24px;
  margin: 0 12px;
}

.card-left  .stop-card { grid-column: 1; justify-self: end; }
.card-right .stop-card { grid-column: 3; justify-self: start; }

.stop-card h2 {
  font-family: var(--font-mono);
  font-size: var(--fs-lead);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: var(--tt-label);
  color: var(--paper);
  margin: 8px 0 10px;
}

.stop-body {
  font-size: var(--fs-note);
  line-height: 1.62;
  color: var(--paper);
}

/* --------------------------------------------------------------------------
   Route end: repeated CTA + the long-form afterword
   -------------------------------------------------------------------------- */

.route-end {
  max-width: 620px;
  margin: 30px auto 0;
  padding: 0 24px;
  text-align: center;
}

.route-end .kicker { margin-bottom: 20px; }
.route-end .cta { margin-bottom: 30px; }

.route-afterword {
  font-size: var(--fs-prose);
  line-height: 1.65;
  color: var(--paper);
  text-align: center;
  max-width: 58ch;
  margin: 0 auto 16px;
}

.return-link {
  display: inline-block;
  margin-top: 26px;
  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(--fir);
}

.return-link:hover { color: var(--flag); }

/* --------------------------------------------------------------------------
   Mobile: single column; cards drop below their medallions; the road passes
   behind the card via a connector line (the panel knocks out its middle)
   -------------------------------------------------------------------------- */

@media (max-width: 959px) {
  .stop { grid-template-columns: 1fr; }

  .stop-plate {
    grid-column: 1;
    grid-row: 1;
    width: var(--strip-w);
    justify-self: center;
  }

  .stop-card,
  .card-left .stop-card,
  .card-right .stop-card {
    grid-column: 1;
    grid-row: 2;
    justify-self: center;
    position: relative;
    margin: 6px auto 26px;
    max-width: min(480px, calc(100vw - 48px));
  }

  /* road continuity behind the card */
  .stop-card::after {
    content: "";
    position: absolute;
    left: 50%;
    top: -30px;
    bottom: -30px;
    width: 2.2px;
    transform: translateX(-50%);
    background: rgba(var(--tan-rgb), 0.5);
    z-index: -1;
  }

  .stop:last-of-type .stop-card::after { display: none; }

  .leg { grid-template-columns: 1fr; }
  .leg > svg {
    grid-column: 1;
    width: var(--strip-w);
    justify-self: center;
  }

  .ev {
    /* 2 x (10px inset + 41vw) stays under 100vw at any phone width, so
       opposite-side notes can never meet in the middle */
    max-width: min(210px, 41vw);
    background: rgba(var(--benthic-rgb), 0.82);
    padding: 4px 7px;
  }

  .ev-left  { right: auto; left: 10px; text-align: left; }
  .ev-right { left: auto; right: 10px; text-align: right; }
}

/* Ultra-narrow phones: margin notes step down to 11px (map-furniture floor
   is 10px) so real rendered heights stay inside the layout pass's estimates.
   The nowrap stop caption also sheds its inset-diameter segment: the longest
   coord + year + inset line (~350px) is wider than a 320px viewport. */
@media (max-width: 379px) {
  .ev .ev-label,
  .ev .ev-note { font-size: var(--fs-ui); }
  .stop-inset { display: none; }
}

/* --------------------------------------------------------------------------
   Reduced motion: no transitions, no dim/brighten game — streets rest lit
   (about.js also bails entirely, so .current is never applied)
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .js .med-streets { opacity: 0.82; }
  .js .med-veil { opacity: 0; transition: none; }
  .med-ring-hot,
  .stop-no,
  .spur,
  .junction,
  .spur-end,
  .span-rail,
  .span-cap,
  .ev .ev-label,
  .recruiter-pitch a,
  .stop-body a,
  .ev-note a,
  .route-afterword a { transition: none; }
}
