/* The Nexa pipeline, animated: one request travelling from the prompt, out to whichever
   agents are working, through Pad and Plan, into the editor, and onto the preview.

   Built as HTML nodes over an SVG connector layer that share one coordinate space
   (1440x360), so the light travels along real curves and the labels stay real text.
   The whole timeline is one 13s loop, PAUSED until the section scrolls in - nothing
   animates while it is off screen. */

.pipe {
  position: relative;
  margin-top: clamp(30px, 4.5vh, 50px);
  width: 100%;
  aspect-ratio: 1440 / 360;
  min-height: 260px;
  --pipe-loop: 13s;
}
.pipe-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.pipe-track { fill: none; stroke: var(--hairline); stroke-width: 1.5; }
/* The travelling light: a short dash chased along the path by its own dashoffset. */
.pipe-spark {
  fill: none; stroke: var(--blue); stroke-width: 2.5; stroke-linecap: round;
  stroke-dasharray: 22 2000; stroke-dashoffset: 2022;
  opacity: 0;
  animation: pipe-spark var(--pipe-loop) linear infinite;
  animation-play-state: paused;
}
@keyframes pipe-spark {
  0%, 4%   { stroke-dashoffset: 2022; opacity: 0; }
  6%       { opacity: 1; }
  16%      { stroke-dashoffset: 1900; opacity: 1; }
  20%, 100% { stroke-dashoffset: 1900; opacity: 0; }
}

/* Nodes are positioned in the same 1440x360 space as the paths. */
.pipe-node {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  border: 1px solid var(--hairline);
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  font-size: var(--fs-lead); font-weight: 600; letter-spacing: -0.005em;
  color: var(--ink-40);
  white-space: nowrap;
  transition: none;
  animation: pipe-lit var(--pipe-loop) ease-in-out infinite;
  animation-play-state: paused;
}
.pipe-node small { font-size: var(--fs-micro); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-40); }
/* Each node holds its lit state for a beat, then hands over to the next one. */
@keyframes pipe-lit {
  0%, 4%    { color: var(--ink-40); border-color: var(--hairline); box-shadow: none; }
  8%, 22%   { color: var(--ink); border-color: color-mix(in srgb, var(--blue) 55%, var(--hairline));
              box-shadow: 0 0 0 4px color-mix(in srgb, var(--blue) 9%, transparent); }
  34%, 100% { color: var(--ink-40); border-color: var(--hairline); box-shadow: none; }
}

/* Start it only once the section is on screen; site.js adds `.in`. */
.reveal.in .pipe-spark, .reveal.in .pipe-node { animation-play-state: running; }

/* The prompt node types its line, then the caret blinks out. */
.pipe-prompt { min-width: 210px; align-items: flex-start; }
.pipe-typed {
  display: block; overflow: hidden; white-space: nowrap;
  font-size: var(--fs-lead); font-weight: 500; color: var(--ink-60);
  border-right: 1.5px solid var(--blue);
  width: 0;
  animation: pipe-type var(--pipe-loop) steps(22, end) infinite, pipe-caret 1s step-end infinite;
  animation-play-state: paused;
}
.reveal.in .pipe-typed { animation-play-state: running; }
@keyframes pipe-type { 0% { width: 0 } 8% { width: 14ch } 82% { width: 14ch } 90%, 100% { width: 0 } }
@keyframes pipe-caret { 50% { border-color: transparent } }

/* The four agent lanes work in parallel - they light together, not in sequence. */
.pipe-agent { min-width: 112px; padding: 8px 14px; }
.pipe-agent b { font-weight: 600; }

.pipe-cap {
  margin-top: clamp(14px, 2vh, 22px);
  font-size: var(--fs-lead); color: var(--ink-40); letter-spacing: 0.01em;
}

/* The three stage wrappers generate no box on desktop, so the absolutely positioned
   diagram above is laid out exactly as if they were not there. They only become real
   containers below 900px, where they carry the labels, grouping and arrows. */
.pipe-stage { display: contents; }
.pipe-stage-label { display: none; }

@media (max-width: 900px) {
  /* Below this the 1440-wide stage turns to confetti, and a flat column of nine unlabelled
     boxes loses the whole point - you cannot tell the four agents are alternatives rather
     than four sequential steps. So the diagram becomes a real vertical flow: three named
     stages, an arrow carrying each into the next, and the agents grouped as the parallel
     choice they actually are. */
  .pipe { aspect-ratio: auto; min-height: 0; display: flex; flex-direction: column; gap: 0; }
  .pipe-svg { display: none; }
  .pipe-stage { display: flex; flex-direction: column; gap: 8px; }
  .pipe-stage-agents { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .pipe-stage-agents > .pipe-stage-label { grid-column: 1 / -1; }
  .pipe-stage-label {
    display: block;
    font-size: var(--fs-micro); font-weight: 600; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--ink-40);
  }
  /* The connector the SVG used to draw, as one glyph between stages. */
  .pipe-stage + .pipe-stage::before {
    content: "↓";
    display: block;
    margin: 14px 0 14px 15px;
    font-size: var(--fs-base); line-height: 1; color: var(--blue);
  }
  .pipe-stage-agents::before { grid-column: 1 / -1; }
  .pipe-node { position: static; transform: none; width: 100%; align-items: flex-start; animation: none;
    color: var(--ink); border-color: var(--hairline); }
  .pipe-agent { min-width: 0; }
  .pipe-typed { animation: none; width: auto; border-right: 0; }
}
@media (max-width: 420px) {
  /* Two agent columns get too narrow to hold "Claude Code" on one line here. */
  .pipe-stage-agents { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  .pipe-spark { animation: none; opacity: .55; stroke-dashoffset: 0; stroke-dasharray: none; }
  .pipe-node { animation: none; color: var(--ink); }
  .pipe-typed { animation: none; width: auto; border-right: 0; }
}
