/* ============================================================================
   WELD front page (2026-10-27, second pass).

   The frame: one WSU green field, cream cards, one gold accent. Every project
   keeps its own mark on its own green tile; the frame never changes. Built on
   WayneUI 2.0.8, copied from its documented static path
   (wayne-ui/apps/site/public/v2) so the page works offline: tokens, container,
   buttons, skip link and focus ring come from wayne-ui.css (all inside
   @layer, so the unlayered rules below win without !important).

   Colours are the WELD brand set (site/brand/README.md): green #0C5449, deep
   green #073A32, gold #FFCC33, cream #FFF4CC, terminal #0F1F1C.

   File map:
     1. tokens and frame        5. cast (bento, terminals, bench)
     2. header and seam         6. paths, footer, toast
     3. hero                    7. responsive
     4. journey                 8. motion (only with .motion, see the end)
   ========================================================================== */

/* -------------------------------------------------------- 1. tokens, frame */

:root {
  --weld-green: #0c5449;
  --weld-green-deep: #073a32;
  --weld-green-ink: #021a16;
  --weld-gold: #ffcc33;
  --weld-gold-bright: #ffd65c;
  --weld-gold-hot: #fff1b8;   /* a bead that has not cooled yet */
  --weld-ember: #ff9f43;      /* the one warm accent, sparks only */
  --weld-cream: #fff4cc;
  --weld-cream-85: rgba(255, 244, 204, 0.85);
  --weld-cream-40: rgba(255, 244, 204, 0.4);
  --weld-cream-20: rgba(255, 244, 204, 0.2);
  --weld-ink: #0f1f1c;
  --weld-term-text: #dce8e4;
  --weld-term-dim: #8fa8a1;
  --weld-term-ok: #9fe0b4;
  --weld-cream-muted: #4f5d58;
  --weld-tile: #065a4e;        /* the green of the marks' own tiles */
  --weld-focus: var(--weld-gold);
  --weld-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset, 0 18px 40px -18px rgba(2, 26, 22, 0.55);
  --weld-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --weld-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

body {
  background-color: var(--weld-green);
  color: var(--weld-cream);
}

/* Gold focus ring on the green field; dark ring on cream cards, where gold
   would disappear. */
:where(a, button, [tabindex]):focus-visible {
  outline: 3px solid var(--weld-focus);
  outline-offset: 2px;
}

.cast-card :focus-visible,
.path-card :focus-visible {
  --weld-focus: var(--weld-ink);
}

.eyebrow {
  margin: 0;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.8125rem;
  font-weight: var(--wsu-font-weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--weld-gold);
}

/* ------------------------------------------------------ 2. header and seam */

.site-header {
  padding-block: var(--wsu-space-5);
}

.site-header .wsu-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wsu-space-4);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
}

.brand img {
  border-radius: 7px;
}

.brand__name {
  font-size: 1.125rem;
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: 0.12em;
  color: var(--weld-cream);
}

.brand__version {
  font-family: var(--wsu-font-family-mono);
  font-size: var(--wsu-font-size-xs);
  font-weight: var(--wsu-font-weight-bold);
  color: var(--weld-ink);
  background-color: var(--weld-gold);
  border-radius: var(--wsu-radius-full);
  padding: 0.125rem 0.625rem;
}

/* A thin gold seam along the top of the window that grows as you read. Only
   where the browser can tie it to scroll natively; otherwise it is absent. */
.seam-progress {
  display: none;
}

/* ------------------------------------------------------------------ 3. hero */

.hero {
  padding-block: clamp(1.5rem, 5vw, 4rem) clamp(3rem, 7vw, 5.5rem);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  text-align: center;
}

.hero__copy {
  max-width: 46rem;
  min-width: 0;
}

/* The art: the helmet as an app icon, a warm glow behind it, embers on top.
   The box has a fixed aspect ratio, so nothing below it moves when the
   canvas wakes up. */
.hero__art {
  position: relative;
  display: grid;
  place-items: center;
  width: clamp(190px, 44vw, 400px);
  aspect-ratio: 1;
}

.hero__glow {
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 204, 51, 0.28), rgba(255, 204, 51, 0.08) 55%, transparent 72%);
}

.hero__embers {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* App-icon treatment. The PNG carries its own green tile, a shade off the
   page green; instead of hiding the seam we make it the point: a raised icon
   with a soft shadow and a hairline cream rim that follows its 20% corner. */
.hero__icon {
  position: relative;
  width: 58%;
  aspect-ratio: 1;
  border-radius: 20%;
  box-shadow:
    0 0 0 1px rgba(255, 244, 204, 0.16),
    0 2px 0 0 rgba(255, 244, 204, 0.08) inset,
    0 28px 48px -16px rgba(2, 26, 22, 0.75),
    0 8px 16px -8px rgba(2, 26, 22, 0.6);
}

.hero__mark {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 20%;
}

/* The arc flash sits on the visor (68%, 46% of the mark). Hidden unless the
   motion layer strikes it, once. */
.hero__flash {
  position: absolute;
  left: 68%;
  top: 46%;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 240, 0.95), rgba(255, 214, 92, 0.55) 35%, transparent 70%);
  transform: translate(-50%, -50%) scale(0.2);
  opacity: 0;
  pointer-events: none;
}

.hero__title {
  margin: 0.5rem 0 0;
  font-size: clamp(4rem, 11vw, 8rem);
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: -0.03em;
  line-height: 0.95;
  color: var(--weld-cream);
}

.hero__letters span {
  display: inline-block;
}

/* The acronym, as four plain words in one even style: no initial is
   picked out. With motion on, each word unrolls out of its first letter as
   the letters above cool, and settles even. The words are laid out from
   the start, so nothing shifts. */
.acro {
  margin: 0.875rem 0 0;
  font-size: clamp(1rem, 1.7vw, 1.3125rem);
  font-weight: var(--wsu-font-weight-bold);
  letter-spacing: 0.03em;
  color: var(--weld-cream);
}

.acro__word {
  display: inline-block;
  white-space: nowrap;
}

.acro__init,
.acro__rest {
  display: inline-block;
}

.hero__tagline {
  margin: 0.5rem 0 0;
  font-size: clamp(1.375rem, 2.8vw, 2rem);
  font-weight: var(--wsu-font-weight-bold);
  color: var(--weld-gold);
}

/* "one piece." sits on a weld bead: a gold line with the overlapping ripples
   a real bead has. With motion on it is laid down left to right. */
.seam {
  position: relative;
  display: inline-block;
  white-space: nowrap;
  /* Same trick as the journey: the runner box overshoots while it moves. */
  overflow: clip;
  overflow-clip-margin: 24px;
}

.seam__bead {
  position: absolute;
  left: 0;
  right: 0.25em;
  bottom: -0.2em;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
}

.seam__fill,
.journey__fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(circle at 0 50%, rgba(255, 255, 255, 0.35) 0 2px, transparent 2.5px) 0 0 / 6px 100% repeat-x,
    var(--weld-gold);
}

.seam__runner {
  position: absolute;
  left: 0;
  right: 0.25em;
  bottom: calc(-0.2em + 3px);
  height: 0;
  opacity: 0;
}

.hero__blurb {
  max-width: 40rem;
  margin: 1.5rem auto 0;
  font-size: var(--wsu-font-size-lg);
  line-height: var(--wsu-font-lineHeight-base);
  color: var(--weld-cream);
  text-wrap: pretty;
}

/* Quick start: one dark bar, the command, and a gold copy button. */
.quickstart {
  display: flex;
  align-items: stretch;
  max-width: 40rem;
  margin: 2rem auto 0;
  background-color: var(--weld-ink);
  border: 1px solid var(--weld-cream-20);
  border-radius: var(--wsu-radius-box);
  box-shadow: 0 18px 40px -24px rgba(2, 26, 22, 0.9);
  overflow: hidden;
}

.quickstart__code {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 0.875rem 1.25rem;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--weld-term-text);
  text-align: left;
  /* The command wraps at spaces rather than scrolling, so the whole of it is
     always visible, phone included. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.t-dim {
  color: var(--weld-term-dim);
}

.t-gold {
  color: var(--weld-gold);
}

.t-ok {
  color: var(--weld-term-ok);
}

/* The terminal caret: a gold block. Blinks only with motion on. */
.caret {
  display: inline-block;
  width: 0.6em;
  height: 1.15em;
  margin-left: 1px;
  vertical-align: -0.2em;
  background-color: var(--weld-gold);
  border-radius: 1px;
}

.copy-btn {
  position: relative;
  align-self: stretch;
  min-width: 5.5rem;
  min-height: 44px;
  border: 0;
  padding-inline: 1.25rem;
  font-family: var(--wsu-font-family-body);
  font-size: 0.9375rem;
  font-weight: var(--wsu-font-weight-bold);
  color: #09090b;
  background-color: var(--weld-gold);
  cursor: pointer;
}

.copy-btn:hover {
  background-color: var(--weld-gold-bright);
}

.copy-btn:focus-visible {
  outline-offset: -5px;
  --weld-focus: var(--weld-ink);
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem 1.75rem;
  margin-top: 2rem;
}

.hero__link {
  font-weight: var(--wsu-font-weight-bold);
  color: var(--weld-cream);
  text-decoration-color: var(--weld-gold);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3em;
}

.hero__link:hover {
  color: var(--weld-gold);
}

/* ------------------------------------------------------------- sections */

.section {
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
}

.section__head {
  max-width: 46rem;
  margin: 0 auto clamp(2rem, 4vw, 3rem);
  text-align: center;
}

.section__head h2 {
  margin: 0;
  font-size: clamp(2rem, 4.5vw, 2.75rem);
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: -0.01em;
  line-height: var(--wsu-font-lineHeight-tight);
  color: var(--weld-cream);
}

.section__head p {
  margin: 0.75rem 0 0;
  font-size: var(--wsu-font-size-lg);
  color: var(--weld-cream-85);
  text-wrap: pretty;
}

/* The journey is a diagram, so its head is quiet... */
.section__head--light h2 {
  font-size: clamp(1.25rem, 2.2vw, 1.5rem);
  letter-spacing: 0.02em;
}

.section__head--light p {
  margin-top: 0.375rem;
  font-size: 1rem;
}

/* ...and the cast is the main event. */
.section__head--main h2 {
  margin-top: 0.5rem;
  font-size: clamp(2.75rem, 7vw, 4.5rem);
  letter-spacing: -0.025em;
  line-height: 1;
}

.section--journey {
  padding-block: clamp(1.5rem, 4vw, 3rem);
}

.section--cast {
  padding-top: clamp(3rem, 7vw, 5.5rem);
}

/* --------------------------------------------------------------- 4. journey */

/* One request, six stops, as an ordered list: real text, readable in any
   order, one markup for both directions. Across from 720px; down below. */

.journey {
  --icon: 64px;
  position: relative;
  max-width: 880px;
  margin-inline: auto;
  /* The runner and the glint travel by translating a track-sized box its
     own length, so at the far end that box hangs a full track past the
     diagram. Clip it sideways here so it never widens the page. Only the
     x axis: the sparks and rings still spill up and down. */
  overflow-x: clip;
}

.journey__stops {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

.journey__stop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  text-align: center;
}

.journey__icon {
  position: relative;
  display: block;
  width: var(--icon);
  height: var(--icon);
  border-radius: 20%;
  box-shadow: 0 10px 22px -10px rgba(2, 26, 22, 0.8);
}

.journey__icon img {
  display: block;
  width: 100%;
  height: 100%;
}

/* WayneUI's mark (its reversed variant: white frame, gold tab, copied from
   wayne-ui/brand/mark-reverse.svg) is drawn bare, not on a tile: seat it on
   the same green tile the other marks carry, as the cast does. */
.journey__icon--tile {
  /* In px from the icon size: a % padding would follow the column width. */
  padding: calc(var(--icon) * 0.16);
  background-color: var(--weld-tile);
}

/* A gold ring marks a stop the request has passed. At rest it is on, a
   little faint, so the path reads with or without motion. */
.journey__icon::before {
  content: "";
  position: absolute;
  inset: -5px;
  border: 2px solid var(--weld-gold);
  border-radius: 26%;
  opacity: 0.55;
}

.journey__text {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.journey__name {
  font-size: 0.9375rem;
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: 0.08em;
  color: var(--weld-cream);
}

.journey__role {
  font-size: 0.875rem;
  color: var(--weld-cream-85);
}

/* The seam: centre of the first icon to centre of the last. */
.journey {
  /* How far the seam stops short of each tile's centre: half the tile, the
     5px gold ring around it, then 7px of clear air. */
  --seam-gap: calc(var(--icon) / 2 + 12px);
}

/* The seam runs centre to centre, but a mask cuts it into five segments that
   live only in the gaps, 7px clear of each tile's ring. Everything inside
   the track (the dashed base, the bead, the riding spark, the glint) is
   masked the same way, so nothing ever draws over or under a tile; the glint
   simply passes behind the tiles. The track is a 40px band, not a 2px line,
   so the spark's glow isn't clipped to the line's height. */
.journey__track {
  position: absolute;
  z-index: 0;
  top: calc(var(--icon) / 2 - 20px);
  left: calc(100% / 12);   /* half a column: centre of the first stop */
  right: calc(100% / 12);
  height: 40px;
  -webkit-mask: linear-gradient(90deg, transparent var(--seam-gap), #000 var(--seam-gap) calc(100% - var(--seam-gap)), transparent calc(100% - var(--seam-gap))) 0 0 / calc(100% / 5) 100% repeat-x;
  mask: linear-gradient(90deg, transparent var(--seam-gap), #000 var(--seam-gap) calc(100% - var(--seam-gap)), transparent calc(100% - var(--seam-gap))) 0 0 / calc(100% / 5) 100% repeat-x;
}

/* The dashed base line, on the band's centre. */
.journey__track::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% - 1px);
  height: 2px;
  background-image: linear-gradient(90deg, var(--weld-cream-40) 50%, transparent 50%);
  background-size: 8px 2px;
}

.journey__bead {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% - 2px);
  height: 4px;
  border-radius: 2px;
  overflow: hidden;
}

.journey__runner,
.journey__glint {
  position: absolute;
  inset: 0;
  opacity: 0;
}

/* ------------------------------------------------------------------ 5. cast */

/* A bento grid on twelve columns: 7 + 5, then three stacked cards, then
   5 + 7, then the shop floor (three stacked, then 7 + 5), then Sourdough
   across the whole width. Split cards put the
   terminal beside the info; stacked cards put it underneath. */

.cast {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 1rem;
}

.cast-card {
  --mx: 50%;
  --my: 50%;
  position: relative;
  grid-column: span var(--span, 4);
  display: grid;
  min-width: 0;
  background-color: var(--weld-cream);
  border-radius: var(--wsu-radius-box);
  box-shadow: var(--weld-shadow);
  overflow: hidden;
  isolation: isolate;
}

.cast-card--split {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
}

.cast-card--stack {
  grid-template-rows: 1fr auto;
}

.cast-card__info {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1.5rem;
  color: var(--weld-ink);
}

.cast-card__mark {
  width: 56px;
  height: 56px;
  border-radius: 18%;
  box-shadow: 0 8px 16px -8px rgba(2, 26, 22, 0.55);
}

/* WayneUI's mark (the reversed variant, from wayne-ui/brand) is drawn bare,
   not on a tile: seat it on the same green tile the other marks carry, so
   the row of marks reads as one family. */
.cast-card__mark--tile {
  padding: 9px;
  background-color: var(--weld-tile);
}

.cast-card__name {
  margin: 0.25rem 0 0;
  font-size: 1.5rem;
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: 0.02em;
  line-height: 1.1;
  color: inherit;
}

.cast-card[style*="--span:7"] .cast-card__name,
.cast-card--sibling .cast-card__name {
  font-size: 1.875rem;
}

.cast-card__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
}

.chip {
  padding: 0.25rem 0.625rem;
  border-radius: var(--wsu-radius-full);
  font-size: var(--wsu-font-size-xs);
  font-weight: var(--wsu-font-weight-bold);
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.chip--version {
  color: var(--weld-cream);
  background-color: var(--weld-ink);
}

.chip--joke {
  color: #09090b;
  background-color: var(--weld-gold);
}

.cast-card__line {
  margin: 0;
  font-size: 0.9375rem;
  line-height: var(--wsu-font-lineHeight-base);
  color: var(--weld-cream-muted);
  text-wrap: pretty;
}

.cast-card__line code {
  font-family: var(--wsu-font-family-mono);
  font-size: 0.875em;
  color: var(--weld-ink);
}

/* The terminal side. */
.term {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: 1.25rem 1.5rem 1.5rem;
  background-color: var(--weld-ink);
}

.cast-card--stack .term {
  margin: 0 0.5rem 0.5rem;
  border-radius: calc(var(--wsu-radius-box) - 4px);
  padding-block: 1rem 1.125rem;
}

.term__bar {
  margin: 0 0 0.75rem;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.75rem;
  color: var(--weld-term-dim);
}

.term__body {
  margin: 0;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.8125rem;
  line-height: 1.75;
  color: var(--weld-term-text);
  /* pre-wrap keeps each line its own and wraps long ones at spaces. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.term__prompt .caret {
  width: 0.55em;
  height: 1.05em;
}

/* The cursor glow: a warm spot that follows the pointer across a card.
   Moved with transform only; sits under the content. Shown on hover. */
.cast-card__glow {
  position: absolute;
  z-index: 0;
  top: 0;
  left: 0;
  width: 360px;
  height: 360px;
  margin: -180px 0 0 -180px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 204, 51, 0.38), rgba(255, 204, 51, 0) 70%);
  opacity: 0;
  pointer-events: none;
}

/* Sourdough: the sibling, on the dark side of the oven. */
.cast-card--sibling {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  background-color: var(--weld-green-deep);
  box-shadow: 0 0 0 1px var(--weld-cream-20) inset;
}

.cast-card--sibling .cast-card__info {
  color: var(--weld-cream);
  justify-content: center;
}

.cast-card--sibling .cast-card__line {
  max-width: 34rem;
  color: var(--weld-cream-85);
}

.cast-card--sibling .chip--version {
  color: var(--weld-ink);
  background-color: var(--weld-cream);
}

.cast-card--sibling .term {
  margin: 0.5rem;
  border-radius: calc(var(--wsu-radius-box) - 4px);
}

.cast-card--sibling .cast-card__glow {
  background: radial-gradient(closest-side, rgba(255, 204, 51, 0.2), rgba(255, 204, 51, 0) 70%);
}

.cast-card--sibling :focus-visible {
  --weld-focus: var(--weld-gold);
}

/* The bench: who comes off the line next. Smaller, quieter, no terminals. */
.bench__title {
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 1rem;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.8125rem;
  font-weight: var(--wsu-font-weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--weld-gold);
}

.bench {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.bench-card {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
  min-width: 0;
  padding: 1rem;
  border: 1px solid var(--weld-cream-20);
  border-radius: var(--wsu-radius-box);
  background-color: rgba(7, 58, 50, 0.55);
}

.bench-card__mark {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 18%;
  box-shadow: 0 8px 16px -8px rgba(2, 26, 22, 0.8);
}

/* An empty mould where a mark will be poured once the project is built. */
.bench-card__mark--mould {
  display: block;
  border: 2px dashed var(--weld-cream-40);
  box-shadow: none;
}

.bench-card__name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: 0.06em;
  color: var(--weld-cream);
}

.chip--next {
  font-family: var(--wsu-font-family-mono);
  font-size: 0.6875rem;
  font-weight: var(--wsu-font-weight-bold);
  letter-spacing: 0.04em;
  padding: 0.0625rem 0.5rem;
  color: var(--weld-gold);
  border: 1px solid rgba(255, 204, 51, 0.6);
}

.bench-card__line {
  margin: 0.25rem 0 0;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--weld-cream-85);
}

/* -------------------------------------------------- 6. paths, footer, toast */

/* The overflow fix. These columns used to be repeat(3, 1fr), and 1fr has a
   minimum of "auto": the min-content width of the card. Each card holds a
   no-wrap command about 470px wide, so every track grew to fit it and the
   grid ran ~260px past the window at 1440 and ~140px past it at 390.
   minmax(0, 1fr) lets the tracks shrink; the commands now wrap. */
.paths {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}

.path-card {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-width: 0;
  padding: 1.5rem;
  background-color: var(--weld-cream);
  border-radius: var(--wsu-radius-box);
  box-shadow: var(--weld-shadow);
  color: var(--weld-ink);
}

.path-card--featured {
  box-shadow: 0 0 0 3px var(--weld-gold), var(--weld-shadow);
}

.path-card .path-card__from {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.75rem;
  font-weight: var(--wsu-font-weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--weld-cream-muted);
}

.chip--soon {
  font-family: var(--wsu-font-family-body);
  text-transform: none;
  letter-spacing: 0.03em;
  color: var(--weld-cream);
  background-color: var(--weld-ink);
}

.path-card h3 {
  margin: 0;
  font-size: 1.25rem;
  font-weight: var(--wsu-font-weight-black);
  letter-spacing: 0.02em;
}

.path-card p {
  margin: 0;
  font-size: 0.9375rem;
  line-height: var(--wsu-font-lineHeight-base);
  color: var(--weld-cream-muted);
}

.path-card code {
  margin-top: auto;
  padding: 0.75rem 1rem;
  background-color: var(--weld-ink);
  border-radius: var(--wsu-radius-field);
  font-family: var(--wsu-font-family-mono);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--weld-term-text);
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.site-footer {
  margin-top: clamp(2rem, 5vw, 4rem);
  padding-block: 2.5rem;
  background-color: var(--weld-green-deep);
}

.site-footer .wsu-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  text-align: center;
}

.site-footer__joke {
  margin: 0;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.9375rem;
  color: var(--weld-gold);
}

.site-footer__org {
  margin: 0;
  font-size: var(--wsu-font-size-sm);
  color: var(--weld-cream-85);
}

/* The torch toast: a tiny terminal in the corner. Empty and invisible until
   the easter egg fires. */
.torch-toast {
  position: fixed;
  z-index: 50;
  right: 1rem;
  bottom: 1rem;
  max-width: min(22rem, calc(100vw - 2rem));
  padding: 0.875rem 1rem;
  font-family: var(--wsu-font-family-mono);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--weld-term-text);
  background-color: var(--weld-ink);
  border: 1px solid rgba(255, 204, 51, 0.5);
  border-radius: var(--wsu-radius-box);
  box-shadow: 0 20px 40px -16px rgba(0, 0, 0, 0.6);
  white-space: pre-wrap;
  visibility: hidden;
  opacity: 0;
}

.torch-toast.is-on {
  visibility: visible;
  opacity: 1;
}

.spark-layer {
  position: fixed;
  z-index: 40;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ------------------------------------------------------------ 7. responsive */

@media (min-width: 960px) {
  /* Desktop hero: copy on the left, the helmet on the right. */
  .hero__grid {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: center;
    justify-items: start;
    text-align: left;
  }

  .hero__art {
    order: 2;
    justify-self: center;
  }

  .hero__blurb,
  .quickstart {
    margin-inline: 0;
  }

  .hero__cta {
    justify-content: flex-start;
  }
}

@media (max-width: 1080px) {
  .bench {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 960px) {
  .cast-card[style*="--span:7"],
  .cast-card[style*="--span:5"] {
    grid-column: span 12;
  }

  .paths {
    grid-template-columns: minmax(0, 1fr);
    max-width: 32rem;
    margin-inline: auto;
  }
}

/* Under 720px the journey turns and runs down the page, icons at 56px. */
@media (max-width: 719px) {
  .journey {
    --icon: 56px;
    --row: 100px;
    /* Tighter rows: 6px of clear air, which still leaves ~22px of seam. */
    --seam-gap: calc(var(--icon) / 2 + 11px);
    max-width: 20rem;
    /* Running down the page, nothing travels sideways: no clip needed. */
    overflow-x: visible;
  }

  .journey__stops {
    grid-template-columns: minmax(0, 1fr);
  }

  .journey__stop {
    flex-direction: row;
    align-items: flex-start;
    gap: 1rem;
    height: var(--row);
    text-align: left;
  }

  .journey__text {
    padding-top: 0.375rem;
  }

  .journey__track {
    top: calc(var(--icon) / 2);
    bottom: calc(var(--row) - var(--icon) / 2);
    left: calc(var(--icon) / 2 - 20px);
    right: auto;
    width: 40px;
    height: auto;
    -webkit-mask: linear-gradient(180deg, transparent var(--seam-gap), #000 var(--seam-gap) calc(100% - var(--seam-gap)), transparent calc(100% - var(--seam-gap))) 0 0 / 100% calc(100% / 5) repeat-y;
    mask: linear-gradient(180deg, transparent var(--seam-gap), #000 var(--seam-gap) calc(100% - var(--seam-gap)), transparent calc(100% - var(--seam-gap))) 0 0 / 100% calc(100% / 5) repeat-y;
  }

  .journey__track::before {
    left: calc(50% - 1px);
    right: auto;
    top: 0;
    bottom: 0;
    width: 2px;
    height: auto;
    background-image: linear-gradient(180deg, var(--weld-cream-40) 50%, transparent 50%);
    background-size: 2px 8px;
  }

  .journey__bead {
    left: calc(50% - 2px);
    right: auto;
    top: 0;
    bottom: 0;
    width: 4px;
    height: auto;
  }
}

@media (max-width: 640px) {
  .cast-card,
  .cast-card--stack {
    grid-column: span 12;
  }

  .cast-card--split,
  .cast-card--sibling {
    grid-template-columns: minmax(0, 1fr);
  }

  .cast-card--split .term {
    margin: 0 0.5rem 0.5rem;
    border-radius: calc(var(--wsu-radius-box) - 4px);
  }

  .bench {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 480px) {
  .quickstart__code {
    padding-inline: 1rem;
    font-size: 0.875rem;
  }

  .copy-btn {
    min-width: 4.5rem;
    padding-inline: 0.875rem;
  }
}

/* ================================================================ 8. motion

   Everything below runs only when both are true:
     - the visitor's system has no reduced-motion request, and
     - the <head> script has put .motion on <html>.
   Without either, the page above is the whole page: final state, already
   cooled, nothing hidden and nothing moving. The JS-driven states (.is-armed,
   .is-welded, .is-done) are only ever added by weld.js, so if the script never
   loads nothing stays hidden. Animations use transform and opacity; the two
   small exceptions are the bead's clip-path (a strip a few pixels tall) and
   the letters' text-shadow on their way in.
   ========================================================================= */

@media (prefers-reduced-motion: no-preference) {

  /* ---------------------------------------------------------- the spark */
  /* A drawn spark that rides the tip of every bead. The canvas throws the
     loose sparks; this is the bright point that stays at the tip. */
  .spark {
    position: absolute;
    left: 0;
    top: 0;
    width: 14px;
    height: 14px;
    margin: -7px 0 0 -7px;
    border-radius: 50%;
    background: radial-gradient(circle, #fff 0 22%, var(--weld-gold-hot) 38%, rgba(255, 204, 51, 0) 70%);
    box-shadow: 0 0 14px 5px rgba(255, 204, 51, 0.5);
  }

  .spark::before,
  .spark::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 28px;
    height: 2px;
    margin: -1px 0 0 -14px;
    border-radius: 1px;
    background: linear-gradient(90deg, transparent, #fff, transparent);
    transform: rotate(35deg);
  }

  .spark::after {
    transform: rotate(-35deg);
  }

  .motion .spark {
    animation: spark-crackle 150ms steps(2) infinite alternate;
  }

  @keyframes spark-crackle {
    from { transform: scale(0.85) rotate(0deg); }
    to   { transform: scale(1.15) rotate(18deg); }
  }

  /* ---------------------------------------------------------- the caret */
  /* About 0.9 blinks a second: alive, and well under three flashes. */
  .motion .caret {
    animation: caret-blink 1.1s linear infinite;
  }

  @keyframes caret-blink {
    0%, 49%   { opacity: 1; }
    50%, 100% { opacity: 0; }
  }

  /* -------------------------------------------------------------- hero */
  .motion .hero__icon {
    animation: icon-in 900ms var(--weld-ease-out) backwards;
    transition: transform 500ms var(--weld-ease-spring);
    cursor: pointer;
  }

  .motion .hero__icon:hover {
    transform: rotate(-3deg) scale(1.03);
  }

  @keyframes icon-in {
    from { opacity: 0; transform: translateY(18px) scale(0.92); }
  }

  /* The arc strikes once, on the visor, as the helmet lands. One flash. */
  .motion .hero__flash {
    animation: arc-flash 750ms ease-out 650ms backwards;
  }

  .motion .hero__flash.is-struck {
    animation: arc-flash-again 600ms ease-out;
  }

  @keyframes arc-flash {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
    18%  { opacity: 0.95; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.4); }
  }

  /* Same flash under a second name, so a click can restart it. */
  @keyframes arc-flash-again {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
    18%  { opacity: 0.8; transform: translate(-50%, -50%) scale(0.9); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.3); }
  }

  .motion .hero__glow {
    animation: glow-breathe 5.5s ease-in-out 1.4s infinite alternate;
  }

  @keyframes glow-breathe {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0.6; transform: scale(0.95); }
  }

  /* Each letter lands hot and cools to cream. */
  .motion .hero__letters span {
    animation: letter-in 800ms var(--weld-ease-out) backwards;
    animation-delay: calc(200ms + var(--i) * 80ms);
  }

  @keyframes letter-in {
    0%   { opacity: 0; transform: translateY(0.22em) rotate(-5deg); color: var(--weld-gold-hot); text-shadow: 0 0 28px rgba(255, 204, 51, 0.9); }
    60%  { opacity: 1; color: var(--weld-gold-hot); text-shadow: 0 0 18px rgba(255, 204, 51, 0.5); }
    100% { opacity: 1; transform: none; color: var(--weld-cream); text-shadow: 0 0 0 rgba(255, 204, 51, 0); }
  }

  .motion .hero__copy .eyebrow,
  .motion .hero__tagline,
  .motion .hero__blurb,
  .motion .quickstart,
  .motion .hero__cta {
    animation: rise 700ms var(--weld-ease-out) backwards;
  }

  .motion .hero__copy .eyebrow { animation-delay: 80ms; }
  .motion .hero__tagline { animation-delay: 1150ms; }
  .motion .hero__blurb { animation-delay: 1250ms; }
  .motion .quickstart { animation-delay: 1350ms; }
  .motion .hero__cta { animation-delay: 1450ms; }

  @keyframes rise {
    from { opacity: 0; transform: translateY(12px); }
  }

  /* The acronym: each first letter lands warm and cools to the same cream
     as the rest, then its word unrolls out of it. */
  .motion .acro__init {
    animation: initial-in 600ms var(--weld-ease-out) backwards;
    animation-delay: calc(380ms + var(--i) * 80ms);
  }

  @keyframes initial-in {
    0%   { opacity: 0; transform: translateY(0.3em); color: var(--weld-gold-hot); text-shadow: 0 0 14px rgba(255, 204, 51, 0.9); }
    100% { opacity: 1; transform: none; color: var(--weld-cream); text-shadow: 0 0 0 rgba(255, 204, 51, 0); }
  }

  .motion .acro__rest {
    animation: word-unroll 650ms var(--weld-ease-out) backwards;
    animation-delay: calc(820ms + var(--i) * 140ms);
  }

  @keyframes word-unroll {
    from { opacity: 0; clip-path: inset(0 100% 0 0); transform: translateX(-0.35em); }
    to   { opacity: 1; clip-path: inset(0 0 0 0); transform: none; }
  }

  /* The bead under "one piece." is laid down left to right, starting hot. */
  .motion .seam__bead {
    animation: bead-draw 900ms linear 1450ms backwards;
  }

  @keyframes bead-draw {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
  }

  .seam__fill::after,
  .journey__fill::after {
    content: "";
    position: absolute;
    inset: 0;
    background-color: var(--weld-gold-hot);
    opacity: 0;
  }

  .motion .seam__fill::after {
    animation: bead-cool 1800ms ease-out 1450ms backwards;
  }

  @keyframes bead-cool {
    from { opacity: 1; }
    to   { opacity: 0; }
  }

  .motion .seam__runner {
    animation: run-x 900ms linear 1450ms backwards;
  }

  @keyframes run-x {
    0%   { opacity: 0; transform: translateX(0); }
    4%   { opacity: 1; }
    96%  { opacity: 1; transform: translateX(100%); }
    100% { opacity: 0; transform: translateX(100%); }
  }

  @keyframes run-y {
    0%   { opacity: 0; transform: translateY(0); }
    4%   { opacity: 1; }
    96%  { opacity: 1; transform: translateY(100%); }
    100% { opacity: 0; transform: translateY(100%); }
  }

  /* The quick-start command types itself. Until weld.js takes over it is
     hidden, with a fallback that shows it at 3s if the script never runs. */
  .motion #quickstart-cmd [data-type] {
    opacity: 0;
    animation: show-late 1ms 3s forwards;
  }

  .motion #quickstart-cmd .caret {
    opacity: 0;
    animation: show-late 1ms 3s forwards;
  }

  @keyframes show-late {
    to { opacity: 1; }
  }

  .motion .quickstart.is-armed #quickstart-cmd [data-type] {
    opacity: 1;
    animation: none;
  }

  .motion .quickstart.is-armed #quickstart-cmd .caret {
    opacity: 0;
    animation: none;
  }

  .motion .quickstart.is-armed.is-done #quickstart-cmd .caret {
    opacity: 1;
    animation: caret-blink 1.1s linear infinite;
  }

  /* ---------------------------------------------------- typed characters */
  .motion .is-armed [data-type] .ch {
    position: relative;
    opacity: 0;
  }

  .motion .is-armed [data-type] .ch.on {
    opacity: 1;
  }

  /* While typing, the cursor rides the last character typed. */
  .motion .is-armed [data-type] .ch.cur::after {
    content: "";
    position: absolute;
    left: 100%;
    top: 0.12em;
    width: 0.55em;
    height: 1.1em;
    background-color: var(--weld-gold);
    border-radius: 1px;
  }

  .motion .term.is-armed .term__out,
  .motion .term.is-armed .term__prompt {
    opacity: 0;
    transition: opacity 160ms ease-out;
  }

  .motion .term.is-armed .term__out.on,
  .motion .term.is-armed.is-done .term__prompt {
    opacity: 1;
  }

  /* ----------------------------------------------------------- journey */
  .motion .journey.is-armed .journey__bead {
    clip-path: inset(0 100% 0 0);
  }

  .motion .journey.is-armed.is-welded .journey__bead {
    clip-path: inset(0 0 0 0);
    transition: clip-path 3000ms linear;
  }

  .motion .journey.is-welded .journey__fill::after {
    animation: bead-cool 3200ms ease-out backwards;
  }

  .motion .journey.is-armed .journey__icon {
    opacity: 0.4;
    transform: scale(0.86);
  }

  .motion .journey.is-armed .journey__icon::before {
    opacity: 0;
    transform: scale(0.8);
  }

  .motion .journey.is-armed.is-welded .journey__icon,
  .motion .journey.is-armed.is-welded .journey__icon::before {
    opacity: 1;
    transform: none;
    transition: opacity 300ms ease-out, transform 700ms var(--weld-ease-spring);
    transition-delay: calc(var(--i) * 600ms);
  }

  .motion .journey.is-armed.is-welded .journey__icon::before {
    opacity: 0.55;
  }

  /* As the bead reaches a stop, a gold ring pops off it, once. */
  .motion .journey.is-welded .journey__icon::after {
    content: "";
    position: absolute;
    inset: -5px;
    border: 2px solid var(--weld-gold);
    border-radius: 26%;
    opacity: 0;
    animation: stop-pop 900ms ease-out backwards;
    animation-delay: calc(var(--i) * 600ms);
  }

  @keyframes stop-pop {
    0%   { opacity: 0; transform: scale(1); }
    12%  { opacity: 0.9; }
    100% { opacity: 0; transform: scale(1.55); }
  }

  .motion .journey.is-welded .journey__runner {
    animation: run-x 3000ms linear backwards;
  }

  /* Afterwards, every eight seconds, one request glints along the finished
     seam and each stop brightens as it passes: the old travelling dot, kept. */
  .journey__glint::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 10px;
    height: 10px;
    margin: -5px 0 0 -5px;
    border-radius: 50%;
    background-color: var(--weld-gold-hot);
    box-shadow: 0 0 10px 3px rgba(255, 204, 51, 0.6);
  }

  .motion .journey.is-welded .journey__glint {
    animation: glint-x 8s linear 3.6s infinite;
  }

  @keyframes glint-x {
    0%   { opacity: 0; transform: translateX(0); }
    3%   { opacity: 1; }
    40%  { opacity: 1; transform: translateX(100%); }
    44%  { opacity: 0; transform: translateX(100%); }
    100% { opacity: 0; transform: translateX(100%); }
  }

  @keyframes glint-y {
    0%   { opacity: 0; transform: translateY(0); }
    3%   { opacity: 1; }
    40%  { opacity: 1; transform: translateY(100%); }
    44%  { opacity: 0; transform: translateY(100%); }
    100% { opacity: 0; transform: translateY(100%); }
  }

  .motion .journey.is-armed.is-welded .journey__stop .journey__icon::before {
    animation: ring-glint 8s linear infinite;
    animation-delay: calc(3.6s + var(--i) * 640ms);
  }

  @keyframes ring-glint {
    0%   { opacity: 0.55; transform: scale(1); }
    3%   { opacity: 1; transform: scale(1.07); }
    12%  { opacity: 0.55; transform: scale(1); }
    100% { opacity: 0.55; transform: scale(1); }
  }

  /* -------------------------------------------------------------- cast */
  .motion .cast-card,
  .motion .path-card,
  .motion .bench-card {
    transition: transform 450ms var(--weld-ease-out), box-shadow 450ms var(--weld-ease-out);
  }

  .motion .cast-card__mark,
  .motion .bench-card__mark {
    transition: transform 550ms var(--weld-ease-spring);
  }

  .motion .cast-card__glow {
    transition: opacity 350ms ease-out;
  }

  /* Cards rise into place as they scroll in, a beat apart. */
  .motion .reveal.is-armed {
    opacity: 0;
    transform: translateY(28px);
  }

  .motion .reveal.is-armed.is-in {
    opacity: 1;
    transform: none;
    transition: transform 900ms var(--weld-ease-out), opacity 700ms ease-out;
    transition-delay: var(--d, 0ms);
  }

  @media (hover: hover) and (pointer: fine) {
    .motion .cast-card:hover,
    .motion .path-card:hover {
      transform: translateY(-4px);
      box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset, 0 28px 50px -20px rgba(2, 26, 22, 0.75);
    }

    .motion .path-card--featured:hover {
      box-shadow: 0 0 0 3px var(--weld-gold), 0 28px 50px -20px rgba(2, 26, 22, 0.75);
    }

    .motion .cast-card:hover .cast-card__mark,
    .motion .bench-card:hover .bench-card__mark {
      transform: translateY(-3px) rotate(-8deg) scale(1.08);
    }

    .motion .cast-card:hover .cast-card__glow {
      opacity: 1;
    }
  }

  /* ------------------------------------------------------------- toast */
  .motion .torch-toast {
    transform: translateY(12px);
    transition: opacity 300ms ease-out, transform 400ms var(--weld-ease-spring), visibility 0s 400ms;
  }

  .motion .torch-toast.is-on {
    transform: none;
    transition: opacity 300ms ease-out, transform 400ms var(--weld-ease-spring), visibility 0s;
  }

  /* --------------------------------------------------- reading progress */
  @supports (animation-timeline: scroll()) {
    .motion .seam-progress {
      display: block;
      position: fixed;
      z-index: 60;
      top: 0;
      left: 0;
      right: 0;
      height: 3px;
      background-color: var(--weld-gold);
      transform-origin: 0 50%;
      animation: seam-grow linear both;
      animation-timeline: scroll(root);
    }

    @keyframes seam-grow {
      from { transform: scaleX(0); }
      to   { transform: scaleX(1); }
    }
  }

  /* --------------------------------------------- the journey, turned down */
  @media (max-width: 719px) {
    .motion .journey.is-armed .journey__bead {
      clip-path: inset(0 0 100% 0);
    }

    .motion .journey.is-welded .journey__runner {
      animation-name: run-y;
    }

    .motion .journey.is-welded .journey__glint {
      animation-name: glint-y;
    }

    .journey__glint::before {
      left: 50%;
      top: 0;
    }
  }
}

/* The journey's runner holds its spark on the track's centre line. */
.journey__runner .spark {
  top: 50%;
}

@media (max-width: 719px) {
  .journey__runner .spark {
    top: 0;
    left: 50%;
  }
}

/* A part's mark and name are one link: the name's link stretches over its
   whole entry, so the mark is clickable too and the entry takes the focus
   ring. No underline on these; the mark brightens (and, with motion allowed,
   lifts) on hover instead. Prose links elsewhere keep their underline. */
.cast-card__info,
li.journey__stop { position: relative; }
.cast-card__info :is(.part-link, .cast-card__link),
li.journey__stop :is(.part-link, .cast-card__link) { color: inherit; text-decoration: none; }
.cast-card__info :is(.part-link, .cast-card__link)::after,
li.journey__stop :is(.part-link, .cast-card__link)::after { content: ""; position: absolute; inset: 0; }
.cast-card__info :is(.part-link, .cast-card__link):focus-visible,
li.journey__stop :is(.part-link, .cast-card__link):focus-visible { outline: none; box-shadow: none; }
li.journey__stop:has(:is(.part-link, .cast-card__link):focus-visible) { outline: 3px solid currentColor; outline-offset: -3px; }
.cast-card__info:has(:is(.part-link, .cast-card__link):hover) img,
li.journey__stop:has(:is(.part-link, .cast-card__link):hover) img { filter: brightness(1.12) saturate(1.1); }
@media (prefers-reduced-motion: no-preference) {
.cast-card__info img,
li.journey__stop img { transition: transform 160ms ease, filter 160ms ease; }
.cast-card__info:has(:is(.part-link, .cast-card__link):hover) img,
li.journey__stop:has(:is(.part-link, .cast-card__link):hover) img { transform: translateY(-2px); }
}

/* A cast card's info half sits flush against its edge and terminal, where an
   inset ring is lost, so the whole card takes WELD's gold ring instead. */
.cast-card:has(.cast-card__link:focus-visible) { outline: 3px solid var(--weld-gold); outline-offset: 3px; }
