/* ==========================================================================
   Animated SVG illustrations (markup in illustrations.js).
   Ambient loops run with CSS; story beats (".dyn-*") replay per cycle when
   script.js toggles .is-running / .is-resetting on the [data-scene] host.
   ========================================================================== */
.ill { width: 100%; height: auto; overflow: visible; }
.ill text { font-family: var(--font); }

/* ---------- Scene primitives ---------- */
.dyn-pop { transform: scale(0); transform-box: fill-box; transform-origin: center; }
.is-running .dyn-pop { animation: pop-in 0.55s var(--ease-spring) var(--delay, 0s) forwards; }
.is-static .dyn-pop { transform: none; }

.dyn-draw { stroke-dasharray: 1; stroke-dashoffset: 1; }
.is-running .dyn-draw { animation: draw var(--dur, 1.6s) var(--ease-out) var(--delay, 0s) forwards; }
.is-static .dyn-draw { stroke-dashoffset: 0; }

.dyn-fade { opacity: 0; }
.is-running .dyn-fade { animation: fade-in 0.6s ease var(--delay, 0s) forwards; }
.is-static .dyn-fade { opacity: 1; }

.dyn-type { transform-box: fill-box; transform-origin: right center; }
.is-running .dyn-type { animation: type-out 0.85s steps(24) var(--delay, 0s) forwards; }
.is-static .dyn-type { transform: scaleX(0); }

.dyn-scan { opacity: 0; }
.is-running .dyn-scan { animation: scan var(--dur, 4s) linear 0.3s forwards; }

.is-resetting .dyn { opacity: 0 !important; transition: opacity 0.6s ease; }

/* Ambient loops pause while their host is off screen (script.js toggles .is-onscreen). */
.js [data-ambient]:not(.is-onscreen) *,
.js [data-scene]:not(.is-onscreen):not(.is-static) * { animation-play-state: paused; }

@keyframes pop-in { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fade-in { to { opacity: 1; } }
@keyframes type-out { to { transform: scaleX(0); } }
@keyframes scan {
  0% { opacity: 1; transform: translateY(0); }
  94% { opacity: 1; }
  100% { opacity: 0; transform: translateY(300px); }
}
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

/* ---------- Hero: neural network data flow ---------- */
.ill-hero .ring { fill: none; stroke: var(--fg); stroke-opacity: 0.14; stroke-width: 1.5; }
.ill-hero .ring--dash,
.ill-hero .orbit { transform-box: view-box; transform-origin: 280px 260px; }
.ill-hero .ring--dash { stroke-dasharray: 3 9; stroke-opacity: 0.32; animation: spin 70s linear infinite; }
.ill-hero .orbit { animation: spin 26s linear infinite; }
.ill-hero .orbit circle { fill: var(--primary); }

.ill-hero .wires path { stroke: var(--fg); stroke-width: 1.3; stroke-opacity: 0.2; }
.js .ill-hero .wires { opacity: 0; animation: fade-in 0.9s ease 1.1s forwards; }
.ill-hero .pulse {
  fill: none;
  stroke: var(--primary);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 14 86;
  stroke-dashoffset: 100;
  animation: synapse 2.4s linear var(--delay, 0s) infinite;
}
@keyframes synapse { to { stroke-dashoffset: 0; } }

.ill-hero .node { fill: var(--bg); stroke: var(--fg); stroke-width: 2.5; transform-box: fill-box; transform-origin: center; }
.js .ill-hero .node { transform: scale(0); animation: pop-in 0.5s var(--ease-spring) calc(1.2s + var(--delay, 0s)) forwards; }
.ill-hero .node--hot { fill: var(--primary); }
.js .ill-hero .node--hot {
  animation:
    pop-in 0.5s var(--ease-spring) calc(1.2s + var(--delay, 0s)) forwards,
    node-beat 2.4s ease-in-out calc(2.4s + var(--delay, 0s)) infinite;
}
.ill-hero .node--out { fill: var(--fg); }
@keyframes node-beat {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.25); }
}

.ill-hero .link { stroke: var(--fg); stroke-width: 2; stroke-opacity: 0.5; stroke-dasharray: 4 5; }
.ill-hero .tile { transform-box: fill-box; transform-origin: center; }
.js .ill-hero .tile { transform: scale(0); animation: pop-in 0.6s var(--ease-spring) calc(1s + var(--delay, 0s)) forwards; }
.ill-hero .tile-shadow { fill: var(--fg); }
.ill-hero .tile-face { fill: var(--bg); stroke: var(--fg); stroke-width: 2.5; }
.ill-hero .ink { fill: none; stroke: var(--fg); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.ill-hero .ink--accent { stroke: var(--primary); }

.ill-hero .chip { animation: float 4s ease-in-out var(--delay, 0s) infinite; }
.ill-hero .chip rect { fill: var(--fg); }
.ill-hero .chip text { fill: var(--bg); font-size: 14px; font-weight: 700; text-anchor: middle; }

/* ---------- Lightbulb ---------- */
.ill-bulb .bulb-body { animation: float 3.2s ease-in-out infinite; }
.ill-bulb .bulb-glass { fill: #ffd84d; stroke: #1b1b1b; stroke-width: 4; stroke-linejoin: round; }
.ill-bulb .bulb-shade { fill: #f5b82e; }
.ill-bulb .bulb-shine { fill: none; stroke: #fff; stroke-width: 5; stroke-linecap: round; opacity: 0.85; }
.ill-bulb .bulb-filament { fill: none; stroke: #1b1b1b; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.ill-bulb .bulb-base { fill: #d9d9d9; stroke: #1b1b1b; stroke-width: 3; }
.ill-bulb .bulb-cap { fill: #1b1b1b; }
.ill-bulb .bulb-glow { transform-box: fill-box; transform-origin: center; animation: glow 3.2s ease-in-out infinite; }
.ill-bulb .bulb-rays path { stroke: var(--primary); stroke-width: 4; stroke-linecap: round; animation: ray 3.2s ease-in-out var(--delay, 0s) infinite; }
@keyframes glow {
  0%, 100% { opacity: 0.35; transform: scale(0.9); }
  50% { opacity: 0.95; transform: scale(1.06); }
}
@keyframes ray {
  0%, 100% { opacity: 0.15; }
  50% { opacity: 1; }
}

/* ---------- Notebook (about frame) ---------- */
.ill-notebook { --nb-bg: #ffffff; --nb-cell: #f3f3f6; }
:root[data-theme='dark'] .ill-notebook { --nb-bg: #222222; --nb-cell: #2c2c2c; }
.ill-notebook .nb-window { fill: var(--nb-bg); }
.ill-notebook .nb-title { fill: var(--fg-soft); font-size: 13px; font-weight: 600; text-anchor: middle; }
.ill-notebook .nb-rule { stroke: var(--fg-faint); stroke-width: 2; }
.ill-notebook .nb-prompt { fill: var(--primary); font-family: var(--mono); font-size: 12px; font-weight: 700; }
.ill-notebook .nb-cell { fill: var(--nb-cell); stroke: var(--fg-faint); }
.ill-notebook .code-line { fill: var(--fg); font-family: var(--mono); font-size: 12.5px; font-weight: 500; }
.ill-notebook .code-line .kw { fill: var(--primary); font-weight: 700; }
.ill-notebook .code-line .str { fill: #2f9e6e; }
:root[data-theme='dark'] .ill-notebook .code-line .str { fill: #7fdc9f; }
.ill-notebook .type-cover { fill: var(--nb-cell); }
.ill-notebook .nb-grid path { stroke: var(--fg-faint); stroke-width: 1; }
.ill-notebook .nb-axis { fill: none; stroke: var(--fg-soft); stroke-width: 1.5; }
.ill-notebook .trend { fill: none; stroke: var(--primary); stroke-width: 2.5; stroke-linecap: round; opacity: 0.7; }
.ill-notebook .pt { fill: var(--fg); fill-opacity: 0.72; }
.ill-notebook .anomaly-dot { fill: var(--primary); }
.ill-notebook .anomaly-ring {
  fill: none;
  stroke: var(--primary);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: ring 1.8s ease-out infinite;
}
.ill-notebook .nb-legend text { fill: var(--fg-soft); font-size: 12px; font-weight: 600; }
.ill-notebook .legend-normal { fill: var(--fg); fill-opacity: 0.72; }
.ill-notebook .legend-anomaly { fill: var(--primary); }
@keyframes ring {
  0% { opacity: 1; transform: scale(0.6); }
  100% { opacity: 0; transform: scale(1.8); }
}

/* ---------- Project covers (shared) ---------- */
.ill-cover .orb { fill: #ffffff; fill-opacity: 0.06; }
.ill-cover .pill { fill: #ffffff; fill-opacity: 0.14; }
.ill-cover .pill-text { fill: #ffffff; font-size: 12px; font-weight: 700; text-anchor: middle; }

/* ---------- Claims-analysis workflow ---------- */
.ill-claims .stage { fill: #ffffff; }
.ill-claims .paper { fill: #ffffff; stroke: #1b1b1b; stroke-width: 2.5; stroke-linejoin: round; }
.ill-claims .paper-back { fill: #f3d6ea; stroke: #1b1b1b; stroke-width: 2.5; }
.ill-claims .paper-tint { fill: #efe3f7; stroke: #1b1b1b; stroke-width: 2.5; }
.ill-claims .ink { fill: none; stroke: #1b1b1b; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.ill-claims .mail-badge { fill: #b63e96; }
.ill-claims .field { fill: #e6dcef; }
.ill-claims .tick circle { fill: #2fbf71; }
.ill-claims .tick path { fill: none; stroke: #ffffff; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.ill-claims .lens { animation: lens 3.2s ease-in-out infinite; }
.ill-claims .lens circle { fill: rgba(255, 255, 255, 0.85); stroke: #b63e96; stroke-width: 3; }
.ill-claims .lens path { stroke: #b63e96; stroke-width: 4; stroke-linecap: round; }
.ill-claims .alert { fill: #e5484d; }
.ill-claims .typing { fill: #b63e96; animation: typing 1.2s ease-in-out var(--delay, 0s) infinite; }
.ill-claims .sparkle {
  fill: #ffd84d;
  stroke: #1b1b1b;
  stroke-width: 1.5;
  stroke-linejoin: round;
  transform-box: fill-box;
  transform-origin: center;
  animation: sparkle 2.4s ease-in-out infinite;
}
.ill-claims .wire { stroke: #ffffff; stroke-opacity: 0.5; stroke-width: 2; stroke-dasharray: 4 5; }
.ill-claims .packet { fill: #ffd84d; animation: packet 1.6s ease-in-out var(--delay, 0s) infinite; }
.ill-claims .stage-label { fill: #ffffff; font-size: 13px; font-weight: 700; text-anchor: middle; }
.ill-claims .cover-footnote { fill: #ffffff; fill-opacity: 0.7; font-size: 11px; font-weight: 600; }

@keyframes lens {
  0%, 100% { transform: translate(0, 0); }
  33% { transform: translate(18px, -14px); }
  66% { transform: translate(8px, 6px); }
}
@keyframes typing {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(-5px); }
}
@keyframes sparkle {
  0%, 100% { transform: scale(0.8) rotate(0deg); }
  50% { transform: scale(1.15) rotate(45deg); }
}
@keyframes packet {
  0% { opacity: 0; transform: translateX(0); }
  15%, 85% { opacity: 1; }
  100% { opacity: 0; transform: translateX(38px); }
}

/* ---------- ToxiScan ---------- */
.ill-toxi .comment-card { fill: #ffffff; fill-opacity: 0.94; }
.ill-toxi .line { fill: #c9d6da; }
.ill-toxi .toxic-tint { fill: #e5484d; fill-opacity: 0.16; stroke: #e5484d; stroke-width: 2.5; }
.ill-toxi .badge--clean circle { fill: #2fbf71; }
.ill-toxi .badge--toxic circle { fill: #e5484d; }
.ill-toxi .badge path { fill: none; stroke: #ffffff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.ill-toxi .shield-ring {
  fill: none;
  stroke: #7ff5e9;
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: ring 2.6s ease-out infinite;
}
.ill-toxi .shield-body { fill: rgba(255, 255, 255, 0.12); stroke: #ffffff; stroke-width: 3; stroke-linejoin: round; }
.ill-toxi .shield-check { fill: none; stroke: #7ff5e9; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.ill-toxi .pipe { stroke: #ffffff; stroke-opacity: 0.35; stroke-width: 2; stroke-dasharray: 4 5; }
.ill-toxi .pipe-dot { fill: #7ff5e9; animation: pipe 2.4s ease-in-out infinite; }
.ill-toxi .tool { fill: #0c2530; fill-opacity: 0.85; stroke: #7ff5e9; stroke-opacity: 0.6; stroke-width: 1.5; }
.ill-toxi .tool-text { fill: #ffffff; font-size: 12px; font-weight: 700; text-anchor: middle; }
@keyframes pipe {
  0% { opacity: 0; transform: translateY(0); }
  15%, 85% { opacity: 1; }
  100% { opacity: 0; transform: translateY(100px); }
}

/* ---------- EcoEnergy ---------- */
.ill-energy .bolt circle { fill: #ffd84d; animation: bolt-glow 2.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.ill-energy .bolt path { fill: #1b1b1b; }
.ill-energy .chart-grid path { stroke: #ffffff; stroke-opacity: 0.1; }
.ill-energy .chart-axis { fill: none; stroke: #ffffff; stroke-opacity: 0.45; stroke-width: 1.5; }
.ill-energy .band { fill: #ffd84d; fill-opacity: 0.18; }
.ill-energy .observed { fill: none; stroke: #ffffff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.ill-energy .forecast { fill: none; stroke: #ffd84d; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.ill-energy .now-line { stroke: #ffffff; stroke-opacity: 0.5; stroke-width: 1.5; stroke-dasharray: 5 6; }
.ill-energy .now-dot { fill: #ffd84d; stroke: #0b241a; stroke-width: 3; }
.ill-energy .chart-label { fill: #ffffff; font-size: 12px; font-weight: 700; }
.ill-energy .chart-label--forecast { fill: #ffd84d; }
@keyframes bolt-glow {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}

/* ---------- Paper plane (contact) ---------- */
.ill-plane .route { fill: none; stroke: var(--fg); stroke-opacity: 0.35; stroke-width: 2; stroke-dasharray: 6 8; stroke-linecap: round; }
.ill-plane .plane path { fill: var(--primary); stroke: var(--fg); stroke-width: 1.5; stroke-linejoin: round; }
.ill-plane .plane .plane-fold { fill: none; }

/* ---------- Timeline marker ---------- */
.ill-dot { transform: rotate(-90deg); }
.ill-dot .dot-ring { fill: none; stroke: var(--primary); stroke-width: 1; }
.ill-dot .dot-progress {
  fill: var(--bg);
  stroke: var(--fg);
  stroke-width: 5;
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - var(--p, 1));
}
.js .ill-dot .dot-progress { stroke-dashoffset: calc(1 - var(--p, 0)); }
.ill-dot .dot-core { fill: var(--primary); animation: dot-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
@keyframes dot-pulse { 50% { opacity: 0.5; } }
