/* V1.34: professional combat beats without viewport shake. */
.vfx-action-beat {
  --vfx-beat-x: 50vw;
  --vfx-beat-y: 50vh;
  --vfx-beat-size: 180px;
  --vfx-beat-life: 560ms;
  --vfx-beat-angle: 0rad;
  --vfx-beat-primary: #8eeeff;
  --vfx-beat-primary-soft: rgba(142, 238, 255, .42);
  --vfx-beat-secondary: #fff1b8;
  --vfx-beat-secondary-soft: rgba(255, 241, 184, .32);
  position: fixed;
  left: var(--vfx-beat-x);
  top: var(--vfx-beat-y);
  z-index: 121;
  width: var(--vfx-beat-size);
  height: var(--vfx-beat-size);
  pointer-events: none;
  transform: translate(-50%, -50%) rotate(var(--vfx-beat-angle));
  isolation: isolate;
  contain: layout style paint;
  mix-blend-mode: screen;
}

.vfx-action-beat > i {
  position: absolute;
  display: block;
  pointer-events: none;
}

.vfx-action-beat-core {
  inset: 27%;
  border-radius: 50%;
  opacity: 0;
  background:
    radial-gradient(circle, #fff 0 4%, var(--vfx-beat-secondary) 7%, var(--vfx-beat-primary) 18%, var(--vfx-beat-primary-soft) 38%, transparent 70%);
  filter: blur(.2px) saturate(1.28);
  animation: vfxActionBeatCore var(--vfx-beat-life) cubic-bezier(.08,.84,.16,1) both;
}

.vfx-action-beat-ring {
  inset: 19%;
  border: 2px solid var(--vfx-beat-primary);
  border-radius: 50%;
  opacity: 0;
  box-shadow:
    0 0 10px var(--vfx-beat-primary-soft),
    0 0 24px var(--vfx-beat-secondary-soft),
    inset 0 0 18px var(--vfx-beat-primary-soft);
}

.vfx-action-beat-ring-a {
  animation: vfxActionBeatRingA var(--vfx-beat-life) cubic-bezier(.1,.78,.18,1) both;
}

.vfx-action-beat-ring-b {
  inset: 31%;
  border-width: 1px;
  border-style: dashed;
  animation: vfxActionBeatRingB var(--vfx-beat-life) 28ms cubic-bezier(.1,.8,.18,1) both;
}

.vfx-action-beat-brackets {
  inset: 8%;
  opacity: 0;
  background:
    linear-gradient(var(--vfx-beat-primary), var(--vfx-beat-primary)) left top / 20% 2px no-repeat,
    linear-gradient(var(--vfx-beat-primary), var(--vfx-beat-primary)) left top / 2px 20% no-repeat,
    linear-gradient(var(--vfx-beat-secondary), var(--vfx-beat-secondary)) right top / 20% 2px no-repeat,
    linear-gradient(var(--vfx-beat-secondary), var(--vfx-beat-secondary)) right top / 2px 20% no-repeat,
    linear-gradient(var(--vfx-beat-secondary), var(--vfx-beat-secondary)) right bottom / 20% 2px no-repeat,
    linear-gradient(var(--vfx-beat-secondary), var(--vfx-beat-secondary)) right bottom / 2px 20% no-repeat,
    linear-gradient(var(--vfx-beat-primary), var(--vfx-beat-primary)) left bottom / 20% 2px no-repeat,
    linear-gradient(var(--vfx-beat-primary), var(--vfx-beat-primary)) left bottom / 2px 20% no-repeat;
  filter: drop-shadow(0 0 7px var(--vfx-beat-primary-soft));
  animation: vfxActionBeatBrackets var(--vfx-beat-life) cubic-bezier(.12,.78,.18,1) both;
}

.vfx-action-beat-sweep {
  left: 8%;
  top: 50%;
  width: 84%;
  height: 2px;
  opacity: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--vfx-beat-primary), #fff 50%, var(--vfx-beat-secondary), transparent);
  box-shadow: 0 0 10px var(--vfx-beat-primary-soft), 0 0 20px var(--vfx-beat-secondary-soft);
  transform: translateY(-50%) scaleX(.12);
  animation: vfxActionBeatSweep var(--vfx-beat-life) steps(3, end) both;
}

.vfx-action-beat-mote {
  left: 50%;
  top: 50%;
  width: clamp(2px, calc(var(--vfx-beat-size) * .018), 5px);
  height: clamp(9px, calc(var(--vfx-beat-size) * .1), 26px);
  margin-left: -1px;
  margin-top: -5px;
  border-radius: 999px;
  opacity: 0;
  transform-origin: 50% 50%;
  background: linear-gradient(180deg, transparent, var(--vfx-beat-secondary), #fff);
  box-shadow: 0 0 8px var(--vfx-beat-primary), 0 0 14px var(--vfx-beat-secondary-soft);
  animation: vfxActionBeatMoteOut var(--vfx-beat-life) var(--vfx-beat-mote-delay) cubic-bezier(.08,.74,.18,1) both;
}

.vfx-action-beat-defend .vfx-action-beat-ring {
  border-radius: 27%;
  border-width: 3px;
  transform: rotate(45deg);
}

.vfx-action-beat-defend .vfx-action-beat-ring-b {
  border-style: solid;
  border-width: 1px;
}

.vfx-action-beat-defend .vfx-action-beat-sweep {
  height: 4px;
  background: linear-gradient(90deg, transparent, var(--vfx-beat-primary) 22%, #fff 50%, var(--vfx-beat-primary) 78%, transparent);
}

.vfx-action-beat-charge .vfx-action-beat-ring {
  border-style: double;
  border-width: 4px;
}

.vfx-action-beat-charge .vfx-action-beat-ring-b {
  border-style: dashed;
  border-width: 2px;
}

.vfx-action-beat-charge .vfx-action-beat-core {
  animation-name: vfxActionBeatChargeCore;
}

.vfx-action-beat-charge .vfx-action-beat-ring-a {
  animation-name: vfxActionBeatChargeRingA;
}

.vfx-action-beat-charge .vfx-action-beat-ring-b {
  animation-name: vfxActionBeatChargeRingB;
}

.vfx-action-beat-charge .vfx-action-beat-mote {
  animation-name: vfxActionBeatMoteIn;
}

.vfx-action-beat-critical {
  filter: saturate(1.2) contrast(1.08);
}

.vfx-action-beat-critical .vfx-action-beat-ring,
.vfx-action-beat.is-heavy .vfx-action-beat-ring {
  border-width: 3px;
}

.vfx-combat-telegraph {
  --vfx-telegraph-origin-x: 50vw;
  --vfx-telegraph-origin-y: 50vh;
  --vfx-telegraph-focus-x: 50vw;
  --vfx-telegraph-focus-y: 50vh;
  --vfx-telegraph-distance: 120px;
  --vfx-telegraph-angle: 0rad;
  --vfx-telegraph-life: 340ms;
  --vfx-telegraph-primary: #8eeeff;
  --vfx-telegraph-secondary: #ffd36a;
  position: fixed;
  inset: 0;
  z-index: 116;
  pointer-events: none;
  overflow: hidden;
  mix-blend-mode: screen;
}

.vfx-combat-telegraph > i {
  position: absolute;
  display: block;
  pointer-events: none;
}

.vfx-combat-telegraph-line {
  left: var(--vfx-telegraph-origin-x);
  top: var(--vfx-telegraph-origin-y);
  width: var(--vfx-telegraph-distance);
  height: 1px;
  opacity: 0;
  transform-origin: 0 50%;
  transform: rotate(var(--vfx-telegraph-angle)) scaleX(.12);
  background: linear-gradient(90deg, transparent, var(--vfx-telegraph-primary) 22%, rgba(255,255,255,.88) 72%, var(--vfx-telegraph-secondary));
  box-shadow: 0 0 8px var(--vfx-telegraph-primary);
  animation: vfxCombatTelegraphLine var(--vfx-telegraph-life) cubic-bezier(.12,.76,.2,1) both;
}

.vfx-combat-telegraph-source,
.vfx-combat-telegraph-target {
  width: 36px;
  height: 36px;
  margin: -18px 0 0 -18px;
  border: 1px solid var(--vfx-telegraph-primary);
  border-radius: 50%;
  opacity: 0;
  box-shadow: 0 0 12px color-mix(in srgb, var(--vfx-telegraph-primary) 58%, transparent);
}

.vfx-combat-telegraph-source {
  left: var(--vfx-telegraph-origin-x);
  top: var(--vfx-telegraph-origin-y);
  animation: vfxCombatTelegraphSource var(--vfx-telegraph-life) cubic-bezier(.12,.78,.18,1) both;
}

.vfx-combat-telegraph-target {
  left: var(--vfx-telegraph-focus-x);
  top: var(--vfx-telegraph-focus-y);
  width: 48px;
  height: 48px;
  margin: -24px 0 0 -24px;
  border-color: var(--vfx-telegraph-secondary);
  border-style: dashed;
  animation: vfxCombatTelegraphTarget var(--vfx-telegraph-life) cubic-bezier(.1,.8,.18,1) both;
}

.vfx-combat-telegraph.is-heavy .vfx-combat-telegraph-line {
  height: 2px;
  box-shadow: 0 0 10px var(--vfx-telegraph-primary), 0 0 18px var(--vfx-telegraph-secondary);
}

.card-vfx-defending {
  outline: 1px solid color-mix(in srgb, var(--card-vfx-secondary, #8eeeff) 74%, transparent);
  box-shadow: 0 0 18px color-mix(in srgb, var(--card-vfx-secondary, #8eeeff) 38%, transparent) !important;
}

.card-vfx-charging {
  outline: 1px solid color-mix(in srgb, var(--card-vfx-accent, #ffd66b) 72%, transparent);
  box-shadow: 0 0 20px color-mix(in srgb, var(--card-vfx-accent, #ffd66b) 42%, transparent) !important;
}

@keyframes vfxActionBeatCore {
  0% { opacity: 0; transform: scale(.12); filter: brightness(2.2) blur(2px); }
  10% { opacity: 1; transform: scale(.72); filter: brightness(1.42) blur(0); }
  26% { opacity: .58; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.3); filter: brightness(.9) blur(2px); }
}

@keyframes vfxActionBeatRingA {
  0% { opacity: 0; transform: scale(.2); }
  15% { opacity: .96; transform: scale(.58); }
  50% { opacity: .52; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.46); }
}

@keyframes vfxActionBeatRingB {
  0% { opacity: 0; transform: scale(.16) rotate(-22deg); }
  18% { opacity: .88; transform: scale(.66) rotate(-4deg); }
  58% { opacity: .42; transform: scale(1.02) rotate(28deg); }
  100% { opacity: 0; transform: scale(1.28) rotate(62deg); }
}

@keyframes vfxActionBeatBrackets {
  0% { opacity: 0; transform: scale(.34); }
  12% { opacity: .96; transform: scale(.82); }
  45% { opacity: .48; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.18); }
}

@keyframes vfxActionBeatSweep {
  0% { opacity: 0; transform: translateY(-50%) scaleX(.08); }
  8% { opacity: 1; transform: translateY(-50%) scaleX(.82); }
  19% { opacity: .52; transform: translateY(-50%) scaleX(1); }
  100% { opacity: 0; transform: translateY(-50%) scaleX(1.14); }
}

@keyframes vfxActionBeatMoteOut {
  0% { opacity: 0; transform: rotate(var(--vfx-beat-mote-angle)) translateX(8px) scale(.2); }
  13% { opacity: .96; transform: rotate(var(--vfx-beat-mote-angle)) translateX(22px) scale(1); }
  58% { opacity: .46; transform: rotate(var(--vfx-beat-mote-angle)) translateX(calc(var(--vfx-beat-mote-distance) * .72)) scale(.72); }
  100% { opacity: 0; transform: rotate(var(--vfx-beat-mote-angle)) translateX(var(--vfx-beat-mote-distance)) scale(.18); }
}

@keyframes vfxActionBeatMoteIn {
  0% { opacity: 0; transform: rotate(var(--vfx-beat-mote-angle)) translateX(var(--vfx-beat-mote-distance)) scale(.2); }
  18% { opacity: .72; transform: rotate(var(--vfx-beat-mote-angle)) translateX(calc(var(--vfx-beat-mote-distance) * .72)) scale(.7); }
  62% { opacity: 1; transform: rotate(var(--vfx-beat-mote-angle)) translateX(18px) scale(1); }
  100% { opacity: 0; transform: rotate(var(--vfx-beat-mote-angle)) translateX(5px) scale(.1); }
}

@keyframes vfxActionBeatChargeCore {
  0% { opacity: 0; transform: scale(1.45); filter: brightness(.8) blur(3px); }
  28% { opacity: .24; transform: scale(1.08); filter: brightness(1) blur(1.4px); }
  62% { opacity: .9; transform: scale(.52); filter: brightness(1.8) blur(0); }
  78% { opacity: 1; transform: scale(.68); filter: brightness(2.15) blur(0); }
  100% { opacity: 0; transform: scale(1.04); filter: brightness(1.2) blur(2px); }
}

@keyframes vfxActionBeatChargeRingA {
  0% { opacity: 0; transform: scale(1.38); }
  22% { opacity: .32; transform: scale(1.08); }
  62% { opacity: .92; transform: scale(.68); }
  82% { opacity: .58; transform: scale(.88); }
  100% { opacity: 0; transform: scale(1.08); }
}

@keyframes vfxActionBeatChargeRingB {
  0% { opacity: 0; transform: scale(1.58) rotate(48deg); }
  24% { opacity: .3; transform: scale(1.18) rotate(30deg); }
  64% { opacity: .82; transform: scale(.72) rotate(4deg); }
  84% { opacity: .46; transform: scale(.9) rotate(-12deg); }
  100% { opacity: 0; transform: scale(1.02) rotate(-24deg); }
}

@keyframes vfxCombatTelegraphLine {
  0% { opacity: 0; transform: rotate(var(--vfx-telegraph-angle)) scaleX(.08); }
  24% { opacity: .72; transform: rotate(var(--vfx-telegraph-angle)) scaleX(.72); }
  58% { opacity: .92; transform: rotate(var(--vfx-telegraph-angle)) scaleX(1); }
  100% { opacity: 0; transform: rotate(var(--vfx-telegraph-angle)) scaleX(1); }
}

@keyframes vfxCombatTelegraphSource {
  0% { opacity: 0; transform: scale(.3); }
  28% { opacity: .78; transform: scale(.72); }
  72% { opacity: .36; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.16); }
}

@keyframes vfxCombatTelegraphTarget {
  0% { opacity: 0; transform: scale(1.38) rotate(-24deg); }
  34% { opacity: .92; transform: scale(.82) rotate(-6deg); }
  72% { opacity: .58; transform: scale(1) rotate(10deg); }
  100% { opacity: 0; transform: scale(.9) rotate(20deg); }
}

@media (max-width: 720px) {
  .vfx-action-beat { opacity: .88; }
  .vfx-combat-telegraph { opacity: .76; }
  .vfx-combat-telegraph-source { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .vfx-action-beat,
  .vfx-combat-telegraph {
    display: none !important;
  }

  .card-vfx-defending,
  .card-vfx-charging {
    outline: 0 !important;
    box-shadow: none !important;
  }
}
