/* The Alcohol of Time — code-native battle effects */

#fieldFxLayer,
#effectLayer,
#screenFxLayer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

#fieldFxLayer {
  z-index: 1;
}

.battle-viewport .actor-layer {
  z-index: 2;
}

#effectLayer {
  z-index: 6;
}

#screenFxLayer {
  z-index: 11;
}

.aot-fx-node,
.aot-fx-node *,
.combatant.aot-status-aura::before,
.combatant.aot-status-aura::after {
  box-sizing: border-box;
  pointer-events: none;
}

.aot-fx-node {
  --fx-color: #f2dfaa;
  --fx-duration: 700ms;
  --fx-delay: 0ms;
  --fx-x: 0px;
  --fx-y: 0px;
  --fx-subject-width: 110px;
  --fx-subject-height: 140px;
  --fx-index: 0;
  --fx-size: 7px;
  --fx-angle: 0deg;
  --fx-distance: 52px;
  --fx-dx: 0px;
  --fx-dy: -52px;
  --fx-rotation: 0deg;
  --fx-scale: 1;
  --fx-length: 100px;
  --fx-from-x: var(--fx-x);
  --fx-from-y: var(--fx-y);
  --fx-to-x: var(--fx-x);
  --fx-to-y: var(--fx-y);
  --fx-segment-x: 0px;
  --fx-segment-y: 0px;
  --fx-radius: 90px;
  --fx-diameter: 180px;
  --fx-tick-angle: 0deg;
  --fx-drift: 0px;
  position: absolute;
  left: var(--fx-x, 0px);
  top: var(--fx-y, 0px);
  display: block;
  color: var(--fx-color);
  transform: translate(-50%, -50%);
  transform-origin: center;
  isolation: isolate;
  will-change: transform, opacity, filter;
}

.aot-fx-particle {
  position: absolute;
  display: block;
  width: var(--fx-size, 7px);
  height: var(--fx-size, 7px);
  animation-delay: var(--fx-delay, 0ms) !important;
  animation-fill-mode: both !important;
  will-change: transform, opacity;
}

.aot-fx-node--reduced {
  filter: none !important;
  mix-blend-mode: normal !important;
}

/* Five-frame ImageGen impact atlases. The slightly oversized background math
   trims the two-pixel atlas seams while preserving every source frame. */

.aot-fx-sprite-vfx {
  --atlas-bg-x: 507.23589%;
  --atlas-bg-y: 405.786618%;
  --atlas-x0: 0.177683%;
  --atlas-x1: 25.088842%;
  --atlas-x2: 50%;
  --atlas-x3: 74.911158%;
  --atlas-x4: 99.822317%;
  --atlas-row-y: 0.236546%;
  --fx-atlas-width: 210px;
  width: min(var(--fx-atlas-width), 72vw, 340px);
  aspect-ratio: 0.9996383363;
  overflow: hidden;
  background-color: transparent;
  background-repeat: no-repeat;
  background-size: var(--atlas-bg-x) var(--atlas-bg-y);
  background-position: var(--atlas-x0) var(--atlas-row-y);
  image-rendering: auto;
  mix-blend-mode: screen;
  filter:
    brightness(1.08)
    saturate(1.12)
    drop-shadow(0 0 9px rgba(255, 255, 255, 0.42));
  animation: aot-fx-sprite-five 450ms linear both;
}

.aot-fx-sprite-vfx--portrait {
  --atlas-bg-x: 508.103728%;
  --atlas-bg-y: 405.169628%;
  --atlas-x0: 0.19857%;
  --atlas-x1: 25.099285%;
  --atlas-x2: 50%;
  --atlas-x3: 74.900715%;
  --atlas-x4: 99.80143%;
  aspect-ratio: 0.7974151858;
}

.aot-fx-sprite-vfx--physical {
  background-image: url("../art/vfx/imagegen/v1/physical-5frame-atlas-transparent.png");
}

.aot-fx-sprite-vfx--elemental {
  background-image: url("../art/vfx/imagegen/v1/elemental-5frame-atlas-transparent.png");
}

.aot-fx-sprite-vfx--time-support {
  background-image: url("../art/vfx/imagegen/v1/time-support-5frame-atlas-transparent.png");
}

.aot-fx-sprite-vfx--projectiles {
  background-image: url("../art/vfx/imagegen/v1/projectiles-5frame-atlas-transparent.png");
}

.aot-fx-sprite-vfx--critical-overlay {
  z-index: 2;
  filter:
    brightness(1.22)
    saturate(1.25)
    drop-shadow(0 0 13px rgba(255, 238, 184, 0.72));
}

@keyframes aot-fx-sprite-five {
  0%, 19.999% {
    opacity: 0.46;
    background-position: var(--atlas-x0) var(--atlas-row-y);
  }
  20%, 39.999% {
    opacity: 0.86;
    background-position: var(--atlas-x1) var(--atlas-row-y);
  }
  40%, 59.999% {
    opacity: 1;
    background-position: var(--atlas-x2) var(--atlas-row-y);
  }
  60%, 79.999% {
    opacity: 1;
    background-position: var(--atlas-x3) var(--atlas-row-y);
  }
  80% {
    opacity: 0.86;
    background-position: var(--atlas-x4) var(--atlas-row-y);
  }
  100% {
    opacity: 0;
    background-position: var(--atlas-x4) var(--atlas-row-y);
  }
}

@keyframes aot-fx-sprite-peak {
  0% {
    opacity: 0;
    background-position: var(--atlas-x3) var(--atlas-row-y);
  }
  32% {
    opacity: 0.88;
    background-position: var(--atlas-x3) var(--atlas-row-y);
  }
  100% {
    opacity: 0;
    background-position: var(--atlas-x3) var(--atlas-row-y);
  }
}

/* Camera and full-screen flashes */

.battle-viewport.aot-fx-camera--light {
  animation: aot-fx-camera-light 220ms ease-out both;
}

.battle-viewport.aot-fx-camera--heavy {
  animation: aot-fx-camera-heavy 360ms cubic-bezier(0.2, 0.8, 0.25, 1) both;
}

.battle-viewport.aot-fx-camera--ko {
  animation: aot-fx-camera-ko 420ms cubic-bezier(0.2, 0.85, 0.22, 1) both;
}

.aot-fx-screen-flash {
  inset: 0;
  width: 100%;
  height: 100%;
  transform: none;
  background:
    radial-gradient(circle at 50% 48%, #ffffff 0 3%, var(--fx-color) 18%, transparent 62%);
  mix-blend-mode: screen;
  animation: aot-fx-screen-flash var(--fx-duration) ease-out both;
}

.aot-fx-screen-flash--light {
  opacity: 0.42;
}

.aot-fx-screen-flash--heavy {
  opacity: 0.78;
  filter: saturate(1.35) brightness(1.2);
}

/* Cast anticipation */

.aot-fx-cast {
  width: clamp(58px, calc(var(--fx-subject-width, 110px) * 0.68), 120px);
  aspect-ratio: 1;
  color: var(--fx-color);
  filter: drop-shadow(0 0 9px var(--fx-color));
  animation: aot-fx-cast-arrive var(--fx-duration) ease-out both;
}

.aot-fx-cast-ring,
.aot-fx-cast-core {
  position: absolute;
  inset: 10%;
  border-radius: 50%;
}

.aot-fx-cast-ring {
  border: 2px solid currentColor;
  background:
    repeating-conic-gradient(from 0deg, currentColor 0 2deg, transparent 2deg 28deg);
  -webkit-mask: radial-gradient(circle, transparent 58%, #000 60% 68%, transparent 70%);
  mask: radial-gradient(circle, transparent 58%, #000 60% 68%, transparent 70%);
  animation: aot-fx-cast-ring-spin var(--fx-duration) cubic-bezier(0.15, 0.8, 0.2, 1) both;
}

.aot-fx-cast-core {
  inset: 28%;
  border: 1px solid rgba(255, 255, 255, 0.8);
  background: radial-gradient(circle, #fff 0 8%, currentColor 22%, transparent 72%);
  box-shadow: 0 0 20px currentColor;
  animation: aot-fx-cast-core-pulse 420ms ease-in-out alternate 2;
}

.aot-fx-cast-mote {
  left: 50%;
  top: 50%;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 7px currentColor;
  animation: aot-fx-cast-mote var(--fx-duration) ease-out both;
}

.aot-fx-cast--none,
.aot-fx-cast--physical {
  filter: drop-shadow(0 0 7px #f2dfaa);
}

.aot-fx-cast--ember .aot-fx-cast-ring {
  border-radius: 45% 55% 42% 58%;
  animation-name: aot-fx-cast-ring-spin, aot-fx-ember-wobble;
}

.aot-fx-cast--frost .aot-fx-cast-core {
  border-radius: 18%;
  transform: rotate(45deg);
}

.aot-fx-cast--storm .aot-fx-cast-ring {
  border-style: dashed;
  animation-timing-function: steps(6, end);
}

.aot-fx-cast--tide .aot-fx-cast-ring {
  transform: scaleY(0.55);
}

.aot-fx-cast--shadow {
  mix-blend-mode: screen;
}

.aot-fx-cast--shadow .aot-fx-cast-core {
  background: radial-gradient(circle, #0c0714 0 30%, currentColor 55%, transparent 74%);
}

.aot-fx-cast--time .aot-fx-cast-ring {
  background:
    repeating-conic-gradient(currentColor 0 3deg, transparent 3deg 30deg);
  animation-direction: reverse;
}

/* Spatial targeting telegraphs */

.aot-fx-telegraph {
  color: var(--fx-color);
  opacity: 0;
  filter: drop-shadow(0 0 5px currentColor);
  mix-blend-mode: screen;
}

.aot-fx-target-marker {
  width: clamp(48px, calc(var(--fx-subject-width, 100px) * 0.78), 118px);
  height: clamp(18px, calc(var(--fx-subject-width, 100px) * 0.24), 36px);
  border: 2px solid currentColor;
  border-radius: 50%;
  background:
    radial-gradient(ellipse, transparent 50%, currentColor 54% 58%, transparent 62%);
  animation: aot-fx-target-marker var(--fx-duration) ease-out both;
}

.aot-fx-target-marker::before,
.aot-fx-target-marker::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  background: currentColor;
  opacity: 0.8;
}

.aot-fx-target-marker::before {
  width: 130%;
  height: 1px;
  transform: translate(-50%, -50%);
}

.aot-fx-target-marker::after {
  width: 1px;
  height: 180%;
  transform: translate(-50%, -50%);
}

.aot-fx-telegraph--line,
.aot-fx-telegraph--ray,
.aot-fx-telegraph--horizontal,
.aot-fx-convergence {
  left: var(--fx-from-x, var(--fx-x));
  top: var(--fx-from-y, var(--fx-y));
  width: var(--fx-length, 100px);
  height: 4px;
  border-radius: 999px;
  transform: translateY(-50%) rotate(var(--fx-angle, 0deg));
  transform-origin: left center;
  background:
    linear-gradient(90deg, transparent, currentColor 20% 78%, #fff 84%, transparent);
  box-shadow:
    0 0 4px currentColor,
    0 0 11px currentColor;
  animation: aot-fx-line-telegraph var(--fx-duration) ease-in-out both;
}

.aot-fx-telegraph--ray {
  height: 7px;
  background:
    repeating-linear-gradient(90deg, transparent 0 12px, currentColor 13px 23px),
    linear-gradient(90deg, transparent, currentColor, transparent);
}

.aot-fx-telegraph--horizontal {
  height: 18px;
  transform: translateY(-50%);
  background:
    linear-gradient(180deg, transparent, currentColor 46% 54%, transparent),
    repeating-linear-gradient(90deg, transparent 0 22px, currentColor 23px 27px);
}

.aot-fx-telegraph--radius,
.aot-fx-telegraph--near-user {
  width: var(--fx-diameter, 180px);
  height: var(--fx-diameter, 180px);
  border: 2px solid currentColor;
  border-radius: 50%;
  background:
    repeating-conic-gradient(currentColor 0 2deg, transparent 2deg 24deg),
    radial-gradient(circle, transparent 57%, currentColor 58% 60%, transparent 61%);
  -webkit-mask: radial-gradient(circle, transparent 0 54%, #000 57% 61%, transparent 64%);
  mask: radial-gradient(circle, transparent 0 54%, #000 57% 61%, transparent 64%);
  animation: aot-fx-radius-telegraph var(--fx-duration) ease-out both;
}

.aot-fx-telegraph--near-user {
  border-style: dashed;
  animation-direction: reverse;
}

.aot-fx-telegraph--all {
  inset: 0;
  width: 100%;
  height: 100%;
  transform: none;
  background:
    linear-gradient(115deg, transparent 25%, currentColor 47%, transparent 58%) -120% 0 / 70% 100% no-repeat,
    repeating-linear-gradient(90deg, transparent 0 18%, currentColor 18.2% 18.6%, transparent 18.8% 36%);
  opacity: 0;
  animation: aot-fx-all-telegraph var(--fx-duration) ease-out both;
}

.aot-fx-telegraph--allenemies {
  -webkit-mask: linear-gradient(90deg, transparent 0 45%, #000 56% 100%);
  mask: linear-gradient(90deg, transparent 0 45%, #000 56% 100%);
}

.aot-fx-telegraph--allallies {
  -webkit-mask: linear-gradient(90deg, #000 0 48%, transparent 58% 100%);
  mask: linear-gradient(90deg, #000 0 48%, transparent 58% 100%);
}

/* Dual, Triple, and Relic convergence */

.aot-fx-convergence {
  height: 5px;
  opacity: 0;
  animation: aot-fx-converge var(--fx-duration) var(--fx-delay, 0ms) cubic-bezier(0.2, 0.9, 0.2, 1) both;
}

.aot-fx-convergence--dual {
  height: 4px;
}

.aot-fx-convergence--triple,
.aot-fx-convergence--relic {
  height: 6px;
  box-shadow:
    0 0 7px #fff,
    0 0 18px currentColor;
}

.aot-fx-combo-seal {
  width: clamp(106px, 19vw, 164px);
  aspect-ratio: 1;
  color: var(--fx-color);
  filter: drop-shadow(0 0 14px currentColor);
  animation: aot-fx-seal-arrive var(--fx-duration) cubic-bezier(0.12, 0.86, 0.2, 1) both;
}

.aot-fx-combo-seal::before,
.aot-fx-combo-seal::after {
  content: "";
  position: absolute;
  inset: 5%;
  border: 2px solid currentColor;
  transform: rotate(45deg);
}

.aot-fx-combo-seal::after {
  inset: 18%;
  border-style: dashed;
  transform: rotate(-45deg);
}

.aot-fx-combo-seal--dual {
  filter: drop-shadow(0 0 10px currentColor);
}

.aot-fx-combo-seal--triple {
  filter:
    drop-shadow(0 0 5px #fff)
    drop-shadow(0 0 18px currentColor);
}

.aot-fx-combo-seal--relic {
  color: #f7d879;
  filter:
    drop-shadow(0 0 6px #fff)
    drop-shadow(0 0 22px #d58cff);
}

.aot-fx-combo-banner {
  left: 50%;
  top: 20%;
  width: min(82%, 560px);
  min-height: 68px;
  padding: 10px 24px 12px;
  border-block: 1px solid currentColor;
  color: var(--fx-color);
  transform: translate(-50%, -50%);
  background:
    linear-gradient(90deg, transparent, rgba(7, 10, 9, 0.82) 18% 82%, transparent),
    linear-gradient(90deg, transparent, currentColor 48% 52%, transparent);
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.7));
  text-align: center;
  text-shadow: 0 2px 3px #000, 0 0 8px currentColor;
  animation: aot-fx-banner var(--fx-duration) cubic-bezier(0.18, 0.84, 0.2, 1) both;
}

.aot-fx-combo-banner-label,
.aot-fx-combo-banner-name {
  display: block;
}

.aot-fx-combo-banner-label {
  color: currentColor;
  font-size: clamp(0.52rem, 1.2vw, 0.72rem);
  font-weight: 800;
  letter-spacing: 0.22em;
}

.aot-fx-combo-banner-name {
  margin-top: 2px;
  color: #fff8db;
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(1rem, 2.8vw, 1.65rem);
  font-weight: 700;
  letter-spacing: 0.04em;
}

.aot-fx-combo-banner--dual {
  width: min(70%, 470px);
}

.aot-fx-combo-banner--triple {
  background:
    linear-gradient(90deg, transparent, rgba(12, 9, 17, 0.9) 14% 86%, transparent),
    linear-gradient(90deg, transparent, currentColor 48% 52%, transparent);
}

.aot-fx-combo-banner--relic {
  border-color: #f7d879;
  color: #f7d879;
  background:
    linear-gradient(90deg, transparent, rgba(24, 15, 34, 0.92) 12% 88%, transparent),
    linear-gradient(90deg, transparent, #d58cff 42%, #f7d879 50%, #d58cff 58%, transparent);
}

/* Clock components shared by Time, combos, victory, and defeat */

.aot-fx-clock-face {
  position: absolute;
  inset: 8%;
  border: 2px solid currentColor;
  border-radius: 50%;
  background:
    radial-gradient(circle, transparent 0 61%, currentColor 63% 65%, transparent 67%),
    radial-gradient(circle, rgba(255, 255, 255, 0.12), transparent 67%);
  box-shadow:
    inset 0 0 16px currentColor,
    0 0 13px currentColor;
  animation: aot-fx-clock-face var(--fx-duration, 900ms) ease-out both;
}

.aot-fx-clock-tick {
  position: absolute;
  left: calc(50% - 1px);
  top: 50%;
  width: 2px;
  height: 9%;
  border-radius: 999px;
  background: currentColor;
  box-shadow: 0 0 4px currentColor;
  transform: rotate(var(--fx-tick-angle, 0deg)) translateY(-430%);
  transform-origin: 50% 0;
}

.aot-fx-clock-hand {
  position: absolute;
  left: calc(50% - 1px);
  bottom: 50%;
  width: 2px;
  border-radius: 999px;
  background: linear-gradient(to top, currentColor, #fff);
  box-shadow: 0 0 5px currentColor;
  transform-origin: 50% 100%;
}

.aot-fx-clock-hand--hour {
  height: 27%;
  animation: aot-fx-clock-hour var(--fx-duration, 900ms) cubic-bezier(0.15, 0.8, 0.2, 1) both;
}

.aot-fx-clock-hand--minute {
  height: 39%;
  animation: aot-fx-clock-minute var(--fx-duration, 900ms) cubic-bezier(0.15, 0.8, 0.2, 1) both;
}

.aot-fx-clock-pin {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 9%;
  aspect-ratio: 1;
  border: 1px solid #fff;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: currentColor;
  box-shadow: 0 0 7px currentColor;
}

/* Shared impact foundation */

.aot-fx-impact {
  width: clamp(92px, calc(var(--fx-subject-width, 120px) * 0.88), 172px);
  aspect-ratio: 1;
  color: var(--fx-color);
  mix-blend-mode: screen;
}

.aot-fx-impact--critical {
  width: clamp(116px, calc(var(--fx-subject-width, 120px) * 1.1), 210px);
  filter:
    drop-shadow(0 0 6px #fff)
    drop-shadow(0 0 15px currentColor);
}

/* Physical */

.aot-fx-physical {
  animation: aot-fx-impact-pop var(--fx-duration) ease-out both;
}

.aot-fx-slash {
  position: absolute;
  left: 0;
  top: calc(50% - 5px);
  width: 100%;
  height: 10px;
  border-radius: 50%;
  transform: rotate(var(--fx-rotation, -38deg)) scaleX(0);
  background:
    linear-gradient(180deg, transparent 0 20%, #fff 46% 54%, currentColor 62%, transparent 82%);
  filter: drop-shadow(0 0 4px currentColor);
  animation: aot-fx-slash var(--fx-duration) var(--fx-delay, 0ms) cubic-bezier(0.16, 0.78, 0.2, 1) both;
}

.aot-fx-impact-star {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: currentColor;
  clip-path: polygon(50% 0, 59% 38%, 100% 50%, 60% 59%, 50% 100%, 40% 60%, 0 50%, 39% 39%);
  animation: aot-fx-star var(--fx-duration) ease-out both;
}

/* Ember */

.aot-fx-ember {
  filter: drop-shadow(0 0 9px #ff704d);
  animation: aot-fx-impact-pop var(--fx-duration) ease-out both;
}

.aot-fx-ember-core,
.aot-fx-ember-ring {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.aot-fx-ember-core {
  width: 52%;
  aspect-ratio: 0.78;
  border-radius: 58% 42% 62% 38% / 70% 55% 45% 30%;
  background:
    radial-gradient(ellipse at 50% 70%, #fff7b2 0 14%, #ffc35a 27%, #ff704d 49%, transparent 72%);
  animation: aot-fx-flame-core var(--fx-duration) ease-out both;
}

.aot-fx-ember-ring {
  width: 82%;
  aspect-ratio: 1;
  border: 3px solid currentColor;
  border-radius: 50%;
  box-shadow: inset 0 0 14px currentColor, 0 0 12px currentColor;
  animation: aot-fx-ring-expand var(--fx-duration) ease-out both;
}

.aot-fx-spark,
.aot-fx-ember-spark {
  left: 50%;
  top: 50%;
  border-radius: 50% 0 50% 50%;
  background: linear-gradient(135deg, #fff6a1, currentColor 55%);
  box-shadow: 0 0 6px currentColor;
  animation: aot-fx-particle-burst var(--fx-duration) ease-out both;
}

/* Frost */

.aot-fx-frost {
  filter: drop-shadow(0 0 8px #80d8ff);
  animation: aot-fx-impact-pop var(--fx-duration) ease-out both;
}

.aot-fx-frost-core,
.aot-fx-frost-ring {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.aot-fx-frost-core {
  width: 52%;
  aspect-ratio: 1;
  background:
    conic-gradient(from 45deg, #fff 0 8%, #80d8ff 9% 17%, transparent 18% 25%, #c9f3ff 26% 34%, transparent 35% 50%, #80d8ff 51% 59%, transparent 60% 75%, #dff9ff 76% 84%, transparent 85%);
  clip-path: polygon(50% 0, 63% 35%, 100% 50%, 64% 63%, 50% 100%, 36% 64%, 0 50%, 35% 36%);
  animation: aot-fx-frost-core var(--fx-duration) ease-out both;
}

.aot-fx-frost-ring {
  width: 82%;
  aspect-ratio: 1;
  border: 2px solid currentColor;
  transform: translate(-50%, -50%) rotate(45deg);
  animation: aot-fx-frost-ring var(--fx-duration) ease-out both;
}

.aot-fx-frost-shard {
  left: 50%;
  top: 50%;
  width: calc(var(--fx-size, 7px) * 0.72);
  height: calc(var(--fx-size, 7px) * 2.4);
  background: linear-gradient(90deg, #fff, currentColor 58%, #3fa4de);
  clip-path: polygon(50% 0, 100% 68%, 50% 100%, 0 68%);
  filter: drop-shadow(0 0 4px currentColor);
  animation: aot-fx-shard-burst var(--fx-duration) ease-out both;
}

/* Storm */

.aot-fx-storm {
  height: clamp(126px, calc(var(--fx-subject-height, 150px) * 0.95), 218px);
  filter:
    drop-shadow(0 0 4px #fff)
    drop-shadow(0 0 10px #ffe268);
  animation: aot-fx-storm-flash var(--fx-duration) steps(5, end) both;
}

.aot-fx-storm-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 42%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 8%, #ffe268 20%, transparent 68%);
  animation: aot-fx-star var(--fx-duration) ease-out both;
}

.aot-fx-bolt-segment {
  position: absolute;
  left: calc(50% + var(--fx-segment-x, 0px));
  top: calc(50% + var(--fx-segment-y, 0px));
  width: var(--fx-length, 28px);
  height: 4px;
  border-radius: 2px;
  transform: rotate(var(--fx-rotation, 30deg));
  transform-origin: left center;
  background: linear-gradient(90deg, #fff, currentColor 42% 88%, transparent);
  box-shadow: 0 0 5px #fff, 0 0 9px currentColor;
  animation: aot-fx-bolt var(--fx-duration) steps(4, end) both;
}

/* Tide */

.aot-fx-tide {
  filter: drop-shadow(0 0 8px #65b8ff);
  animation: aot-fx-impact-pop var(--fx-duration) ease-out both;
}

.aot-fx-tide-ripple,
.aot-fx-ferment-ripple {
  position: absolute;
  left: 50%;
  top: 60%;
  width: 34%;
  height: 16%;
  border: 3px solid currentColor;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 8px currentColor, inset 0 0 8px currentColor;
  animation: aot-fx-ripple var(--fx-duration) var(--fx-delay, 0ms) ease-out both;
}

.aot-fx-tide-drop {
  left: 50%;
  top: 52%;
  border-radius: 70% 25% 65% 42%;
  transform: rotate(45deg);
  background: linear-gradient(135deg, #e9fbff, currentColor 62%);
  box-shadow: 0 0 5px currentColor;
  animation: aot-fx-droplet-burst var(--fx-duration) ease-out both;
}

/* Shadow */

.aot-fx-shadow {
  filter: drop-shadow(0 0 11px #6f3ab8);
  animation: aot-fx-impact-pop var(--fx-duration) ease-out both;
}

.aot-fx-shadow-core,
.aot-fx-shadow-vortex {
  position: absolute;
  left: 50%;
  top: 50%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

.aot-fx-shadow-core {
  width: 42%;
  aspect-ratio: 1;
  background: radial-gradient(circle, #030207 0 24%, #522074 42%, currentColor 58%, transparent 72%);
  box-shadow: 0 0 18px currentColor;
  animation: aot-fx-shadow-core var(--fx-duration) ease-in both;
}

.aot-fx-shadow-vortex {
  width: 86%;
  aspect-ratio: 1;
  background:
    repeating-conic-gradient(from 20deg, currentColor 0 8deg, transparent 10deg 29deg);
  -webkit-mask: radial-gradient(circle, transparent 0 35%, #000 42% 65%, transparent 72%);
  mask: radial-gradient(circle, transparent 0 35%, #000 42% 65%, transparent 72%);
  animation: aot-fx-shadow-vortex var(--fx-duration) cubic-bezier(0.15, 0.8, 0.2, 1) both;
}

.aot-fx-shadow-mote {
  left: 50%;
  top: 50%;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 6px currentColor;
  animation: aot-fx-shadow-mote var(--fx-duration) ease-in both;
}

/* Time */

.aot-fx-time {
  filter:
    drop-shadow(0 0 5px #dfffea)
    drop-shadow(0 0 13px #79f2c0);
  animation: aot-fx-time-arrive var(--fx-duration) cubic-bezier(0.12, 0.82, 0.2, 1) both;
}

.aot-fx-time-ring {
  position: absolute;
  left: 50%;
  top: 50%;
  aspect-ratio: 1;
  border: 2px solid currentColor;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

.aot-fx-time-ring--outer {
  width: 96%;
  border-style: dashed;
  animation: aot-fx-time-ring-outer var(--fx-duration) ease-out both;
}

.aot-fx-time-ring--inner {
  width: 48%;
  animation: aot-fx-time-ring-inner var(--fx-duration) ease-out both;
}

/* Fermentation, healing, and items */

.aot-fx-ferment {
  filter:
    drop-shadow(0 0 6px #fff1ac)
    drop-shadow(0 0 12px currentColor);
  animation: aot-fx-ferment-arrive var(--fx-duration) ease-out both;
}

.aot-fx-liquid-ribbon {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 34%;
  height: 92%;
  transform: translate(-50%, -50%);
  border: 5px solid transparent;
  border-left-color: currentColor;
  border-right-color: #ffd86b;
  border-radius: 50%;
  filter: drop-shadow(0 0 6px currentColor);
  animation: aot-fx-liquid-helix var(--fx-duration) cubic-bezier(0.15, 0.8, 0.2, 1) both;
}

.aot-fx-ferment-ripple {
  color: #ffd86b;
}

.aot-fx-cork-pop {
  position: absolute;
  left: 50%;
  top: 47%;
  width: 10%;
  min-width: 7px;
  height: 20%;
  border: 1px solid #633c1f;
  border-radius: 3px 3px 5px 5px;
  background:
    repeating-linear-gradient(90deg, transparent 0 2px, rgba(83, 44, 20, 0.22) 2px 3px),
    #d9a65e;
  box-shadow: 0 0 6px #fff1ac;
  animation: aot-fx-cork-pop var(--fx-duration) cubic-bezier(0.18, 0.8, 0.25, 1) both;
}

.aot-fx-ferment-bubble,
.aot-fx-golden-bubble {
  left: 50%;
  top: 56%;
  border: 1px solid rgba(255, 250, 205, 0.94);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 28%, #fff 0 8%, #ffd86b 22%, rgba(241, 167, 53, 0.24) 55%, transparent 72%);
  box-shadow: 0 0 7px #f1a735;
  animation: aot-fx-bubble-rise var(--fx-duration) ease-out both;
}

/* Outcome words */

.aot-fx-outcome {
  z-index: 4;
  min-width: 62px;
  padding: 3px 7px;
  border: 1px solid currentColor;
  border-radius: 3px;
  color: #fff5c9;
  background: rgba(13, 14, 12, 0.82);
  box-shadow: 0 3px 9px rgba(0, 0, 0, 0.6), 0 0 8px currentColor;
  font-size: clamp(0.58rem, 1.5vw, 0.78rem);
  font-weight: 900;
  letter-spacing: 0.11em;
  line-height: 1;
  text-align: center;
  text-shadow: 0 1px #000;
  animation: aot-fx-outcome var(--fx-duration) ease-out both;
}

.aot-fx-outcome--critical {
  color: #fff1a2;
  border-color: #ff8d43;
  font-size: clamp(0.7rem, 1.8vw, 0.95rem);
}

.aot-fx-outcome--weak {
  color: #ffce72;
  border-color: #ff704d;
}

.aot-fx-outcome--resist {
  color: #bcd6dc;
  border-color: #7f9ca3;
}

.aot-fx-outcome--absorb {
  color: #83ebad;
  border-color: #79f2c0;
}

.aot-fx-outcome--immune,
.aot-fx-outcome--miss {
  color: #d1d3ce;
  border-color: #8b918c;
  box-shadow: 0 3px 9px rgba(0, 0, 0, 0.58);
}

/* Persistent status auras on combatants */

.combatant.aot-status-aura {
  --aot-status-color: #d6dde0;
}

.combatant.aot-status--positive {
  --aot-status-color: #79f2c0;
}

.combatant.aot-status--negative {
  --aot-status-color: #c878d8;
}

.combatant.aot-status--mixed {
  --aot-status-color: #ff7b59;
}

.combatant.aot-status-aura::before,
.combatant.aot-status-aura::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 54%;
  z-index: -1;
  width: clamp(62px, 82%, 162px);
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.72;
}

.combatant.aot-status-aura::before {
  border: 1px solid var(--aot-status-color);
  box-shadow:
    inset 0 0 12px var(--aot-status-color),
    0 0 9px var(--aot-status-color);
  animation: aot-fx-status-breathe 1.55s ease-in-out infinite;
}

.combatant.aot-status-aura::after {
  background: radial-gradient(circle, transparent 45%, var(--aot-status-color) 72%, transparent 76%);
  -webkit-mask: repeating-conic-gradient(#000 0 4deg, transparent 5deg 30deg);
  mask: repeating-conic-gradient(#000 0 4deg, transparent 5deg 30deg);
  animation: aot-fx-status-orbit 3.2s linear infinite;
}

.combatant.aot-status--poison {
  --aot-status-color: #86c54b;
}

.combatant.aot-status--poison::after {
  width: 70%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 20% 70%, #b8ed69 0 4%, transparent 5%),
    radial-gradient(circle at 72% 52%, #8ed055 0 5%, transparent 6%),
    radial-gradient(circle at 45% 18%, #d5f594 0 3%, transparent 4%);
  -webkit-mask: none;
  mask: none;
  animation: aot-fx-status-bubbles 1.8s ease-in-out infinite;
}

.combatant.aot-status--blind {
  --aot-status-color: #6b536f;
}

.combatant.aot-status--blind::before {
  border: 0;
  background: radial-gradient(ellipse, transparent 0 22%, rgba(13, 8, 18, 0.86) 46%, transparent 72%);
  box-shadow: none;
  animation: aot-fx-status-blind 1.8s ease-in-out infinite;
}

.combatant.aot-status--sleep {
  --aot-status-color: #83b7e8;
}

.combatant.aot-status--sleep::after {
  content: "Z  z";
  left: 68%;
  top: 12%;
  width: auto;
  aspect-ratio: auto;
  color: #cdeaff;
  background: none;
  -webkit-mask: none;
  mask: none;
  font-family: Georgia, serif;
  font-size: clamp(0.7rem, 2vw, 1.05rem);
  font-weight: 800;
  text-shadow: 0 0 6px #5da2db, 0 2px 2px #000;
  animation: aot-fx-status-sleep 1.6s ease-in-out infinite;
}

.combatant.aot-status--confuse {
  --aot-status-color: #e58ddb;
}

.combatant.aot-status--confuse::after {
  top: 14%;
  width: 58%;
  border: 3px dotted currentColor;
  background: none;
  -webkit-mask: none;
  mask: none;
  animation: aot-fx-status-confuse 1.35s linear infinite;
}

.combatant.aot-status--lock {
  --aot-status-color: #d29b67;
}

.combatant.aot-status--lock::after {
  content: "×";
  left: 72%;
  top: 17%;
  width: 24px;
  aspect-ratio: 1;
  border: 2px solid currentColor;
  border-radius: 4px;
  background: rgba(24, 16, 11, 0.82);
  -webkit-mask: none;
  mask: none;
  color: #ffd2a8;
  font-size: 20px;
  font-weight: 900;
  line-height: 18px;
  text-align: center;
  animation: aot-fx-status-lock 1.7s ease-in-out infinite;
}

.combatant.aot-status--slow {
  --aot-status-color: #8fa6cc;
}

.combatant.aot-status--slow::after {
  background: repeating-conic-gradient(currentColor 0 5deg, transparent 5deg 45deg);
  -webkit-mask: radial-gradient(circle, transparent 55%, #000 58% 65%, transparent 68%);
  mask: radial-gradient(circle, transparent 55%, #000 58% 65%, transparent 68%);
  animation: aot-fx-status-slow 4.5s linear infinite;
}

.combatant.aot-status--stop {
  --aot-status-color: #a8f1d7;
}

.combatant.aot-status--stop::before {
  border: 2px solid currentColor;
  background:
    linear-gradient(90deg, transparent 49%, currentColor 50% 51%, transparent 52%),
    linear-gradient(0deg, transparent 49%, currentColor 50% 51%, transparent 52%);
  animation: aot-fx-status-stop 1.4s steps(2, end) infinite;
}

.combatant.aot-status--stun {
  --aot-status-color: #ffe268;
}

.combatant.aot-status--stun::after {
  top: 12%;
  width: 64%;
  background:
    radial-gradient(circle at 15% 55%, currentColor 0 5%, transparent 7%),
    radial-gradient(circle at 50% 20%, currentColor 0 6%, transparent 8%),
    radial-gradient(circle at 82% 58%, currentColor 0 5%, transparent 7%);
  -webkit-mask: none;
  mask: none;
  animation: aot-fx-status-stun 1.05s linear infinite;
}

.combatant.aot-status--berserk {
  --aot-status-color: #ff614f;
}

.combatant.aot-status--berserk::before {
  border: 2px solid currentColor;
  background: radial-gradient(circle, transparent 35%, rgba(255, 67, 48, 0.42) 69%, transparent 73%);
  animation: aot-fx-status-berserk 0.72s ease-in-out infinite alternate;
}

.combatant.aot-status--haste {
  --aot-status-color: #79f2c0;
}

.combatant.aot-status--haste::after {
  background: repeating-conic-gradient(currentColor 0 9deg, transparent 10deg 32deg);
  -webkit-mask: radial-gradient(circle, transparent 58%, #000 60% 67%, transparent 69%);
  mask: radial-gradient(circle, transparent 58%, #000 60% 67%, transparent 69%);
  animation: aot-fx-status-haste 0.9s linear infinite;
}

.combatant.aot-status--shield {
  --aot-status-color: #f4c96a;
}

.combatant.aot-status--shield::before {
  top: 52%;
  width: 108%;
  border: 2px solid currentColor;
  border-radius: 50% 50% 46% 46%;
  background: linear-gradient(135deg, rgba(255, 243, 178, 0.22), transparent 45%);
  box-shadow: inset 0 0 12px currentColor, 0 0 8px currentColor;
  animation: aot-fx-status-shield 1.65s ease-in-out infinite;
}

.combatant.aot-status--barrier {
  --aot-status-color: #b48cff;
}

.combatant.aot-status--barrier::before {
  width: 108%;
  border: 2px solid currentColor;
  border-radius: 18%;
  transform: translate(-50%, -50%) rotate(45deg);
  background: linear-gradient(135deg, rgba(211, 184, 255, 0.22), transparent 48%);
  animation: aot-fx-status-barrier 2s ease-in-out infinite;
}

.combatant.aot-status--reraise {
  --aot-status-color: #8bffd0;
}

.combatant.aot-status--reraise::after {
  background: repeating-conic-gradient(currentColor 0 3deg, transparent 3deg 30deg);
  -webkit-mask: radial-gradient(circle, transparent 58%, #000 60% 65%, transparent 67%);
  mask: radial-gradient(circle, transparent 58%, #000 60% 65%, transparent 67%);
  animation: aot-fx-status-reraise 3.1s linear infinite;
}

.combatant.aot-status--ko {
  --aot-status-color: #6f6175;
}

.combatant.aot-status--ko::before,
.combatant.aot-status--ko::after {
  animation: none;
  opacity: 0.25;
}

/* KO transition */

.combatant.aot-fx-actor-ko {
  animation: aot-fx-actor-ko 920ms cubic-bezier(0.18, 0.8, 0.22, 1) both;
}

.aot-fx-ko-burst {
  width: clamp(112px, calc(var(--fx-subject-width, 130px) * 1.05), 210px);
  aspect-ratio: 1;
  filter: drop-shadow(0 0 13px var(--fx-color));
  animation: aot-fx-ko-burst var(--fx-duration) ease-out both;
}

.aot-fx-ko-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 58%;
  aspect-ratio: 1;
  border: 3px solid currentColor;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, #fff 0 4%, currentColor 18%, rgba(22, 8, 31, 0.82) 46%, transparent 70%);
  animation: aot-fx-ko-core var(--fx-duration) ease-in both;
}

.aot-fx-ko-shard {
  left: 50%;
  top: 50%;
  background: linear-gradient(135deg, #fff, currentColor 50%, #2b1b30);
  clip-path: polygon(50% 0, 100% 100%, 0 74%);
  animation: aot-fx-shard-burst var(--fx-duration) ease-out both;
}

/* Festive victory, defeat, and escape */

.aot-fx-battle-end {
  inset: 0;
  width: 100%;
  height: 100%;
  transform: none;
  overflow: hidden;
}

.aot-fx-victory {
  background:
    radial-gradient(circle at 50% 47%, rgba(255, 230, 125, 0.3), transparent 34%),
    linear-gradient(to bottom, rgba(25, 12, 2, 0.08), rgba(62, 29, 5, 0.18));
  animation: aot-fx-victory-wash var(--fx-duration) ease-out both;
}

.aot-fx-victory-clock,
.aot-fx-defeat-clock {
  position: absolute;
  left: 50%;
  top: 47%;
  width: clamp(130px, 29vw, 240px);
  aspect-ratio: 1;
  color: #f7d879;
  transform: translate(-50%, -50%);
  filter:
    drop-shadow(0 0 6px #fff3b0)
    drop-shadow(0 0 24px #f1a735);
  animation: aot-fx-victory-clock var(--fx-duration) cubic-bezier(0.16, 0.82, 0.2, 1) both;
}

.aot-fx-victory-sweep {
  position: absolute;
  left: 50%;
  top: 47%;
  width: 68%;
  height: 4px;
  transform: translate(-50%, -50%) rotate(-38deg) scaleX(0);
  background: linear-gradient(90deg, transparent, #fff 30% 70%, transparent);
  box-shadow: 0 0 10px #fff3a1, 0 0 24px #f1a735;
  animation: aot-fx-victory-sweep var(--fx-duration) ease-out both;
}

.aot-fx-victory-cork {
  position: absolute;
  left: 50%;
  top: 58%;
  width: 13px;
  height: 28px;
  border: 2px solid #674223;
  border-radius: 4px 4px 6px 6px;
  background:
    repeating-linear-gradient(90deg, transparent 0 3px, rgba(91, 48, 22, 0.25) 3px 4px),
    #d9a65e;
  box-shadow: 0 0 8px #fff1ac;
  animation: aot-fx-victory-cork var(--fx-duration) cubic-bezier(0.16, 0.76, 0.2, 1) both;
}

.aot-fx-confetti {
  top: -8%;
  width: var(--fx-size, 8px);
  height: calc(var(--fx-size, 8px) * 1.65);
  border-radius: 1px;
  background: var(--fx-color, #f1a735);
  box-shadow: 0 0 3px color-mix(in srgb, var(--fx-color, #f1a735), transparent 35%);
  animation: aot-fx-confetti-fall var(--fx-duration) var(--fx-delay, 0ms) cubic-bezier(0.18, 0.62, 0.25, 1) both;
}

.aot-fx-confetti--0 {
  clip-path: polygon(50% 0, 100% 100%, 0 78%);
}

.aot-fx-confetti--1 {
  border-radius: 50% 0 50% 0;
}

.aot-fx-confetti--2 {
  clip-path: polygon(50% 0, 64% 36%, 100% 50%, 64% 64%, 50% 100%, 36% 64%, 0 50%, 36% 36%);
}

.aot-fx-golden-bubble {
  top: auto;
  bottom: -12%;
  animation-name: aot-fx-golden-bubble;
}

.aot-fx-defeat {
  background: rgba(11, 8, 13, 0.12);
  animation: aot-fx-defeat-wash var(--fx-duration) ease-out both;
}

.aot-fx-defeat-vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 47%, transparent 10%, rgba(13, 8, 17, 0.82) 78%);
  animation: aot-fx-defeat-vignette var(--fx-duration) ease-in both;
}

.aot-fx-defeat-clock {
  color: #8d8294;
  filter: drop-shadow(0 0 13px #4d3d54);
  animation-name: aot-fx-defeat-clock;
}

.aot-fx-defeat-crack {
  position: absolute;
  left: 50%;
  top: 47%;
  width: clamp(74px, 16vw, 132px);
  height: 2px;
  transform: rotate(var(--fx-rotation, 0deg));
  transform-origin: left center;
  background: linear-gradient(90deg, #eee7f0, #6d5a74 45%, transparent);
  box-shadow: 0 0 5px #a98db3;
  clip-path: polygon(0 20%, 24% 0, 47% 62%, 73% 12%, 100% 68%, 100% 100%, 72% 45%, 46% 100%, 22% 40%, 0 80%);
  animation: aot-fx-defeat-crack var(--fx-duration) ease-out both;
}

.aot-fx-escape {
  background:
    repeating-linear-gradient(115deg, transparent 0 8%, rgba(121, 242, 192, 0.28) 8.5% 9.5%, transparent 10% 19%);
  animation: aot-fx-escape var(--fx-duration) ease-in both;
}

.result-overlay .result-card {
  animation: aot-result-card-arrive 420ms cubic-bezier(0.16, 0.84, 0.2, 1) both;
}

.result-overlay.victory {
  background:
    radial-gradient(circle at 50% 42%, rgba(241, 167, 53, 0.17), transparent 34rem),
    rgba(5, 7, 6, 0.78);
}

.result-overlay.victory .result-card {
  border-color: rgba(255, 218, 120, 0.76);
  box-shadow:
    0 0 0 1px rgba(241, 167, 53, 0.22),
    0 0 42px rgba(241, 167, 53, 0.2),
    0 30px 100px #000;
}

.result-overlay.victory #resultTitle {
  color: #ffe5a0;
  text-shadow: 0 0 18px rgba(241, 167, 53, 0.52);
}

.result-overlay.defeat .result-card {
  border-color: rgba(158, 127, 171, 0.56);
  filter: saturate(0.72);
}

.result-overlay.escape .result-card {
  border-color: rgba(121, 242, 192, 0.5);
}

/* Keyframes */

@keyframes aot-result-card-arrive {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.94);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes aot-fx-camera-light {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(-2px, 1px); }
  50% { transform: translate(2px, -1px); }
  75% { transform: translate(-1px, -1px); }
}

@keyframes aot-fx-camera-heavy {
  0%, 100% { transform: translate(0, 0) scale(1); }
  12% { transform: translate(-5px, 2px) scale(1.008); }
  26% { transform: translate(5px, -3px) scale(1.008); }
  42% { transform: translate(-4px, -2px); }
  60% { transform: translate(3px, 2px); }
  78% { transform: translate(-1px, 1px); }
}

@keyframes aot-fx-camera-ko {
  0%, 100% { transform: translate(0, 0); }
  16% { transform: translate(0, 4px); }
  34% { transform: translate(-4px, -2px); }
  50% { transform: translate(4px, 1px); }
  68% { transform: translate(-2px, 0); }
}

@keyframes aot-fx-screen-flash {
  0% { opacity: 0; }
  14% { opacity: 0.82; }
  100% { opacity: 0; }
}

@keyframes aot-fx-cast-arrive {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
  28% { opacity: 1; }
  72% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.24); }
}

@keyframes aot-fx-cast-ring-spin {
  0% { opacity: 0; transform: rotate(-120deg) scale(0.35); }
  30% { opacity: 0.95; }
  100% { opacity: 0; transform: rotate(180deg) scale(1.18); }
}

@keyframes aot-fx-cast-core-pulse {
  from { opacity: 0.35; transform: scale(0.72); }
  to { opacity: 1; transform: scale(1.1); }
}

@keyframes aot-fx-cast-mote {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--fx-dx)), calc(-50% + var(--fx-dy))) scale(0.3); }
}

@keyframes aot-fx-ember-wobble {
  0%, 100% { border-radius: 45% 55% 42% 58%; }
  50% { border-radius: 58% 42% 60% 40%; }
}

@keyframes aot-fx-target-marker {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(1.7); }
  24%, 68% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(0.75); }
}

@keyframes aot-fx-line-telegraph {
  0% { opacity: 0; transform: translateY(-50%) rotate(var(--fx-angle, 0deg)) scaleX(0); }
  28%, 72% { opacity: 0.72; }
  100% { opacity: 0; transform: translateY(-50%) rotate(var(--fx-angle, 0deg)) scaleX(1); }
}

@keyframes aot-fx-radius-telegraph {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.25) rotate(-60deg); }
  35%, 72% { opacity: 0.72; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1) rotate(50deg); }
}

@keyframes aot-fx-all-telegraph {
  0% { opacity: 0; background-position: -120% 0, 0 0; }
  30%, 75% { opacity: 0.55; }
  100% { opacity: 0; background-position: 240% 0, 0 0; }
}

@keyframes aot-fx-converge {
  0% { opacity: 0; transform: translateY(-50%) rotate(var(--fx-angle)) scaleX(0); }
  28% { opacity: 1; }
  72% { opacity: 0.88; }
  100% { opacity: 0; transform: translateY(-50%) rotate(var(--fx-angle)) scaleX(1); }
}

@keyframes aot-fx-seal-arrive {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-110deg) scale(0.15); }
  38%, 72% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(32deg) scale(1.18); }
}

@keyframes aot-fx-banner {
  0% { opacity: 0; transform: translate(-50%, -50%) scaleX(0.2); clip-path: inset(0 50%); }
  24%, 74% { opacity: 1; transform: translate(-50%, -50%) scaleX(1); clip-path: inset(0); }
  100% { opacity: 0; transform: translate(-50%, -62%) scaleX(0.94); clip-path: inset(0); }
}

@keyframes aot-fx-clock-face {
  0% { opacity: 0; transform: rotate(90deg) scale(0.25); }
  30%, 72% { opacity: 0.95; }
  100% { opacity: 0; transform: rotate(-35deg) scale(1.08); }
}

@keyframes aot-fx-clock-hour {
  0% { transform: rotate(-40deg); }
  100% { transform: rotate(140deg); }
}

@keyframes aot-fx-clock-minute {
  0% { transform: rotate(30deg); }
  100% { transform: rotate(750deg); }
}

@keyframes aot-fx-impact-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.35); }
  18% { opacity: 1; transform: translate(-50%, -50%) scale(1.08); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.22); }
}

@keyframes aot-fx-slash {
  0% { opacity: 0; transform: rotate(var(--fx-rotation)) scaleX(0) scaleY(0.5); }
  16% { opacity: 1; }
  46% { opacity: 1; transform: rotate(var(--fx-rotation)) scaleX(var(--fx-scale, 1)) scaleY(1); }
  100% { opacity: 0; transform: rotate(var(--fx-rotation)) scaleX(var(--fx-scale, 1)) scaleY(0.1); }
}

@keyframes aot-fx-star {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(0) scale(0); }
  18% { opacity: 1; transform: translate(-50%, -50%) rotate(20deg) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(70deg) scale(1.8); }
}

@keyframes aot-fx-flame-core {
  0% { opacity: 0; transform: translate(-50%, -30%) scale(0.2) rotate(-8deg); }
  22% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -75%) scale(1.55) rotate(7deg); }
}

@keyframes aot-fx-ring-expand {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
  22% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.45); }
}

@keyframes aot-fx-particle-burst {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--fx-rotation)) scale(0); }
  18% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--fx-dx)), calc(-50% + var(--fx-dy))) rotate(calc(var(--fx-rotation) + 180deg)) scale(0.3); }
}

@keyframes aot-fx-frost-core {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-80deg) scale(0.15); }
  26% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(20deg) scale(1.45); }
}

@keyframes aot-fx-frost-ring {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(5deg) scale(0.2); }
  28% { opacity: 0.95; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(90deg) scale(1.38); }
}

@keyframes aot-fx-shard-burst {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--fx-rotation)) scale(0); }
  16% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--fx-dx)), calc(-50% + var(--fx-dy))) rotate(calc(var(--fx-rotation) + 120deg)) scale(0.46); }
}

@keyframes aot-fx-storm-flash {
  0%, 100% { opacity: 0; }
  12%, 23%, 38% { opacity: 1; }
  18%, 31%, 62% { opacity: 0.25; }
}

@keyframes aot-fx-bolt {
  0%, 100% { opacity: 0; transform: rotate(var(--fx-rotation)) scaleX(0); }
  14%, 40% { opacity: 1; transform: rotate(var(--fx-rotation)) scaleX(1); }
  28%, 58% { opacity: 0.18; }
}

@keyframes aot-fx-ripple {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
  18% { opacity: 0.92; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(3.1); }
}

@keyframes aot-fx-droplet-burst {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(45deg) scale(0); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--fx-dx)), calc(-50% + var(--fx-dy))) rotate(135deg) scale(0.42); }
}

@keyframes aot-fx-shadow-core {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(1.5); }
  40% { opacity: 1; transform: translate(-50%, -50%) scale(0.72); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(0.12); }
}

@keyframes aot-fx-shadow-vortex {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-120deg) scale(1.5); }
  34% { opacity: 0.86; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(180deg) scale(0.18); }
}

@keyframes aot-fx-shadow-mote {
  0% { opacity: 0; transform: translate(calc(-50% + var(--fx-dx)), calc(-50% + var(--fx-dy))) scale(0.2); }
  28% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.25); }
}

@keyframes aot-fx-time-arrive {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(1.5); }
  26%, 72% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(0.28); }
}

@keyframes aot-fx-time-ring-outer {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(120deg) scale(1.4); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(-180deg) scale(0.35); }
}

@keyframes aot-fx-time-ring-inner {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-90deg) scale(0.2); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(210deg) scale(1.8); }
}

@keyframes aot-fx-ferment-arrive {
  0% { opacity: 0; transform: translate(-50%, -40%) scale(0.42); }
  24%, 76% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -68%) scale(1.08); }
}

@keyframes aot-fx-liquid-helix {
  0% { opacity: 0; transform: translate(-50%, -20%) rotate(0) scaleY(0.1); }
  26% { opacity: 0.92; }
  100% { opacity: 0; transform: translate(-50%, -72%) rotate(360deg) scaleY(1.1); }
}

@keyframes aot-fx-cork-pop {
  0% { opacity: 0; transform: translate(-50%, 40%) rotate(0) scale(0.5); }
  22% { opacity: 1; }
  100% { opacity: 0; transform: translate(150%, -390%) rotate(410deg) scale(0.86); }
}

@keyframes aot-fx-bubble-rise {
  0% { opacity: 0; transform: translate(-50%, 0) scale(0.25); }
  25% { opacity: 0.95; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--fx-dx)), var(--fx-dy)) scale(1.15); }
}

@keyframes aot-fx-outcome {
  0% { opacity: 0; transform: translate(-50%, -20%) scale(0.62); }
  18%, 64% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -130%) scale(0.94); }
}

@keyframes aot-fx-status-breathe {
  0%, 100% { opacity: 0.35; transform: translate(-50%, -50%) scale(0.94); }
  50% { opacity: 0.75; transform: translate(-50%, -50%) scale(1.05); }
}

@keyframes aot-fx-status-orbit {
  from { transform: translate(-50%, -50%) rotate(0); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes aot-fx-status-bubbles {
  0%, 100% { opacity: 0.38; transform: translate(-50%, -40%) scale(0.9); }
  50% { opacity: 0.82; transform: translate(-50%, -62%) scale(1.08); }
}

@keyframes aot-fx-status-blind {
  0%, 100% { opacity: 0.55; transform: translate(-50%, -50%) scale(0.95); }
  50% { opacity: 0.82; transform: translate(-50%, -50%) scale(1.04); }
}

@keyframes aot-fx-status-sleep {
  0% { opacity: 0; transform: translate(-50%, 20%) scale(0.72); }
  35% { opacity: 1; }
  100% { opacity: 0; transform: translate(15%, -110%) scale(1.08); }
}

@keyframes aot-fx-status-confuse {
  from { transform: translate(-50%, -50%) rotate(0); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes aot-fx-status-lock {
  0%, 100% { opacity: 0.48; transform: translate(-50%, -50%) scale(0.9); }
  50% { opacity: 1; transform: translate(-50%, -50%) scale(1.08); }
}

@keyframes aot-fx-status-slow {
  from { transform: translate(-50%, -50%) rotate(0); }
  to { transform: translate(-50%, -50%) rotate(-360deg); }
}

@keyframes aot-fx-status-stop {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.85; }
}

@keyframes aot-fx-status-stun {
  from { transform: translate(-50%, -50%) rotate(0); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes aot-fx-status-berserk {
  from { opacity: 0.42; transform: translate(-50%, -50%) scale(0.9); }
  to { opacity: 0.9; transform: translate(-50%, -50%) scale(1.1); }
}

@keyframes aot-fx-status-haste {
  from { transform: translate(-50%, -50%) rotate(0); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes aot-fx-status-shield {
  0%, 100% { opacity: 0.35; transform: translate(-50%, -50%) scaleX(0.96); }
  50% { opacity: 0.72; transform: translate(-50%, -50%) scaleX(1.04); }
}

@keyframes aot-fx-status-barrier {
  0%, 100% { opacity: 0.32; transform: translate(-50%, -50%) rotate(45deg) scale(0.94); }
  50% { opacity: 0.74; transform: translate(-50%, -50%) rotate(135deg) scale(1.04); }
}

@keyframes aot-fx-status-reraise {
  from { transform: translate(-50%, -50%) rotate(0); }
  to { transform: translate(-50%, -50%) rotate(-360deg); }
}

@keyframes aot-fx-actor-ko {
  0% { filter: brightness(1); }
  18% { filter: brightness(3) saturate(0); }
  46% { filter: brightness(0.6) saturate(0.4); }
  100% { filter: grayscale(1) brightness(0.62); }
}

@keyframes aot-fx-ko-burst {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.3); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.45); }
}

@keyframes aot-fx-ko-core {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
  24% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(0.05); }
}

@keyframes aot-fx-victory-wash {
  0% { opacity: 0; filter: saturate(1); }
  18%, 74% { opacity: 1; filter: saturate(1.25); }
  100% { opacity: 0; filter: saturate(1); }
}

@keyframes aot-fx-victory-clock {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-90deg) scale(0.15); }
  22%, 70% { opacity: 0.82; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(50deg) scale(1.35); }
}

@keyframes aot-fx-victory-sweep {
  0%, 18% { opacity: 0; transform: translate(-50%, -50%) rotate(-38deg) scaleX(0); }
  30% { opacity: 1; }
  62% { opacity: 0.75; transform: translate(-50%, -50%) rotate(-38deg) scaleX(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(-38deg) scaleX(1.35); }
}

@keyframes aot-fx-victory-cork {
  0%, 12% { opacity: 0; transform: translate(-50%, 0) rotate(0) scale(0.5); }
  20% { opacity: 1; }
  68% { opacity: 1; transform: translate(180%, -580%) rotate(560deg) scale(1); }
  100% { opacity: 0; transform: translate(240%, -680%) rotate(720deg) scale(0.7); }
}

@keyframes aot-fx-confetti-fall {
  0% { opacity: 0; transform: translate(0, -20px) rotate(0); }
  12% { opacity: 1; }
  88% { opacity: 0.92; }
  100% { opacity: 0; transform: translate(var(--fx-drift, 0px), 430px) rotate(var(--fx-rotation, 540deg)); }
}

@keyframes aot-fx-golden-bubble {
  0% { opacity: 0; transform: translate(0, 20px) scale(0.35); }
  20% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(var(--fx-drift, 0px), -410px) scale(1.35); }
}

@keyframes aot-fx-defeat-wash {
  0% { opacity: 0; filter: grayscale(0); }
  28%, 78% { opacity: 1; filter: grayscale(0.75); }
  100% { opacity: 0; filter: grayscale(1); }
}

@keyframes aot-fx-defeat-vignette {
  0% { opacity: 0; }
  55%, 84% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes aot-fx-defeat-clock {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(0) scale(1.3); }
  32%, 70% { opacity: 0.66; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(-35deg) scale(0.42); }
}

@keyframes aot-fx-defeat-crack {
  0%, 25% { opacity: 0; transform: rotate(var(--fx-rotation)) scaleX(0); }
  42%, 78% { opacity: 0.85; transform: rotate(var(--fx-rotation)) scaleX(1); }
  100% { opacity: 0; transform: rotate(var(--fx-rotation)) scaleX(1.15); }
}

@keyframes aot-fx-escape {
  0% { opacity: 0; transform: translateX(-25%); }
  30% { opacity: 0.72; }
  100% { opacity: 0; transform: translateX(25%); }
}

/* Smaller battle layouts */

@media (max-width: 760px) {
  .aot-fx-combo-banner {
    top: 18%;
    min-height: 52px;
    padding: 7px 16px 9px;
  }

  .aot-fx-combo-seal {
    width: clamp(88px, 22vw, 126px);
  }

  .aot-fx-victory-clock,
  .aot-fx-defeat-clock {
    width: clamp(104px, 31vw, 170px);
  }

  .aot-fx-outcome {
    min-width: 48px;
    padding: 2px 5px;
  }
}

/* Reduced-motion works both from the media query and the JS-applied viewport class. */

@media (prefers-reduced-motion: reduce) {
  .result-overlay .result-card {
    animation: none !important;
  }

  .battle-viewport.aot-fx-camera--light,
  .battle-viewport.aot-fx-camera--heavy,
  .battle-viewport.aot-fx-camera--ko {
    animation: none !important;
  }

  .aot-fx-node,
  .aot-fx-node *,
  .combatant.aot-status-aura::before,
  .combatant.aot-status-aura::after {
    animation-duration: 120ms !important;
    animation-iteration-count: 1 !important;
  }

  .combatant.aot-status-aura::before,
  .combatant.aot-status-aura::after {
    animation: none !important;
    opacity: 0.42;
  }

  .aot-fx-confetti:nth-of-type(n + 10),
  .aot-fx-golden-bubble:nth-of-type(n + 7) {
    display: none;
  }
}

.aot-fx-reduced-motion.aot-fx-camera--light,
.aot-fx-reduced-motion.aot-fx-camera--heavy,
.aot-fx-reduced-motion.aot-fx-camera--ko {
  animation: none !important;
}

.aot-fx-reduced-motion .aot-fx-node,
.aot-fx-reduced-motion .aot-fx-node *,
.aot-fx-reduced-motion .combatant.aot-status-aura::before,
.aot-fx-reduced-motion .combatant.aot-status-aura::after {
  animation-duration: 120ms !important;
  animation-iteration-count: 1 !important;
}

.aot-fx-reduced-motion .combatant.aot-status-aura::before,
.aot-fx-reduced-motion .combatant.aot-status-aura::after {
  animation: none !important;
  opacity: 0.42;
}

/* Do not flash rapidly through all five frames for reduced-motion players. */
@media (prefers-reduced-motion: reduce) {
  .aot-fx-node.aot-fx-sprite-vfx {
    animation: aot-fx-sprite-peak 120ms ease-out both !important;
    mix-blend-mode: screen !important;
  }
}

.aot-fx-reduced-motion .aot-fx-node.aot-fx-sprite-vfx,
.aot-fx-node--reduced.aot-fx-sprite-vfx {
  animation: aot-fx-sprite-peak 120ms ease-out both !important;
  mix-blend-mode: screen !important;
}
.aot-fx-overhead-lightning {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  background: transparent;
  /* The stage itself is the only clip; no target-sized sprite rectangle. */
  transform: none;
}

