/* landing_shots.css — the product illustrations on the landing page.
 *
 * These replaced six static PNG screenshots. A screenshot of a pipeline cannot
 * show the thing that makes it a pipeline: stages completing in order, a bar
 * filling, a status flipping to green. It shows one frozen instant and asks
 * the reader to imagine the rest — which is the whole reason the hero topology
 * and the AI mesh were built as live drawings in the first place. These six
 * finish that job, and take 2.8 MB of PNG out of the page with them.
 *
 * ── Why HTML and CSS rather than SVG ──────────────────────────────────────
 * The hero topology is a graph, so it is SVG: nodes at coordinates, edges
 * between them. These are user interfaces — rows, cards, tables, a terminal —
 * and laying those out by hand in a viewBox means recomputing every x when a
 * label changes. Flexbox and grid already do that. The one drawn diagram here,
 * the narrative timeline, is inline SVG for the same reason the mesh is.
 *
 * ── Scaling ───────────────────────────────────────────────────────────────
 * Each mock is authored at one size and scales with its frame through a
 * container query: the frame declares `container-type: inline-size` and every
 * length inside is in `em`, with the root em set from `cqw`. One number moves
 * and the whole mock follows, so a mock never needs a media query of its own.
 * The `px` declaration before each `cqw` is the fallback for a browser without
 * container queries — it renders at a fixed size rather than at nothing.
 *
 * ── Motion ────────────────────────────────────────────────────────────────
 * Everything animated here is decoration: it repeats, it carries no
 * information the static frame does not already show, and the last rule in
 * this file switches all of it off under prefers-reduced-motion. That is why
 * the animations may loop indefinitely without trapping anyone who cannot
 * tolerate them — and why each mock's final state, not its first, is the one
 * that reads correctly with motion disabled.
 */

/* ── Shared shell ─────────────────────────────────────────────────────── */

.lp-shot-frame { container-type: inline-size; }

/* On a phone the frame is a third of its desktop width, and scaling a full
   screen into it proportionally leaves type nobody can read — the mock becomes
   a texture. Trading rows for size is the better bargain: the same mock, fewer
   of its repeating elements, at a size that still says what it is. Only
   repeated rows are dropped, never a label or a status, so nothing the
   illustration claims disappears with them. */
@container (max-width: 470px) {
  .lps { font-size: 3.5cqw; padding: 1.2em; gap: .7em; }
  .lps-person:nth-child(n+5),
  .lps-pkt:nth-child(n+7),
  .lps-spec:nth-child(n+5),
  .lps-chip:nth-child(n+5),
  .lps-persona:nth-child(n+4) { display: none; }
  /* Three tiles, chosen rather than truncated: dropping the last two would
     take Overdue with them, and "how many people are late" is the number the
     whole view exists to surface. Enrolled and Credentials go instead. */
  .lps-stats { grid-template-columns: repeat(3, 1fr); }
  .lps-stat:nth-child(2), .lps-stat:nth-child(5) { display: none; }
  .lps-specs { grid-template-columns: repeat(2, 1fr); }
}

/* The row stretches its visual column to match the text beside it, which left
   a band of bare card below every mock — the frame kept its 16/10 while the
   card grew. Centring the card instead of stretching it is the fix that keeps
   the mock at the proportions it was drawn for; letting the frame absorb the
   slack instead just moved the empty space inside the screen, where it read as
   a half-loaded page. */
.lp-feat .lp-feat-vis { align-self: center; }
.lp-shot { display: flex; flex-direction: column; }

.lps {
  position: absolute; inset: 0;
  font-size: 13px;               /* fallback: no container query support */
  font-size: 2.32cqw;
  font-family: Inter, 'Segoe UI', system-ui, Arial, sans-serif;
  line-height: 1.35;
  padding: 1.5em;
  display: flex; flex-direction: column; gap: .95em;
  overflow: hidden;
  --lps-ink: #14251b;
  --lps-dim: #6d8a7a;
  --lps-line: #dbe7df;
  --lps-card: #ffffff;
  --lps-go: #0a9e4b;
  --lps-glow: #2ee27c;
  --lps-warn: #d97706;
  color: var(--lps-ink);
}
.lps-dark {
  --lps-ink: #dff6e7;
  --lps-dim: #7fae90;
  --lps-line: rgba(46, 226, 124, .16);
  --lps-card: rgba(255, 255, 255, .04);
  background: linear-gradient(158deg, #0b2318, #071a12 70%);
  border-radius: .5em;
}
.lps-violet {
  background: linear-gradient(158deg, #140f24, #0b0817 70%);
  border-radius: .5em;
  --lps-ink: #ece3ff;
  --lps-dim: #9d8ac4;
  --lps-line: rgba(167, 139, 250, .2);
  --lps-card: rgba(167, 139, 250, .07);
  --lps-go: #a78bfa;
  --lps-glow: #c4b5fd;
}

.lps-row { display: flex; align-items: center; gap: .7em; }
.lps-h {
  font-size: .78em; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--lps-dim);
}
.lps-card {
  background: var(--lps-card); border: 1px solid var(--lps-line);
  border-radius: .55em; padding: .6em .75em;
}
.lps-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* A dot that settles on green once its stage is done. */
.lps-dot {
  width: .62em; height: .62em; border-radius: 50%; flex: none;
  background: var(--lps-line); border: 1px solid var(--lps-line);
}
.lps-dot.on { background: var(--lps-go); border-color: var(--lps-go); }

/* The two bands that carry their own palette: the frame behind the mock has to
   agree with it, or a rounded corner shows a strip of the light canvas. */
.lp-shot--lore .lp-shot-frame { background: #0d0a18; }
.lp-shot--card .lp-shot-frame { background: #0b2318; }

/* ── 1. Provisioning pipeline ─────────────────────────────────────────── */

.lps-deploy { justify-content: space-between; }
.lps-stage {
  display: grid; grid-template-columns: 1.5em 1fr auto; align-items: center;
  gap: .7em; padding: .5em .7em; border-radius: .5em;
  border: 1px solid transparent; font-size: .95em;
}
.lps-stage b { font-weight: 700; }
.lps-stage .lps-when { font-size: .8em; color: var(--lps-dim); font-variant-numeric: tabular-nums; }
.lps-stage .lps-mark {
  width: 1.5em; height: 1.5em; border-radius: 50%; display: grid; place-items: center;
  border: 1.5px solid var(--lps-line); color: transparent; font-size: .72em; font-weight: 900;
}
.lps-stage.done .lps-mark { background: var(--lps-go); border-color: var(--lps-go); color: #fff; }
.lps-stage.done { background: rgba(10, 158, 75, .05); border-color: rgba(10, 158, 75, .16); }

.lps-bar {
  height: .55em; border-radius: 999px; background: var(--lps-line); overflow: hidden;
}
.lps-bar i {
  display: block; height: 100%; width: 100%; border-radius: inherit;
  background: linear-gradient(90deg, var(--lps-go), var(--lps-glow));
  transform-origin: left center;
}
.lps-url {
  font-size: .82em; color: var(--lps-go); font-weight: 700;
  overflow: hidden; white-space: nowrap;
}

/* One 11s cycle, and every element resets on the same frame.
 *
 * The obvious way to stagger four stages is one keyframe set plus four
 * animation-delays. That is wrong here, and visibly so: a delay shifts the
 * whole timeline, so each stage also *ends* at its own moment, and for the
 * 1.5s between stage three resetting and stage four resetting the mock shows
 * "deploy" complete while "validate" is not. A pipeline that claims a later
 * step finished before an earlier one is worse than no animation at all.
 *
 * So the stagger lives in the keyframes instead — same duration, no delay,
 * each stage turning on at its own percentage and every one of them dropping
 * back together at 96%. The cost is four near-identical blocks; the benefit is
 * that the illustration cannot contradict itself.
 */
.lps-deploy .lps-stage { background: transparent; border-color: transparent; }
.lps-deploy .lps-stage .lps-mark { background: transparent; border-color: var(--lps-line); color: transparent; }

.lps-deploy .lps-stage:nth-child(2) { animation: lpsStage1 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(3) { animation: lpsStage2 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(4) { animation: lpsStage3 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(5) { animation: lpsStage4 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(2) .lps-mark { animation: lpsMark1 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(3) .lps-mark { animation: lpsMark2 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(4) .lps-mark { animation: lpsMark3 11s linear infinite; }
.lps-deploy .lps-stage:nth-child(5) .lps-mark { animation: lpsMark4 11s linear infinite; }

@keyframes lpsStage1 { 0%,5% { background: transparent; border-color: transparent; }
  6%,96% { background: rgba(10,158,75,.05); border-color: rgba(10,158,75,.16); }
  97%,100% { background: transparent; border-color: transparent; } }
@keyframes lpsStage2 { 0%,19% { background: transparent; border-color: transparent; }
  20%,96% { background: rgba(10,158,75,.05); border-color: rgba(10,158,75,.16); }
  97%,100% { background: transparent; border-color: transparent; } }
@keyframes lpsStage3 { 0%,33% { background: transparent; border-color: transparent; }
  34%,96% { background: rgba(10,158,75,.05); border-color: rgba(10,158,75,.16); }
  97%,100% { background: transparent; border-color: transparent; } }
@keyframes lpsStage4 { 0%,47% { background: transparent; border-color: transparent; }
  48%,96% { background: rgba(10,158,75,.05); border-color: rgba(10,158,75,.16); }
  97%,100% { background: transparent; border-color: transparent; } }

@keyframes lpsMark1 { 0%,5% { background: transparent; border-color: var(--lps-line); color: transparent; }
  6%,96% { background: var(--lps-go); border-color: var(--lps-go); color: #fff; }
  97%,100% { background: transparent; border-color: var(--lps-line); color: transparent; } }
@keyframes lpsMark2 { 0%,19% { background: transparent; border-color: var(--lps-line); color: transparent; }
  20%,96% { background: var(--lps-go); border-color: var(--lps-go); color: #fff; }
  97%,100% { background: transparent; border-color: var(--lps-line); color: transparent; } }
@keyframes lpsMark3 { 0%,33% { background: transparent; border-color: var(--lps-line); color: transparent; }
  34%,96% { background: var(--lps-go); border-color: var(--lps-go); color: #fff; }
  97%,100% { background: transparent; border-color: var(--lps-line); color: transparent; } }
@keyframes lpsMark4 { 0%,47% { background: transparent; border-color: var(--lps-line); color: transparent; }
  48%,96% { background: var(--lps-go); border-color: var(--lps-go); color: #fff; }
  97%,100% { background: transparent; border-color: var(--lps-line); color: transparent; } }

.lps-bar { margin-top: auto; }
.lps-deploy .lps-bar i { animation: lpsFill 11s cubic-bezier(.35,.1,.2,1) infinite; }
@keyframes lpsFill {
  0%, 5% { transform: scaleX(.02); } 19% { transform: scaleX(.26); }
  33% { transform: scaleX(.5); } 47% { transform: scaleX(.72); }
  62%, 96% { transform: scaleX(1); } 100% { transform: scaleX(.02); }
}
.lps-deploy .lps-url { animation: lpsUrl 11s steps(1) infinite; }
@keyframes lpsUrl { 0%, 63% { opacity: 0; } 64%, 96% { opacity: 1; } 97%, 100% { opacity: 0; } }

.lps-infra { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5em; }
.lps-infra > span {
  display: flex; align-items: center; gap: .4em; font-size: .76em; color: var(--lps-dim);
}
.lps-infra > span:nth-child(1) .lps-dot { animation: lpsDot1 11s steps(1) infinite; }
.lps-infra > span:nth-child(2) .lps-dot { animation: lpsDot2 11s steps(1) infinite; }
.lps-infra > span:nth-child(3) .lps-dot { animation: lpsDot3 11s steps(1) infinite; }
.lps-infra > span:nth-child(4) .lps-dot { animation: lpsDot4 11s steps(1) infinite; }
@keyframes lpsDot1 { 0%,49% { background: var(--lps-line); } 50%,96% { background: var(--lps-go); } 97%,100% { background: var(--lps-line); } }
@keyframes lpsDot2 { 0%,52% { background: var(--lps-line); } 53%,96% { background: var(--lps-go); } 97%,100% { background: var(--lps-line); } }
@keyframes lpsDot3 { 0%,55% { background: var(--lps-line); } 56%,96% { background: var(--lps-go); } 97%,100% { background: var(--lps-line); } }
@keyframes lpsDot4 { 0%,58% { background: var(--lps-line); } 59%,96% { background: var(--lps-go); } 97%,100% { background: var(--lps-line); } }

/* ── 2. Challenge library ─────────────────────────────────────────────── */

.lps-chips { display: flex; gap: .35em; flex-wrap: wrap; }
.lps-chip {
  font-size: .72em; font-weight: 700; padding: .3em .7em; border-radius: 999px;
  border: 1px solid var(--lps-line); color: var(--lps-dim); white-space: nowrap;
}
.lps-catalog .lps-chip { animation: lpsChip 10s steps(1) infinite; }
.lps-catalog .lps-chip:nth-child(1) { animation-delay: 0s; }
.lps-catalog .lps-chip:nth-child(2) { animation-delay: 2s; }
.lps-catalog .lps-chip:nth-child(3) { animation-delay: 4s; }
.lps-catalog .lps-chip:nth-child(4) { animation-delay: 6s; }
.lps-catalog .lps-chip:nth-child(5) { animation-delay: 8s; }
@keyframes lpsChip {
  0%, 19% { background: rgba(10,158,75,.1); border-color: var(--lps-go); color: var(--lps-go); }
  20%, 100% { background: transparent; border-color: var(--lps-line); color: var(--lps-dim); }
}

.lps-specs { display: grid; grid-template-columns: repeat(3, 1fr); gap: .55em; flex: 1; }
.lps-spec {
  border: 1px solid var(--lps-line); border-radius: .5em; padding: .55em .6em;
  display: flex; flex-direction: column; gap: .28em; background: var(--lps-card);
}
.lps-spec b { font-size: .8em; font-weight: 700; line-height: 1.25; }
.lps-spec span { font-size: .68em; color: var(--lps-dim); }
.lps-spec em {
  font-style: normal; font-size: .64em; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--lps-go); margin-top: auto;
}
.lps-catalog .lps-spec { animation: lpsSpec 10s ease-in-out infinite; }
.lps-catalog .lps-spec:nth-child(1) { animation-delay: .2s; }
.lps-catalog .lps-spec:nth-child(2) { animation-delay: 1.9s; }
.lps-catalog .lps-spec:nth-child(3) { animation-delay: 3.6s; }
.lps-catalog .lps-spec:nth-child(4) { animation-delay: 5.3s; }
.lps-catalog .lps-spec:nth-child(5) { animation-delay: 7s; }
.lps-catalog .lps-spec:nth-child(6) { animation-delay: 8.7s; }
@keyframes lpsSpec {
  0%, 6% { border-color: var(--lps-go); box-shadow: 0 0 0 2px rgba(10,158,75,.12); }
  14%, 100% { border-color: var(--lps-line); box-shadow: 0 0 0 0 rgba(10,158,75,0); }
}

.lps-scale { display: flex; align-items: center; gap: .45em; font-size: .7em; color: var(--lps-dim); }
.lps-scale i {
  flex: 1; height: .3em; border-radius: 999px; position: relative;
  background: linear-gradient(90deg, #7fd6a3, #0a9e4b 40%, #d97706 75%, #b3261e);
}
.lps-scale i::after {
  content: ""; position: absolute; top: 50%; width: .85em; height: .85em; border-radius: 50%;
  background: #fff; border: 2px solid var(--lps-ink); transform: translate(-50%, -50%);
  animation: lpsScale 10s cubic-bezier(.5,0,.5,1) infinite;
}
@keyframes lpsScale {
  0%, 8% { left: 12%; } 25% { left: 38%; } 50% { left: 62%; }
  75% { left: 86%; } 92%, 100% { left: 12%; }
}

/* ── 3. Workbench (terminal on our side of the wire) ──────────────────── */

.lps-wb { gap: .55em; }
.lps-wb-top { display: flex; align-items: center; gap: .5em; }
.lps-tag {
  font-size: .66em; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  padding: .22em .6em; border-radius: 999px; border: 1px solid;
}
.lps-tag--off { color: #ff9b9b; border-color: rgba(255,155,155,.4); background: rgba(255,90,90,.1); }
.lps-tag--on { color: var(--lps-glow); border-color: rgba(46,226,124,.4); background: rgba(46,226,124,.1); }
.lps-prompt { font-size: .8em; }
.lps-prompt .lps-ps { color: var(--lps-glow); }
.lps-type {
  display: inline-block; overflow: hidden; white-space: nowrap; vertical-align: bottom;
  border-right: .12em solid var(--lps-glow);
  animation: lpsType 9s steps(46) infinite, lpsCaret .9s steps(1) infinite;
}
@keyframes lpsType { 0% { width: 0; } 34%, 92% { width: 27em; } 100% { width: 0; } }
@keyframes lpsCaret { 50% { border-color: transparent; } }

.lps-pkts { flex: 1; display: flex; flex-direction: column; gap: .18em; font-size: .72em; }
.lps-pkt {
  display: grid; grid-template-columns: 3.2em 6.4em 6.4em 3.4em 1fr; gap: .5em;
  padding: .22em .45em; border-radius: .3em; color: var(--lps-dim);
  opacity: 0; animation: lpsPkt 9s steps(1) infinite;
}
.lps-pkt b { color: var(--lps-ink); font-weight: 600; }
.lps-pkt.hit { background: rgba(46,226,124,.1); color: var(--lps-glow); }
.lps-pkt.hit b { color: var(--lps-glow); }
.lps-pkt:nth-child(1) { animation-delay: 3.4s; }
.lps-pkt:nth-child(2) { animation-delay: 3.8s; }
.lps-pkt:nth-child(3) { animation-delay: 4.2s; }
.lps-pkt:nth-child(4) { animation-delay: 4.6s; }
.lps-pkt:nth-child(5) { animation-delay: 5.0s; }
.lps-pkt:nth-child(6) { animation-delay: 5.4s; }
.lps-pkt:nth-child(7) { animation-delay: 5.8s; }
.lps-pkt:nth-child(8) { animation-delay: 6.2s; }
.lps-pkt:nth-child(9) { animation-delay: 6.6s; }
.lps-pkt:nth-child(10) { animation-delay: 7.0s; }
.lps-wb-foot {
  margin-top: auto; font-size: .68em; color: var(--lps-dim);
  border-top: 1px solid var(--lps-line); padding-top: .45em;
  opacity: 0; animation: lpsPop 9s steps(1) infinite; animation-delay: 7.4s;
}
@keyframes lpsPkt { 0% { opacity: 0; } 1%, 94% { opacity: 1; } 100% { opacity: 0; } }

/* ── 4. Universe bible ────────────────────────────────────────────────── */

.lps-lore { flex-direction: row; gap: 1.1em; }
.lps-lore-col { display: flex; flex-direction: column; gap: .45em; flex: 1; min-width: 0; }
.lps-persona {
  display: flex; align-items: center; gap: .55em; padding: .45em .6em;
  border: 1px solid var(--lps-line); border-radius: .5em; background: var(--lps-card);
  opacity: 0; transform: translateY(.5em); animation: lpsRise 12s ease-out infinite;
}
.lps-persona .lps-av {
  width: 1.7em; height: 1.7em; border-radius: 50%; flex: none;
  background: linear-gradient(140deg, #7c3aed, #a78bfa); display: grid; place-items: center;
  font-size: .62em; font-weight: 800; color: #fff;
}
.lps-persona b { font-size: .78em; font-weight: 700; display: block; }
.lps-persona span { font-size: .66em; color: var(--lps-dim); }
.lps-lore .lps-persona:nth-child(2) { animation-delay: .3s; }
.lps-lore .lps-persona:nth-child(3) { animation-delay: .9s; }
.lps-lore .lps-persona:nth-child(4) { animation-delay: 1.5s; }
@keyframes lpsRise {
  0% { opacity: 0; transform: translateY(.5em); }
  6%, 94% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(.5em); }
}

.lps-tl { flex: 1; width: 100%; height: 100%; }
.lps-tl-spine {
  fill: none; stroke: rgba(167,139,250,.45); stroke-width: 1.6; stroke-linecap: round;
  stroke-dasharray: 300; stroke-dashoffset: 300;
  animation: lpsDraw 12s cubic-bezier(.4,0,.3,1) infinite;
}
@keyframes lpsDraw { 0% { stroke-dashoffset: 300; } 30%, 94% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 300; } }
.lps-tl-node { fill: #0d0a18; stroke: #a78bfa; stroke-width: 1.6; opacity: 0;
  animation: lpsPop 12s ease-out infinite; }
.lps-tl-txt { fill: #ece3ff; font-size: 9px; font-weight: 600; opacity: 0;
  animation: lpsPop 12s ease-out infinite; }
.lps-tl-date { fill: #9d8ac4; font-size: 8px; font-family: ui-monospace, monospace; opacity: 0;
  animation: lpsPop 12s ease-out infinite; }
.lps-tl [data-n="1"] { animation-delay: 2.0s; }
.lps-tl [data-n="2"] { animation-delay: 2.8s; }
.lps-tl [data-n="3"] { animation-delay: 3.6s; }
.lps-tl [data-n="4"] { animation-delay: 4.4s; }
@keyframes lpsPop { 0% { opacity: 0; } 4%, 94% { opacity: 1; } 100% { opacity: 0; } }
.lps-tl-core { fill: rgba(167,139,250,.16); stroke: #c4b5fd; stroke-width: 1.4;
  animation: lpsPulse 3.2s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
@keyframes lpsPulse { 50% { opacity: .55; transform: scale(1.08); } }

/* ── 5. MCP client ────────────────────────────────────────────────────── */

.lps-mcp { gap: .6em; }
.lps-json {
  font-size: .74em; line-height: 1.55; white-space: pre; overflow: hidden;
  color: var(--lps-dim);
}
.lps-json em { font-style: normal; }
.lps-json .k { color: var(--lps-glow); }
.lps-json .s { color: #ffd479; }
/* Reserved height, revealed by a wipe. Animating max-height instead made the
   tool list below jump up and down through every cycle, which is the one thing
   a mock of a config file should not do. */
.lps-mcp .lps-json { height: 8.2em; }
.lps-mcp .lps-json > span {
  display: block; opacity: 0; animation: lpsPop 10s steps(1) infinite;
}
.lps-mcp .lps-json > span:nth-child(1) { animation-delay: .3s; }
.lps-mcp .lps-json > span:nth-child(2) { animation-delay: .7s; }
.lps-mcp .lps-json > span:nth-child(3) { animation-delay: 1.1s; }
.lps-mcp .lps-json > span:nth-child(4) { animation-delay: 1.5s; }
.lps-mcp .lps-json > span:nth-child(5) { animation-delay: 1.9s; }
.lps-mcp .lps-json > span:nth-child(6) { animation-delay: 2.3s; }
.lps-mcp .lps-json > span:nth-child(7) { animation-delay: 2.7s; }
.lps-call {
  margin-top: auto; font-size: .74em; display: flex; flex-direction: column; gap: .2em;
  border-top: 1px solid var(--lps-line); padding-top: .5em;
}
.lps-call span { opacity: 0; animation: lpsPop 10s steps(1) infinite; }
.lps-call span:nth-child(1) { animation-delay: 6.2s; }
.lps-call span:nth-child(2) { animation-delay: 7.0s; }
.lps-call .ok { color: var(--lps-glow); }
.lps-tools { display: flex; flex-direction: column; gap: .3em; }
.lps-tool {
  display: flex; align-items: center; gap: .5em; font-size: .74em;
  padding: .3em .55em; border-radius: .4em; border: 1px solid var(--lps-line);
  opacity: 0; animation: lpsPop 10s ease-out infinite;
}
.lps-tool span { color: var(--lps-dim); margin-left: auto; font-size: .88em; }
.lps-tools .lps-tool:nth-child(1) { animation-delay: 4.4s; }
.lps-tools .lps-tool:nth-child(2) { animation-delay: 4.9s; }
.lps-tools .lps-tool:nth-child(3) { animation-delay: 5.4s; }

/* ── 6. Manager module ────────────────────────────────────────────────── */

.lps-mgr { gap: .7em; }
.lps-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: .45em; }
.lps-stat {
  border: 1px solid var(--lps-line); border-radius: .5em; padding: .45em .55em;
  background: var(--lps-card);
}
.lps-stat .k { font-size: .62em; color: var(--lps-dim); text-transform: uppercase; letter-spacing: .07em; }
.lps-stat .v { font-size: 1.15em; font-weight: 800; font-variant-numeric: tabular-nums; }
.lps-stat.warn .v { color: var(--lps-warn); }

.lps-people { display: flex; flex-direction: column; gap: .3em; flex: 1; }
.lps-person { display: grid; grid-template-columns: 1fr 6em 3.6em; align-items: center; gap: .6em;
  font-size: .76em; padding: .28em .2em; border-bottom: 1px solid var(--lps-line); }
.lps-person:last-child { border-bottom: 0; }
.lps-person .who b { font-weight: 600; }
.lps-person .who span { color: var(--lps-dim); font-size: .84em; display: block; }
.lps-track { height: .42em; border-radius: 999px; background: var(--lps-line); overflow: hidden; }
.lps-track i { display: block; height: 100%; border-radius: inherit; background: var(--lps-go);
  transform-origin: left center; animation: lpsTrack 7s cubic-bezier(.3,.1,.2,1) infinite; }
@keyframes lpsTrack { 0% { transform: scaleX(.04); } 55%, 92% { transform: scaleX(1); } 100% { transform: scaleX(.04); } }
.lps-person:nth-child(2) .lps-track i { animation-delay: .35s; }
.lps-person:nth-child(3) .lps-track i { animation-delay: .7s; }
.lps-person:nth-child(4) .lps-track i { animation-delay: 1.05s; }
.lps-person .st { font-size: .82em; font-weight: 700; text-align: right; color: var(--lps-go); }
.lps-person .st.late { color: var(--lps-warn); }
.lps-person .lps-track i.late { background: var(--lps-warn); animation-name: lpsTrackLate; }
@keyframes lpsTrackLate { 0% { transform: scaleX(.04); } 55%, 92% { transform: scaleX(.42); } 100% { transform: scaleX(.04); } }

.lps-lrs { display: flex; align-items: center; gap: .5em; font-size: .72em; color: var(--lps-dim); }
.lps-lrs .wire { flex: 1; height: 1px; background: var(--lps-line); position: relative; }
.lps-lrs .wire::after {
  content: ""; position: absolute; top: -.18em; width: .45em; height: .45em; border-radius: 50%;
  background: var(--lps-glow); box-shadow: 0 0 .5em var(--lps-glow);
  animation: lpsWire 2.6s linear infinite;
}
@keyframes lpsWire { 0% { left: 0; opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { left: 100%; opacity: 0; } }

/* ── Motion off ───────────────────────────────────────────────────────── */
/* Every mock is authored so its *end* state is the readable one, which is why
   forcing the animations to their final frame rather than their first is what
   makes this rule correct rather than merely quiet. */
@media (prefers-reduced-motion: reduce) {
  .lps *, .lps { animation: none !important; }
  .lps-bar i, .lps-track i { transform: scaleX(1); }
  .lps-track i.late { transform: scaleX(.42); }
  .lps-pkt, .lps-persona, .lps-tool, .lps-url, .lps-wb-foot,
  .lps-json > span, .lps-call span,
  .lps-tl-node, .lps-tl-txt, .lps-tl-date { opacity: 1; transform: none; }
  .lps-tl-spine { stroke-dashoffset: 0; }
  .lps-type { width: auto; border-right: 0; }
  /* Selector for selector with the animated state, because that is what these
     have to beat. The deploy mock declares its off state at .lps-deploy .lps-stage
     — two classes — so a bare .lps-stage here loses, and the page ends up
     showing a full progress bar and a live URL above four unticked stages.
     Which is the exact contradiction this block exists to prevent. */
  .lps-deploy .lps-stage {
    background: rgba(10, 158, 75, .05); border-color: rgba(10, 158, 75, .16);
  }
  .lps-deploy .lps-stage .lps-mark {
    background: var(--lps-go); border-color: var(--lps-go); color: #fff;
  }
  .lps-infra .lps-dot { background: var(--lps-go); }
  .lps-scale i::after { left: 62%; }
  /* Scoped: the lore panel uses chips for places, and an unscoped rule painted
     one of them in the catalog's green inside a violet frame. */
  .lps-catalog .lps-chip:first-child {
    background: rgba(10,158,75,.1); border-color: var(--lps-go); color: var(--lps-go);
  }
}
