/* ============================================================
   SCENE GRAPHICS — per-chapter SVG styling + animation
   Animations run only while a scene is `.active`.
   ============================================================ */

.scene-svg text { font-size: 11px; fill: var(--text-2); }
.scene-svg .tiny { font-size: 9.5px; letter-spacing: .1em; }
.scene-svg .dimtext { fill: var(--text-3); }
.scene-svg .alarm-text { fill: var(--danger); }
.hud-num { font-size: 21px; fill: var(--accent); font-weight: 600; }

/* ─────────────────────────────────────────────
   01 — COLLEGE: PCB traces → race car
   ───────────────────────────────────────────── */

.pcb .trace {
  stroke-dasharray: 460;
  stroke-dashoffset: 460;
  opacity: .85;
}
[data-vis="0"].active .pcb .trace { animation: drawTrace 2s var(--ease) forwards; }
.pcb .trace:nth-child(2) { animation-delay: .12s !important; }
.pcb .trace:nth-child(3) { animation-delay: .24s !important; }
.pcb .trace:nth-child(4) { animation-delay: .36s !important; }
.pcb .trace:nth-child(5) { animation-delay: .48s !important; }
.pcb .trace:nth-child(6) { animation-delay: .60s !important; }
@keyframes drawTrace { to { stroke-dashoffset: 0; } }

.pads .pad { opacity: 0; }
[data-vis="0"].active .pads .pad { animation: padOn .4s var(--ease) forwards; animation-delay: 1.1s; }
@keyframes padOn { to { opacity: 1; } }

.chip rect { fill: var(--surface); stroke: var(--accent); stroke-width: 1.6; }
.chip-pins { stroke: var(--accent); stroke-width: 1.6; fill: none; }
.chip-text { fill: var(--accent); font-size: 11px; letter-spacing: .08em; }
.chip { opacity: 0; transform-origin: 210px 150px; }
[data-vis="0"].active .chip { animation: chipIn .6s var(--ease) .9s forwards; }
@keyframes chipIn { from { opacity: 0; transform: scale(.82); } to { opacity: 1; transform: scale(1); } }


.car-road { stroke: var(--border); stroke-width: 2; fill: none; }
.car-shell { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; }
.car-wing-f, .car-wing-r { stroke: var(--accent); stroke-width: 2.4; fill: none; stroke-linecap: round; }
.wheel { fill: var(--bg-3); stroke: var(--text-2); stroke-width: 2.5; }
.hub { fill: var(--accent); }
.cockpit { fill: var(--bg); stroke: var(--accent); stroke-width: 1.4; }
.speed path { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; opacity: 0; }
.shift-text { fill: var(--accent-2); font-size: 13px; letter-spacing: .16em; opacity: 0; }

[data-vis="1"].active .car-body { animation: carRoll 1s var(--ease) both; }
@keyframes carRoll { from { transform: translateX(-90px); opacity: 0; } to { transform: none; opacity: 1; } }

[data-vis="1"].active .wheel { animation: spin 1.1s linear infinite; transform-box: fill-box; transform-origin: center; }
@keyframes spin { to { transform: rotate(360deg); } }

[data-vis="1"].active .speed path { animation: speedLine 1.1s linear infinite; }
.speed path:nth-child(2) { animation-delay: .22s !important; }
.speed path:nth-child(3) { animation-delay: .44s !important; }
@keyframes speedLine {
  0%   { opacity: 0; transform: translateX(-16px); }
  40%  { opacity: .9; }
  100% { opacity: 0; transform: translateX(52px); }
}

[data-vis="1"].active .shift-text { animation: shiftFlash 2.4s var(--ease) infinite; }
@keyframes shiftFlash {
  0%, 55%   { opacity: 0; transform: translateY(6px); }
  62%, 78%  { opacity: 1; transform: translateY(0); }
  100%      { opacity: 0; transform: translateY(-8px); }
}

/* ─────────────────────────────────────────────
   02.0 — RFID TOLL GANTRY
   ───────────────────────────────────────────── */

.road { stroke: var(--text-3); stroke-width: 2; fill: none; }
.road-dash { stroke: var(--border); stroke-width: 2; stroke-dasharray: 16 14; fill: none; }
.gantry path { stroke: var(--text-2); stroke-width: 3; fill: none; stroke-linejoin: round; }
.reader-box { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; }

.rf { fill: none; stroke: var(--accent); stroke-width: 2; opacity: 0; transform-box: fill-box; transform-origin: center; }
[data-vis="0"].active .rf { animation: rfPulse 1.8s var(--ease) infinite; }
.rf.r2 { animation-delay: .6s !important; }
.rf.r3 { animation-delay: 1.2s !important; }
@keyframes rfPulse {
  0%   { transform: scale(.28); opacity: 0; }
  25%  { opacity: .85; }
  100% { transform: scale(3.4); opacity: 0; }
}

.tc-body { fill: var(--bg-3); stroke: var(--text-2); stroke-width: 2; stroke-linejoin: round; }
.tc-wheel { fill: var(--text-3); }
.tc-tag { fill: var(--accent); }
[data-vis="0"].active .toll-car { animation: driveThrough 4.2s linear infinite; }
@keyframes driveThrough { from { transform: translateX(0); } to { transform: translateX(400px); } }
[data-vis="0"].active .tc-tag { animation: tagBlink 4.2s linear infinite; }
@keyframes tagBlink { 0%,42% { fill: var(--text-3); } 46%,56% { fill: var(--accent-2); } 60%,100% { fill: var(--text-3); } }

.hud-box { fill: var(--surface); stroke: var(--border); stroke-width: 1.4; }

/* ─────────────────────────────────────────────
   02.1 — BLE BEACON → GATEWAY → PHONE
   ───────────────────────────────────────────── */

.node { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.ping { fill: none; stroke: var(--accent); stroke-width: 1.8; opacity: 0; transform-box: fill-box; transform-origin: center; }
[data-vis="1"].active .ping { animation: rfPulse 2.2s var(--ease) infinite; }
[data-vis="1"].active .b2 .ping { animation-delay: .5s; }
.ping.p2 { animation-delay: 1.1s !important; }

.link { fill: none; stroke: var(--border); stroke-width: 1.8; stroke-dasharray: 5 6; }
[data-vis="1"].active .link { animation: dashFlow 1.4s linear infinite; stroke: var(--accent); opacity: .6; }
@keyframes dashFlow { to { stroke-dashoffset: -22; } }

.gw-box { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.gw-led { stroke: var(--accent); stroke-width: 3; stroke-linecap: round; }
[data-vis="1"].active .gw-led { animation: ledBlink 1s steps(1) infinite; }
[data-vis="1"].active .gw-led.d2 { animation-delay: .5s; }
@keyframes ledBlink { 0%,49% { opacity: 1; } 50%,100% { opacity: .18; } }

.ph-body { fill: var(--bg-3); stroke: var(--text-2); stroke-width: 2; }
.ph-screen { fill: var(--surface); }
.ph-bars rect { fill: var(--accent); transform-box: fill-box; transform-origin: bottom; }
[data-vis="1"].active .ph-bars rect { animation: barRise .6s var(--ease) both; }
.ph-bars rect:nth-child(2) { animation-delay: .15s !important; }
.ph-bars rect:nth-child(3) { animation-delay: .3s !important; }
@keyframes barRise { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* ─────────────────────────────────────────────
   02.2 — RSSI TRILATERATION
   ───────────────────────────────────────────── */

.floor > path { fill: var(--bg-2); stroke: var(--border); stroke-width: 1.5; }
.floor-grid path { stroke: var(--grid-line); stroke-width: 1; }
.ring { fill: none; stroke: var(--accent); stroke-width: 1.4; opacity: .34; stroke-dasharray: 4 7; }
[data-vis="2"].active .ring { animation: ringBreathe 3s var(--ease) infinite; transform-box: fill-box; transform-origin: center; }
.ring.g2 { animation-delay: .4s !important; }
.ring.g3 { animation-delay: .8s !important; }
@keyframes ringBreathe { 0%,100% { transform: scale(.96); opacity: .2; } 50% { transform: scale(1.02); opacity: .55; } }

.anchor { fill: var(--accent); }
.asset-box { fill: var(--accent-2); }
.asset-halo { fill: var(--accent-2); opacity: .16; transform-box: fill-box; transform-origin: center; }
[data-vis="2"].active .asset-halo { animation: haloPulse 2s var(--ease) infinite; }
@keyframes haloPulse { 0%,100% { transform: scale(.8); opacity: .1; } 50% { transform: scale(1.25); opacity: .28; } }
[data-vis="2"].active .asset { animation: assetDrift 5s ease-in-out infinite; }
@keyframes assetDrift {
  0%,100% { transform: translate(202px,156px); }
  50%     { transform: translate(214px,146px); }
}
.acc-line { stroke: var(--accent-2); stroke-width: 1.4; stroke-dasharray: 3 4; }
.acc-label text { fill: var(--accent-2); }

/* ─────────────────────────────────────────────
   02.3 — PEDOMETER WAVEFORM
   ───────────────────────────────────────────── */

.axes path, .axes-line { stroke: var(--border); stroke-width: 1.6; fill: none; }
.accel-wave {
  fill: none; stroke: var(--accent); stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 640; stroke-dashoffset: 640;
}
[data-vis="3"].active .accel-wave { animation: drawWave 2.4s var(--ease) forwards; }
@keyframes drawWave { to { stroke-dashoffset: 0; } }

.thresh { stroke: var(--accent-2); stroke-width: 1.2; stroke-dasharray: 5 5; fill: none; opacity: .7; }
.peak { fill: var(--accent-2); opacity: 0; transform-box: fill-box; transform-origin: center; }
[data-vis="3"].active .peak { animation: peakPop .5s var(--ease) forwards; }
.peak.k1 { animation-delay: .55s !important; }
.peak.k2 { animation-delay: 1.05s !important; }
.peak.k3 { animation-delay: 1.55s !important; }
.peak.k4 { animation-delay: 2.05s !important; }
@keyframes peakPop { from { opacity: 0; transform: scale(0); } 60% { transform: scale(1.5); } to { opacity: 1; transform: scale(1); } }

/* ─────────────────────────────────────────────
   03.0 — OTA UPDATE
   ───────────────────────────────────────────── */

.cloud-shape { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.cloud-shape.faded { stroke: var(--text-3); opacity: .55; }
.ota-path { fill: none; stroke: var(--border); stroke-width: 1.6; stroke-dasharray: 5 6; }

.pkt rect { fill: var(--accent); }
.pkt {
  offset-path: path('M120 84 C200 84 220 190 300 198');
  offset-rotate: 0deg;
  opacity: 0;
}
[data-vis="0"].active .pkt { animation: pktFly 2.4s linear infinite; }
.pkt.p2 { animation-delay: .8s !important; }
.pkt.p3 { animation-delay: 1.6s !important; }
@keyframes pktFly {
  0%   { offset-distance: 0%; opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}

.dev-box { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.bar-track { fill: var(--bg-3); }
.bar-fill { fill: var(--accent); transform-box: fill-box; transform-origin: left; transform: scaleX(0); }
[data-vis="0"].active .bar-fill { animation: fillBar 2.4s linear infinite; }
@keyframes fillBar { 0% { transform: scaleX(0); } 90%,100% { transform: scaleX(1); } }

/* ─────────────────────────────────────────────
   03.1 — MODBUS BUS
   ───────────────────────────────────────────── */

.hub-box { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.bus { stroke: var(--text-2); stroke-width: 2.6; fill: none; }
.drop { stroke: var(--border); stroke-width: 1.8; fill: none; }
.sensor { fill: var(--bg-3); stroke: var(--accent); stroke-width: 1.8; }
.bus-nodes text { fill: var(--text-2); }

.poll circle { fill: var(--accent-2); }
.poll { offset-path: path('M108 150 H392'); opacity: 0; }
[data-vis="1"].active .poll { animation: pollRun 2.6s ease-in-out infinite; }
@keyframes pollRun {
  0%   { offset-distance: 0%;   opacity: 0; }
  8%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}
[data-vis="1"].active .bus-nodes .sensor { animation: sensorPing 2.6s ease-in-out infinite; }
[data-vis="1"].active .bus-nodes g:nth-child(1) .sensor { animation-delay: .55s; }
[data-vis="1"].active .bus-nodes g:nth-child(2) .sensor { animation-delay: 1.1s; }
[data-vis="1"].active .bus-nodes g:nth-child(3) .sensor { animation-delay: 1.65s; }
@keyframes sensorPing {
  0%, 100% { fill: var(--bg-3); }
  6%, 16%  { fill: var(--accent-soft); stroke: var(--accent-2); }
}

/* ─────────────────────────────────────────────
   03.2 — DEEP SLEEP
   ───────────────────────────────────────────── */

.pwr-before { fill: none; stroke: var(--text-3); stroke-width: 1.6; stroke-dasharray: 6 6; }
.pwr-after {
  fill: none; stroke: var(--accent); stroke-width: 2.4;
  stroke-linejoin: round; stroke-dasharray: 900; stroke-dashoffset: 900;
}
[data-vis="2"].active .pwr-after { animation: drawPwr 2.2s var(--ease) forwards; }
@keyframes drawPwr { to { stroke-dashoffset: 0; } }

.sleep-text { fill: var(--accent-2); font-size: 13px; opacity: 0; }
[data-vis="2"].active .sleep-text { animation: zFloat 2.6s var(--ease) infinite; }
.zzz text:nth-child(2) { animation-delay: .5s !important; }
.zzz text:nth-child(3) { animation-delay: 1s !important; }
@keyframes zFloat {
  0%   { opacity: 0; transform: translateY(6px); }
  30%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-16px); }
}

.bat-shell { fill: none; stroke: var(--text-2); stroke-width: 2; }
.bat-cap { fill: var(--text-2); }
.bat-fill { fill: var(--accent); transform-box: fill-box; transform-origin: left; transform: scaleX(.45); }
[data-vis="2"].active .bat-fill { animation: batGrow 2.6s var(--ease) .6s forwards; }
@keyframes batGrow { from { transform: scaleX(.45); } to { transform: scaleX(1); } }

/* ─────────────────────────────────────────────
   03.3 — SD FALLBACK
   ───────────────────────────────────────────── */

.route { fill: none; stroke-width: 1.8; stroke-dasharray: 5 6; }
.route.up   { stroke: var(--text-3); opacity: .45; }
.route.down { stroke: var(--accent); }
[data-vis="3"].active .route.down { animation: dashFlow 1.2s linear infinite; }

.break-x { stroke: var(--danger); stroke-width: 3; stroke-linecap: round; }
.break-ring { fill: none; stroke: var(--danger); stroke-width: 1.6; opacity: .5; transform-box: fill-box; transform-origin: center; }
[data-vis="3"].active .break-ring { animation: haloPulse 1.8s var(--ease) infinite; }

.sd-shape { fill: var(--surface); stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; }
.sd-pins path { stroke: var(--accent); stroke-width: 1.6; }

.pkt-fall rect { fill: var(--accent); }
.pkt-fall {
  offset-path: path('M96 162 C170 200 210 224 300 232');
  opacity: 0;
}
[data-vis="3"].active .pkt-fall { animation: pktFall 2.2s linear infinite; }
.pkt-fall.f2 { animation-delay: 1.1s !important; }
@keyframes pktFall {
  0%   { offset-distance: 0%; opacity: 0; }
  14%  { opacity: 1; }
  86%  { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* ─────────────────────────────────────────────
   03.4 — WATER LEVEL + SMS
   ───────────────────────────────────────────── */

.bank { fill: var(--bg-3); stroke: none; }
.bank-edge { fill: none; stroke: var(--text-2); stroke-width: 2.5; stroke-linejoin: round; }
.pole { stroke: var(--text-2); stroke-width: 2.5; }
.river-sensor text { fill: var(--text-2); }
.water { fill: var(--accent); opacity: .3; }
.wave-top { fill: var(--accent); opacity: .5; }
[data-vis="4"].active .water,
[data-vis="4"].active .wave-top { animation: waterRise 5s ease-in-out infinite; }
@keyframes waterRise {
  0%   { transform: translateY(76px); }
  55%  { transform: translateY(0); }
  85%  { transform: translateY(0); }
  100% { transform: translateY(76px); }
}
[data-vis="4"].active .wave-top { animation-name: waterRise, waveSlide; animation-duration: 5s, 2.4s; animation-timing-function: ease-in-out, linear; animation-iteration-count: infinite, infinite; }
@keyframes waveSlide { to { transform: translateX(-88px); } }

.alarm-line { stroke: var(--danger); stroke-width: 1.6; stroke-dasharray: 6 5; fill: none; }
[data-vis="4"].active .alarm-line { animation: alarmBlink 5s ease-in-out infinite; }
@keyframes alarmBlink { 0%,50% { opacity: .5; } 56%,84% { opacity: 1; } 90%,100% { opacity: .5; } }

.gsm-box { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.ant { stroke: var(--text-2); stroke-width: 2.4; }
.gsm-waves path { fill: none; stroke: var(--accent); stroke-width: 2; opacity: 0; }
[data-vis="4"].active .gsm-waves path { animation: gsmOut 5s ease-in-out infinite; }
.gsm-waves .gw2 { animation-delay: .18s !important; }
@keyframes gsmOut { 0%,52% { opacity: 0; } 58%,80% { opacity: 1; } 86%,100% { opacity: 0; } }

.sms-box { fill: var(--surface); stroke: var(--danger); stroke-width: 1.6; }
.sms-tail { fill: var(--surface); stroke: var(--danger); stroke-width: 1.6; }
.sms { opacity: 0; }
[data-vis="4"].active .sms { animation: smsIn 5s ease-in-out infinite; }
@keyframes smsIn {
  0%,56%   { opacity: 0; transform: translate(150px, 278px); }
  64%,88%  { opacity: 1; transform: translate(150px, 268px); }
  96%,100% { opacity: 0; transform: translate(150px, 268px); }
}

/* ─────────────────────────────────────────────
   04 — THE MOVE (flight), scroll-driven via --p
   ───────────────────────────────────────────── */

.move-stage { display: flex; flex-direction: column; justify-content: center; gap: 20px; }
.flight-wrap { position: relative; }
.flight-svg { width: 100%; height: auto; max-height: 46vh; }

.sky circle { fill: var(--text-3); opacity: .5; }
[data-scene="move"].in-view .sky circle { animation: twinkle 3.4s ease-in-out infinite; }
.sky circle:nth-child(2n) { animation-delay: .8s !important; }
.sky circle:nth-child(3n) { animation-delay: 1.6s !important; }
@keyframes twinkle { 0%,100% { opacity: .18; } 50% { opacity: .75; } }

.land path { fill: var(--bg-3); stroke: var(--border); stroke-width: 1.6; }
.land-ind { opacity: 1; }
.land-usa { opacity: 1; }

.arc { fill: none; stroke: var(--border); stroke-width: 2; stroke-dasharray: 6 8; }
.arc-fill {
  fill: none; stroke: url(#gArc); stroke-width: 2.6; stroke-linecap: round;
  stroke-dasharray: 1000;
  /* Negative offset reveals from the END of the path (Mumbai), so the
     trail is drawn behind the plane rather than ahead of it. */
  stroke-dashoffset: calc((var(--p, 0) * 1000px) - 1000px);
}

.pin-halo { fill: var(--accent); opacity: .16; transform-box: fill-box; transform-origin: center; }
.pin-dot  { fill: var(--accent); }
.pin text { fill: var(--text-2); }
.pin-from .pin-halo, .pin-from .pin-dot { fill: var(--accent-2); }
[data-scene="move"].in-view .pin-halo { animation: haloPulse 2.4s var(--ease) infinite; }
.pin-to { opacity: calc(.25 + var(--p, 0) * .75); }

.plane {
  fill: var(--accent);
  offset-path: path('M196 244 C 340 60, 620 60, 776 250');
  offset-rotate: auto 180deg;
  offset-distance: calc(100% - (var(--p, 0) * 100%));
}

.move-copy { text-align: center; margin-top: 6px; }
.move-line { font-size: clamp(1rem, 2.2vw, 1.3rem); color: var(--text-2); margin: 0 0 6px; }
.move-line.accent { color: var(--accent); font-weight: 600; }

/* ─────────────────────────────────────────────
   05.0 — DSP → ML
   ───────────────────────────────────────────── */

.sig-raw {
  fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round;
  stroke-dasharray: 300; stroke-dashoffset: 300;
}
[data-vis="0"].active .sig-raw { animation: drawWave 1.6s var(--ease) forwards; }

.arrow { stroke: var(--text-3); stroke-width: 1.6; fill: none; marker-end: none; stroke-dasharray: 4 4; }
.vis.active .arrow { animation: dashFlow 1.2s linear infinite; }

.bin { fill: var(--accent); opacity: .75; transform-box: fill-box; transform-origin: bottom; }
[data-vis="0"].active .bin { animation: barRise .5s var(--ease) both; }
.bins .bin:nth-child(2) { animation-delay: .1s !important; }
.bins .bin:nth-child(3) { animation-delay: .2s !important; }
.bins .bin:nth-child(4) { animation-delay: .3s !important; }
.bins .bin:nth-child(5) { animation-delay: .4s !important; }

.layer circle { fill: var(--surface); stroke: var(--accent); stroke-width: 1.8; }
.edges path { stroke: var(--border); stroke-width: 1; }
[data-vis="0"].active .edges path { animation: edgeGlow 2.4s ease-in-out infinite; }
@keyframes edgeGlow { 0%,100% { stroke: var(--border); } 50% { stroke: var(--accent); opacity: .7; } }
.board-box { fill: var(--bg-2); stroke: var(--border-soft); stroke-width: 1.4; }

/* ─────────────────────────────────────────────
   05.1 — CRASH DETECTION
   ───────────────────────────────────────────── */

.crash-wave {
  fill: none; stroke: var(--accent); stroke-width: 2.2;
  stroke-linejoin: round; stroke-dasharray: 700; stroke-dashoffset: 700;
}
[data-vis="2"].active .crash-wave { animation: drawWave 2s var(--ease) forwards; }
.crash-dot { fill: none; stroke: var(--danger); stroke-width: 2.4; opacity: 0; transform-box: fill-box; transform-origin: center; }
[data-vis="2"].active .crash-dot { animation: peakPop .5s var(--ease) 1.2s forwards, haloPulse 1.6s var(--ease) 1.7s infinite; }

.gps-pin { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; }
.gps-hole { fill: var(--bg); }
.gps text { fill: var(--text-2); }
.gps, .alert-card { opacity: 0; }
[data-vis="2"].active .gps { animation: fadeIn .6s var(--ease) 1.5s forwards; }
[data-vis="2"].active .alert-card { animation: fadeIn .6s var(--ease) 1.9s forwards; }

/* ─────────────────────────────────────────────
   05.2 — PUBLICATIONS
   ───────────────────────────────────────────── */

.sheet rect { fill: var(--surface); stroke: var(--border); stroke-width: 1.6; }
.sheet.s1 rect { stroke: var(--accent); }
.lines path { stroke: var(--border); stroke-width: 2; stroke-linecap: round; }
.lines path:first-child { stroke: var(--accent); }
[data-vis="5"].active .sheet { animation: sheetIn .7s var(--ease) both; }
[data-vis="5"].active .sheet.s2 { animation-delay: .1s; }
[data-vis="5"].active .sheet.s1 { animation-delay: .2s; }
@keyframes sheetIn { from { opacity: 0; } to { opacity: 1; } }

/* ─────────────────────────────────────────────
   REDUCED MOTION
   ───────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .pcb .trace, .accel-wave, .pwr-after, .crash-wave, .sig-raw { stroke-dashoffset: 0 !important; }
  .pads .pad, .chip, .peak, .crash-dot, .sms, .sleep-text,
  .gsm-waves path, .speed path, .shift-text, .pkt, .pkt-fall, .poll { opacity: 1 !important; }
  .arc-fill { stroke-dashoffset: 0 !important; }
  .plane { offset-distance: 50% !important; }
  .pin-to { opacity: 1 !important; }
  [data-scene="college"][data-active="1"] .pcb,
  [data-scene="college"][data-active="1"] .pads,
  [data-scene="college"][data-active="1"] .chip { opacity: 1; }
  .car { opacity: 1 !important; }
}


/* ─────────────────────────────────────────────
   05.1 — INDUSTRIAL HAZARD SENSOR (drivers → sensors → dashboard)
   ───────────────────────────────────────────── */

.scene-svg .micro { font-size: 8px; letter-spacing: .08em; }

/* Opacity-only entrance for groups positioned by an SVG transform attribute */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.drv-row { fill: var(--bg-3); stroke: var(--accent); stroke-width: 1.2; opacity: 0; }
[data-vis="1"].active .drv .drv-row { animation: padOn .45s var(--ease) forwards; }
.drv .drv-row:nth-of-type(2) { animation-delay: .12s !important; }
.drv .drv-row:nth-of-type(3) { animation-delay: .24s !important; }
.drv .drv-row:nth-of-type(4) { animation-delay: .36s !important; }
.drv .drv-row:nth-of-type(5) { animation-delay: .48s !important; }
.drv text { fill: var(--accent); }

.sensor-pins .drop { stroke: var(--border); stroke-width: 1.6; fill: none; stroke-dasharray: 4 5; }
[data-vis="1"].active .sensor-pins .drop { animation: dashFlow 1.4s linear infinite; }
[data-vis="1"].active .sens-node .sensor { animation: sensorPing 3.2s ease-in-out infinite; }
[data-vis="1"].active .sens-node:nth-child(6) .sensor { animation-delay: .5s; }
[data-vis="1"].active .sens-node:nth-child(7) .sensor { animation-delay: 1s; }
[data-vis="1"].active .sens-node:nth-child(8) .sensor { animation-delay: 1.5s; }

.mqtt-path { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-dasharray: 5 6; opacity: .7; }
[data-vis="1"].active .mqtt-path { animation: dashFlow 1.2s linear infinite; }
.dash-bars rect { fill: var(--accent); transform-box: fill-box; transform-origin: bottom; }
[data-vis="1"].active .dash-bars rect { animation: barRise .5s var(--ease) both; }
.dash-bars rect:nth-child(2) { animation-delay: .1s !important; }
.dash-bars rect:nth-child(3) { animation-delay: .2s !important; }
.dash-bars rect:nth-child(4) { animation-delay: .3s !important; }
.alarm-chip { opacity: 0; }
[data-vis="1"].active .alarm-chip { animation: chipAlert 4s ease-in-out 1.4s infinite; }
@keyframes chipAlert { 0%, 18% { opacity: 0; } 30%, 70% { opacity: 1; } 88%, 100% { opacity: 0; } }

/* ─────────────────────────────────────────────
   05.2 — ECIES HANDSHAKE
   ───────────────────────────────────────────── */

.peer .dev-box { fill: var(--surface); stroke: var(--accent); stroke-width: 2; }
.hs { fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-dasharray: 6 6; opacity: 0; }
[data-vis="2"].active .hs1 { animation: hsIn .7s var(--ease) .2s forwards, dashFlow 1.2s linear 1s infinite; }
[data-vis="2"].active .hs2 { animation: hsIn .7s var(--ease) .8s forwards, dashFlow 1.2s linear 1.6s infinite; }
@keyframes hsIn { to { opacity: .85; } }
.hs1 ~ text, .hs2 ~ text { fill: var(--text-3); }

.kdf-box { fill: var(--bg-3); stroke: var(--accent); stroke-width: 1.6; }
.kdf { opacity: 0; }
[data-vis="2"].active .kdf { animation: fadeIn .6s var(--ease) 1.5s forwards; }
.kdf text { fill: var(--accent); }

.seal-box { fill: var(--surface); stroke: var(--accent-2); stroke-width: 1.6; }
.lock { fill: none; stroke: var(--accent-2); stroke-width: 2; }
.lock-body { fill: var(--accent-2); }
.sealed { opacity: 0; }
[data-vis="2"].active .sealed { animation: fadeIn .6s var(--ease) 2.1s forwards; }
.sealed text { fill: var(--accent-2); }

/* ─────────────────────────────────────────────
   05.3 — CROP CLASSIFICATION
   ───────────────────────────────────────────── */

.sat-body { fill: var(--surface); stroke: var(--accent); stroke-width: 1.8; }
.sat-panel { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1.4; }
[data-vis="0"].active .sat { animation: satDrift 5s ease-in-out infinite; }
@keyframes satDrift {
  0%, 100% { transform: translate(64px, 44px); }
  50%      { transform: translate(76px, 50px); }
}
.beam-ray { stroke: var(--accent); stroke-width: 1.2; stroke-dasharray: 3 5; opacity: .5; }
[data-vis="0"].active .beam-ray { animation: dashFlow 1.6s linear infinite; }

.parcel { stroke: var(--border); stroke-width: 1.4; opacity: 0; }
.parcel.p1 { fill: var(--accent-soft); }
.parcel.p2 { fill: rgba(251, 191, 36, .18); }
.parcel.p3 { fill: var(--bg-3); }
[data-vis="0"].active .parcel { animation: padOn .5s var(--ease) forwards; }
.parcels .parcel:nth-child(2) { animation-delay: .12s !important; }
.parcels .parcel:nth-child(3) { animation-delay: .24s !important; }
.parcels .parcel:nth-child(4) { animation-delay: .36s !important; }

.cnn-layer { fill: var(--surface); stroke: var(--accent); stroke-width: 1.6; transform-box: fill-box; transform-origin: center; }
[data-vis="2"].active .cnn-layer { animation: layerPulse 2s ease-in-out infinite; }
.cnn .cnn-layer:nth-child(2) { animation-delay: .2s !important; }
.cnn .cnn-layer:nth-child(3) { animation-delay: .4s !important; }
@keyframes layerPulse { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }

@keyframes clsIn { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }

/* ─────────────────────────────────────────────
   05.4 — MATRIX MULTIPLIER
   ───────────────────────────────────────────── */

.mat-box { fill: var(--bg-2); stroke: var(--border); stroke-width: 1.6; }
.mat-c .mat-box { stroke: var(--accent); }
.mult { fill: var(--text-3); font-size: 20px; }
.mat { opacity: 0; }
[data-vis="3"].active .mat { animation: fadeIn .5s var(--ease) forwards; }
[data-vis="3"].active .mat-b { animation-delay: .15s; }
[data-vis="3"].active .mat-c { animation-delay: .3s; }
[data-vis="3"].active .mat-c .mat-box { animation: matGlow 2.4s ease-in-out .8s infinite; }
@keyframes matGlow { 0%, 100% { opacity: .6; } 50% { opacity: 1; } }


/* ─────────────────────────────────────────────
   02.4 — MACHINE VIBRATION / HEALTH GAUGE
   ───────────────────────────────────────────── */

.zone { fill: none; stroke-width: 15; }
.z-good { stroke: var(--accent); }
.z-mid  { stroke: var(--accent-2); }
.z-bad  { stroke: var(--danger); }
.ticks path { stroke: var(--text-3); stroke-width: 2; stroke-linecap: round; }

.needle-arm { stroke: var(--text); stroke-width: 3.4; stroke-linecap: round; }
.needle-hub { fill: var(--text); }
/* the needle group carries no transform attribute, so rotating it in CSS is safe */
.needle { transform-box: view-box; transform-origin: 210px 200px; transform: rotate(-72deg); }
[data-vis="4"].active .needle { animation: needleSweep 6s ease-in-out infinite; }
@keyframes needleSweep {
  0%, 8%    { transform: rotate(-72deg); }
  32%       { transform: rotate(-18deg); }
  58%       { transform: rotate(22deg); }
  78%, 88%  { transform: rotate(66deg); }
  100%      { transform: rotate(-72deg); }
}

.verdict-text { font-size: 15px; letter-spacing: .18em; opacity: 0; font-weight: 600; }
.v-good { fill: var(--accent); }
.v-mid  { fill: var(--accent-2); }
.v-bad  { fill: var(--danger); }
[data-vis="4"].active .v-good { animation: verdictGood 6s ease-in-out infinite; }
[data-vis="4"].active .v-mid  { animation: verdictMid  6s ease-in-out infinite; }
[data-vis="4"].active .v-bad  { animation: verdictBad  6s ease-in-out infinite; }
@keyframes verdictGood { 0%, 20% { opacity: 1; } 26%, 100% { opacity: 0; } }
@keyframes verdictMid  { 0%, 30% { opacity: 0; } 38%, 52% { opacity: 1; } 58%, 100% { opacity: 0; } }
@keyframes verdictBad  { 0%, 64% { opacity: 0; } 72%, 88% { opacity: 1; } 94%, 100% { opacity: 0; } }

.mach-body { fill: var(--surface); stroke: var(--text-2); stroke-width: 2; }
.mach-shaft { fill: var(--accent); transform-box: fill-box; transform-origin: center; }
[data-vis="4"].active .mach-shaft { animation: spin 1.3s linear infinite; }
.vwave { fill: none; stroke: var(--accent-2); stroke-width: 2.2; opacity: 0; }
[data-vis="4"].active .vwave { animation: vibPulse 1.1s ease-in-out infinite; }
.vwave.v2 { animation-delay: .14s !important; }
@keyframes vibPulse { 0%, 100% { opacity: 0; } 50% { opacity: .9; } }


/* ─────────────────────────────────────────────
   06 — THESIS
   ───────────────────────────────────────────── */

/* 06.1 feature ranking + random forest */
.fbar { fill: var(--bg-3); stroke: var(--border); stroke-width: 1.2; opacity: 0; }
.fbar.sel { fill: var(--accent-soft); stroke: var(--accent); }
[data-vis="1"].active .feat .fbar { animation: growBar .5s var(--ease) forwards; transform-box: fill-box; transform-origin: left; }
.feat .fbar:nth-of-type(2) { animation-delay: .08s !important; }
.feat .fbar:nth-of-type(3) { animation-delay: .16s !important; }
.feat .fbar:nth-of-type(4) { animation-delay: .24s !important; }
.feat .fbar:nth-of-type(5) { animation-delay: .32s !important; }
.feat .fbar:nth-of-type(6) { animation-delay: .40s !important; }
@keyframes growBar { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: scaleX(1); } }

.rf-branch { fill: none; stroke: var(--border); stroke-width: 1.6; }
.rf-node { fill: var(--surface); stroke: var(--accent); stroke-width: 1.8; }
.rf-leaf { fill: var(--accent); }
.forest .rf-tree { opacity: 0; }
[data-vis="1"].active .rf-tree { animation: fadeIn .5s var(--ease) forwards; }
[data-vis="1"].active .rf-tree:nth-of-type(2) { animation-delay: .18s; }
[data-vis="1"].active .rf-tree:nth-of-type(3) { animation-delay: .36s; }

/* 06.2 model comparison bars */
.mtrack { fill: var(--bg-3); }
.mbar { fill: var(--accent); transform-box: fill-box; transform-origin: left; }
.mbar.b3 { fill: var(--accent); opacity: .8; }
.mbar.b4 { fill: var(--accent); opacity: .62; }
[data-vis="2"].active .mbar { animation: growBar .7s var(--ease) both; }
[data-vis="2"].active .mbar.b2 { animation-delay: .1s; }
[data-vis="2"].active .mbar.b3 { animation-delay: .2s; }
[data-vis="2"].active .mbar.b4 { animation-delay: .3s; }
.model-bars text { fill: var(--text-2); }

/* 06.3 generalization drop */
.gbar { transform-box: fill-box; transform-origin: bottom; }
.g-rand { fill: var(--text-3); opacity: .55; }
.g-farm { fill: var(--accent); }
.g-year { fill: var(--accent-2); }
[data-vis="3"].active .gbar { animation: riseBar .7s var(--ease) both; }
[data-vis="3"].active .g-farm { animation-delay: .15s; }
[data-vis="3"].active .g-year { animation-delay: .3s; }
@keyframes riseBar { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.gen-trend {
  fill: none; stroke: var(--danger); stroke-width: 2; stroke-dasharray: 5 5;
  stroke-dashoffset: 260; opacity: .9;
}
[data-vis="3"].active .gen-trend { animation: drawTrend 1s var(--ease) .6s forwards; }
@keyframes drawTrend { to { stroke-dashoffset: 0; } }
.gen-bars text { fill: var(--text-2); }

/* 06.4 web interface */
.br-frame { fill: var(--surface); stroke: var(--border); stroke-width: 1.8; }
.br-bar { stroke: var(--border); stroke-width: 1.5; }
.br-dot { fill: var(--text-3); }
.mp { stroke: var(--border); stroke-width: 1.2; opacity: 0; }
.mp.p1, .lg.p1 { fill: var(--accent-soft); }
.mp.p2, .lg.p2 { fill: rgba(251, 191, 36, .22); }
.mp.p3, .lg.p3 { fill: var(--bg-3); }
.lg { stroke: var(--border); stroke-width: 1.2; }
[data-vis="4"].active .mp { animation: padOn .45s var(--ease) forwards; }
.map .mp:nth-child(2) { animation-delay: .08s !important; }
.map .mp:nth-child(3) { animation-delay: .16s !important; }
.map .mp:nth-child(4) { animation-delay: .24s !important; }
.map .mp:nth-child(5) { animation-delay: .32s !important; }
.map .mp:nth-child(6) { animation-delay: .40s !important; }
.sel-box { fill: var(--bg-3); stroke: var(--accent); stroke-width: 1.3; }
.legend text, .browser text { fill: var(--text-2); }
