/* ╔═══════════════════════════════════════════════════════════════════════════╗
   ║  THE HOT PIC — THEME LAYER                                                ║
   ║                                                                           ║
   ║  The motion system here is ported from SENTINEL v14d: real masked glass    ║
   ║  neon tubes with gas moving inside them, a directional shutter wipe on     ║
   ║  every route change, and one sweep-driven circuit band across the whole    ║
   ║  interface. The palette is lifted from the splash illustration — hot pink, ║
   ║  gold, lavender, wall green, deep aubergine.                              ║
   ╚═══════════════════════════════════════════════════════════════════════════╝ */

/* ── Registered properties ────────────────────────────────────────────────────
   --sweep-deg is written by canvas-bg.js roughly ten times a second. Registering
   it lets the browser interpolate between those writes; without @property it is
   an unanimatable token and the circuit band visibly steps. The published value
   is monotonic and never wraps at 360, or the band would spin backwards once
   per revolution.                                                            */
@property --sweep-deg { syntax: "<angle>";      inherits: true;  initial-value: 0deg; }
@property --tube-turn { syntax: "<angle>";      inherits: false; initial-value: 0deg; }
@property --gas-a     { syntax: "<percentage>"; inherits: false; initial-value: 40%; }

:root {
  /* ── Palette, sampled from the splash art ─────────────────────────────── */
  --hp-pink:    #f2496e;
  --hp-pink-hi: #ff6f8d;
  --hp-coral:   #fb5b32;
  --hp-gold:    #ffc93c;
  --hp-gold-hi: #ffdd7a;
  --hp-lav:     #b49ce0;
  --hp-violet:  #7c53c9;
  --hp-plum:    #3d2159;
  --hp-green:   #6d9440;
  --hp-mint:    #74d6a8;
  --hp-cream:   #fff4e6;

  /* ── Surfaces ─────────────────────────────────────────────────────────── */
  --bg-deep:    #100a18;
  --bg:         #160e22;
  --bg-raise:   #1e142c;
  --panel:      rgba(38, 24, 54, .62);
  --panel-solid:#241634;
  --hair:       rgba(180, 156, 224, .18);
  --hair-hot:   rgba(242, 73, 110, .34);

  /* ── Type ─────────────────────────────────────────────────────────────── */
  --ink:        #f6ecff;
  --ink-2:      #c9b6e0;
  --ink-3:      #8e7aa8;
  --ink-on-hot: #2a0f1b;

  /* ── Semantic ─────────────────────────────────────────────────────────── */
  --ok:      var(--hp-mint);
  --warn:    var(--hp-gold);
  --err:     var(--hp-coral);
  --busy:    var(--hp-lav);
  --idle:    var(--ink-3);
  --sim:     #ff9ad5;

  /* ── Geometry ─────────────────────────────────────────────────────────── */
  --r-sm: 8px; --r-md: 14px; --r-lg: 20px; --r-xl: 28px; --r-pill: 999px;
  --rail-w: 232px; --rail-w-collapsed: 68px;
  --header-h: 60px; --strip-h: 132px; --inspector-w: 356px;

  /* ── Motion ───────────────────────────────────────────────────────────── */
  --ease-out:  cubic-bezier(.16,1,.3,1);
  --ease-gta:  cubic-bezier(.62,.02,.12,1);
  --ease-snap: cubic-bezier(.34,1.56,.64,1);
  --pulse:     2900ms;
  --sweep:     9000ms;

  /* ── Tube ─────────────────────────────────────────────────────────────── */
  --tube-w: 6px;
  --tube-r: var(--r-md);
  --cc: var(--hp-pink);

  --nav-dir: 1;
  --sweep-deg: 0deg;
  transition: --sweep-deg 140ms linear;

  --density: 1;
  color-scheme: dark;
}

/* Interface density (Settings › Interface) */
:root[data-density="compact"]     { --density: .88; }
:root[data-density="comfortable"] { --density: 1.12; }

/* Light theme. The neon language survives — it just runs on paper. */
:root[data-theme="light"] {
  --bg-deep: #f3ebe0; --bg: #fbf4ea; --bg-raise: #fff;
  --panel: rgba(255,255,255,.72); --panel-solid: #fff;
  --hair: rgba(61,33,89,.16); --hair-hot: rgba(242,73,110,.3);
  --ink: #26142f; --ink-2: #5a4270; --ink-3: #8b7a9c;
  color-scheme: light;
}
:root[data-contrast="high"] {
  --hair: rgba(180,156,224,.5); --ink-2: #e4d8f2; --ink-3: #c0aed4;
}

/* ── Per-item neon colours ──────────────────────────────────────────────────
   Cycled by index so a grid of cards reads as a bank of different tubes rather
   than one repeated sign.                                                   */
.n0 { --cc: var(--hp-pink); }   .n1 { --cc: var(--hp-gold); }
.n2 { --cc: var(--hp-lav);  }   .n3 { --cc: var(--hp-mint); }
.n4 { --cc: var(--hp-coral);}   .n5 { --cc: var(--hp-violet); }
.n6 { --cc: var(--hp-green);}   .n7 { --cc: var(--hp-pink-hi); }
.n8 { --cc: var(--hp-gold-hi); }

/* ═══════════════════════════════════════════════════════════════════════════
   BASE
   ═══════════════════════════════════════════════════════════════════════════ */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg-deep);
  color: var(--ink);
  font: 400 calc(14px * var(--density))/1.55 ui-rounded, "SF Pro Rounded",
        "Segoe UI Variable Display", "Nunito", "Trebuchet MS", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  overscroll-behavior: none;
}
h1, h2, h3, h4, .display {
  font-family: ui-rounded, "SF Pro Rounded", "Segoe UI Variable Display",
               "Nunito", "Arial Rounded MT Bold", system-ui, sans-serif;
  font-weight: 800; letter-spacing: -.01em; margin: 0;
}
code, kbd, .mono, .num {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}
:focus-visible {
  outline: 2px solid var(--hp-gold);
  outline-offset: 2px;
  border-radius: 4px;
}
::selection { background: var(--hp-pink); color: #fff; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--hp-violet) 45%, transparent);
  border-radius: 99px; border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--hp-pink) 60%, transparent); background-clip: content-box; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 9999;
  background: var(--hp-gold); color: var(--ink-on-hot);
  padding: 10px 16px; border-radius: var(--r-pill); font-weight: 800;
  transform: translateY(-160%); transition: transform .2s var(--ease-out);
}
.skip-link:focus { transform: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE TUBE
   Anatomy, outside in:
     .tube        bloom carrier. Unmasked, so its drop-shadow can escape.
       ::after    electrode caps where the tube enters the housing.
       .gas       the ring itself, clipped to a hollow rounded rectangle by two
                  mask layers composited with exclude. Everything inside is
                  confined to the glass.
         ::before the gas: a blurred conic hot band, rotating.
         ::after  the glass: outer specular edge plus a raking sheen.
     .haze        the interior. Contained gas filling the cell body, plus the
                  inner glass line.

   Any host of .tube must be position:relative and must NOT clip overflow, or
   the bloom is amputated at its own border.
   ═══════════════════════════════════════════════════════════════════════════ */
.neon { position: relative; overflow: visible; border-radius: var(--tube-r); }

.tube {
  position: absolute; inset: 0; z-index: 4;
  border-radius: inherit; pointer-events: none;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--cc) 58%, transparent))
          drop-shadow(0 0 17px color-mix(in srgb, var(--cc) 32%, transparent));
  animation: tube-bloom var(--pulse) ease-in-out infinite;
  animation-delay: var(--phase, 0ms);
}
@keyframes tube-bloom {
  0%, 100% { filter: drop-shadow(0 0 4px  color-mix(in srgb, var(--cc) 42%, transparent))
                     drop-shadow(0 0 13px color-mix(in srgb, var(--cc) 20%, transparent)); }
  50%      { filter: drop-shadow(0 0 9px  color-mix(in srgb, var(--cc) 90%, transparent))
                     drop-shadow(0 0 30px color-mix(in srgb, var(--cc) 54%, transparent))
                     drop-shadow(0 0 58px color-mix(in srgb, var(--cc) 26%, transparent)); }
}

/* Electrodes. box-shadow offsets must be <length> — percentages silently kill
   the whole declaration, so these are radial gradients that scale with the
   tube width instead. */
.tube::after {
  content: ""; position: absolute; z-index: 2;
  left: 0; right: 0; top: 0;
  height: calc(var(--tube-w) * 1.15);
  pointer-events: none;
  background:
    radial-gradient(closest-side circle at 50% 50%, #fff 8%,
      color-mix(in srgb, var(--cc) 92%, #fff) 42%, transparent 78%),
    radial-gradient(closest-side circle at 50% 50%, #fff 8%,
      color-mix(in srgb, var(--cc) 92%, #fff) 42%, transparent 78%);
  background-size: calc(var(--tube-w) * 3.4) 100%, calc(var(--tube-w) * 3.4) 100%;
  background-position: 20% 50%, 80% 50%;
  background-repeat: no-repeat;
  opacity: .95;
}

.gas {
  position: absolute; inset: 0;
  border-radius: inherit;
  padding: var(--tube-w);
  overflow: hidden;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--cc) 60%, transparent),
    color-mix(in srgb, var(--cc) 32%, transparent) 45%,
    color-mix(in srgb, var(--cc) 72%, transparent));
}
.gas::before {
  content: ""; position: absolute;
  left: -50%; top: -50%; width: 200%; height: 200%;
  background: conic-gradient(from 0deg,
    transparent 0deg,
    color-mix(in srgb, var(--cc) 22%, transparent) 20deg,
    color-mix(in srgb, var(--cc) 90%, #fff) 44deg,
    #fff 56deg,
    color-mix(in srgb, var(--cc) 88%, #fff) 70deg,
    color-mix(in srgb, var(--cc) 30%, transparent) 110deg,
    transparent 158deg,
    color-mix(in srgb, var(--cc) 45%, transparent) 226deg,
    color-mix(in srgb, var(--cc) 95%, #fff) 258deg,
    #fff 268deg,
    color-mix(in srgb, var(--cc) 20%, transparent) 306deg,
    transparent 360deg);
  filter: blur(3.4px) saturate(1.6) contrast(1.15);
  animation: gas-swirl 7.5s linear infinite;
  animation-delay: var(--phase, 0ms);
  will-change: transform;
}
@keyframes gas-swirl { to { transform: rotate(360deg); } }

.gas::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1.3px rgba(255,255,255,.46),
              inset 0 0 6px -2px rgba(255,255,255,.30);
  background: linear-gradient(148deg,
    rgba(255,255,255,.42) 0%, rgba(255,255,255,.10) 24%,
    transparent 46%, rgba(255,255,255,.16) 90%);
  mix-blend-mode: screen;
}

.haze {
  position: absolute; inset: var(--tube-w); z-index: 2;
  border-radius: calc(var(--tube-r) - var(--tube-w));
  pointer-events: none; mix-blend-mode: screen;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08);
  background:
    radial-gradient(78% 62% at 22% 8%,  color-mix(in srgb, var(--cc) 22%, transparent), transparent 72%),
    radial-gradient(66% 74% at 88% 96%, color-mix(in srgb, var(--cc) 17%, transparent), transparent 70%),
    radial-gradient(120% 100% at 50% 50%, transparent 42%, color-mix(in srgb, var(--cc) 12%, transparent));
  animation: haze-drift 11s ease-in-out infinite alternate;
  animation-delay: var(--phase, 0ms);
}
@keyframes haze-drift {
  0%   { background-position: 0 0, 0 0, 0 0;      opacity: .76; }
  100% { background-position: 14% 9%, -12% -8%, 0; opacity: 1; }
}

/* Strike. A real tube stutters and catches; it does not fade up. */
.neon.strikeable:hover > .tube,
.neon.strikeable:focus-within > .tube {
  animation: tube-strike 1s steps(1, end) 1 forwards,
             tube-bloom var(--pulse) ease-in-out infinite 1s;
}
@keyframes tube-strike {
  0%, 4%   { filter: drop-shadow(0 0 2px  color-mix(in srgb, var(--cc) 18%, transparent)); }
  5%       { filter: drop-shadow(0 0 14px #fff) drop-shadow(0 0 40px var(--cc)); }
  6%, 8%   { filter: drop-shadow(0 0 2px  color-mix(in srgb, var(--cc) 14%, transparent)); }
  9%       { filter: drop-shadow(0 0 16px #fff) drop-shadow(0 0 48px var(--cc)); }
  10%, 12% { filter: drop-shadow(0 0 3px  color-mix(in srgb, var(--cc) 28%, transparent)); }
  13%,100% { filter: drop-shadow(0 0 10px color-mix(in srgb, var(--cc) 95%, transparent))
                     drop-shadow(0 0 34px color-mix(in srgb, var(--cc) 68%, transparent))
                     drop-shadow(0 0 70px color-mix(in srgb, var(--cc) 34%, transparent)); }
}
.neon.strikeable:hover > .gas::before { animation-duration: 2.6s; }

/* ── Gas carries state ──────────────────────────────────────────────────────
   Status stops being a word in a label and becomes the condition of the gas.
   You read a grid before you read any of it.                                */
.neon[data-tube="dead"] > .tube { animation: none !important;
  filter: drop-shadow(0 0 2px rgba(142,122,168,.22)) !important; }
.neon[data-tube="dead"] > .tube > .gas {
  background: linear-gradient(180deg, rgba(112,96,132,.30), rgba(70,58,88,.22));
  animation: dead-glass 13s steps(1, end) infinite;
}
.neon[data-tube="dead"] > .tube > .gas::before {
  background: linear-gradient(180deg, color-mix(in srgb, var(--cc) 66%, transparent), transparent 70%);
  filter: blur(6px);
  animation: gas-drain 1.25s cubic-bezier(.5,0,.75,0) both;
}
@keyframes gas-drain {
  0%   { transform: translateY(0);    opacity: .9; }
  70%  { transform: translateY(62%);  opacity: .32; }
  100% { transform: translateY(112%); opacity: 0; }
}
@keyframes dead-glass {
  0%, 93% { opacity: .55; } 94% { opacity: .95; }
  95%, 96% { opacity: .40; } 97% { opacity: .88; } 98%, 100% { opacity: .55; }
}
.neon[data-tube="dead"] > .haze { opacity: .09; animation: none; }

/* Working: the gas surges electrode to electrode. */
.neon[data-tube="busy"] > .tube > .gas::before {
  animation: gas-swirl 1.5s linear infinite, gas-surge 1.05s ease-in-out infinite;
}
@keyframes gas-surge { 0%,100% { opacity: .34 } 45% { opacity: 1 } }

/* Warning: amber striations drift through otherwise healthy gas. */
.neon[data-tube="warn"] > .tube > .gas {
  background-image:
    linear-gradient(180deg,
      color-mix(in srgb, var(--cc) 60%, transparent),
      color-mix(in srgb, var(--cc) 32%, transparent) 45%,
      color-mix(in srgb, var(--cc) 72%, transparent)),
    repeating-linear-gradient(118deg,
      color-mix(in srgb, var(--hp-gold) 55%, transparent) 0 3px, transparent 3px 11px);
  background-size: 100% 100%, 240% 240%;
  animation: gas-striate 3.2s linear infinite;
}
@keyframes gas-striate { 0% { background-position: 0 0, 0 0; } 100% { background-position: 0 0, 240% 0; } }

/* Error */
.neon[data-tube="error"] { --cc: var(--hp-coral); }
.neon[data-tube="error"] > .tube > .gas::before { animation: gas-swirl 3s linear infinite, gas-surge .55s steps(2,end) infinite; }

/* ═══════════════════════════════════════════════════════════════════════════
   ROUTE TRANSITIONS
   The router parks inactive routes with display:none, so an outgoing route
   would otherwise cease to exist on the same frame the class flips — which
   reads as a hard cut. .rt-exit lifts it back out of the park, absolutely
   positioned over the stage so it cannot push layout, long enough to play a
   real exit. --nav-dir is published once from the route index delta so the
   shutter, the exit and the entrance all throw the same way.
   ═══════════════════════════════════════════════════════════════════════════ */
.route { display: none; }
.route.active { display: block; }

.route.rt-exit {
  display: block !important;
  position: absolute !important; inset: 0;
  z-index: 9; pointer-events: none !important; overflow: hidden;
  animation: rt-exit .34s var(--ease-gta) both !important;
}
@keyframes rt-exit {
  0%   { opacity: 1; transform: none; filter: none; clip-path: inset(0 0 0 0); }
  34%  { opacity: 1; filter: brightness(1.7) saturate(1.6);
         transform: perspective(1200px) translate3d(calc(var(--nav-dir) * -2vw), 0, 0); }
  100% { opacity: 0; filter: brightness(2.4) saturate(1.9) blur(5px);
         transform: perspective(1200px) rotateX(10deg)
                    translate3d(calc(var(--nav-dir) * -16vw), -20px, 0) scale(.93);
         clip-path: inset(46% 0 46% 0); }
}

.route.rt-enter { animation: rt-enter .54s var(--ease-gta) both; }
@keyframes rt-enter {
  0%   { opacity: 0; clip-path: inset(47% 0 47% 0);
         transform: perspective(1200px) rotateX(-32deg)
                    translate3d(calc(var(--nav-dir) * 19vw), 0, 0) scale(.94);
         filter: brightness(2.6) saturate(2.1) blur(4px); }
  12%  { opacity: 1; clip-path: inset(26% 0 30% 0);
         transform: perspective(1200px) rotateX(-10deg)
                    translate3d(calc(var(--nav-dir) * 6vw), 0, 0) scale(1.012);
         filter: brightness(1.9) saturate(1.8) blur(0); }
  22%  { clip-path: inset(3% 0 48% 0);
         transform: perspective(1200px) rotateX(6deg)
                    translate3d(calc(var(--nav-dir) * -3vw), -3px, 0);
         filter: brightness(1.5) saturate(1.5) hue-rotate(16deg); }
  32%  { clip-path: inset(0 0 0 0);
         transform: perspective(1200px) translate3d(calc(var(--nav-dir) * 1.4vw), 2px, 0);
         filter: brightness(1.3) saturate(1.25) hue-rotate(-12deg); }
  48%  { transform: translate3d(calc(var(--nav-dir) * -.5vw), 0, 0); filter: brightness(1.1); }
  66%  { transform: translate3d(calc(var(--nav-dir) * .2vw), 0, 0); }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0); filter: none; }
}

/* Children arrive in sequence rather than as one slab. */
.route.rt-enter [data-stagger] > * {
  animation: child-in .42s var(--ease-out) both;
  animation-delay: calc(110ms + var(--i, 0) * 36ms);
}
@keyframes child-in {
  from { opacity: 0; filter: brightness(1.7);
         transform: translate3d(calc(var(--nav-dir) * 3vw), 15px, 0) scale(.98); }
  to   { opacity: 1; filter: none; transform: none; }
}

/* ── Shutter: the channel change ─────────────────────────────────────────── */
.shutter { position: fixed; inset: 0; z-index: 92; pointer-events: none; opacity: 0; contain: strict; }
.shutter.run { opacity: 1; }
.sh-bar {
  position: absolute; top: -5vh; bottom: -5vh; width: 40vw; left: -46vw;
  background: linear-gradient(90deg, transparent 0%,
    color-mix(in srgb, var(--hp-violet) 26%, transparent) 32%,
    color-mix(in srgb, var(--hp-pink) 48%, transparent) 70%,
    var(--hp-gold) 92%, #fff 97%, rgba(255,255,255,0) 100%);
  box-shadow: 0 0 90px 10px color-mix(in srgb, var(--hp-pink) 35%, transparent);
  transform: translateX(0) skewX(-9deg);
  mix-blend-mode: screen;
}
.shutter.run .sh-bar { animation: shutter-run .5s var(--ease-gta) both; }
@keyframes shutter-run {
  from { transform: translateX(0) skewX(-9deg); }
  to   { transform: translateX(210vw) skewX(-9deg); }
}
:root[data-nav-dir="back"] .sh-bar { left: auto; right: -46vw; transform: translateX(0) skewX(9deg); }
:root[data-nav-dir="back"] .shutter.run .sh-bar { animation-name: shutter-run-back; }
@keyframes shutter-run-back {
  from { transform: translateX(0) skewX(9deg); }
  to   { transform: translateX(-210vw) skewX(9deg); }
}
/* Head-switching noise at the bottom of the frame — a tape machine artifact,
   which is the right vocabulary for an image tool that talks about frames. */
.sh-tear {
  position: absolute; left: 0; right: 0; bottom: 0; height: 30px;
  opacity: 0; mix-blend-mode: screen;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,.55) 0 2px, transparent 2px 6px),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--hp-gold) 60%, transparent) 0 1px, transparent 1px 9px);
}
.shutter.run .sh-tear { animation: head-switch .34s steps(1, end) both; }
@keyframes head-switch {
  0%   { opacity: .85; height: 30px; transform: translateX(0); }
  20%  { opacity: .6;  height: 14px; transform: translateX(-9px); }
  40%  { opacity: .9;  height: 42px; transform: translateX(7px); }
  60%  { opacity: .45; height: 20px; transform: translateX(-4px); }
  80%  { opacity: .7;  height: 9px;  transform: translateX(3px); }
  100% { opacity: 0;   height: 0; }
}

/* ── One circuit ────────────────────────────────────────────────────────────
   Every neon element used to run its own private loop. The sweep angle
   published by canvas-bg.js drives a single band across the whole interface,
   so the sign bank reads as one power feed. Screen blend, brightening only.  */
.circuit {
  position: fixed; inset: -30%; z-index: 78; pointer-events: none;
  mix-blend-mode: screen;
  background: conic-gradient(from var(--sweep-deg) at 50% 50%,
    color-mix(in srgb, var(--hp-pink) 8%, transparent) 0deg,
    color-mix(in srgb, var(--hp-gold) 4%, transparent) 7deg,
    color-mix(in srgb, var(--hp-lav) 3%, transparent) 14deg,
    transparent 27deg, transparent 353deg,
    color-mix(in srgb, var(--hp-pink) 3%, transparent) 360deg);
}
:root[data-busy="true"] .circuit {
  background: conic-gradient(from var(--sweep-deg) at 50% 50%,
    color-mix(in srgb, var(--hp-gold) 14%, transparent) 0deg,
    color-mix(in srgb, var(--hp-pink) 7%, transparent) 9deg,
    color-mix(in srgb, var(--hp-coral) 4%, transparent) 18deg,
    transparent 32deg, transparent 360deg);
}

/* ── Card flier (FLIP from a thumbnail into the canvas) ──────────────────── */
.tube-flier {
  position: fixed; z-index: 91; pointer-events: none;
  border-radius: var(--tube-r);
  box-shadow:
    inset 0 0 0 var(--tube-w) color-mix(in srgb, var(--cc) 85%, transparent),
    inset 0 0 0 calc(var(--tube-w) + 1px) rgba(255,255,255,.35),
    0 0 34px color-mix(in srgb, var(--cc) 70%, transparent),
    0 0 90px color-mix(in srgb, var(--cc) 40%, transparent);
  will-change: transform, opacity;
}

/* ═══════════════════════════════════════════════════════════════════════════
   LOWER-POWER PATH
   Animated drop-shadow is paint-bound. On phones the multi-layer bloom
   collapses to one static shadow and only transform-driven motion — the gas
   swirl — survives, which is the part that composites for free.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 760px) {
  :root { --tube-w: 5px; }
  .tube {
    animation: none !important;
    filter: drop-shadow(0 0 5px color-mix(in srgb, var(--cc) 68%, transparent))
            drop-shadow(0 0 15px color-mix(in srgb, var(--cc) 32%, transparent)) !important;
  }
  .gas::before { filter: blur(3px); }
  .haze { animation: none; }
  .circuit { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   REDUCED MOTION
   The tube stays — it is state, not decoration. The gas stops moving.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  .route.rt-exit { display: none !important; }
  .shutter, .circuit { display: none !important; }
  .tube { filter: drop-shadow(0 0 4px color-mix(in srgb, var(--cc) 70%, transparent)) !important; }
  .gas::before { transform: none; opacity: .5; }
}
:root[data-motion="reduced"] *, :root[data-motion="reduced"] *::before, :root[data-motion="reduced"] *::after {
  animation-duration: .001ms !important; animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
}
:root[data-motion="reduced"] .shutter,
:root[data-motion="reduced"] .circuit { display: none !important; }
:root[data-motion="reduced"] .route.rt-exit { display: none !important; }
:root[data-motion="reduced"] .tube {
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--cc) 70%, transparent)) !important;
}
