/* =============================================================================
   VISION: "Every farmer a biomanufacturer."  One becomes many.
   -----------------------------------------------------------------------------
   One ink band, and the page's last word. The words set up one farm and the
   reactor at the end of its field; the picture starts close on that farm at
   night and pulls back, scroll-linked, while first light comes up, until the
   frame holds a whole valley of small farms, each with its own reactor lit
   green. The line lands on the sky, and its full stop lights last. Then two
   short notes, and the band ends on ink, straight into #explore.

   THE PICTURE is four image layers on one artboard (1600 x 1800 units),
   .vl-art: sky, ridges, valley and the focal farm at higher detail
   (assets/img/home/vision/README.md). This file places the artboard where the
   LAST frame has it, so without script the section is static and complete.
   home-vision.js (.is-live) then pins the stage in a longer runway and moves
   a camera over the same layers: one transform per layer, plus a night tint,
   the farm's lit windows and a canvas of reactor glows it adds itself.
   With reduced motion it only draws the last frame (.is-still).

   Classes are prefixed vl- (valley) so they cannot collide with the big
   picture's generic names (.node, .link, .task) or anything else on the page.
   ========================================================================== */

#vision.vl {
  --vl-h: clamp(30rem, calc(100svh - var(--nav-h)), 64rem);
  /* the words on the sky; the static artboard below estimates where they end
     from the same four values */
  --vl-pad: clamp(1.25rem, 5svh, 3.5rem);
  --vl-fs: clamp(2.125rem, .75rem + 4.9vw, 5.25rem);
  --vl-gap: var(--sp-4);
  --vl-gfs: var(--text-lede);
  padding: 0; background-color: var(--ink); color: var(--leaf-100);
}
.vl :focus-visible { outline-color: var(--sig-green); }

/* ---- the words before the picture ---- */
.vl-head { padding-top: var(--sp-8); padding-bottom: var(--sp-5); }
.vl-intro {
  margin: 0 0 var(--sp-4); max-width: 22ch;
  font-family: var(--font-display);
  font-size: var(--text-h2); font-weight: 700; line-height: 1.14; letter-spacing: -.018em;
  color: var(--white); text-wrap: balance;
}
.vl-head .lede { margin: 0; }

/* ---- the stage: one frame, the height of the screen under the nav ---- */
.vl-run { position: relative; }
.vl-stage {
  position: relative; overflow: hidden;
  height: var(--vl-h);
  background-color: var(--ink);
  isolation: isolate;
}

/* ---- the artboard, at its last frame ----
   1600 x 1800 units; the horizon is 1204 units down (66.9 %).
   A wide screen shows the artboard's whole width, so it is 112.5vw tall and
   only its lower part fits: it is moved up until the horizon sits about 72px
   below the end of the words (which end near 5svh + 10vw + 104px, the same
   rule home-vision.js uses), and never so far that its foot leaves the
   stage's foot. */
.vl-art {
  position: absolute; z-index: 0; left: 0;
  width: 100%; aspect-ratio: 1600 / 1800;
  top: min(0px, max(calc(var(--vl-h) - 112.5vw), calc(5svh - 65.25vw + 176px)));
  pointer-events: none;
}
/* A tall screen (a phone, a tablet held upright) shows about a third of
   the valley's width, as the script's last frame does: the artboard is 1.48
   times the stage's height, its foot on the stage's foot, centred. */
@media (max-aspect-ratio: 1/1) {
  .vl-art {
    width: auto; height: 148%;
    top: auto; bottom: 0;
    left: calc(50% - var(--vl-h) * .6578);
  }
}
.vl-layer {
  position: absolute; display: block; max-width: none;
  transform-origin: 0 0;
  -webkit-user-select: none; user-select: none;
}
/* the script sets the artboard in px and moves each layer on its own GPU layer */
.vl.is-live .vl-layer, .vl.is-live .vl-lit { will-change: transform; backface-visibility: hidden; }

/* the night: a tint over the picture (not over the lit windows or the glows),
   lifted by the script as first light comes up */
.vl-night {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(to bottom, #03060a, #050a0a 55%, #040807);
  opacity: 0; will-change: opacity;
}
.vl-lit { position: absolute; z-index: 0; display: block; max-width: none; transform-origin: 0 0; pointer-events: none; }
.vl-glows { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }

/* The picture has no hard edges: its top melts out of the words above it and
   its foot into the ink the notes sit on. Over the picture, under the words. */
.vl-stage::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    linear-gradient(to bottom, var(--ink), rgb(7 11 9 / 0) 3rem),
    linear-gradient(to bottom, rgb(7 11 9 / .42), rgb(7 11 9 / 0) calc(var(--vl-pad) + 2.04 * var(--vl-fs) + 7rem)),
    linear-gradient(to top, var(--ink), rgb(7 11 9 / .6) 5%, rgb(7 11 9 / 0) 10%);
}

/* the sky: the line, and the sentence under it */
.vl-sky {
  position: absolute; left: 0; right: 0; top: 0; z-index: 1;
  padding-top: var(--vl-pad);
  pointer-events: none;
}
.vl-line {
  margin: 0; max-width: 16ch;
  font-family: var(--font-display);
  font-size: var(--vl-fs);
  font-weight: 750; line-height: 1.02; letter-spacing: -.034em;
  color: var(--white);
  text-wrap: balance;
}
.vl-gloss {
  margin: var(--vl-gap) 0 0; max-width: 46ch; text-wrap: balance;
  font-size: var(--vl-gfs); line-height: 1.5;
  color: var(--leaf-200);
}
/* A soft dark halo keeps the words at reading contrast wherever the sky
   behind them brightens, without a box round them. */
.vl-line, .vl-gloss { text-shadow: 0 1px 2px rgb(7 11 9 / .7), 0 0 18px rgb(7 11 9 / .75); }
/* The full stop is one more reactor coming on: --sig-green, the only thing on
   the page that glows, and on ink only. Lit in the resting state. */
.vl-stop {
  color: var(--sig-green);
  text-shadow: 0 0 .28em rgb(53 224 138 / .55), 0 1px 2px rgb(7 11 9 / .7);
  transition: color .5s ease, text-shadow .5s ease;
}
.vl.is-live:not(.is-lit) .vl-stop { color: var(--white); text-shadow: 0 1px 2px rgb(7 11 9 / .7), 0 0 18px rgb(7 11 9 / .75); }
/* the line and its sentence wait for the valley; the script fades them in */
.vl.is-live .vl-line, .vl.is-live .vl-gloss { opacity: 0; will-change: opacity, transform; }

/* the honesty tag, in the frame the whole time */
.vl-tag {
  position: absolute; right: var(--sp-4); bottom: var(--sp-4); z-index: 1;
  margin: 0; max-width: calc(100% - 2 * var(--sp-4));
  padding: .35rem .7rem; border-radius: 999px;
  background: rgb(7 11 9 / .72);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  font-size: var(--text-xs, .75rem); line-height: 1.35; color: var(--leaf-100);
}
.vl-tag strong { color: var(--white); font-weight: 650; }

/* the first reactor's label: in the opening frame only, placed by the
   script under the reactor with a leader line up to its plinth */
.vl-rx {
  position: absolute; left: 0; top: 0; z-index: 1;
  display: none;
  margin: 0; max-width: 17rem; padding-left: .6rem;
  font-size: var(--text-sm); line-height: 1.4; font-weight: 500;
  color: var(--leaf-100);
  text-shadow: 0 1px 2px rgb(7 11 9 / .85), 0 0 14px rgb(7 11 9 / .85);
  pointer-events: none; will-change: transform, opacity;
}
.vl-rx::before {
  content: ""; position: absolute; left: 0; bottom: calc(100% - .55em);
  width: 1px; height: calc(var(--vl-lead, 14px) + .55em);
  background: rgb(227 240 232 / .55);
}
.vl.is-live .vl-rx { display: block; }

/* ---- the scroll-linked version (script, motion allowed) ----
   The runway is the stage plus about two screens of scroll: the stage sticks
   under the nav while the camera pulls back, then holds the finished frame. */
.vl.is-live .vl-run { height: calc(var(--vl-h) + 180svh); }
.vl.is-live .vl-stage { position: sticky; top: var(--nav-h); }

/* ---- the notes ---- */
.vl-notes {
  display: grid; gap: var(--sp-5);
  padding-top: var(--sp-6); padding-bottom: var(--sp-8);
}
@media (min-width: 760px) { .vl-notes { grid-template-columns: repeat(2, minmax(0, 27rem)); gap: var(--sp-7); } }
.vl-note { border-top: 1px solid rgb(255 255 255 / .16); padding-top: var(--sp-4); }
.vl-note h3 {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-display); font-size: var(--text-base); font-weight: 650;
  color: var(--white);
}
.vl-note p { margin: 0; max-width: 46ch; text-wrap: pretty; font-size: var(--text-sm); line-height: 1.6; color: var(--leaf-200); }
.vl-more {
  display: inline-block; margin-top: var(--sp-3);
  font-size: var(--text-sm); font-weight: 600; color: var(--leaf-200);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.vl-more::after { content: " \2192"; }
.vl-more:hover { color: var(--white); }

/* a short screen: the words climb, so the sentence stays on the sky */
@media (max-height: 760px) and (min-width: 640px) {
  #vision.vl { --vl-pad: 1.25rem; --vl-fs: clamp(2rem, .8rem + 3.3vw, 3.6rem); --vl-gap: var(--sp-3); }
}

@media (max-width: 639px) {
  #vision.vl { --vl-gfs: var(--text-base); }
  .vl-rx { max-width: 14rem; }
  .vl-tag { right: var(--sp-3); bottom: var(--sp-3); font-size: .6875rem; }
}

/* 1 Oct (students: line breaks). The intro runs to two even lines at most,
   and the gloss is one line wherever it fits. */
.vl-intro { max-width: 32ch; }
@media (min-width: 900px) { .vl-gloss { max-width: none; white-space: nowrap; } }

.vl-intro { margin-bottom: 0; }   /* round 2: no lede under it any more */
