/* Approved painted rigs; shared pixel output is applied after animation. */

/* Coarse painted hero, only loaded by the local art preview. */
.actor-wrap > .wayfarer { animation: none !important; image-rendering: pixelated; }
.wayfarer { overflow: visible; pointer-events: none; }
.wayfarer image { image-rendering: pixelated; }
.wayfarer-puppet {
  transform-origin: 630px 1148px;
  animation: wayfarer-breathe 4.4s steps(4, end) infinite;
  animation-delay: var(--hero-clock);
}
.wayfarer-arm-idle, .wayfarer-sword-arm { transform-origin: 760px 700px; }
.wayfarer-arm-idle { animation: wayfarer-ready 4.4s steps(4, end) infinite; animation-delay: var(--hero-clock); }
.wayfarer-lantern-sway { transform-origin: 495px 635px; animation: wayfarer-lantern-sway 3.8s steps(5, end) infinite; animation-delay: var(--hero-clock); }
.wayfarer-bounce { opacity: .2; animation: wayfarer-light 2.3s steps(2, end) infinite; animation-delay: var(--hero-clock); }
.wayfarer-halo, .wayfarer-lantern-light { opacity: .4; animation: wayfarer-light 2.3s steps(2, end) infinite; animation-delay: var(--hero-clock); }
.wayfarer-flame { transform-origin: 310px 979px; animation: wayfarer-flame 1.7s steps(3, end) infinite; animation-delay: var(--hero-clock); }
.player-stage.attacking:has(.wayfarer) .actor-wrap { animation: wayfarer-stride .5s steps(6, end) both; }
.attacking .wayfarer-sword-arm { animation: wayfarer-strike .5s steps(6, end) both; }
.taking-hit .wayfarer-sword-arm { animation: wayfarer-guard .5s steps(5, end) both; }
.player-stage.taking-hit:has(.wayfarer) .actor-wrap { animation: wayfarer-recoil .5s steps(6, end) both; }
.player-stage.blocking:has(.wayfarer) .wayfarer-sword-arm { animation: wayfarer-guard .5s steps(5, end) both; }
:is(.attacking, .taking-hit, .blocking) :is(.wayfarer-puppet, .wayfarer-arm-idle) { animation-play-state: paused; }
.fallen .wayfarer * { animation: none !important; }

@keyframes wayfarer-breathe { 0%,100% { transform: scaleY(1); } 50% { transform: scaleY(.985); } }
@keyframes wayfarer-ready { 0%,100% { transform: rotate(0deg); } 50% { transform: rotate(2deg); } }
@keyframes wayfarer-lantern-sway { 0%,100% { transform: rotate(-2.5deg); } 50% { transform: rotate(3deg); } }
@keyframes wayfarer-light { 0%,100% { opacity: .28; } 19% { opacity: .45; } 34% { opacity: .32; } 52% { opacity: .55; } 67% { opacity: .4; } 83% { opacity: .5; } }
@keyframes wayfarer-flame { 0%,100% { transform: translateY(0); } 37% { transform: translateY(-14px); } 70% { transform: translateY(-6px); } }
@keyframes wayfarer-stride { 0%,100% { translate: 0 0; } 10% { translate: -5px 0; } 24%,38% { translate: 20px 0; } 74% { translate: 4px 0; } }
@keyframes wayfarer-strike { 0%,100% { transform: rotate(0deg); } 10% { transform: rotate(-18deg); } 24% { transform: rotate(48deg); } 38% { transform: rotate(44deg); } 74% { transform: rotate(6deg); } }
@keyframes wayfarer-guard { 0%,100% { transform: rotate(0deg); } 20%,38% { transform: rotate(-24deg); } 72% { transform: rotate(-8deg); } }
@keyframes wayfarer-recoil { 0%,100% { translate: 0 0; rotate: 0deg; filter: none; } 20% { translate: -13px 0; rotate: -4deg; filter: brightness(1.6); } 42% { translate: -5px 0; rotate: -2deg; filter: none; } 74% { translate: 2px 0; rotate: 0deg; } }

/* Keep readable stationary warm light when either motion preference is enabled. */
@media (prefers-reduced-motion: reduce) {
  .wayfarer *, .player-stage:has(.wayfarer) .actor-wrap { animation: none !important; }
}
:root[data-reduce-motion="true"] :is(.wayfarer *, .player-stage:has(.wayfarer) .actor-wrap) { animation: none !important; }

/* Only the local art preview loads this puppet. The intent stays outside it. */
.enemy-figure.mossling-figure { animation: none !important; }
.mossling-art, .mossling-art image { image-rendering: pixelated; }
.mossling-art { overflow: visible; pointer-events: none; }
.mossling-motion, .mossling-breathe { transform-origin: 659px 1116px; }
.mossling-breathe { animation: mossling-breathe 3.6s steps(5, end) infinite; animation-delay: var(--mossling-clock); }
.mossling-sprout { transform-origin: 751px 446px; animation: mossling-leaves 3.6s steps(5, end) infinite; animation-delay: var(--mossling-clock); }

/* The existing stun intent is the source of truth, including item stuns. */
.mossling-figure:has(> :where(.intent.stun)) .mossling-motion { transform: scale(1.05, .88); animation: mossling-dazed 2.2s steps(5, end) infinite; animation-delay: var(--mossling-clock); }
.mossling-figure:has(> :where(.intent.stun)) .mossling-breathe { animation: none; }
.mossling-figure:has(> :where(.intent.stun)) .mossling-sprout { transform: rotate(17deg); animation: mossling-droop 2.2s steps(5, end) infinite; animation-delay: var(--mossling-clock); }

/* Move the creature itself; don't drag the next-move badge with the lunge. */
.enemy-stage:is(.attacking, .taking-hit):has(.mossling-figure) .actor-wrap { animation: none; }
.enemy-stage.attacking .mossling-motion { animation: mossling-attack .5s steps(6, end) both; animation-delay: 0s; }
.enemy-stage.attacking .mossling-sprout { animation: mossling-attack-leaves .5s steps(6, end) both; animation-delay: 0s; }
.enemy-stage.taking-hit .mossling-motion { animation: mossling-hit .5s steps(6, end) both; animation-delay: 0s; }
.enemy-stage.taking-hit .mossling-sprout { animation: mossling-hit-leaves .5s steps(6, end) both; animation-delay: 0s; }
.enemy-stage:is(.attacking, .taking-hit) .mossling-breathe { animation: none; }
.enemy-stage.defeated:has(.mossling-figure) .actor-wrap { animation:none;transform:none;opacity:1;filter:none; }
.enemy-stage.defeated .mossling-breathe { animation:none; }
.enemy-stage.defeated .mossling-motion { transform:scale(1.08,.76);opacity:.45;animation:mossling-collapse .62s steps(8,end) both;animation-delay:var(--mossling-death-clock); }
.enemy-stage.defeated .mossling-sprout { transform:rotate(24deg);animation:mossling-wilt .62s steps(8,end) both;animation-delay:var(--mossling-death-clock); }

@keyframes mossling-breathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.014, .977); } }
@keyframes mossling-leaves { 0%,100% { transform: rotate(-3deg); } 38% { transform: rotate(4deg); } 68% { transform: rotate(1deg); } }
@keyframes mossling-dazed { 0%,100% { transform: rotate(-2deg) scale(1.05, .88); } 50% { transform: rotate(2deg) scale(1.05, .88); } }
@keyframes mossling-droop { 0%,100% { transform: rotate(17deg); } 50% { transform: rotate(23deg); } }
@keyframes mossling-attack {
  0%,100% { transform: none; }
  14% { transform: translateX(28px) scale(1.08, .88); }
  32%,42% { transform: translate(-125px, -28px) rotate(-6deg) scale(1.07, .96); }
  64% { transform: translateX(-35px) scale(1.08, .91); }
  82% { transform: scale(.985, 1.015); }
}
@keyframes mossling-attack-leaves { 0%,100% { transform: none; } 14% { transform: rotate(-8deg); } 38% { transform: rotate(19deg); } 64% { transform: rotate(-13deg); } 82% { transform: rotate(5deg); } }
@keyframes mossling-hit {
  0%,100% { transform: none; filter: none; }
  16%,30% { transform: translateX(65px) rotate(4deg) scale(.94, .93); filter: brightness(1.6); }
  54% { transform: translateX(20px) rotate(-2deg) scale(1.055, .94); filter: none; }
  78% { transform: translateX(-6px) scale(.99, 1.01); }
}
@keyframes mossling-hit-leaves { 0%,100% { transform: none; } 20% { transform: rotate(-20deg); } 52% { transform: rotate(15deg); } 78% { transform: rotate(-5deg); } }
@keyframes mossling-collapse {0%{transform:none;opacity:1}18%{transform:scale(.97,1.035)}52%{transform:scale(1.12,.69);opacity:.65}76%,100%{transform:scale(1.08,.76);opacity:.45}}
@keyframes mossling-wilt {0%{transform:none}20%{transform:rotate(-8deg)}58%{transform:rotate(32deg)}80%,100%{transform:rotate(24deg)}}

/* A stationary compressed pose still distinguishes stun without animation. */
@media (prefers-reduced-motion: reduce) {
  .mossling-art *, .enemy-stage:has(.mossling-figure) .actor-wrap { animation: none !important; }
}
:root[data-reduce-motion="true"] :is(.mossling-art *, .enemy-stage:has(.mossling-figure) .actor-wrap) { animation: none !important; }

/* Local art preview only. The move icon is outside all moving groups. */
.enemy-figure.gloombat-figure { animation: none !important; }
.gloombat-art, .gloombat-art image { image-rendering: pixelated; }
.gloombat-art { overflow: visible; pointer-events: none; }
.gloombat-motion, .gloombat-hover { transform-origin: 836px 585px; }
.gloombat-hover { animation: gloombat-hover 1.92s steps(8, end) infinite; animation-delay: var(--bat-clock); }
.gloombat-left { --wing-side: -1; transform-origin: 716px 590px; }
.gloombat-right { --wing-side: 1; transform-origin: 956px 590px; }
.gloombat-wing { animation: gloombat-wingbeat .96s steps(6, end) infinite; animation-delay: var(--bat-clock); }

/* A raised, tighter wingbeat telegraphs the existing interruptible diving strike. */
.gloombat-figure:has(> :where(.intent.channel)) .gloombat-motion { transform: translate(18px, -62px) rotate(-5deg); animation: gloombat-aim 1.28s steps(6, end) infinite; animation-delay: var(--bat-clock); }
.gloombat-figure:has(> :where(.intent.channel)) .gloombat-hover { animation: none; }
.gloombat-figure:has(> :where(.intent.channel)) .gloombat-wing { transform: rotate(calc(var(--wing-side) * -7deg)) scale(.86, .95); animation: gloombat-ready-wing .64s steps(5, end) infinite; animation-delay: var(--bat-clock); }

/* The bite crouches forward instead of climbing into the dive. */
.gloombat-figure:has(> :where(.intent.drain)) .gloombat-motion { transform: translate(-28px, 22px) rotate(-4deg); }
.gloombat-figure:has(> :where(.intent.drain)) .gloombat-wing { animation-duration: .72s; }
.intent.drain, .intent-drain-heal { color: #f3a6ac; }
.intent-drain-heal { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; }
.intent-drain-heal .icon { width: 13px; height: 13px; }

/* An uneven, drooping flight state follows the actual stun intent. */
.gloombat-figure:has(> :where(.intent.stun)) .gloombat-motion { transform: translateY(55px) rotate(-5deg); animation: gloombat-dazed 1.8s steps(6, end) infinite; animation-delay: var(--bat-clock); }
.gloombat-figure:has(> :where(.intent.stun)) .gloombat-hover { animation: none; }
.gloombat-figure:has(> :where(.intent.stun)) .gloombat-wing { transform: rotate(calc(var(--wing-side) * 24deg)) scale(.86, .58); animation: gloombat-stun-wing 1.4s steps(4, end) infinite; animation-delay: var(--bat-clock); }
.gloombat-figure:has(> :where(.intent.stun)) .gloombat-right { animation-duration: 1.8s; }

/* Actions override the stun pose; it resumes when the action class is removed. */
.enemy-stage:is(.attacking, .taking-hit):has(.gloombat-figure) .actor-wrap { animation: none; }
.enemy-stage:is(.attacking, .taking-hit) .gloombat-hover { animation: none; }
.enemy-stage.attacking .gloombat-motion { animation: gloombat-swoop .5s steps(6, end); animation-delay: 0s; }
.enemy-stage.attacking .gloombat-wing { animation: gloombat-swoop-wing .5s steps(6, end); animation-delay: 0s; }
.enemy-stage.attacking[data-effect="drain"] .gloombat-motion { animation: gloombat-bite .6s steps(7, end); }
.enemy-stage.attacking[data-effect="drain"] .gloombat-wing { animation: gloombat-bite-wing .6s steps(7, end); }
.enemy-stage[data-effect="blood-heal"] .gloombat-body { animation: gloombat-fed .6s steps(6, end); }
.enemy-stage.taking-hit .gloombat-motion { animation: gloombat-hit .5s steps(6, end); animation-delay: 0s; }
.enemy-stage.taking-hit .gloombat-wing { animation: gloombat-hit-wing .5s steps(6, end); animation-delay: 0s; }

/* Stop hovering, fold and fall once, even across consecutive loot renders. */
.enemy-stage.defeated:has(.gloombat-figure) .actor-wrap { animation: none; transform: none; opacity: 1; filter: none; }
.enemy-stage.defeated .gloombat-hover { animation: none; }
.enemy-stage.defeated .gloombat-motion { transform: translateY(130px) rotate(10deg) scale(.94); opacity: .35; animation: gloombat-fall .55s steps(6, end) both; animation-delay: var(--bat-defeat-clock); }
.enemy-stage.defeated .gloombat-wing { transform: rotate(calc(var(--wing-side) * 33deg)) scale(.65, .48); animation: gloombat-fold .55s steps(6, end) both; animation-delay: var(--bat-defeat-clock); }

@keyframes gloombat-hover {
  0%,50%,100% { transform: translateY(0); }
  24% { transform: translateY(-24px); }
  74% { transform: translateY(-32px); }
}
@keyframes gloombat-wingbeat {
  0%,100% { transform: rotate(calc(var(--wing-side) * -4deg)); }
  16%,78% { transform: none; }
  36%,48% { transform: rotate(calc(var(--wing-side) * 22deg)) scale(.86, .58); }
}
@keyframes gloombat-dazed {
  0%,100% { transform: translate(0, 55px) rotate(-5deg); }
  48% { transform: translate(18px, 74px) rotate(4deg); }
}
@keyframes gloombat-aim {
  0%,100% { transform: translate(18px, -62px) rotate(-5deg); }
  50% { transform: translate(8px, -82px) rotate(-7deg); }
}
@keyframes gloombat-ready-wing {
  0%,100% { transform: rotate(calc(var(--wing-side) * -7deg)) scale(.86, .95); }
  45% { transform: rotate(calc(var(--wing-side) * 4deg)) scale(.82, .8); }
}
@keyframes gloombat-stun-wing {
  0%,100% { transform: rotate(calc(var(--wing-side) * 24deg)) scale(.86, .58); }
  55% { transform: rotate(calc(var(--wing-side) * 17deg)) scale(.9, .68); }
}
@keyframes gloombat-swoop {
  0%,100% { transform: none; }
  16% { transform: translate(35px, -44px) rotate(6deg); }
  34%,46% { transform: translate(-155px, 60px) rotate(-13deg); }
  72% { transform: translate(-42px, -16px) rotate(-3deg); }
}
@keyframes gloombat-swoop-wing {
  0%,100% { transform: none; }
  16% { transform: rotate(calc(var(--wing-side) * -10deg)) scale(1, .92); }
  34%,46% { transform: rotate(calc(var(--wing-side) * 28deg)) scale(.78, .5); }
  72% { transform: rotate(calc(var(--wing-side) * -5deg)); }
}
@keyframes gloombat-bite {
  0%,100% { transform: none; }
  12% { transform: translate(34px, -12px) rotate(4deg); }
  30%,57% { transform: translate(-240px, 96px) rotate(-17deg); }
  65% { transform: translate(-226px, 88px) rotate(-14deg); }
  84% { transform: translate(-65px, 24px) rotate(-5deg); }
}
@keyframes gloombat-bite-wing {
  0%,100% { transform: none; }
  30%,65% { transform: rotate(calc(var(--wing-side) * 32deg)) scale(.7, .54); }
  84% { transform: rotate(calc(var(--wing-side) * -9deg)); }
}
@keyframes gloombat-fed {
  0%,100% { filter: none; }
  28%,55% { filter: sepia(.35) saturate(1.4) brightness(1.5) drop-shadow(0 0 14px #e67391); }
}
.flight.blood .flight-body { color: #ff9cae; filter: drop-shadow(0 0 5px #9b3158); }
.combat-pop.blood-heal, .combat-pop.bite, .receipt-enemy-heal { color: #ffadb8; }
.impact-ring.blood-heal { border-color: #ec8caa90; background: radial-gradient(transparent 30%, #ae487744); }
.impact-ring.bite { border-color: #e6739166; background: none; }
.bite-mark { position: absolute; left: 50%; top: 36%; translate: -50% 0; color: #ffe3d2; animation: blood-bite-mark .55s steps(5, end) both; }
.bite-mark .icon { width: 64px; height: 64px; filter: drop-shadow(0 2px 0 #963f66); }
@keyframes blood-bite-mark { 0% { opacity: 0; transform: scale(1.3); } 25%,60% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: translateY(10px); } }
@keyframes gloombat-hit {
  0%,100% { transform: none; filter: none; }
  16%,32% { transform: translate(88px, -20px) rotate(11deg); filter: brightness(1.65); }
  58% { transform: translate(24px, 22px) rotate(-5deg); filter: none; }
  80% { transform: translate(-8px, 8px) rotate(2deg); }
}
@keyframes gloombat-hit-wing {
  0%,100% { transform: none; }
  16%,32% { transform: rotate(calc(var(--wing-side) * 30deg)) scale(.76, .48); }
  58% { transform: rotate(calc(var(--wing-side) * -8deg)); }
  80% { transform: rotate(calc(var(--wing-side) * 6deg)) scale(.96, .88); }
}
@keyframes gloombat-fall {
  0% { transform: none; opacity: 1; }
  22% { transform: translate(30px, -20px) rotate(-7deg); opacity: .9; }
  70% { transform: translateY(138px) rotate(12deg) scale(.94); opacity: .5; }
  100% { transform: translateY(130px) rotate(10deg) scale(.94); opacity: .35; }
}
@keyframes gloombat-fold {
  from { transform: none; }
  to { transform: rotate(calc(var(--wing-side) * 33deg)) scale(.65, .48); }
}

/* Both preferences keep distinct stationary stunned and defeated poses. */
@media (prefers-reduced-motion: reduce) {
  .gloombat-art *, .enemy-stage:has(.gloombat-figure) .actor-wrap { animation: none !important; }
  .bite-mark { animation: none; }
}
:root[data-reduce-motion="true"] :is(.gloombat-art *, .enemy-stage:has(.gloombat-figure) .actor-wrap) { animation: none !important; }
:root[data-reduce-motion="true"] .bite-mark { animation: none; }

/* Local trial only. Intents stay anchored outside the moving illustration. */
.enemy-figure.toad-figure { animation: none !important; }
.toad-art, .toad-art image { image-rendering: pixelated; }
.toad-art { overflow: visible; }
.toad-motion, .toad-breathe { transform-origin: var(--toad-pivot); }
.toad-throat { transform-origin: var(--throat-pivot); }
.toad-breathe { animation: toad-breathe 3.8s steps(6, end) infinite; animation-delay: var(--toad-clock); }
.elite-toad .toad-breathe { animation-duration: 4.6s; }
.toad-throat { animation: toad-mouth 3.8s steps(5, end) infinite; animation-delay: var(--toad-clock); }
.elite-toad .toad-throat { animation: toad-throat 4.6s steps(6, end) infinite; animation-delay: var(--toad-clock); }
.toad-spit { opacity: 0; fill: #b4ce68; transform: translate(var(--spit-x), var(--spit-y)); }
.elite-toad .toad-spit { fill: #d3c867; }

/* The next poison move has a visible preparatory breath, not a new turn timer. */
.toad-figure:has(> :where(.intent.poison)) .toad-breathe { animation-name: toad-ready; animation-duration: 2.4s; }
.toad-figure:has(> :where(.intent.poison)) .toad-throat { animation-name: toad-mouth-ready; animation-duration: 2.4s; }
.elite-toad:has(> :where(.intent.poison)) .toad-throat { animation-name: toad-throat-ready; }

.toad-figure:has(> :where(.intent.stun)) .toad-motion { transform: rotate(2deg) scale(1.04, .91); animation: toad-dazed 2.2s steps(5, end) infinite; animation-delay: var(--toad-clock); }
.toad-figure:has(> :where(.intent.stun)) :is(.toad-breathe, .toad-throat) { animation: none; }

.enemy-stage:is(.attacking, .taking-hit, [data-effect="poison"]):has(.toad-figure) .actor-wrap { animation: none; }
.enemy-stage:is(.attacking, .taking-hit, [data-effect="poison"]) .toad-breathe { animation: none; }
.enemy-stage.attacking .toad-motion { animation: toad-hop .52s steps(7, end); animation-delay: 0s; }
.enemy-stage.attacking .elite-toad .toad-motion { animation-name: toad-pounce; }
.enemy-stage.attacking .toad-throat { animation: none; }

/* Only the application event spits. Later poison ticks belong to the player. */
.enemy-stage[data-effect="poison"] .toad-motion { animation: toad-croak .55s steps(7, end); animation-delay: 0s; }
.enemy-stage[data-effect="poison"] .toad-throat { animation: toad-mouth-croak .55s steps(7, end); animation-delay: 0s; }
.enemy-stage[data-effect="poison"] .elite-toad .toad-throat { animation-name: toad-throat-croak; }
.enemy-stage[data-effect="poison"] .toad-spit { animation: toad-spit .52s steps(7, end); animation-delay: 0s; }
.enemy-stage[data-effect="poison"] .toad-spit-1 { animation-delay: .07s; }

/* Hits override both the preparatory breath and a persistent stunned pose. */
.enemy-stage.taking-hit .toad-motion { animation: toad-hit .5s steps(6, end); animation-delay: 0s; }
.enemy-stage.taking-hit .toad-throat { animation: toad-hit-throat .5s steps(6, end); animation-delay: 0s; }
.enemy-stage.defeated:has(.toad-figure) .actor-wrap { animation: none; transform: none; opacity: 1; filter: none; }
.enemy-stage.defeated :is(.toad-breathe, .toad-throat) { animation: none !important; }
.enemy-stage.defeated .toad-motion { transform: scale(1.08, .63); opacity: .38; animation: toad-collapse .55s steps(7, end) both; animation-delay: var(--toad-defeat-clock); }
.enemy-stage.defeated .elite-toad .toad-motion { transform: rotate(-4deg) scale(1.06, .70); animation-name: toad-elite-collapse; }
.enemy-stage.defeated .toad-spit { animation: none; opacity: 0; }

@keyframes toad-breathe { 0%,100% { transform: none; } 48% { transform: scale(1.008, .984); } }
@keyframes toad-mouth { 0%,100% { transform: none; } 48% { transform: scale(1.008, 1.055); } }
/* Expand away from the sloped jaw so the throat's upper edge stays attached. */
@keyframes toad-throat { 0%,100% { transform: none; } 45% { transform: rotate(13deg) scale(1, 1.052) rotate(-13deg); } }
@keyframes toad-ready { 0%,100% { transform: scale(1.01, .985); } 50% { transform: scale(1.018, 1.012); } }
@keyframes toad-mouth-ready { 0%,100% { transform: scale(1.01, 1.04); } 50% { transform: scale(1.015, 1.08); } }
@keyframes toad-throat-ready { 0%,100% { transform: rotate(13deg) scale(1, 1.045) rotate(-13deg); } 50% { transform: rotate(13deg) scale(1, 1.12) rotate(-13deg); } }
@keyframes toad-dazed { 0%,100% { transform: rotate(2deg) scale(1.04, .91); } 48% { transform: rotate(-2deg) scale(1.04, .89); } }
@keyframes toad-hop {
  0%,100% { transform: none; }
  15% { transform: translateX(25px) scale(1.1, .8); }
  35% { transform: translate(-120px, -110px) rotate(-4deg) scale(.97, 1.04); }
  53% { transform: translate(-80px, -34px) rotate(-2deg); }
  70% { transform: translateX(-25px) scale(1.07, .88); }
  86% { transform: scale(.99, 1.01); }
}
@keyframes toad-pounce {
  0%,100% { transform: none; }
  15% { transform: translateX(45px) scale(1.05, .9); }
  35%,45% { transform: translate(-175px, -44px) rotate(-5deg) scale(1.04, .96); }
  68% { transform: translateX(-38px) scale(1.05, .92); }
  84% { transform: scale(.99, 1.015); }
}
@keyframes toad-croak {
  0%,100% { transform: none; }
  20%,32% { transform: translateX(22px) scale(1.045, .96); }
  48% { transform: translateX(-45px) scale(.985, 1.025); }
  70% { transform: translateX(12px) scale(1.025, .97); }
}
@keyframes toad-mouth-croak { 0%,100% { transform: none; } 20%,32% { transform: scale(1.035, 1.18); } 48% { transform: scale(1.025, 1.12); } 70% { transform: scale(1.01, 1.08); } }
@keyframes toad-throat-croak { 0%,100% { transform: none; } 20%,32% { transform: rotate(13deg) scale(1, 1.25) rotate(-13deg); } 48% { transform: none; } 70% { transform: rotate(13deg) scale(1, 1.07) rotate(-13deg); } }
@keyframes toad-spit {
  0%,29% { opacity: 0; transform: translate(var(--spit-x), var(--spit-y)) scale(.5); }
  35% { opacity: 1; transform: translate(var(--spit-x), var(--spit-y)); }
  64% { opacity: 1; transform: translate(calc(var(--spit-x) - 330px), calc(var(--spit-y) - 40px)) scale(.85); }
  100% { opacity: 0; transform: translate(calc(var(--spit-x) - 650px), calc(var(--spit-y) + 65px)) scale(.45); }
}
@keyframes toad-hit {
  0%,100% { transform: none; filter: none; }
  16%,30% { transform: translateX(70px) rotate(4deg) scale(.95, .91); filter: brightness(1.65); }
  55% { transform: translateX(18px) rotate(-2deg) scale(1.055, .95); filter: none; }
  80% { transform: translateX(-5px) scale(.99, 1.01); }
}
@keyframes toad-hit-throat { 0%,100% { transform: none; } 20% { transform: scale(1, 1.08); } 55% { transform: scale(1, 1.025); } }
.enemy-stage.taking-hit .elite-toad .toad-throat { animation-name: toad-hit-elite-throat; }
@keyframes toad-hit-elite-throat { 0%,100% { transform: none; } 20% { transform: rotate(13deg) scale(1, 1.08) rotate(-13deg); } 55% { transform: rotate(13deg) scale(1, 1.025) rotate(-13deg); } }
@keyframes toad-collapse { 0% { transform: none; opacity: 1; } 22% { transform: scale(.94, 1.035); opacity: .9; } 65% { transform: scale(1.1, .59); opacity: .5; } 100% { transform: scale(1.08, .63); opacity: .38; } }
@keyframes toad-elite-collapse { 0% { transform: none; opacity: 1; } 22% { transform: rotate(3deg) scale(.98, 1.02); opacity: .9; } 65% { transform: rotate(-5deg) scale(1.08, .66); opacity: .5; } 100% { transform: rotate(-4deg) scale(1.06, .70); opacity: .38; } }

@media (prefers-reduced-motion: reduce) {
  .toad-art *, .enemy-stage:has(.toad-figure) .actor-wrap { animation: none !important; }
}
:root[data-reduce-motion="true"] :is(.toad-art *, .enemy-stage:has(.toad-figure) .actor-wrap) { animation: none !important; }

/* Art study only. Match the painting's coarse motion and keep feet/intents fixed. */
.enemy-figure.warden-figure{animation:none!important;width:min(100%,310px,calc((var(--actor-height,370px) - var(--art-clearance,28px))*var(--warden-ratio)))}
.warden-art,.warden-art image{image-rendering:pixelated}.warden-art{overflow:visible}
.warden-motion,.warden-breathe{transform-origin:var(--warden-foot)}
.warden-left{transform-origin:var(--warden-left)}.warden-right{transform-origin:var(--warden-right)}
.warden-breathe{animation:warden-breathe 5.6s steps(5,end) infinite;animation-delay:var(--warden-clock)}
.warden-left{animation:warden-arm 5.6s steps(5,end) infinite;animation-delay:var(--warden-clock)}
.warden-right{animation:warden-arm-back 5.6s steps(5,end) infinite;animation-delay:var(--warden-clock)}
.briarBrute .warden-breathe{animation-duration:4.8s}
.warden-cast-earth,.warden-poison{opacity:0;fill:#bb874b}
.warden-poison{fill:#b9ba71}
.warden-figure:has(>:where(.intent.charge,.intent.heavy,.intent.channel,.intent.root)) .warden-breathe{animation-name:warden-ready;animation-duration:2.6s}
.warden-figure:has(>:where(.intent.charge,.intent.heavy)) .warden-left{transform:rotate(-7deg);animation:none}
.warden-figure:has(>:where(.intent.channel,.intent.root)) .warden-right{transform:rotate(7deg);animation:none}
.warden-figure:has(>:where(.intent.stun)) .warden-motion{animation:warden-dazed 2.6s steps(5,end) infinite;animation-delay:var(--warden-clock)}
.warden-figure:has(>:where(.intent.stun)) :is(.warden-breathe,.warden-left,.warden-right){animation:none}
.enemy-stage:is(.attacking,.taking-hit,[data-effect=root],[data-effect=poison],[data-effect=ward]):has(.warden-figure) .actor-wrap{animation:none}
.enemy-stage:is(.attacking,.taking-hit,[data-effect=root],[data-effect=poison],[data-effect=ward]) :is(.warden-breathe,.warden-left,.warden-right){animation:none}
.enemy-stage.attacking .warden-motion{animation:warden-strike .56s steps(7,end);animation-delay:0s}
.enemy-stage.attacking .warden-left{animation:warden-swipe .56s steps(7,end);animation-delay:0s}
.enemy-stage.attacking .briarBrute .warden-motion{animation-name:brute-strike}
.enemy-stage.attacking .briarBrute .warden-left{animation-name:brute-fist}
.enemy-stage.attacking[data-heavy=true] .warden-motion{animation:warden-slam .6s steps(8,end);animation-delay:0s}
.enemy-stage.attacking[data-heavy=true] .warden-left{animation:warden-slam-arm .6s steps(8,end);animation-delay:0s}
.enemy-stage.attacking[data-heavy=true] .warden-right{animation:warden-root-back .6s steps(8,end);animation-delay:0s}
.enemy-stage.attacking[data-heavy=true] .warden-cast-earth{animation:warden-earth .6s steps(6,end)}
.enemy-stage[data-effect=root] .warden-motion{animation:warden-root-cast .6s steps(8,end);animation-delay:0s}
.enemy-stage[data-effect=root] .warden-left{animation:warden-root-arm .6s steps(8,end);animation-delay:0s}
.enemy-stage[data-effect=root] .warden-right{animation:warden-root-back .6s steps(8,end);animation-delay:0s}
.enemy-stage[data-effect=root] .warden-cast-earth{animation:warden-earth .6s steps(6,end)}
.enemy-stage[data-effect=ward] .warden-motion{animation:warden-channel .6s steps(6,end);animation-delay:0s}
.enemy-stage[data-effect=poison] .warden-motion{animation:warden-poison-cast .55s steps(6,end);animation-delay:0s}
.enemy-stage[data-effect=poison] .warden-right{animation:warden-root-back .55s steps(6,end);animation-delay:0s}
.enemy-stage[data-effect=poison] .warden-poison{animation:warden-spores .55s steps(6,end)}
.enemy-stage.taking-hit .warden-motion{animation:warden-hit .5s steps(6,end);animation-delay:0s}
.enemy-stage.taking-hit .warden-left{animation:warden-hit-arm .5s steps(6,end);animation-delay:0s}
.enemy-stage.defeated:has(.warden-figure) .actor-wrap{animation:none;transform:none;opacity:1;filter:none}
.enemy-stage.defeated :is(.warden-breathe,.warden-left,.warden-right){animation:none!important}
.enemy-stage.defeated .warden-motion{transform:rotate(5deg) scale(1.03,.69);opacity:.35;animation:warden-fall .65s steps(8,end) both;animation-delay:var(--warden-death-clock)}
.enemy-stage.defeated .briarBrute .warden-motion{animation-name:brute-fall;transform:scale(1.08,.65)}
.player-roots{position:absolute;bottom:0;pointer-events:none;overflow:visible;width:min(100%,310px,calc((var(--actor-height,370px) - var(--art-clearance,28px))*1.04889));height:auto;max-height:calc(var(--actor-height,370px) - var(--art-clearance,28px));filter:none;animation:none!important;z-index:2}
.root-bind{transform-origin:600px 1150px;animation:root-rise .58s steps(7,end) both;animation-delay:var(--root-age)}
.root-right{animation-name:root-rise-right}.root-cross{animation-name:root-wrap}
.root-ground{animation:root-earth .55s steps(5,end) both;animation-delay:var(--root-age)}
.roots-release .root-bind{animation:root-break .55s steps(7,end) both;animation-delay:0s}
.roots-release .root-right{animation-name:root-break-right}.roots-release .root-ground{animation:root-clear .55s steps(6,end) both}
.root-status{color:#edc485!important;background:#312b2a!important;border-color:#967c57!important;white-space:nowrap}
.root-status .icon{width:16px;height:16px}.intent.root{color:#edc485}.combat-pop.roots,.combat-pop.root-release{color:#f3cd8b}.impact-ring.roots{border-color:#c59a59}
@keyframes warden-breathe{0%,100%{transform:none}50%{transform:scale(1.004,.988)}}
@keyframes warden-arm{0%,100%{transform:none}50%{transform:rotate(.8deg)}}
@keyframes warden-arm-back{0%,100%{transform:none}50%{transform:rotate(-.7deg)}}
@keyframes warden-ready{0%,100%{transform:scale(1.008,.977)}50%{transform:scale(1.003,.99)}}
@keyframes warden-dazed{0%,100%{transform:rotate(2deg) scale(1,.96)}50%{transform:rotate(-1.5deg) scale(1.01,.94)}}
@keyframes warden-strike{0%,100%{transform:none}18%{transform:rotate(3deg)}40%,51%{transform:translateX(-65px) rotate(-6deg)}75%{transform:rotate(1deg)}}
@keyframes warden-swipe{0%,100%{transform:none}18%{transform:rotate(-10deg)}40%,51%{transform:rotate(15deg)}75%{transform:rotate(-2deg)}}
@keyframes brute-strike{0%,100%{transform:none}18%{transform:translateX(18px) scale(1.035,.93)}42%,53%{transform:translateX(-64px) rotate(-3deg) scale(1.015,.98)}75%{transform:scale(1.04,.94)}}
@keyframes brute-fist{0%,100%{transform:none}18%{transform:rotate(-13deg)}42%,53%{transform:rotate(23deg) translateX(-15px)}75%{transform:rotate(4deg)}}
@keyframes warden-slam{0%,100%{transform:none}25%{transform:rotate(2deg) scale(.99,1.025)}48%,61%{transform:translateX(-42px) rotate(-2deg) scale(1.06,.86)}78%{transform:translateX(-8px) scale(1.015,.97)}}
@keyframes warden-slam-arm{0%,100%{transform:none}25%{transform:rotate(18deg)}48%,61%{transform:rotate(-6deg) translateY(20px)}78%{transform:rotate(2deg)}}
@keyframes warden-root-cast{0%,100%{transform:none}22%{transform:rotate(2deg) scale(.995,1.012)}48%,64%{transform:rotate(-3deg) scale(1.035,.95)}84%{transform:scale(1.008,.985)}}
@keyframes warden-root-arm{0%,100%{transform:none}22%{transform:rotate(7deg)}48%,64%{transform:rotate(-5deg) translateY(18px)}84%{transform:rotate(2deg)}}
@keyframes warden-root-back{0%,100%{transform:none}22%{transform:rotate(-12deg)}48%,64%{transform:rotate(13deg)}84%{transform:rotate(3deg)}}
@keyframes warden-earth{0%,25%,100%{opacity:0}48%,70%{opacity:1}}
@keyframes warden-channel{0%,100%{transform:none}38%,58%{transform:scale(1.03,.95)}78%{transform:scale(.995,1.01)}}
@keyframes warden-poison-cast{0%,100%{transform:none}25%{transform:rotate(2deg)}50%{transform:rotate(-2deg) scale(1.01,.98)}}
@keyframes warden-spores{0%,20%,100%{opacity:0;translate:0 0}40%{opacity:1;translate:-40px 0}85%{opacity:.4;translate:-125px 60px}}
@keyframes warden-hit{0%,100%{transform:none;filter:none}18%{transform:translateX(36px) rotate(4deg);filter:brightness(1.55)}44%{transform:translateX(18px) rotate(2deg);filter:none}72%{transform:rotate(-1deg)}}
@keyframes warden-hit-arm{0%,100%{transform:none}25%{transform:rotate(-8deg)}60%{transform:rotate(3deg)}}
@keyframes warden-fall{0%{transform:none;opacity:1}20%{transform:rotate(-2deg) scale(1,.96)}48%{transform:rotate(6deg) scale(1.03,.72)}72%,100%{transform:rotate(5deg) scale(1.03,.69);opacity:.35}}
@keyframes brute-fall{0%{transform:none;opacity:1}20%{transform:scale(1.02,.96)}48%{transform:scale(1.1,.61)}72%,100%{transform:scale(1.08,.65);opacity:.35}}
@keyframes root-rise{0%{transform:scaleY(.02);opacity:0}18%{opacity:1}75%{transform:scaleY(1.04)}100%{transform:none;opacity:1}}
@keyframes root-rise-right{0%,10%{transform:scaleY(.02);opacity:0}27%{opacity:1}85%{transform:scaleY(1.025)}100%{transform:none;opacity:1}}
@keyframes root-wrap{0%,22%{transform:scale(.5,.1);opacity:0}45%{opacity:1}85%{transform:scale(1.02,1)}100%{transform:none;opacity:1}}
@keyframes root-earth{0%{opacity:0;translate:0 15px}38%,100%{opacity:1;translate:0 0}}
@keyframes root-break{0%{transform:none;opacity:1}28%{transform:translate(-12px,8px) rotate(-2deg);opacity:1}100%{transform:translate(-45px,100px) rotate(-10deg) scaleY(.3);opacity:0}}
@keyframes root-break-right{0%{transform:none;opacity:1}28%{transform:translate(12px,8px) rotate(2deg);opacity:1}100%{transform:translate(45px,100px) rotate(10deg) scaleY(.3);opacity:0}}
@keyframes root-clear{0%{opacity:1}100%{opacity:0}}
@media(prefers-reduced-motion:reduce){.warden-art *,.player-roots *{animation:none!important}.warden-poison,.warden-cast-earth,.roots-release{display:none}.warden-figure:has(>.intent.stun) .warden-motion{transform:rotate(2deg) scale(1,.96)}}
html[data-reduce-motion=true] :is(.warden-art *,.player-roots *){animation:none!important}
html[data-reduce-motion=true] :is(.warden-poison,.warden-cast-earth,.roots-release){display:none}
html[data-reduce-motion=true] .warden-figure:has(>.intent.stun) .warden-motion{transform:rotate(2deg) scale(1,.96)}

/* Local Rust Sentry study. The intent stays outside every moving group. */
.enemy-figure.sentry-figure{animation:none!important;width:min(100%,310px,calc((var(--actor-height,370px) - var(--art-clearance,28px))*var(--sentry-ratio)))}
.sentry-art,.sentry-art image{image-rendering:pixelated}.sentry-art{overflow:visible}
.sentry-motion,.sentry-idle{transform-origin:520px 1169px}
.sentry-head{transform-origin:674px 438px}.sentry-sword{transform-origin:553px 612px}.sentry-arm{transform-origin:1080px 557px}
.sentry-idle{animation:sentry-breathe 4.8s steps(5,end) infinite;animation-delay:var(--sentry-clock)}
.sentry-head{animation:sentry-watch 4.8s steps(5,end) infinite;animation-delay:var(--sentry-clock)}
.sentry-sword{animation:sentry-sword-idle 4.8s steps(5,end) infinite;animation-delay:var(--sentry-clock)}
.sentry-arm{animation:sentry-arm-idle 4.8s steps(5,end) infinite;animation-delay:var(--sentry-clock)}
.sentry-block-sparks{opacity:0;pointer-events:none}

/* Anticipation before the guard move; a firmer stance while block is active. */
.sentry-figure:has(>:where(.intent.guard)) .sentry-idle{animation-name:sentry-ready}
.sentry-figure:has(>:where(.intent.guard)) .sentry-sword{animation:none;transform:rotate(12deg)}
.enemy-stage:has(.enemy-ward) .sentry-sword{animation:none;transform:rotate(32deg)}
.enemy-stage:has(.enemy-ward) .sentry-arm{animation:none;transform:rotate(8deg)}
.enemy-stage:has(.enemy-ward) .sentry-head{animation:none;transform:translate(-8px,8px) rotate(-2deg)}

/* An interrupted guard drops visibly; hitting a stunned Sentry still recoils. */
.enemy-stage .sentry-figure:has(>:where(.intent.stun)) .sentry-motion{transform:rotate(2deg) scale(1,.98);animation:sentry-dazed 2.4s steps(5,end) infinite;animation-delay:var(--sentry-clock)}
.enemy-stage .sentry-figure:has(>:where(.intent.stun)) .sentry-idle{animation:none}
.enemy-stage .sentry-figure:has(>:where(.intent.stun)) .sentry-head{animation:none;transform:translateY(24px) rotate(7deg)}
.enemy-stage .sentry-figure:has(>:where(.intent.stun)) .sentry-sword{animation:none;transform:rotate(-8deg)}
.enemy-stage .sentry-figure:has(>:where(.intent.stun)) .sentry-arm{animation:none;transform:rotate(-5deg)}

.enemy-stage:is(.attacking,.taking-hit,[data-effect=ward]):has(.sentry-figure) .actor-wrap{animation:none;filter:none}
.enemy-stage:is(.attacking,.taking-hit,[data-effect=ward]) .sentry-idle{animation:none}
.enemy-stage.attacking .sentry-motion{animation:sentry-strike .58s steps(8,end);animation-delay:0s}
.enemy-stage.attacking .sentry-sword{animation:sentry-cut .58s steps(8,end);animation-delay:0s}
.enemy-stage.attacking .sentry-head{animation:sentry-strike-head .58s steps(8,end);animation-delay:0s}
.enemy-stage.attacking .sentry-arm{animation:sentry-counterweight .58s steps(8,end);animation-delay:0s}
.enemy-stage[data-effect=ward] .sentry-motion{animation:sentry-brace .58s steps(7,end);animation-delay:0s}
.enemy-stage[data-effect=ward] .sentry-sword{animation:sentry-raise .58s steps(7,end) both;animation-delay:0s}
.enemy-stage[data-effect=ward] .sentry-arm{animation:sentry-guard-arm .58s steps(7,end) both;animation-delay:0s}
.enemy-stage.taking-hit .sentry-motion{animation:sentry-hit .5s steps(6,end);animation-delay:0s}
.enemy-stage.taking-hit .sentry-head{animation:sentry-head-hit .5s steps(6,end);animation-delay:0s}
.enemy-stage.taking-hit .sentry-sword{animation:sentry-sword-hit .5s steps(6,end);animation-delay:0s}
.enemy-stage.taking-hit .sentry-arm{animation:sentry-arm-hit .5s steps(6,end);animation-delay:0s}
.enemy-stage[data-sentry-block=full] .sentry-motion{animation:sentry-parry .5s steps(6,end);animation-delay:0s}
.enemy-stage[data-sentry-block=full] .sentry-head{animation:none;transform:translateY(9px) rotate(-2deg)}
.enemy-stage[data-sentry-block=full] .sentry-sword{animation:sentry-parry-blade .5s steps(6,end);animation-delay:0s}
.enemy-stage[data-sentry-block] .sentry-block-sparks{animation:sentry-sparks .5s steps(5,end);animation-delay:0s}
.enemy-stage[data-sentry-action=interrupt] .sentry-motion{animation:sentry-hit .55s steps(7,end);animation-delay:0s}
.enemy-stage[data-sentry-action=interrupt] .sentry-sword{animation:sentry-guard-break .55s steps(7,end) both;animation-delay:0s}
.enemy-stage[data-sentry-action=interrupt] .sentry-head{animation:sentry-head-hit .55s steps(7,end);animation-delay:0s}

/* Hold the last pose across loot renders instead of restarting the fall. */
.enemy-stage.defeated:has(.sentry-figure) .actor-wrap{animation:none;transform:none;opacity:1;filter:none}
.enemy-stage.defeated .sentry-idle{animation:none}
.enemy-stage.defeated .sentry-motion{transform:rotate(-7deg) scale(1,.7);opacity:.4;animation:sentry-collapse .64s steps(8,end) both;animation-delay:var(--sentry-death-clock)}
.enemy-stage.defeated .sentry-head{transform:translate(-15px,40px) rotate(-12deg);animation:sentry-head-fall .64s steps(8,end) both;animation-delay:var(--sentry-death-clock)}
.enemy-stage.defeated .sentry-sword{transform:rotate(-12deg);animation:sentry-sword-fall .64s steps(8,end) both;animation-delay:var(--sentry-death-clock)}
.enemy-stage.defeated .sentry-arm{transform:rotate(-10deg);animation:none}

@keyframes sentry-breathe{0%,100%{transform:none}50%{transform:scale(1.002,.993)}}
@keyframes sentry-watch{0%,100%{transform:none}50%{transform:translateY(6px) rotate(-.7deg)}}
@keyframes sentry-sword-idle{0%,100%{transform:none}50%{transform:rotate(1.2deg)}}
@keyframes sentry-arm-idle{0%,100%{transform:none}50%{transform:rotate(-.6deg)}}
@keyframes sentry-ready{0%,100%{transform:scale(1,.987)}50%{transform:scale(1.004,.995)}}
@keyframes sentry-dazed{0%,100%{transform:rotate(2deg) scale(1,.98)}50%{transform:rotate(-1deg) scale(1,.975)}}
@keyframes sentry-strike{0%,100%{transform:none}20%{transform:translateX(22px) rotate(2deg)}44%,56%{transform:translateX(-75px) rotate(-4deg)}78%{transform:translateX(-20px) rotate(-1deg)}}
@keyframes sentry-cut{0%,100%{transform:none}20%{transform:rotate(-20deg)}44%,56%{transform:rotate(38deg) translateX(-18px)}78%{transform:rotate(13deg)}}
@keyframes sentry-strike-head{0%,100%{transform:none}20%{transform:rotate(3deg)}44%,56%{transform:translate(-12px,8px) rotate(-5deg)}78%{transform:rotate(-1deg)}}
@keyframes sentry-counterweight{0%,100%{transform:none}20%{transform:rotate(5deg)}44%,56%{transform:rotate(-11deg)}78%{transform:rotate(-3deg)}}
@keyframes sentry-brace{0%,100%{transform:none}28%{transform:translateX(16px)}52%,72%{transform:rotate(-2deg) scale(1.01,.975)}}
@keyframes sentry-raise{0%{transform:none}28%{transform:rotate(10deg)}52%,72%{transform:rotate(36deg)}100%{transform:rotate(32deg)}}
@keyframes sentry-guard-arm{0%{transform:none}52%,72%{transform:rotate(11deg)}100%{transform:rotate(8deg)}}
@keyframes sentry-hit{0%,100%{transform:none;filter:none}20%{transform:translateX(40px) rotate(5deg);filter:brightness(1.45)}44%{transform:translateX(16px) rotate(2deg);filter:none}72%{transform:rotate(-1deg)}}
@keyframes sentry-head-hit{0%,100%{transform:none}20%{transform:rotate(9deg)}50%{transform:translateY(8px) rotate(3deg)}}
@keyframes sentry-sword-hit{0%,100%{transform:none}20%{transform:rotate(-10deg)}58%{transform:rotate(4deg)}}
@keyframes sentry-arm-hit{0%,100%{transform:none}20%{transform:rotate(-6deg)}58%{transform:rotate(3deg)}}
@keyframes sentry-parry{0%,100%{transform:none}24%{transform:translateX(20px) scale(1.005,.985)}48%{transform:translateX(-10px) rotate(-1deg)}76%{transform:translateX(5px)}}
@keyframes sentry-parry-blade{0%{transform:rotate(32deg)}24%{transform:rotate(24deg)}48%{transform:rotate(40deg)}76%{transform:rotate(15deg)}100%{transform:none}}
@keyframes sentry-sparks{0%,10%,100%{opacity:0;transform:none}24%,44%{opacity:1;transform:translate(-20px,-15px)}76%{opacity:.5;transform:translate(-60px,10px)}}
@keyframes sentry-guard-break{0%{transform:rotate(32deg)}24%{transform:rotate(40deg)}58%{transform:rotate(-15deg)}100%{transform:rotate(-8deg)}}
@keyframes sentry-collapse{0%{transform:none;opacity:1}22%{transform:rotate(2deg) scale(1,.97)}52%{transform:rotate(-8deg) scale(1,.67)}78%,100%{transform:rotate(-7deg) scale(1,.7);opacity:.4}}
@keyframes sentry-head-fall{0%{transform:none}35%{transform:rotate(-5deg)}78%,100%{transform:translate(-15px,40px) rotate(-12deg)}}
@keyframes sentry-sword-fall{0%{transform:none}40%{transform:rotate(-18deg)}78%,100%{transform:rotate(-12deg)}}
@media(prefers-reduced-motion:reduce){.sentry-art *,.enemy-stage:has(.sentry-figure) .actor-wrap{animation:none!important}.sentry-block-sparks{display:none}}
html[data-reduce-motion=true] :is(.sentry-art *,.enemy-stage:has(.sentry-figure) .actor-wrap){animation:none!important}
html[data-reduce-motion=true] .sentry-block-sparks{display:none}

/* Light, flame and iron have separate clocks. Intent never rides on the cage. */
.enemy-figure.wisp-figure{animation:none!important;margin-bottom:0;width:min(100%,235px,calc((var(--actor-height,370px) - var(--art-clearance,28px))*var(--wisp-ratio)))}
.wisp-art,.wisp-art image{image-rendering:pixelated}.wisp-art{overflow:visible}
.wisp-motion,.wisp-hover{transform-origin:640px 740px}.wisp-swing{transform-origin:645px 200px}
.wisp-flame,.wisp-core{transform-origin:653px 918px}.wisp-tongue{transform-origin:648px 700px}.wisp-tail{transform-origin:630px 1030px}
.wisp-hover{animation:wisp-hover 3.8s steps(12,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-swing{animation:wisp-swing 4.7s steps(14,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-core{animation:wisp-core 1.37s steps(1,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-tongue{animation:wisp-tongue .83s steps(1,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-tail{animation:wisp-tail 1.13s steps(1,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-light{opacity:.85;animation:wisp-light 1.37s steps(1,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-ember{opacity:0;animation:wisp-ember 2.4s steps(6,end) infinite;animation-delay:var(--wisp-clock)}
.wisp-ember.e2{animation-delay:calc(var(--wisp-clock) - .8s)}.wisp-ember.e3{animation-delay:calc(var(--wisp-clock) - 1.6s)}
.wisp-burst,.wisp-smoke{opacity:0;pointer-events:none}.wisp-burst{transform-origin:520px 760px}

/* A held charge is legible even when the player pauses before guessing. */
.wisp-figure:has(>:where(.intent.channel,.intent.heavy)) .wisp-flame{transform:scale(1.05,1.13);filter:brightness(1.13)}
.wisp-figure:has(>:where(.intent.channel,.intent.heavy)) .wisp-tongue{animation-duration:.53s}
.wisp-figure:has(>:where(.intent.channel,.intent.heavy)) .wisp-tail{animation-duration:.67s}
.wisp-figure:has(>:where(.intent.channel,.intent.heavy)) .wisp-light{opacity:1;animation-name:wisp-hot-light}
.wisp-figure:has(>:where(.intent.channel,.intent.heavy)) .wisp-swing{animation-duration:2.1s}

/* Stun leaves a small living ember, not a second defeat. */
.enemy-stage .wisp-figure:has(>:where(.intent.stun)) .wisp-motion{transform:translateY(32px) rotate(5deg)}
.enemy-stage .wisp-figure:has(>:where(.intent.stun)) .wisp-flame{transform:scale(.76,.62);filter:brightness(.72)}
.enemy-stage .wisp-figure:has(>:where(.intent.stun)) .wisp-tongue{animation-duration:1.7s}
.enemy-stage .wisp-figure:has(>:where(.intent.stun)) .wisp-tail{transform:scale(.7,.35);animation:none;opacity:.45}
.enemy-stage .wisp-figure:has(>:where(.intent.stun)) .wisp-light{animation:none;opacity:.16}
.enemy-stage .wisp-figure:has(>:where(.intent.stun)) .wisp-embers{display:none}

.enemy-stage:is(.attacking,.taking-hit,[data-wisp-action]):has(.wisp-figure) .actor-wrap{animation:none;filter:none}
.enemy-stage:is(.attacking,.taking-hit,[data-wisp-action]) .wisp-hover{animation:none}
.enemy-stage[data-wisp-action=charge] .wisp-flame{animation:wisp-charge .6s steps(6,end);animation-delay:0s}
.enemy-stage[data-wisp-action=charge] .wisp-light{animation:wisp-charge-light .6s steps(6,end);animation-delay:0s}
.enemy-stage.attacking .wisp-motion{animation:wisp-tap .58s steps(8,end);animation-delay:0s}
.enemy-stage.attacking .wisp-flame{animation:wisp-spit .58s steps(7,end);animation-delay:0s}
.enemy-stage.attacking .wisp-burst{animation:wisp-burst .58s steps(7,end);animation-delay:0s}
.enemy-stage.attacking .wisp-light{animation:wisp-flash .58s steps(7,end);animation-delay:0s}
.enemy-stage[data-wisp-action=blast] .wisp-motion{animation:wisp-blast .62s steps(9,end);animation-delay:0s}
.enemy-stage[data-wisp-action=blast] .wisp-flame{animation:wisp-flare .62s steps(8,end);animation-delay:0s}
.enemy-stage[data-wisp-action=blast] .wisp-burst{animation:wisp-big-burst .62s steps(8,end);animation-delay:0s}
.enemy-stage[data-wisp-action=blast] .wisp-light{animation:wisp-flash .62s steps(8,end);animation-delay:0s}
.enemy-stage.taking-hit .wisp-motion{animation:wisp-hit .5s steps(7,end);animation-delay:0s}
.enemy-stage.taking-hit .wisp-flame{animation:wisp-gutter .5s steps(6,end);animation-delay:0s}
.enemy-stage.taking-hit .wisp-light{animation:wisp-hit-light .5s steps(6,end);animation-delay:0s}
.enemy-stage[data-wisp-action=interrupt] .wisp-flame{animation:wisp-interrupt .6s steps(7,end) both;animation-delay:0s}
.enemy-stage[data-wisp-action=interrupt] .wisp-motion{animation:wisp-rock .6s steps(7,end);animation-delay:0s}
.enemy-stage[data-wisp-action=interrupt] .wisp-light{animation:none;opacity:.16}
.enemy-stage[data-wisp-action=interrupt] .wisp-tail{animation:none;transform:scale(.7,.35);opacity:.45}

/* One extinction timeline continues over damage, gold and health-growth renders. */
.enemy-stage.defeated:has(.wisp-figure) .actor-wrap{animation:none;transform:none;opacity:1;filter:none}
.enemy-stage.defeated .wisp-hover,.enemy-stage.defeated .wisp-swing{animation:none}
.enemy-stage.defeated .wisp-motion{transform:translateY(120px) rotate(-8deg);opacity:.5;animation:wisp-fall .64s steps(9,end) both;animation-delay:var(--wisp-death-clock)}
.enemy-stage.defeated .wisp-flame{opacity:0;transform:scale(.18,.05);animation:wisp-extinguish .5s steps(7,end) both;animation-delay:var(--wisp-death-clock)}
.enemy-stage.defeated .wisp-tail{opacity:0;animation:wisp-tail-out .35s steps(5,end) both;animation-delay:var(--wisp-death-clock)}
.enemy-stage.defeated .wisp-light{opacity:0;animation:wisp-light-out .5s steps(7,end) both;animation-delay:var(--wisp-death-clock)}
.enemy-stage.defeated .wisp-core,.enemy-stage.defeated .wisp-tongue{animation:none}
.enemy-stage.defeated .wisp-embers,.enemy-stage.defeated .wisp-burst{display:none}
.enemy-stage.defeated .wisp-smoke{animation:wisp-smoke .64s steps(7,end) both;animation-delay:var(--wisp-death-clock)}

@keyframes wisp-hover{0%,100%{transform:translateY(0)}50%{transform:translateY(-27px)}}
@keyframes wisp-swing{0%,100%{transform:rotate(-.7deg)}43%{transform:rotate(1.3deg)}74%{transform:rotate(.2deg)}}
@keyframes wisp-core{0%,100%{transform:none}18%{transform:scale(1.02,.97)}39%{transform:scale(.98,1.02)}56%{transform:scale(1.03,.98)}78%{transform:scale(.99,1.01)}}
@keyframes wisp-tongue{0%,100%{transform:skewX(-3deg) scale(.98,1)}16%{transform:skewX(6deg) scale(.91,.85)}35%{transform:skewX(-5deg) scale(1.04,1.08)}58%{transform:skewX(2deg) scale(.96,.92)}79%{transform:skewX(-7deg) scale(.95,1.04)}}
@keyframes wisp-tail{0%,100%{transform:skewX(3deg) scaleY(.94)}22%{transform:skewX(-8deg) scaleY(.76)}41%{transform:skewX(6deg) scaleY(1.04)}67%{transform:skewX(-4deg) scaleY(.87)}83%{transform:skewX(8deg) scaleY(.98)}}
@keyframes wisp-light{0%,100%{opacity:.85}18%{opacity:.64}39%{opacity:.98}56%{opacity:.73}78%{opacity:.91}}
@keyframes wisp-hot-light{0%,100%{opacity:1}18%{opacity:.87}39%{opacity:1}56%{opacity:.9}78%{opacity:1}}
@keyframes wisp-ember{0%,13%,80%,100%{opacity:0;transform:none}18%{opacity:.65;transform:translate(0,-12px)}40%{opacity:.5;transform:translate(12px,-44px)}65%{opacity:.2;transform:translate(-10px,-82px)}}
@keyframes wisp-charge{0%,100%{transform:scale(1.05,1.13)}27%{transform:scale(.92,.83)}60%{transform:scale(1.08,1.2)}}
@keyframes wisp-charge-light{0%{opacity:.75}27%{opacity:.45}60%,100%{opacity:1}}
@keyframes wisp-tap{0%,100%{transform:none}20%{transform:translateX(18px) rotate(2deg)}45%,58%{transform:translate(-64px,-5px) rotate(-4deg)}80%{transform:translateX(-15px)}}
@keyframes wisp-spit{0%,100%{transform:none}20%{transform:scale(.92,.88)}45%,58%{transform:skewX(5deg) scale(1.1,1.08)}80%{transform:scale(.94,.9)}}
@keyframes wisp-blast{0%,100%{transform:none}24%{transform:translate(25px,8px) rotate(3deg)}43%,56%{transform:translate(-110px,-20px) rotate(-8deg)}78%{transform:translate(22px,10px) rotate(4deg)}}
@keyframes wisp-flare{0%{transform:scale(1.05,1.13)}24%{transform:scale(.8,.7)}43%,56%{transform:scale(1.16,1.3);filter:brightness(1.25)}78%{transform:scale(.8,.74);filter:none}100%{transform:none}}
@keyframes wisp-burst{0%,25%,80%,100%{opacity:0;transform:scale(.2,.4)}42%,58%{opacity:1;transform:scale(.7,.75)}70%{opacity:.4;transform:translateX(-25px) scale(.9,.45)}}
@keyframes wisp-big-burst{0%,25%,92%,100%{opacity:0;transform:scale(.2,.4)}43%,56%{opacity:1;transform:scale(1.35,1.15)}75%{opacity:.4;transform:translateX(-28px) scale(1.5,.6)}}
@keyframes wisp-flash{0%,100%{opacity:.85}24%{opacity:.35}43%,58%{opacity:1}78%{opacity:.45}}
@keyframes wisp-hit{0%,100%{transform:none;filter:none}22%{transform:translate(45px,8px) rotate(8deg);filter:brightness(1.25)}48%{transform:translateX(12px) rotate(-4deg);filter:none}76%{transform:rotate(2deg)}}
@keyframes wisp-gutter{0%,100%{transform:none}22%{transform:translateX(18px) scale(.85,.7)}48%{transform:scale(1.04,1.12)}76%{transform:scale(.98,.94)}}
@keyframes wisp-hit-light{0%,100%{opacity:.85}22%{opacity:.15}48%{opacity:1}76%{opacity:.7}}
@keyframes wisp-interrupt{0%{transform:scale(1.05,1.13);filter:brightness(1.13)}28%{transform:scale(.6,.4);filter:brightness(.65)}53%{transform:scale(.9,.76)}100%{transform:scale(.76,.62);filter:brightness(.72)}}
@keyframes wisp-rock{0%{transform:none}28%{transform:translateY(20px) rotate(8deg)}53%{transform:translateY(30px) rotate(-3deg)}100%{transform:translateY(32px) rotate(5deg)}}
@keyframes wisp-fall{0%{transform:none;opacity:1}25%{transform:translateY(16px) rotate(4deg)}70%{transform:translateY(125px) rotate(-10deg);opacity:.6}100%{transform:translateY(120px) rotate(-8deg);opacity:.5}}
@keyframes wisp-extinguish{0%{opacity:1;transform:none}25%{opacity:1;transform:scale(.8,.6)}65%{opacity:.65;transform:scale(.4,.18)}100%{opacity:0;transform:scale(.18,.05)}}
@keyframes wisp-tail-out{0%{opacity:1;transform:none}60%{opacity:.5;transform:scale(.6,.28)}100%{opacity:0;transform:scale(.3,.03)}}
@keyframes wisp-light-out{0%{opacity:.85}35%{opacity:.4}65%{opacity:.12}100%{opacity:0}}
@keyframes wisp-smoke{0%,25%,100%{opacity:0;transform:none}45%{opacity:.4;transform:translateY(-20px)}75%{opacity:.2;transform:translate(12px,-85px)}100%{opacity:0;transform:translate(20px,-120px)}}

@media(prefers-reduced-motion:reduce){.wisp-art *,.enemy-stage:has(.wisp-figure) .actor-wrap{animation:none!important}.wisp-embers,.wisp-burst,.wisp-smoke{display:none}}
html[data-reduce-motion=true] :is(.wisp-art *,.enemy-stage:has(.wisp-figure) .actor-wrap){animation:none!important}
html[data-reduce-motion=true] :is(.wisp-embers,.wisp-burst,.wisp-smoke){display:none}

/* Heavy shell, separate grounded feet. Intent is outside every moving group. */
.enemy-figure.crawler-figure{animation:none!important;width:min(100%,330px,calc((var(--actor-height,370px) - var(--art-clearance,28px))*var(--crawler-ratio)))}
.crawler-art,.crawler-art image{image-rendering:pixelated}.crawler-art{overflow:visible;filter:none;pointer-events:none}
.crawler-figure>.crawler-art{max-width:none}
.crawler-motion{transform-origin:810px 937px}
.crawler-torso{transform-origin:810px 790px;animation:none}
.crawler-head{transform-origin:500px 670px;animation:crawler-watch 6.4s steps(8,end) infinite;animation-delay:var(--crawler-clock)}
.crawler-leg{animation:crawler-step 6.4s steps(6,end) infinite;animation-delay:calc(var(--crawler-clock) - var(--leg-phase))}
.crawler-front{--leg-phase:0s;transform-origin:510px 655px}.crawler-middle{--leg-phase:3.2s;transform-origin:680px 655px}.crawler-inner{--leg-phase:1.6s;transform-origin:1040px 740px}.crawler-rear{--leg-phase:4.8s;transform-origin:1270px 655px}
.crawler-dust,.crawler-sparks{opacity:0;pointer-events:none}

/* Readying a guard, then tucking the head beneath the planted shell. */
.crawler-figure:has(>:where(.intent.guard)) .crawler-torso{animation-name:crawler-ready}
.crawler-figure:has(>:where(.intent.guard)) .crawler-head{animation:none;transform:translate(16px,8px)}
.enemy-stage:has(.enemy-ward) .crawler-torso{animation:none;transform:translateY(22px)}
.enemy-stage:has(.enemy-ward) .crawler-head{animation:none;transform:translate(52px,3px) rotate(-3deg)}
.enemy-stage:has(.enemy-ward) .crawler-leg{animation:none;transform:scale(1.04,.91)}

.enemy-stage .crawler-figure:has(>:where(.intent.stun)) .crawler-torso{transform:translateY(26px) rotate(.5deg);animation:crawler-dazed 2.8s steps(6,end) infinite;animation-delay:var(--crawler-clock)}
.enemy-stage .crawler-figure:has(>:where(.intent.stun)) .crawler-head{animation:none;transform:translate(-12px,18px) rotate(-4deg)}
.enemy-stage .crawler-figure:has(>:where(.intent.stun)) .crawler-leg{animation:none;transform:scale(1,.93)}

.enemy-stage:is(.attacking,.taking-hit,[data-effect=ward],[data-crawler-action]):has(.crawler-figure) .actor-wrap{animation:none;filter:none}
.enemy-stage:is(.attacking,.taking-hit,[data-effect=ward],[data-crawler-action]) :is(.crawler-torso,.crawler-head,.crawler-leg){animation:none}
.enemy-stage.attacking .crawler-motion{animation:crawler-ram .6s steps(9,end);animation-delay:0s}
.enemy-stage.attacking .crawler-torso{animation:crawler-ram-shell .6s steps(9,end);animation-delay:0s}
.enemy-stage.attacking .crawler-head{animation:crawler-ram-head .6s steps(9,end);animation-delay:0s}
.enemy-stage.attacking .crawler-leg{animation:crawler-push .6s steps(9,end);animation-delay:0s}
.enemy-stage.attacking .crawler-dust{animation:crawler-dust .6s steps(6,end);animation-delay:0s}
.enemy-stage[data-effect=ward] .crawler-torso{animation:crawler-brace .6s steps(7,end) both;animation-delay:0s}
.enemy-stage[data-effect=ward] .crawler-head{animation:crawler-tuck .6s steps(7,end) both;animation-delay:0s}
.enemy-stage[data-effect=ward] .crawler-leg{animation:crawler-plant .6s steps(7,end) both;animation-delay:0s}
.enemy-stage.taking-hit .crawler-motion{animation:crawler-hit .5s steps(7,end);animation-delay:0s}
.enemy-stage.taking-hit .crawler-torso{animation:crawler-rattle .5s steps(7,end);animation-delay:0s}
.enemy-stage.taking-hit .crawler-head{animation:crawler-head-hit .5s steps(7,end);animation-delay:0s}
.enemy-stage[data-crawler-action=block] .crawler-motion{animation:crawler-block .5s steps(7,end);animation-delay:0s}
.enemy-stage[data-crawler-action=block] .crawler-torso{animation:crawler-shell-block .5s steps(7,end);animation-delay:0s}
.enemy-stage[data-crawler-action=block] .crawler-head{animation:none;transform:translate(45px,5px) rotate(-3deg)}
.enemy-stage:is([data-crawler-action=block],[data-crawler-action=partial-block]) .crawler-sparks{animation:crawler-chips .5s steps(6,end);animation-delay:0s}
.enemy-stage[data-crawler-action=interrupt] .crawler-torso{animation:crawler-interrupt .55s steps(7,end);animation-delay:0s}
.enemy-stage[data-crawler-action=interrupt] .crawler-head{animation:crawler-head-hit .55s steps(7,end);animation-delay:0s}

/* The stone sinks onto folded legs; it stays down through solve and loot renders. */
.enemy-stage.defeated:has(.crawler-figure) .actor-wrap{animation:none;transform:none;opacity:1;filter:none}
.enemy-stage.defeated .crawler-motion{animation:crawler-fade .64s steps(8,end) both;animation-delay:var(--crawler-death-clock);transform:none;opacity:.55}
.enemy-stage.defeated .crawler-torso{animation:crawler-collapse .64s steps(8,end) both;animation-delay:var(--crawler-death-clock);transform:translateY(72px)}
.enemy-stage.defeated .crawler-head{animation:crawler-head-fall .64s steps(8,end) both;animation-delay:var(--crawler-death-clock);transform:translate(28px,-5px) rotate(-3deg)}
.enemy-stage.defeated .crawler-leg{animation:crawler-fold .64s steps(8,end) both;animation-delay:var(--crawler-death-clock);transform:scaleY(var(--fold-rest,.745))}
.enemy-stage.defeated .crawler-dust{animation:crawler-fall-dust .64s steps(7,end) both;animation-delay:var(--crawler-death-clock)}
.enemy-stage.defeated .crawler-sparks{display:none}

@keyframes crawler-settle{0%,100%{transform:none}20%{transform:translate(-3px,-6px)}40%{transform:translateY(6px)}65%{transform:translate(3px,-4px)}80%{transform:translateY(7px)}}
@keyframes crawler-step{0%,18%,55%,100%{transform:none}28%{transform:rotate(-5deg)}40%{transform:rotate(3deg)}48%{transform:rotate(2deg)}}
@keyframes crawler-watch{0%,100%{transform:none}30%{transform:translate(-8px,3px) rotate(-.6deg)}65%{transform:translate(4px,-3px)}}
@keyframes crawler-ready{0%,100%{transform:translateY(10px)}50%{transform:translateY(15px)}}
@keyframes crawler-dazed{0%,100%{transform:translateY(26px) rotate(.5deg)}50%{transform:translateY(22px) rotate(-.6deg)}}
@keyframes crawler-ram{0%,100%{transform:none}22%{transform:translateX(26px)}46%,56%{transform:translateX(-125px)}76%{transform:translateX(-45px)}}
@keyframes crawler-ram-shell{0%,100%{transform:none}22%{transform:translateY(18px)}46%,56%{transform:translateY(10px) rotate(-1deg)}76%{transform:translateY(20px)}}
@keyframes crawler-ram-head{0%,100%{transform:none}22%{transform:translateX(35px)}46%,56%{transform:translate(-22px,-8px)}76%{transform:translateX(5px)}}
@keyframes crawler-push{0%,100%{transform:none}22%{transform:translateX(-20px) scale(1,.9)}46%,56%{transform:translateX(34px) scale(1,.95)}76%{transform:translateX(5px)}}
@keyframes crawler-brace{0%{transform:none}25%{transform:translateY(-7px)}55%{transform:translateY(32px)}100%{transform:translateY(22px)}}
@keyframes crawler-tuck{0%{transform:none}55%{transform:translate(65px,8px) rotate(-4deg)}100%{transform:translate(52px,3px) rotate(-3deg)}}
@keyframes crawler-plant{0%{transform:none}55%{transform:scale(1.06,.86)}100%{transform:scale(1.04,.91)}}
@keyframes crawler-hit{0%,100%{transform:none;filter:none}23%{transform:translateX(30px);filter:brightness(1.4)}46%{transform:translateX(10px);filter:none}72%{transform:translateX(-6px)}}
@keyframes crawler-rattle{0%,100%{transform:none}23%{transform:translate(10px,-15px) rotate(1.1deg)}46%{transform:translateY(12px)}72%{transform:translateY(-4px)}}
@keyframes crawler-head-hit{0%,100%{transform:none}23%{transform:translate(25px,9px) rotate(3deg)}46%{transform:translate(-8px,12px) rotate(-3deg)}72%{transform:translateY(3px)}}
@keyframes crawler-block{0%,100%{transform:none}24%{transform:translateX(12px)}48%{transform:translateX(-5px)}72%{transform:translateX(3px)}}
@keyframes crawler-shell-block{0%{transform:translateY(22px)}24%{transform:translate(8px,29px)}48%{transform:translate(-4px,18px)}72%{transform:translateY(24px)}100%{transform:none}}
@keyframes crawler-interrupt{0%{transform:translateY(22px)}25%{transform:translateY(-8px)}48%{transform:translateY(32px) rotate(-.8deg)}100%{transform:translateY(26px) rotate(.5deg)}}
@keyframes crawler-chips{0%,10%,100%{opacity:0;transform:none}24%,40%{opacity:1;transform:translate(-25px,-15px)}75%{opacity:.5;transform:translate(-60px,20px)}}
@keyframes crawler-dust{0%,20%,100%{opacity:0;transform:none}46%{opacity:.6;transform:translate(35px,-15px)}76%{opacity:.3;transform:translate(70px,-25px)}}
@keyframes crawler-fade{0%,25%{opacity:1}100%{opacity:.55}}
@keyframes crawler-collapse{0%{transform:none}24%{transform:translateY(-10px)}58%{transform:translateY(87px)}78%,100%{transform:translateY(72px)}}
@keyframes crawler-head-fall{0%{transform:none}58%{transform:translate(34px,-2px) rotate(-4deg)}78%,100%{transform:translate(28px,-5px) rotate(-3deg)}}
@keyframes crawler-fold{0%{transform:none}24%{transform:scaleY(1.035)}58%{transform:scaleY(var(--fold-impact,.692))}78%,100%{transform:scaleY(var(--fold-rest,.745))}}
@keyframes crawler-fall-dust{0%,35%,100%{opacity:0;transform:none}58%{opacity:.7;transform:translateY(-10px) scaleX(1.05)}80%{opacity:.3;transform:translateY(-28px) scaleX(1.15)}}
@media(prefers-reduced-motion:reduce){.crawler-art *,.enemy-stage:has(.crawler-figure) .actor-wrap{animation:none!important}.crawler-dust,.crawler-sparks{display:none}}
html[data-reduce-motion=true] :is(.crawler-art *,.enemy-stage:has(.crawler-figure) .actor-wrap){animation:none!important}
html[data-reduce-motion=true] :is(.crawler-dust,.crawler-sparks){display:none}

/* The inner hip has a shorter lever to the floor. All hips follow the shell. */
.crawler-inner{--fold-impact:.558;--fold-rest:.635}

.enemy-figure.executioner-figure{animation:none!important;width:min(100%,350px,calc((var(--actor-height,370px) - var(--art-clearance,28px))*var(--executioner-ratio)))}
/* Facing is inside world motion: the lunge, recoil and sparks stay in world space. */
.executioner-figure>.executioner-art{max-width:none}.executioner-art{overflow:visible;pointer-events:none;filter:none}.executioner-art,.executioner-art image{image-rendering:pixelated}
.executioner-motion,.executioner-idle{transform-origin:600px 1100px}.executioner-free{transform-origin:430px 530px}.executioner-weapon{transform-origin:770px 530px}
.executioner-idle{animation:executioner-breathe 4.8s steps(8,end) infinite;animation-delay:var(--executioner-clock)}
.executioner-free{animation:executioner-free-idle 4.8s steps(8,end) infinite;animation-delay:var(--executioner-clock)}
.executioner-weapon{animation:executioner-weapon-idle 4.8s steps(8,end) infinite;animation-delay:var(--executioner-clock)}
.executioner-sparks{opacity:0;pointer-events:none}
.executioner-figure:has(>:where(.intent.guard)) .executioner-weapon{animation:none;transform:rotate(-8deg)}
.enemy-stage:has(.enemy-ward) .executioner-weapon{animation:none;transform:rotate(-22deg)}
.enemy-stage:has(.enemy-ward) .executioner-free{animation:none;transform:rotate(-8deg)}
.executioner-figure:has(>:where(.intent.channel)) .executioner-weapon{transform:rotate(-55deg);animation:executioner-held-charge 1.8s steps(6,end) infinite;animation-delay:var(--executioner-clock)}
.executioner-figure:has(>:where(.intent.channel)) .executioner-free{animation:none;transform:rotate(14deg)}
.executioner-figure:has(>:where(.intent.stun)) .executioner-idle{animation:none;transform:rotate(2deg)}
.executioner-figure:has(>:where(.intent.stun)) .executioner-weapon{animation:executioner-dazed 2.6s steps(6,end) infinite;animation-delay:var(--executioner-clock);transform:rotate(9deg)}
.executioner-figure:has(>:where(.intent.stun)) .executioner-free{animation:none;transform:rotate(-10deg)}
.enemy-stage:is(.attacking,.taking-hit,[data-executioner-action],[data-effect=ward]):has(.executioner-figure) .actor-wrap{animation:none;filter:none}
.enemy-stage:is(.attacking,.taking-hit,[data-executioner-action],[data-effect=ward]) :is(.executioner-idle,.executioner-free,.executioner-weapon){animation:none}
.enemy-stage.attacking .executioner-motion{animation:executioner-strike .6s steps(9,end);animation-delay:0s}
.enemy-stage.attacking .executioner-weapon{animation:executioner-cut .6s steps(9,end);animation-delay:0s}
.enemy-stage.attacking .executioner-free{animation:executioner-counterweight .6s steps(9,end);animation-delay:0s}
.enemy-stage[data-executioner-action=execution] .executioner-weapon{animation:executioner-heavy-cut .62s steps(10,end);animation-delay:0s}
.enemy-stage[data-executioner-action=execution] .executioner-motion{animation:executioner-heavy-step .62s steps(10,end);animation-delay:0s}
.enemy-stage[data-effect=ward] .executioner-weapon{animation:executioner-guard .55s steps(7,end) both;animation-delay:0s}
.enemy-stage.taking-hit .executioner-motion{animation:executioner-hit .5s steps(7,end);animation-delay:0s}
.enemy-stage.taking-hit .executioner-weapon{animation:executioner-hit-arm .5s steps(7,end);animation-delay:0s}
.enemy-stage[data-executioner-action=block] .executioner-motion{animation:executioner-block .5s steps(7,end);animation-delay:0s}
.enemy-stage[data-executioner-action=block] .executioner-weapon{animation:executioner-parry .5s steps(7,end);animation-delay:0s}
.enemy-stage:is([data-executioner-action=block],[data-executioner-action=partial-block]) .executioner-sparks{animation:executioner-sparks .5s steps(6,end);animation-delay:0s}
.enemy-stage[data-executioner-action=charge] .executioner-weapon{animation:executioner-raise .6s steps(8,end) both;animation-delay:0s}
.enemy-stage[data-executioner-action=interrupt] .executioner-weapon{animation:executioner-interrupt .6s steps(8,end) both;animation-delay:0s}
.enemy-stage[data-executioner-action=interrupt] .executioner-motion{animation:executioner-hit .6s steps(8,end);animation-delay:0s}
.enemy-stage.defeated:has(.executioner-figure) .actor-wrap{animation:none;transform:none;opacity:1;filter:none}
.enemy-stage.defeated .executioner-idle{animation:none;transform:none}
.enemy-stage.defeated .executioner-motion{transform:rotate(-7deg) scaleY(.85);opacity:.5;animation:executioner-fall .64s steps(9,end) both;animation-delay:var(--executioner-death-clock)}
.enemy-stage.defeated .executioner-weapon{transform:rotate(24deg);animation:executioner-drop .64s steps(9,end) both;animation-delay:var(--executioner-death-clock)}
.enemy-stage.defeated .executioner-free{transform:rotate(-18deg);animation:none}.enemy-stage.defeated .executioner-sparks{display:none}
@keyframes executioner-breathe{0%,100%{transform:none}50%{transform:scaleY(.994)}}
@keyframes executioner-free-idle{0%,100%{transform:none}50%{transform:rotate(-1.2deg)}}
@keyframes executioner-weapon-idle{0%,100%{transform:none}50%{transform:rotate(1deg)}}
@keyframes executioner-held-charge{0%,100%{transform:rotate(-55deg)}50%{transform:rotate(-57deg)}}
@keyframes executioner-dazed{0%,100%{transform:rotate(9deg)}50%{transform:rotate(12deg)}}
@keyframes executioner-strike{0%,100%{transform:none}22%{transform:translateX(18px) rotate(1deg)}48%,58%{transform:translateX(-75px) rotate(-2deg)}80%{transform:translateX(-22px)}}
@keyframes executioner-cut{0%,100%{transform:none}22%{transform:rotate(-28deg)}48%,58%{transform:rotate(65deg)}80%{transform:rotate(18deg)}}
@keyframes executioner-counterweight{0%,100%{transform:none}22%{transform:rotate(-8deg)}48%,58%{transform:rotate(18deg)}80%{transform:rotate(4deg)}}
@keyframes executioner-heavy-cut{0%{transform:rotate(-55deg)}22%{transform:rotate(-61deg)}48%,60%{transform:rotate(82deg)}82%{transform:rotate(23deg)}100%{transform:none}}
@keyframes executioner-heavy-step{0%,100%{transform:none}22%{transform:translateX(25px)}48%,60%{transform:translateX(-110px) rotate(-4deg)}82%{transform:translateX(-30px)}}
@keyframes executioner-guard{0%{transform:none}60%{transform:rotate(-28deg)}100%{transform:rotate(-22deg)}}
@keyframes executioner-hit{0%,100%{transform:none;filter:none}24%{transform:translateX(35px) rotate(3deg);filter:brightness(1.35)}48%{transform:translateX(12px) rotate(1deg);filter:none}75%{transform:translateX(-5px)}}
@keyframes executioner-hit-arm{0%,100%{transform:none}24%{transform:rotate(-10deg)}48%{transform:rotate(5deg)}75%{transform:rotate(-2deg)}}
@keyframes executioner-block{0%,100%{transform:none}24%{transform:translateX(12px)}48%{transform:translateX(-6px)}}
@keyframes executioner-parry{0%{transform:rotate(-22deg)}24%{transform:rotate(-15deg)}48%{transform:rotate(-29deg)}100%{transform:rotate(-22deg)}}
@keyframes executioner-sparks{0%,10%,100%{opacity:0;transform:none}25%,45%{opacity:1;transform:translate(-20px,-18px)}75%{opacity:.3;transform:translate(-55px,12px)}}
@keyframes executioner-raise{0%{transform:none}65%{transform:rotate(-61deg)}100%{transform:rotate(-55deg)}}
@keyframes executioner-interrupt{0%{transform:rotate(-55deg)}25%{transform:rotate(-38deg)}55%{transform:rotate(18deg)}100%{transform:rotate(9deg)}}
@keyframes executioner-fall{0%{transform:none;opacity:1}25%{transform:rotate(2deg)}65%{transform:rotate(-9deg) scaleY(.83);opacity:.7}100%{transform:rotate(-7deg) scaleY(.85);opacity:.5}}
@keyframes executioner-drop{0%{transform:none}65%{transform:rotate(29deg)}100%{transform:rotate(24deg)}}
@media(prefers-reduced-motion:reduce){.executioner-art *,.enemy-stage:has(.executioner-figure) .actor-wrap{animation:none!important}.executioner-sparks{display:none}}
html[data-reduce-motion=true] :is(.executioner-art *,.enemy-stage:has(.executioner-figure) .actor-wrap){animation:none!important}
html[data-reduce-motion=true] .executioner-sparks{display:none}

/* Final character rendering only. The game board, text and effects stay sharp. */
.battle-layout > .character-pixel-layer{position:absolute;inset:0;overflow:clip;pointer-events:none;z-index:0}
.battle-layout .combatants{z-index:1}
.battle-layout .pixel-source{visibility:hidden!important}
.battle-layout .actor-wrap svg{pointer-events:none}
.battle-layout .puzzle-panel,.battle-layout .ending-panel{z-index:2}
