/* ══════════════════════════════════════════════════════════════
   NEW 2048 — 动效 / 特效
   ══════════════════════════════════════════════════════════════ */

@keyframes screen-in { from { opacity: 0; transform: translateY(10px) scale(0.99); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes panel-in { from { opacity: 0; transform: translateY(16px) scale(0.97); } to { opacity: 1; transform: none; } }
@keyframes drift { from { transform: translate3d(-2%, -1%, 0) scale(1); } to { transform: translate3d(2%, 2%, 0) scale(1.08); } }
@keyframes mini-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.42; } }
@keyframes rift-breathe { 0%, 100% { transform: scale(1); filter: brightness(1); } 50% { transform: scale(0.985); filter: brightness(1.35); } }
@keyframes danger-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@keyframes super-shift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }

/* ── Toast ───────────────────────────────────────────────── */
@keyframes toast-in { from { opacity: 0; transform: translateY(14px) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(-8px) scale(0.97); } }

/* ── 方块入场 ─────────────────────────────────────────────── */
@keyframes tile-spawn {
  0% { opacity: 0; transform: translate3d(var(--px), var(--py), 0) scale(0.35); }
  62% { opacity: 1; transform: translate3d(var(--px), var(--py), 0) scale(1.12); }
  100% { opacity: 1; transform: translate3d(var(--px), var(--py), 0) scale(1); }
}
.tile--spawn {
  animation: tile-spawn var(--speed-pop) cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
  z-index: 3;
}
/* 位置由 --px/--py 驱动（动画期间 transform 被 keyframes 接管） */
.tile--spawn { --px: calc(var(--tx, 0) * (100% + var(--gap))); --py: calc(var(--ty, 0) * (100% + var(--gap))); }

/* ── 合并爆点 ─────────────────────────────────────────────── */
@keyframes tile-pop {
  0% { transform: translate3d(var(--px), var(--py), 0) scale(1); }
  38% { transform: translate3d(var(--px), var(--py), 0) scale(1.26); }
  100% { transform: translate3d(var(--px), var(--py), 0) scale(1); }
}
.tile--pop {
  --px: calc(var(--tx, 0) * (100% + var(--gap)));
  --py: calc(var(--ty, 0) * (100% + var(--gap)));
  animation: tile-pop 240ms cubic-bezier(0.2, 0.9, 0.3, 1.3) both;
  z-index: 4;
}
@keyframes tile-nudge { 0%, 100% { transform: translate3d(var(--px), var(--py), 0) rotate(0); } 30% { transform: translate3d(var(--px), var(--py), 0) rotate(-3deg) scale(0.94); } }
.tile--nudge { --px: calc(var(--tx, 0) * (100% + var(--gap))); --py: calc(var(--ty, 0) * (100% + var(--gap))); animation: tile-nudge 180ms ease; }

/* ── 方块消失 ─────────────────────────────────────────────── */
@keyframes tile-vanish {
  0% { opacity: 1; transform: translate3d(var(--px), var(--py), 0) scale(1); }
  100% { opacity: 0; transform: translate3d(var(--px), var(--py), 0) scale(0.55); }
}
.tile--vanish {
  --px: calc(var(--tx, 0) * (100% + var(--gap)));
  --py: calc(var(--ty, 0) * (100% + var(--gap)));
  animation: tile-vanish var(--speed-fade) ease-out forwards;
  pointer-events: none;
  z-index: 1;
}
@keyframes tile-burn {
  0% { opacity: 1; transform: translate3d(var(--px), var(--py), 0) scale(1.1); filter: brightness(1.6) saturate(2); }
  100% { opacity: 0; transform: translate3d(var(--px), var(--py), 0) scale(1.7) rotate(9deg); filter: brightness(2.4); }
}
.tile--burn { --px: calc(var(--tx, 0) * (100% + var(--gap))); --py: calc(var(--ty, 0) * (100% + var(--gap))); animation: tile-burn 380ms ease-out forwards; z-index: 5; }
@keyframes tile-shatter {
  0% { opacity: 1; transform: translate3d(var(--px), var(--py), 0) scale(1); filter: brightness(1.4); }
  100% { opacity: 0; transform: translate3d(var(--px), var(--py), 0) scale(0.3) rotate(-14deg); filter: brightness(2); }
}
.tile--shatter { --px: calc(var(--tx, 0) * (100% + var(--gap))); --py: calc(var(--ty, 0) * (100% + var(--gap))); animation: tile-shatter 340ms ease-in forwards; z-index: 5; }
@keyframes tile-thaw { 0% { filter: brightness(1.8); } 100% { filter: none; } }
.tile--thaw { animation: tile-thaw 380ms ease-out; }

/* ── 棋盘反馈 ─────────────────────────────────────────────── */
@keyframes shake-sm { 0%, 100% { transform: translate3d(0, 0, 0); } 25% { transform: translate3d(2px, -2px, 0); } 50% { transform: translate3d(-2px, 1px, 0); } 75% { transform: translate3d(1px, 2px, 0); } }
@keyframes shake-md { 0%, 100% { transform: translate3d(0, 0, 0) rotate(0); } 15% { transform: translate3d(4px, -4px, 0) rotate(-0.4deg); } 35% { transform: translate3d(-5px, 2px, 0) rotate(0.4deg); } 55% { transform: translate3d(3px, 4px, 0); } 80% { transform: translate3d(-2px, -2px, 0); } }
@keyframes shake-lg { 0%, 100% { transform: translate3d(0, 0, 0) rotate(0) scale(1); } 12% { transform: translate3d(9px, -7px, 0) rotate(-0.9deg) scale(1.012); } 30% { transform: translate3d(-10px, 5px, 0) rotate(0.9deg) scale(1.012); } 52% { transform: translate3d(7px, 8px, 0) rotate(-0.5deg); } 74% { transform: translate3d(-5px, -4px, 0); } }
.board--shake-sm { animation: shake-sm 180ms ease; }
.board--shake-md { animation: shake-md 340ms ease; }
.board--shake-lg { animation: shake-lg 520ms cubic-bezier(0.36, 0.07, 0.19, 0.97); }
.board--sink { animation: board-sink 900ms cubic-bezier(0.4, 0, 0.2, 1) forwards; }
@keyframes board-sink { 0% { transform: none; filter: none; } 100% { transform: translateY(14px) scale(0.94); filter: grayscale(0.9) brightness(0.55) blur(1px); } }
.board--surge { animation: board-surge 700ms cubic-bezier(0.2, 0.9, 0.3, 1); }
@keyframes board-surge { 0% { transform: scale(1); } 40% { transform: scale(1.035); } 100% { transform: scale(1); } }
.board--freeze-flash { box-shadow: var(--shadow-panel), 0 0 0 3px rgba(143, 227, 255, 0.7), 0 0 60px rgba(143, 227, 255, 0.45); }

/* 单个格子脉冲（元素效果定位） */
.cell--hit { animation: cell-hit 420ms ease-out; }
@keyframes cell-hit { 0% { background: var(--accent-soft); filter: brightness(2.2); } 100% { background: var(--cell-bg); filter: none; } }

/* ── 全屏特效层 ───────────────────────────────────────────── */
.fx {
  position: fixed; inset: 0; z-index: 60;
  pointer-events: none;
  overflow: hidden;
}
.fx__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.fx__flash {
  position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(70% 60% at 50% 45%, #fff, rgba(255, 255, 255, 0) 72%);
}
.fx__flash.is-on { animation: flash-burst 420ms ease-out; }
@keyframes flash-burst { 0% { opacity: 0; } 12% { opacity: 0.85; } 100% { opacity: 0; } }
.fx__flash[data-color="gold"].is-on { animation-name: flash-gold; }
@keyframes flash-gold { 0% { opacity: 0; } 14% { opacity: 0.9; } 100% { opacity: 0; } }
.fx__vignette {
  position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(120% 100% at 50% 50%, transparent 45%, rgba(255, 46, 99, 0.55) 100%);
  transition: opacity 0.6s ease;
}
.fx__vignette.is-on { opacity: 1; }
.fx__slowmo {
  position: absolute; inset: 0; opacity: 0;
  background: rgba(120, 200, 255, 0.1);
  backdrop-filter: blur(0.5px);
}
.fx__slowmo.is-on { animation: slowmo 320ms ease-out; }
@keyframes slowmo { 0% { opacity: 0.55; } 100% { opacity: 0; } }

/* 评级弹字 */
.fx__rating {
  position: absolute; left: 50%; top: 42%;
  transform: translate(-50%, -50%) scale(0.5);
  font-family: var(--font-num);
  font-size: clamp(30px, 9vmin, 58px);
  font-weight: 800;
  letter-spacing: 0.02em;
  opacity: 0;
  color: #fff;
  text-shadow: 0 0 24px currentColor, 0 6px 30px rgba(0, 0, 0, 0.6);
  white-space: nowrap;
}
.fx__rating.is-on { animation: rating-pop 760ms cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes rating-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4) rotate(-6deg); }
  18% { opacity: 1; transform: translate(-50%, -58%) scale(1.18) rotate(2deg); }
  34% { transform: translate(-50%, -62%) scale(1) rotate(0); }
  76% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -100%) scale(1.04); }
}
.fx__rating[data-tier="5"] { animation-duration: 1100ms; }

/* 事件横幅（能量爆发 / 元素触发 / 里程碑） */
.fx__banner {
  position: absolute; left: 50%; top: 19%;
  transform: translate(-50%, -10px);
  padding: 8px 18px;
  border-radius: 999px;
  font-size: 13px; font-weight: 700; letter-spacing: 0.1em;
  background: var(--c-panel);
  border: 1px solid var(--accent-line);
  color: var(--c-accent);
  opacity: 0;
  white-space: nowrap;
  box-shadow: 0 12px 34px -14px rgba(0, 229, 255, 0.8);
}
.fx__banner.is-on { animation: banner-in 1500ms cubic-bezier(0.2, 0.9, 0.3, 1); }
@keyframes banner-in {
  0% { opacity: 0; transform: translate(-50%, 8px) scale(0.94); }
  14% { opacity: 1; transform: translate(-50%, 0) scale(1); }
  78% { opacity: 1; transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -14px) scale(0.98); }
}
.fx__banner[data-kind="gold"] { border-color: rgba(255, 200, 87, 0.6); color: var(--c-gold); box-shadow: 0 12px 34px -14px rgba(255, 200, 87, 0.9); }
.fx__banner[data-kind="danger"] { border-color: rgba(255, 77, 109, 0.6); color: var(--c-danger); }
.fx__banner[data-kind="fire"] { border-color: rgba(255, 122, 41, 0.65); color: var(--el-fire); }
.fx__banner[data-kind="ice"] { border-color: rgba(143, 227, 255, 0.65); color: var(--el-ice); }
.fx__banner[data-kind="poison"] { border-color: rgba(134, 255, 92, 0.6); color: var(--el-poison); }
.fx__banner[data-kind="star"] { border-color: rgba(255, 215, 94, 0.65); color: var(--el-star); }
.fx__banner[data-kind="thunder"] { border-color: rgba(192, 139, 255, 0.65); color: var(--el-thunder); }

/* 连击数字 */
@keyframes combo-rise {
  0% { opacity: 0; transform: translate(-50%, 30%) scale(0.5); }
  22% { opacity: 1; transform: translate(-50%, 0) scale(1.25); }
  40% { transform: translate(-50%, -10%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -160%) scale(1.1); }
}
.float--combo.is-on { animation: combo-rise 900ms cubic-bezier(0.16, 1, 0.3, 1); }
.float--combo .float__num { font-size: clamp(38px, 12vmin, 72px); text-shadow: 0 0 30px currentColor; }

/* 分数跳动 */
.stat__delta.is-on { animation: delta-rise 700ms ease-out; }
@keyframes delta-rise { 0% { opacity: 0; transform: translate(-50%, 6px); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -22px); } }
.stat--score.is-bump { animation: score-bump 260ms cubic-bezier(0.2, 0.9, 0.3, 1.4); }
@keyframes score-bump { 0% { transform: scale(1); } 45% { transform: scale(1.11); } 100% { transform: scale(1); } }

/* 能量满提示 */
.energy__bar.is-full { box-shadow: 0 0 22px rgba(255, 122, 41, 0.7); }
.energy--burst { animation: energy-burst 560ms ease-out; }
@keyframes energy-burst { 0% { transform: scale(1); } 30% { transform: scale(1.045); filter: brightness(1.6); } 100% { transform: scale(1); } }

/* 道具使用反馈 */
.item-btn.is-used { animation: item-used 420ms ease-out; }
@keyframes item-used { 0% { box-shadow: 0 0 0 0 rgba(0, 229, 255, 0.8); } 100% { box-shadow: 0 0 0 16px rgba(0, 229, 255, 0); } }

/* 胜利 */
.board--win { animation: board-win 1200ms cubic-bezier(0.2, 0.9, 0.3, 1); }
@keyframes board-win {
  0% { transform: scale(1); filter: brightness(1); }
  20% { transform: scale(1.06); filter: brightness(1.8) saturate(1.4); }
  50% { transform: scale(1.02); filter: brightness(1.2); }
  100% { transform: scale(1); filter: none; }
}
.logo__2048 { animation: logo-hue 12s linear infinite; }
@keyframes logo-hue { 0%, 100% { filter: drop-shadow(0 10px 34px rgba(0, 229, 255, 0.35)); } 50% { filter: drop-shadow(0 10px 34px rgba(169, 123, 255, 0.45)); } }

/* 屏幕边缘能量条（5 连击以上出现） */
#app[data-hype="1"]::after {
  content: ""; position: fixed; inset: 0; z-index: 55; pointer-events: none;
  box-shadow: inset 0 0 90px -20px var(--hype-color, rgba(0, 229, 255, 0.55));
  animation: hype-breathe 1.6s ease-in-out infinite;
}
@keyframes hype-breathe { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
