/* ============ 地图滚动 ============ */
#board.scrolling {
  transition: transform 0.55s cubic-bezier(0.35, 0.1, 0.25, 1);
}

/* 新行从顶部滑入 */
.board-row.row-enter {
  animation: row-slide-in 0.55s cubic-bezier(0.25, 0.6, 0.3, 1) both;
}
@keyframes row-slide-in {
  from { opacity: 0; transform: translateY(calc(-1 * (var(--card-h) + var(--card-gap)))); }
  to   { opacity: 1; transform: translateY(0); }
}

/* 旧行滑出 */
.board-row.row-exit {
  animation: row-slide-out 0.45s ease both;
}
@keyframes row-slide-out {
  to { opacity: 0; transform: translateY(60px) scale(0.94); }
}

/* 卡牌翻开 */
.card.flip-in { animation: card-flip 0.4s ease both; }
@keyframes card-flip {
  from { transform: rotateY(90deg) scale(0.9); opacity: 0.4; }
  to   { transform: rotateY(0) scale(1); opacity: 1; }
}

/* Rest 时第一行重刷 */
.card.reshuffle { animation: card-reshuffle 0.5s ease both; }
@keyframes card-reshuffle {
  0%   { transform: translateY(0) rotateZ(0); opacity: 1; }
  45%  { transform: translateY(-20px) rotateZ(6deg); opacity: 0.2; }
  55%  { transform: translateY(-20px) rotateZ(-6deg); opacity: 0.2; }
  100% { transform: translateY(0) rotateZ(0); opacity: 1; }
}

/* Drift：世界演化时卡牌游荡换位 */
.card.drift-move { animation: card-drift 0.45s ease both; }
@keyframes card-drift {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.1) translateY(-8px); }
  100% { transform: scale(1); }
}

/* ============ 玩家 ============ */
.card.card-player.player-hop { animation: player-hop 0.4s cubic-bezier(0.3, 0, 0.4, 1); }
@keyframes player-hop {
  0%   { transform: translateY(0) scale(1); }
  40%  { transform: translateY(-26px) scale(1.08); }
  100% { transform: translateY(0) scale(1); }
}

/* ============ 战斗 ============ */
.combat-stage.clash .combatant { animation: combat-shake 0.3s ease infinite; }
@keyframes combat-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px) rotate(-1.5deg); }
  75% { transform: translateX(5px) rotate(1.5deg); }
}

.combatant.winner { animation: winner-pop 0.5s ease both; }
@keyframes winner-pop {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.28); }
  100% { transform: scale(1.12); }
}
.combatant.loser { animation: loser-fall 0.6s ease both; }
@keyframes loser-fall {
  to { transform: translateY(24px) rotate(8deg); opacity: 0.25; filter: grayscale(1); }
}

/* 伤害 / 增益数字 */
.float-num {
  position: fixed;
  font-size: 24px;
  font-weight: bold;
  pointer-events: none;
  animation: float-up 1.1s ease-out forwards;
  text-shadow: 0 2px 6px #000c;
  z-index: 300;
}
.float-num.dmg { color: var(--hp); }
.float-num.heal { color: #6fe07f; }
.float-num.pow { color: var(--power); }
.float-num.gold { color: var(--gold); }
@keyframes float-up {
  0%   { opacity: 0; transform: translateY(8px) scale(0.7); }
  15%  { opacity: 1; transform: translateY(0) scale(1.15); }
  100% { opacity: 0; transform: translateY(-52px) scale(1); }
}

/* 金币飞向 UI */
.fly-coin {
  position: fixed;
  font-size: 22px;
  z-index: 300;
  pointer-events: none;
  transition: transform 0.7s cubic-bezier(0.35, -0.2, 0.6, 1), opacity 0.7s ease;
}

/* Toast */
@keyframes toast-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(-10px); }
}

/* 模态出现 */
.modal-box { animation: modal-pop 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.2) both; }
@keyframes modal-pop {
  from { opacity: 0; transform: scale(0.86) translateY(18px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* 屏幕震动（Boss / 死亡） */
#app.screen-shake { animation: screen-shake 0.4s ease; }
@keyframes screen-shake {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(-6px, 3px); }
  40% { transform: translate(5px, -4px); }
  60% { transform: translate(-4px, 2px); }
  80% { transform: translate(3px, -2px); }
}
