/**
 * 中国象棋双主题吃子特效样式表 v3 (capture-effects.css)
 * 时间轴编排 + Canvas 粒子 + SVG 精细图形 + 屏幕级反馈
 * 作用域：.board-surface / .board-wrapper / body 下的特效专用类
 */

/* ================= 常驻粒子画布 ================= */
.fx-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 39;
}

.capture-effects-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: hidden;
  z-index: 35;
}

.fx-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .fx-container * {
    animation-duration: 0.2s !important;
    animation-iteration-count: 1 !important;
  }
}

/* ================= 屏幕级反馈 ================= */
.fx-shake {
  animation: fx-screen-shake 0.22s ease-out;
}
.fx-shake-hard {
  animation: fx-screen-shake-hard 0.26s ease-out;
}
@keyframes fx-screen-shake {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(-2px, 1px); }
  50% { transform: translate(2px, -1px); }
  75% { transform: translate(-1px, -2px); }
}
@keyframes fx-screen-shake-hard {
  0%, 100% { transform: translate(0, 0); }
  15% { transform: translate(-3px, 2px); }
  35% { transform: translate(3px, -2px); }
  55% { transform: translate(-2px, -3px); }
  75% { transform: translate(2px, 2px); }
}

.fx-jelly {
  animation: fx-jelly-wobble 0.45s cubic-bezier(0.28, 0.84, 0.42, 1);
}
@keyframes fx-jelly-wobble {
  0%, 100% { transform: scale(1, 1); }
  25% { transform: scale(1.035, 0.955); }
  50% { transform: scale(0.97, 1.035); }
  75% { transform: scale(1.02, 0.985); }
}

/* 全屏氛围：战场暗角金光 */
.fx-ambient-gold {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 90;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(255, 190, 60, 0.28) 100%);
  animation: fx-ambient-pulse 0.85s ease-out forwards;
}
/* 全屏氛围：萌系柔彩晕 */
.fx-ambient-confetti {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 90;
  background:
    radial-gradient(ellipse at 20% 20%, rgba(244, 114, 182, 0.16), transparent 45%),
    radial-gradient(ellipse at 80% 30%, rgba(56, 189, 248, 0.15), transparent 45%),
    radial-gradient(ellipse at 50% 85%, rgba(250, 204, 21, 0.14), transparent 45%);
  animation: fx-ambient-pulse 0.9s ease-out forwards;
}
@keyframes fx-ambient-pulse {
  0% { opacity: 0; }
  18% { opacity: 1; }
  100% { opacity: 0; }
}

/* ================= SVG 精细图形配色 ================= */
.fx-container svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.svg-blade-body { fill: rgba(255, 240, 200, 0.92); }
.svg-blade-edge { fill: none; stroke: #fff; stroke-width: 1.6; filter: drop-shadow(0 0 6px #ffd700); }

.svg-horseshoe-body { fill: #b08d4f; stroke: #6e5426; stroke-width: 1.5; filter: drop-shadow(0 0 4px rgba(212, 175, 55, 0.7)); }
.svg-horseshoe-nail { fill: #e8cf9a; }

.svg-sigil-border { fill: rgba(230, 184, 0, 0.10); stroke: #e6b800; stroke-width: 2.5; }
.svg-sigil-line { stroke: #d4af37; stroke-width: 2; }
.svg-sigil-cell { fill: rgba(230, 184, 0, 0.22); stroke: #e6b800; stroke-width: 1.2; }

.svg-seal-body { fill: rgba(180, 30, 20, 0.92); stroke: #ffd700; stroke-width: 3; filter: drop-shadow(0 0 8px rgba(255, 215, 0, 0.8)); }
.svg-seal-inner { fill: none; stroke: rgba(255, 240, 180, 0.75); stroke-width: 1.6; }
.svg-seal-char { font-size: 26px; font-weight: 900; fill: #ffe9a8; font-family: "KaiTi", "楷体", serif; }

.svg-crack-line { stroke: rgba(50, 35, 20, 0.75); stroke-width: 2; stroke-linecap: round; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4)); }
.fx-scorch .svg-crack-line { stroke: rgba(40, 22, 8, 0.8); }

.svg-crown-body { fill: #fde047; stroke: #d4a017; stroke-width: 2; filter: drop-shadow(0 0 8px rgba(253, 224, 71, 0.9)); }
.svg-crown-gem { fill: #f472b6; filter: drop-shadow(0 0 4px #f472b6); }

.svg-bell-body { fill: #facc15; stroke: #b45309; stroke-width: 1.6; filter: drop-shadow(0 0 6px rgba(250, 204, 21, 0.8)); }
.svg-bell-clap { fill: #b45309; }

.svg-cloud-puff { fill: rgba(255, 255, 255, 0.92); filter: drop-shadow(0 2px 6px rgba(147, 197, 253, 0.6)); }

.svg-focus-lines line { stroke: rgba(56, 189, 248, 0.5); stroke-width: 2.4; }

/* ================= SVG 图形节点包装 ================= */
.fx-blade-wrap {
  position: absolute;
  height: 10%;
  transform-origin: 0% 50%;
  filter: drop-shadow(0 0 8px rgba(255, 215, 0, 0.7));
}
.fx-blade-out { animation: fx-blade-swing 0.3s cubic-bezier(0.2, 0.8, 0.3, 1) forwards; }
/* FX-07 修复：关键帧补 translateY(-50%) 居中起点 + rotate(--fx-angle) 方向，
   与 battle-ray/moe-line 同一规则；角度在 JS 侧按实际像素空间计算 */
@keyframes fx-blade-swing {
  0% { opacity: 0; transform: translateY(-50%) rotate(var(--fx-angle, 0deg)) scaleX(0.2); }
  40% { opacity: 1; transform: translateY(-50%) rotate(var(--fx-angle, 0deg)) scaleX(1.05); }
  100% { opacity: 0; transform: translateY(-50%) rotate(var(--fx-angle, 0deg)) scaleX(1.15); }
}
.fx-blade-slash-a { animation: fx-blade-slash-a 0.26s ease-out forwards; }
@keyframes fx-blade-slash-a {
  0% { opacity: 0; transform: rotate(-58deg) scaleX(0.1); }
  45% { opacity: 1; transform: rotate(-45deg) scaleX(1.2); }
  100% { opacity: 0; transform: rotate(-38deg) scaleX(1.5); }
}
.fx-blade-slash-b { animation: fx-blade-slash-b 0.24s ease-out forwards; }
@keyframes fx-blade-slash-b {
  0% { opacity: 0; transform: rotate(50deg) scaleX(0.1); }
  45% { opacity: 1; transform: rotate(38deg) scaleX(1.2); }
  100% { opacity: 0; transform: rotate(30deg) scaleX(1.5); }
}

.fx-horseshoe {
  position: absolute;
  width: 22px;
  height: 22px;
  transform: translate(-50%, -50%);
}
.fx-hs-a { animation: fx-hs-stamp 0.3s ease-out forwards; }
.fx-hs-b { animation: fx-hs-stamp 0.3s ease-out forwards; }
@keyframes fx-hs-stamp {
  0% { transform: translate(-50%, -50%) scale(0.4) rotate(-40deg); opacity: 0; }
  40% { transform: translate(-50%, -50%) scale(1.15) rotate(0deg); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }
}

.fx-sigil {
  position: absolute;
  width: 74px;
  height: 74px;
  transform: translate(-50%, -50%);
}
.fx-sigil svg { animation: fx-sigil-spin 0.5s ease-out forwards; }
@keyframes fx-sigil-spin {
  0% { transform: rotate(-120deg) scale(0.3); opacity: 0; }
  50% { transform: rotate(30deg) scale(1.1); opacity: 1; }
  100% { transform: rotate(90deg) scale(1.3); opacity: 0; }
}

.fx-seal-drop {
  position: absolute;
  width: 52px;
  height: 52px;
  transform: translate(-50%, -50%);
}
.fx-seal-drop svg { animation: fx-seal-fall 0.3s cubic-bezier(0.5, 0, 0.9, 0.6) forwards; }
@keyframes fx-seal-fall {
  0% { transform: translateY(-150px) scale(1.8) rotate(-18deg); opacity: 0; }
  60% { transform: translateY(0) scale(1) rotate(0deg); opacity: 1; }
  100% { transform: translateY(0) scale(0.96); opacity: 0; }
}

.fx-crack {
  position: absolute;
  width: 22%;
  height: 8%;
  transform: translate(-50%, -50%);
}
.fx-crack svg { animation: fx-crack-show 0.75s ease-out forwards; }
@keyframes fx-crack-show {
  0% { transform: scale(0.2); opacity: 0; }
  20% { transform: scale(1); opacity: 1; }
  75% { opacity: 0.85; }
  100% { opacity: 0; }
}

.fx-crown-drop {
  position: absolute;
  width: 40px;
  height: 34px;
  transform: translate(-50%, -50%);
}
.fx-crown-drop svg { animation: fx-crown-fall 0.32s cubic-bezier(0.34, 1.4, 0.64, 1) forwards; }
@keyframes fx-crown-fall {
  0% { transform: translateY(-120px) scale(0.5) rotate(-24deg); opacity: 0; }
  65% { transform: translateY(0) scale(1.2) rotate(8deg); opacity: 1; }
  100% { transform: translateY(0) scale(1) rotate(0deg); opacity: 1; }
}

.fx-bell-ring {
  position: absolute;
  width: 26px;
  height: 26px;
  transform: translate(-50%, -50%);
}
.fx-bell-ring svg { animation: fx-bell-swing 0.5s ease-in-out forwards; transform-origin: 50% 0%; }
@keyframes fx-bell-swing {
  0%, 100% { transform: rotate(0deg); }
  20% { transform: rotate(26deg); }
  45% { transform: rotate(-20deg); }
  70% { transform: rotate(12deg); }
  88% { transform: rotate(-6deg); }
}

.fx-cloud-pop {
  position: absolute;
  width: 56px;
  height: 32px;
  transform: translate(-50%, -50%);
}
.fx-cloud-pop svg { animation: fx-cloud-bounce 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards; }
@keyframes fx-cloud-bounce {
  0% { transform: scale(0.2); opacity: 0; }
  50% { transform: scale(1.25); opacity: 1; }
  100% { transform: scale(1.5); opacity: 0; }
}

.fx-focus-lines {
  position: absolute;
  width: 120px;
  height: 120px;
  transform: translate(-50%, -50%);
  animation: fx-focus-zoom 0.32s ease-out forwards;
}
@keyframes fx-focus-zoom {
  0% { transform: translate(-50%, -50%) scale(0.5) rotate(0deg); opacity: 0.9; }
  60% { transform: translate(-50%, -50%) scale(1.05) rotate(8deg); opacity: 0.8; }
  100% { transform: translate(-50%, -50%) scale(1.3) rotate(16deg); opacity: 0; }
}

/* ================= 漫画拟声字 ================= */
.fx-sfx-text {
  position: absolute;
  width: 60px;
  height: 40px;
  transform: translate(-50%, -140%);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.fx-sfx-text span {
  font-family: "KaiTi", "楷体", "Segoe UI", sans-serif;
  font-weight: 900;
  font-style: italic;
  font-size: 26px;
  color: #fff;
  -webkit-text-stroke: 1.2px #ec4899;
  text-shadow: 2px 2px 0 #db2777, -1px -1px 0 #f9a8d4;
  animation: fx-sfx-pop 0.55s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards;
}
.fx-sfx-text.pop span {
  -webkit-text-stroke-color: #38bdf8;
  text-shadow: 2px 2px 0 #0284c7, -1px -1px 0 #7dd3fc;
  color: #fffde7;
}
@keyframes fx-sfx-pop {
  0% { transform: scale(0.2) rotate(-18deg); opacity: 0; }
  45% { transform: scale(1.35) rotate(6deg); opacity: 1; }
  70% { transform: scale(1.05) rotate(-2deg); opacity: 1; }
  100% { transform: scale(1.15) rotate(0deg) translateY(-12px); opacity: 0; }
}

/* ================= 战斗通用元素 ================= */
.fx-hit-flash {
  position: absolute;
  width: 52px;
  height: 52px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  animation: fx-flash-fade 0.35s ease-out forwards;
}
.fx-hit-flash.battle { background: radial-gradient(circle, rgba(255, 200, 50, 0.9) 0%, rgba(180, 50, 0, 0.6) 60%, transparent 80%); }
.fx-hit-flash.moe { background: radial-gradient(circle, rgba(255, 180, 220, 0.95) 0%, rgba(120, 200, 255, 0.7) 60%, transparent 80%); }
@keyframes fx-flash-fade {
  0% { transform: translate(-50%, -50%) scale(0.4); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.6); opacity: 0; }
}

.fx-echo-ghost {
  position: absolute;
  width: 34px;
  height: 34px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 170, 60, 0.5) 0%, rgba(255, 100, 0, 0.22) 60%, transparent 80%);
  animation: fx-echo-fade 0.32s ease-out forwards;
}
@keyframes fx-echo-fade {
  0% { transform: translate(-50%, -50%) scale(0.6); opacity: 0.95; }
  100% { transform: translate(-50%, -50%) scale(1.25); opacity: 0; }
}

.fx-dust-puff {
  position: absolute;
  width: 40px;
  height: 22px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(150, 120, 80, 0.55) 0%, transparent 70%);
  animation: fx-dust-rise 0.45s ease-out forwards;
}
@keyframes fx-dust-rise {
  0% { transform: translate(-50%, -50%) scale(0.5); opacity: 0.9; }
  100% { transform: translate(-50%, -90%) scale(1.5); opacity: 0; }
}

.fx-muzzle-flame {
  position: absolute;
  width: 44px;
  height: 26px;
  transform: translate(-50%, -50%);
  background: linear-gradient(90deg, #fff 0%, #ffd700 35%, #ff5500 70%, transparent 100%);
  border-radius: 40% 50% 50% 40%;
  filter: blur(1px) drop-shadow(0 0 8px #ff8800);
  animation: fx-muzzle-blaze 0.2s ease-out forwards;
}
@keyframes fx-muzzle-blaze {
  0% { transform: translate(-50%, -50%) scaleX(0.2); opacity: 1; }
  60% { transform: translate(-50%, -50%) scaleX(1.3); opacity: 1; }
  100% { transform: translate(-50%, -50%) scaleX(0.9); opacity: 0; }
}

.fx-draw-flash {
  position: absolute;
  width: 46px;
  height: 46px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, rgba(170, 230, 255, 0.7) 45%, transparent 75%);
  animation: fx-flash-fade 0.22s ease-out forwards;
}

.fx-charge-glow {
  position: absolute;
  width: 40px;
  height: 40px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(249, 168, 212, 0.85) 0%, rgba(147, 197, 253, 0.5) 55%, transparent 78%);
  animation: fx-charge-pulse 0.18s ease-in forwards;
}
@keyframes fx-charge-pulse {
  0% { transform: translate(-50%, -50%) scale(0.3); opacity: 0.6; }
  100% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
}

.fx-gold-pillar {
  position: absolute;
  width: 56px;
  height: 150px;
  transform: translate(-50%, -100%);
  background: linear-gradient(180deg, rgba(255, 240, 180, 0.95) 0%, rgba(255, 200, 60, 0.55) 55%, transparent 100%);
  border-radius: 50% 50% 12% 12%;
  filter: blur(1.5px) drop-shadow(0 0 14px rgba(255, 200, 0, 0.85));
  animation: fx-pillar-beam 0.42s ease-out forwards;
}
@keyframes fx-pillar-beam {
  0% { transform: translate(-50%, -100%) scaleY(0.2); opacity: 0; }
  35% { transform: translate(-50%, -100%) scaleY(1); opacity: 1; }
  100% { transform: translate(-50%, -100%) scaleY(0.85); opacity: 0; }
}

.fx-sparkle-cross {
  position: absolute;
  width: 34px;
  height: 34px;
  transform: translate(-50%, -50%);
  animation: fx-sparkle-rot 0.4s ease-out forwards;
}
.fx-sparkle-cross::before,
.fx-sparkle-cross::after {
  content: '';
  position: absolute;
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 0 8px #fde047;
}
.fx-sparkle-cross::before { left: 50%; top: 0; width: 3.5px; height: 100%; transform: translateX(-50%); }
.fx-sparkle-cross::after { top: 50%; left: 0; height: 3.5px; width: 100%; transform: translateY(-50%); }
@keyframes fx-sparkle-rot {
  0% { transform: translate(-50%, -50%) scale(0.2) rotate(0deg); opacity: 0; }
  45% { transform: translate(-50%, -50%) scale(1.3) rotate(45deg); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(0.9) rotate(90deg); opacity: 0; }
}

/* ---- 既有战斗图形（保留并增强） ---- */
.fx-battle-charge-ray {
  position: absolute;
  height: 6px;
  background: linear-gradient(90deg, rgba(255, 215, 0, 0) 0%, rgba(255, 160, 0, 0.9) 70%, #fff 100%);
  box-shadow: 0 0 12px #ff8800;
  transform-origin: 0% 50%;
  animation: battle-ray-anim 0.25s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
@keyframes battle-ray-anim {
  0% { transform: rotate(var(--fx-angle, 0deg)) scaleX(0.1); opacity: 1; }
  60% { transform: rotate(var(--fx-angle, 0deg)) scaleX(1); opacity: 1; height: 10px; }
  100% { transform: rotate(var(--fx-angle, 0deg)) scaleX(1); opacity: 0; height: 1px; }
}

.fx-battle-shockwave {
  position: absolute;
  width: 70px;
  height: 70px;
  transform: translate(-50%, -50%);
  border: 3px solid rgba(255, 180, 0, 0.85);
  border-radius: 50%;
  box-shadow: 0 0 20px rgba(255, 100, 0, 0.8), inset 0 0 15px rgba(255, 200, 0, 0.6);
  animation: battle-shockwave-anim 0.4s ease-out forwards;
}
.fx-battle-shockwave.big { width: 95px; height: 95px; border-width: 4px; box-shadow: 0 0 30px rgba(255, 80, 0, 0.95), inset 0 0 22px rgba(255, 190, 0, 0.7); }
.fx-battle-shockwave.delay2 { animation-delay: 0.09s; animation-fill-mode: backwards; }
@keyframes battle-shockwave-anim {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.7); opacity: 0; }
}

.fx-battle-hoof {
  position: absolute;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.fx-battle-hoof.stomp {
  border: 3px double #d4af37;
  background: radial-gradient(circle, rgba(160, 60, 0, 0.7) 0%, transparent 70%);
  animation: battle-hoof-stomp-anim 0.45s cubic-bezier(0.1, 0.9, 0.2, 1) forwards;
}
@keyframes battle-hoof-stomp-anim {
  0% { transform: translate(-50%, -50%) scale(0.3); opacity: 1; }
  50% { transform: translate(-50%, -50%) scale(1.3); opacity: 0.9; }
  100% { transform: translate(-50%, -50%) scale(1.6); opacity: 0; }
}

.fx-battle-cannon-muzzle {
  position: absolute;
  width: 36px;
  height: 36px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #ff5500 60%, transparent 80%);
  animation: cannon-muzzle-flash 0.2s ease-out forwards;
}
@keyframes cannon-muzzle-flash {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.4); opacity: 0; }
}

.fx-battle-cannon-shell {
  position: absolute;
  width: 14px;
  height: 14px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #ffaa00 50%, #b32d00 100%);
  box-shadow: 0 0 12px #ff6600, 0 0 20px #ff0000;
  animation: cannon-shell-pulse 0.32s linear forwards;
}
@keyframes cannon-shell-pulse {
  0% { transform: translate(-50%, -50%) scale(0.8); }
  50% { transform: translate(-50%, -50%) scale(1.35); filter: brightness(1.3); }
  100% { transform: translate(-50%, -50%) scale(1.1); }
}

.fx-battle-cannon-explosion {
  position: absolute;
  width: 80px;
  height: 80px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #ffffff 0%, #ffb700 30%, #ff3700 65%, rgba(40, 20, 10, 0.8) 85%, transparent 100%);
  box-shadow: 0 0 35px rgba(255, 60, 0, 0.9);
  animation: cannon-explosion-anim 0.5s cubic-bezier(0.1, 0.8, 0.3, 1) forwards;
}
@keyframes cannon-explosion-anim {
  0% { transform: translate(-50%, -50%) scale(0.1); opacity: 1; }
  40% { transform: translate(-50%, -50%) scale(1.3); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.8); opacity: 0; filter: blur(3px); }
}

.fx-battle-bishop-earthquake {
  position: absolute;
  width: 65px;
  height: 65px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 3px dashed #8b5a2b;
  animation: bishop-earthquake-anim 0.45s ease-out forwards;
}
@keyframes bishop-earthquake-anim {
  0% { transform: translate(-50%, -50%) scale(0.4); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.6); opacity: 0; }
}

.fx-battle-advisor-slash {
  position: absolute;
  width: 70px;
  height: 8px;
  transform: translate(-50%, -50%) rotate(-45deg);
  background: linear-gradient(90deg, transparent, #ffffff 50%, transparent);
  box-shadow: 0 0 15px #66ccff;
  animation: advisor-slash-anim 0.28s ease-out forwards;
}
@keyframes advisor-slash-anim {
  0% { transform: translate(-50%, -50%) rotate(-45deg) scaleX(0.1); opacity: 1; }
  50% { transform: translate(-50%, -50%) rotate(-45deg) scaleX(1.4); opacity: 1; }
  100% { transform: translate(-50%, -50%) rotate(-45deg) scaleX(1.7); opacity: 0; }
}

.fx-battle-king-seal {
  position: absolute;
  width: 58px;
  height: 58px;
  transform: translate(-50%, -50%);
  border: 3px solid #ffd700;
  border-radius: 6px;
  background: radial-gradient(circle, rgba(255, 215, 0, 0.4) 0%, rgba(180, 100, 0, 0.2) 100%);
  box-shadow: 0 0 25px rgba(255, 215, 0, 0.8), inset 0 0 15px rgba(255, 215, 0, 0.5);
  animation: king-seal-drop 0.45s cubic-bezier(0.1, 0.9, 0.2, 1) forwards;
}
@keyframes king-seal-drop {
  0% { transform: translate(-50%, -90%) scale(1.8); opacity: 0; }
  60% { transform: translate(-50%, -50%) scale(1.0); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.15); opacity: 0; }
}

.fx-battle-king-aura {
  position: absolute;
  width: 120px;
  height: 120px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 2px solid rgba(255, 215, 0, 0.6);
  box-shadow: 0 0 25px rgba(255, 180, 0, 0.4);
  animation: king-aura-expand 0.6s ease-out forwards;
}
@keyframes king-aura-expand {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.6); opacity: 0; }
}

.fx-battle-pawn-thrust {
  position: absolute;
  width: 32px;
  height: 4px;
  transform-origin: 0% 50%;
  background: linear-gradient(90deg, transparent, #ffffff 70%, #ff8800);
  box-shadow: 0 0 10px #ffaa00;
  animation: pawn-thrust-anim 0.2s ease-out forwards;
}
@keyframes pawn-thrust-anim {
  0% { transform: rotate(var(--fx-angle, 0deg)) scaleX(0.2); opacity: 1; }
  100% { transform: rotate(var(--fx-angle, 0deg)) scaleX(1.3); opacity: 0; }
}

.fx-battle-pawn-impact {
  position: absolute;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #ffffff 0%, #ff9900 50%, transparent 80%);
  animation: fx-flash-fade 0.3s ease-out forwards;
}

/* ================= 萌系图形元素 ================= */
.fx-moe-speed-line {
  position: absolute;
  height: 8px;
  transform-origin: 0% 50%;
  background: linear-gradient(90deg, transparent 0%, #38bdf8 60%, #ec4899 100%);
  border-radius: 4px;
  box-shadow: 0 0 10px #38bdf8;
  animation: moe-speed-anim 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
@keyframes moe-speed-anim {
  0% { transform: rotate(var(--fx-angle, 0deg)) scaleX(0.1); opacity: 1; }
  70% { transform: rotate(var(--fx-angle, 0deg)) scaleX(1.05); opacity: 1; }
  100% { transform: rotate(var(--fx-angle, 0deg)) scaleX(1); opacity: 0; }
}

.fx-moe-star-burst {
  position: absolute;
  width: 58px;
  height: 58px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: moe-star-burst-anim 0.4s ease-out forwards;
}
.fx-moe-star-burst::before { content: "⭐"; font-size: 32px; filter: drop-shadow(0 0 8px #fde047); }
.fx-moe-star-burst.d2 { animation-delay: 0.08s; animation-fill-mode: backwards; }
.fx-moe-star-burst.d2::before { font-size: 22px; }
@keyframes moe-star-burst-anim {
  0% { transform: translate(-50%, -50%) scale(0.2) rotate(0deg); opacity: 1; }
  60% { transform: translate(-50%, -50%) scale(1.4) rotate(72deg); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.8) rotate(144deg); opacity: 0; }
}

.fx-moe-spring-bounce {
  position: absolute;
  width: 16px;
  height: 16px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #f472b6 60%, #c084fc 100%);
  box-shadow: 0 0 15px #f472b6;
  animation: moe-spring-squash 0.3s cubic-bezier(0.17, 0.67, 0.83, 0.67) forwards;
}
@keyframes moe-spring-squash {
  0% { transform: translate(-50%, -50%) scale(1, 0.7); }
  50% { transform: translate(-50%, -50%) scale(0.85, 1.3); }
  100% { transform: translate(-50%, -50%) scale(1, 0.9); }
}

.fx-moe-bell-stars {
  position: absolute;
  width: 54px;
  height: 54px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: moe-bell-stars-anim 0.4s ease-out forwards;
}
.fx-moe-bell-stars::before { content: "✨"; font-size: 26px; filter: drop-shadow(0 0 8px #facc15); }
@keyframes moe-bell-stars-anim {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 1; }
  50% { transform: translate(-50%, -50%) scale(1.3); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.6); opacity: 0; }
}

.fx-moe-candy-arc {
  position: absolute;
  width: 18px;
  height: 18px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #fb7185 60%, #ec4899 100%);
  box-shadow: 0 0 16px #fb7185;
  animation: moe-candy-spin 0.32s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}
@keyframes moe-candy-spin {
  0% { transform: translate(-50%, -50%) scale(0.8) rotate(0deg); }
  50% { transform: translate(-50%, -50%) scale(1.4) rotate(180deg); }
  100% { transform: translate(-50%, -50%) scale(1) rotate(360deg); }
}

.fx-moe-confetti-pop {
  position: absolute;
  width: 75px;
  height: 75px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95) 0%, rgba(244, 114, 182, 0.8) 40%, rgba(96, 165, 250, 0.6) 70%, transparent 90%);
  box-shadow: 0 0 30px rgba(244, 114, 182, 0.8);
  animation: moe-confetti-anim 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards;
}
@keyframes moe-confetti-anim {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 1; }
  60% { transform: translate(-50%, -50%) scale(1.3); opacity: 0.9; }
  100% { transform: translate(-50%, -50%) scale(1.7); opacity: 0; }
}

.fx-jelly-ripple {
  position: absolute;
  width: 60px;
  height: 60px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 3px solid rgba(249, 168, 212, 0.9);
  box-shadow: 0 0 16px rgba(56, 189, 248, 0.6), inset 0 0 10px rgba(249, 168, 212, 0.5);
  animation: fx-jelly-ripple-anim 0.55s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards;
}
@keyframes fx-jelly-ripple-anim {
  0% { transform: translate(-50%, -50%) scale(0.3); opacity: 1; border-radius: 50% 45% 52% 48%; }
  50% { transform: translate(-50%, -50%) scale(1.35); opacity: 0.9; border-radius: 45% 52% 48% 55%; }
  100% { transform: translate(-50%, -50%) scale(1.65); opacity: 0; border-radius: 50%; }
}

.fx-moe-bishop-bubbles {
  position: absolute;
  width: 48px;
  height: 48px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: bishop-bubbles-anim 0.45s ease-out forwards;
}
.fx-moe-bishop-bubbles::before { content: "🫧"; font-size: 30px; }
@keyframes bishop-bubbles-anim {
  0% { transform: translate(-50%, -50%) scale(0.5); opacity: 1; }
  100% { transform: translate(-50%, -70%) scale(1.4); opacity: 0; }
}

.fx-moe-advisor-laser {
  position: absolute;
  width: 72px;
  height: 10px;
  transform: translate(-50%, -50%) rotate(-45deg);
  background: linear-gradient(90deg, transparent, #ec4899 40%, #ffffff 50%, #38bdf8 60%, transparent);
  border-radius: 5px;
  box-shadow: 0 0 16px #ec4899;
  animation: advisor-laser-anim 0.26s ease-out forwards;
}
@keyframes advisor-laser-anim {
  0% { transform: translate(-50%, -50%) rotate(-45deg) scaleX(0.2); opacity: 1; }
  50% { transform: translate(-50%, -50%) rotate(-45deg) scaleX(1.3); opacity: 1; }
  100% { transform: translate(-50%, -50%) rotate(-45deg) scaleX(1.6); opacity: 0; }
}

.fx-moe-king-halo {
  position: absolute;
  width: 100px;
  height: 100px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 3px solid rgba(244, 114, 182, 0.8);
  box-shadow: 0 0 25px rgba(56, 189, 248, 0.7);
  animation: king-aura-expand 0.6s ease-out forwards;
}
.fx-moe-king-halo.d2 { animation-delay: 0.12s; animation-fill-mode: backwards; border-color: rgba(56, 189, 248, 0.8); }

.fx-fist-charge {
  position: absolute;
  width: 30px;
  height: 30px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(253, 224, 71, 0.8) 0%, transparent 75%);
  animation: fx-charge-pulse 0.15s ease-in forwards;
}

.fx-moe-pawn-punch {
  position: absolute;
  width: 42px;
  height: 42px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: moe-pawn-punch-anim 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards;
}
.fx-moe-pawn-punch::before { content: "🥊"; font-size: 26px; }
@keyframes moe-pawn-punch-anim {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 1; }
  60% { transform: translate(-50%, -50%) scale(1.4); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.1); opacity: 0; }
}

/* ================= 出手替身与退场残影 ================= */
.fx-piece-hidden { visibility: hidden !important; }

.fx-attacker-ghost {
  position: absolute;
  width: min(54px, 10.2%);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--piece-wood-light, #f5deb3) 0%, var(--piece-wood-dark, #b8860b) 90%);
  border: 2px solid #7c4819;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 45;
}
.fx-attacker-ghost.battle { box-shadow: 0 4px 10px rgba(0,0,0,0.45), 0 0 18px rgba(255, 140, 0, 0.75); }
.fx-attacker-ghost.moe { box-shadow: 0 4px 10px rgba(0,0,0,0.35), 0 0 18px rgba(244, 114, 182, 0.8); }
.fx-attacker-char {
  font-size: min(28px, 5.5vw);
  font-weight: 900;
  font-family: "KaiTi", "楷体", serif;
  line-height: 1;
}
.fx-attacker-ghost.red .fx-attacker-char { color: #c0392b; text-shadow: 0 1px 1px rgba(255,255,255,0.6), 0 -1px 1px rgba(90,0,0,0.5); }
.fx-attacker-ghost.black .fx-attacker-char { color: #1c1c1e; text-shadow: 0 1px 1px rgba(255,255,255,0.35), 0 -1px 1px rgba(0,0,0,0.6); }

/* 命中瞬间 squash & stretch 回弹 */
.fx-attacker-ghost.fx-ghost-land { animation: fx-ghost-squash 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
@keyframes fx-ghost-squash {
  0% { opacity: 1; }
  35% { transform: translate(-50%, -50%) scale(1.3, 0.72); filter: brightness(1.35); }
  70% { transform: translate(-50%, -50%) scale(0.9, 1.12); opacity: 0.85; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }
}

.fx-vanish-ghost {
  position: absolute;
  width: 48px;
  height: 48px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fx-vanish-ghost.battle { animation: fx-vanish-battle 0.5s ease-out forwards; }
.fx-vanish-ghost.battle::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(60, 40, 25, 0.75) 0%, rgba(20, 15, 10, 0.35) 60%, transparent 80%);
}
@keyframes fx-vanish-battle {
  0% { transform: translate(-50%, -50%) scale(0.6); opacity: 1; filter: blur(0px); }
  100% { transform: translate(-50%, -50%) scale(1.9); opacity: 0; filter: blur(4px); }
}
.fx-vanish-ghost.moe { animation: fx-vanish-moe 0.55s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards; }
.fx-vanish-ghost.moe::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(244, 114, 182, 0.55) 0%, rgba(56, 189, 248, 0.35) 60%, transparent 80%);
}
@keyframes fx-vanish-moe {
  0% { transform: translate(-50%, -50%) scale(0.5) rotate(0deg); opacity: 1; }
  50% { transform: translate(-50%, -50%) scale(1.35) rotate(30deg); opacity: 0.85; }
  100% { transform: translate(-50%, -50%) scale(1.8) rotate(60deg); opacity: 0; }
}
.fx-vanish-char {
  position: relative;
  font-size: min(26px, 5vw);
  font-weight: 900;
  font-family: "KaiTi", "楷体", serif;
  color: #5a3a1a;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.5);
}

/* ================= 特效与音量设置弹窗 ================= */
.effects-settings-card {
  max-width: 400px;
  width: 90%;
  max-height: calc(100vh - 24px);
  max-height: calc(100dvh - 24px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.effects-settings-card .modal-body { overflow-y: auto; min-height: 0; -webkit-overflow-scrolling: touch; }
.effects-settings-card .modal-title,
.effects-settings-card .modal-actions { flex-shrink: 0; }

@media (max-height: 420px) {
  .effects-settings-card .modal-body { padding-top: 6px; padding-bottom: 6px; }
  .effects-settings-card .settings-group { margin-bottom: 8px; }
  .effects-settings-card .settings-label { margin-bottom: 4px; font-size: 12px; }
  .effects-settings-card .settings-radio-label { padding: 5px 8px; font-size: 12px; }
  .effects-settings-card .settings-preview-bar { margin-top: 8px; padding-top: 8px; }
  .effects-settings-card .modal-actions { margin-top: 8px; }
}

.settings-group { margin-bottom: 16px; }
.settings-label { font-size: 13px; color: var(--text-muted); margin-bottom: 8px; display: block; }
.settings-radio-group { display: flex; gap: 10px; }
.settings-radio-label {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  color: var(--text-color);
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s ease;
  user-select: none;
}
.settings-radio-label:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.2); }
.settings-radio-label input[type="radio"] { accent-color: #d4af37; }
.settings-radio-label.active { background: rgba(212, 175, 55, 0.2); border-color: #d4af37; color: #ffd700; font-weight: bold; }

.settings-range-slider { width: 100%; accent-color: #d4af37; height: 6px; border-radius: 3px; background: rgba(255, 255, 255, 0.1); outline: none; }
.volume-row { display: flex; align-items: center; gap: 12px; }
.volume-val-badge { font-size: 13px; color: #d4af37; font-family: monospace; min-width: 38px; }
.settings-preview-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px dashed rgba(255, 255, 255, 0.1); }
.settings-help { flex-basis: 100%; font-size: 11px; line-height: 1.6; color: var(--text-muted); margin: 6px 0 0; }
.settings-radio-group:has(input[name="fx-voice"]) { flex-wrap: wrap; }
.settings-radio-group:has(input[name="fx-voice"]) .settings-radio-label { padding: 8px; white-space: nowrap; }

/* ================= v4 立绘特效层 ================= */
/* 定位：wrapper 只动 left/top（与棋盘同几何），自身居中用负 margin 百分比（相对容器宽，非 translate%） */
.fx-art {
  position: absolute;
  width: 30%;
  aspect-ratio: 1 / 1;
  margin-left: -15%;
  margin-top: -15%;
  pointer-events: none;
  opacity: 0;
  z-index: 46;
  will-change: left, top, opacity;
}
.fx-art .fx-art-flip { position: absolute; inset: 0; transform: var(--fx-flip, none); }
.fx-art .fx-art-img {
  width: 100%; height: 100%; object-fit: contain; display: block;
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.35));
}
.fx-art-flash-wrap {
  position: absolute; width: 34%; aspect-ratio: 1 / 1;
  margin-left: -17%; margin-top: -17%;
  pointer-events: none; z-index: 47; mix-blend-mode: screen;
}
.fx-art-flash-wrap .fx-art-img { width: 100%; height: 100%; object-fit: contain; display: block; animation: fx-art-flash-pop 0.34s ease-out forwards; }
.fx-art-ghost-wrap {
  position: absolute; width: 27%; aspect-ratio: 1 / 1;
  margin-left: -13.5%; margin-top: -13.5%;
  pointer-events: none; z-index: 45;
}
.fx-art-ghost-wrap .fx-art-img { width: 100%; height: 100%; object-fit: contain; display: block; animation: fx-art-ghost-dissolve 0.42s ease-in forwards; }

@keyframes fx-art-flash-pop {
  0% { opacity: 0.95; transform: scale(1.15); }
  100% { opacity: 0; transform: scale(1.4); }
}
@keyframes fx-art-ghost-dissolve {
  0% { opacity: 0.55; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.1); }
}
@keyframes fx-art-vanish { to { opacity: 0; } }
.fx-art.fx-phase-out { animation: fx-art-vanish 0.36s ease-in forwards; }

/* 兵种攻击姿态（只动 scale/rotate，绝不动位移） */
@keyframes fx-art-pose-ram { 0% { transform: scale(1); } 45% { transform: scale(1.2); } 100% { transform: scale(1.04); } }
@keyframes fx-art-pose-rear { 0% { transform: rotate(-10deg) scale(1); } 55% { transform: rotate(12deg) scale(1.1); } 100% { transform: rotate(0deg) scale(1); } }
@keyframes fx-art-pose-recoil { 0% { transform: rotate(0deg) scale(1.06); } 40% { transform: rotate(-15deg) scale(1); } 100% { transform: rotate(-8deg) scale(1.02); } }
@keyframes fx-art-pose-stomp { 0% { transform: scale(1.24); } 55% { transform: scale(0.92); } 100% { transform: scale(1.06); } }
@keyframes fx-art-pose-slash { 0% { transform: rotate(-18deg) scale(1.06); } 100% { transform: rotate(6deg) scale(1); } }
@keyframes fx-art-pose-slash-heavy { 0% { transform: rotate(-26deg) scale(1.14); } 100% { transform: rotate(3deg) scale(1); } }
@keyframes fx-art-pose-thrust { 0% { transform: scale(1.12); } 45% { transform: scaleX(1.28) scale(1.05); } 100% { transform: scale(1); } }

.fx-piece-r.fx-phase-attack .fx-art-img { animation: fx-art-pose-ram 0.3s ease-out; }
.fx-piece-n.fx-phase-attack .fx-art-img { animation: fx-art-pose-rear 0.32s ease-out; }
.fx-piece-c.fx-phase-attack .fx-art-img { animation: fx-art-pose-recoil 0.34s ease-out; }
.fx-piece-b.fx-phase-attack .fx-art-img { animation: fx-art-pose-stomp 0.3s ease-out; }
.fx-piece-a.fx-phase-attack .fx-art-img { animation: fx-art-pose-slash 0.3s ease-out; }
.fx-piece-k.fx-phase-attack .fx-art-img { animation: fx-art-pose-slash-heavy 0.32s ease-out; }
.fx-piece-p.fx-phase-attack .fx-art-img { animation: fx-art-pose-thrust 0.3s ease-out; }

/* reduced 档：静态浮现淡出 */
@keyframes fx-art-reduced-fade { 0% { opacity: 0; } 25% { opacity: 0.9; } 70% { opacity: 0.9; } 100% { opacity: 0; } }
.fx-art.fx-phase-reduced { animation: fx-art-reduced-fade 0.9s ease-in-out forwards; }

@media (prefers-reduced-motion: reduce) {
  .fx-art .fx-art-img, .fx-art-flash-wrap .fx-art-img, .fx-art-ghost-wrap .fx-art-img { animation: none !important; }
  .fx-art.fx-phase-reduced { animation: fx-art-reduced-fade 0.9s ease-in-out forwards; }
}

/* ================= v4 棋盘皮肤与氛围背景 ================= */
/* 皮肤背景图层：置于格线 SVG 之下，不挡交互 */
.board-skin {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
}

/* 深底皮肤(a1/a2)：格线与楚河汉界字换浅色（表现属性可被 CSS 覆写） */
.board-surface.skin-lines-dark .board-svg line,
.board-surface.skin-lines-dark .board-svg rect {
  stroke: rgba(235, 222, 195, 0.75) !important;
}
.board-surface.skin-lines-dark .board-svg text {
  fill: rgba(235, 222, 195, 0.85) !important;
}

/* 全屏氛围 KV：fixed 层置于 body 首子元素，内容层 z-index 抬升 */
#fx-theme-kv {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 0.45s ease;
}
#fx-theme-kv.on { opacity: 0.5; }
#fx-theme-kv.on.kv-b { opacity: 0.55; }
#fx-theme-kv::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 42%, rgba(0, 0, 0, 0.5) 100%);
}
.game-container { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  #fx-theme-kv { transition: none; }
}

/* ================= v4 棋子图像化 ================= */
.chess-piece .piece-face {
  position: absolute;
  inset: -2px;
  width: calc(100% + 4px);
  height: calc(100% + 4px);
  object-fit: contain;
  border-radius: 50%;
  pointer-events: none;
  z-index: 2;
}
/* 图片渲染成功：隐藏文字与木质底，整颗显示切片图 */
.chess-piece.has-face { background: none; border-color: transparent; box-shadow: none; }
.chess-piece.has-face .piece-char { opacity: 0; }
.chess-piece.has-face .piece-face { filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.45)); }

/* 皮肤单选组换行 */
.skin-radio-group { flex-wrap: wrap; }

/* ================= v5 中央大特写演出层 ================= */
.fx-stage {
  position: fixed;
  inset: 0;
  z-index: 90;              /* 模态(100+)之下、棋盘特效之上 */
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* 暗角聚焦：立绘登场瞬间四周压暗，突出主体 */
.fx-stage .fx-stage-dim {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, rgba(0,0,0,0) 34%, rgba(0,0,0,0.52) 100%);
  opacity: 0;
  transition: opacity 0.28s ease;
}
.fx-stage .fx-stage-dim.on { opacity: 1; }

.fx-stage .fx-stage-art {
  position: relative;
  width: min(66vmin, 420px);
  aspect-ratio: 1 / 1;
  transform: scale(0.16);
  opacity: 0;
  filter: drop-shadow(0 10px 26px rgba(0, 0, 0, 0.55));
}
.fx-stage .fx-stage-img {
  width: 100%; height: 100%; object-fit: contain; display: block;
  transform: var(--fx-flip, none);
}
.fx-stage.fx-stage-cute .fx-stage-img { filter: saturate(1.12); }
/* 立绘加载中：先隐藏，onload 弹入（v6.1 中央演出不再被加载窗口卡掉） */
.fx-stage .fx-stage-img.fx-stage-wait { opacity: 0; }
/* 立绘缺失/失败兜底：大号兵种字符走同一套缩放节奏 */
.fx-stage .fx-stage-char {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-family: "KaiTi", "STKaiti", "SimSun", serif;
  font-weight: 700; line-height: 1;
  font-size: min(46vmin, 300px);
}
.fx-stage .fx-stage-char.red { color: #e8452e; text-shadow: 0 0 26px rgba(255, 120, 60, 0.5), 0 6px 18px rgba(0, 0, 0, 0.65); }
.fx-stage .fx-stage-char.black { color: #d7dde8; text-shadow: 0 0 26px rgba(150, 180, 255, 0.4), 0 6px 18px rgba(0, 0, 0, 0.65); }
.fx-stage.fx-stage-cute .fx-stage-char.red { color: #ff7fae; text-shadow: 0 0 24px rgba(255, 150, 200, 0.7), 0 6px 16px rgba(0, 0, 0, 0.3); }
.fx-stage.fx-stage-cute .fx-stage-char.black { color: #8fd0ff; text-shadow: 0 0 24px rgba(140, 200, 255, 0.7), 0 6px 16px rgba(0, 0, 0, 0.3); }

/* 登场：由小变大（带过冲回弹） */
@keyframes fx-stage-in {
  0%   { transform: scale(0.16); opacity: 0; }
  62%  { transform: scale(1.16); opacity: 1; }
  82%  { transform: scale(0.97); }
  100% { transform: scale(1.04); opacity: 1; }
}
.fx-stage .fx-stage-art.fx-stage-in { animation: fx-stage-in 0.5s cubic-bezier(0.22, 1.1, 0.36, 1) forwards; }

/* 命中定格：受击顿挫（缩一下再弹住） */
@keyframes fx-stage-hit {
  0%   { transform: scale(1.04); }
  28%  { transform: scale(0.94) rotate(-2deg); }
  60%  { transform: scale(1.07) rotate(1.5deg); }
  100% { transform: scale(1.03) rotate(0deg); }
}
/* FX-01 修复：命中关键帧只定义 transform，登场动画移除后基础 opacity:0 会回落，
   命中态必须显式保持可见，否则立绘在中央特写中段消失、退场才闪回 */
.fx-stage .fx-stage-art.fx-stage-hit {
  opacity: 1;
  animation: fx-stage-hit 0.42s cubic-bezier(0.3, 0.8, 0.3, 1) forwards;
}

/* 退场：由大变小淡出 */
@keyframes fx-stage-out {
  0%   { transform: scale(1.03); opacity: 1; }
  100% { transform: scale(0.22); opacity: 0; }
}
.fx-stage .fx-stage-art.fx-stage-out { animation: fx-stage-out 0.5s cubic-bezier(0.5, 0, 0.75, 0.3) forwards; }

@media (prefers-reduced-motion: reduce) {
  .fx-stage .fx-stage-art.fx-stage-in { animation-duration: 0.25s; }
  .fx-stage .fx-stage-art.fx-stage-hit { animation: none; }
  .fx-stage .fx-stage-art.fx-stage-out { animation-duration: 0.25s; }
}
