/* The flight (js/flight.js): one WebGL canvas behind Headwaters, Descent and
   Valley. The sections are wrapped in .flight; .flight-view is a screen-tall
   sticky layer at its top (the first section is pulled up over it with a
   negative margin), so the canvas scrolls in with Headwaters, stays put through
   the sections and scrolls out with the last one. (Until 2026-10-05 the view
   itself had the negative margin; a sticky box is kept inside its parent by
   its margin box, so the canvas overhung the flight by a screen and covered the
   first screen of the section after it.) With paper: 'clear' the sky is
   transparent, so the page background shows through around the terrain. */

/* .flight itself stays unpositioned, so the sections' offsetTop is still
   measured from the page. */

.flight-view {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  pointer-events: none;
}

.flight-view + .flight-leg { margin-top: -100vh; }

.flight .flyover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 1.2s ease;
}

.flight .flyover.is-ready { opacity: 1; }

/* The flight's sections sit over the sticky view but are mostly empty: let the
   pointer through to the journey key's nodes, except on what's really there. */
.journey.flight-leg, .flight-leg .journey-stage, .flight-leg .journey-media { pointer-events: none; }
.flight-leg .journey-stage .frag, .flight-leg .journey-stage a, .flight-leg .journey-stage button { pointer-events: auto; }

/* Keep the long pinned sections on phones too (site.css collapses journey
   sections into a flowing column below 640px). */
@media (max-width: 640px) {
  .journey.flight-leg { height: calc(var(--length, 1) * 100vh); min-height: 0; }

  .flight-leg .journey-stage {
    position: sticky;
    height: 100vh;
    min-height: 0;
    overflow: hidden;
    padding: 0;
    display: block;
  }
}

/* Reduced motion: one still per section, one screen tall each. */
@media (prefers-reduced-motion: reduce) {
  .journey.flight-leg { height: 100vh; }
  .flight .flyover { transition: none; }
}

/* The journey key (js/journey-key.js): a strip of the background map on the
   left with the water's route, lit behind you, and a drop where you are.
   Each stop is a node: pointing at it grows it and shows the place's name;
   clicking flies there. Colours are the flight's graded ones (ink #f0ece4,
   water blue). Only the nodes take the pointer; the rest lets it through. */
.journey-key {
  position: absolute;
  left: clamp(10px, 2.4vw, 36px);
  top: 50%;
  height: min(66vh, 600px);
  aspect-ratio: 330 / 1189;
  transform: translateY(-50%);
  opacity: var(--jk, 0);
  pointer-events: none;
}
.journey-key:not(.is-ready) { display: none; }
.journey-key svg {
  width: 100%; height: 100%; display: block; overflow: visible; background: #0d1117;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 5%, #000 95%, transparent), linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to bottom, transparent, #000 5%, #000 95%, transparent), linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
  mask-composite: intersect;
}
.journey-key image { opacity: 0.9; }
.journey-key svg.jk-top { position: absolute; inset: 0; background: none; -webkit-mask-image: none; mask-image: none; pointer-events: none; }
/* the water, under the route: a thin river to the intake (a small ring), the Aqueduct below as a canal's double rule */
.journey-key .jk-water { fill: none; stroke: rgba(143, 180, 255, 0.7); stroke-width: 1.3px; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.journey-key .jk-creek { stroke-width: 0.9px; stroke: rgba(143, 180, 255, 0.5); }
.journey-key .jk-lower { stroke-width: 0.9px; stroke: rgba(143, 180, 255, 0.4); }
.journey-key .jk-laRiver { stroke-width: 1px; stroke: rgba(143, 180, 255, 0.5); }   /* the LA River, thin like the Lower Owens */
.journey-key .jk-canal { fill: none; stroke: rgba(143, 180, 255, 0.75); stroke-width: 3.6px; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.journey-key .jk-canal-in { fill: none; stroke: #121822; stroke-width: 1.4px; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.journey-key .jk-gate { fill: #0d1117; stroke: rgba(143, 180, 255, 0.9); stroke-width: 1.4px; vector-effect: non-scaling-stroke; }
/* our route: dotted beside the water, the dots behind the drop lit */
.journey-key .jk-ahead { fill: none; stroke: rgba(240, 236, 228, 0.55); stroke-width: 2.2px; stroke-linecap: round; stroke-dasharray: 0 5.5; vector-effect: non-scaling-stroke; }
.journey-key .jk-lit { fill: none; stroke: #f0ece4; stroke-width: 2.8px; stroke-linecap: round; stroke-dasharray: 0 5.5; vector-effect: non-scaling-stroke; }
/* the cloud on top: back to the start */
.jk-cloud {
  position: absolute; left: 50%; bottom: calc(100% - 4%); transform: translateX(-50%);
  width: 48%; padding: 0; border: 0; background: none; cursor: pointer; pointer-events: none;
  transition: transform 0.2s ease, filter 0.2s ease;
}
.journey-key.is-live .jk-cloud { pointer-events: auto; }
.jk-cloud img { display: block; width: 100%; height: auto; }
.jk-cloud .jk-name { left: calc(100% + 2px); }
.jk-cloud:hover, .jk-cloud:focus-visible { transform: translateX(-50%) translateY(-2px); filter: brightness(1.15); }
.jk-cloud:hover .jk-name, .jk-cloud:focus-visible .jk-name { opacity: 1; transform: translate(0, -50%); }
.jk-cloud:focus { outline: none; }
.jk-cloud:focus-visible img { outline: 1px solid rgba(143, 180, 255, 0.8); outline-offset: 2px; }
/* the foot: the user's wave, to the last stop (the ocean). A little smaller than the cloud and off to the side, clear
   of the strip's end, so the route's last stretch and the ocean stop show (the user, 2026-10-06); it reaches ~108.6%
   of the key's height (180x128 at 41% of a 330/1189 strip, from 100.5%) */
.jk-foot {
  position: absolute; left: 17%; top: 98%; transform: translateX(-50%);
  width: 41%; padding: 0; border: 0; background: none; cursor: pointer; pointer-events: none;
  transition: transform 0.2s ease, filter 0.2s ease;
}
.journey-key.is-live .jk-foot { pointer-events: auto; }
.jk-foot img { display: block; width: 100%; height: auto; }
.jk-foot .jk-name { left: calc(100% + 2px); }
.jk-foot:hover, .jk-foot:focus-visible { transform: translateX(-50%) translateY(2px); filter: brightness(1.15); }
.jk-foot:hover .jk-name, .jk-foot:focus-visible .jk-name { opacity: 1; transform: translate(0, -50%); }
.jk-foot:focus { outline: none; }
.jk-foot:focus-visible img { outline: 1px solid rgba(143, 180, 255, 0.8); outline-offset: 2px; }
.journey-key .jk-drop-shape { transform: scale(1.5); transform-box: view-box; }
.journey-key .jk-drop-shape path:first-child { fill: #8fb4ff; stroke: #0d1117; stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.journey-key .jk-glint { fill: none; stroke: rgba(255, 255, 255, 0.85); stroke-width: 1.4px; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.journey-key.is-resting .jk-drop-shape { animation: jk-breathe 2.6s ease-in-out infinite; }
@keyframes jk-breathe { 50% { transform: scale(1.62); } }

.jk-nodes { position: absolute; inset: 0; pointer-events: none; }
.journey-key.is-live .jk-nodes { pointer-events: auto; }
.jk-nodes.is-pointing { cursor: pointer; }
.jk-node {
  position: absolute;
  width: 26px; height: 26px;
  margin: -13px 0 0 -13px;
  padding: 0; border: 0; background: none;
  pointer-events: none;   /* the pointer is handled by .jk-nodes (nearest node); the buttons are for the keyboard */
}
.jk-node:focus { outline: none; }
.jk-dot {
  position: absolute; left: 50%; top: 50%;
  width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: #0d1117;
  box-shadow: 0 0 0 1.5px rgba(240, 236, 228, 0.8);
  transition: transform 0.18s ease, background-color 0.18s ease;
}
.jk-node.is-past .jk-dot { background: #8fb4ff; box-shadow: 0 0 0 1.5px #0d1117; }
.jk-node.is-here .jk-dot { opacity: 0; }   /* the drop sits there */
.jk-name {
  position: absolute; left: calc(100% + 4px); top: 50%;
  transform: translate(-4px, -50%);
  white-space: nowrap;
  font: 400 15px/1 var(--label-face, var(--display, 'Rokkitt', serif));
  letter-spacing: 0.02em;
  color: #f0ece4;
  background: rgba(13, 17, 23, 0.82);
  padding: 4px 8px 5px;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
}
.jk-node.is-hot .jk-dot, .jk-node:focus-visible .jk-dot { transform: scale(2); opacity: 1; }
.jk-node.is-hot .jk-name, .jk-node:focus-visible .jk-name { opacity: 1; transform: translate(0, -50%); }
.jk-node.is-hot, .jk-node:focus-visible { z-index: 1; }
.jk-node:focus-visible .jk-dot { box-shadow: 0 0 0 1.5px #f0ece4, 0 0 0 4px rgba(143, 180, 255, 0.7); }

@media (max-width: 640px) {
  .journey-key { height: 40vh; left: 6px; }
}
@media (prefers-reduced-motion: reduce) {
  .journey-key.is-resting .jk-drop-shape { animation: none; }
  .jk-dot, .jk-name { transition: none; }
}

/* Labels pinned to places in the flight (js/flight-labels.js), callout style: a square on the place, a long thin
   leader angled up to a card set off in the open (to the right, or the left with .fl-label--l). Each .fl-label's
   origin is the place itself; JS moves it there every frame and fades it in around its stop. */
.flight-labels { position: absolute; inset: 0; pointer-events: none; z-index: 1; transition: opacity 0.35s ease; }
.flight-labels.is-off { opacity: 0; }
.fl-label { position: absolute; left: 0; top: 0; opacity: 0; visibility: hidden; will-change: transform, opacity; }
.fl-mark {
  position: absolute; left: 0; top: 0;
  width: 7px; height: 7px; margin: -4.5px 0 0 -4.5px;
  border: 1.5px solid rgba(240, 236, 228, 0.7);
  background: #0d1117;
}
.fl-leader { position: absolute; top: 0; left: 0; width: 1px; height: 1px; transform-origin: 0 50%; background: rgba(240, 236, 228, 0.42); }
.fl-card {
  position: absolute; display: block; white-space: nowrap;
  left: var(--dx, 160px); top: var(--dy, -120px); transform: translate(0, -100%);
  background: #0d1117;   /* opaque: the drawing behind made it unreadable */
  border: 1px solid rgba(240, 236, 228, 0.32);
  padding: 6px 9px 7px;
  color: rgba(240, 236, 228, 0.88);
}
.fl-label--l .fl-card { transform: translate(-100%, -100%); text-align: right; }
.fl-text { display: block; font: 11px/1.1 var(--label-face, var(--mono, monospace)); letter-spacing: 0.14em; text-transform: uppercase; }   /* quiet map lettering (the bold slab was too loud) */
.fl-sub { display: block; margin-top: 4px; font: 9px/1 var(--label-face, var(--mono, monospace)); letter-spacing: 0.12em; text-transform: uppercase; color: rgba(240, 236, 228, 0.5); }

@media (max-width: 640px) {
  .fl-text { font-size: 10px; }
  .fl-sub { font-size: 8px; }
  .fl-card { padding: 5px 7px 6px; }
}


/* Scroll to explore, at the first stop (js/flight/switch.js): a button low in the middle of the view */
.flight-start {
  position: absolute; left: 50%; bottom: 25vh; transform: translateX(-50%);
  display: flex; gap: 14px;
  opacity: 0; visibility: hidden;
  transition: opacity 0.5s ease, visibility 0s linear 0.5s;
}
.flight-start.is-shown { opacity: 1; visibility: visible; transition-delay: 0s; pointer-events: auto; }
.flight-start button {
  padding: 11px 26px 10px;
  border: 1px solid rgba(240, 236, 228, 0.55); background: rgba(13, 17, 23, 0.72);
  color: #f0ece4; cursor: pointer;
  font: 500 17px/1 var(--label-face, var(--display, serif)); letter-spacing: 0.12em;   /* the label face, as the menu and the place labels */
  transition: background 0.2s ease, color 0.2s ease;
}
.flight-start button:hover, .flight-start button:focus-visible { background: #f0ece4; color: #0d1117; outline: none; }
