/* ---- number effects (ui/number-effects.mjs, ui/led.mjs, ui/number-interaction.mjs, ui/number-probe.mjs) ----
   .ladder-wrap[data-num-fx] says which effect the live speed numbers carry: jet (also when missing:
   the orbit engine in styles.css, untouched here), ping, gear or off. Loaded after styles.css; every
   override below wins by selector specificity (it repeats the running selector and adds the mode),
   never by !important. Numbers, units, ranks and the static meter and tier colours are never hidden.

   ping: one .nfx-ping per live speed cell (led.mjs), under the number (z-index 0 < 1), pointer-events
   none. Its box is the ring at full size, centred on the number: 2R wide, 2R·E high (E = .45, flat
   so it stays near its own row), R = 70–300 px (phones 44–140 px) by the plume's reach (--led-reach).
   At φ = 0 of the row's jet cycle (--jet-p, --jet-delay, pinned by led.mjs on nfx-ping-ring) the front
   leaves the number at k0·R (--nfx-k0: the number's half width over R, bounded .15–.6) and opens to
   R by φ = .55 on cubic-bezier(1/3, 2/3, 2/3, 1), which is exactly 2u − u² (u = φ / .55), the wave
   front ui/number-interaction.mjs pushes the background with; then it rests unseen until the next
   cycle. The front is a radar energy shell, not an outline: a bright edge with an energy wake over the
   last 18 % of the radius inside it (the field's wake), cut into 48 range dashes and weighted by two
   horizontal lobes (alpha .3 straight up and down, 1 from 50° to 130° either side: the field's lobe).
   Tiers: t1–t2 green, t3–t4 cyan, t4+ a trailing range ring (1 px, half alpha, .08 P later, dashes
   only), t5–t6 ice with a gold range ring, t6+ an emission flash, t7 white with a gold range ring;
   phones keep one front and the flash. Transform and opacity only; parked off screen (data-led-idle),
   stopped in a hidden tab (data-led-paused), faded on the replay hold, gone with motion off or reduced
   motion.

   probe (ping only): the pointer is the ping's radar target (ui/number-probe.mjs, one loop that runs
   only while a pointer is active or an echo is alive). .nfx-probe lies in the ladder table at z-index
   0, so it is under every number and unit (z-index 1); its lens is the front bent round the pointer
   (an arc centred on it, radius = its distance to the front), its echoes the rings a front sends back
   from the pointer. The loop writes their transform and opacity only.

   gear: one .nfx-gear per live speed cell (led.mjs), under the number, pointer-events none: a 12-tooth
   pixel sprocket (green teeth, dark green rim), a crank arm and its pedal (cyan up to t4, gold from
   t5). 40 px across, its centre 24 px left of the number's left edge on the number's middle (phones
   18 px across, under the number's first digits on the unit line, clear of the 六维 button). The box
   stays put (ui/number-interaction.mjs measures it: Rg is its half width); only its rotor turns,
   clockwise, linear, at 0.3 + 1.2·reach turns per second in steps of .05 (--nfx-gear-p), on the
   document clock (--nfx-gear-t, pinned by led.mjs on nfx-gear-turn like --led-t / --jet-t, less the
   row's stagger --nfx-gear-off). 踏风火轮: --nfx-fire (0–1, led.mjs ledGearFire from the real speed)
   lights a flame ring on the rotor out to Rg·(1 + .45·fire) and a wind-fire tail left of the wheel,
   from Rg/2 left of its centre to Rg·(1.3 + 1.9·fire) (phones Rg·(1.2 + 1·fire)), tapering to .35 of
   its 1.5·Rg height: the field's swirl and tail boxes. No random flicker: the flames pulse at a third
   and the wind streaks run at half of the real turn period. Same gates as the ping.

   transport (交通工具): one vehicle per live speed cell, walking to a rocket and spacecraft by the number as
   shown (a seated figure at 0.0, nothing when unknown), facing left, its trail to the right; see its section below.

   off: no rings, sky, plume, ping, gear or vehicle, no number lift, and the meter's tip and chase stand still. */

/* Copies of a row (the tracking dock) never show a ping. */
.nfx-ping { display: none; }
#ladder-rows .nfx-ping { position: absolute; z-index: 0; pointer-events: none;
  --nfx-r: calc(70px + 230px * var(--led-reach, 0)); --nfx-cx: calc(61px + var(--led-chars, 4) * 7.2px); --nfx-dy: 0px;
  --nfx-k0: var(--nfx-k0d, .3);
  width: calc(2 * var(--nfx-r)); height: calc(2 * var(--nfx-r) * .45);
  right: calc(var(--nfx-cx) - var(--nfx-r)); top: calc(50% + var(--nfx-dy) - var(--nfx-r) * .45);
  --nfx-ring: #39ff88; --nfx-glow: rgba(57, 255, 136, .32); --nfx-wake: rgba(57, 255, 136, .13); --nfx-echo: #39ff88;
  /* The lobes (the field's lobe weight) and the range dashes, intersected. */
  --nfx-lobes: conic-gradient(rgba(0, 0, 0, .3), #000 50deg 130deg, rgba(0, 0, 0, .3) 180deg, #000 230deg 310deg, rgba(0, 0, 0, .3));
  --nfx-dash: repeating-conic-gradient(#000 0 6deg, transparent 6deg 7.5deg);
  transition: opacity .6s, visibility 0s; }
.ladder-wrap[data-num-fx="ping"] #ladder-rows .nfx-ping { display: block; }
/* The front's outer edge is the box's edge, so the drawn front is the physics radius; the wake fills
   the last 18 % of the radius inside it. */
#ladder-rows .nfx-ping > i { position: absolute; inset: 0; border-radius: 50%; opacity: 0; transform: scale(var(--nfx-k0));
  border: 1.5px solid var(--nfx-ring); box-shadow: inset 0 0 6px var(--nfx-glow);
  background: radial-gradient(closest-side, transparent 82%, var(--nfx-wake) 99%);
  -webkit-mask: var(--nfx-lobes), var(--nfx-dash); -webkit-mask-composite: source-in;
  mask: var(--nfx-lobes), var(--nfx-dash); mask-composite: intersect; }
#ladder-rows .nfx-ping > i + i { border-width: 1px; border-color: var(--nfx-echo); box-shadow: none; background: none; }
/* The emission flash: a soft burst around the number as the front leaves it. */
#ladder-rows .nfx-ping::before { content: ""; position: absolute; border-radius: 50%; opacity: 0;
  left: calc(50% - var(--nfx-r) * var(--nfx-k0) * 1.5); top: calc(50% - var(--nfx-r) * var(--nfx-k0) * .675);
  width: calc(var(--nfx-r) * var(--nfx-k0) * 3); height: calc(var(--nfx-r) * var(--nfx-k0) * 1.35);
  background: radial-gradient(closest-side, #f2fff7, rgba(165, 243, 252, .55) 45%, transparent); }

/* Tiers (the LED tier, led.mjs). Lower tiers hide what they do not draw (visibility: the cycle keeps
   running, so one --jet-t stays right for every part). The probe's lens and echoes take the colours of
   the row whose front they bend or echo. */
#ladder-rows .nfx-ping:is(.t3, .t4), .nfx-probe > :is(.t3, .t4) { --nfx-ring: #3ff2ff; --nfx-glow: rgba(63, 242, 255, .32); --nfx-wake: rgba(63, 242, 255, .13); --nfx-echo: #3ff2ff; }
#ladder-rows .nfx-ping:is(.t5, .t6), .nfx-probe > :is(.t5, .t6) { --nfx-ring: #a5f3fc; --nfx-glow: rgba(165, 243, 252, .36); --nfx-wake: rgba(165, 243, 252, .13); --nfx-echo: #facc15; }
#ladder-rows .nfx-ping.t7, .nfx-probe > .t7 { --nfx-ring: #f2fff7; --nfx-glow: rgba(242, 255, 247, .4); --nfx-wake: rgba(165, 243, 252, .14); --nfx-echo: #facc15; }
#ladder-rows .nfx-ping:is(.t1, .t2, .t3) > i + i { visibility: hidden; }
#ladder-rows .nfx-ping:not(.t6, .t7)::before { visibility: hidden; }

/* Running: ping chosen, effects on, live, tab visible, the cell on (or near) the screen. */
.ladder-wrap[data-num-fx="ping"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-ping > i:first-child {
  animation: nfx-ping-ring var(--jet-p, 2.4s) linear infinite var(--jet-delay); }
.ladder-wrap[data-num-fx="ping"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-ping > i + i {
  animation: nfx-ping-echo var(--jet-p, 2.4s) linear infinite calc(var(--jet-delay) + .08 * var(--jet-p, 2.4s)); }
.ladder-wrap[data-num-fx="ping"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-ping::before {
  animation: nfx-ping-flash var(--jet-p, 2.4s) linear infinite var(--jet-delay); }

/* Parked rings keep their layout (only hidden), so ui/number-interaction.mjs can still measure them. */
.c-value[data-led-idle] .nfx-ping { visibility: hidden; }
.ladder-wrap[data-rain-hold] #ladder-rows .nfx-ping { opacity: 0; visibility: hidden; transition: opacity .6s, visibility 0s .6s; }
.ladder-wrap[data-fx-off] #ladder-rows .nfx-ping { display: none; }

/* The probe: one layer in the ladder table (ui/number-probe.mjs), under the numbers. Its parts sit at
   the layer's origin and are moved, turned and scaled by the loop (transform, opacity). */
.nfx-probe { position: absolute; left: 0; top: 0; width: 0; height: 0; z-index: 0; pointer-events: none;
  --nfx-ring: #39ff88; --nfx-glow: rgba(57, 255, 136, .32); }
.nfx-probe > i { position: absolute; left: 0; top: 0; border-radius: 50%; opacity: 0; transform-origin: 50% 50%; will-change: transform, opacity; }
.nfx-probe > i.nfx-lens { width: 80px; height: 80px; margin: -40px 0 0 -40px; border: 2px solid var(--nfx-ring);
  box-shadow: inset 0 0 6px var(--nfx-glow);
  -webkit-mask: conic-gradient(from -60deg, transparent, #000 25deg 95deg, transparent 120deg);
  mask: conic-gradient(from -60deg, transparent, #000 25deg 95deg, transparent 120deg); }
.nfx-probe > i.nfx-echo { width: 128px; height: 128px; margin: -64px 0 0 -64px; border: 1.5px solid var(--nfx-ring);
  box-shadow: 0 0 6px var(--nfx-glow), inset 0 0 8px var(--nfx-glow);
  background: radial-gradient(closest-side, transparent 70%, var(--nfx-glow)); }
.ladder-wrap:not([data-num-fx="ping"]) .nfx-probe, .ladder-wrap:is([data-fx-off], [data-rain-hold], [data-led-paused]) .nfx-probe { display: none; }

/* The sprocket: the box is fixed (and measured); the rotor i turns with rim, hub and crank on it,
   the teeth on its ::before, the pedal at the crank's end on its ::after and the flame ring (its b).
   The box's own b is the wind-fire tail, which does not turn. */
.nfx-gear { display: none; }
#ladder-rows .nfx-gear { position: absolute; z-index: 0; pointer-events: none;
  --nfx-gd: 40px; --nfx-pd: 4px; --nfx-gx: calc(61px + var(--led-chars, 4) * 14.4px + 24px); --nfx-dy: 0px;
  width: var(--nfx-gd); height: var(--nfx-gd);
  right: calc(var(--nfx-gx) - var(--nfx-gd) / 2); top: calc(50% + var(--nfx-dy) - var(--nfx-gd) / 2);
  --nfx-pedal: #3ff2ff; --nfx-tail-a: .3; --nfx-tail-b: 1.9; --nfx-flame: #facc15; --nfx-ember: rgba(249, 115, 22, .8);
  transition: opacity .6s, visibility 0s; }
.ladder-wrap[data-num-fx="gear"] #ladder-rows .nfx-gear { display: block; }
#ladder-rows .nfx-gear:is(.t5, .t6, .t7) { --nfx-pedal: #facc15; }
#ladder-rows .nfx-gear.t7 { --nfx-flame: #fff3c4; --nfx-ember: rgba(251, 113, 133, .8); }
#ladder-rows .nfx-gear > i { position: absolute; inset: 0; border-radius: 50%; transform: rotate(0turn);
  background: linear-gradient(#eafff3 0 0) 50% calc(var(--nfx-gd) * .18) / 2px calc(var(--nfx-gd) * .32) no-repeat,
    radial-gradient(closest-side, #eafff3 0 12%, transparent 12% 56%, #1f6b45 56% 74%, transparent 74%); }
#ladder-rows .nfx-gear > i::before { content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: repeating-conic-gradient(#39ff88 0 13deg, transparent 13deg 30deg);
  -webkit-mask: radial-gradient(closest-side, transparent 72%, #000 72%); mask: radial-gradient(closest-side, transparent 72%, #000 72%); }
#ladder-rows .nfx-gear > i::after { content: ""; position: absolute; width: var(--nfx-pd); height: var(--nfx-pd);
  left: calc(50% - var(--nfx-pd) / 2); top: calc(var(--nfx-gd) * .18 - var(--nfx-pd) / 2);
  background: var(--nfx-pedal); box-shadow: 0 0 4px var(--nfx-pedal); }
/* The flame ring: twelve tongues between the teeth, from the rim (.96 Rg, clear of the teeth) out to
   Rg·(1 + .45·fire), as bright as the fire; none at fire 0. */
#ladder-rows .nfx-gear > i > b { position: absolute; inset: calc(var(--nfx-gd) * -.225 * var(--nfx-fire, 0)); border-radius: 50%;
  opacity: calc(var(--nfx-fire, 0) * 1.5);
  background: repeating-conic-gradient(from 15deg, var(--nfx-flame) 0 5deg, var(--nfx-ember) 11deg, transparent 20deg 30deg);
  -webkit-mask: radial-gradient(closest-side, transparent calc(96% / (1 + .45 * var(--nfx-fire, 0))), #000 calc(100% / (1 + .45 * var(--nfx-fire, 0))), transparent);
  mask: radial-gradient(closest-side, transparent calc(96% / (1 + .45 * var(--nfx-fire, 0))), #000 calc(100% / (1 + .45 * var(--nfx-fire, 0))), transparent); }
/* The wind-fire tail: right edge Rg/2 left of the centre, left end Rg·(1 + tail) left of it, 1.5 Rg
   high at the wheel and .35 of that at the tip; flame near the wheel, two wind streaks along it. */
#ladder-rows .nfx-gear > b { position: absolute; right: calc(var(--nfx-gd) * .75); top: calc(50% - var(--nfx-gd) * .375);
  width: calc(var(--nfx-gd) * .5 * (.5 + var(--nfx-tail-a) + (var(--nfx-tail-b) - var(--nfx-tail-a)) * var(--nfx-fire, 0)));
  height: calc(var(--nfx-gd) * .75); overflow: hidden; opacity: calc(var(--nfx-fire, 0) * 1.6);
  clip-path: polygon(0 32.5%, 100% 0, 100% 100%, 0 67.5%);
  background: linear-gradient(to left, var(--nfx-flame), var(--nfx-ember) 30%, rgba(249, 115, 22, .25) 65%, transparent); }
#ladder-rows .nfx-gear > b::before, #ladder-rows .nfx-gear > b::after { content: ""; position: absolute; left: 0; width: 200%; height: 1px;
  background: repeating-linear-gradient(90deg, transparent 0 7px, rgba(165, 243, 252, .85) 7px 15px, transparent 15px 22px); }
#ladder-rows .nfx-gear > b::before { top: 38%; }
#ladder-rows .nfx-gear > b::after { top: 60%; }
.ladder-wrap[data-num-fx="gear"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-gear > i {
  animation: nfx-gear-turn var(--nfx-gear-p, 2s) linear infinite calc(var(--nfx-gear-t, var(--led-t, 0ms)) - var(--nfx-gear-off, 0ms)); }
.ladder-wrap[data-num-fx="gear"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-gear > i > b {
  animation: nfx-gear-flame calc(var(--nfx-gear-p, 2s) / 3) ease-in-out infinite; }
.ladder-wrap[data-num-fx="gear"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-gear > b::before,
.ladder-wrap[data-num-fx="gear"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .nfx-gear > b::after {
  animation: nfx-gear-wind calc(var(--nfx-gear-p, 2s) / 2) linear infinite; }
.c-value[data-led-idle] .nfx-gear { visibility: hidden; }
.ladder-wrap[data-rain-hold] #ladder-rows .nfx-gear { opacity: 0; visibility: hidden; transition: opacity .6s, visibility 0s .6s; }
.ladder-wrap[data-fx-off] #ladder-rows .nfx-gear { display: none; }

/* 交通工具 (transport) v2: one .nfx-tr per live speed cell (led.mjs) whose number is known, under the number,
   pointer-events none, aria-hidden. The vehicle follows the number as shown (ui/transport.mjs: walking to a
   rocket and spacecraft on one internal speed table, no hysteresis); a shown 0.0 is the sleeper (data-v="rest":
   a person lying asleep, head left on a pillow, quiet z's; no lane, no trail, no ground, no push; reduced motion
   keeps it, still); an unknown number has none. The
   cell carries data-tr (it may have no LED: an idle row follows its own number), which gates everything.
   Every vehicle faces left; its lane (.nfx-tr-lane, the field's measured lane) leaves the tail emitter to the
   right, past the box's right edge by --tr-lane, and ends 8px left of the number (phones: on the unit line,
   33px from the cell's right, clear of `tok/s`, vehicle + lane within 32px, ≤ 14px high). The trail inside it
   is U·--tr-trail long (phones × .6), clipped to the lane like the push (ui/number-interaction.mjs), U·--tr-half
   thick tapering to --tr-tip; its opacity pulses as the field does (nfx-tr-pulse: the stops of transport.mjs
   TRANSPORT.pulse, depth --tr-depth, --tr-beats per P). Solid bodies: paint, a darker shade, metal, tinted
   glass with glints, a cool rim light (--tr-a) brightening with --tr-boost, warm lamps and exhausts (--tr-b),
   tyres whose treads turn (counter-clockwise: rolling left), flames, shock diamonds and sparks that come in
   with --tr-max. Stages are continuous (--tr-boost, --tr-max, --tr-u are registered and ease over .8s; the
   discrete data-stage is a label). All parts run on the row's main cycle P = --tr-p from --tr-delay
   (= --tr-t − --tr-off, --tr-t pinned by led.mjs on nfx-tr-bob), transform and opacity only, no animated
   filter. Same gates as the gear.
   v3 shared layer: the box is 2U high, U = 18px on desktops from 1180px, 14px from 1024px; from 721px to 1023px
   (tablets, touch landscape, narrow windows) the compact box of the phones sits on the meter line inside the speed
   cell, left of the meter, so it never reaches the name or its meta line; phones as before (transport.mjs
   TRANSPORT.size). The desktop lane is 3.6U past the box. The
   wake is three layers inside the trail (clipped to it, so exactly where the field pushes): its body (light A,
   pulsing with the push), the speed lines (two rows, brighter with --tr-boost, one long centre streak with
   --tr-max) and the hot core (exhaust, --tr-max). Palettes and each vehicle's own CSS are generated from the
   artists' designs between the transport:palettes and transport:artist-css markers (cc-runs/v3-integrate.mjs). */
@property --tr-boost { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --tr-max { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --tr-u { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --tr-lean { syntax: '<angle>'; inherits: true; initial-value: 0deg; }
.nfx-tr { display: none; }
#ladder-rows .nfx-tr { position: absolute; z-index: 0; pointer-events: none;
  --tr-U: 18px; --tr-trail-k: 1; --tr-lane: calc(var(--tr-U) * 3.6); --tr-flick-n: 1; --tr-hot-k: 0;
  --tr-paint: #2563eb; --tr-paint2: #0f172a; --tr-shade: #1e3a8a; --tr-metal: #dbe4ee; --tr-glass: rgba(56, 189, 248, .5);
  --tr-a: #67e8f9; --tr-b: #fb7185; --tr-lamp: #fff4c2; --tr-core: #fff7ed; --tr-stripe: var(--tr-a);
  --tr-jersey: #22d3ee; --tr-skin: #f3c9a1; --tr-leg: #cbd5e1; --tr-helmet: #f8fafc; --tr-leathers: #1f2937; --tr-hair: #3b2a1e;
  --tr-tire: #0a0e14; --tr-tread: #64748b; --tr-tire-line: #cbd5e1;
  --tr-wake: color-mix(in srgb, var(--tr-a) 30%, transparent); --tr-streak: color-mix(in srgb, var(--tr-a) 70%, white);
  --tr-wake-hi: color-mix(in srgb, var(--tr-a) 62%, transparent);
  --tr-glow: color-mix(in srgb, var(--tr-a) 55%, transparent);
  --tr-delay: calc(var(--tr-t, 0ms) - var(--tr-off, 0ms));
  width: calc(2 * var(--tr-U) * var(--tr-aspect, 2)); height: calc(2 * var(--tr-U));
  right: calc(61px + var(--led-chars, 4) * 14.4px + 8px + var(--tr-lane)); top: calc(50% - var(--tr-U));
  transition: opacity .6s, visibility 0s, --tr-boost .8s ease, --tr-max .8s ease, --tr-u .8s ease, --tr-lean .8s ease; }
#ladder-rows .nfx-tr[data-v="rest"] { --tr-lane: 0px; right: calc(61px + var(--led-chars, 4) * 14.4px + 10px); }
#ladder-rows .nfx-tr[data-v="rest"]::before { content: none; }
.ladder-wrap[data-num-fx="transport"] #ladder-rows .nfx-tr { display: block; }
/* The sleeper (rest) is drawn centrally, not by a vehicle's artist. */
#ladder-rows .nfx-tr[data-v="rest"] { --tr-jersey: #2dd4bf; --tr-leg: #64748b; --tr-metal: #94a3b8; --tr-a: #99f6e4; --tr-b: #f59e0b; }
#ladder-rows .nfx-tr .r-pillow { fill: #e2e8f0; }
#ladder-rows .nfx-tr .r-zzz { stroke: var(--tr-a); stroke-width: 1.1px; opacity: .85; }
/* transport:palettes:begin — generated from each artist's DESIGN.json palette (cc-runs/v3-integrate.mjs). Per vehicle:
   paint, its shade, metal, glass, light A (cool: rim, beam, wake) and light B (warm: tail, exhaust) on the box, and the
   number's coupling tint (--trn-a, light A) on the cell that rides it (数字联动). */
#ladder-rows .nfx-tr[data-v="walk"] { --tr-jersey: #f7eedc; --tr-paint: #eadcc0; --tr-paint2: #d9c6a3; --tr-shade: #c4a77e; --tr-metal: #f1e6cf; --tr-glass: rgba(255, 225, 161, .5); --tr-a: #ffe1a1; --tr-b: #f59e0b; --tr-lamp: #fff4c2; --tr-core: #fff7e6; --tr-stripe: #fbbf24; --tr-skin: #e7b189; --tr-hair: #3b271a; --tr-wake: rgba(251, 191, 36, .16); --tr-streak: rgba(255, 222, 160, .85); }
#ladder-rows .nfx-tr[data-v="bicycle"] { --tr-paint: #3fe3b2; --tr-paint2: #13977a; --tr-shade: #0c6652; --tr-metal: #dbe7e3; --tr-glass: rgba(8, 15, 26, .92); --tr-a: #95f9d7; --tr-b: #ff5b6e; --tr-lamp: #fff3cc; --tr-core: #effff8; --tr-stripe: #ffcf47; --tr-jersey: #253f6e; --tr-leg: #2c4878; --tr-helmet: #ffc53d; --tr-skin: #efbf98; --tr-tread: #d6b98b; --tr-tire: #0b1015; --tr-wake: color-mix(in srgb, #95f9d7 22%, transparent); --tr-streak: rgba(214, 255, 241, .92); --tr-glow: color-mix(in srgb, #95f9d7 40%, transparent); --tr-leathers: #1a3160; }
#ladder-rows .nfx-tr[data-v="ebike"] { --tr-paint: #1ea7e1; --tr-paint2: #137fb4; --tr-shade: #0b4c70; --tr-metal: #cfdbe6; --tr-glass: rgba(125, 233, 255, .75); --tr-a: #7ee9ff; --tr-b: #ff4d6d; --tr-lamp: #f2fbff; --tr-core: #e8fdff; --tr-stripe: #3cc8f7; --tr-jersey: #e6edf4; --tr-skin: #f1c7a0; --tr-leg: #4f6b8c; --tr-helmet: #1ea7e1; --tr-hair: #3b2a1e; --tr-tire: #0a0e14; --tr-tread: #8597ab; --tr-tire-line: #d6e2ec; --tr-wake: color-mix(in srgb, var(--tr-a) 16%, transparent); --tr-streak: color-mix(in srgb, var(--tr-a) 78%, white); --tr-glow: color-mix(in srgb, var(--tr-a) 42%, transparent); }
#ladder-rows .nfx-tr[data-v="motorcycle"] { --tr-paint: #1c2029; --tr-paint2: #e0b04a; --tr-shade: #08090c; --tr-metal: #f2cf72; --tr-glass: rgba(150, 108, 34, .55); --tr-a: #fcd770; --tr-b: #ff6a2b; --tr-lamp: #fff7de; --tr-core: #fff3c4; --tr-stripe: #e9b949; --tr-helmet: #f2c14e; --tr-leathers: #3e4759; --tr-leg: #3e4759; --tr-tire: #06080b; --tr-tread: #3a404c; --tr-wake: rgba(252, 215, 112, .28); --tr-streak: rgba(255, 236, 176, .85); --tr-hot-k: .8; --tr-flick-n: 2; --tr-gloss: #4d5666; --tr-engine: #272c36; --tr-arm: #242a35; --tr-steel: #aab2c0; --tr-heat-tint: #8b7cf6; --tr-brake: #ff3d48; --tr-suit-hi: #ebe4d0; --tr-rim-gold: #ffd166; }
#ladder-rows .nfx-tr[data-v="car"] { --tr-paint: #ff6b57; --tr-paint2: #fff1df; --tr-paint-hi: #ffa08a; --tr-shade: #c2392f; --tr-metal: #eef2f6; --tr-glass: rgba(14, 26, 40, .92); --tr-a: #6ff7d6; --tr-b: #ffb04a; --tr-lamp: #fff7dc; --tr-core: #fff4dc; --tr-stripe: #fff1df; --tr-tail-red: #ff2f4a; --tr-tire: #0b0f15; --tr-tread: #8b9bb0; --tr-wake: rgba(255, 150, 105, .26); --tr-streak: rgba(222, 255, 245, .82); --tr-glow: color-mix(in srgb, #ff6b57 45%, transparent); --tr-hot-k: .35; }
#ladder-rows .nfx-tr[data-v="suv"] { --tr-paint: #d3a95c; --tr-paint2: #17191e; --tr-shade: #8f6a2f; --tr-paint-hi: #f0d394; --tr-metal: #d8c69c; --tr-glass: rgba(18, 38, 44, .92); --tr-a: #8ff0d8; --tr-b: #ff5a36; --tr-lamp: #fff2cf; --tr-core: #fff1d6; --tr-stripe: #2b2620; --tr-tire: #0b0c0f; --tr-tread: #4b5059; --tr-glow: rgba(255, 214, 140, .32); --tr-wake: rgba(214, 184, 122, .3); --tr-streak: rgba(242, 224, 182, .72); --tr-bar: #ffcf6e; --tr-dust: rgba(240, 220, 172, .8); --tr-hot-k: .12; --tr-flick-n: 1; }
#ladder-rows .nfx-tr[data-v="sedan"] { --tr-paint: #2457e6; --tr-paint2: #6d95ff; --tr-shade: #16338c; --tr-metal: #d9e4f4; --tr-glass: rgba(8, 16, 40, .94); --tr-a: #8fb6ff; --tr-b: #ff2d55; --tr-lamp: #eef7ff; --tr-core: #ffe4ea; --tr-stripe: #b4caff; --tr-tire: #06080d; --tr-tread: #6b7a93; --tr-hot-k: .1; --tr-wake: rgba(111, 155, 255, .26); --tr-streak: rgba(150, 186, 255, .72); --tr-glow: rgba(111, 155, 255, .5); --tr-sd-caliper: #ff2d55; }
#ladder-rows .nfx-tr[data-v="sportsCar"] { --tr-paint: #5228a6; --tr-paint2: #a283f4; --tr-shade: #29104e; --tr-metal: #ead2a2; --tr-glass: rgba(14, 8, 28, .92); --tr-a: #dccbff; --tr-b: #f5bd6b; --tr-lamp: #f2f7ff; --tr-core: #fff6e2; --tr-stripe: #f0d6a0; --tr-tire: #07060b; --tr-tread: #6b6184; --tr-wake: rgba(150, 112, 255, .3); --tr-streak: rgba(252, 232, 196, .8); --tr-glow: rgba(180, 150, 255, .5); --tr-hot-k: .35; --tr-flick-n: 2; }
#ladder-rows .nfx-tr[data-v="rallyCar"] { --tr-paint: #f8fafc; --tr-paint2: #e11d2e; --tr-shade: #a3b0c2; --tr-metal: #e8edf3; --tr-glass: rgba(8, 13, 26, .92); --tr-a: #bae6fd; --tr-b: #ff5a2c; --tr-lamp: #fff3c4; --tr-core: #fff7e6; --tr-stripe: #0f172a; --tr-tire: #090c11; --tr-tread: #5b6472; --tr-wake: rgba(196, 160, 104, .36); --tr-streak: rgba(242, 226, 190, .95); --tr-hot-k: 0; --tr-rally-paint-shade: #9b1023; --tr-rally-lip: #7f0d1d; --tr-rally-carbon: #2b3443; --tr-rally-mud: #a07a4c; --tr-rally-dust: #c9a46c; --tr-rally-grit: #e9d6ae; }
#ladder-rows .nfx-tr[data-v="supercar"] { --tr-paint: #ff6a13; --tr-paint2: #ffa63d; --tr-shade: #bd3f0d; --tr-metal: #d6dde6; --tr-glass: rgba(8, 15, 30, .92); --tr-a: #5ce1ff; --tr-b: #ff2d55; --tr-lamp: #f2fbff; --tr-core: #fff4d6; --tr-stripe: #161c26; --tr-tire: #06080c; --tr-tread: #4b5563; --tr-wake: rgba(255, 128, 48, .26); --tr-streak: rgba(196, 244, 255, .9); }
#ladder-rows .nfx-tr[data-v="raceCar"] { --tr-paint: #18dcf5; --tr-paint2: #0c1524; --tr-shade: #0a3a4e; --tr-metal: #e6f7fb; --tr-glass: rgba(14, 116, 144, .6); --tr-a: #a5f3fc; --tr-b: #ff8a3d; --tr-lamp: #ffd8a8; --tr-core: #fff3d6; --tr-stripe: #ff7a2f; --tr-helmet: #ffd60a; --tr-tire: #07090d; --tr-tread: #94a3b8; --tr-compound: #ff3355; --tr-flank: #0c93ad; --tr-rain: #ff2d55; --tr-hot-k: .8; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] { --tr-paint: #e4ebf5; --tr-paint2: #1e40af; --tr-shade: #8796b3; --tr-metal: #c3cfe0; --tr-glass: #0a1430; --tr-a: #8cc8ff; --tr-b: #8f9cff; --tr-lamp: #eef5ff; --tr-core: #eef4ff; --tr-stripe: #2556e8; --tr-tire: #0a0e14; --tr-tread: #5b6b86; --tr-wake: rgba(80, 130, 255, .16); --tr-streak: rgba(222, 238, 255, .8); --tr-glow: rgba(140, 200, 255, .45); --tr-hot-k: .55; --tr-bt-band: rgba(56, 110, 255, .85); }
#ladder-rows .nfx-tr[data-v="maglev"] { --tr-paint: #e9eef4; --tr-paint2: #b7c2d1; --tr-shade: #63738b; --tr-metal: #ffffff; --tr-glass: #08111f; --tr-a: #4ee6f7; --tr-b: #f5c451; --tr-lamp: #eafcff; --tr-core: #fff6d8; --tr-stripe: #16c4e6; --tr-hot-k: .5; --tr-wake: color-mix(in srgb, #4ee6f7 22%, transparent); --tr-streak: color-mix(in srgb, #4ee6f7 40%, white); --tr-glow: color-mix(in srgb, #4ee6f7 45%, transparent); --tr-mg-skirt: #141d2b; --tr-mg-gold: #e9b949; }
#ladder-rows .nfx-tr[data-v="jetliner"] { --tr-paint: #eef2f6; --tr-paint2: #1e3a8a; --tr-shade: #7f8da3; --tr-metal: #e2e8f0; --tr-glass: #13254d; --tr-a: #bae6fd; --tr-b: #f43f5e; --tr-lamp: #f8fafc; --tr-core: #f0f9ff; --tr-stripe: #2563eb; --tr-wake: rgba(224, 242, 254, .5); --tr-streak: rgba(240, 249, 255, .92); --tr-glow: color-mix(in srgb, #bae6fd 55%, transparent); }
#ladder-rows .nfx-tr[data-v="fighterJet"] { --tr-paint: #6a7c93; --tr-paint2: #3d495b; --tr-shade: #2c3545; --tr-metal: #c3cfdc; --tr-glass: rgba(251, 191, 36, .8); --tr-canopy: #e8a51f; --tr-a: #7dd3fc; --tr-b: #fb923c; --tr-lamp: #fff4c2; --tr-core: #eef6ff; --tr-stripe: #fbbf24; --tr-wake: rgba(125, 180, 255, .26); --tr-streak: rgba(224, 242, 254, .9); --tr-hot-k: .95; --tr-flick-n: 2; }
#ladder-rows .nfx-tr[data-v="x15"] { --tr-paint: #181d27; --tr-paint2: #262d3a; --tr-shade: #07090d; --tr-metal: #a9b2bf; --tr-glass: #182134; --tr-a: #c4b5fd; --tr-b: #8b5cf6; --tr-lamp: #fde68a; --tr-core: #faf5ff; --tr-stripe: #fbbf24; --tr-wake: rgba(196, 181, 253, .32); --tr-streak: rgba(237, 233, 254, .9); --tr-glow: rgba(167, 139, 250, .55); --tr-hot-k: 1; --tr-flick-n: 1; }
#ladder-rows .nfx-tr[data-v="rocket"] { --tr-paint: #eef2f7; --tr-paint2: #dc2626; --tr-shade: rgba(51, 65, 85, .34); --tr-metal: #94a3b8; --tr-glass: #0c4a6e; --tr-a: #dbeafe; --tr-b: #f97316; --tr-lamp: #fde68a; --tr-core: #fffbeb; --tr-stripe: #dc2626; --tr-wake: rgba(251, 191, 36, .3); --tr-streak: rgba(241, 245, 249, .7); --tr-glow: rgba(251, 191, 36, .3); --tr-hot-k: 1; --tr-flick-n: 3; --tr-rk-far: #b8c3d1; --tr-rk-far-red: #a51d1d; --tr-rk-bell: #1e293b; --tr-rk-skirt: #475569; --tr-rk-gold: #fcd34d; --tr-rk-smoke: rgba(226, 232, 240, .62); }
#ladder-rows .c-value[data-tr="walk"] { --trn-a: #ffe1a1; }
#ladder-rows .c-value[data-tr="bicycle"] { --trn-a: #95f9d7; }
#ladder-rows .c-value[data-tr="ebike"] { --trn-a: #7ee9ff; }
#ladder-rows .c-value[data-tr="motorcycle"] { --trn-a: #fcd770; }
#ladder-rows .c-value[data-tr="car"] { --trn-a: #6ff7d6; }
#ladder-rows .c-value[data-tr="suv"] { --trn-a: #8ff0d8; }
#ladder-rows .c-value[data-tr="sedan"] { --trn-a: #8fb6ff; }
#ladder-rows .c-value[data-tr="sportsCar"] { --trn-a: #dccbff; }
#ladder-rows .c-value[data-tr="rallyCar"] { --trn-a: #bae6fd; }
#ladder-rows .c-value[data-tr="supercar"] { --trn-a: #5ce1ff; }
#ladder-rows .c-value[data-tr="raceCar"] { --trn-a: #a5f3fc; }
#ladder-rows .c-value[data-tr="bulletTrain"] { --trn-a: #8cc8ff; }
#ladder-rows .c-value[data-tr="maglev"] { --trn-a: #4ee6f7; }
#ladder-rows .c-value[data-tr="jetliner"] { --trn-a: #bae6fd; }
#ladder-rows .c-value[data-tr="fighterJet"] { --trn-a: #7dd3fc; }
#ladder-rows .c-value[data-tr="x15"] { --trn-a: #c4b5fd; }
#ladder-rows .c-value[data-tr="rocket"] { --trn-a: #dbeafe; }
/* transport:palettes:end */
#ladder-rows .nfx-tr i, #ladder-rows .nfx-tr b { position: absolute; display: block; }
#ladder-rows .nfx-tr-v, #ladder-rows .nfx-tr-p.still { inset: 0; }
#ladder-rows .nfx-tr-v { transform-origin: 50% 100%; rotate: var(--tr-lean, 0deg); }
#ladder-rows .nfx-tr-p > svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
#ladder-rows .nfx-tr-p.still > svg { filter: drop-shadow(0 0 1.5px var(--tr-glow)); }
#ladder-rows .nfx-tr path { fill: none; stroke: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
/* Layers (transport-art.mjs roles). */
#ladder-rows .nfx-tr .r-paint { fill: var(--tr-paint); }
#ladder-rows .nfx-tr .r-paint2 { fill: var(--tr-paint2); }
#ladder-rows .nfx-tr .r-shade { fill: var(--tr-shade); }
#ladder-rows .nfx-tr .r-dark { fill: #0b1220; }
#ladder-rows .nfx-tr .r-metal { fill: var(--tr-metal); }
#ladder-rows .nfx-tr .r-metalLine { stroke: var(--tr-metal); stroke-width: .8px; opacity: .85; }
#ladder-rows .nfx-tr .r-chrome { stroke: var(--tr-metal); stroke-width: 1.2px; }
#ladder-rows .nfx-tr .r-chromeThick { stroke: var(--tr-metal); stroke-width: 1.8px; }
#ladder-rows .nfx-tr .r-frame { stroke: var(--tr-paint); stroke-width: 2px; }
#ladder-rows .nfx-tr .r-fender { stroke: var(--tr-paint2); stroke-width: 1.4px; }
#ladder-rows .nfx-tr .r-chain { stroke: var(--tr-metal); stroke-width: 1px; }
#ladder-rows .nfx-tr .r-glass { fill: var(--tr-glass); stroke: color-mix(in srgb, var(--tr-a) 60%, transparent); stroke-width: .5px; }
#ladder-rows .nfx-tr .r-canopy { fill: var(--tr-canopy, var(--tr-glass)); }
#ladder-rows .nfx-tr .r-glint { stroke: #fff; stroke-width: .8px; opacity: .85; }
#ladder-rows .nfx-tr .r-pillar { stroke: var(--tr-paint); stroke-width: 1.4px; }
#ladder-rows .nfx-tr .r-seam { stroke: rgba(2, 6, 23, .5); stroke-width: .6px; }
#ladder-rows .nfx-tr .r-stripe { stroke: var(--tr-stripe); stroke-width: 1px; }
#ladder-rows .nfx-tr .r-stripeFill { fill: var(--tr-stripe); }
#ladder-rows .nfx-tr .r-edge { stroke: var(--tr-a); stroke-width: 1px; opacity: calc(.5 + .5 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr .r-lamp { fill: var(--tr-lamp); }
#ladder-rows .nfx-tr .r-tail { fill: var(--tr-b); }
#ladder-rows .nfx-tr .r-nav { fill: #4ade80; }
#ladder-rows .nfx-tr .r-tire { fill: var(--tr-tire); stroke: rgba(148, 163, 184, .5); stroke-width: .5px; }
#ladder-rows .nfx-tr .r-tread { stroke: var(--tr-tread); stroke-width: 1px; stroke-dasharray: .45 .55; stroke-linecap: butt; vector-effect: none;
  opacity: calc(.9 - .6 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr .r-rimw { fill: var(--tr-metal); }
#ladder-rows .nfx-tr .r-spoke { stroke: rgba(2, 6, 23, .8); stroke-width: .8px; opacity: calc(1 - .7 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr .r-hub { fill: #0b1220; }
#ladder-rows .nfx-tr .r-tireLine { stroke: var(--tr-tire-line); stroke-width: 1.6px; opacity: .9; }
#ladder-rows .nfx-tr .r-rimLine { stroke: var(--tr-paint); stroke-width: .7px; }
#ladder-rows .nfx-tr .r-spokeThin { stroke: var(--tr-metal); stroke-width: .4px; opacity: calc(.75 - .5 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr .r-crank { stroke: var(--tr-metal); stroke-width: 1.4px; }
#ladder-rows .nfx-tr .r-jersey { fill: var(--tr-jersey); }
#ladder-rows .nfx-tr .r-leathers { fill: var(--tr-leathers); }
#ladder-rows .nfx-tr .r-skin { fill: var(--tr-skin); }
#ladder-rows .nfx-tr .r-skinLine { stroke: var(--tr-skin); stroke-width: 1.4px; }
#ladder-rows .nfx-tr .r-legLine { stroke: var(--tr-leg); stroke-width: 2.2px; }
#ladder-rows .nfx-tr .r-armLine { stroke: var(--tr-leathers); stroke-width: 1.6px; }
#ladder-rows .nfx-tr .r-helmet { fill: var(--tr-helmet); }
#ladder-rows .nfx-tr .r-visor { fill: #0f172a; }
#ladder-rows .nfx-tr .r-hair { fill: var(--tr-hair); }
#ladder-rows .nfx-tr .r-shoe { fill: #e2e8f0; }
#ladder-rows .nfx-tr .r-limb { stroke: var(--tr-leg); stroke-width: var(--tr-limb-w, 2.2px); }
#ladder-rows .nfx-tr .r-battery, #ladder-rows .nfx-tr .r-levitate { stroke: var(--tr-a); stroke-width: 2px; }
#ladder-rows .nfx-tr .r-flame { fill: var(--tr-b); fill-opacity: .75; }
#ladder-rows .nfx-tr .r-flameCore { fill: var(--tr-core); }
#ladder-rows .nfx-tr .r-shock { fill: var(--tr-core); stroke: var(--tr-a); stroke-width: .8px; }
/* Limbs turn round their left middle (hip, knee, shoulder); at rest they hold their first keyframe. */
#ladder-rows .nfx-tr-p.limb { transform-origin: 0 50%; transform: rotate(calc(var(--n) + var(--a0) * var(--tr-stride, 1))); }
/* Wheels blur into a ring as the car speeds up (--tr-blur). */
#ladder-rows .nfx-tr-p.spin:not(.crank)::after { content: ""; position: absolute; inset: 8%; border-radius: 50%;
  border: 1.5px solid var(--tr-tread); opacity: calc(.45 * var(--tr-blur, 0)); }
/* Flames: an exhaust pop (motorcycle) only near max, a jet's or rocket's burner always, longer and brighter with u. */
#ladder-rows .nfx-tr-p.flame { --tr-flame-a: calc(.45 + .55 * var(--tr-max, 0)); opacity: var(--tr-flame-a); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.flame { --tr-flame-a: var(--tr-max, 0); }
#ladder-rows .nfx-tr-p.shock { opacity: var(--tr-max, 0); }
#ladder-rows .nfx-tr-p.glow { --tr-glow-a: 1; }
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-p.glow, #ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-p.glow { --tr-glow-a: calc(.45 + .55 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr-under { border-radius: 50%; opacity: calc(.3 + .7 * var(--tr-boost, 0));
  background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-b) 70%, transparent), transparent); }
#ladder-rows .nfx-tr-spark { width: 2px; height: 2px; margin: -1px 0 0 -1px; border-radius: 50%; background: var(--tr-core); box-shadow: 0 0 3px var(--tr-b); opacity: 0; }
#ladder-rows .nfx-tr-ring { width: calc(var(--tr-U) * .9); height: calc(var(--tr-U) * .9); margin: calc(var(--tr-U) * -.45) 0 0 calc(var(--tr-U) * -.45);
  border: 1px solid var(--tr-b); border-radius: 50%; opacity: 0; }
/* The headlamp's light cone, to the left (light only: it pushes nothing). Reaches further and brighter with --tr-boost. */
#ladder-rows .nfx-tr-beam { width: calc(var(--tr-U) * 2.6); height: calc(var(--tr-U) * .8); transform-origin: 100% 50%;
  transform: translate(-100%, -50%) scaleX(calc(.45 + .55 * var(--tr-boost, 0)));
  clip-path: polygon(0 0, 100% 40%, 100% 60%, 0 100%); opacity: calc(.3 + .45 * var(--tr-boost, 0));
  background: linear-gradient(to left, color-mix(in srgb, var(--tr-lamp) 70%, transparent), transparent); }
/* The lane: from the tail emitter (left/top) along --tr-dir, to the box's right edge plus --tr-lane; the field
   measures its length. The trail inside it is the field's trail box: bright at the emitter, gone at the tip. */
#ladder-rows .nfx-tr-lane { --tr-L: calc(var(--tr-U) * var(--tr-trail, 2) * var(--tr-trail-k));
  height: calc(2 * var(--tr-U) * var(--tr-half, .5)); margin-top: calc(-1 * var(--tr-U) * var(--tr-half, .5));
  width: calc((1 - var(--tr-ax, 1)) * 2 * var(--tr-U) * var(--tr-aspect, 2) + var(--tr-lane));
  transform-origin: 0 50%; transform: rotate(var(--tr-dir, 0deg)); overflow: hidden; }
#ladder-rows .nfx-tr-trail {
  left: 0; top: 0; bottom: 0; width: min(100%, var(--tr-L)); overflow: hidden;
  clip-path: polygon(0 0, 100% calc(50% - 50% * var(--tr-tip, .5)), 100% calc(50% + 50% * var(--tr-tip, .5)), 0 100%);
  background: linear-gradient(to right, var(--tr-wake-hi), var(--tr-wake) 38%, transparent);
  -webkit-mask: linear-gradient(transparent, #000 20% 80%, transparent); mask: linear-gradient(transparent, #000 20% 80%, transparent); }
/* Speed lines in the wake: they flow right one pattern per P/--tr-flow-n. Two rows (a quarter in from each edge)
   come up with --tr-boost; a long white centre streak comes in with --tr-max. One flowing layer, so all of it
   stays inside the trail. */
#ladder-rows .nfx-tr-trail::before { content: ""; position: absolute; top: 0; bottom: 0; right: 0; left: calc(-1 * var(--tr-flow) * var(--tr-U));
  --tr-dash: calc(var(--tr-flow) * var(--tr-U));
  opacity: calc(.3 + .7 * var(--tr-boost, 0));
  background:
    repeating-linear-gradient(90deg, color-mix(in srgb, #fff calc(100% * var(--tr-max, 0)), transparent) 0 calc(var(--tr-dash) * .8), transparent 0 var(--tr-dash)) 0 calc(50% - 1px) / 100% 2px no-repeat,
    repeating-linear-gradient(90deg, var(--tr-streak) 0 calc(var(--tr-dash) * .45), transparent 0 var(--tr-dash)) 0 26% / 100% max(1px, 9%) no-repeat,
    repeating-linear-gradient(90deg, var(--tr-streak) 0 calc(var(--tr-dash) * .45), transparent 0 var(--tr-dash)) calc(var(--tr-dash) * .5) 74% / 100% max(1px, 9%) no-repeat; }
#ladder-rows .nfx-tr[data-f="step"] .nfx-tr-trail::before { background: radial-gradient(closest-side, var(--tr-streak), transparent) 0 50% / var(--tr-dash) 70% repeat-x; }
#ladder-rows .nfx-tr[data-f="rail"] .nfx-tr-trail::before {
  background: repeating-linear-gradient(90deg, color-mix(in srgb, #fff calc(100% * var(--tr-max, 0)), transparent) 0 calc(var(--tr-dash) * .9), transparent 0 var(--tr-dash)) 0 calc(50% - 1px) / 100% 2px no-repeat,
    repeating-linear-gradient(90deg, var(--tr-streak) 0 calc(var(--tr-dash) * .8), transparent 0 var(--tr-dash)) 0 22% / 100% max(1px, 10%) no-repeat,
    repeating-linear-gradient(90deg, var(--tr-streak) 0 calc(var(--tr-dash) * .8), transparent 0 var(--tr-dash)) 0 78% / 100% max(1px, 10%) no-repeat; }
#ladder-rows .nfx-tr[data-f="rocket"] .nfx-tr-trail::before { background: radial-gradient(closest-side, var(--tr-streak), transparent) 0 50% / calc(var(--tr-dash) * .5) 80% repeat-x; }
/* The hot core: exhaust and afterburner heat, from the emitter, hotter with --tr-max; none for walkers and riders. */
#ladder-rows .nfx-tr-trail::after { content: ""; position: absolute; inset: 28% 0; opacity: calc((.2 + .8 * var(--tr-max, 0)) * var(--tr-hot-k));
  background: linear-gradient(to right, var(--tr-core), var(--tr-b) calc(16% + 18% * var(--tr-max, 0)), transparent calc(55% + 30% * var(--tr-max, 0))); }
/* The ground: lane dashes, a walker's path, rail and sleepers or the guideway, flowing right (the vehicle rolls left). */
#ladder-rows .nfx-tr[data-g]::after { content: ""; position: absolute; top: var(--tr-gy, 95%); right: -30%; left: calc(-1 * var(--tr-flow) * var(--tr-U));
  height: 1px; opacity: calc(.45 + .4 * var(--tr-boost, 0));
  background: repeating-linear-gradient(90deg, color-mix(in srgb, var(--tr-a) 70%, white) 0 calc(var(--tr-flow) * var(--tr-U) * .5), transparent 0 calc(var(--tr-flow) * var(--tr-U)));
  -webkit-mask: linear-gradient(to right, transparent, #000 25% 75%, transparent); mask: linear-gradient(to right, transparent, #000 25% 75%, transparent); }
#ladder-rows .nfx-tr[data-g="path"]::after { background: repeating-linear-gradient(90deg, rgba(214, 199, 161, .8) 0 1.5px, transparent 0 calc(var(--tr-flow) * var(--tr-U))); }
#ladder-rows .nfx-tr[data-g="rail"]::after { height: 3px; margin-top: -1px;
  background: linear-gradient(#94a3b8, #94a3b8) 0 0 / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, #64748b 0 1.5px, transparent 0 calc(var(--tr-flow) * var(--tr-U))); }
#ladder-rows .nfx-tr[data-g="guide"]::after { height: 4px; margin-top: 0; opacity: .7;
  background: linear-gradient(#475569, #475569) 0 0 / 100% 2px no-repeat,
    repeating-linear-gradient(90deg, var(--tr-a) 0 2px, transparent 0 calc(var(--tr-flow) * var(--tr-U))) 0 2px / 100% 2px no-repeat; }
/* The aura of a vehicle at its limit (--tr-max), which is also the upgrade flash on an arriving faster vehicle. */
#ladder-rows .nfx-tr::before { content: ""; position: absolute; inset: -18% 14%; border-radius: 50%; opacity: calc(.3 * var(--tr-max, 0));
  background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-a) 55%, transparent), color-mix(in srgb, var(--tr-b) 22%, transparent) 55%, transparent); }

/* Running: transport chosen, effects on, live, tab visible, the cell on (or near) the screen. */
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-v {
  animation: nfx-tr-bob calc(var(--tr-p, 1s) * var(--tr-bob-k, 1)) ease-in-out infinite var(--tr-delay); }
@media (prefers-reduced-motion: no-preference) {
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rest"] .nfx-tr-v {
    animation: nfx-tr-breathe 4.2s ease-in-out infinite; }
}
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-p.limb {
  animation: nfx-tr-limb var(--tr-p, 1s) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-p.spin {
  animation: nfx-tr-spin calc(var(--tr-p, 1s) * var(--k, 1)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-p.flame {
  animation: nfx-tr-flick calc(var(--tr-p, 1s) / var(--tr-flick-n)) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-p.glow {
  animation: nfx-tr-glow calc(var(--tr-p, 1s) / 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-spark {
  animation: nfx-tr-spark calc(var(--tr-p, 1s) / 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-spark.late {
  animation: nfx-tr-spark calc(var(--tr-p, 1s) / 2) linear infinite calc(var(--tr-delay) - var(--tr-p, 1s) / 4); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-ring {
  animation: nfx-tr-ring var(--tr-p, 1s) ease-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr:not([data-f="rail"]) .nfx-tr-trail {
  animation: nfx-tr-pulse calc(var(--tr-p, 1s) / var(--tr-beats, 1)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr-trail::before {
  animation: nfx-tr-flow calc(var(--tr-p, 1s) / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-g]::after {
  animation: nfx-tr-flow calc(var(--tr-p, 1s) / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); }
/* A change: the new vehicle arrives (faster: from behind, the right, with a flash; slower: settles back from
   ahead), the old one leaves under it, faint, forward (left) or back (right), and is removed by led.mjs after
   its fade: it never covers the current vehicle. */
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr.nfx-tr-in-up {
  animation: nfx-tr-in-up .5s cubic-bezier(.2, .9, .3, 1.15) both; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr.nfx-tr-in-up::before {
  animation: nfx-tr-flash .45s ease-out .1s both; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr.nfx-tr-in-down {
  animation: nfx-tr-in-down .5s ease-out both; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr.nfx-tr-out-up {
  animation: nfx-tr-out-up .34s ease-in forwards; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr.nfx-tr-out-down {
  animation: nfx-tr-out-down .5s ease-in-out forwards; }
#ladder-rows .nfx-tr.nfx-tr-out { opacity: .5; }
.c-value[data-led-idle] .nfx-tr { visibility: hidden; }
.ladder-wrap[data-rain-hold] #ladder-rows .nfx-tr { opacity: 0; visibility: hidden; transition: opacity .6s, visibility 0s .6s; }
.ladder-wrap[data-fx-off] #ladder-rows .nfx-tr { display: none; }
/* transport:artist-css:begin — each vehicle's own CSS from its DESIGN.json (scoped to .nfx-tr[data-v="key"], its own
   keyframes, running only under the transport gates on the row clock), generated by cc-runs/v3-integrate.mjs. */
/* walk (步行) */
/* 步行 / Walking v3: a race walker (竞走) in a warm-white kit with an amber sash, headband and shoes; each footfall
   plants an amber footprint that stays on the ground (it flows right at exactly the ground's speed) and is uncovered
   as the foot lifts. Parts by order in .nfx-tr-v (DESIGN.json art): 1 stomp ring, 2–4 far ghost (still, far leg, near
   leg), 5–7 near ghost, 8 far arm, 9 far leg, 10 far shoe, 11 ponytail, 12 body, 13 near leg, 14 near shoe,
   15 shorts, 16 near arm. Limbs are filled shapes (.r-limb gets a fill); each rig's colour is its --tr-leg.
   --wk-step: one step of ground in px, scaled with --tr-stride like the gait (no foot slip at any u). Assumes
   led.mjs writes --tr-flow / --tr-stride on .nfx-tr (where --wk-step resolves). */
#ladder-rows .nfx-tr[data-v="walk"] { --tr-jersey: #f7eedc; --tr-paint: #eadcc0; --tr-paint2: #d9c6a3; --tr-shade: #c4a77e;
  --tr-metal: #f1e6cf; --tr-glass: rgba(255, 225, 161, .5); --tr-stripe: #fbbf24; --tr-skin: #e7b189; --tr-hair: #3b271a;
  --tr-leg: var(--tr-skin); --tr-limb-w: .7px; --tr-a: #ffe1a1; --tr-b: #f59e0b; --tr-lamp: #fff4c2; --tr-core: #fff7e6; --tr-hot-k: 0;
  --tr-wake: rgba(251, 191, 36, .16); --tr-streak: rgba(255, 222, 160, .85);
  --wk-skin-far: #b37b58; --wk-shoe: #fbbf24; --wk-shoe-far: #d4880b; --wk-ghost: #ffdc94;
  --wk-step: calc(var(--tr-flow, 0.9577) * var(--tr-U) * var(--tr-stride, 1));
  --wk-s0: calc(var(--tr-U) * (-0.4198 + -0.4392 * var(--tr-stride, 1)));
  --wk-fl: calc(var(--tr-U) * 0.2234); }
/* Desktop: a person is tall and narrow, so the walker gets a slightly taller box (36px) than the 30px default. */
@media (min-width: 721px) { #ladder-rows .nfx-tr[data-v="walk"] { --tr-U: 18px; } }
/* Body bob follows the leg's pendulum: ∝ stride² (feet stay on the ground at every stride). */
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v { --tr-bob: calc(0.02 * var(--tr-stride, 1) * var(--tr-stride, 1)); }
#ladder-rows .nfx-tr[data-v="walk"] .r-limb { fill: var(--tr-leg); stroke: var(--tr-leg); }
#ladder-rows .nfx-tr[data-v="walk"] .r-ghost { fill: var(--wk-ghost); }
#ladder-rows .nfx-tr[data-v="walk"] .r-tail { fill: var(--tr-b); }
#ladder-rows .nfx-tr[data-v="walk"] .r-seam { stroke: #3b271a; stroke-width: .8px; }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :is(:nth-child(8), :nth-child(9)) { --tr-leg: var(--wk-skin-far); }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(10) { --tr-leg: var(--wk-shoe-far); }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(14) { --tr-leg: var(--wk-shoe); }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :is(:nth-child(10), :nth-child(14)) svg { filter: drop-shadow(0 0 1px rgba(251, 191, 36, .85)); }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(11) { --tr-leg: var(--tr-hair); }
/* Afterimages: where the walker was a quarter / half cycle ago, carried back by the ground (half a step / a step). */
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(n+2):nth-child(-n+7) { --tr-leg: var(--wk-ghost); }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(n+2):nth-child(-n+4) { opacity: calc(.15 * var(--tr-max, 0)); translate: var(--wk-step) 0; }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(n+5):nth-child(-n+7) { opacity: calc(.27 * var(--tr-boost, 0)); translate: calc(.5 * var(--wk-step)) 0; }
/* The stomp: a flat amber ring at the heel strike, once per step, carried back with the ground. */
#ladder-rows .nfx-tr[data-v="walk"] .r-stomp { fill: color-mix(in srgb, var(--tr-b) 22%, transparent); stroke: var(--tr-b); stroke-width: 1px; }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-p.glow { opacity: 0; translate: calc((1 - var(--tr-stride, 1)) * 0.382 * var(--tr-U)) 0; }
/* The wake lane runs back along the ground from the trailing foot: a warm haze (steady), the footprints (::before,
   planted, flowing with the ground) and the kicked dust (::after, pulsing exactly as the field's push). */
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-trail { background: linear-gradient(to right, transparent, rgba(251, 191, 36, .3) 8%, transparent 92%) 0 50% / 100% 2px no-repeat;
  -webkit-mask: linear-gradient(to right, #000 35%, transparent), linear-gradient(transparent, #000 20% 80%, transparent); -webkit-mask-composite: source-in;
  mask: linear-gradient(to right, #000 35%, transparent), linear-gradient(transparent, #000 20% 80%, transparent); mask-composite: intersect; }
#ladder-rows .nfx-tr[data-v="walk"][data-f="step"] .nfx-tr-trail::before { left: calc(-2 * var(--wk-step)); right: 0; opacity: calc(.62 + .38 * var(--tr-boost, 0));
  -webkit-mask: none; mask: none; background-repeat: repeat-x; background-size: calc(2 * var(--wk-step)) 100%;
  background-position: calc(var(--wk-s0) + 2 * var(--wk-step) - .2 * var(--wk-fl)) 0;
  background-image:
    radial-gradient(calc(.95 * var(--wk-fl)) calc(.2 * var(--tr-U)) at calc(.7 * var(--wk-fl)) calc(50% + .06 * var(--tr-U)), rgba(251, 191, 36, .3), transparent),
    radial-gradient(calc(.5 * var(--wk-fl)) max(1.2px, calc(.095 * var(--tr-U))) at calc(.48 * var(--wk-fl)) calc(50% + .06 * var(--tr-U)), #ffe7a3 25%, rgba(251, 191, 36, .7) 60%, transparent),
    radial-gradient(calc(.26 * var(--wk-fl)) max(1px, calc(.08 * var(--tr-U))) at calc(1.15 * var(--wk-fl)) calc(50% + .06 * var(--tr-U)), #ffe7a3 25%, rgba(251, 191, 36, .7) 60%, transparent),
    radial-gradient(calc(.95 * var(--wk-fl)) calc(.2 * var(--tr-U)) at calc(var(--wk-step) + 0.0234 * var(--tr-U) + .7 * var(--wk-fl)) calc(50% - .06 * var(--tr-U)), rgba(251, 191, 36, .3), transparent),
    radial-gradient(calc(.48 * var(--wk-fl)) max(1.1px, calc(.088 * var(--tr-U))) at calc(var(--wk-step) + 0.0234 * var(--tr-U) + .48 * var(--wk-fl)) calc(50% - .06 * var(--tr-U)), rgba(255, 226, 150, .9) 25%, rgba(245, 158, 11, .55) 60%, transparent),
    radial-gradient(calc(.25 * var(--wk-fl)) max(.9px, calc(.075 * var(--tr-U))) at calc(var(--wk-step) + 0.0234 * var(--tr-U) + 1.15 * var(--wk-fl)) calc(50% - .06 * var(--tr-U)), rgba(255, 226, 150, .9) 25%, rgba(245, 158, 11, .55) 60%, transparent); }
#ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-trail::after { inset: 0 auto 0 0; width: calc(var(--tr-U) * 1.6); opacity: 0; --wk-kick: calc(.5 + .5 * var(--tr-boost, 0));
  background: radial-gradient(circle at 18% 40%, #fff1cc 0 .9px, transparent 1.5px), radial-gradient(circle at 36% 26%, #ffd98a 0 .8px, transparent 1.4px),
    radial-gradient(circle at 52% 38%, #ffd98a 0 .7px, transparent 1.3px), radial-gradient(circle at 30% 50%, #fff1cc 0 .7px, transparent 1.3px),
    radial-gradient(circle at 66% 30%, #fbbf24 0 .6px, transparent 1.2px),
    radial-gradient(ellipse 46% 24% at 30% 44%, rgba(251, 191, 36, .32), transparent); }
/* The limit aura (also the arrival flash): a warm pool round the walker and the ground, not a tall column. */
#ladder-rows .nfx-tr[data-v="walk"]::before { inset: 6% -42% -14%; }
/* The ground: a warm track line with ticks, flowing right at the ground's (stride-scaled) speed. */
#ladder-rows .nfx-tr[data-v="walk"][data-g]::after { left: calc(-1 * var(--wk-step)); right: -8%; height: 1px; opacity: calc(.42 + .3 * var(--tr-boost, 0));
  background: repeating-linear-gradient(90deg, rgba(251, 191, 36, .85) 0 1px, rgba(251, 191, 36, .22) 1px calc(var(--wk-step) / 4)); }
/* Running (the base RUN gates; equal specificity, later in the cascade). */
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="walk"] .nfx-tr-trail { animation: none; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="walk"][data-f="step"] .nfx-tr-trail::before { animation: nfx-walk-prints var(--tr-p, 1s) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="walk"] .nfx-tr-trail::after { animation: nfx-walk-kick calc(var(--tr-p, 1s) / 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="walk"][data-g]::after { animation: nfx-walk-ground calc(var(--tr-p, 1s) / 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="walk"] .nfx-tr-p.glow { animation: nfx-walk-stomp calc(var(--tr-p, 1s) / 2) linear infinite var(--tr-delay); }
@keyframes nfx-walk-prints { from { transform: translateX(0); } to { transform: translateX(calc(2 * var(--wk-step))); } }
@keyframes nfx-walk-ground { from { transform: translateX(0); } to { transform: translateX(var(--wk-step)); } }
@keyframes nfx-walk-stomp { 0% { opacity: calc(.3 + .7 * var(--tr-boost, 0)); transform: translateX(0) scale(.35, .55); animation-timing-function: cubic-bezier(.2, .7, .4, 1); }
  60%, 100% { opacity: 0; transform: translateX(calc(.6 * var(--wk-step))) scale(1.1, 1); } }
@keyframes nfx-walk-kick { 0%, 100% { opacity: var(--wk-kick); transform: translate(0, 0); }
  12.5% { opacity: calc(.645 * var(--wk-kick)); transform: translate(calc(.14 * var(--wk-step)), calc(-.05 * var(--tr-U))); }
  25% { opacity: calc(.125 * var(--wk-kick)); transform: translate(calc(.28 * var(--wk-step)), calc(-.1 * var(--tr-U))); }
  37.5% { opacity: calc(.009 * var(--wk-kick)); transform: translate(calc(.42 * var(--wk-step)), calc(-.15 * var(--tr-U))); }
  50% { opacity: 0; transform: translate(calc(.56 * var(--wk-step)), calc(-.2 * var(--tr-U))); } 50.01% { opacity: 0; transform: translate(calc(-.56 * var(--wk-step)), calc(.2 * var(--tr-U))); }
  62.5% { opacity: calc(.009 * var(--wk-kick)); transform: translate(calc(-.42 * var(--wk-step)), calc(.15 * var(--tr-U))); }
  75% { opacity: calc(.125 * var(--wk-kick)); transform: translate(calc(-.28 * var(--wk-step)), calc(.1 * var(--tr-U))); }
  87.5% { opacity: calc(.645 * var(--wk-kick)); transform: translate(calc(-.14 * var(--wk-step)), calc(.05 * var(--tr-U))); } }
/* Phones: a plain walker (no ghosts, stomp or dust), thinner outlines, one dot per footprint. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :nth-child(-n+7) { display: none; }
  #ladder-rows .nfx-tr[data-v="walk"] { --tr-limb-w: .4px; }
  #ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-v > :is(:nth-child(10), :nth-child(14)) svg { filter: none; }
  #ladder-rows .nfx-tr[data-v="walk"] .nfx-tr-trail::after { display: none; }
  #ladder-rows .nfx-tr[data-v="walk"][data-f="step"] .nfx-tr-trail::before { background-image:
    radial-gradient(1.4px 1px at calc(.6 * var(--wk-fl)) calc(50% + .5px), #ffe7a3, transparent),
    radial-gradient(1.2px .9px at calc(var(--wk-step) + .6 * var(--wk-fl)) calc(50% - .5px), rgba(255, 209, 102, .6), transparent); }
}
/* bicycle (自行车) */
#ladder-rows .nfx-tr[data-v="bicycle"] { --tr-paint: #3fe3b2; --tr-paint2: #13977a; --tr-shade: #0c6652; --tr-metal: #dbe7e3; --tr-glass: rgba(8, 15, 26, .92); --tr-a: #95f9d7; --tr-b: #ff5b6e; --tr-lamp: #fff3cc; --tr-core: #effff8; --tr-stripe: #ffcf47; --tr-jersey: #27467f; --tr-leathers: #1a3160; --tr-leg: #5280d4; --tr-helmet: #ffc53d; --tr-skin: #efbf98; --tr-tread: #d6b98b; --tr-tire: #0b1015; --tr-wake: color-mix(in srgb, #95f9d7 22%, transparent); --tr-streak: rgba(214, 255, 241, .92); --tr-glow: color-mix(in srgb, #95f9d7 40%, transparent); --bk-sock: #eef3f7; --bk-rim: #0d161e; --bk-disc: #101a24; --bk-air-a: calc(.6 * var(--tr-boost, 0) + .4 * var(--tr-max, 0)); } #ladder-rows .nfx-tr[data-v="bicycle"] .r-tire { fill: var(--tr-tread); fill-rule: evenodd; stroke: none; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-rimw { fill: var(--bk-rim); fill-rule: evenodd; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-bkDisc { fill: var(--bk-disc); } #ladder-rows .nfx-tr[data-v="bicycle"] .r-bkDecal { fill: var(--tr-a); } #ladder-rows .nfx-tr[data-v="bicycle"] .r-spokeThin { stroke-width: .45px; opacity: calc(.55 - .4 * var(--tr-blur, 0)); } #ladder-rows .nfx-tr[data-v="bicycle"] .r-metal { fill-rule: evenodd; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-bkSheen { fill: #fff; opacity: .11; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.spin:not(.crank)::after { inset: 13%; border: 1.3px solid var(--tr-a); opacity: calc(.55 * var(--tr-blur, 0) + .35 * var(--tr-max, 0)); box-shadow: 0 0 4px color-mix(in srgb, var(--tr-a) 65%, transparent), inset 0 0 3px color-mix(in srgb, var(--tr-a) 45%, transparent); } #ladder-rows .nfx-tr[data-v="bicycle"] .r-crank { stroke: #c9d6d2; stroke-width: .9px; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.crank:has(.r-bkPedalFar) .r-crank { stroke: #6f7f8a; stroke-width: 1.6px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-metalLine { stroke: #d5e1dd; stroke-width: .55px; opacity: 1; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-chromeThick { stroke: #f3f8f6; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-bkPedalFar { fill: #a77d16; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-chain { stroke: #7d8e98; stroke-width: .7px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-dark { fill: #1b2735; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-bkBar { stroke: #213040; stroke-width: 1.5px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-chrome { stroke: #f2f6f4; stroke-width: 1.5px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-edge { stroke-width: .9px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-legLine { stroke-width: 2.5px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-skinLine { stroke-width: 1.7px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-armLine { stroke-width: 1.7px; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.limb > svg .r-limb { fill: var(--tr-leg); stroke: var(--tr-leg); stroke-width: .5px; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.limb .nfx-tr-p.limb > svg .r-limb { fill: var(--bk-sock); stroke: var(--bk-sock); } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-v > .nfx-tr-p.limb:first-child { --tr-leg: #2c4c8a; --bk-sock: #8794a3; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.still:is(:has(.r-jersey), :has(.r-legLine)) { transform-origin: 66.19% 29.07%; rotate: calc(-2.4deg * var(--tr-boost, 0)); } #ladder-rows .nfx-tr[data-v="bicycle"] .r-bkAir { stroke: var(--tr-streak); stroke-width: .7px; stroke-dasharray: 9 3 2 3; opacity: var(--bk-air-a); } #ladder-rows .nfx-tr[data-v="bicycle"]::before { opacity: calc(.32 * var(--tr-max, 0)); background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-a) 45%, transparent), color-mix(in srgb, var(--tr-stripe) 16%, transparent) 55%, transparent); } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-trail { background: radial-gradient(ellipse 80% 64% at 0 50%, color-mix(in srgb, var(--tr-a) 30%, transparent), transparent 74%), linear-gradient(to right, color-mix(in srgb, var(--tr-a) 14%, transparent), transparent); -webkit-mask: linear-gradient(to right, transparent, #000 9%), linear-gradient(transparent, #000 22% 78%, transparent); -webkit-mask-composite: source-in; mask: linear-gradient(to right, transparent, #000 9%), linear-gradient(transparent, #000 22% 78%, transparent); mask-composite: intersect; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-trail::before { left: calc(-3 * var(--tr-flow, 1) * var(--tr-U)); opacity: calc(.5 + .5 * var(--tr-boost, 0)); background: var(--tr-streak); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Cpath d='M0 6.7C5 5.7 10 5.7 15 6.7S25 7.7 30 6.7M0 13.3C5 14.3 10 14.3 15 13.3S25 12.3 30 13.3' fill='none' stroke='%23000' stroke-width='1.05'/%3E%3Cpath d='M1 10H11M16 10H27' fill='none' stroke='%23000' stroke-opacity='.75' stroke-width='.85'/%3E%3C/svg%3E") 0 0 / calc(3 * var(--tr-flow, 1) * var(--tr-U)) 100% repeat-x; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Cpath d='M0 6.7C5 5.7 10 5.7 15 6.7S25 7.7 30 6.7M0 13.3C5 14.3 10 14.3 15 13.3S25 12.3 30 13.3' fill='none' stroke='%23000' stroke-width='1.05'/%3E%3Cpath d='M1 10H11M16 10H27' fill='none' stroke='%23000' stroke-opacity='.75' stroke-width='.85'/%3E%3C/svg%3E") 0 0 / calc(3 * var(--tr-flow, 1) * var(--tr-U)) 100% repeat-x; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-trail::after { inset: 0 0 0 calc(-3 * var(--tr-flow, 1) * var(--tr-U)); opacity: calc(.25 * var(--tr-boost, 0) + .75 * var(--tr-max, 0)); background: color-mix(in srgb, var(--tr-a) 70%, white); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 20'%3E%3Cg fill='%23000'%3E%3Ccircle cx='3.5' cy='8.3' r='.95'/%3E%3Ccircle cx='10.5' cy='12.3' r='.75'/%3E%3Ccircle cx='17.5' cy='7.6' r='.65'/%3E%3Ccircle cx='24' cy='11.4' r='1'/%3E%3Ccircle cx='14' cy='10.2' r='.5'/%3E%3Ccircle cx='28' cy='8.8' r='.5'/%3E%3C/g%3E%3C/svg%3E") 0 0 / calc(3 * var(--tr-flow, 1) * var(--tr-U)) 100% repeat-x; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 20'%3E%3Cg fill='%23000'%3E%3Ccircle cx='3.5' cy='8.3' r='.95'/%3E%3Ccircle cx='10.5' cy='12.3' r='.75'/%3E%3Ccircle cx='17.5' cy='7.6' r='.65'/%3E%3Ccircle cx='24' cy='11.4' r='1'/%3E%3Ccircle cx='14' cy='10.2' r='.5'/%3E%3Ccircle cx='28' cy='8.8' r='.5'/%3E%3C/g%3E%3C/svg%3E") 0 0 / calc(3 * var(--tr-flow, 1) * var(--tr-U)) 100% repeat-x; } .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="bicycle"] .nfx-tr-p.still:is(:has(.r-jersey), :has(.r-legLine)) { animation: nfx-bk-rider calc(var(--tr-p, 1s) / 2) ease-in-out infinite var(--tr-delay); } .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="bicycle"] .nfx-tr-p.glow:has(.r-bkAir) { animation: nfx-bk-breathe calc(var(--tr-p, 1s) / 2) ease-in-out infinite var(--tr-delay); } .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="bicycle"] .nfx-tr-p.glow:has(.r-tail) { animation-duration: var(--tr-p, 1s); } .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="bicycle"] .nfx-tr-trail::before { animation: nfx-bk-wake calc(var(--tr-p, 1s) * 3 / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); } .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="bicycle"] .nfx-tr-trail::after { animation: nfx-bk-wake calc(var(--tr-p, 1s) * 4.5 / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); } @keyframes nfx-bk-rider { 0%, 100% { transform: translateY(calc(var(--tr-U, 15px) * (.014 + .026 * var(--tr-max, 0)))); } 50% { transform: translateY(0); } } @keyframes nfx-bk-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .7; } } @keyframes nfx-bk-wake { from { transform: translateX(0); } to { transform: translateX(calc(3 * var(--tr-flow, 1) * var(--tr-U))); } } @media (max-width: 720px) { #ladder-rows .nfx-tr[data-v="bicycle"] :is(.r-spokeThin, .r-bkSheen, .r-metalLine, .r-chain, .r-seam, .r-glint, .r-armLine) { display: none; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.glow:has(.r-bkAir), #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-trail::after { display: none; } #ladder-rows .nfx-tr[data-v="bicycle"] :is(.r-chrome, .r-bkBar) { stroke-width: .8px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-chromeThick { stroke-width: 1px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-crank { stroke-width: .6px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-legLine { stroke-width: 1.3px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-skinLine { stroke-width: .9px; } #ladder-rows .nfx-tr[data-v="bicycle"] .r-edge { stroke-width: .5px; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.limb > svg .r-limb { stroke-width: .2px; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-p.spin:not(.crank)::after { border-width: 1px; box-shadow: none; } #ladder-rows .nfx-tr[data-v="bicycle"] .nfx-tr-trail::before { -webkit-mask: repeating-linear-gradient(transparent 0 28%, #000 28% 40%, transparent 40% 60%, #000 60% 72%, transparent 72%); mask: repeating-linear-gradient(transparent 0 28%, #000 28% 40%, transparent 40% 60%, #000 60% 72%, transparent 72%); background: repeating-linear-gradient(90deg, var(--tr-streak) 0 calc(var(--tr-flow, 1) * var(--tr-U) * 1.8), transparent 0 calc(var(--tr-flow, 1) * var(--tr-U) * 3)); } }
/* ebike (电助力自行车) */
/* 电助力自行车 / E-bike v3 (key ebike, family pedal, enter 25): a lake-blue SUV pedelec. Fat tubes as filled
   shapes, a down-tube battery whose four assist LEDs (ECO → TURBO) fill with --tr-u, a mid-drive motor that
   flashes on each pedal stroke, a charge packet running battery → motor every P/2 (boost-gated), fat tyres with
   reflective sidewalls and a rim mark that shows the spin, and a restrained electric wake: one thin sine
   current, faint ions and a cyan core filament gated by --tr-max. Everything is scoped to data-v="ebike",
   keyframes are nfx-tr-ebike-*, clocks are the shared --tr-p / --tr-delay. Replaces the old lime ebike line. */
#ladder-rows .nfx-tr[data-v="ebike"] {
  --tr-paint: #1ea7e1; --tr-paint2: #137fb4; --tr-shade: #0b4c70; --tr-metal: #cfdbe6; --tr-glass: rgba(125, 233, 255, .75);
  --tr-a: #7ee9ff; --tr-b: #ff4d6d; --tr-lamp: #f2fbff; --tr-core: #e8fdff; --tr-stripe: #3cc8f7;
  --tr-jersey: #e6edf4; --tr-skin: #f1c7a0; --tr-leg: #4f6b8c; --tr-helmet: #1ea7e1; --tr-hair: #3b2a1e;
  --tr-tire: #0a0e14; --tr-tread: #8597ab; --tr-tire-line: #d6e2ec;
  --tr-wake: color-mix(in srgb, var(--tr-a) 16%, transparent); --tr-streak: color-mix(in srgb, var(--tr-a) 78%, white);
  --tr-glow: color-mix(in srgb, var(--tr-a) 42%, transparent);
  --tr-hot-k: .55;
  --eb-fold: #a9bccf; --eb-motor: #1c2a38; --eb-leg-far: #2f4157; --eb-metal-far: #6d8196; --eb-shoe: #e3eaf1; --eb-shoe-far: #8193a8;
  --eb-s: calc(var(--tr-U) / 15);
  --eb-tile: calc(var(--tr-flow, 1) * var(--tr-U) * 3);
  --tr-limb-w: max(1.1px, calc(var(--eb-s) * 2.3)); }
/* Far crank arm, far leg and far shoe (parts 1–3) sit in shadow. Thighs are thicker than shins. */
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-v > :nth-child(1) { --tr-metal: var(--eb-metal-far); }
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-v > :nth-child(2) { --tr-leg: var(--eb-leg-far); }
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-v > :nth-child(3) { --eb-shoe: var(--eb-shoe-far); }
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-v > .limb > svg > .r-limb { stroke-width: max(1.4px, calc(var(--eb-s) * 3)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebShoe { fill: var(--eb-shoe); }
/* Strokes scale with U (desktop U 15px = the designed widths), with floors for phones. */
#ladder-rows .nfx-tr[data-v="ebike"] .r-crank { stroke-width: max(.8px, calc(var(--eb-s) * 1.7)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-tireLine { stroke-width: max(.7px, calc(var(--eb-s) * 1.15)); opacity: .92; }
#ladder-rows .nfx-tr[data-v="ebike"] .r-rimLine { stroke-width: max(.6px, calc(var(--eb-s) * 1.25)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-spokeThin { stroke-width: calc(var(--eb-s) * .45); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-chromeThick { stroke-width: max(.8px, calc(var(--eb-s) * 1.6)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-metalLine { stroke-width: calc(var(--eb-s) * .8); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-edge { stroke-width: calc(var(--eb-s) * 1); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-stripe { stroke-width: calc(var(--eb-s) * 1.1); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-glint { stroke-width: calc(var(--eb-s) * .8); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-seam { stroke-width: calc(var(--eb-s) * .6); }
/* E-bike roles. */
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebDark { fill: rgba(3, 10, 20, .82); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebMotor { fill: var(--eb-motor); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebFold { fill: var(--eb-fold); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebMark { stroke: var(--tr-a); stroke-width: calc(var(--eb-s) * 1.5); opacity: calc(.95 - .6 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebRing { stroke: var(--tr-a); stroke-width: calc(var(--eb-s) * 1.2); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-battery { stroke: var(--tr-a); stroke-width: calc(var(--eb-s) * 4.4); stroke-opacity: .3; }
/* Assist LEDs: ECO is on whenever the motor helps; TOUR, SPORT and TURBO come in at u .25, .5, .75. */
#ladder-rows .nfx-tr[data-v="ebike"] :is(.r-ebCell1, .r-ebCell2, .r-ebCell3) { fill: var(--tr-a); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebCell4 { fill: var(--tr-core); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebCell2 { opacity: calc(.14 + .86 * clamp(0, (var(--tr-u, 0) - .25) * 10, 1)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebCell3 { opacity: calc(.14 + .86 * clamp(0, (var(--tr-u, 0) - .5) * 10, 1)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebCell4 { opacity: calc(.14 + .86 * clamp(0, (var(--tr-u, 0) - .75) * 10, 1)); }
/* The charge packet (a 'k' part): visible from boost, hidden while parked. */
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-p.shock { opacity: calc(.12 + .88 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="ebike"] .r-ebZap { fill: var(--tr-core); stroke: var(--tr-a); stroke-width: calc(var(--eb-s) * .6); opacity: 0; }
/* Electric wake: the field's wake box stays, fades out along its length; one thin sine current with faint ions
   flows right at road speed (3 dashes per tile); the core filament is cyan-white and only strong at --tr-max. */
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-trail {
  -webkit-mask: linear-gradient(transparent, #000 22% 78%, transparent), linear-gradient(to right, transparent, #000 7% 32%, transparent 98%);
  -webkit-mask-composite: source-in;
  mask: linear-gradient(transparent, #000 22% 78%, transparent), linear-gradient(to right, transparent, #000 7% 32%, transparent 98%);
  mask-composite: intersect; }
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-trail::before { left: calc(-1 * var(--eb-tile)); opacity: calc(.38 + .62 * var(--tr-boost, 0));
  background: var(--tr-streak);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 24' preserveAspectRatio='none'%3E%3Cpath d='M0 12C10 7.6 20 7.6 30 12S50 16.4 60 12' fill='none' stroke='%23000' stroke-width='2'/%3E%3Ccircle cx='21' cy='16.8' r='1.1'/%3E%3Ccircle cx='50' cy='7' r='1'/%3E%3C/svg%3E") 0 50% / var(--eb-tile) 100% repeat-x;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 24' preserveAspectRatio='none'%3E%3Cpath d='M0 12C10 7.6 20 7.6 30 12S50 16.4 60 12' fill='none' stroke='%23000' stroke-width='2'/%3E%3Ccircle cx='21' cy='16.8' r='1.1'/%3E%3Ccircle cx='50' cy='7' r='1'/%3E%3C/svg%3E") 0 50% / var(--eb-tile) 100% repeat-x; }
#ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-trail::after { inset: 47.5% 0; background: linear-gradient(to right, var(--tr-core), var(--tr-a) 24%, transparent 66%); }
/* At the limit the aura stays cool (no warm ring). */
#ladder-rows .nfx-tr[data-v="ebike"]::before { background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-a) 40%, transparent), color-mix(in srgb, var(--tr-paint) 18%, transparent) 55%, transparent); }
/* Running (the stock gate). */
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="ebike"] .r-ebZap {
  animation: nfx-tr-ebike-zap calc(var(--tr-p, 1s) / 2) cubic-bezier(.45, 0, .85, .7) infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="ebike"] .nfx-tr-trail::before {
  animation: nfx-tr-ebike-arc calc(var(--tr-p, 1s) * 3 / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); }
@keyframes nfx-tr-ebike-zap { 0% { transform: translate(0, 0); opacity: 0; } 18% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translate(12.18px, 10.22px); opacity: 0; } }
@keyframes nfx-tr-ebike-arc { from { transform: translateX(0); } to { transform: translateX(var(--eb-tile)); } }
/* Phones: a quiet silhouette (frame, fat tyres, battery bar, rider); no spokes, marks, seams or packet. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="ebike"] :is(.r-spokeThin, .r-tread, .r-ebMark, .r-glint, .r-seam, .r-stripe, .r-metalLine, .r-glass, .r-visor, .r-ebZap, .r-ebFold) { display: none; }
  #ladder-rows .nfx-tr[data-v="ebike"] .nfx-tr-trail::before { opacity: calc(.3 + .45 * var(--tr-boost, 0)); }
}
/* motorcycle (摩托车) */
/* motorcycle (black-gold superbike) — scoped roles and motion. Wheelie pivots on the rear tyre's contact patch. */
#ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-v { transform-origin: 81.99% 98.59%; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcGold { fill: var(--tr-paint2); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcGoldLine { stroke: var(--tr-paint2); stroke-width: .8px; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcGloss { fill: var(--tr-gloss); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcEngine { fill: var(--tr-engine); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcArm { fill: var(--tr-arm); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcPipe { fill: var(--tr-steel); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcHeatTint { fill: var(--tr-heat-tint); opacity: calc(.55 + .45 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcBrake { fill: var(--tr-brake); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcSuit { fill: var(--tr-leathers); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcSuitHi { fill: var(--tr-suit-hi); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcBoot { fill: #07090d; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcVisorGlint { stroke: var(--tr-a); stroke-width: .8px; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcRim { stroke: var(--tr-rim-gold); stroke-width: 1.3px; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcSpoke { stroke: var(--tr-rim-gold); stroke-width: 1.1px; opacity: calc(1 - .55 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcDisc { stroke: var(--tr-steel); stroke-width: 1px; opacity: .8; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcHub { fill: var(--tr-core); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.spin::after { inset: 15%; border: 1.5px solid var(--tr-a); box-shadow: 0 0 4px var(--tr-a), inset 0 0 3px color-mix(in srgb, var(--tr-a) 60%, transparent);
  opacity: calc(.12 + .6 * var(--tr-blur, 0) + .2 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.still:has(.r-mcSuit) { transform-origin: 61.03% 24.65%; translate: calc(-.8% * var(--tr-boost, 0)) calc(2.8% * var(--tr-boost, 0)); rotate: calc(-1.6deg * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.glow:has(.r-mcHeat) { --tr-glow-a: calc(.18 + .82 * var(--tr-boost, 0)); opacity: var(--tr-glow-a); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcHeat { fill: var(--tr-b); fill-opacity: .7; }
#ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.glow:has(.r-mcFlare) { --tr-glow-a: calc(.85 * var(--tr-boost, 0)); opacity: var(--tr-glow-a); }
#ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcFlare { fill: var(--tr-lamp); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="motorcycle"] .nfx-tr-p.glow:has(.r-mcFlare) { animation: nfx-tr-mc-flare calc(var(--tr-p, 1s) * 4) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-tr-mc-flare { 0%, 100% { opacity: var(--tr-glow-a, 0); transform: scaleX(1); } 50% { opacity: calc(.7 * var(--tr-glow-a, 0)); transform: scaleX(1.2); } }
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="motorcycle"] :is(.r-mcSpoke, .r-mcDisc, .r-tread, .r-stripe, .r-glint, .r-seam, .r-metalLine, .r-mcGoldLine, .r-mcHeatTint, .r-mcVisorGlint, .r-mcSuitHi, .r-mcGloss) { display: none; }
  #ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.glow:has(.r-mcFlare), #ladder-rows .nfx-tr[data-v="motorcycle"] .nfx-tr-p.spin::after { display: none; }
  #ladder-rows .nfx-tr[data-v="motorcycle"] .r-mcRim { stroke-width: 1px; } #ladder-rows .nfx-tr[data-v="motorcycle"] .r-edge { stroke-width: .7px; }
}
/* car (小型两厢车) */
/* car (小型两厢车): coral retro-modern hot hatch. Extra roles: paintHi, tailRed, sheen, airflow. */
#ladder-rows .nfx-tr[data-v="car"] .r-paintHi { fill: var(--tr-paint-hi); }
#ladder-rows .nfx-tr[data-v="car"] .r-tailRed { fill: var(--tr-tail-red); }
#ladder-rows .nfx-tr[data-v="car"] .r-flameCore { fill-opacity: .95; }
#ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.still { transform-origin: 79.06% 76.99%; rotate: calc(var(--tr-boost, 0) * 1.1deg);
  --tr-car-ride: calc(.055 - .03 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.glow:has(.r-sheen) { overflow: hidden; transform-origin: 136.56% 83.64%; rotate: calc(var(--tr-boost, 0) * 1.1deg);
  --tr-car-ride: calc(.055 - .03 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.glow:has(.r-sheen)::after { content: ""; position: absolute; top: -10%; bottom: -10%; left: 0; width: 26%;
  background: linear-gradient(90deg, transparent, rgba(255, 246, 236, .75) 45%, rgba(255, 255, 255, .9) 52%, transparent);
  transform: translateX(-130%) skewX(-24deg); opacity: calc(.3 + .5 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="car"] .r-sheen { stroke: rgba(255, 236, 226, .55); stroke-width: .7px; }
#ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.glow:has(.r-airflow) { transform-origin: 0 50%; opacity: 0; }
#ladder-rows .nfx-tr[data-v="car"] .r-airflow { stroke: var(--tr-streak); stroke-width: .9px; }
#ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.flame { --tr-flame-a: var(--tr-max, 0); opacity: 0; }
#ladder-rows .nfx-tr[data-v="car"] .nfx-tr-beam { background: linear-gradient(to left, color-mix(in srgb, var(--tr-lamp) 78%, transparent), color-mix(in srgb, var(--tr-a) 18%, transparent) 55%, transparent); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="car"] .nfx-tr-p.still, .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="car"] .nfx-tr-p.glow:has(.r-sheen) {
  animation: nfx-tr-car-ride calc(2 * var(--tr-p, 1s)) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="car"] .nfx-tr-p.glow:has(.r-sheen)::after {
  animation: nfx-tr-car-sheen calc(3 * var(--tr-p, 1s)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="car"] .nfx-tr-p.glow:has(.r-airflow) {
  animation: nfx-tr-car-air var(--tr-p, 1s) ease-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="car"] .nfx-tr-p.flame {
  animation: nfx-tr-car-pop calc(2 * var(--tr-p, 1s)) linear infinite var(--tr-delay); }
@keyframes nfx-tr-car-ride {
  0%, 50%, 100% { translate: 0 0; rotate: calc(var(--tr-boost, 0) * 1.1deg); }
  25% { translate: 0 calc(var(--tr-U) * var(--tr-car-ride, .05)); rotate: calc(var(--tr-boost, 0) * 1.1deg - .55deg); }
  75% { translate: 0 calc(var(--tr-U) * var(--tr-car-ride, .05) * -.6); rotate: calc(var(--tr-boost, 0) * 1.1deg + .35deg); } }
@keyframes nfx-tr-car-sheen {
  0% { transform: translateX(-130%) skewX(-24deg); }
  60%, 100% { transform: translateX(420%) skewX(-24deg); } }
@keyframes nfx-tr-car-air {
  0% { opacity: 0; transform: scaleX(.35); }
  30% { opacity: calc(.85 * var(--tr-boost, 0)); }
  100% { opacity: 0; transform: scaleX(1.3); } }
@keyframes nfx-tr-car-pop {
  0%, 100% { opacity: 0; transform: scaleX(.3); }
  5% { opacity: var(--tr-max, 0); transform: scaleX(1); }
  13% { opacity: calc(.4 * var(--tr-max, 0)); transform: scaleX(1.2); }
  18% { opacity: calc(.7 * var(--tr-max, 0)); transform: scaleX(.85); }
  32% { opacity: 0; transform: scaleX(.5); } }
@media (max-width: 720px), (pointer: coarse) and (max-height: 720px) {
  #ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.glow, #ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.flame { display: none; }
  #ladder-rows .nfx-tr[data-v="car"] .nfx-tr-p.still { rotate: 0deg; }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="car"] .nfx-tr-p.still { animation: none; }
}
/* suv (越野SUV) */
/* suv: added roles (paintHi, beadlock, barGlow, lightbar, amber, spare, dustA/B/F) and its own motion. */
#ladder-rows .nfx-tr[data-v="suv"] { --tr-jolt: calc(var(--tr-U) * (.025 + .055 * var(--tr-boost, 0))); --tr-pitch: calc(.45deg + 1deg * var(--tr-boost, 0));
  --tr-dust-a: min(1, calc(.32 + .45 * var(--tr-boost, 0) + .23 * var(--tr-max, 0))); --tr-dust-x: calc(.55 + .95 * var(--tr-u, 0)); }
#ladder-rows .nfx-tr[data-v="suv"] .r-paintHi { fill: var(--tr-paint-hi); }
#ladder-rows .nfx-tr[data-v="suv"] .r-beadlock { stroke: var(--tr-paint2); stroke-width: .7px; }
#ladder-rows .nfx-tr[data-v="suv"] .r-spoke { stroke: #14161b; stroke-width: 1.15px; }
#ladder-rows .nfx-tr[data-v="suv"] .r-tread { stroke-width: 1.1px; stroke-dasharray: .5 .5; }
#ladder-rows .nfx-tr[data-v="suv"] .r-tire { stroke: rgba(214, 190, 140, .35); }
#ladder-rows .nfx-tr[data-v="suv"] .r-spare { fill: var(--tr-paint2); stroke: var(--tr-paint); stroke-width: .6px; }
#ladder-rows .nfx-tr[data-v="suv"] .r-amber { fill: #fbbf24; }
#ladder-rows .nfx-tr[data-v="suv"] .r-lightbar { fill: var(--tr-bar); opacity: calc(.35 + .65 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="suv"] .r-barGlow { stroke: var(--tr-bar); stroke-width: 3.2px; opacity: calc(.08 + .42 * var(--tr-boost, 0) + .2 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="suv"] :is(.r-dustA, .r-dustB, .r-dustF) { fill: var(--tr-dust); }
#ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-p.still { transform-origin: 50% 80%; }
#ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-p.glow:has(.r-dustA, .r-dustB) { transform-origin: 8% 92%; opacity: calc(.55 * var(--tr-dust-a)); transform: scale(.85); }
#ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-p.glow:has(.r-dustF) { transform-origin: 10% 90%; opacity: calc(.5 * var(--tr-max, 0)); transform: scale(.85); }
#ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-spark { width: 1.6px; height: 1.6px; background: #e3cc98; box-shadow: 0 0 2px rgba(160, 120, 60, .9); }
#ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-trail::before { -webkit-mask: none; mask: none;
  background: radial-gradient(closest-side, var(--tr-streak), transparent) 0 64% / calc(var(--tr-flow) * var(--tr-U)) 72% repeat-x,
    radial-gradient(closest-side, color-mix(in srgb, var(--tr-streak) 65%, transparent), transparent) calc(var(--tr-flow) * var(--tr-U) * .25) 22% / calc(var(--tr-flow) * var(--tr-U) * .5) 46% repeat-x; }
#ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-trail { -webkit-mask: linear-gradient(transparent, #000 25% 75%, transparent), linear-gradient(to right, #000 55%, transparent); -webkit-mask-composite: source-in;
  mask: linear-gradient(transparent, #000 25% 75%, transparent), linear-gradient(to right, #000 55%, transparent); mask-composite: intersect; }
#ladder-rows .nfx-tr[data-v="suv"]::before { background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-bar) 34%, transparent), color-mix(in srgb, var(--tr-dust) 22%, transparent) 55%, transparent); }
#ladder-rows .nfx-tr[data-v="suv"][data-g]::after { height: 2px; margin-top: -1px; opacity: .62;
  background: repeating-linear-gradient(90deg, rgba(226, 198, 140, .9) 0 calc(var(--tr-flow) * var(--tr-U) * .34), transparent 0 calc(var(--tr-flow) * var(--tr-U) * .5),
    rgba(226, 198, 140, .4) 0 calc(var(--tr-flow) * var(--tr-U) * .6), transparent 0 calc(var(--tr-flow) * var(--tr-U))); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="suv"] .nfx-tr-p.still { animation: nfx-tr-suv-jolt calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="suv"] .nfx-tr-p.glow:has(.r-dustA) { animation: nfx-tr-suv-dust var(--tr-p, 1s) cubic-bezier(.2, .7, .4, 1) infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="suv"] .nfx-tr-p.glow:has(.r-dustB) { animation: nfx-tr-suv-dust var(--tr-p, 1s) cubic-bezier(.2, .7, .4, 1) infinite calc(var(--tr-delay) - var(--tr-p, 1s) / 2); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="suv"] .nfx-tr-p.glow:has(.r-dustF) { --tr-dust-a: calc(.8 * var(--tr-max, 0)); animation: nfx-tr-suv-dust var(--tr-p, 1s) cubic-bezier(.2, .7, .4, 1) infinite calc(var(--tr-delay) - var(--tr-p, 1s) / 4); }
@keyframes nfx-tr-suv-jolt {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  12% { transform: translateY(calc(-1 * var(--tr-jolt))) rotate(calc(-1 * var(--tr-pitch))); }
  27% { transform: translateY(calc(.35 * var(--tr-jolt))) rotate(calc(.45 * var(--tr-pitch))); }
  46% { transform: translateY(calc(-.45 * var(--tr-jolt))) rotate(calc(.7 * var(--tr-pitch))); }
  63% { transform: translateY(calc(.2 * var(--tr-jolt))) rotate(calc(-.3 * var(--tr-pitch))); }
  81% { transform: translateY(calc(-.7 * var(--tr-jolt))) rotate(calc(.25 * var(--tr-pitch))); } }
@keyframes nfx-tr-suv-dust {
  0% { opacity: var(--tr-dust-a); transform: translate(0, 0) scale(.45); }
  35% { opacity: calc(.85 * var(--tr-dust-a)); }
  100% { opacity: 0; transform: translate(calc(var(--tr-U) * var(--tr-dust-x)), calc(var(--tr-U) * -.24)) scale(1.35); } }
/* Phones: a quiet silhouette. No jolt, no front dust, no fine lines; one soft rear puff stays. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="suv"] :is(.r-seam, .r-glint, .r-metalLine, .r-fender, .r-barGlow, .r-beadlock, .r-amber, .r-stripeFill) { display: none; }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="suv"] .nfx-tr-p.still { animation: none; }
  #ladder-rows .nfx-tr[data-v="suv"] .nfx-tr-p.glow:has(.r-dustF, .r-dustB) { display: none; }
}
/* sedan (运动轿车) */
/* 运动轿车 sedan v3: metallic sapphire, ice-white blade lamp, red through light bar. */
#ladder-rows .nfx-tr[data-v="sedan"] { --tr-paint: #2457e6; --tr-paint2: #6d95ff; --tr-shade: #16338c; --tr-metal: #d9e4f4; --tr-glass: rgba(8, 16, 40, .94); --tr-a: #8fb6ff; --tr-b: #ff2d55; --tr-lamp: #eef7ff; --tr-core: #ffe4ea; --tr-stripe: #b4caff; --tr-tire: #06080d; --tr-tread: #6b7a93; --tr-hot-k: .1; --tr-sd-caliper: #ff2d55; --tr-wake: rgba(111, 155, 255, .26); --tr-streak: rgba(150, 186, 255, .72); --tr-glow: rgba(111, 155, 255, .5); }
#ladder-rows .nfx-tr[data-v="sedan"] .r-sdSpoke { fill: var(--tr-metal); opacity: calc(1 - .62 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="sedan"] .r-sdCaliper { fill: var(--tr-sd-caliper); }
#ladder-rows .nfx-tr[data-v="sedan"] .r-sdSheen { fill: #fff; fill-opacity: .13; }
#ladder-rows .nfx-tr[data-v="sedan"] .nfx-tr-p.glow .r-lamp { fill-opacity: .6; }
#ladder-rows .nfx-tr[data-v="sedan"] .r-tread { stroke: #2a3445; stroke-width: .8px; opacity: calc(.95 - .55 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="sedan"] .r-glint { opacity: .7; }
#ladder-rows .nfx-tr[data-v="sedan"] .r-stripe { stroke-width: .7px; opacity: calc(.55 + .35 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="sedan"] .r-flameCore { fill: var(--tr-core); }
#ladder-rows .nfx-tr[data-v="sedan"] .nfx-tr-under { transform: scaleY(1.9); opacity: calc(.4 + .3 * var(--tr-boost, 0) + .3 * var(--tr-max, 0)); background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-b) 78%, transparent), color-mix(in srgb, var(--tr-b) 24%, transparent) 55%, transparent); }
#ladder-rows .nfx-tr[data-v="sedan"] .nfx-tr-p.glow { overflow: hidden; opacity: calc(.12 + .88 * var(--tr-boost, 0)); -webkit-mask: linear-gradient(to right, transparent, #000 16% 80%, transparent); mask: linear-gradient(to right, transparent, #000 16% 80%, transparent); }
#ladder-rows .nfx-tr[data-v="sedan"] .nfx-tr-p.shock { transform: translateY(calc((1 - var(--tr-max, 0)) * 42%)); }
#ladder-rows .nfx-tr[data-v="sedan"] .nfx-tr-p.flame { --tr-flame-a: calc(var(--tr-boost, 0) * (.55 + .45 * var(--tr-max, 0))); transform: scaleX(calc(.3 + .7 * var(--tr-u, 0))); -webkit-mask: linear-gradient(to right, #000 12%, rgba(0, 0, 0, .5) 50%, transparent); mask: linear-gradient(to right, #000 12%, rgba(0, 0, 0, .5) 50%, transparent); }
#ladder-rows .nfx-tr[data-v="sedan"] .nfx-tr-p.flame .r-flame { fill-opacity: .9; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sedan"] .nfx-tr-p.glow { animation: none; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sedan"] .nfx-tr-p.glow > svg { animation: nfx-tr-sedan-sheen calc(var(--tr-p, 1s) * 3) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sedan"] .nfx-tr-p.flame { animation: nfx-tr-sedan-ribbon calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-tr-sedan-sheen { 0% { transform: translateX(0); } 42%, 100% { transform: translateX(132%); } }
@keyframes nfx-tr-sedan-ribbon { 0%, 100% { opacity: var(--tr-flame-a, 0); transform: scaleX(calc(.3 + .7 * var(--tr-u, 0))); } 50% { opacity: calc(.82 * var(--tr-flame-a, 0)); transform: scaleX(calc((.3 + .7 * var(--tr-u, 0)) * .93)); } }
@media (max-width: 720px) { #ladder-rows .nfx-tr[data-v="sedan"] :is(.r-glint, .r-seam, .r-metalLine, .r-stripe, .r-metal, .r-sdSpoke, .r-sdCaliper) { display: none; } #ladder-rows .nfx-tr[data-v="sedan"] :is(.nfx-tr-p.glow, .nfx-tr-p.shock, .nfx-tr-p.flame) { display: none; } #ladder-rows .nfx-tr[data-v="sedan"] .r-edge { stroke-width: .6px; } #ladder-rows .nfx-tr[data-v="sedan"] .r-tail { stroke: var(--tr-b); stroke-width: .9px; } #ladder-rows .nfx-tr[data-v="sedan"] .r-lamp { stroke: var(--tr-lamp); stroke-width: .7px; } }
/* sportsCar (GT跑车) */
/* GT 跑车 v3 (sportsCar): obsidian violet, champagne gold. Extra roles (styled here only): r-gtTail rose LED tail bar; r-gtWin the dark windows between the alloy's swept spokes (fade as the wheel blurs); r-gtGlassHi a soft sky reflection on the side glass; r-gtSheen a reflection band crossing the upper flank. Transform and opacity only; every animation sits behind the shared RUN gate on the row clock (--tr-p, --tr-delay); intensity always scales with --tr-boost / --tr-max. */
#ladder-rows .nfx-tr[data-v="sportsCar"] { --tr-gt-tail: #ff3d73; --tr-gt-win: #140a24; --tr-gt-sheen: #f6f0ff; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-gtTail { fill: var(--tr-gt-tail); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-gtWin { fill: var(--tr-gt-win); opacity: calc(1 - .5 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-gtGlassHi { fill: var(--tr-a); opacity: .16; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-gtSheen { fill: var(--tr-gt-sheen); fill-opacity: .34; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-glint { stroke-width: .7px; opacity: .7; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-stripe { stroke-width: 1.1px; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-metalLine { stroke-width: .7px; opacity: .9; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-pillar { stroke: var(--tr-shade); stroke-width: 1.3px; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .r-edge { stroke-width: 1.1px; opacity: calc(.55 + .45 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-p.glow { clip-path: polygon(0.69% 67.72%, 0.61% 70.34%, 1.51% 65.25%, 2.15% 62.92%, 2.96% 61.02%, 5.22% 57.41%, 7.6% 54.21%, 10.15% 51.38%, 12.92% 48.9%, 15.96% 46.76%, 19.33% 44.92%, 23.96% 43.32%, 28.54% 41.92%, 33% 40.68%, 37.27% 39.58%, 41.28% 38.6%, 44.97% 37.71%, 46.75% 34.23%, 48.53% 29.63%, 50.32% 24.42%, 52.13% 19.1%, 53.96% 14.18%, 55.82% 10.17%, 57.36% 8.12%, 59% 6.61%, 60.72% 5.61%, 62.5% 5.12%, 64.29% 5.09%, 66.07% 5.51%, 69.6% 7.81%, 73.25% 11.5%, 76.97% 16.21%, 80.73% 21.55%, 84.47% 27.15%, 88.17% 32.63%, 89.91% 34.85%, 91.58% 36.44%, 93.17% 37.39%, 94.68% 37.71%, 96.11% 37.39%, 97.44% 36.44%, 98.52% 38.98%, 98.97% 44.71%, 99.26% 51.46%, 99.39% 58.81%, 99.56% 63.05%, 87.5% 63.99%, 86.1% 55.27%, 84.19% 48.52%, 81.93% 44.26%, 79.49% 42.8%, 77.04% 44.26%, 74.78% 48.52%, 72.88% 55.27%, 71.47% 63.99%, 27.64% 66.84%, 26.29% 57.04%, 24.34% 49.37%, 21.95% 44.48%, 19.33% 42.8%, 16.71% 44.48%, 14.32% 49.37%, 12.36% 57.04%, 11.02% 66.84%); opacity: calc(.24 + .46 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-p.glow > svg { opacity: 0; transform: translateX(-12%); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sportsCar"] .nfx-tr-p.glow { animation: none; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sportsCar"] .nfx-tr-p.glow > svg { animation: nfx-gt-sheen calc(var(--tr-p, 1s) * 3) linear infinite var(--tr-delay); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-p.flame { --tr-flame-a: calc(.9 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-under { opacity: calc(.22 + .5 * var(--tr-boost, 0)); background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-a) 55%, transparent), color-mix(in srgb, var(--tr-b) 18%, transparent) 60%, transparent); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-trail { background: linear-gradient(to right, var(--tr-wake), color-mix(in srgb, var(--tr-wake) 40%, transparent) 35%, transparent); -webkit-mask: linear-gradient(transparent, #000 30% 70%, transparent); mask: linear-gradient(transparent, #000 30% 70%, transparent); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-trail::before { -webkit-mask: repeating-linear-gradient(transparent 0 21%, #000 21% 27%, transparent 27% 44%); mask: repeating-linear-gradient(transparent 0 21%, #000 21% 27%, transparent 27% 44%); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-trail::after { inset: 67.08% 0 10.92% 0; }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::before, #ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::after { content: ""; position: absolute; left: 0; height: 1px; transform-origin: 0 50%; width: calc(var(--tr-U) * var(--tr-trail, 2) * var(--tr-trail-k, 1)); opacity: calc(.1 + .75 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::before { top: 5.79%; height: 1.5px; rotate: atan2(calc(var(--tr-U) * var(--tr-half, .5) * (1 - var(--tr-tip, .5))), calc(var(--tr-U) * var(--tr-trail, 2) * var(--tr-trail-k, 1))); background: linear-gradient(to right, var(--tr-gt-tail), color-mix(in srgb, var(--tr-gt-tail) 45%, transparent) 45%, transparent 95%); }
#ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::after { bottom: 4%; rotate: calc(-1 * atan2(calc(var(--tr-U) * var(--tr-half, .5) * (1 - var(--tr-tip, .5))), calc(var(--tr-U) * var(--tr-trail, 2) * var(--tr-trail-k, 1)))); background: linear-gradient(to right, color-mix(in srgb, var(--tr-stripe) 80%, white), color-mix(in srgb, var(--tr-stripe) 40%, transparent) 45%, transparent 95%); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::before, .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::after { animation: nfx-gt-ribbon calc(var(--tr-p, 1s) / var(--tr-beats, 1)) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-gt-sheen { 0% { opacity: 0; transform: translateX(-12%); } 10% { opacity: 1; } 76% { opacity: 1; } 90%, 100% { opacity: 0; transform: translateX(100%); } }
@keyframes nfx-gt-ribbon { 0%, 100% { opacity: calc(.1 + .75 * var(--tr-boost, 0)); } 50% { opacity: calc((.1 + .75 * var(--tr-boost, 0)) * .62); } }
@media (max-width: 720px) { #ladder-rows .nfx-tr[data-v="sportsCar"] :is(.r-glint, .r-seam, .r-metalLine, .r-stripe, .r-stripeFill, .r-pillar, .r-gtWin, .r-gtGlassHi, .r-hub, .r-tread) { display: none; } #ladder-rows .nfx-tr[data-v="sportsCar"] :is(.nfx-tr-p.glow, .nfx-tr-p.flame) { display: none; } #ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::before, #ladder-rows .nfx-tr[data-v="sportsCar"] .nfx-tr-lane::after { content: none; } #ladder-rows .nfx-tr[data-v="sportsCar"] .r-edge { stroke-width: .8px; } }
/* rallyCar (拉力赛车) */
/* rallyCar (拉力赛车): white/red gravel hatch. Palette, 4 extra roles, gravel roost trail, gravel ground, anti-lag pops,
   suspension travel; every animation on the shared RUN gate and the row clock (--tr-p, --tr-delay). */
#ladder-rows .nfx-tr[data-v="rallyCar"] { --tr-paint: #f8fafc; --tr-paint2: #e11d2e; --tr-shade: #a3b0c2; --tr-metal: #e8edf3;
  --tr-glass: rgba(8, 13, 26, .92); --tr-a: #bae6fd; --tr-b: #ff5a2c; --tr-lamp: #fff3c4; --tr-core: #fff7e6;
  --tr-stripe: #0f172a; --tr-tire: #090c11; --tr-tread: #5b6472;
  --tr-wake: rgba(196, 160, 104, .36); --tr-streak: rgba(242, 226, 190, .95); --tr-hot-k: 0;
  --tr-rally-paint-shade: #9b1023; --tr-rally-lip: #7f0d1d; --tr-rally-carbon: #2b3443;
  --tr-rally-mud: #a07a4c; --tr-rally-dust: #c9a46c; --tr-rally-grit: #e9d6ae; }
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-paintShade { fill: var(--tr-rally-paint-shade); }
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-carbon { fill: var(--tr-rally-carbon); }
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-mud { fill: var(--tr-rally-mud); opacity: .6; }
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-lip { stroke: var(--tr-rally-lip); stroke-width: 1px; }
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-tread { stroke-width: 1.5px; stroke-dasharray: .5 .5; }
/* Gravel roost instead of a smooth wake: dust puffs that fan out, grit flowing back, brighter with --tr-boost. */
#ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-trail {
  background: radial-gradient(ellipse 34% 46% at 20% 60%, color-mix(in srgb, var(--tr-rally-dust) 62%, transparent), transparent 72%),
    radial-gradient(ellipse 30% 40% at 50% 42%, color-mix(in srgb, var(--tr-rally-dust) 44%, transparent), transparent 72%),
    radial-gradient(ellipse 26% 34% at 78% 58%, color-mix(in srgb, var(--tr-rally-dust) 26%, transparent), transparent 72%),
    linear-gradient(to right, transparent, var(--tr-wake) 14%, transparent 92%);
  -webkit-mask: linear-gradient(transparent, #000 25% 75%, transparent), linear-gradient(to right, transparent, #000 16%); -webkit-mask-composite: source-in;
  mask: linear-gradient(transparent, #000 25% 75%, transparent), linear-gradient(to right, transparent, #000 16%); mask-composite: intersect; }
#ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-trail::before { opacity: calc(.35 + .65 * var(--tr-boost, 0));
  background: radial-gradient(circle at 30% 30%, var(--tr-streak) 0 .9px, transparent 1.4px) 0 0 / calc(var(--tr-flow) * var(--tr-U) / 2) 50%,
    radial-gradient(circle at 70% 70%, var(--tr-rally-grit) 0 .7px, transparent 1.1px) 0 0 / calc(var(--tr-flow) * var(--tr-U) / 3) 34%;
  -webkit-mask: linear-gradient(to right, transparent, #000 18% 40%, transparent 95%); mask: linear-gradient(to right, transparent, #000 18% 40%, transparent 95%); }
/* Dust puffs: the shared hot core (unused: --tr-hot-k 0) becomes a soft puff that leaves the tyre on every roost beat
   (P / --tr-beats on the row clock) and billows back as it fades; brighter with --tr-boost. */
#ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-trail::after { inset: 0 auto 0 0; width: 55%; border-radius: 50%; opacity: 0;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-rally-dust) 75%, transparent), transparent); }
/* A gravel stage under it: loose stones and a broken rut, flowing right on the shared ground clock. */
#ladder-rows .nfx-tr[data-v="rallyCar"][data-g]::after { height: 2px; margin-top: -1px; opacity: .65;
  background: radial-gradient(circle at 25% 50%, color-mix(in srgb, var(--tr-rally-grit) 85%, transparent) 0 .8px, transparent 1.1px) 0 0 / calc(var(--tr-flow) * var(--tr-U) / 3) 100% repeat-x,
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--tr-rally-dust) 60%, transparent) 0 calc(var(--tr-flow) * var(--tr-U) * .3), transparent 0 calc(var(--tr-flow) * var(--tr-U) * .5)) 0 100% / 100% 1px no-repeat; }
/* Stones, not sparks. */
#ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-spark { width: 2.4px; height: 2.4px; margin: -1.2px 0 0 -1.2px; border-radius: 35%; background: var(--tr-rally-grit);
  box-shadow: 0 0 2px color-mix(in srgb, var(--tr-rally-dust) 80%, transparent); }
#ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-spark.late { width: 1.8px; height: 1.8px; margin: -.9px 0 0 -.9px; }
/* Anti-lag: no flame below max; at max a double pop once per 4 cycles (calm, never a strobe). */
#ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-p.flame { --tr-flame-a: var(--tr-max, 0); opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rallyCar"] .nfx-tr-p.flame { animation: nfx-tr-rally-pop calc(var(--tr-p, 1s) * 4) linear infinite var(--tr-delay); }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rallyCar"] .nfx-tr-trail::after { animation: nfx-tr-rally-puff calc(var(--tr-p, 1s) / 2) ease-out infinite var(--tr-delay); }
}
@media (prefers-reduced-motion: no-preference) and (min-width: 721px) {
  /* Suspension travel: the body (paint, arches, flaps, wing) works over the gravel against wheels that stay on the
     road, more travel and pitch with --tr-u. */
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rallyCar"] .nfx-tr-p.still { animation: nfx-tr-rally-susp calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
}
@keyframes nfx-tr-rally-susp {
  0%, 100% { translate: 0 0; rotate: 0deg; }
  14% { translate: 0 calc(var(--tr-U) * (.025 + .055 * var(--tr-u, 0))); rotate: calc(-.25deg - .55deg * var(--tr-u, 0)); }
  30% { translate: 0 calc(var(--tr-U) * (-.015 - .035 * var(--tr-u, 0))); rotate: calc(.15deg + .4deg * var(--tr-u, 0)); }
  48% { translate: 0 calc(var(--tr-U) * (.006 + .012 * var(--tr-u, 0))); rotate: 0deg; }
  64% { translate: 0 calc(var(--tr-U) * (.02 + .045 * var(--tr-u, 0))); rotate: calc(.2deg + .45deg * var(--tr-u, 0)); }
  80% { translate: 0 calc(var(--tr-U) * (-.012 - .028 * var(--tr-u, 0))); rotate: calc(-.1deg - .3deg * var(--tr-u, 0)); } }
@keyframes nfx-tr-rally-puff {
  0% { opacity: calc(.3 + .5 * var(--tr-boost, 0)); transform: translateX(0) scale(.45); }
  100% { opacity: 0; transform: translateX(85%) scale(1.2); } }
@keyframes nfx-tr-rally-pop {
  0% { opacity: 0; transform: rotate(var(--fd, 0deg)) scaleX(.35) rotate(calc(-1 * var(--fd, 0deg))); }
  3% { opacity: var(--tr-flame-a, 0); transform: rotate(var(--fd, 0deg)) scaleX(calc(.95 + .45 * var(--tr-u, 0))) rotate(calc(-1 * var(--fd, 0deg))); }
  8% { opacity: calc(.15 * var(--tr-flame-a, 0)); transform: rotate(var(--fd, 0deg)) scaleX(.7) rotate(calc(-1 * var(--fd, 0deg))); }
  11% { opacity: calc(.8 * var(--tr-flame-a, 0)); transform: rotate(var(--fd, 0deg)) scaleX(calc(.8 + .35 * var(--tr-u, 0))) rotate(calc(-1 * var(--fd, 0deg))); }
  19%, 100% { opacity: 0; transform: rotate(var(--fd, 0deg)) scaleX(.5) rotate(calc(-1 * var(--fd, 0deg))); } }
/* Phones: a quiet white/red hatch with its dust; no pops, stones (shared), grit or fine lines. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="rallyCar"] :is(.r-seam, .r-glint, .r-mud, .r-lip) { display: none; }
  #ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-p.flame { display: none; }
  #ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-trail::before, #ladder-rows .nfx-tr[data-v="rallyCar"] .nfx-tr-trail::after { display: none; }
}
/* polish-v5: wing struts — graphite (carbon mixed toward metal) with a metal leading-edge highlight, so the wing reads as
   bolted to the tailgate instead of floating. */
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-strut { fill: color-mix(in srgb, var(--tr-rally-carbon) 42%, var(--tr-metal)); }
#ladder-rows .nfx-tr[data-v="rallyCar"] .r-strutEdge { stroke: var(--tr-metal); stroke-width: .8px; opacity: .9; }
@media (max-width: 720px) { #ladder-rows .nfx-tr[data-v="rallyCar"] .r-strutEdge { display: none; } }
/* supercar (超跑) */
/* 超跑 supercar (CC design v3). Scoped to data-v="supercar"; unique sc- keyframes; transform/opacity only. */
#ladder-rows .nfx-tr[data-v="supercar"] { --tr-hot-k: .85; --tr-flick-n: 1; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-carbon { fill: #161c26; stroke: color-mix(in srgb, var(--tr-a) 35%, transparent); stroke-width: .4px; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-crease { stroke: #ffd29a; stroke-width: .7px; opacity: .8; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-vane { stroke: #3b4656; stroke-width: .8px; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-heat { fill: #ff7a1a; opacity: calc(.85 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="supercar"] .r-strut { stroke: #8391a5; stroke-width: 1.3px; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-pipe { fill: #2a313d; stroke: #9aa6b5; stroke-width: .5px; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-wing { fill: #161c26; stroke: var(--tr-a); stroke-width: .6px; stroke-opacity: calc(.45 + .55 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="supercar"] .r-wingTrim { stroke: var(--tr-paint); stroke-width: .8px; }
/* Active aero: the wing sits low (a ducktail) at cruise and rises on its struts with boost; trims its angle at max. */
#ladder-rows .nfx-tr[data-v="supercar"] :is(.r-wing, .r-wingTrim, .r-strut) { transform: translateY(calc(1.7px * (1 - var(--tr-boost, 0)))); }
#ladder-rows .nfx-tr[data-v="supercar"] :is(.r-wing, .r-wingTrim) { transform-box: fill-box; transform-origin: 0 60%;
  transform: translateY(calc(1.7px * (1 - var(--tr-boost, 0)))) rotate(calc(-4deg * var(--tr-max, 0))); }
/* Max: the rim face between the spokes runs red-hot (carbon-ceramic brakes behind the spokes). */
#ladder-rows .nfx-tr[data-v="supercar"] .r-scRim { fill: color-mix(in srgb, #ff4a1c calc(62% * var(--tr-max, 0)), #1b222d); }
/* Boost: two cyan comet arcs ride the tyre edge and turn with the wheel (replaces the plain blur ring). */
#ladder-rows .nfx-tr[data-v="supercar"] .nfx-tr-p.spin::after { inset: -4%; border: 0; border-radius: 50%; opacity: calc(.95 * var(--tr-boost, 0));
  background: conic-gradient(from 290deg, #fff 0deg, var(--tr-a) 12deg, color-mix(in srgb, var(--tr-a) 35%, transparent) 75deg, transparent 135deg 180deg,
    #fff 180deg, var(--tr-a) 192deg, color-mix(in srgb, var(--tr-a) 35%, transparent) 255deg, transparent 315deg);
  -webkit-mask: radial-gradient(closest-side, transparent 70%, #000 74% 97%, transparent 100%); mask: radial-gradient(closest-side, transparent 70%, #000 74% 97%, transparent 100%); }
#ladder-rows .nfx-tr[data-v="supercar"] .r-scSpoke { stroke: #d9e1ea; stroke-width: .9px; opacity: calc(1 - .65 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="supercar"] .r-scLip { stroke: var(--tr-paint); stroke-width: .7px; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-caliper { fill: var(--tr-a); }
#ladder-rows .nfx-tr[data-v="supercar"] .r-flame { fill: #ff3b2a; fill-opacity: .8; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-flameMid { fill: #ff9a1f; }
#ladder-rows .nfx-tr[data-v="supercar"] .r-flameCore { fill: #fff3d6; }
/* Backfire pops only toward the limit. */
#ladder-rows .nfx-tr[data-v="supercar"] .nfx-tr-p.flame { --tr-flame-a: var(--tr-max, 0); }
/* The road under it catches the paint (not a neon kit). */
#ladder-rows .nfx-tr[data-v="supercar"] .nfx-tr-under { background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-paint) 50%, transparent), transparent); }
/* Airflow streaks ramp up the wedge (nose -> windscreen header) from boost on: three phases, one per P/2. */
#ladder-rows .nfx-tr[data-v="supercar"] :is(.r-air1, .r-air2, .r-air3) { stroke: color-mix(in srgb, var(--tr-a) 75%, white); stroke-width: 1.4px; opacity: 0; }
#ladder-rows .nfx-tr[data-v="supercar"] :is(.r-gnd1, .r-gnd2, .r-gnd3) { stroke: #b5f6ff; stroke-width: 2px; opacity: 0; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="supercar"] .r-air1 {
  animation: nfx-tr-supercar-air calc(var(--tr-p, 1s) * 1.5) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="supercar"] .r-air2 {
  animation: nfx-tr-supercar-air calc(var(--tr-p, 1s) * 1.5) linear infinite calc(var(--tr-delay) - var(--tr-p, 1s) * .5); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="supercar"] .r-air3 {
  animation: nfx-tr-supercar-air calc(var(--tr-p, 1s) * 1.5) linear infinite calc(var(--tr-delay) - var(--tr-p, 1s)); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="supercar"] .r-gnd1 {
  animation: nfx-tr-supercar-gnd calc(var(--tr-p, 1s) * 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="supercar"] .r-gnd2 {
  animation: nfx-tr-supercar-gnd calc(var(--tr-p, 1s) * 2) linear infinite calc(var(--tr-delay) - var(--tr-p, 1s) * 2 / 3); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="supercar"] .r-gnd3 {
  animation: nfx-tr-supercar-gnd calc(var(--tr-p, 1s) * 2) linear infinite calc(var(--tr-delay) - var(--tr-p, 1s) * 4 / 3); }
/* Road sweep: 60 units per 2P, about the road speed (roll 29.5 per P); fades in under the nose, out in the wake. */
@keyframes nfx-tr-supercar-gnd { 0% { opacity: 0; transform: translateX(0); } 14%, 70% { opacity: calc(.95 * var(--tr-boost, 0)); } 100% { opacity: 0; transform: translateX(60px); } }
@keyframes nfx-tr-supercar-air { 0% { opacity: 0; transform: translate(0, 0); } 18%, 72% { opacity: calc(.9 * var(--tr-boost, 0)); } 100% { opacity: 0; transform: translate(29px, -8.9px); } }
@media (max-width: 720px) {
  /* Phones: a quiet silhouette (body, glass, lamps, tyres, wing); no fine lines or streaks at 25px. */
  #ladder-rows .nfx-tr[data-v="supercar"] :is(.r-air1, .r-air2, .r-air3, .r-vane, .r-crease, .r-glint, .r-caliper, .r-scSpoke, .r-scLip, .r-strut, .r-seam, .r-wingTrim, .r-pillar, .r-edge, .r-gnd1, .r-gnd2, .r-gnd3) { display: none; }
  #ladder-rows .nfx-tr[data-v="supercar"] .nfx-tr-p.spin::after { display: none; }
  #ladder-rows .nfx-tr[data-v="supercar"] .r-wing { stroke: none; }
}
/* raceCar (方程式赛车) */
#ladder-rows .nfx-tr[data-v="raceCar"] .r-wingPlate { fill: var(--tr-paint2); stroke: var(--tr-a); stroke-width: .8px; stroke-opacity: .8; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-flank { fill: var(--tr-flank); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-floorEdge { stroke: var(--tr-a); stroke-width: .6px; opacity: .45; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-hi { stroke: #ecfeff; stroke-width: .7px; opacity: .7; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-rain { fill: var(--tr-rain); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-rainHalo { fill: var(--tr-rain); opacity: .35; }

#ladder-rows .nfx-tr[data-v="raceCar"] .r-wing { fill: var(--tr-paint2); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-wingEdge { stroke: var(--tr-a); stroke-width: .9px; opacity: calc(.6 + .4 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-arm { stroke: #64748b; stroke-width: .7px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-halo { stroke: var(--tr-metal); stroke-width: 1.5px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-helmetStripe { stroke: var(--tr-stripe); stroke-width: .9px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-drs { fill: var(--tr-paint); stroke: var(--tr-stripe); stroke-width: .7px;
  transform-box: fill-box; transform-origin: 100% 0; transform: rotate(calc(24deg * var(--tr-max, 0))); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-drsSlot { stroke: #ecfeff; stroke-width: 1.4px; opacity: var(--tr-max, 0); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-compound { stroke: var(--tr-compound); stroke-width: 1.1px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-logo { stroke: #f8fafc; stroke-width: 1.2px; stroke-linecap: butt; opacity: calc(.95 - .55 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-rimF1 { fill: #111a27; stroke: var(--tr-paint); stroke-width: .7px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-spokeF1 { stroke: var(--tr-a); stroke-width: .7px; opacity: calc(.7 - .45 * var(--tr-blur, 0)); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-nut { fill: var(--tr-b); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-vortex { fill: rgba(236, 254, 255, .75); }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.shock { transform-origin: 0 50%; }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.flame { --tr-flame-a: calc(.2 + .8 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-rimArc { fill: #f0fdff; stroke: var(--tr-a); stroke-width: .6px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-rimArc2 { fill: var(--tr-a); opacity: .8; }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-rimArc) { --tr-glow-a: var(--tr-boost, 0); opacity: var(--tr-boost, 0); }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-roadSheen) { overflow: hidden; opacity: var(--tr-boost, 0); border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--tr-a) 80%, transparent), color-mix(in srgb, var(--tr-a) 28%, transparent) 60%, transparent);
  -webkit-mask: linear-gradient(90deg, transparent, #000 18% 82%, transparent); mask: linear-gradient(90deg, transparent, #000 18% 82%, transparent); }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-roadSheen)::before { content: ""; position: absolute; top: calc(50% - 1px); height: 2px; right: 0; left: calc(-1 * var(--tr-flow) * var(--tr-U));
  background: repeating-linear-gradient(90deg, #ffffff 0 calc(var(--tr-flow) * var(--tr-U) * .35), transparent 0 calc(var(--tr-flow) * var(--tr-U))); box-shadow: 0 0 3px var(--tr-a); }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.shock:has(.r-heat) { border-radius: 50%; transform-origin: 20% 50%;
  background: radial-gradient(closest-side at 20% 50%, var(--tr-core), color-mix(in srgb, var(--tr-b) 95%, transparent) 24%, color-mix(in srgb, var(--tr-b) 58%, transparent) 50%, color-mix(in srgb, var(--tr-b) 18%, transparent) 76%, transparent); }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-spark { width: 6px; height: 2px; margin: -1px 0 0 -3px; border-radius: 1px; background: #ffd27a; box-shadow: 0 0 4px var(--tr-b), 0 0 1px #fff; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-rimArc) {
  animation: nfx-tr-rc-rim calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-roadSheen) {
  animation: none; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-roadSheen)::before {
  animation: nfx-tr-flow calc(var(--tr-p, 1s) / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.shock:has(.r-heat) {
  animation: nfx-tr-rc-heat calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-tr-rc-rim { 0%, 100% { opacity: var(--tr-boost, 0); } 50% { opacity: calc(.7 * var(--tr-boost, 0)); } }
@keyframes nfx-tr-rc-heat { 0%, 100% { opacity: var(--tr-max, 0); transform: scale(1.12, 1); } 50% { opacity: calc(.7 * var(--tr-max, 0)); transform: scale(.92, .9); } }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-sheen { fill: #ffffff; opacity: .22; }
#ladder-rows .nfx-tr[data-v="raceCar"] .r-ers { stroke: var(--tr-core); stroke-width: 1.4px; }
#ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-ers) { opacity: 0; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-ers) {
  animation: nfx-tr-rc-ers calc(var(--tr-p, 1s) * 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:has(.r-rain) {
  animation: nfx-tr-glow calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-tr-rc-ers { 0% { opacity: 0; transform: translate(0, 0); } 12% { opacity: calc(.95 * var(--tr-boost, 0)); } 55% { opacity: calc(.8 * var(--tr-boost, 0)); transform: translate(78%, -42%); } 62%, 100% { opacity: 0; transform: translate(84%, -45%); } }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="raceCar"] .nfx-tr-p.shock:has(.r-vortex) {
  animation: nfx-tr-rc-vortex calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-tr-rc-vortex { 0%, 100% { opacity: var(--tr-max, 0); transform: scaleX(1); } 50% { opacity: calc(.55 * var(--tr-max, 0)); transform: scaleX(.82); } }
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="raceCar"] :is(.r-edge, .r-wingEdge, .r-glint, .r-logo, .r-arm, .r-helmetStripe, .r-drsSlot, .r-spokeF1, .r-halo, .r-hi, .r-floorEdge, .r-rainHalo) { display: none; }
  #ladder-rows .nfx-tr[data-v="raceCar"] .r-compound { stroke-width: .7px; }
  #ladder-rows .nfx-tr[data-v="raceCar"] .r-wingPlate { stroke: none; }
  #ladder-rows .nfx-tr[data-v="raceCar"] .r-drs { stroke: none; }
  #ladder-rows .nfx-tr[data-v="raceCar"] :is(.r-sheen, .r-ers) { display: none; }
  #ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.shock { display: none; }
  #ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:is(:has(.r-rimArc), :has(.r-roadSheen)) { display: none; }
}
@media (pointer: coarse) and (max-height: 720px) {
  #ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.shock, #ladder-rows .nfx-tr[data-v="raceCar"] .nfx-tr-p.glow:is(:has(.r-rimArc), :has(.r-roadSheen), :has(.r-ers)) { display: none; }
}
/* bulletTrain (高铁) */
/* bulletTrain (高铁) v3: pearl body, cobalt swoosh, light sweep, rail light pool, pantograph arc at max. */
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-gloss { fill: #fff; opacity: .9; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-pin { stroke: var(--tr-a); stroke-width: .8px; opacity: calc(.45 + .55 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-cabin { stroke: var(--tr-a); stroke-width: .9px; opacity: calc(.25 + .6 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-mullion { stroke: var(--tr-paint); stroke-width: .6px; opacity: .3; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-seam { stroke: rgba(40, 60, 110, .32); }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-bandHot { fill: #4f8dff; opacity: calc(.7 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-bandLit { stroke: #dff1ff; stroke-width: .9px; opacity: calc(.15 + .85 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-sheenSoft { fill: #dbeafe; opacity: .16; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-sheen { fill: #fff; opacity: .3; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-sheenCore { fill: #fff; opacity: calc(.4 + .6 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-arc { fill: var(--tr-core); stroke: var(--tr-b); stroke-width: .8px; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-bow { stroke: var(--tr-a); stroke-width: 1px; opacity: .7; }
#ladder-rows .nfx-tr[data-v="bulletTrain"] .r-bowFar { stroke: var(--tr-a); stroke-width: .8px; opacity: .35; }
/* The train runs on past the box's right edge: its body fades into the light wake. */
#ladder-rows .nfx-tr[data-v="bulletTrain"] .nfx-tr-p.still { -webkit-mask: linear-gradient(to left, transparent, #000 9%); mask: linear-gradient(to left, transparent, #000 9%); }
/* The light sweep: clipped to the body silhouette; brighter with --tr-boost. */
#ladder-rows .nfx-tr[data-v="bulletTrain"] .nfx-tr-p.shock { opacity: calc(.3 + .6 * var(--tr-boost, 0)); clip-path: polygon(0.26% 86.23%, 0.74% 81.89%, 1.65% 77.56%, 3.02% 73.28%, 4.84% 69.06%, 7.12% 64.91%, 9.87% 60.87%, 12.99% 56.45%, 15.87% 51.83%, 18.54% 46.92%, 21.01% 41.65%, 23.31% 35.94%, 25.45% 29.71%, 27.43% 23.59%, 29.51% 17.74%, 31.75% 12.41%, 34.21% 7.86%, 36.94% 4.36%, 40% 2.17%, 100% 1.45%, 100% 98.55%, 14.29% 98.55%, 4.68% 97.46%, 0.91% 92.75%); }
/* Max-only effects (arc and bow wave) pulse on the glow clock, gated by --tr-max. */
#ladder-rows .nfx-tr[data-v="bulletTrain"] .nfx-tr-p.glow { --tr-glow-a: var(--tr-max, 0); opacity: var(--tr-glow-a); }
/* Rail: a brighter running rail with a gleam per sleeper pitch. */
#ladder-rows .nfx-tr[data-v="bulletTrain"][data-g="rail"]::after { opacity: calc(.5 + .35 * var(--tr-boost, 0));
  background: repeating-linear-gradient(90deg, #cfe0ff 0 calc(var(--tr-flow) * var(--tr-U) * .18), #8ea3c4 0 calc(var(--tr-flow) * var(--tr-U))) 0 0 / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, #5b6b86 0 1.5px, transparent 0 calc(var(--tr-flow) * var(--tr-U))) 0 1px / 100% 2px no-repeat; }
/* Wake: the train continues as speed-blurred light (window lights over the cobalt band). */
#ladder-rows .nfx-tr[data-v="bulletTrain"][data-f="rail"] .nfx-tr-trail { -webkit-mask: linear-gradient(transparent, #000 10% 90%, transparent); mask: linear-gradient(transparent, #000 10% 90%, transparent); }
#ladder-rows .nfx-tr[data-v="bulletTrain"][data-f="rail"] .nfx-tr-trail::before {
  background: linear-gradient(var(--tr-streak), var(--tr-streak)) 0 4% / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, var(--tr-streak) 0 calc(var(--tr-flow) * var(--tr-U) * .78), transparent 0 calc(var(--tr-flow) * var(--tr-U))) 0 20% / 100% 11% no-repeat,
    repeating-linear-gradient(90deg, var(--tr-bt-band) 0 calc(var(--tr-flow) * var(--tr-U) * .93), transparent 0 calc(var(--tr-flow) * var(--tr-U))) 0 74% / 100% 15% no-repeat,
    linear-gradient(var(--tr-a), var(--tr-a)) 0 93% / 100% 1px no-repeat;
  -webkit-mask: linear-gradient(to right, #000 15%, transparent 95%); mask: linear-gradient(to right, #000 15%, transparent 95%); }
#ladder-rows .nfx-tr[data-v="bulletTrain"][data-f="rail"] .nfx-tr-trail::after { inset: 45% 0; background: linear-gradient(to right, var(--tr-core), var(--tr-a) 30%, transparent 80%); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="bulletTrain"] .nfx-tr-p.shock > svg { animation: nfx-tr-bullet-sheen calc(var(--tr-p, 1s) * 4) linear infinite var(--tr-delay); }
@keyframes nfx-tr-bullet-sheen { 0% { transform: translateX(0); opacity: 0; } 6% { opacity: 1; } 60% { opacity: 1; } 74%, 100% { transform: translateX(122%); opacity: 0; } }
/* Phones: a quiet silhouette (pearl body, cobalt swoosh, windows, lamp); no sweep, arc, wheels or fine lines. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="bulletTrain"] :is(.nfx-tr-p.shock, .nfx-tr-p.glow, .nfx-tr-p.spin) { display: none; }
  #ladder-rows .nfx-tr[data-v="bulletTrain"] :is(.r-gloss, .r-glint, .r-cabin, .r-mullion, .r-seam, .r-pin, .r-chrome, .r-edge, .r-metal, .r-bandLit) { display: none; }
}
/* maglev (磁浮列车) */
/* 磁浮 maglev v4: a silver train with a rounded high-speed nose, floating over a lit guideway. Scoped to .nfx-tr[data-v="maglev"];
   new roles r-mg*; keyframes nfx-tr-mg-*; animations only under the shared RUN gate, on --tr-p / --tr-delay. */
#ladder-rows .nfx-tr[data-v="maglev"] { --tr-paint: #e9eef4; --tr-paint2: #b7c2d1; --tr-shade: #63738b; --tr-metal: #ffffff; --tr-glass: #08111f;
  --tr-a: #4ee6f7; --tr-b: #f5c451; --tr-lamp: #eafcff; --tr-core: #fff6d8; --tr-stripe: #16c4e6; --tr-hot-k: .5;
  --tr-mg-skirt: #141d2b; --tr-mg-gold: #e9b949;
  --tr-wake: color-mix(in srgb, var(--tr-a) 22%, transparent); --tr-streak: color-mix(in srgb, var(--tr-a) 40%, white);
  --tr-glow: color-mix(in srgb, var(--tr-a) 26%, transparent); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgSkirt { fill: var(--tr-mg-skirt); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-metal { opacity: .92; }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgLight { stroke: color-mix(in srgb, var(--tr-a) 35%, white); stroke-width: .9px; opacity: calc(.3 + .7 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgGold { stroke: var(--tr-mg-gold); stroke-width: .7px; opacity: calc(.45 + .55 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgLip { stroke: var(--tr-a); stroke-width: .8px; opacity: calc(.55 + .45 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-seam { stroke: rgba(30, 41, 59, .45); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-glint { opacity: .8; }
#ladder-rows .nfx-tr[data-v="maglev"] .r-edge { stroke-width: .8px; opacity: calc(.35 + .45 * var(--tr-boost, 0)); }
/* The train runs on past the right edge: its next car fades into the wake. */
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-p.still > svg {
  -webkit-mask: linear-gradient(to right, #000 87%, rgba(0, 0, 0, .18)); mask: linear-gradient(to right, #000 87%, rgba(0, 0, 0, .18)); }
/* The levitation gap: a soft cyan field, a brighter inner band, the core line, white-gold at the limit (static glow). */
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-v > .nfx-tr-p.glow:first-child > svg { filter: drop-shadow(0 0 1.2px var(--tr-a)); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgGap { fill: color-mix(in srgb, var(--tr-a) 16%, transparent); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgGapIn { fill: color-mix(in srgb, var(--tr-a) 48%, transparent); }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgGapCore { stroke: color-mix(in srgb, var(--tr-a) 70%, white); stroke-width: 1.1px; }
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgGapHot { stroke: var(--tr-core); stroke-width: 1.3px; opacity: var(--tr-max, 0); }
/* Window reflections (they run back along the band; faint at cruise, full from boost). */
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgSheen { fill: #fff; opacity: 0; }
/* The bow pressure wave ahead of the nose: only at the limit (k: opacity --tr-max). */
#ladder-rows .nfx-tr[data-v="maglev"] .r-mgBow { stroke: var(--tr-a); stroke-width: .9px; opacity: .85; transform-box: fill-box; transform-origin: 100% 50%; }
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-p.shock { opacity: calc(.9 * var(--tr-max, 0)); }
/* The guideway: a static beam under the coils (only the coils move, in the u part below). */
#ladder-rows .nfx-tr[data-v="maglev"][data-g]::after { height: calc(var(--tr-U) * .3); margin-top: 0; left: -8%; right: -34%; opacity: .95;
  background: linear-gradient(color-mix(in srgb, var(--tr-a) 40%, #cbd5e1) 0 1px, #2b3a4f 1px, #182338 45%, transparent);
  -webkit-mask: linear-gradient(to right, transparent, #000 12% 72%, transparent); mask: linear-gradient(to right, transparent, #000 12% 72%, transparent); }
/* The lit stator coils (the u part): packs flowing right at ground speed (one per flow), bright under the car,
   an afterglow behind it; gold-white over cyan with --tr-max. */
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-under { border-radius: 0; overflow: hidden; opacity: calc(.6 + .4 * var(--tr-boost, 0));
  background: radial-gradient(48% 46% at 42% 30%, color-mix(in srgb, var(--tr-a) 32%, transparent), transparent);
  -webkit-mask: linear-gradient(to right, transparent, #000 9% 62%, rgba(0, 0, 0, .5) 77%, transparent);
  mask: linear-gradient(to right, transparent, #000 9% 62%, rgba(0, 0, 0, .5) 77%, transparent); }
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-under::before, #ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-under::after { content: "";
  position: absolute; top: 30%; height: 40%; right: 0; left: calc(-1 * var(--tr-flow, 1) * var(--tr-U));
  background: repeating-linear-gradient(90deg, var(--tr-a) 0 calc(var(--tr-flow, 1) * var(--tr-U) * .44), transparent 0 calc(var(--tr-flow, 1) * var(--tr-U)));
  -webkit-mask: linear-gradient(transparent, rgba(0, 0, 0, .35) 15%, #000 30% 70%, rgba(0, 0, 0, .35) 85%, transparent);
  mask: linear-gradient(transparent, rgba(0, 0, 0, .35) 15%, #000 30% 70%, rgba(0, 0, 0, .35) 85%, transparent); }
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-under::after { opacity: var(--tr-max, 0);
  background: repeating-linear-gradient(90deg, var(--tr-core) 0 calc(var(--tr-flow, 1) * var(--tr-U) * .18), var(--tr-b) 0 calc(var(--tr-flow, 1) * var(--tr-U) * .44), transparent 0 calc(var(--tr-flow, 1) * var(--tr-U))); }
/* The wake: a laminar slipstream, three thin lines and a thin cyan-white filament (no heat). */
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-trail::before {
  -webkit-mask: repeating-linear-gradient(transparent 0 15%, #000 15% 21%, transparent 21% 33.34%); mask: repeating-linear-gradient(transparent 0 15%, #000 15% 21%, transparent 21% 33.34%); }
#ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-trail::after { inset: 46% 0; background: linear-gradient(to right, var(--tr-core), var(--tr-a) 30%, transparent 85%); }

.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="maglev"] .nfx-tr-p.glow {
  animation: nfx-tr-mg-hum calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="maglev"][data-g]::after {
  animation: none; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="maglev"] .nfx-tr-under::before,
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="maglev"] .nfx-tr-under::after {
  animation: nfx-tr-flow calc(var(--tr-p, 1s) / var(--tr-flow-n, 1)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="maglev"] .r-mgSheen {
  animation: nfx-tr-mg-sheen calc(var(--tr-p, 1s) * 4) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="maglev"] .r-mgBow {
  animation: nfx-tr-mg-bow calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-tr-mg-hum { 0%, 100% { opacity: var(--tr-glow-a, 1); } 50% { opacity: calc(.8 * var(--tr-glow-a, 1)); } }
@keyframes nfx-tr-mg-sheen { 0% { transform: translateX(0); opacity: 0; } 7%, 43% { opacity: calc(.15 + .75 * var(--tr-boost, 0)); }
  50%, 100% { transform: translateX(24.5px); opacity: 0; } }
@keyframes nfx-tr-mg-bow { 0%, 100% { transform: scale(.9); } 50% { transform: scale(1.08); } }

@media (max-width: 720px) {
  /* Phones: a quiet silver sliver, its window line, cyan stripe and gap line; no fine detail or extras. */
  #ladder-rows .nfx-tr[data-v="maglev"] :is(.r-glint, .r-seam, .r-mgGold, .r-mgLight, .r-metal, .r-mgSheen, .r-mgLip, .r-mgGap) { display: none; }
  #ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-p.shock { display: none; }
  #ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-p.still > svg, #ladder-rows .nfx-tr[data-v="maglev"] .nfx-tr-v > .nfx-tr-p.glow:first-child > svg { -webkit-mask: none; mask: none; filter: none; }
  #ladder-rows .nfx-tr[data-v="maglev"][data-g]::after { height: 1px; right: -20%; background: color-mix(in srgb, var(--tr-a) 55%, #475569); }
}
/* jetliner (客机) */
/* 客机 jetliner v3: platinum fuselage, deep-blue fin and nacelle, ice-blue contrail. Scoped to [data-v="jetliner"]. */
#ladder-rows .nfx-tr[data-v="jetliner"] { --tr-paint: #eef2f6; --tr-paint2: #1e3a8a; --tr-shade: #7f8da3; --tr-metal: #e2e8f0; --tr-glass: #13254d;
  --tr-a: #bae6fd; --tr-b: #f43f5e; --tr-lamp: #f8fafc; --tr-core: #f0f9ff; --tr-stripe: #2563eb;
  --tr-wake: rgba(224, 242, 254, .5); --tr-streak: rgba(240, 249, 255, .92); --tr-hot-k: 0; --tr-flick-n: 1;
  --jl-far: #6b7a93; --jl-mid: #c5cedb; --jl-wing: #d2dae5; --jl-navy: #172554;
  --jl-con: rgba(232, 246, 255, .82); --jl-con-far: rgba(186, 230, 253, .46); }
/* Roles added by this vehicle. */
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlFar { fill: var(--jl-far); }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlMid { fill: var(--jl-mid); }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlWing { fill: var(--jl-wing); }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlNavy { fill: var(--jl-navy); }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlSheen { stroke: #fff; stroke-width: .9px; opacity: .85; }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlArc { stroke: var(--tr-a); stroke-width: 1px; opacity: calc(.75 + .25 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlHeat { fill: rgba(232, 246, 255, .42); }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-jlVortex { stroke: rgba(240, 249, 255, .85); stroke-width: .8px; }
/* Existing roles, tuned: dark windows without the glass rim, the intake lip as a bright ring. */
#ladder-rows .nfx-tr[data-v="jetliner"] .r-glass { stroke: none; }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-chrome { stroke-width: 1.1px; }
#ladder-rows .nfx-tr[data-v="jetliner"] .r-seam { stroke: rgba(15, 23, 42, .35); stroke-width: .5px; }
/* Light halos (box backgrounds; the dots themselves are the paths). */
#ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-p.glow:has(.r-tail) { border-radius: 50%; background: radial-gradient(closest-side, rgba(244, 63, 94, .7), rgba(244, 63, 94, .18) 50%, transparent); }
#ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-p.glow:has(.r-lamp) { border-radius: 50%; background: radial-gradient(closest-side, rgba(255, 255, 255, .7), rgba(186, 230, 253, .25) 55%, transparent); }
/* Contrail: two condensation lines (near engine centre, far engine above it), clear for the first eighth (the
   hot exhaust has not condensed yet), fading at the tip; puffs flow aft instead of speed lines. */
#ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-trail {
  background: linear-gradient(to bottom, transparent 14%, var(--jl-con-far) 24%, transparent 34%),
    linear-gradient(to bottom, transparent 39%, var(--jl-con) 51%, transparent 65%);
  -webkit-mask: linear-gradient(to right, transparent 0, #000 12%, #000 55%, transparent);
  mask: linear-gradient(to right, transparent 0, #000 12%, #000 55%, transparent); }
#ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-trail::before { opacity: calc(.35 + .65 * var(--tr-boost, 0));
  background:
    radial-gradient(closest-side, var(--tr-streak), transparent) 0 51% / calc(var(--tr-flow) * var(--tr-U) * .5) 26% repeat-x,
    radial-gradient(closest-side, color-mix(in srgb, var(--tr-streak) 55%, transparent), transparent) calc(var(--tr-flow) * var(--tr-U) * .25) 22% / calc(var(--tr-flow) * var(--tr-U) * .5) 16% repeat-x;
  -webkit-mask: none; mask: none; }
/* At its limit the contrail hardens: a crisp white persistent core along the near line. */
#ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-trail::after { inset: 48% 0 46% 0; opacity: calc(.12 + .7 * var(--tr-max, 0));
  background: linear-gradient(to right, transparent 3%, #fff 14%, rgba(224, 242, 254, .6) 48%, transparent 90%); }
/* The aura (limit / arrival flash) in ice, not the red of the beacon. */
#ladder-rows .nfx-tr[data-v="jetliner"]::before { background: radial-gradient(closest-side, rgba(186, 230, 253, .34), rgba(186, 230, 253, .1) 60%, transparent); }
/* Vapour and vortex: only at the limit (the shock role's --tr-max), softly. */
#ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-p.shock { opacity: calc(.85 * var(--tr-max, 0)); }
/* Running (the same gates as every vehicle): beacon blink once per 2P, a soft double strobe between, the vortex
   streak shedding aft, the vapour breathing. Transform and opacity only. */
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="jetliner"] .nfx-tr-p.glow:has(.r-tail) { animation: jl-beacon calc(var(--tr-p, 1s) * 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="jetliner"] .nfx-tr-p.glow:has(.r-lamp) { animation: jl-strobe calc(var(--tr-p, 1s) * 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="jetliner"] .nfx-tr-p.shock:has(.r-jlVortex) { animation: jl-vortex calc(var(--tr-p, 1s) / 2) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="jetliner"] .nfx-tr-p.shock:has(.r-jlHeat) { animation: jl-vapour var(--tr-p, 1s) ease-in-out infinite var(--tr-delay); }
@keyframes jl-beacon { 0%, 100% { opacity: .12; } 4% { opacity: 1; } 18% { opacity: .12; } }
@keyframes jl-strobe { 0%, 40% { opacity: 0; } 42% { opacity: .9; } 46% { opacity: 0; } 52% { opacity: .75; } 56%, 100% { opacity: 0; } }
@keyframes jl-vortex { 0% { opacity: calc(.85 * var(--tr-max, 0)); transform: translateX(0); } 100% { opacity: calc(.25 * var(--tr-max, 0)); transform: translateX(calc(var(--tr-U) * .5)); } }
@keyframes jl-vapour { 0%, 100% { opacity: calc(.85 * var(--tr-max, 0)); } 50% { opacity: calc(.5 * var(--tr-max, 0)); } }
/* Phones: a quiet silhouette (body, fin, wing, nacelle) and one contrail line; no windows, logo, far wing or lights. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="jetliner"] { --tr-paint2: #2f5fd6; --jl-navy: #1e3a8a; }
  #ladder-rows .nfx-tr[data-v="jetliner"] :is(.r-glass, .r-glint, .r-seam, .r-jlArc, .r-jlSheen, .r-stripeFill, .r-chrome, .r-jlFar, .r-tail, .r-edge) { display: none; }
  #ladder-rows .nfx-tr[data-v="jetliner"] :is(.nfx-tr-p.glow, .nfx-tr-p.shock, .nfx-tr-p.flame) { display: none; }
  #ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-trail { background: linear-gradient(to bottom, transparent 20%, var(--jl-con) 50%, transparent 80%); }
  #ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-trail::before, #ladder-rows .nfx-tr[data-v="jetliner"] .nfx-tr-trail::after { content: none; }
}
/* fighterJet (战斗机) */
#ladder-rows .nfx-tr[data-v="fighterJet"] { --tr-paint: #6a7c93; --tr-paint2: #3d495b; --tr-shade: #2c3545; --tr-metal: #c3cfdc; --tr-glass: rgba(251, 191, 36, .8);
  --tr-canopy: #e8a51f; --tr-a: #7dd3fc; --tr-b: #fb923c; --tr-lamp: #fff4c2; --tr-core: #eef6ff; --tr-stripe: #fbbf24;
  --tr-fj-sheen: #93a6bc; --tr-fj-canopy-hi: #ffe08a; --tr-fj-ab: #4f9dff; --tr-fj-vapor: #e0f2fe;
  --tr-wake: rgba(125, 180, 255, .26); --tr-streak: rgba(224, 242, 254, .9); --tr-glow: color-mix(in srgb, #7dd3fc 45%, transparent); --tr-hot-k: 0.95; --tr-flick-n: 2; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-sheen { fill: var(--tr-fj-sheen); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-canopy { fill: var(--tr-canopy); stroke: #7c5410; stroke-width: .6px; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-canopyLo { fill: #8a5a10; opacity: .55; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-abSpill { fill: var(--tr-b); opacity: calc(.1 * var(--tr-boost, 0) + .3 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-canopyHi { fill: var(--tr-fj-canopy-hi); opacity: .85; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-edge2 { stroke: var(--tr-a); stroke-width: .8px; opacity: calc(.25 + .35 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-stripe { stroke-width: .8px; opacity: .75; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-heat { stroke: var(--tr-b); stroke-width: 1.3px; opacity: calc(.35 + .65 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .nfx-tr-p.flame { --tr-flame-a: calc(.8 + .2 * var(--tr-boost, 0)); transform: scale(calc((.6 + .8 * var(--tr-u, 0)) * var(--tr-fj-fk, 1)), 1); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-flame { fill: var(--tr-b); fill-opacity: .8; opacity: calc(.12 + .88 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-abBlue { fill: var(--tr-fj-ab); fill-opacity: .85; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-flameCore { fill: var(--tr-core); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-shock { fill: #fffbeb; stroke: #fde68a; stroke-width: .5px; opacity: var(--tr-max, 0); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .nfx-tr-p.glow { --tr-glow-a: 1; transform-origin: 0 50%; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .nfx-tr-p.glow ~ .nfx-tr-p.glow { transform-origin: 50% 50%; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-bloom { fill: var(--tr-b); fill-opacity: .2; opacity: calc(.15 + .45 * var(--tr-boost, 0) + .4 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-vortex { fill: #f0f9ff; opacity: calc(.75 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="fighterJet"] .nfx-tr-p.shock { transform-origin: 1% 47%; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-vapor { fill: var(--tr-fj-vapor); fill-opacity: .16; }
#ladder-rows .nfx-tr[data-v="fighterJet"] .r-vaporRim { fill: #f8fbff; fill-opacity: .55; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="fighterJet"] .nfx-tr-p.flame { animation-name: nfx-fj-burn; animation-timing-function: linear; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="fighterJet"] .nfx-tr-p.glow { animation: nfx-fj-vortex calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="fighterJet"] .nfx-tr-p.glow ~ .nfx-tr-p.glow { animation: nfx-fj-thump calc(var(--tr-p, 1s) / var(--tr-beats, 1)) linear infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="fighterJet"] .nfx-tr-p.shock { animation: nfx-fj-vapor calc(var(--tr-p, 1s) * 4) ease-in-out infinite var(--tr-delay); }
@keyframes nfx-fj-burn {
  0%, 100% { opacity: var(--tr-flame-a, 1); transform: scale(calc((.6 + .8 * var(--tr-u, 0)) * var(--tr-fj-fk, 1)), 1); }
  25% { opacity: calc(.9 * var(--tr-flame-a, 1)); transform: scale(calc((.6 + .8 * var(--tr-u, 0)) * var(--tr-fj-fk, 1) * .9), .95); }
  50% { opacity: calc(.97 * var(--tr-flame-a, 1)); transform: scale(calc((.6 + .8 * var(--tr-u, 0)) * var(--tr-fj-fk, 1) * .97), 1.04); }
  75% { opacity: calc(.88 * var(--tr-flame-a, 1)); transform: scale(calc((.6 + .8 * var(--tr-u, 0)) * var(--tr-fj-fk, 1) * .87), .97); } }
@keyframes nfx-fj-thump { 0%, 100% { opacity: 1; transform: scale(1.1); } 25% { opacity: .82; transform: scale(1); } 50% { opacity: .72; transform: scale(.94); } 75% { opacity: .82; transform: scale(1); } }
@keyframes nfx-fj-vortex { 0%, 100% { opacity: 1; transform: scaleX(1); } 50% { opacity: .7; transform: scaleX(.86); } }
@keyframes nfx-fj-vapor { 0%, 100% { opacity: var(--tr-max, 0); transform: scale(1); } 50% { opacity: calc(.75 * var(--tr-max, 0)); transform: scale(1.035, 1.05); } }
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="fighterJet"] :is(.r-seam, .r-glint, .r-edge, .r-edge2, .r-stripe, .r-canopyHi, .r-canopyLo, .r-metalLine, .r-heat, .r-shock, .r-abSpill) { display: none; }
  #ladder-rows .nfx-tr[data-v="fighterJet"] { --tr-fj-fk: .5; }
  #ladder-rows .nfx-tr[data-v="fighterJet"] :is(.nfx-tr-p.glow, .nfx-tr-p.shock) { display: none; }
  #ladder-rows .nfx-tr[data-v="fighterJet"] .r-canopy { stroke: none; } }
/* x15 (X-15 试验机) */
/* X-15 v3: black Inconel-X / titanium rocket plane, orange-gold livery, violet-white XLR99 plume. Scoped to [data-v="x15"]. */
#ladder-rows .nfx-tr[data-v="x15"] { --tr-paint: #181d27; --tr-paint2: #262d3a; --tr-shade: #07090d; --tr-metal: #a9b2bf; --tr-glass: #182134;
  --tr-a: #c4b5fd; --tr-b: #8b5cf6; --tr-core: #faf5ff; --tr-lamp: #fde68a; --tr-stripe: #fbbf24;
  --tr-wake: rgba(196, 181, 253, .32); --tr-streak: rgba(237, 233, 254, .9); --tr-glow: rgba(167, 139, 250, .55);
  --tr-hot-k: 1; --tr-flick-n: 1;
  --x15-top: #3a4355; --x15-wing: #353e50; --x15-gold: #fbbf24; --x15-orange: #f97316; --x15-hot: #fb923c; --x15-plume: #ddd6fe; }
/* Roles added by this vehicle. */
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Top { fill: var(--x15-top); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Wing { fill: var(--x15-wing); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Gold { fill: var(--x15-gold); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Orange { fill: var(--x15-orange); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Panel { stroke: rgba(203, 213, 225, .26); stroke-width: .5px; }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15LE { stroke: #e2e8f0; stroke-width: .9px; opacity: .7; }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Hot { stroke: var(--x15-hot); stroke-width: 1.3px; opacity: calc(.9 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15RimLow { stroke: var(--tr-a); stroke-width: .7px; opacity: calc(.3 + .25 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Throat { stroke: var(--x15-plume); stroke-width: 1.4px; opacity: calc(.45 + .55 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Plume { fill: var(--x15-plume); fill-opacity: .8; }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Heat { fill: var(--x15-hot); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Sheen { stroke: #fff; stroke-width: 1.1px; }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15ConeFill { fill: rgba(196, 181, 253, .13); }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Cone { stroke: #ede9fe; stroke-width: .9px; opacity: .85; }
#ladder-rows .nfx-tr[data-v="x15"] .r-x15Cone2 { stroke: var(--tr-a); stroke-width: .6px; opacity: .45; }
#ladder-rows .nfx-tr[data-v="x15"] .r-glass { stroke: color-mix(in srgb, var(--tr-a) 70%, transparent); stroke-width: .6px; }
#ladder-rows .nfx-tr[data-v="x15"] .r-edge { stroke-width: 1.1px; }
#ladder-rows .nfx-tr[data-v="x15"] .r-shock { stroke-width: .7px; }
/* Bow shock: max only (reference shock gate), fading aft. Nose heat: max only, a slow glow, never a strobe. */
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p.shock:has(.r-x15Cone) { transform-origin: 1% 51%;
  -webkit-mask: linear-gradient(to right, #000 30%, transparent 98%); mask: linear-gradient(to right, #000 30%, transparent 98%); }
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p.glow:has(.r-x15Heat) { --tr-glow-a: var(--tr-max, 0); opacity: var(--tr-glow-a); border-radius: 50%;
  background: radial-gradient(closest-side at 22% 50%, rgba(253, 186, 116, .85), rgba(249, 115, 22, .32) 45%, transparent); }
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p.glow:has(.r-x15Sheen) { overflow: hidden; opacity: calc(.3 + .7 * var(--tr-boost, 0)); }
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p.glow:has(.r-x15Sheen) > svg { opacity: 0; }
/* The XLR99 burns all the time: the plume is lit at cruise and brightens with max; a soft violet halo rides with it. */
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p.flame { --tr-flame-a: calc(.72 + .28 * var(--tr-max, 0));
  background: radial-gradient(closest-side at 30% 50%, rgba(167, 139, 250, calc(.22 + .26 * var(--tr-boost, 0))), transparent); }
/* The wake: a hot violet jet (white at the nozzle), two thin streak lines (not bars), the reference hot core. */
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-trail { background: linear-gradient(to right, rgba(237, 233, 254, .55), rgba(139, 92, 246, .38) 28%, rgba(139, 92, 246, .12) 68%, transparent); }
#ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-trail::before { background: repeating-linear-gradient(90deg, transparent 0, var(--tr-streak) calc(var(--tr-flow) * var(--tr-U) * .12),
    transparent calc(var(--tr-flow) * var(--tr-U) * .62), transparent calc(var(--tr-flow) * var(--tr-U)));
  -webkit-mask: linear-gradient(transparent 0 25%, #000 25% 33%, transparent 33% 67%, #000 67% 75%, transparent 75%);
  mask: linear-gradient(transparent 0 25%, #000 25% 33%, transparent 33% 67%, #000 67% 75%, transparent 75%); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="x15"] .nfx-tr-p.shock:has(.r-x15Cone) { animation: x15-cone calc(var(--tr-p, 1s) * 4) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="x15"] .nfx-tr-p.glow:has(.r-x15Heat) { animation: x15-heat calc(var(--tr-p, 1s) * 8) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="x15"] .nfx-tr-p.glow:has(.r-x15Sheen) { animation: none; }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="x15"] .nfx-tr-p.glow:has(.r-x15Sheen) > svg { animation: x15-sheen calc(var(--tr-p, 1s) * 12) linear infinite var(--tr-delay); }
@keyframes x15-cone { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.025, 1.05); } }
@keyframes x15-heat { 0%, 100% { opacity: var(--tr-glow-a, 0); } 50% { opacity: calc(.72 * var(--tr-glow-a, 0)); } }
@keyframes x15-sheen { 0% { opacity: 0; transform: translateX(-14%); } 12% { opacity: .9; } 70% { opacity: .9; } 88%, 100% { opacity: 0; transform: translateX(100%); } }
/* Phones: a quiet dart (lighter body so it reads on the dark row, gold and violet kept); no cone, heat, diamonds or sheen. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="x15"] { --tr-paint: #3b4456; --tr-paint2: #3b4456; --x15-top: #566175; --x15-wing: #3b4456; --tr-shade: #222936; }
  #ladder-rows .nfx-tr[data-v="x15"] :is(.r-x15Panel, .r-glint, .r-x15LE, .r-x15Hot, .r-x15RimLow, .r-x15Orange) { display: none; }
  #ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p:is(.shock, .glow) { display: none; }
  #ladder-rows .nfx-tr[data-v="x15"] .nfx-tr-p.flame { --tr-u: 0; background: none; }
  #ladder-rows .nfx-tr[data-v="x15"] .r-edge { stroke-width: .8px; }
}
/* rocket (火箭·航天器) */
/* 火箭·航天器 rocket v3: a crewed launcher climbing up-left at 13° (escape tower, fairing with a crew porthole,
   white core with red bands and a grey interstage, two finned strap-on boosters, four hot bells), an orange-gold
   plume with a white-hot core. Stages: liftoff smoke (cruise), Max-Q vapour collar and Mach diamonds (boost, gone
   again by max: the air thins), a high-altitude plume bloom, Mach ring and sparks (max). Scoped to
   [data-v="rocket"]; keyframes rk-*; transform and opacity only, on the shared clock (--tr-p, --tr-delay). */
#ladder-rows .nfx-tr[data-v="rocket"] { --tr-paint: #eef2f7; --tr-paint2: #dc2626; --tr-shade: rgba(51, 65, 85, .34); --tr-metal: #94a3b8; --tr-glass: #0c4a6e; --tr-a: #dbeafe; --tr-b: #f97316; --tr-lamp: #fde68a; --tr-core: #fffbeb; --tr-stripe: #dc2626; --tr-wake: rgba(251, 191, 36, .3); --tr-streak: rgba(241, 245, 249, .7); --tr-glow: rgba(251, 191, 36, .3); --tr-hot-k: 1; --tr-flick-n: 3; --tr-rk-far: #b8c3d1; --tr-rk-far-red: #a51d1d; --tr-rk-bell: #1e293b; --tr-rk-skirt: #475569; --tr-rk-gold: #fcd34d; --tr-rk-smoke: rgba(226, 232, 240, .62); }
/* Roles added by this vehicle. */
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkFar { fill: var(--tr-rk-far); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkFarRed { fill: var(--tr-rk-far-red); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkBell { fill: var(--tr-rk-bell); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkSkirt { fill: var(--tr-rk-skirt); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkSheen { fill: #fff; opacity: .8; }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkShadow { fill: rgba(15, 23, 42, .3); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkTruss { stroke: var(--tr-metal); stroke-width: .7px; }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkLip { stroke: #fdba74; stroke-width: .8px; opacity: calc(.45 + .55 * var(--tr-u, 0)); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkHot { fill: #fb923c; opacity: calc(.12 + .3 * var(--tr-u, 0)); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkGold { fill: var(--tr-rk-gold); fill-opacity: .92; }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkBFlame { fill: var(--tr-b); fill-opacity: .7; }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkBCore { fill: #fde68a; }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkNoz { fill: var(--tr-core); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkBloom { fill: rgba(253, 224, 71, .09); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkBloomIn { fill: rgba(254, 243, 199, .12); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkBloomRing { stroke: rgba(255, 251, 235, .4); stroke-width: .6px; }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkVapor { fill: rgba(248, 250, 252, .3); }
#ladder-rows .nfx-tr[data-v="rocket"] .r-rkVaporEdge { stroke: rgba(255, 255, 255, .9); stroke-width: .7px; }
/* Vapour and bloom are soft-edged (a static blur on their own layer; never animated). */
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:is(:has(.r-rkVapor), :has(.r-rkBloom)) > svg { filter: blur(.5px); }
/* Existing roles, tuned: Mach diamonds white-gold, the plume always lit (not only at max). */
#ladder-rows .nfx-tr[data-v="rocket"] .r-shock { fill: var(--tr-core); stroke: #fbbf24; stroke-width: .6px; }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.flame { --tr-flame-a: calc(.82 + .18 * var(--tr-max, 0)); }
/* Stage gates: diamonds from boost, the Max-Q collar only between boost and max, the bloom only at max. */
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:has(.r-shock) { opacity: calc(.3 * var(--tr-boost, 0) + .7 * var(--tr-max, 0)); }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:has(.r-rkVapor) { opacity: calc(.95 * var(--tr-boost, 0) * (1 - var(--tr-max, 0))); }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:has(.r-rkBloom) { opacity: calc(.85 * var(--tr-max, 0)); transform-origin: 4.23% 32.52%; }
/* The nozzle halo: a hot white point in a gold glow, stronger up the band. */
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.glow { --tr-glow-a: calc(.45 + .55 * var(--tr-u, 0)); border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 251, 235, .85), rgba(253, 186, 116, .4) 35%, rgba(249, 115, 22, .12) 65%, transparent); }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-ring { border-color: #fcd34d; }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-spark { background: #fff7d6; box-shadow: 0 0 3px #f59e0b; }
/* The wake: a hot gold root cooling into grey-white smoke billows that flow aft, fading at the tip. */
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-trail {
  background: linear-gradient(to right, rgba(255, 237, 160, .6), rgba(251, 146, 60, .36) 18%, rgba(203, 213, 225, .24) 46%, rgba(148, 163, 184, .12) 78%, transparent);
  -webkit-mask: linear-gradient(transparent, #000 18% 82%, transparent), linear-gradient(to right, #000 62%, transparent); -webkit-mask-composite: source-in;
  mask: linear-gradient(transparent, #000 18% 82%, transparent), linear-gradient(to right, #000 62%, transparent); mask-composite: intersect; }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-trail::before { opacity: calc(.45 + .55 * var(--tr-boost, 0));
  background:
    radial-gradient(closest-side, var(--tr-rk-smoke), transparent) 0 28% / calc(var(--tr-flow) * var(--tr-U) * .5) 52% repeat-x,
    radial-gradient(closest-side, color-mix(in srgb, var(--tr-rk-smoke) 70%, transparent), transparent) calc(var(--tr-flow) * var(--tr-U) * .25) 72% / calc(var(--tr-flow) * var(--tr-U)) 64% repeat-x;
  -webkit-mask: none; mask: none; }
#ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-trail::after { inset: 38% 0; opacity: calc((.35 + .65 * var(--tr-max, 0)) * var(--tr-hot-k));
  background: linear-gradient(to right, var(--tr-core), #fcd34d 14%, rgba(249, 115, 22, .7) 32%, transparent 68%); }
/* The aura (limit / arrival flash): the fire lighting the air round the engines, not the whole box. */
#ladder-rows .nfx-tr[data-v="rocket"]::before { inset: -40% -22% -50% 58%;
  background: radial-gradient(closest-side, rgba(253, 186, 116, .34), rgba(249, 115, 22, .1) 60%, transparent); }
/* Running (the shared gates): the booster plumes flicker a seventh of P behind the core, the base light flickers
   with the fire, diamonds shimmer, the collar shivers, the bloom breathes along the plume, a Mach ring per P. */
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rocket"] .nfx-tr-p.flame:has(.r-rkBCore) {
  animation-delay: calc(var(--tr-delay) - var(--tr-p, 1s) / 7); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rocket"] .r-rkHot {
  animation: rk-hot calc(var(--tr-p, 1s) / var(--tr-flick-n, 1)) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:has(.r-shock) {
  animation: rk-diamond calc(var(--tr-p, 1s) / var(--tr-flick-n, 1)) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:has(.r-rkVapor) {
  animation: rk-vapor calc(var(--tr-p, 1s) / 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rocket"] .nfx-tr-p.shock:has(.r-rkBloom) {
  animation: rk-bloom calc(var(--tr-p, 1s) * 2) ease-in-out infinite var(--tr-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rocket"] .nfx-tr-ring {
  animation: rk-ring var(--tr-p, 1s) ease-out infinite var(--tr-delay); }
@keyframes rk-hot { 0%, 100% { opacity: calc(.12 + .3 * var(--tr-u, 0)); } 50% { opacity: calc(.65 * (.12 + .3 * var(--tr-u, 0))); } }
@keyframes rk-diamond { 0%, 100% { opacity: calc(.3 * var(--tr-boost, 0) + .7 * var(--tr-max, 0)); } 50% { opacity: calc(.6 * (.3 * var(--tr-boost, 0) + .7 * var(--tr-max, 0))); } }
@keyframes rk-vapor { 0%, 100% { opacity: calc(.95 * var(--tr-boost, 0) * (1 - var(--tr-max, 0))); } 50% { opacity: calc(.62 * var(--tr-boost, 0) * (1 - var(--tr-max, 0))); } }
@keyframes rk-bloom { 0%, 100% { transform: rotate(13deg) scale(.94, .9) rotate(-13deg); } 50% { transform: rotate(13deg) scale(1.04, 1.06) rotate(-13deg); } }
@keyframes rk-ring { 0% { opacity: calc(.8 * var(--tr-max, 0)); transform: rotate(13deg) scale(.12, .35); } 70%, 100% { opacity: 0; transform: rotate(13deg) scale(.5, 1.7); } }
/* Phones: a quiet white stick with a red nose and fins and one plume; no tower truss, bands, porthole, collar,
   diamonds, bloom, halo or booster plumes. The body gets a hairline outline in its own colour so it reads at 9px. */
@media (max-width: 720px) {
  #ladder-rows .nfx-tr[data-v="rocket"] :is(.r-rkTruss, .r-dark, .r-glass, .r-glint, .r-seam, .r-edge, .r-rkSheen, .r-rkShadow, .r-shade, .r-metal, .r-stripeFill, .r-rkLip, .r-rkHot, .r-rkSkirt) { display: none; }
  #ladder-rows .nfx-tr[data-v="rocket"] :is(.nfx-tr-p.shock, .nfx-tr-p.glow, .nfx-tr-p.flame:has(.r-rkBCore)) { display: none; }
  #ladder-rows .nfx-tr[data-v="rocket"] :is(.r-paint, .r-rkFar) { stroke: currentColor; stroke-width: .6px; }
  #ladder-rows .nfx-tr[data-v="rocket"] .r-paint { color: var(--tr-paint); }
  #ladder-rows .nfx-tr[data-v="rocket"] .r-rkFar { color: var(--tr-rk-far); }
  #ladder-rows .nfx-tr[data-v="rocket"] .r-rkGold { display: none; }
  /* Half-length plume so it ends inside the 7px phone lane, clear of `tok/s` (origin: the core nozzle). */
  #ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-p.flame > svg { transform: scale(.5); transform-origin: 5.24% 36.2%; }
  #ladder-rows .nfx-tr[data-v="rocket"]::before { content: none; }
  #ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-trail { background: linear-gradient(to right, rgba(253, 186, 116, .55), rgba(203, 213, 225, .18) 55%, transparent); }
  #ladder-rows .nfx-tr[data-v="rocket"] .nfx-tr-trail::before { content: none; }
}
/* transport:artist-css:end */
/* Narrower desktops: a smaller box (U 14px) so the vehicle and its wake keep clear of the name and its meta line;
   the headlamp's cone (light only) goes below 1100px. From 721px to 1023px the compact box (at most 16px high and
   64px wide: U = min(8px, 32px / aspect), a 12px lane) rides the meter line inside the speed cell, its lane ending 4px
   left of the meter (22px + 80px from the cell's right), under the number and never beside the name or its meta line. */
/* Reserve the complete desktop vehicle/wake/number corridor in the table itself.
   Device groups wrap within the name column instead of running underneath the artwork. */
@media (min-width: 1024px) {
  .ladder-wrap[data-num-fx="transport"] .ladder .c-value { width: 420px; }
  .ladder-wrap[data-num-fx="transport"] .ladder .row-meta { flex-basis: 100%; flex-wrap: wrap; align-items: baseline; }
  .ladder-wrap[data-num-fx="transport"] .ladder .row-meta .tools { flex: 1 1 180px; }
}
@media (min-width: 1024px) and (max-width: 1179px) {
  .ladder-wrap[data-num-fx="transport"] .ladder .c-value { width: 370px; }
}
@media (min-width: 1024px) and (max-width: 1179px) { #ladder-rows .nfx-tr { --tr-U: 14px; } }
@media (max-width: 1100px) { #ladder-rows .nfx-tr .nfx-tr-beam { display: none; } }
/* 电脑速度特效 (desktop speed FX): desktops with a fine pointer only, from 1024px (TRANSPORT.fx.media). Phones, touch
   screens of any width and the compact box (721–1023px) keep the light set above. Everything stays inside the reserved
   corridor: in the vehicle's own box (its rows of air and its afterimage) or inside its pushed trail (the core and the
   front, clipped to min(lane, trail): exactly where the field pushes, never past the number). Rest and unknown get none.
   The stage reads in three ways at once, all continuous in u: how many rush lines run and how long they are (one row
   at cruise, more with --tr-boost and --tr-max), how fast they cross (a share of the ground's speed, so the cadence
   ×2 of the band shows), and how far the core and the front run down the trail. Per family: walkers and riders are
   quieter (--dfx-k) and walkers keep their own dust and afterimages (no core, front or ghost); the GT car's ribbons
   own both lane layers. Transform and opacity only on the row clock; the afterimage is a static filter (no animated
   filter), off at cruise. Parked, held, hidden, off and reduced motion stop or hide it with the vehicle.
   Rush lines (掠过速度线): .nfx-tr-v::before above the silhouette, ::after below it (z −1 inside the vehicle), each a
   cluster that crosses nose → tail in max(160ms, P · --dfx-cross), --dfx-cross = .77 · aspect / (flow · flow-n): the
   58% of the box it travels at 1.5 × the ground's speed. The second cluster runs half a crossing later.
   Afterimage (轮廓拖影): two offsets to the right (tail side) of the whole vehicle in its light A, .16U · boost and
   .32U · max. Slipstream core (滑流芯): a tapered line from the emitter along the trail, (.3 + .7u) of the pushed
   length, in the vehicle's streak (engines warm with --tr-hot-k), pulsing with the push (nfx-tr-pulse).
   Pressure front (风压前沿): a soft band that runs the pushed length in TRANSPORT.fx.front.travel of a gust and fades by
   .travel + .fade, once per gust (--trn-gust), started travel · gust early so it reaches the lane's end exactly
   --trn-lag after the beat, when the number's glow, sweep and nudge begin (数字联动): the number answers the front.
   Its strength follows u and the number's coupling (--trn-k), a steady wake (trains) at a gentler swell. */
@media (min-width: 1024px) and (pointer: fine) {
  #ladder-rows .nfx-tr { --dfx-k: 1; --dfx-cross: calc(.77 * var(--tr-aspect, 2) / (var(--tr-flow, 1) * var(--tr-flow-n, 1)));
    --dfx-c: color-mix(in srgb, var(--tr-streak) 80%, white); --dfx-low: 1; }
  #ladder-rows .nfx-tr[data-f="step"] { --dfx-k: .5; }
  #ladder-rows .nfx-tr[data-f="pedal"] { --dfx-k: .8; }
  #ladder-rows .nfx-tr[data-g] { --dfx-low: .55; }
  #ladder-rows .nfx-tr:not([data-f="rest"]) .nfx-tr-v::before,
  #ladder-rows .nfx-tr:not([data-f="rest"]) .nfx-tr-v::after { content: ""; position: absolute; z-index: -1; pointer-events: none; left: 0; width: 42%; opacity: 0;
    --dfx-len: calc(42% + 58% * var(--tr-u, 0)); --dfx-rush-a: calc((.5 + .4 * var(--tr-u, 0)) * var(--dfx-k)); }
  #ladder-rows .nfx-tr:not([data-f="rest"]) .nfx-tr-v::before { top: calc(-.46 * var(--tr-U)); height: calc(.4 * var(--tr-U));
    background:
      linear-gradient(to right, transparent, var(--dfx-c) 72%, transparent) 0 72% / var(--dfx-len) 1px no-repeat,
      linear-gradient(to right, transparent, color-mix(in srgb, var(--dfx-c) calc(85% * var(--tr-boost, 0)), transparent) 72%, transparent) 70% 36% / calc(var(--dfx-len) * .8) 1px no-repeat,
      linear-gradient(to right, transparent, color-mix(in srgb, #fff calc(80% * var(--tr-max, 0)), transparent) 75%, transparent) 25% 0 / calc(var(--dfx-len) * .65) 1px no-repeat; }
  #ladder-rows .nfx-tr:not([data-f="rest"]) .nfx-tr-v::after { top: calc(100% + .1 * var(--tr-U)); height: calc(.34 * var(--tr-U));
    background:
      linear-gradient(to right, transparent, color-mix(in srgb, var(--dfx-c) calc(85% * var(--tr-boost, 0) * var(--dfx-low)), transparent) 72%, transparent) 40% 0 / calc(var(--dfx-len) * .85) 1px no-repeat,
      linear-gradient(to right, transparent, color-mix(in srgb, var(--dfx-c) calc(70% * var(--tr-max, 0) * var(--dfx-low)), transparent) 72%, transparent) 0 100% / calc(var(--dfx-len) * .6) 1px no-repeat; }
  #ladder-rows .nfx-tr:not([data-f="rest"]):not([data-f="step"]):not([data-stage="cruise"]) .nfx-tr-v {
    filter: drop-shadow(calc(.16 * var(--tr-U) * var(--tr-boost, 0)) 0 0 color-mix(in srgb, var(--tr-a) calc(34% * var(--tr-boost, 0) * var(--dfx-k)), transparent))
      drop-shadow(calc(.32 * var(--tr-U) * var(--tr-max, 0)) 0 .6px color-mix(in srgb, var(--tr-a) calc(20% * var(--tr-max, 0) * var(--dfx-k)), transparent)); }
  #ladder-rows .nfx-tr:not([data-f="step"]):not([data-v="sportsCar"]) .nfx-tr-lane::before,
  #ladder-rows .nfx-tr:not([data-f="step"]):not([data-v="sportsCar"]) .nfx-tr-lane::after { content: ""; position: absolute; left: 0; pointer-events: none;
    --dfx-reach: min(calc((1 - var(--tr-ax, 1)) * 2 * var(--tr-U) * var(--tr-aspect, 2) + var(--tr-lane)), var(--tr-L)); }
  #ladder-rows .nfx-tr:not([data-f="step"]):not([data-v="sportsCar"]) .nfx-tr-lane::before { top: 50%; height: max(1px, calc(.1 * var(--tr-U))); translate: 0 -50%;
    width: var(--dfx-reach); transform-origin: 0 50%; transform: scaleX(calc(.3 + .7 * var(--tr-u, 0))); border-radius: 1px;
    --dfx-core: color-mix(in srgb, var(--tr-b) calc(70% * var(--tr-hot-k, 0)), var(--dfx-c));
    background: linear-gradient(to right, color-mix(in srgb, var(--dfx-core) calc(100% * (.3 + .45 * var(--tr-boost, 0) + .25 * var(--tr-max, 0)) * var(--dfx-k)), transparent),
      color-mix(in srgb, var(--dfx-core) calc(45% * (.3 + .7 * var(--tr-boost, 0)) * var(--dfx-k)), transparent) 50%, transparent); }
  #ladder-rows .nfx-tr:not([data-f="step"]):not([data-v="sportsCar"]) .nfx-tr-lane::after { top: 0; bottom: 0; width: calc(.6 * var(--tr-U)); opacity: 0;
    --dfx-front-a: calc((.4 + .25 * var(--tr-u, 0) + .35 * var(--trn-k, 0)) * (.45 + .55 * var(--trn-swell, 1)) * var(--dfx-k));
    background: radial-gradient(ellipse 100% 50% at 0 50%, transparent 52%, color-mix(in srgb, var(--dfx-c) 35%, transparent) 70%, color-mix(in srgb, var(--dfx-c) 70%, white) 88%, transparent 100%),
      linear-gradient(to right, transparent, color-mix(in srgb, var(--dfx-c) 18%, transparent));
    -webkit-mask: linear-gradient(transparent, #000 16% 84%, transparent); mask: linear-gradient(transparent, #000 16% 84%, transparent); }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr:not([data-f="rest"]) .nfx-tr-v::before {
    animation: nfx-tr-rush max(160ms, calc(var(--tr-p, 1s) * var(--dfx-cross, 1))) linear infinite var(--tr-delay); }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr:not([data-f="rest"]) .nfx-tr-v::after {
    animation: nfx-tr-rush max(160ms, calc(var(--tr-p, 1s) * var(--dfx-cross, 1))) linear infinite calc(var(--tr-delay) - max(160ms, calc(var(--tr-p, 1s) * var(--dfx-cross, 1))) / 2); }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr:not([data-f="step"]):not([data-v="sportsCar"]) .nfx-tr-lane::before {
    animation: nfx-tr-pulse calc(var(--tr-p, 1s) / var(--tr-beats, 1)) linear infinite var(--tr-delay); }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr:not([data-f="step"]):not([data-v="sportsCar"]) .nfx-tr-lane::after {
    animation: nfx-tr-front var(--trn-gust, calc(var(--tr-p, 1s) / var(--tr-beats, 1))) linear infinite calc(var(--tr-delay) + var(--trn-lag, 0ms) - var(--trn-gust, calc(var(--tr-p, 1s) / var(--tr-beats, 1))) * .16); }
}
@keyframes nfx-tr-rush { 0% { opacity: 0; transform: translateX(0); } 18%, 72% { opacity: var(--dfx-rush-a, .5); } 100% { opacity: 0; transform: translateX(138%); } }
@keyframes nfx-tr-front { 0% { opacity: 0; transform: translateX(calc(-.6 * var(--tr-U))) scaleY(1); animation-timing-function: cubic-bezier(.3, .55, .55, 1); } 4% { opacity: var(--dfx-front-a, .5); } 16% { opacity: var(--dfx-front-a, .5); transform: translateX(calc(var(--dfx-reach) - .6 * var(--tr-U))) scaleY(var(--tr-tip, .5)); } 26%, 100% { opacity: 0; transform: translateX(calc(var(--dfx-reach) - .6 * var(--tr-U))) scaleY(var(--tr-tip, .5)); } }
@media (min-width: 721px) and (max-width: 1023px) {
  #ladder-rows .nfx-tr { --tr-U: min(8px, calc(32px / var(--tr-aspect, 2))); --tr-lane: 12px;
    right: calc(106px + var(--tr-lane)); top: calc(50% + 19px - var(--tr-U)); }
  #ladder-rows .nfx-tr[data-v="rest"] { --tr-lane: 0px; right: 106px; }
  #ladder-rows .nfx-tr-p.still > svg { filter: none; }
}

/* Ping, gear, transport and off: the jet's layers are gone (led.mjs removes them; hidden here at once)
   and the number does not lift. */
.ladder-wrap:is([data-num-fx="ping"], [data-num-fx="gear"], [data-num-fx="transport"], [data-num-fx="off"]) #ladder-rows .led-rings,
.ladder-wrap:is([data-num-fx="ping"], [data-num-fx="gear"], [data-num-fx="transport"], [data-num-fx="off"]) #ladder-rows .orbit-sky,
.ladder-wrap:is([data-num-fx="ping"], [data-num-fx="gear"], [data-num-fx="transport"], [data-num-fx="off"]) #ladder-rows .led-wind { display: none; }
.ladder-wrap:is([data-num-fx="ping"], [data-num-fx="gear"], [data-num-fx="transport"], [data-num-fx="off"]):not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-led]:not([data-led-idle]) .value {
  animation: none; }
/* 数字联动 (the wake reaching the number): while a vehicle moves (led.mjs: data-trn and --trn-* on its cell), the number
   feels its wake in gusts on the vehicle's own clock: every --trn-gust (a whole number of the trail's beats), --trn-lag
   after a beat leaves the emitter, a glow in the vehicle's light A (--trn-a) washes into the digits from their left
   edge, where the lane ends; on desktops a light sweep crosses the digits and the number is nudged right by at most
   --trn-nudge. All of it scales with --trn-k, how far the trail reaches down its lane (transport.mjs couple: 0 at a
   band's cruise and low on the ladder, up to 1 at a fast vehicle's max): quiet slow numbers, clear fast ones. Between
   gusts the glow keeps a floor (a steady wake: a gentle swell only). Both layers are behind the digits (z −1 inside
   .value); the text, its value, its tier colour and the row's rank never change. Transform and opacity only; the
   nudge (nfx-trn-kick) pins --trn-t. Rest, unknown, another mode, hidden, parked, held, off and reduced motion: none. */
#ladder-rows .c-value { --trn-k: var(--trn-kd, 0); --trn-nudge: 1.6px; --trn-a: #7dd3fc;
  --trn-delay: calc(var(--trn-t, 0ms) - var(--trn-off, 0ms) + var(--trn-lag, 0ms));
  --trn-push: calc(var(--trn-nudge) * clamp(0, (var(--trn-k) - .25) / .75, 1)); --trn-sweep: calc(.8 * clamp(0, (var(--trn-k) - .25) / .75, 1)); }
.ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::before,
.ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::after { content: ""; position: absolute; z-index: -1; pointer-events: none; opacity: 0; }
.ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::before { left: -14px; top: -6px; bottom: -6px;
  width: calc(var(--led-chars, 4) * 14.4px * .85 + 14px); transform-origin: 0 50%;
  background:
    linear-gradient(to right, color-mix(in srgb, var(--trn-a) 95%, transparent), color-mix(in srgb, var(--trn-a) 40%, transparent) 55%, transparent) 0 calc(50% - 6px) / 100% 2px no-repeat,
    linear-gradient(to right, color-mix(in srgb, var(--trn-a) 95%, transparent), color-mix(in srgb, var(--trn-a) 40%, transparent) 55%, transparent) 0 calc(50% + 5px) / 100% 2px no-repeat,
    radial-gradient(ellipse 100% 50% at 14px 50%, color-mix(in srgb, var(--trn-a) 50%, transparent), transparent);
  -webkit-mask: linear-gradient(to right, transparent, #000 14px); mask: linear-gradient(to right, transparent, #000 14px); }
.ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::after { left: -12px; top: -5px; bottom: -5px; width: 12px;
  background: linear-gradient(to right, transparent, color-mix(in srgb, #fff 65%, var(--trn-a)), transparent); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-trn]:not([data-led-idle]) .value {
  animation: nfx-trn-kick var(--trn-gust, 2s) linear infinite var(--trn-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-trn]:not([data-led-idle]) .value::before {
  animation: nfx-trn-glow var(--trn-gust, 2s) linear infinite var(--trn-delay); }
.ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-trn]:not([data-led-idle]) .value::after {
  animation: nfx-trn-sweep var(--trn-gust, 2s) linear infinite var(--trn-delay); }

/* Off: the meter stands still (its tier colours, lit cells and glow stay). */
.ladder-wrap[data-num-fx="off"] #ladder-rows .led-lit::after, .ladder-wrap[data-num-fx="off"] #ladder-rows .led-chase { animation: none; }
.ladder-wrap[data-num-fx="off"] #ladder-rows .led-burst { display: none; }

@keyframes nfx-ping-ring { 0% { opacity: .85; transform: scale(var(--nfx-k0)); animation-timing-function: cubic-bezier(.3333, .6667, .6667, 1); } 55%, 100% { opacity: 0; transform: scale(1); } }
@keyframes nfx-ping-echo { 0% { opacity: .425; transform: scale(var(--nfx-k0)); animation-timing-function: cubic-bezier(.3333, .6667, .6667, 1); } 55%, 100% { opacity: 0; transform: scale(1); } }
@keyframes nfx-ping-flash { 0% { opacity: .35; transform: scale(.7); animation-timing-function: ease-out; } 15%, 100% { opacity: 0; transform: scale(1.15); } }
@keyframes nfx-gear-turn { from { transform: rotate(0turn); } to { transform: rotate(1turn); } }
@keyframes nfx-gear-flame { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.07); } 70% { transform: scale(.97); } }
@keyframes nfx-gear-wind { from { transform: translateX(0); } to { transform: translateX(-22px); } }
@keyframes nfx-tr-bob { 0%, 100% { transform: translateY(calc(var(--tr-bob, 0) * 2 * var(--tr-U))); } 50% { transform: translateY(0); } }
@keyframes nfx-tr-breathe { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(1.025); } }
@keyframes nfx-tr-limb { 0%, 100% { transform: rotate(calc(var(--n) + var(--a0) * var(--tr-stride, 1))); } 12.5% { transform: rotate(calc(var(--n) + var(--a1) * var(--tr-stride, 1))); } 25% { transform: rotate(calc(var(--n) + var(--a2) * var(--tr-stride, 1))); } 37.5% { transform: rotate(calc(var(--n) + var(--a3) * var(--tr-stride, 1))); } 50% { transform: rotate(calc(var(--n) + var(--a4) * var(--tr-stride, 1))); } 62.5% { transform: rotate(calc(var(--n) + var(--a5) * var(--tr-stride, 1))); } 75% { transform: rotate(calc(var(--n) + var(--a6) * var(--tr-stride, 1))); } 87.5% { transform: rotate(calc(var(--n) + var(--a7) * var(--tr-stride, 1))); } }
@keyframes nfx-tr-spin { from { transform: rotate(0turn); } to { transform: rotate(-1turn); } }
@keyframes nfx-tr-flick { 0%, 100% { opacity: var(--tr-flame-a, 1); transform: rotate(var(--fd, 0deg)) scaleX(calc(.6 + .8 * var(--tr-u, 0))) rotate(calc(-1 * var(--fd, 0deg))); } 50% { opacity: calc(.8 * var(--tr-flame-a, 1)); transform: rotate(var(--fd, 0deg)) scaleX(calc((.6 + .8 * var(--tr-u, 0)) * .78)) rotate(calc(-1 * var(--fd, 0deg))); } }
@keyframes nfx-tr-glow { 0%, 100% { opacity: var(--tr-glow-a, 1); } 50% { opacity: calc(.45 * var(--tr-glow-a, 1)); } }
@keyframes nfx-tr-spark { 0% { opacity: var(--tr-spark, 0); transform: translate(0, 0); } 100% { opacity: 0; transform: translate(calc(var(--sx, 1) * 1.6 * var(--tr-U)), calc(var(--sy, 0) * 1.6 * var(--tr-U))); } }
@keyframes nfx-tr-ring { 0% { opacity: .8; transform: scale(.3); } 60%, 100% { opacity: 0; transform: scale(1.5); } }
@keyframes nfx-tr-pulse { 0%, 100% { opacity: 1; } 12.5%, 87.5% { opacity: calc(1 - var(--tr-depth, 0) * .355); } 25%, 75% { opacity: calc(1 - var(--tr-depth, 0) * .875); } 37.5%, 62.5% { opacity: calc(1 - var(--tr-depth, 0) * .991); } 50% { opacity: calc(1 - var(--tr-depth, 0) * 1); } }
@keyframes nfx-tr-flow { from { transform: translateX(0); } to { transform: translateX(calc(var(--tr-flow, 1) * var(--tr-U))); } }
@keyframes nfx-tr-in-up { 0% { opacity: 0; transform: translateX(45%); } 30% { opacity: 1; } 70% { transform: translateX(-4%); } 100% { opacity: 1; transform: translateX(0); } }
@keyframes nfx-tr-in-down { 0% { opacity: 0; transform: translateX(-12%); } 100% { opacity: 1; transform: translateX(0); } }
@keyframes nfx-tr-out-up { 0% { opacity: .5; transform: translateX(0) scale(.92); } 100% { opacity: 0; transform: translateX(-60%) scale(.85); } }
@keyframes nfx-tr-out-down { 0% { opacity: .5; transform: translateX(0) scale(.92); } 100% { opacity: 0; transform: translateX(40%) scale(.85); } }
@keyframes nfx-trn-kick { 0% { transform: translateX(0); animation-timing-function: cubic-bezier(.3, 0, .2, 1); } 7% { transform: translateX(var(--trn-push, 0px)); animation-timing-function: cubic-bezier(.4, 0, .6, 1); } 38%, 100% { transform: translateX(0); } }
@keyframes nfx-trn-glow { 0% { opacity: calc(var(--trn-k, 0) * (1 - .65 * var(--trn-swell, 1))); transform: scaleX(calc(1 - .6 * var(--trn-swell, 1))); animation-timing-function: cubic-bezier(.3, 0, .2, 1); } 8% { opacity: var(--trn-k, 0); transform: scaleX(1); animation-timing-function: ease-in-out; } 45%, 100% { opacity: calc(var(--trn-k, 0) * (1 - .65 * var(--trn-swell, 1))); transform: scaleX(calc(1 - .6 * var(--trn-swell, 1))); } }
@keyframes nfx-trn-sweep { 0% { opacity: 0; transform: translateX(0) skewX(-16deg); } 6% { opacity: var(--trn-sweep, 0); } 34% { opacity: 0; transform: translateX(calc(var(--led-chars, 4) * 14.4px + 12px)) skewX(-16deg); } 100% { opacity: 0; transform: translateX(calc(var(--led-chars, 4) * 14.4px + 12px)) skewX(-16deg); } }
@keyframes nfx-tr-flash { 0% { opacity: 0; transform: scale(.4); } 30% { opacity: .8; } 100% { opacity: calc(.3 * var(--tr-max, 0)); transform: scale(1); } }

@media (max-width: 720px) {
  /* The phone number sits right-aligned over its unit: centre on the number line. */
  #ladder-rows .nfx-ping { --nfx-r: calc(44px + 96px * var(--led-reach, 0)); --nfx-cx: calc(var(--led-chars, 4) * 6px); --nfx-dy: -6.5px;
    --nfx-k0: var(--nfx-k0p, .3); }
  /* The 六维 button sits left of the number: the sprocket goes under its first digits, on the unit line. */
  #ladder-rows .nfx-gear { --nfx-gd: 18px; --nfx-pd: 3px; --nfx-gx: calc(var(--led-chars, 4) * 12px - 10px); --nfx-dy: 11.5px; --nfx-tail-a: .2; --nfx-tail-b: 1; }
  /* The vehicle rides the unit line between the 六维 button and `tok/s`: the lane ends 33px from the cell's right
     (past the unit), the vehicle and its lane together stay within 32px and 14px high (long vehicles shrink their
     U so the art keeps its proportions and the field, which measures the box and lane, follows); trails × .6
     (transport.mjs TRANSPORT.phoneTrail). No beam: no room beside the number. The sleeper is ≤ 25px wide. */
  #ladder-rows .nfx-tr { --tr-U: min(7px, calc(12.5px / var(--tr-aspect, 2))); --tr-lane: 7px; --tr-trail-k: .6;
    right: calc(33px + var(--tr-lane)); top: calc(50% + 11.5px - var(--tr-U)); }
  #ladder-rows .nfx-tr[data-v="rest"] { --tr-lane: 0px; right: 33px; }
  #ladder-rows .nfx-tr .nfx-tr-beam { display: none; }
  #ladder-rows .nfx-tr-p.still > svg { filter: none; }
  /* 数字联动 on phones: the glow only, centred where the lane ends (33px from the right, on the unit line). */
  #ladder-rows .c-value { --trn-k: var(--trn-kp, 0); --trn-nudge: 0px; }
  .ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::before { left: auto; right: 15px; top: auto; bottom: -7px; height: 24px; width: 36px;
    transform-origin: 50% 50%; background: radial-gradient(closest-side, color-mix(in srgb, var(--trn-a) 70%, transparent), transparent); -webkit-mask: none; mask: none; }
  .ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::after { display: none; }
}
@media (max-width: 380px) {
  #ladder-rows .nfx-ping { --nfx-cx: calc(var(--led-chars, 4) * 5.4px); }
  #ladder-rows .nfx-gear { --nfx-gx: calc(var(--led-chars, 4) * 10.8px - 10px); }
}
/* Phones (also turned to landscape): one front and the flash. */
@media (max-width: 720px), (pointer: coarse) and (max-height: 720px) {
  #ladder-rows .nfx-ping > i + i { visibility: hidden; }
  #ladder-rows .nfx-tr :is(.nfx-tr-spark, .nfx-tr-ring, .nfx-tr-under) { display: none; }
  #ladder-rows .nfx-tr { --tr-trail-k: .6; }
}
/* 数字联动 by layout: touch landscape in the desktop box (the phones' shorter trail) its own coupling and a smaller
   nudge; the compact box (721–1023px) the glow alone, centred where its lane ends under the number (84px left of
   the unit's right edge, on the meter line), with the compact lane's coupling (full trail; touch: shorter trail). */
@media (pointer: coarse) and (max-height: 720px) and (min-width: 721px) {
  #ladder-rows .c-value { --trn-k: var(--trn-kl, 0); --trn-nudge: .8px; }
}
@media (min-width: 721px) and (max-width: 1023px) {
  #ladder-rows .c-value { --trn-k: var(--trn-kc, 0); --trn-nudge: 0px; }
  .ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::before { left: auto; right: 64px; top: auto; bottom: -20px; height: 26px; width: 40px;
    transform-origin: 50% 50%; background: radial-gradient(closest-side, color-mix(in srgb, var(--trn-a) 70%, transparent), transparent); -webkit-mask: none; mask: none; }
  .ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::after { display: none; }
}
@media (min-width: 721px) and (max-width: 1023px) and (pointer: coarse) and (max-height: 720px) {
  #ladder-rows .c-value { --trn-k: var(--trn-kt, 0); }
}
/* Without motion there are no number layers, only the static meter; with Vehicles chosen, a shown 0.0 keeps its
   sleeper, still (no breathing, no arrival, nothing else animates and nothing pushes). Motion off, the hold and
   parking still hide it. */
@media (prefers-reduced-motion: reduce) {
  .ladder-wrap[data-num-fx] #ladder-rows .nfx-ping, .ladder-wrap[data-num-fx] #ladder-rows .nfx-gear { display: none; }
  .ladder-wrap[data-num-fx] #ladder-rows .nfx-tr { display: none; }
  .ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::before, .ladder-wrap[data-num-fx="transport"] #ladder-rows .c-value[data-trn] .value::after { content: none; }
  .ladder-wrap[data-num-fx="transport"]:not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rest"]:not(.nfx-tr-out) { display: block; }
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rest"]:not(.nfx-tr-out),
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rest"]:not(.nfx-tr-out)::before,
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-tr]:not([data-led-idle]) .nfx-tr[data-v="rest"]:not(.nfx-tr-out) .nfx-tr-v { animation: none; }
  .nfx-probe { display: none; }
}

/* Phone budget: keep the vehicle's gait/wheels and short trail, with no animated
   glow/sweep on the digits or filtered SVG surfaces. The observer releases
   off-screen vehicle trees; at most six visible vehicles are mounted. */
@media (max-width: 720px), (pointer: coarse) and (max-height: 720px) {
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-trn]:not([data-led-idle]) .value,
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-trn]:not([data-led-idle]) .value::before,
  .ladder-wrap[data-num-fx="transport"]:not([data-fx-off]):not([data-rain-hold]):not([data-led-paused]) #ladder-rows .c-value[data-trn]:not([data-led-idle]) .value::after { animation: none; }
  #ladder-rows .c-value[data-tr] .nfx-tr, #ladder-rows .c-value[data-tr] .nfx-tr * { filter: none; will-change: auto; }
}
