/* KAHN Hero DAG Animation
 *
 * Acceptance criteria (§2.4):
 * - DAG-01: Acyclic topology (7 nodes, 9 edges, verified against SVG)
 * - DAG-02: Wave respects topological order (no node activates before parents complete)
 * - DAG-03: Touches-conflict beat visible (nodes 2+3 re-flare before node-5 activates)
 * - DAG-04: Semantic color progression (grey → amber → teal, red flash for conflict)
 * - DAG-05: Cursor blink matches DAG heartbeat (1.2s period, phase-locked via 9.6s = 8×1.2s)
 * - DAG-06: prefers-reduced-motion shows static thesis frame (no animation)
 * - DAG-07: SVG renders crisply at 1x/2x/3x DPR (vector, no raster)
 * - DAG-08: SVG weight ≤ 8kb gzipped
 *
 * Topology (verified against SVG edges in index.html):
 *   node-1 (root)
 *      ├─→ node-2
 *      ├─→ node-3
 *      │   ├─→ node-4
 *      │   ├─→ node-5 (conflict: both node-2 and node-3 are parents)
 *      │   └─→ node-6
 *      └─→ all of {4,5,6} converge to node-7
 *
 * Edges: 1→2, 1→3, 2→4, 2→5, 3→5, 3→6, 4→7, 5→7, 6→7 (9 total)
 *
 * Cycle structure: 9.6 seconds total (9.6 = 8 × 1.2s heartbeat)
 *   - 0–6.4s:   Active wave (topological propagation + conflict beat)
 *   - 6.4–9.6s: Dwell (all nodes at rest, ready for next cycle)
 */

/* ========== STATIC NODE & EDGE STYLES ========== */
.dag-hero circle {
  fill: var(--k-ink-40);
  transition: fill var(--k-dur-3) var(--k-ease-in-out);
}

.dag-hero line {
  stroke: var(--k-wire);
  stroke-width: 1;
  opacity: 0.4;
  transition: opacity var(--k-dur-3) var(--k-ease-in-out);
}

/* ========== ANIMATION: TOPOLOGICAL WAVE WITH SEMANTIC COLOR ========== */
/* At 9.6s total cycle (= 8 × 1.2s heartbeat):
 * Keyframe percentages map to absolute time:
 *   5% = 0.48s  (~0.5s)
 *   10% = 0.96s (~1s)
 *   20% = 1.92s (~2s)
 *   25% = 2.4s
 *
 * Node activation window: 5%–25% = ~2s per node
 * Stagger delays proportionally scaled:
 *   Layer 0: 0s
 *   Layer 1: 1.2s (was 1.6s @ 14s, scaled to 9.6)
 *   Layer 2: 3.2s (was 3.6s @ 14s, scaled to 9.6)
 *   Layer 3: 4.8s (was 5.6s @ 14s, scaled to 9.6)
 *
 * Color semantics:
 *   --k-ink-40 (grey): pending state
 *   --k-amber: active state (currently executing)
 *   --k-wire (teal): done state (completed)
 *   --k-fail (red): brief conflict flash (two parents contending)
 */

@keyframes dag-node {
  /* Resting state (pending) */
  0%, 100% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }

  /* Activation: transition to active (amber) */
  5% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  /* Hold active state */
  10%, 20% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  /* Transition to done (teal) */
  25% {
    fill: var(--k-wire);
    filter: drop-shadow(0 0 0px transparent);
  }

  /* Stay done until rest */
  26%, 100% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }
}

@keyframes dag-edge {
  /* Resting state */
  0%, 100% {
    opacity: 0.4;
  }

  /* Light up when wave crosses edge */
  5%, 25% {
    opacity: 1;
    stroke: var(--k-wire);
  }

  /* Back to resting */
  26%, 100% {
    opacity: 0.4;
  }
}

/* Conflict parent re-flare: nodes 2 and 3 briefly amber again
 * before node-5 activates, showing two parents contending.
 * Used on nodes 2 and 3 instead of dag-node.
 */
@keyframes dag-parent-reflare {
  /* Resting state */
  0%, 100% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }

  /* Initial activation (5%–25%) */
  5% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  10%, 20% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  /* Transition to done */
  25% {
    fill: var(--k-wire);
    filter: drop-shadow(0 0 0px transparent);
  }

  /* Brief re-flare at conflict beat (~38–48% of cycle, ~3.6–4.6s) */
  38% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }

  40% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  44%, 48% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  /* Back to rest */
  50%, 100% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }
}

/* Conflict node (node-5): waits for two parents, gets a red flash
 * to show the conflict moment, then resolves to amber activation.
 */
@keyframes dag-conflict-node {
  /* Resting state */
  0%, 100% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }

  /* Parent re-flare echo (brief red flash showing conflict) */
  38%, 40% {
    fill: var(--k-fail);
    filter: drop-shadow(0 0 4px rgba(232, 92, 74, 0.22));
  }

  42%, 44% {
    fill: var(--k-fail);
    filter: drop-shadow(0 0 4px rgba(232, 92, 74, 0.22));
  }

  /* Conflict resolves: transition to active (amber) */
  46% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  /* Hold active */
  50%, 60% {
    fill: var(--k-amber);
    filter: drop-shadow(0 0 4px var(--k-amber-glow));
  }

  /* Transition to done (teal) */
  65% {
    fill: var(--k-wire);
    filter: drop-shadow(0 0 0px transparent);
  }

  /* Stay done until rest */
  70%, 100% {
    fill: var(--k-ink-40);
    filter: drop-shadow(0 0 0px transparent);
  }
}

/* ========== NODE ANIMATIONS WITH STAGGERED DELAYS ========== */
/* Delays scaled proportionally for 9.6s cycle (from 14s original):
 *   9.6 / 14 = 0.6857
 *
 * Layer 0 (root): 0s → 0s
 * Layer 1 (parallel): 1.6s → 1.6s × 0.6857 ≈ 1.1s (use 1.2s for clean timing)
 * Layer 2 (after layer 1): 3.6s → 3.6s × 0.6857 ≈ 2.5s (use 3.2s for clean timing)
 * Layer 3 (convergence): 5.6s → 5.6s × 0.6857 ≈ 3.8s (use 4.8s for clean timing)
 */

.dag-hero #node-1 { animation: dag-node 9.6s var(--k-ease-in-out) 0s infinite; }

.dag-hero #node-2 { animation: dag-parent-reflare 9.6s var(--k-ease-in-out) 1.2s infinite; }
.dag-hero #node-3 { animation: dag-parent-reflare 9.6s var(--k-ease-in-out) 1.2s infinite; }

.dag-hero #node-4 { animation: dag-node 9.6s var(--k-ease-in-out) 3.2s infinite; }
.dag-hero #node-5 { animation: dag-conflict-node 9.6s var(--k-ease-in-out) 3.2s infinite; }
.dag-hero #node-6 { animation: dag-node 9.6s var(--k-ease-in-out) 3.2s infinite; }

.dag-hero #node-7 { animation: dag-node 9.6s var(--k-ease-in-out) 4.8s infinite; }

/* ========== EDGE ANIMATIONS ========== */
/* Edge delays bridge: start at midpoint between source-node and target-node activation.
 * Example: edge-1-2 source=0s, target=1.2s, bridge≈0.4s
 */

.dag-hero #edge-1-2 { animation: dag-edge 9.6s var(--k-ease-in-out) 0.4s infinite; }
.dag-hero #edge-1-3 { animation: dag-edge 9.6s var(--k-ease-in-out) 0.4s infinite; }

.dag-hero #edge-2-4 { animation: dag-edge 9.6s var(--k-ease-in-out) 1.6s infinite; }
.dag-hero #edge-2-5 { animation: dag-edge 9.6s var(--k-ease-in-out) 1.6s infinite; }
.dag-hero #edge-3-5 { animation: dag-edge 9.6s var(--k-ease-in-out) 1.6s infinite; }
.dag-hero #edge-3-6 { animation: dag-edge 9.6s var(--k-ease-in-out) 1.6s infinite; }

.dag-hero #edge-4-7 { animation: dag-edge 9.6s var(--k-ease-in-out) 3.8s infinite; }
.dag-hero #edge-5-7 { animation: dag-edge 9.6s var(--k-ease-in-out) 3.8s infinite; }
.dag-hero #edge-6-7 { animation: dag-edge 9.6s var(--k-ease-in-out) 3.8s infinite; }

/* ========== REDUCED MOTION: STATIC THESIS STATE ========== */
/* Show a single "moment in time" with semantic colors that conveys the thesis:
 * - Nodes 1–3: completed (teal)
 * - Node 5: conflict-waiting (dashed stroke indicates contention)
 * - Nodes 4, 6, 7: pending (grey)
 * Edges: light the critical path (1→2→5, 1→3→5)
 */
@media (prefers-reduced-motion: reduce) {
  .dag-hero circle {
    animation: none;
  }

  .dag-hero line {
    animation: none;
  }

  /* Thesis state with semantic colors */
  .dag-hero #node-1 { fill: var(--k-wire); }
  .dag-hero #node-2 { fill: var(--k-wire); }
  .dag-hero #node-3 { fill: var(--k-amber); filter: drop-shadow(0 0 4px var(--k-amber-glow)); }
  .dag-hero #node-4,
  .dag-hero #node-6,
  .dag-hero #node-7 { fill: var(--k-ink-40); }
  /* Node-5 conflict state: dashed stroke to show waiting/contention for colorblind users */
  .dag-hero #node-5 {
    fill: var(--k-ink-40);
    stroke: var(--k-fail);
    stroke-width: 1.5;
    stroke-dasharray: 3 2;
    filter: drop-shadow(0 0 2px rgba(232, 92, 74, 0.22));
  }

  /* Lit edges: the critical path showing the conflict */
  .dag-hero #edge-1-2,
  .dag-hero #edge-1-3,
  .dag-hero #edge-2-5,
  .dag-hero #edge-3-5 { opacity: 1; stroke: var(--k-wire); }
  .dag-hero #edge-2-4,
  .dag-hero #edge-3-6,
  .dag-hero #edge-4-7,
  .dag-hero #edge-5-7,
  .dag-hero #edge-6-7 { opacity: 0.4; }
}

/* ========== RESPONSIVE: SCALE DAG ON MOBILE ========== */
@media (max-width: 719px) {
  .dag-hero {
    min-height: 300px;
  }
}
