/* Git-graph system: main/session x40, task x88; stations on a 56px grid.
   One 12s clock: draw/travel 0–75%, settle 75–90%, fade 90–98%, reset hidden.
   Only 4px task/report tokens travel; lines reveal ahead, labels keep arrival color.
   Cross-audit alone has parallel tokens, slightly staggered within the same clock.
   Dependency waves reveal together; one token traces them. Kept work lasts to the end. */
.explainer { margin: 2rem 0; min-width: 0; }
.explainer svg { display: block; width: 100%; max-width: 420px; height: auto; overflow: visible; }
.explainer text { fill: var(--ink); font-family: var(--mono); font-size: 11px; }
.explainer .detail { fill: var(--muted); font-size: 9px; }
.explainer path { fill: none; stroke: var(--accent); stroke-width: 1.5; }
.explainer .baseline { stroke: var(--line); }
.explainer figcaption { max-width: 65ch; margin-top: 1rem; font-size: .9rem; color: var(--muted); }
.capabilities .explainer { grid-column: 3; margin-block: 1.5rem .5rem; }
@media (max-width: 800px) {
  .capabilities .explainer { grid-column: 1 / -1; }
}
.graph { --cycle: 12s; --travel: cubic-bezier(.65, 0, .35, 1); }
.graph svg { max-width: 420px; }
.graph text { font-size: 11px; }
.graph .detail { font-size: 9px; }
.graph path { stroke-width: 1.25; }
.graph .station { fill: var(--bg); stroke: var(--accent); stroke-width: 1.25; }
.graph .token, .graph .salvage { fill: var(--accent); }
.graph .token { transform: translate(40px, 312px); }
.graph .custody-token { transform: translate(88px, 208px); opacity: 0; }
.graph .retry-token { transform: translate(136px, 312px); }
.graph .verify-ring { opacity: 0; }
.graph .failure-mark { stroke: var(--accent); }
.graph .arrival { fill: var(--accent); }
.hero > .graph { margin-inline: max(24px, calc((100% - 1120px) / 2)); }
@media (min-width: 1100px) {
  .hero > .graph { position: absolute; top: 2rem; right: 0; width: 320px; margin-block: 0; }
  .hero .hero-description, .hero .install { max-width: 650px; }
}
@media (prefers-reduced-motion: no-preference) {
  .graph .story { animation: graph-cycle var(--cycle) ease infinite; }
  .graph .branch { stroke-dasharray: 100; animation: graph-draw var(--cycle) var(--travel) infinite; }
  .graph .kept { animation-name: kept-draw; }
  .graph .retry-branch { animation-name: retry-draw; }
  .graph .token { animation: lifecycle-travel var(--cycle) var(--travel) infinite; }
  .graph .custody-token { animation-name: custody-travel; }
  .graph .retry-token { animation-name: retry-travel; }
  .graph .arrival { animation: arrive-advise var(--cycle) ease infinite; }
  .graph .run { animation-name: arrive-run; }
  .graph .verify { animation-name: arrive-verify; }
  .graph .show { animation-name: arrive-show; }
  .graph .retry { animation-name: arrive-retry; }
  .graph .accept { animation-name: arrive-accept; }
  .graph .failure-mark { animation: failure-arrives var(--cycle) ease infinite; }
  .graph .verify-ring { animation: ring-leaves var(--cycle) ease infinite; }
  .graph .salvage { animation: salvage-arrives var(--cycle) ease infinite; }
  .graph.motion-ready:not(.is-seen) .story,
  .graph.motion-ready:not(.is-seen) .story * { animation-play-state: paused; }
  @keyframes graph-cycle { 0%, 98%, 100% { opacity: 0; } 5%, 90% { opacity: 1; } }
  @keyframes graph-draw {
    0%, 5% { stroke-dashoffset: 100; } 17% { stroke-dashoffset: 78; }
    31% { stroke-dashoffset: 60; } 47% { stroke-dashoffset: 41; }
    63% { stroke-dashoffset: 22; } 73%, 100% { stroke-dashoffset: 0; }
  }
  @keyframes lifecycle-travel {
    0%, 8% { transform: translate(40px, 48px); }
    20%, 25% { transform: translate(88px, 96px); }
    35%, 41% { transform: translate(88px, 152px); }
    51%, 57% { transform: translate(88px, 208px); }
    67% { transform: translate(88px, 264px); }
    75%, 100% { transform: translate(40px, 312px); }
  }
  @keyframes kept-draw {
    0%, 5% { stroke-dashoffset: 100; } 17% { stroke-dashoffset: 70; }
    31% { stroke-dashoffset: 35; } 47%, 100% { stroke-dashoffset: 0; }
  }
  @keyframes custody-travel {
    0%, 8% { transform: translate(40px, 48px); }
    20%, 25% { transform: translate(88px, 96px); }
    35%, 41% { transform: translate(88px, 152px); }
    51%, 100% { transform: translate(88px, 208px); }
    0%, 53% { opacity: 1; } 55%, 100% { opacity: 0; }
  }
  @keyframes retry-draw {
    0%, 55% { stroke-dashoffset: 100; } 64% { stroke-dashoffset: 45; }
    73%, 100% { stroke-dashoffset: 0; }
  }
  @keyframes retry-travel {
    0%, 55% { transform: translate(88px, 208px); opacity: 0; }
    57% { transform: translate(88px, 208px); opacity: 1; }
    67%, 70% { transform: translate(136px, 256px); opacity: 1; }
    75%, 100% { transform: translate(136px, 312px); opacity: 1; }
  }
  @keyframes arrive-advise { 0% { fill: var(--muted); } 8%, 100% { fill: var(--accent); } }
  @keyframes arrive-run { 0%, 17% { fill: var(--muted); } 20%, 100% { fill: var(--accent); } }
  @keyframes arrive-verify { 0%, 32% { fill: var(--muted); } 35%, 100% { fill: var(--accent); } }
  @keyframes arrive-show { 0%, 48% { fill: var(--muted); } 51%, 100% { fill: var(--accent); } }
  @keyframes arrive-retry { 0%, 64% { fill: var(--muted); } 67%, 100% { fill: var(--accent); } }
  @keyframes arrive-accept { 0%, 72% { fill: var(--muted); } 75%, 100% { fill: var(--accent); } }
  @keyframes failure-arrives { 0%, 34% { opacity: 0; } 36%, 100% { opacity: 1; } }
  @keyframes ring-leaves { 0%, 34% { opacity: 1; } 36%, 100% { opacity: 0; } }
  @keyframes salvage-arrives {
    0%, 48% { fill: var(--bg); } 51%, 100% { fill: var(--accent); }
  }
}

.graph .auxiliary { stroke: var(--line); }
.graph .execution-token { opacity: 0; }
.graph .report-token { transform: translate(40px, 312px); }
.graph .routing-token { transform: translate(40px, 312px); }
.graph .batch-token { transform: translate(40px, 312px); }
.graph .stop-token { transform: translate(88px, 208px); }
.graph .audit-a { --lane: 88px; }
.graph .audit-b { --lane: 136px; }
.graph .audit-c { --lane: 184px; }
.graph .audit-token { transform: translate(40px, 312px); }
.graph .verdict-glyph { stroke: var(--bg); }
@media (prefers-reduced-motion: no-preference) {
  .graph .execution-token { animation-name: execution-travel; }
  .graph .report-token { animation-name: report-travel; }
  .graph .routing-token { animation-name: routing-travel; }
  .graph .batch-token { animation-name: batch-travel; }
  .graph .stop-token { animation-name: stop-travel; }
  .graph .wave-a, .graph .wave-b { animation-name: first-wave; }
  .graph .wave-next { animation-name: next-wave; }
  .graph .held-route { stroke: var(--muted); }
  .graph .audit-token { animation-name: audit-travel; }
  .graph .audit-token.audit-b { animation-name: audit-travel-b; }
  .graph .audit-token.audit-c { animation-name: audit-travel-c; }
  .graph .branch.audit-a, .graph .branch.audit-b, .graph .branch.audit-c { animation-name: audit-draw; }
  .graph .detected { animation-name: detection-arrives; }
  .graph .disagreement { animation-name: disagreement-arrives; }
  .graph .verdict-glyph { animation: verdict-arrives var(--cycle) ease infinite; }
  .graph .verdict-b { animation-name: verdict-arrives-b; }
  .graph .verdict-c { animation-name: verdict-arrives-c; }
  .graph .audit-verdict-a { animation-name: verdict-label-a; }
  .graph .audit-verdict-b { animation-name: arrive-retry; }
  .graph .audit-verdict-c { animation-name: verdict-label-c; }
  @keyframes execution-travel {
    0%, 8% { transform: translate(40px, 48px); opacity: 1; }
    20%, 25% { transform: translate(88px, 96px); }
    35%, 41% { transform: translate(88px, 152px); }
    51%, 57% { transform: translate(88px, 208px); }
    66% { transform: translate(88px, 264px); opacity: 1; }
    67%, 100% { transform: translate(88px, 264px); opacity: 0; }
  }
  @keyframes report-travel {
    0%, 67% { transform: translate(88px, 264px); opacity: 0; }
    68% { transform: translate(88px, 264px); opacity: 1; }
    75%, 100% { transform: translate(40px, 312px); opacity: 1; }
  }
  @keyframes routing-travel {
    0%, 8% { transform: translate(40px, 48px); }
    20%, 25% { transform: translate(88px, 96px); }
    35%, 41% { transform: translate(136px, 152px); }
    51%, 57% { transform: translate(136px, 208px); }
    67% { transform: translate(136px, 264px); }
    75%, 100% { transform: translate(40px, 312px); }
  }
  @keyframes batch-travel {
    0%, 8% { transform: translate(40px, 48px); }
    20%, 25% { transform: translate(88px, 96px); }
    35%, 41% { transform: translate(112px, 152px); }
    51%, 57% { transform: translate(112px, 208px); }
    67% { transform: translate(88px, 264px); }
    75%, 100% { transform: translate(40px, 312px); }
  }
  @keyframes stop-travel {
    0%, 8% { transform: translate(40px, 48px); }
    20%, 25% { transform: translate(88px, 96px); }
    35%, 41% { transform: translate(88px, 152px); }
    51%, 100% { transform: translate(88px, 208px); }
  }
  @keyframes first-wave {
    0%, 5% { stroke-dashoffset: 100; } 17% { stroke-dashoffset: 35; }
    31%, 100% { stroke-dashoffset: 0; }
  }
  @keyframes next-wave {
    0%, 31% { stroke-dashoffset: 100; } 47% { stroke-dashoffset: 65; }
    63% { stroke-dashoffset: 25; } 73%, 100% { stroke-dashoffset: 0; }
  }
  @keyframes audit-draw {
    0%, 5% { stroke-dashoffset: 100; } 17% { stroke-dashoffset: 55; }
    31% { stroke-dashoffset: 40; } 47% { stroke-dashoffset: 25; }
    63%, 100% { stroke-dashoffset: 0; }
  }
  @keyframes audit-travel {
    0%, 8% { transform: translate(40px, 48px); }
    20%, 25% { transform: translate(var(--lane), 96px); }
    35%, 41% { transform: translate(var(--lane), 152px); }
    51%, 57% { transform: translate(var(--lane), 208px); }
    65% { transform: translate(var(--lane), 264px); }
    75%, 100% { transform: translate(40px, 312px); }
  }
  @keyframes audit-travel-b {
    0%, 10% { transform: translate(40px, 48px); }
    22%, 27% { transform: translate(var(--lane), 96px); }
    37%, 43% { transform: translate(var(--lane), 152px); }
    53%, 59% { transform: translate(var(--lane), 208px); }
    67% { transform: translate(var(--lane), 264px); }
    75%, 100% { transform: translate(40px, 312px); }
  }
  @keyframes audit-travel-c {
    0%, 12% { transform: translate(40px, 48px); }
    24%, 29% { transform: translate(var(--lane), 96px); }
    39%, 45% { transform: translate(var(--lane), 152px); }
    55%, 61% { transform: translate(var(--lane), 208px); }
    69% { transform: translate(var(--lane), 264px); }
    75%, 100% { transform: translate(40px, 312px); }
  }
  @keyframes verdict-arrives { 0%, 62% { opacity: 0; } 65%, 100% { opacity: 1; } }
  @keyframes verdict-arrives-b { 0%, 64% { opacity: 0; } 67%, 100% { opacity: 1; } }
  @keyframes verdict-arrives-c { 0%, 66% { opacity: 0; } 69%, 100% { opacity: 1; } }
  @keyframes verdict-label-a { 0%, 62% { fill: var(--muted); } 65%, 100% { fill: var(--accent); } }
  @keyframes verdict-label-c { 0%, 66% { fill: var(--muted); } 69%, 100% { fill: var(--accent); } }
  @keyframes disagreement-arrives { 0%, 66% { opacity: 0; } 68%, 100% { opacity: 1; } }
  @keyframes detection-arrives { 0%, 48% { opacity: 0; } 51%, 100% { opacity: 1; } }
}
