/* =========================================================
   NEXEN — illustration kit
   Loaded AFTER the page's theme sheet. Shared by every animated
   diagram on a product page.

   How it works
   - The SVG markup carries only shapes + class names. Colour, stroke
     and motion all live here, driven by the page's theme variables
     (--accent, --muted, --amber, ...), so a diagram re-themes with its page.
   - Each figure is `.illo` + one scene class (.dgWhy, .dgBms, ...).
   - The resting state (no motion) is the END of each story. Reduced-motion
     users see that frame; everyone else sees the loop.
   - Figures ship with `.idle` (paused). script.js removes it while the
     figure is on screen, so a story starts from its first frame when you
     scroll to it and nothing animates off-screen.
   ========================================================= */

:root {
    --dg-amb: var(--amber, #ffb020);
    --dg-amb-dim: rgba(255, 176, 32, 0.45);
}

/* Zero-size SVG that holds shared <symbol>s and gradients. */
.dgSprite {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.dgSprite .gA {
    stop-color: var(--accent);
}

.dgSprite .gM {
    stop-color: var(--dg-amb);
}

/* ---------------- Frame ---------------- */
.illo {
    margin: 0;
}

.illo svg {
    width: 100%;
    height: auto;
}

/* The "screen": deep background with a faint drafting-dot grid */
.illoPanel {
    background-color: var(--bg-deep);
    background-image: radial-gradient(var(--line-dim) 1px, transparent 1px);
    background-size: 16px 16px;
}

/* Wide figure with a caption bar (section hero diagrams) */
.illoWide {
    border: var(--edge);
    background: var(--bg-panel);
    margin-bottom: 40px;
}

.illoWide .illoPanel {
    border-bottom: var(--edge);
}

.illoWide svg {
    max-height: 380px;
}

.illoCap {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 8px 24px;
    padding: 14px 20px;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.illoCap b {
    color: var(--ink);
    font-weight: 500;
    margin-right: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Live status chip: stacked states that fade in sync with the scene */
.illoState {
    display: grid;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.illoState>span {
    grid-area: 1 / 1;
    text-align: right;
    white-space: nowrap;
}

.illoState>span::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-right: 8px;
    background: currentColor;
    box-shadow: 0 0 8px currentColor;
}

/* ---------------- Primitives (all scoped to .illo) ---------------- */
.illo .ln {
    fill: none;
    stroke: var(--muted);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.illo .part {
    fill: var(--bg-panel);
    stroke: var(--muted);
    stroke-width: 1.5;
    stroke-linejoin: round;
}

.illo .thick {
    stroke-width: 3;
}

.illo .dashed {
    stroke-dasharray: 3 4;
}

/* stroke colours */
.illo .sAcc {
    stroke: var(--accent);
}

.illo .sAmb {
    stroke: var(--dg-amb);
}

/* fills (no outline) */
.illo .fAcc {
    fill: var(--accent);
    stroke: none;
}

.illo .fAmb {
    fill: var(--dg-amb);
    stroke: none;
}

.illo .fMuted {
    fill: var(--muted);
    stroke: none;
}

/* glows */
.illo .glow {
    filter: drop-shadow(0 0 5px var(--accent-dim));
}

.illo .glowAmb {
    filter: drop-shadow(0 0 5px var(--dg-amb-dim));
}

/* labels */
.illo .txt {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.08em;
    fill: var(--muted);
}

.illo .tInk {
    fill: var(--ink);
}

.illo .tAcc {
    fill: var(--accent);
}

.illo .tAmb {
    fill: var(--dg-amb);
}

/* marching dashes = current flowing (same look as the hero power-flow) */
.illo .run {
    fill: none;
    stroke: var(--accent);
    stroke-width: 3;
    stroke-linecap: round;
    stroke-dasharray: 2 12;
    filter: drop-shadow(0 0 4px var(--accent));
    animation: dgRun 0.7s linear infinite;
}

.illo .run.amb {
    stroke: var(--dg-amb);
    filter: drop-shadow(0 0 4px var(--dg-amb));
}

/* spark burst: <use href="#dg-burst">, centred on its x/y + half its size */
.illo .burst {
    fill: none;
    stroke: var(--dg-amb);
    stroke-width: 2;
    stroke-linecap: round;
    filter: drop-shadow(0 0 4px var(--dg-amb));
    opacity: 0;
}

@keyframes dgRun {
    to {
        stroke-dashoffset: -14;
    }
}

@keyframes dgBreath {

    0%,
    100% {
        opacity: 0.65;
    }

    50% {
        opacity: 1;
    }
}

/* =========================================================
   1 · WHY — the line is cut, the lights go out        (9 s)
   ========================================================= */
.dgWhy .wire {
    fill: none;
    stroke: var(--muted);
    stroke-width: 2;
    stroke-linecap: round;
}

.dgWhy .moon {
    fill: var(--muted);
    opacity: 0.7;
}

.dgWhy .txt {
    font-size: 12px;
}

/* the two halves swing about their anchors (pole / roof mast) */
.dgWhy .wL {
    transform-origin: 174px 82px;
    transform: rotate(22deg);
    animation: dgWhyL 9s infinite;
}

.dgWhy .wR {
    transform-origin: 630px 130px;
    transform: rotate(-22deg);
    animation: dgWhyR 9s infinite;
}

/* current running along the wires while the line is whole */
.dgWhy .pulse {
    opacity: 0;
    animation: dgRun 0.7s linear infinite, dgWhyFeed 9s infinite;
}

/* bare copper at the cut ends */
.dgWhy .tip {
    fill: var(--dg-amb);
    animation: dgWhyTip 9s infinite;
}

.dgWhy .burst {
    transform-origin: 402px 153px;
    animation: dgWhySpark 9s infinite;
}

/* everything that glows while the lights are on */
.dgWhy .lit {
    opacity: 0;
    animation: dgWhyLit 9s infinite;
}

.dgWhy .down {
    animation: dgWhyDown 9s infinite;
}

.dgWhy .stOk {
    color: var(--accent);
    opacity: 0;
    animation: dgWhyOk 9s infinite;
}

.dgWhy .stBad {
    color: var(--dg-amb);
    animation: dgWhyBad 9s infinite;
}

@keyframes dgWhyL {

    0%,
    22% {
        transform: rotate(0deg);
        animation-timing-function: ease-in;
    }

    27% {
        transform: rotate(27deg);
        animation-timing-function: ease-in-out;
    }

    31% {
        transform: rotate(17deg);
        animation-timing-function: ease-in-out;
    }

    35% {
        transform: rotate(24deg);
        animation-timing-function: ease-in-out;
    }

    39%,
    82% {
        transform: rotate(22deg);
        animation-timing-function: ease-in-out;
    }

    92%,
    100% {
        transform: rotate(0deg);
    }
}

@keyframes dgWhyR {

    0%,
    22% {
        transform: rotate(0deg);
        animation-timing-function: ease-in;
    }

    27% {
        transform: rotate(-27deg);
        animation-timing-function: ease-in-out;
    }

    31% {
        transform: rotate(-17deg);
        animation-timing-function: ease-in-out;
    }

    35% {
        transform: rotate(-24deg);
        animation-timing-function: ease-in-out;
    }

    39%,
    82% {
        transform: rotate(-22deg);
        animation-timing-function: ease-in-out;
    }

    92%,
    100% {
        transform: rotate(0deg);
    }
}

@keyframes dgWhyFeed {

    0%,
    21.9% {
        opacity: 1;
    }

    22%,
    92.9% {
        opacity: 0;
    }

    93%,
    100% {
        opacity: 1;
    }
}

@keyframes dgWhyTip {

    0%,
    21.9% {
        opacity: 0;
    }

    22.5%,
    91% {
        opacity: 1;
    }

    92%,
    100% {
        opacity: 0;
    }
}

@keyframes dgWhySpark {

    0%,
    21.9% {
        opacity: 0;
        transform: scale(0.4);
    }

    23% {
        opacity: 1;
        transform: scale(1);
    }

    31% {
        opacity: 0;
        transform: scale(1.8);
    }

    91.9% {
        opacity: 0;
        transform: scale(0.4);
    }

    93% {
        opacity: 0.9;
        transform: scale(0.9);
    }

    98%,
    100% {
        opacity: 0;
        transform: scale(1.5);
    }
}

@keyframes dgWhyLit {

    0%,
    24% {
        opacity: 1;
    }

    25.5% {
        opacity: 0.15;
    }

    27% {
        opacity: 0.85;
    }

    28.5% {
        opacity: 0.1;
    }

    30% {
        opacity: 0.55;
    }

    31.5%,
    93% {
        opacity: 0;
    }

    94% {
        opacity: 0.6;
    }

    95% {
        opacity: 0.1;
    }

    96.5% {
        opacity: 0.9;
    }

    97.5% {
        opacity: 0.3;
    }

    99%,
    100% {
        opacity: 1;
    }
}

@keyframes dgWhyDown {

    0%,
    27% {
        opacity: 0;
    }

    31%,
    84% {
        opacity: 1;
    }

    88%,
    100% {
        opacity: 0;
    }
}

@keyframes dgWhyOk {

    0%,
    23% {
        opacity: 1;
    }

    25%,
    93% {
        opacity: 0;
    }

    95%,
    100% {
        opacity: 1;
    }
}

@keyframes dgWhyBad {

    0%,
    24% {
        opacity: 0;
    }

    26%,
    90% {
        opacity: 1;
    }

    93%,
    100% {
        opacity: 0;
    }
}

/* =========================================================
   2 · BMS — the full cell holds, the others catch up   (7 s)
   ========================================================= */
.dgBms .lvl {
    fill: var(--accent);
    fill-opacity: 0.8;
    stroke: none;
    transform-box: fill-box;
    transform-origin: 50% 100%;
    transform: scaleY(0.9);
}

.dgBms .l2 {
    animation: dgBmsC2 7s infinite;
}

.dgBms .l3 {
    animation: dgBmsC3 7s infinite;
}

/* excess leaves the full cell through its bleed resistor */
.dgBms .hot {
    opacity: 0;
    filter: drop-shadow(0 0 4px var(--dg-amb));
    animation: dgBmsBleed 7s infinite;
}

.dgBms .bleed {
    opacity: 0;
    animation: dgRun 0.7s linear infinite, dgBmsBleed 7s infinite;
}

.dgBms .target {
    animation: dgBmsTarget 7s infinite;
}

.dgBms .stA {
    opacity: 0;
    animation: dgBmsStA 7s infinite;
}

.dgBms .stB {
    animation: dgBmsStB 7s infinite;
}

@keyframes dgBmsC2 {

    0%,
    8% {
        transform: scaleY(0.58);
    }

    66%,
    94% {
        transform: scaleY(0.9);
    }

    100% {
        transform: scaleY(0.58);
    }
}

@keyframes dgBmsC3 {

    0%,
    8% {
        transform: scaleY(0.74);
    }

    66%,
    94% {
        transform: scaleY(0.9);
    }

    100% {
        transform: scaleY(0.74);
    }
}

@keyframes dgBmsBleed {

    0%,
    4% {
        opacity: 0;
    }

    8%,
    64% {
        opacity: 1;
    }

    68%,
    100% {
        opacity: 0;
    }
}

@keyframes dgBmsTarget {

    0%,
    62% {
        opacity: 0;
    }

    72%,
    92% {
        opacity: 1;
    }

    97%,
    100% {
        opacity: 0;
    }
}

@keyframes dgBmsStA {

    0%,
    64% {
        opacity: 1;
    }

    68%,
    100% {
        opacity: 0;
    }
}

@keyframes dgBmsStB {

    0%,
    68% {
        opacity: 0;
    }

    72%,
    93% {
        opacity: 1;
    }

    97%,
    100% {
        opacity: 0;
    }
}

/* =========================================================
   3 · HEAT — heat rises through the sink and radiates away   (loops)
   ========================================================= */
.dgHeat .heat {
    animation: dgBreath 2.6s ease-in-out infinite;
}

.dgHeat .hotpart {
    fill: var(--dg-amb);
    fill-opacity: 0.22;
    stroke: var(--dg-amb);
    stroke-width: 1.5;
    filter: drop-shadow(0 0 6px var(--dg-amb-dim));
    animation: dgBreath 2.6s ease-in-out infinite;
}

.dgHeat .wave {
    fill: none;
    stroke: var(--dg-amb);
    stroke-width: 2.2;
    stroke-linecap: round;
    opacity: 0.6;
    transform: translateY(-4px);
    animation: dgHeatRise 2.8s ease-out infinite;
}

.dgHeat .wave:nth-child(2) {
    animation-delay: -0.56s;
}

.dgHeat .wave:nth-child(3) {
    animation-delay: -1.12s;
}

.dgHeat .wave:nth-child(4) {
    animation-delay: -1.68s;
}

.dgHeat .wave:nth-child(5) {
    animation-delay: -2.24s;
}

@keyframes dgHeatRise {
    0% {
        opacity: 0;
        transform: translateY(10px);
    }

    20% {
        opacity: 0.9;
    }

    100% {
        opacity: 0;
        transform: translateY(-16px);
    }
}

/* =========================================================
   4 · CELLS — genuine, inspected, matched               (6 s)
   ========================================================= */
.dgCells .brand {
    font-family: var(--display);
    font-weight: 700;
    font-size: 15px;
    letter-spacing: 0.2em;
    fill: var(--ink);
}

.dgCells .spec {
    font-family: var(--mono);
    font-size: 8px;
    letter-spacing: 0.08em;
    fill: var(--muted);
}

.dgCells .pol {
    font-family: var(--mono);
    font-size: 15px;
    font-weight: 700;
    fill: var(--ink);
}

.dgCells .sheen {
    stroke-opacity: 0.25;
}

/* inspection line sweeping down the stack */
.dgCells .scan {
    opacity: 0;
    animation: dgCellScan 6s infinite;
}

/* a cell is outlined + ticked once the line has passed it */
.dgCells .ok1 {
    animation: dgCellOk1 6s infinite;
}

.dgCells .ok2 {
    animation: dgCellOk2 6s infinite;
}

.dgCells .ok3 {
    animation: dgCellOk3 6s infinite;
}

@keyframes dgCellScan {

    0%,
    6% {
        transform: translateY(14px);
        opacity: 0;
    }

    8% {
        transform: translateY(14px);
        opacity: 1;
    }

    80% {
        transform: translateY(166px);
        opacity: 1;
    }

    84%,
    100% {
        transform: translateY(166px);
        opacity: 0;
    }
}

@keyframes dgCellOk1 {

    0%,
    21% {
        opacity: 0;
    }

    24%,
    92% {
        opacity: 1;
    }

    97%,
    100% {
        opacity: 0;
    }
}

@keyframes dgCellOk2 {

    0%,
    45% {
        opacity: 0;
    }

    48%,
    92% {
        opacity: 1;
    }

    97%,
    100% {
        opacity: 0;
    }
}

@keyframes dgCellOk3 {

    0%,
    69% {
        opacity: 0;
    }

    72%,
    92% {
        opacity: 1;
    }

    97%,
    100% {
        opacity: 0;
    }
}

/* =========================================================
   5 · FUSE — overload, the fuse blows, the pack is protected   (7 s)
   ========================================================= */
.dgFuse .txt {
    font-size: 9px;
}

.dgFuse .flowOk {
    opacity: 0;
    animation: dgRun 0.7s linear infinite, dgFuseOk 7s infinite;
}

.dgFuse .surge {
    opacity: 0;
    stroke-width: 4;
    stroke-dasharray: 5 9;
    animation: dgRun 0.3s linear infinite, dgFuseSurge 7s infinite;
}

.dgFuse .mid {
    opacity: 0;
    animation: dgFuseMid 7s infinite;
}

.dgFuse .fil {
    opacity: 0;
    filter: drop-shadow(0 0 5px var(--dg-amb));
    animation: dgFuseFil 7s infinite;
}

.dgFuse .soot {
    fill: var(--dg-amb);
    fill-opacity: 0.14;
    stroke: none;
    animation: dgFuseSoot 7s infinite;
}

.dgFuse .flash {
    opacity: 0;
    transform-origin: 160px 112px;
    animation: dgFuseFlash 7s infinite;
}

.dgFuse .burst {
    transform-origin: 160px 112px;
    animation: dgFuseSpark 7s infinite;
}

.dgFuse .bolt {
    opacity: 0.3;
    animation: dgFuseBolt 7s infinite;
}

.dgFuse .shield {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    animation: dgFuseShield 7s infinite;
}

.dgFuse .shieldBody {
    fill: var(--accent);
    fill-opacity: 0.12;
}

@keyframes dgFuseOk {

    0%,
    19% {
        opacity: 1;
    }

    20%,
    95% {
        opacity: 0;
    }

    97%,
    100% {
        opacity: 1;
    }
}

@keyframes dgFuseSurge {

    0%,
    19% {
        opacity: 0;
    }

    21%,
    39.5% {
        opacity: 1;
    }

    40%,
    100% {
        opacity: 0;
    }
}

@keyframes dgFuseMid {

    0%,
    39.9% {
        opacity: 1;
    }

    40%,
    91% {
        opacity: 0;
    }

    93%,
    100% {
        opacity: 1;
    }
}

@keyframes dgFuseFil {

    0%,
    20% {
        opacity: 0;
    }

    28% {
        opacity: 0.6;
    }

    33% {
        opacity: 0.9;
    }

    39.5% {
        opacity: 1;
    }

    40%,
    100% {
        opacity: 0;
    }
}

@keyframes dgFuseSoot {

    0%,
    39.9% {
        opacity: 0;
    }

    41%,
    91% {
        opacity: 1;
    }

    96%,
    100% {
        opacity: 0;
    }
}

@keyframes dgFuseFlash {

    0%,
    39.9% {
        opacity: 0;
        transform: scale(0.3);
    }

    41% {
        opacity: 1;
        transform: scale(1);
    }

    52%,
    100% {
        opacity: 0;
        transform: scale(1.8);
    }
}

@keyframes dgFuseSpark {

    0%,
    39.9% {
        opacity: 0;
        transform: scale(0.4);
    }

    41% {
        opacity: 1;
        transform: scale(1);
    }

    50%,
    100% {
        opacity: 0;
        transform: scale(1.8);
    }
}

@keyframes dgFuseBolt {

    0%,
    19% {
        opacity: 0;
    }

    21% {
        opacity: 1;
    }

    24% {
        opacity: 0.3;
    }

    27% {
        opacity: 1;
    }

    30% {
        opacity: 0.5;
    }

    33%,
    39.9% {
        opacity: 1;
    }

    42%,
    91% {
        opacity: 0.3;
    }

    95%,
    100% {
        opacity: 0;
    }
}

@keyframes dgFuseShield {

    0%,
    43% {
        opacity: 0;
        transform: scale(0.5);
    }

    49% {
        opacity: 1;
        transform: scale(1.1);
    }

    52%,
    90% {
        opacity: 1;
        transform: scale(1);
    }

    96%,
    100% {
        opacity: 0;
        transform: scale(1);
    }
}

/* =========================================================
   6 · LIMIT — the buck keeps the board under its limit   (7 s)
   ========================================================= */
.dgLimit .curve {
    stroke-linecap: butt;
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
}

.dgLimit .curveA {
    stroke-width: 2.2;
    animation: dgLimA 7s infinite;
}

.dgLimit .curveB {
    stroke-width: 2.6;
    animation: dgLimB 7s infinite;
}

.dgLimit .excess {
    fill: var(--dg-amb);
    fill-opacity: 0.22;
    stroke: none;
    animation: dgLimX 7s infinite;
}

@keyframes dgLimA {

    0%,
    4% {
        stroke-dashoffset: 1;
        opacity: 1;
    }

    38%,
    94% {
        stroke-dashoffset: 0;
        opacity: 1;
    }

    99%,
    100% {
        stroke-dashoffset: 0;
        opacity: 0;
    }
}

@keyframes dgLimB {

    0%,
    46% {
        stroke-dashoffset: 1;
        opacity: 1;
    }

    76%,
    94% {
        stroke-dashoffset: 0;
        opacity: 1;
    }

    99%,
    100% {
        stroke-dashoffset: 0;
        opacity: 0;
    }
}

@keyframes dgLimX {

    0%,
    76% {
        opacity: 0;
    }

    86%,
    94% {
        opacity: 1;
    }

    99%,
    100% {
        opacity: 0;
    }
}

/* =========================================================
   7 · LOW VOLTAGE — mains stops at the sealed supply
   ========================================================= */
.dgLv .zone {
    fill: var(--accent);
    fill-opacity: 0.04;
    stroke: var(--accent);
    stroke-width: 1.2;
    stroke-dasharray: 4 4;
    animation: dgMarch 1.6s linear infinite;
}

.dgLv .brandSm {
    font-family: var(--display);
    font-weight: 700;
    font-size: 18px;
    fill: var(--accent);
}

.dgLv .bulb {
    animation: dgBreath 3s ease-in-out infinite;
}

@keyframes dgMarch {
    to {
        stroke-dashoffset: -16;
    }
}

/* =========================================================
   8 · MAINSTREAM — sponsorship in, light out, $0 to the family
   ========================================================= */
.dgMain .name,
.dgLog .name {
    font-family: var(--display);
    font-weight: 700;
    fill: var(--ink);
}

.dgMain .name {
    font-size: 18px;
}

.dgMain .name.sm {
    font-size: 15px;
}

.dgMain .price {
    font-family: var(--display);
    font-weight: 700;
    font-size: 24px;
    fill: var(--accent);
    animation: dgBreath 2.4s ease-in-out infinite;
}

.dgMain .bulb {
    animation: dgBreath 3s ease-in-out infinite;
}

/* =========================================================
   9 · BUILD LOG — progress along revisions A to E        (7 s)
   ========================================================= */
.dgLog .name {
    font-size: 15px;
}

.dgLog .name.dim {
    fill: var(--muted);
}

.dgLog .base circle {
    fill: var(--bg-deep);
}

.dgLog .letter {
    font-family: var(--display);
    font-weight: 700;
    font-size: 18px;
    text-anchor: middle;
    fill: var(--muted);
}

.dgLog .letter.lit {
    fill: var(--accent);
}

.dgLog .grow {
    transform-box: fill-box;
    transform-origin: 0 50%;
    animation: dgLogGrow 7s infinite;
}

.dgLog .rA {
    animation: dgLogA 7s infinite;
}

.dgLog .rB {
    animation: dgLogB 7s infinite;
}

.dgLog .rC {
    animation: dgLogC 7s infinite;
}

.dgLog .ring {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    opacity: 0.4;
    transform: scale(1.35);
    animation: dgRing 2.2s ease-out infinite;
}

@keyframes dgRing {
    0% {
        opacity: 0.7;
        transform: scale(1);
    }

    100% {
        opacity: 0;
        transform: scale(1.8);
    }
}

@keyframes dgLogGrow {

    0%,
    4% {
        transform: scaleX(0);
        opacity: 1;
    }

    42%,
    94% {
        transform: scaleX(1);
        opacity: 1;
    }

    99%,
    100% {
        transform: scaleX(1);
        opacity: 0;
    }
}

@keyframes dgLogA {

    0%,
    2% {
        opacity: 0;
    }

    6%,
    94% {
        opacity: 1;
    }

    99%,
    100% {
        opacity: 0;
    }
}

@keyframes dgLogB {

    0%,
    22% {
        opacity: 0;
    }

    26%,
    94% {
        opacity: 1;
    }

    99%,
    100% {
        opacity: 0;
    }
}

@keyframes dgLogC {

    0%,
    40% {
        opacity: 0;
    }

    44%,
    94% {
        opacity: 1;
    }

    99%,
    100% {
        opacity: 0;
    }
}

/* =========================================================
   10 · HERO (landing page) — the line is cut, the lights stay on   (10 s)
   Same story as 1 · WHY, with the ending the product exists for.
   Resting frame = after the cut: wire down, unit active, lights on.
   Drawn inside the landing page's .schematic card; landing.css points
   --accent at the BCKUP//ENRGY green for this scene.
   ========================================================= */
.dgHero .frame {
    fill: none;
    stroke: var(--line-dim);
    stroke-width: 1;
}

.dgHero .gStop {
    stop-color: var(--accent);
}

.dgHero .txt {
    font-size: 11px;
}

.dgHero .wire {
    fill: none;
    stroke: var(--muted);
    stroke-width: 2;
    stroke-linecap: round;
}

/* the two halves of the service line swing about their anchors (pole / roof mast) */
.dgHero .wL {
    transform-origin: 94px 120px;
    transform: rotate(24deg);
    animation: dgHeroL 10s infinite;
}

.dgHero .wR {
    transform-origin: 252px 164px;
    transform: rotate(-24deg);
    animation: dgHeroR 10s infinite;
}

/* grid current, only while the line is whole */
.dgHero .pulse {
    opacity: 0;
    animation: dgRun 0.7s linear infinite, dgHeroFeed 10s infinite;
}

/* bare copper at the cut ends */
.dgHero .tip {
    fill: var(--dg-amb);
    animation: dgHeroTip 10s infinite;
}

.dgHero .burst {
    transform-origin: 173px 154px;
    animation: dgHeroSpark 10s infinite;
}

/* the unit wakes when the grid goes: outline, bolt and a glow */
.dgHero .unitOn {
    animation: dgHeroUnit 10s infinite;
}

/* the lights flicker out for a moment, then hold once the unit takes over */
.dgHero .lit {
    animation: dgHeroLit 10s infinite;
}

.dgHero .stA,
.dgHero .stC {
    opacity: 0;
}

.dgHero .stA {
    animation: dgHeroGridUp 10s infinite;
}

.dgHero .stB {
    animation: dgHeroGridDown 10s infinite;
}

.dgHero .stC {
    animation: dgHeroUnitIdle 10s infinite;
}

.dgHero .stD {
    animation: dgHeroUnitLive 10s infinite;
}

@keyframes dgHeroL {

    0%,
    22% {
        transform: rotate(0deg);
        animation-timing-function: ease-in;
    }

    27% {
        transform: rotate(29deg);
        animation-timing-function: ease-in-out;
    }

    31% {
        transform: rotate(19deg);
        animation-timing-function: ease-in-out;
    }

    35% {
        transform: rotate(26deg);
        animation-timing-function: ease-in-out;
    }

    39%,
    82% {
        transform: rotate(24deg);
        animation-timing-function: ease-in-out;
    }

    92%,
    100% {
        transform: rotate(0deg);
    }
}

@keyframes dgHeroR {

    0%,
    22% {
        transform: rotate(0deg);
        animation-timing-function: ease-in;
    }

    27% {
        transform: rotate(-29deg);
        animation-timing-function: ease-in-out;
    }

    31% {
        transform: rotate(-19deg);
        animation-timing-function: ease-in-out;
    }

    35% {
        transform: rotate(-26deg);
        animation-timing-function: ease-in-out;
    }

    39%,
    82% {
        transform: rotate(-24deg);
        animation-timing-function: ease-in-out;
    }

    92%,
    100% {
        transform: rotate(0deg);
    }
}

@keyframes dgHeroFeed {

    0%,
    21.9% {
        opacity: 1;
    }

    22%,
    92.9% {
        opacity: 0;
    }

    93%,
    100% {
        opacity: 1;
    }
}

@keyframes dgHeroTip {

    0%,
    21.9% {
        opacity: 0;
    }

    22.5%,
    91% {
        opacity: 1;
    }

    92%,
    100% {
        opacity: 0;
    }
}

@keyframes dgHeroSpark {

    0%,
    21.9% {
        opacity: 0;
        transform: scale(0.4);
    }

    23% {
        opacity: 1;
        transform: scale(1);
    }

    31%,
    100% {
        opacity: 0;
        transform: scale(1.45);
    }
}

@keyframes dgHeroLit {

    0%,
    21.9% {
        opacity: 1;
    }

    22.5% {
        opacity: 0.2;
    }

    24% {
        opacity: 0.85;
    }

    26% {
        opacity: 0.1;
    }

    29% {
        opacity: 0.6;
    }

    31%,
    36% {
        opacity: 0.08;
    }

    39%,
    100% {
        opacity: 1;
    }
}

@keyframes dgHeroUnit {

    0%,
    33% {
        opacity: 0;
    }

    37%,
    92% {
        opacity: 1;
    }

    96%,
    100% {
        opacity: 0;
    }
}

@keyframes dgHeroGridUp {

    0%,
    21.9% {
        opacity: 1;
    }

    22%,
    92.9% {
        opacity: 0;
    }

    93%,
    100% {
        opacity: 1;
    }
}

@keyframes dgHeroGridDown {

    0%,
    21.9% {
        opacity: 0;
    }

    22%,
    92.9% {
        opacity: 1;
    }

    93%,
    100% {
        opacity: 0;
    }
}

@keyframes dgHeroUnitIdle {

    0%,
    35.9% {
        opacity: 1;
    }

    36%,
    95.9% {
        opacity: 0;
    }

    96%,
    100% {
        opacity: 1;
    }
}

@keyframes dgHeroUnitLive {

    0%,
    35.9% {
        opacity: 0;
    }

    36%,
    95.9% {
        opacity: 1;
    }

    96%,
    100% {
        opacity: 0;
    }
}

/* =========================================================
   11 · LUMINA3ai (landing page) — a student and LUMINA3ai trade messages   (12 s)
   The student asks, LUMINA3ai types, answers line by line, the student follows
   up, LUMINA3ai types again. No numbers or claims are drawn: lines stand in
   for the words. Resting frame = the end of the story: all three messages in,
   LUMINA3ai typing, the input bar empty.
   Drawn inside the landing page's .schematic card; landing.css points
   --accent at LUMINA3ai's blue for this scene.
   ========================================================= */
.dgLumina .frame {
    fill: none;
    stroke: var(--line-dim);
    stroke-width: 1;
}

.dgLumina .txt {
    font-size: 11px;
}

/* messages pop up from below their final place */
.dgLumina .m1 {
    animation: dgLmM1 12s var(--ease-out) infinite;
}

.dgLumina .m2 {
    animation: dgLmM2 12s var(--ease-out) infinite;
}

.dgLumina .m3 {
    animation: dgLmM3 12s var(--ease-out) infinite;
}

.dgLumina .tp {
    animation: dgLmTyping 12s var(--ease-out) infinite;
}

/* the answer is written line by line (pathLength 1: dashoffset 1 = not drawn yet) */
.dgLumina .d1,
.dgLumina .d2,
.dgLumina .d3,
.dgLumina .d4,
.dgLumina .inLine {
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
}

.dgLumina .d1 {
    animation: dgLmD1 12s infinite;
}

.dgLumina .d2 {
    animation: dgLmD2 12s infinite;
}

.dgLumina .d3 {
    animation: dgLmD3 12s infinite;
}

.dgLumina .d4 {
    animation: dgLmD4 12s infinite;
}

/* the student's message is typed into the input bar, then sent */
.dgLumina .inLine {
    stroke-dashoffset: 1;
    animation: dgLmInput 12s infinite;
}

.dgLumina .dot1,
.dgLumina .dot2,
.dgLumina .dot3 {
    animation: dgBreath 1s ease-in-out infinite;
}

.dgLumina .dot2 {
    animation-delay: 0.18s;
}

.dgLumina .dot3 {
    animation-delay: 0.36s;
}

/* readout: the student row and the LUMINA3ai row each swap between two states */
.dgLumina .stA,
.dgLumina .stC {
    opacity: 0;
}

.dgLumina .stA {
    animation: dgLmStudentTyping 12s infinite;
}

.dgLumina .stB {
    animation: dgLmStudentWaiting 12s infinite;
}

.dgLumina .stC {
    animation: dgLmListening 12s infinite;
}

.dgLumina .stD {
    animation: dgLmAiTyping 12s infinite;
}

@keyframes dgLmM1 {

    0%,
    5% {
        opacity: 0;
        transform: translateY(10px);
    }

    9%,
    92% {
        opacity: 1;
        transform: translateY(0);
    }

    96%,
    100% {
        opacity: 0;
        transform: translateY(0);
    }
}

@keyframes dgLmM2 {

    0%,
    33% {
        opacity: 0;
        transform: translateY(10px);
    }

    38%,
    92% {
        opacity: 1;
        transform: translateY(0);
    }

    96%,
    100% {
        opacity: 0;
        transform: translateY(0);
    }
}

@keyframes dgLmM3 {

    0%,
    56% {
        opacity: 0;
        transform: translateY(10px);
    }

    60%,
    92% {
        opacity: 1;
        transform: translateY(0);
    }

    96%,
    100% {
        opacity: 0;
        transform: translateY(0);
    }
}

/* typing indicator: first while the answer is composed, again after the follow-up */
@keyframes dgLmTyping {

    0%,
    10% {
        opacity: 0;
    }

    14%,
    31% {
        opacity: 1;
    }

    33%,
    63% {
        opacity: 0;
    }

    67%,
    92% {
        opacity: 1;
    }

    96%,
    100% {
        opacity: 0;
    }
}

@keyframes dgLmD1 {

    0%,
    35% {
        stroke-dashoffset: 1;
    }

    40%,
    100% {
        stroke-dashoffset: 0;
    }
}

@keyframes dgLmD2 {

    0%,
    39% {
        stroke-dashoffset: 1;
    }

    44%,
    100% {
        stroke-dashoffset: 0;
    }
}

@keyframes dgLmD3 {

    0%,
    43% {
        stroke-dashoffset: 1;
    }

    48%,
    100% {
        stroke-dashoffset: 0;
    }
}

@keyframes dgLmD4 {

    0%,
    47% {
        stroke-dashoffset: 1;
    }

    52%,
    100% {
        stroke-dashoffset: 0;
    }
}

@keyframes dgLmInput {

    0%,
    1% {
        stroke-dashoffset: 1;
    }

    5% {
        stroke-dashoffset: 0;
    }

    6%,
    52% {
        stroke-dashoffset: 1;
    }

    57% {
        stroke-dashoffset: 0;
    }

    58%,
    100% {
        stroke-dashoffset: 1;
    }
}

@keyframes dgLmStudentTyping {

    0%,
    5.9% {
        opacity: 1;
    }

    6%,
    51.9% {
        opacity: 0;
    }

    52%,
    57.9% {
        opacity: 1;
    }

    58%,
    100% {
        opacity: 0;
    }
}

@keyframes dgLmStudentWaiting {

    0%,
    5.9% {
        opacity: 0;
    }

    6%,
    51.9% {
        opacity: 1;
    }

    52%,
    57.9% {
        opacity: 0;
    }

    58%,
    100% {
        opacity: 1;
    }
}

@keyframes dgLmListening {

    0%,
    10.9% {
        opacity: 1;
    }

    11%,
    32.9% {
        opacity: 0;
    }

    33%,
    65.9% {
        opacity: 1;
    }

    66%,
    91.9% {
        opacity: 0;
    }

    92%,
    100% {
        opacity: 1;
    }
}

@keyframes dgLmAiTyping {

    0%,
    10.9% {
        opacity: 0;
    }

    11%,
    32.9% {
        opacity: 1;
    }

    33%,
    65.9% {
        opacity: 0;
    }

    66%,
    91.9% {
        opacity: 1;
    }

    92%,
    100% {
        opacity: 0;
    }
}

/* wide scenes whose labels matter scroll sideways on small screens */
.illoScroll .illoPanel {
    overflow-x: auto;
}

.illoScroll svg {
    min-width: 640px;
}

/* ---------------- Play control + reduced motion ---------------- */
.illo.idle,
.illo.idle * {
    animation-play-state: paused !important;
}

@media (prefers-reduced-motion: reduce) {

    .illo,
    .illo * {
        animation: none !important;
    }
}

@media (max-width: 560px) {

    /* labels inside the wide scene would shrink below readable size */
    .dgWhy .txt {
        display: none;
    }
}
