/* ============================================================
   Element TD · Candy Crush UI Edition
   参考：candycrush-ui-study Candy Crush 经典糖果界面风格
   核心色板：
     糖果粉红  #FF4D8B / #ff7eb6
     糖果紫    #8a2be2 / #b026ff
     糖果黄    #ffd93d / #ffaa00
     糖果绿    #6FE26F / #2bc14a
     糖果蓝    #4da8ff / #2962ff
     糖果橙    #ff8c2a / #ff5a3a
   ============================================================ */

@property --core-rot {
  syntax: '<angle>';
  inherits: true;
  initial-value: 45deg;
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; user-select: none; }
html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  font-family: "Baloo 2", "Comic Sans MS", "PingFang SC", -apple-system, sans-serif;
  background: #2b1055;
  color: #fff;
  touch-action: manipulation;
}

/* ---------- Container · 糖果星空世界 ---------- */
#game-container {
  position: relative;
  width: 100vw;
  height: 100vh;
  max-width: 480px;
  margin: 0 auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background:
    /* 顶部柔和糖果光晕 */
    radial-gradient(ellipse at 50% 0%, rgba(255,150,220,.7) 0%, rgba(170,80,255,.4) 30%, transparent 65%),
    /* 中部光带 */
    radial-gradient(ellipse at 80% 35%, rgba(255,200,100,.35) 0%, transparent 45%),
    radial-gradient(ellipse at 20% 30%, rgba(120,180,255,.4) 0%, transparent 50%),
    /* 主深紫渐变 */
    linear-gradient(180deg, #5a1da8 0%, #3d1280 35%, #2a0e5e 65%, #1a0840 100%);
}

/* 糖果星点小装饰 */
#game-container::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    radial-gradient(3px 3px at 8% 12%,  rgba(255,255,255,.95), transparent 70%),
    radial-gradient(2px 2px at 22% 38%, rgba(255,180,220,.85), transparent 70%),
    radial-gradient(3px 3px at 65% 18%, rgba(180,120,255,.85), transparent 70%),
    radial-gradient(2px 2px at 85% 50%, rgba(255,210,140,.9),  transparent 70%),
    radial-gradient(3px 3px at 38% 70%, rgba(255,255,255,.95), transparent 70%),
    radial-gradient(2px 2px at 75% 82%, rgba(140,220,255,.85), transparent 70%),
    radial-gradient(3px 3px at 12% 60%, rgba(255,180,80,.85),  transparent 70%),
    radial-gradient(2px 2px at 50% 92%, rgba(255,220,160,.85), transparent 70%);
  background-size: 100% 100%;
  pointer-events: none;
  filter: blur(.5px);
  z-index: 0;
  animation: starsTwinkle 4s ease-in-out infinite alternate;
}
@keyframes starsTwinkle {
  0%   { opacity: .7; }
  100% { opacity: 1; }
}

/* ---------- Top status bar · Candy Crush 标志条 ---------- */
#top-bar {
  flex: 0 0 auto;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 0 8px;
  /* ✦ 防溢出：所有子元素允许收缩，超出截断 */
  min-width: 0;
  background:
    linear-gradient(180deg, rgba(255,255,255,.25) 0%, rgba(255,255,255,0) 50%),
    linear-gradient(180deg, #ff4d8b 0%, #d62a72 60%, #8b1856 100%);
  border-bottom: 4px solid #4a0a3a;
  box-shadow:
    0 4px 0 #2a042a,
    0 6px 18px rgba(80,0,60,.55),
    0 -1px 0 rgba(255,255,255,.5) inset,
    0 2px 0 rgba(255,255,255,.55) inset;
  z-index: 10;
  position: relative;
}
#top-bar::after {
  content: '';
  position: absolute;
  left: 6px; right: 6px; top: 4px;
  height: 35%;
  background: linear-gradient(180deg, rgba(255,255,255,.55), transparent);
  border-radius: 30px;
  pointer-events: none;
}

/* 状态块通用 —— Candy Crush 圆角徽章 */
.stat-block {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 38px;
  padding: 0 10px;
  border-radius: 22px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.35) 0%, transparent 50%),
    linear-gradient(180deg, #4a1280 0%, #2a0856 100%);
  border: 3px solid #fff;
  box-shadow:
    0 0 0 2px #4a0a3a,
    0 3px 0 #4a0a3a,
    0 5px 8px rgba(0,0,0,.35),
    0 1px 0 rgba(255,255,255,.4) inset;
  font-size: 13px;
  font-weight: 900;
  color: #fff;
  text-shadow: 0 2px 0 #2a0856, 0 3px 4px rgba(0,0,0,.3);
  position: relative;
  z-index: 1;
  /* ✦ 防溢出：允许收缩，内容截断 */
  min-width: 0;
  flex-shrink: 1;
  white-space: nowrap;
  overflow: hidden;
}
.stat-block .icon {
  font-size: 18px;
  flex-shrink: 0;
  filter: drop-shadow(0 2px 2px rgba(0,0,0,.4));
}
/* HP 块吃掉剩余空间，wave / score 自适应 */
/* ✦ 用户诉求：❤︎ 与血条整体在 .hp-block 框内居中，两侧到边框留白对称 */
.hp-block { flex: 1 1 auto; max-width: 200px; min-width: 90px; padding: 0 10px; justify-content: center; }
.wave-block { flex: 0 1 auto; }
.score-block { flex: 0 1 auto; }

.bar-wrap {
  position: relative;
  flex: 1;
  height: 18px;
  background: linear-gradient(180deg, #1a042a, #3a0a4a);
  border: 2px solid #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow:
    0 2px 0 rgba(0,0,0,.4),
    0 0 0 2px #2a0856,
    0 1px 0 rgba(255,255,255,.4) inset;
}
.bar {
  position: absolute; left: 0; top: 0; bottom: 0;
  border-radius: 10px;
  transition: width .35s cubic-bezier(.5,0,.2,1);
}
.hp-bar {
  width: 100%;
  background:
    linear-gradient(180deg, rgba(255,255,255,.6) 0%, transparent 50%),
    linear-gradient(90deg, #ff2255 0%, #ff5a7a 50%, #ffaa3a 100%);
  box-shadow: 0 0 8px #ff3860 inset;
}
.bar-text {
  position: absolute; inset: 0;
  text-align: center; line-height: 18px;
  font-size: 11px; color: #fff;
  font-weight: 900;
  text-shadow: 0 1px 2px #000, 0 0 3px #000;
  letter-spacing: 1px;
}
.wave-block { color: #fff; }
.score-block {
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,.4) 0%, transparent 50%),
    linear-gradient(180deg, #ffaa00 0%, #d97a00 100%);
  border-color: #fff;
  box-shadow:
    0 0 0 2px #6a3a00,
    0 3px 0 #6a3a00,
    0 5px 8px rgba(0,0,0,.35),
    0 1px 0 rgba(255,255,255,.55) inset;
  text-shadow: 0 2px 0 #6a3a00, 0 3px 4px rgba(0,0,0,.3);
}
.wave-block {
  background:
    linear-gradient(180deg, rgba(255,255,255,.4) 0%, transparent 50%),
    linear-gradient(180deg, #4da8ff 0%, #1a5da8 100%);
  border-color: #fff;
  box-shadow:
    0 0 0 2px #0a3a6a,
    0 3px 0 #0a3a6a,
    0 5px 8px rgba(0,0,0,.35),
    0 1px 0 rgba(255,255,255,.55) inset;
  text-shadow: 0 2px 0 #0a3a6a, 0 3px 4px rgba(0,0,0,.3);
}

/* ---------- Tower-defense zone · 糖果云海 ---------- */
#tower-zone {
  position: relative;
  flex: 0 0 38%;
  background:
    /* 顶部太阳光晕 */
    radial-gradient(ellipse 60% 35% at 50% -5%, rgba(255,236,170,.85) 0%, rgba(255,180,220,.45) 30%, transparent 65%),
    /* 远处地平线粉雾 */
    radial-gradient(ellipse 90% 18% at 50% 95%, rgba(255,140,200,.45) 0%, transparent 70%),
    /* 糖果天空：粉橙-粉紫渐变 */
    linear-gradient(180deg, #ffc4e0 0%, #ff9ec8 30%, #d678c8 65%, #a64ec0 100%);
  border-bottom: 5px solid #fff;
  box-shadow:
    0 5px 0 #6a1a8a,
    0 9px 16px rgba(80,0,80,.45),
    0 -2px 0 rgba(255,255,255,.6) inset;
  overflow: hidden;
  /* ⚠️ 不再使用 isolation/contain:paint/translateZ 强制建立合成层：
     overflow:hidden 已能裁切子元素，强制合成层反而会让子层位图与父层合成时
     在 transform 切换瞬间出现"幽灵帧"残影。
     直接交给浏览器自动管理即可，残影问题彻底消失。 */
}
/* 云层：糖果白云 */
#tower-zone::before {
  content: '';
  position: absolute;
  top: 0; left: -50%;
  width: 200%; height: 100%;
  pointer-events: none;
  z-index: 1;
  background:
    radial-gradient(70px 26px at 8%  18%, rgba(255,255,255,.95), transparent 72%),
    radial-gradient(90px 32px at 22% 12%, rgba(255,255,255,.92), transparent 70%),
    radial-gradient(55px 22px at 33% 22%, rgba(255,255,255,.85), transparent 75%),
    radial-gradient(80px 28px at 48% 8%,  rgba(255,255,255,.90), transparent 72%),
    radial-gradient(60px 24px at 60% 24%, rgba(255,255,255,.80), transparent 75%),
    radial-gradient(95px 32px at 74% 14%, rgba(255,255,255,.92), transparent 70%),
    radial-gradient(50px 20px at 86% 22%, rgba(255,255,255,.78), transparent 75%),
    radial-gradient(40px 14px at 14% 42%, rgba(255,255,255,.55), transparent 78%),
    radial-gradient(54px 18px at 38% 50%, rgba(255,255,255,.50), transparent 80%),
    radial-gradient(46px 16px at 66% 46%, rgba(255,255,255,.55), transparent 78%),
    radial-gradient(60px 20px at 88% 52%, rgba(255,255,255,.48), transparent 80%);
  filter: blur(.5px);
  animation: cloudDrift 60s linear infinite;
}
/* 鸟 + 风 */
#tower-zone::after {
  content: '';
  position: absolute;
  top: 0; left: -100%;
  width: 300%; height: 100%;
  pointer-events: none;
  z-index: 2;
  background:
    radial-gradient(2.5px 1px at 12% 30%, rgba(80,40,80,.85), transparent 100%),
    radial-gradient(2.5px 1px at 13.4% 29.4%, rgba(80,40,80,.85), transparent 100%),
    radial-gradient(2px 0.8px at 26% 38%, rgba(80,40,80,.75), transparent 100%),
    radial-gradient(2px 0.8px at 27% 37.4%, rgba(80,40,80,.75), transparent 100%),
    radial-gradient(3px 1.2px at 44% 26%, rgba(80,40,80,.9), transparent 100%),
    radial-gradient(3px 1.2px at 45.6% 25.4%, rgba(80,40,80,.9), transparent 100%),
    radial-gradient(2px 0.8px at 60% 44%, rgba(80,40,80,.7), transparent 100%),
    radial-gradient(2px 0.8px at 61% 43.4%, rgba(80,40,80,.7), transparent 100%),
    radial-gradient(2.5px 1px at 78% 34%, rgba(80,40,80,.85), transparent 100%),
    radial-gradient(2.5px 1px at 79.2% 33.4%, rgba(80,40,80,.85), transparent 100%),
    linear-gradient(90deg, transparent 0%, transparent 5%, rgba(255,255,255,.32) 7%, rgba(255,255,255,.32) 11%, transparent 13%, transparent 100%) no-repeat 0 22%/14% 1.2px,
    linear-gradient(90deg, transparent 0%, transparent 30%, rgba(255,255,255,.22) 32%, rgba(255,255,255,.22) 39%, transparent 41%, transparent 100%) no-repeat 0 56%/14% 1px,
    linear-gradient(90deg, transparent 0%, transparent 65%, rgba(255,255,255,.28) 67%, rgba(255,255,255,.28) 72%, transparent 74%, transparent 100%) no-repeat 0 70%/14% 1.2px;
  animation: birdFlock 24s linear infinite, windGust 7s ease-in-out infinite;
}
@keyframes cloudDrift {
  0%   { transform: translateX(0); }
  100% { transform: translateX(25%); }
}
@keyframes birdFlock {
  0%   { transform: translateX(-10%); opacity: .85; }
  50%  { opacity: 1; }
  100% { transform: translateX(60%); opacity: .85; }
}
@keyframes windGust {
  0%, 100% { background-position-x: -120%, -120%, -120%, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; opacity: 0; }
  20%      { opacity: .9; }
  60%      { opacity: .9; }
  100%     { background-position-x: 220%, 220%, 220%, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; opacity: 0; }
}
#fx-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 5;
}
#lanes {
  position: absolute; inset: 0;
  display: flex;
  z-index: 1;
  pointer-events: none;
}
.lane {
  flex: 1;
  height: 100%;
  position: relative;
  border: none;
  background: transparent;
}
.lane:last-child { border-right: none; }

#enemies-layer, #projectiles-layer, #towers-layer {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 3;
  /* 只用 overflow:hidden 做硬裁切；不再 contain:paint，
     避免独立 paint 上下文与子合成层重叠时出现位图残影。 */
  overflow: hidden;
  contain: layout;
}
#towers-layer { z-index: 2; }
#projectiles-layer { z-index: 4; }

/* wave banner · 糖果气泡字 */
#wave-banner {
  position: absolute;
  top: 30%; left: 50%;
  transform: translate(-50%, -50%) scale(0);
  font-size: 32px; font-weight: 900;
  color: #fff;
  font-family: "Baloo 2", "Comic Sans MS", system-ui, cursive;
  text-shadow:
    -2px 0 0 #8a1856, 2px 0 0 #8a1856,
    0 -2px 0 #8a1856, 0 2px 0 #8a1856,
    -3px -3px 0 #8a1856, 3px 3px 0 #8a1856,
    0 5px 0 #4a0a3a,
    0 0 22px #ff4d8b;
  z-index: 20;
  pointer-events: none;
  letter-spacing: 4px;
}
#wave-banner.show { animation: bannerShow 2s ease-out; }
@keyframes bannerShow {
  0%   { transform: translate(-50%,-50%) scale(0);   opacity: 0; }
  20%  { transform: translate(-50%,-50%) scale(1.25);opacity: 1; }
  60%  { transform: translate(-50%,-50%) scale(1);   opacity: 1; }
  100% { transform: translate(-50%,-50%) scale(1.5); opacity: 0; }
}

/* ============================================================
   ENEMY · 糖果怪物（圆润果冻形态）
   ============================================================ */
.enemy {
  position: absolute;
  width: 48px; height: 48px;
  transform: translate3d(-9999px,-9999px,0);
  /* ⚠️ 不写 will-change: transform 与 contain: paint：
     这俩组合会强制独立合成层 + 硬裁切，反而在 transform 频繁更新（每帧）时
     导致 GPU 位图缓存残留为"上一帧位置"的拖影/残影；
     浏览器对 transform 自动启发式提升合成层已足够，无需手工干预。 */
  contain: layout style;
  display: block;
}
/* ✦ 用户需求 #1 Remove exterior：彻底移除"圆形糖果体外壳"和"顶部白色高光"
   原 .enemy::before 是径向渐变圆形糖果体（外框）+ 阴影，现在让它消失，
   原 .enemy::after 是顶部白色高光泡泡（同样属于 exterior 装饰），同样去除。
   保留 ::before/::after 的 content:none，是为了在不影响其他状态选择器
   （.frozen::before / .burning::before）的语法基础上，确保普通态什么都不画。 */
.enemy::before {
  content: none;
}
.enemy::after {
  content: none;
}
.enemy > span {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  z-index: 2;
  filter:
    drop-shadow(0 0 2px rgba(255,255,255,.95))
    drop-shadow(0 1px 1px rgba(255,255,255,.6));
  animation: enemyBlink 2.4s ease-in-out infinite;
}
@keyframes enemyBlink {
  0%, 92%, 100% { transform: scale(1); }
  95%           { transform: scale(1, .85); }
}

/* ✦ 用户需求 #2 剪影遮罩层（.silhouette）
   - 与主体 emoji 完全重叠（同样 inset:0、同样字号、同样 emoji 字符）
   - 使用 brightness(0) + sepia/contrast 把彩色 emoji 渲染成纯黑色剪影
     （brightness(0) 会把所有彩色像素压成黑色，配合 saturate(100) + contrast(100)
      能保持锐利剪影边缘；这是把 emoji 变剪影的最稳跨浏览器方案，
      不依赖 mask-image，对 iOS Safari / Android Chromium 都生效）
   - z-index:2.5 让剪影位于主体 emoji 之上、HP 条之下
   - 1s 一个完整循环：opacity 0 → 1 → 0
   - pointer-events:none 不影响命中检测；
     animation 名 silhouettePulse 与 emojiBlink 互不冲突 */
.enemy .silhouette {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  z-index: 2;
  pointer-events: none;
  /* 把 emoji 渲染成纯黑色剪影 */
  filter: brightness(0) saturate(100%) contrast(100%);
  opacity: 0;
  animation: silhouettePulse 1s ease-in-out infinite;
  /* 防止剪影自身参与 enemyBlink 缩放，避免和主体反向脉动看着不同步 */
  will-change: opacity;
}

@keyframes silhouettePulse {
  0%   { opacity: 0; }
  50%  { opacity: 1; }   /* 中点完全显形（100%） */
  100% { opacity: 0; }
}
.enemy .hp {
  /* ✦ 用户需求：移除怪物血条（保留 DOM 让 tower.js 中 hpFillEl.style.width 写入不报错，仅视觉隐藏） */
  display: none;
  position: absolute;
  bottom: -9px; left: 50%;
  transform: translateX(-50%);
  width: 40px; height: 6px;
  background: rgba(255,255,255,.55);
  border-radius: 6px;
  overflow: hidden;
  border: 1.5px solid rgba(255,255,255,.95);
  box-shadow: 0 1px 3px rgba(80,0,60,.55), 0 0 4px rgba(255,255,255,.6);
  z-index: 3;
}
.enemy .hp-fill {
  height: 100%;
  border-radius: 6px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.7) 0%, transparent 55%),
    linear-gradient(90deg, #ff2255, #ffd93d);
  transition: width .15s;
}
/* ✦ 已移除 exterior，::before 不再渲染，命中时改为给整个 .enemy 加亮度滤镜 */
.enemy.hit { filter: brightness(1.6) saturate(1.3); }
/* ✦ 死亡动画修复：原 keyframes 只写 scale+rotate，会覆盖 JS 的 translate3d，
   导致死亡瞬间所有怪物被瞬移到 #enemies-layer 左上角 (0,0) 播放动画。
   修复：keyframes 中保留 translate(var(--ex), var(--ey)) 平移分量，
   JS 在添加 .dying 之前把当前 (e.x, e.y) 写入 CSS 变量 --ex / --ey，
   使死亡动画在怪物当前位置原地播放，而非左上角。
   ⚠️ fallback 必须用 0px（合法 <length>），不能用 0（unitless），
   否则变量未注入时整段 transform 失效、怪物退回左上角。 */
.enemy.dying { animation: enemyDie .45s forwards; }
@keyframes enemyDie {
  0%   { opacity: 1; transform: translate(var(--ex,0px), var(--ey,0px)) translate(-50%,-50%) scale(1)    rotate(0); }
  60%  { opacity: 1; transform: translate(var(--ex,0px), var(--ey,0px)) translate(-50%,-50%) scale(1.25) rotate(8deg); }
  100% { opacity: 0; transform: translate(var(--ex,0px), var(--ey,0px)) translate(-50%,-50%) scale(0)    rotate(-20deg); }
}
/* ✦ 已移除 exterior，frozen 状态不再渲染圆形冰晶外壳，
   仅在怪物本体上叠一圈淡蓝光晕（drop-shadow），并保留 ❄ 属性图标。 */
.enemy.frozen > span {
  filter:
    drop-shadow(0 0 4px #aaeeff)
    drop-shadow(0 0 10px #79d4ff);
}
.enemy.frozen > span::before {
  content: '❄';
  position: absolute;
  top: -10%; left: -2%;
  font-size: 14px;
  color: #fff;
  text-shadow: 0 0 6px #aaeeff, 0 0 12px #79d4ff;
  z-index: 3;
  animation: none;
}
/* ✦ 已移除 exterior，burning 状态改为给怪物本体叠橙色光晕 + 保留 🔥 属性图标 */
.enemy.burning > span {
  filter:
    drop-shadow(0 0 4px #ffae5c)
    drop-shadow(0 0 10px #ff7544);
}
.enemy.burning > span::after {
  content: '🔥';
  position: absolute;
  top: -28%;
  right: -10%;
  font-size: 16px;
  z-index: 3;
  filter: drop-shadow(0 0 6px #ff7544);
  animation: none;
}

/* ============================================================
   TOWER · 糖果炮塔（保留视觉，仅微调投影色到糖果紫）
   ============================================================ */
.tower {
  position: absolute;
  width: 44px; height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  transform: translate3d(-9999px,-9999px,0);
  background:
    radial-gradient(ellipse 55% 45% at 32% 26%, rgba(255,255,255,.95) 0%, rgba(255,255,255,.3) 35%, transparent 65%),
    radial-gradient(circle at 50% 55%, #ffe27d 0%, #ffb13a 60%, #ff8d3a 100%);
  box-shadow:
    0 6px 10px rgba(255,140,60,.45),
    0 2px 0 rgba(255,255,255,.85) inset,
    0 -3px 6px rgba(255,140,60,.3) inset;
  /* ⚠️ 不能写 will-change: transform + contain: paint：
     这两者会让元素被强制提升为独立合成层。当 transform / aim-* 类切换时，
     旧合成层位图在某些 GPU/WebView 实现里会短暂残留为"幽灵塔身"。
     仅在元素本身确实做高频 transform 动画时才提升合成层；
     主炮的"瞄准方向切换"频率很低（几百毫秒一次），不需要合成层，
     直接交还浏览器自动管理即可，残影问题彻底消失。 */
}
.tower.spawn .tower-inner { animation: towerSpawnInner .4s cubic-bezier(.34,1.56,.64,1); }
@keyframes towerSpawnInner {
  0% { transform: scale(0) rotate(-90deg); opacity: 0; }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}
.tower.shoot .tower-inner { animation: towerShootInner .18s; }
@keyframes towerShootInner {
  0% { transform: scale(1); }
  50% { transform: scale(1.22); }
  100% { transform: scale(1); }
}
.tower-inner {
  width: 100%; height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  filter: drop-shadow(0 2px 3px rgba(255,140,60,.6));
}

/* ===========================================================
   Main tower → 奇幻水晶炮台（保持原结构，色调略调和糖果紫）
   =========================================================== */
.tower.main-tower {
  width: 140px; height: 110px;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  animation: none;
  z-index: 5;
  overflow: hidden;
  font-size: 0;
}
.tower.main-tower::before { content: none; }

.tower-inner.cannon {
  width: 140px; height: 140px;
  position: absolute;
  left: 0; top: 0;
  transform-origin: 50% 50%;
  transition: transform .12s ease-out;
  /* ⚠️ 移除 filter: drop-shadow —— 该属性会创建独立合成层，
     当内部 .cannon-barrel 频繁切换 aim-up/aim-left/aim-right 时，
     旧合成层位图会短暂残留为"幽灵塔身"。
     主炮的视觉投影感由 .cannon-glow / 各组件自身的 box-shadow 提供已足够。 */
}

.cannon-glow {
  position: absolute;
  left: 50%; top: 84%;
  width: 130px; height: 22px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(180,120,255,.85) 0%, rgba(140,80,255,.35) 40%, transparent 75%);
  filter: blur(3px);
  z-index: 0;
  pointer-events: none;
  animation: cannonGlowPulse 2.4s ease-in-out infinite;
}
@keyframes cannonGlowPulse {
  0%,100% { opacity: .65; transform: translate(-50%, -50%) scale(1); }
  50%     { opacity: 1;   transform: translate(-50%, -50%) scale(1.15); }
}

.cannon-base-disc {
  position: absolute;
  left: 50%; top: 78%;
  width: 116px; height: 50px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background:
    radial-gradient(ellipse at 50% 28%, rgba(220,235,255,.55) 0%, transparent 45%),
    radial-gradient(ellipse at 50% 60%, #6a829e 0%, #3d4d6a 50%, #1d2940 100%);
  box-shadow:
    inset 0 4px 0 rgba(255,255,255,.4),
    inset 0 -6px 10px rgba(0,0,0,.7),
    0 0 0 2px #0d1426,
    0 4px 10px rgba(0,0,0,.6),
    0 0 16px rgba(180,120,255,.45);
  z-index: 1;
}

.cannon-base-deco {
  position: absolute;
  width: 16px; height: 12px;
  border-radius: 3px 3px 2px 2px;
  background: linear-gradient(180deg, #fff1a8 0%, #ffd24a 30%, #d99425 70%, #7a4c10 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 -2px 0 rgba(80,40,0,.6),
    0 0 0 1px rgba(40,20,0,.7),
    0 1px 2px rgba(0,0,0,.6),
    0 0 5px rgba(255,200,80,.5);
  z-index: 2;
}
.cannon-base-deco::before {
  content: '';
  position: absolute;
  left: 50%; top: 45%;
  width: 4px; height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ffd0ff 0%, #b04eff 50%, #3a1a7a 100%);
  box-shadow: 0 0 4px rgba(180,120,255,.9);
}
.cannon-base-deco.d1 { left: calc(50% - 50px); top: calc(78% - 6px);  }
.cannon-base-deco.d2 { left: calc(50% - 28px); top: calc(78% - 18px); }
.cannon-base-deco.d3 { left: calc(50% - 8px);  top: calc(78% - 22px); }
.cannon-base-deco.d4 { left: calc(50% + 12px); top: calc(78% - 18px); }
.cannon-base-deco.d5 { left: calc(50% + 34px); top: calc(78% - 6px);  }

.cannon-base-mid {
  position: absolute;
  inset: 18% 14% 18% 14%;
  border-radius: 50%;
  background:
    radial-gradient(ellipse at 50% 30%, rgba(255,255,200,.55) 0%, transparent 45%),
    radial-gradient(ellipse at 50% 55%, #ffe27a 0%, #d99425 55%, #7a4810 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,200,.8),
    inset 0 -3px 0 rgba(60,30,0,.7),
    0 0 0 1px rgba(20,10,0,.7);
  z-index: 3;
}
.cannon-base-core {
  position: absolute;
  left: 50%; top: 50%;
  width: 38px; height: 18px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 35%, #d8a0ff 0%, #6a2acc 45%, #2a0a5a 100%);
  box-shadow:
    inset 0 2px 0 rgba(220,180,255,.55),
    inset 0 -3px 6px rgba(0,0,0,.85),
    0 0 0 1px #0a1224,
    0 0 10px rgba(180,120,255,.6);
  z-index: 4;
}
.cannon-base-rune {
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  border: 1px dashed rgba(220,180,255,.55);
  box-shadow: inset 0 0 6px rgba(180,120,255,.5);
  animation: cannonRuneSpin 6s linear infinite;
}
@keyframes cannonRuneSpin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.cannon-mount {
  position: absolute;
  left: 50%; top: 64%;
  width: 38px; height: 30px;
  transform: translate(-50%, -50%);
  border-radius: 8px 8px 6px 6px;
  background:
    linear-gradient(180deg, #8a96aa 0%, #4d586c 50%, #232a3a 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.45),
    inset 0 -3px 0 rgba(0,0,0,.6),
    0 0 0 1.5px #0c111c,
    0 2px 4px rgba(0,0,0,.6);
  z-index: 5;
}
.cannon-mount-bolt {
  position: absolute;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff5b0 0%, #ffcc44 45%, #b07000 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    0 0 0 1px rgba(0,0,0,.5),
    0 0 3px rgba(255,200,80,.7);
}
.cannon-mount-bolt.b1 { left: 4px;  top: 50%; transform: translateY(-50%); }
.cannon-mount-bolt.b2 { right: 4px; top: 50%; transform: translateY(-50%); }

.cannon-barrel {
  position: absolute;
  left: 50%; top: 64%;
  width: 78px; height: 26px;
  transform-origin: 13px 50%;
  --aim: -90deg;
  transform: translate(-13px, -50%) rotate(var(--aim));
  transition: transform .25s cubic-bezier(.34,1.4,.64,1);
  z-index: 6;
}
.cannon-barrel.aim-up    { --aim: -90deg;  }
.cannon-barrel.aim-left  { --aim: -125deg; }
.cannon-barrel.aim-right { --aim: -55deg;  }
.cannon-barrel-body {
  position: absolute;
  inset: 0;
  border-radius: 13px;
  background:
    linear-gradient(180deg,
      rgba(255,255,255,.55) 0%,
      rgba(255,255,255,.15) 18%,
      transparent 32%,
      transparent 65%,
      rgba(0,0,0,.3) 88%,
      rgba(0,0,0,.55) 100%),
    linear-gradient(180deg, #5a6680 0%, #3a445c 45%, #1c2438 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.55),
    inset 0 -3px 0 rgba(0,0,0,.55),
    0 0 0 2px #0c111c,
    0 3px 6px rgba(0,0,0,.55);
}
.cannon-barrel-band {
  position: absolute;
  top: -2px; bottom: -2px;
  width: 8px;
  border-radius: 3px;
  background:
    linear-gradient(180deg, #fff1a8 0%, #ffd24a 25%, #d99425 70%, #7a4c10 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 -2px 0 rgba(80,40,0,.6),
    0 0 0 1.5px rgba(40,20,0,.8),
    0 0 4px rgba(255,200,80,.5);
  z-index: 1;
}
.cannon-barrel-band.band1 { left: 22%; }
.cannon-barrel-band.band2 { left: 58%; }

.cannon-barrel-muzzle {
  position: absolute;
  right: 0; top: 1px;
  width: 8px; height: 24px;
  border-top-right-radius: 100% 50%;
  border-bottom-right-radius: 100% 50%;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  background:
    linear-gradient(180deg,
      rgba(255,255,255,.45) 0%,
      rgba(255,255,255,.1) 18%,
      transparent 32%,
      transparent 65%,
      rgba(0,0,0,.35) 88%,
      rgba(0,0,0,.6) 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.4),
    inset 0 -3px 0 rgba(0,0,0,.55),
    inset -3px 0 5px rgba(0,0,0,.6);
  z-index: 1;
  overflow: hidden;
}
.cannon-muzzle-hole {
  position: absolute;
  left: 15%; top: 22%;
  width: 22%; height: 56%;
  border-radius: 50%;
  background: linear-gradient(180deg, rgba(255,255,255,.8) 0%, rgba(255,255,255,.25) 60%, transparent 100%);
  filter: blur(.5px);
}
.cannon-barrel-shine {
  position: absolute;
  left: 8%; right: 12%; top: 3px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.9) 30%, rgba(255,255,255,.5) 70%, transparent 100%);
  filter: blur(.5px);
  z-index: 3;
}

.cannon-energy-core {
  position: absolute;
  left: 50%; top: 50%;
  width: 16px; height: 16px;
  --core-rot: 45deg;
  transform: translate(-50%, -50%) rotate(var(--core-rot));
  transition: left .25s cubic-bezier(.34,1.4,.64,1),
              top  .25s cubic-bezier(.34,1.4,.64,1),
              --core-rot .25s cubic-bezier(.34,1.4,.64,1);
  background:
    linear-gradient(135deg, #ffd0ff 0%, #b04eff 45%, #3a0a7a 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -2px 0 rgba(40,10,80,.7),
    0 0 0 1.5px #2a0a5a,
    0 0 10px rgba(220,140,255,.95),
    0 0 20px rgba(180,80,255,.55);
  border-radius: 3px;
  z-index: 7;
  animation: cannonCoreFloat 2s ease-in-out infinite;
}
.tower.main-tower.aim-up    .cannon-energy-core { left: 50%; top: 50%; --core-rot: 45deg; }
.tower.main-tower.aim-left  .cannon-energy-core { left: 53%; top: 52%; --core-rot: 10deg; }
.tower.main-tower.aim-right .cannon-energy-core { left: 47%; top: 52%; --core-rot: 80deg; }
.cannon-energy-shine {
  position: absolute;
  left: 22%; top: 18%;
  width: 35%; height: 30%;
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(255,255,255,.95) 0%, transparent 70%);
  filter: blur(.5px);
}
@keyframes cannonCoreFloat {
  0%,100% { box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -2px 0 rgba(40,10,80,.7),
    0 0 0 1.5px #2a0a5a,
    0 0 10px rgba(220,140,255,.95),
    0 0 20px rgba(180,80,255,.55);
  }
  50% { box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 -2px 0 rgba(40,10,80,.7),
    0 0 0 1.5px #2a0a5a,
    0 0 16px rgba(240,180,255,1),
    0 0 32px rgba(200,120,255,.75);
  }
}

.cannon-shockwave {
  position: absolute;
  left: 50%; top: 64%;
  width: 80px; height: 80px;
  transform: translate(-50%, -50%) scale(0);
  border-radius: 50%;
  border: 3px solid rgba(255,220,140,.95);
  box-shadow: 0 0 22px rgba(255,200,100,.85), inset 0 0 14px rgba(255,240,180,.7);
  opacity: 0;
  pointer-events: none;
  z-index: 8;
}
.cannon-muzzle-flash {
  position: absolute;
  left: 50%;
  top: calc(64% - 45px);
  width: 40px; height: 40px;
  transform: translate(-50%, -50%) scale(0);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.85) 0%, rgba(255,241,168,.6) 30%, rgba(255,174,58,.35) 60%, transparent 80%);
  filter: blur(2px);
  opacity: 0;
  pointer-events: none;
  z-index: 9;
  transition: left .25s cubic-bezier(.34,1.4,.64,1), top .25s cubic-bezier(.34,1.4,.64,1);
}
.tower.main-tower.aim-up    .cannon-muzzle-flash { left: 50%;              top: calc(64% - 45px); }
.tower.main-tower.aim-left  .cannon-muzzle-flash { left: calc(50% - 36px); top: calc(64% - 26px); }
.tower.main-tower.aim-right .cannon-muzzle-flash { left: calc(50% + 36px); top: calc(64% - 26px); }

.tower.main-tower.shoot .tower-inner.cannon {
  animation: cannonRecoil .42s cubic-bezier(.18,.9,.32,1.25);
}
.tower.main-tower.shoot .cannon-barrel {
  animation: cannonBarrelRecoil .42s cubic-bezier(.18,.9,.32,1.25);
}
.tower.main-tower.shoot .cannon-energy-core {
  animation: cannonCoreFire .42s cubic-bezier(.18,.9,.32,1.25);
}
.tower.main-tower.shoot .cannon-shockwave {
  animation: cannonShockwave .55s ease-out;
}
.tower.main-tower.shoot .cannon-muzzle-flash {
  animation: cannonMuzzleFlash .28s ease-out;
}
@keyframes cannonRecoil {
  0%   { transform: scale(1); }
  18%  { transform: scale(.96, .9); }
  42%  { transform: scale(1.08, 1.06); }
  68%  { transform: scale(.98, 1.02); }
  100% { transform: scale(1); }
}
@keyframes cannonBarrelRecoil {
  0%   { transform: translate(-13px, -50%) rotate(var(--aim)) translateX(0)    scaleX(1); }
  15%  { transform: translate(-13px, -50%) rotate(var(--aim)) translateX(-7px) scaleX(.92); }
  42%  { transform: translate(-13px, -50%) rotate(var(--aim)) translateX(2px)  scaleX(1.04); }
  100% { transform: translate(-13px, -50%) rotate(var(--aim)) translateX(0)    scaleX(1); }
}
@keyframes cannonCoreFire {
  0%   { transform: translate(-50%, -50%) rotate(var(--core-rot, 45deg)) scale(1);   filter: brightness(1); }
  18%  { transform: translate(-50%, -50%) rotate(var(--core-rot, 45deg)) scale(.7);  filter: brightness(1.4); }
  42%  { transform: translate(-50%, -50%) rotate(var(--core-rot, 45deg)) scale(1.5); filter: brightness(2.2); }
  100% { transform: translate(-50%, -50%) rotate(var(--core-rot, 45deg)) scale(1);   filter: brightness(1); }
}
@keyframes cannonShockwave {
  0%   { transform: translate(-50%, -50%) scale(0);   opacity: 0; border-width: 4px; }
  20%  { transform: translate(-50%, -50%) scale(.5);  opacity: 1; border-width: 4px; }
  100% { transform: translate(-50%, -50%) scale(2.4); opacity: 0; border-width: 1px; }
}
@keyframes cannonMuzzleFlash {
  0%   { transform: translate(-50%, -50%) scale(0);   opacity: 0; }
  18%  { transform: translate(-50%, -50%) scale(1.3); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1.8); opacity: 0; }
}

.tower.main-tower.spawn .tower-inner.cannon {
  animation: cannonSpawn .55s cubic-bezier(.34,1.56,.64,1);
}
@keyframes cannonSpawn {
  0%   { transform: scale(.2)  translateY(40px); opacity: 0; }
  60%  { transform: scale(1.1) translateY(-2px); opacity: 1; }
  100% { transform: scale(1)   translateY(0);    opacity: 1; }
}

/* ---------- Projectile · 糖果炮弹 ---------- */
.projectile {
  position: absolute;
  width: 14px; height: 14px;
  --angle: 0deg;
  transform: translate3d(-9999px,-9999px,0);
  background:
    radial-gradient(circle at 32% 30%,
      #fff 0%,
      #ffe5cf 12%,
      #ffaa6b 38%,
      #ff5a3a 72%,
      #8a1a05 100%);
  border-radius: 50%;
  box-shadow:
    inset 0 -2px 3px rgba(0,0,0,.7),
    inset 0 1px 1.5px rgba(255,255,255,.55),
    0 0 0 1px #5a0a0a,
    0 0 8px rgba(255,180,80,.85),
    0 0 16px rgba(255,120,40,.55);
  will-change: transform;
  /* ⚠️ 移除 contain: paint —— 它会把绘制硬裁到元素 14×14 矩形内，
     box-shadow 的发光圈 / drop-shadow 阴影都会被裁掉，
     更致命的是高速移动时 GPU 合成层重绘造成位图残影。 */
}
.projectile::before {
  content: '';
  position: absolute;
  left: 70%;
  top: 50%;
  width: 12px; height: 12px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background:
    radial-gradient(circle,
      #ffffff 0%,
      #fff2a0 25%,
      #ffae3a 55%,
      rgba(255,120,40,.55) 80%,
      transparent 100%);
  filter: blur(1px);
  pointer-events: none;
}
.projectile::after {
  content: '';
  position: absolute;
  right: 100%;
  top: 50%;
  width: 26px; height: 8px;
  transform: translateY(-50%);
  background: linear-gradient(
    to left,
    rgba(255,210,180,.85) 0%,
    rgba(255,180,140,.55) 35%,
    rgba(220,160,140,.25) 70%,
    transparent 100%);
  border-radius: 50% 0 0 50% / 50% 0 0 50%;
  filter: blur(1.5px);
  pointer-events: none;
}

/* ============================================================
   CARD BAR · 5 张糖果按钮（充能水位）
   ============================================================ */
#card-bar {
  flex: 0 0 auto;
  height: 88px;
  display: flex;
  gap: 8px;
  padding: 8px 10px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.3) 0%, transparent 30%),
    linear-gradient(180deg, #ff4d8b 0%, #b8246a 100%);
  /* ✦ 移除塔防区与技能栏之间的 4px 白色高光带（原 border-top: 4px solid #fff） */
  border-bottom: 4px solid #4a0a3a;
  box-shadow:
    0 -4px 0 #6a1a4a,
    0 4px 0 #2a042a,
    0 6px 14px rgba(80,0,60,.45);
  z-index: 8;
  position: relative;
}

/* Candy Crush 经典糖果按钮：圆角白边 + 内嵌彩色光泽 + 底部投影 */
.card-item {
  flex: 1;
  position: relative;
  border-radius: 18px;
  /* 主底色：糖果按钮的彩色（外圆）+ 内层亮色 */
  background:
    /* 顶部高光 */
    radial-gradient(ellipse 80% 40% at 50% 18%, rgba(255,255,255,.65) 0%, rgba(255,255,255,.15) 40%, transparent 70%),
    /* 主色：使用 --card-color 派生 */
    linear-gradient(180deg,
      color-mix(in srgb, var(--card-color, #fff) 80%, white) 0%,
      var(--card-color, #888) 55%,
      color-mix(in srgb, var(--card-color, #fff) 70%, black) 100%);
  border: 4px solid #fff;
  box-shadow:
    /* 外深色描边 */
    0 0 0 3px color-mix(in srgb, var(--card-color, #888) 50%, black),
    /* 内白圈光晕 */
    inset 0 2px 0 rgba(255,255,255,.55),
    inset 0 -3px 6px color-mix(in srgb, var(--card-color, #888) 60%, black),
    /* 立体底部投影 */
    0 4px 0 color-mix(in srgb, var(--card-color, #888) 40%, black),
    0 6px 12px rgba(0,0,0,.45);
  overflow: hidden;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .12s ease-out, box-shadow .2s;
}
.card-item:active {
  transform: translateY(3px) scale(.96);
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--card-color, #888) 50%, black),
    inset 0 2px 0 rgba(255,255,255,.55),
    inset 0 -3px 6px color-mix(in srgb, var(--card-color, #888) 60%, black),
    0 1px 0 color-mix(in srgb, var(--card-color, #888) 40%, black),
    0 2px 6px rgba(0,0,0,.4);
}

/* 充能水位：从底部上涨的"液体"，糖浆质感 */
.card-fill {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 0%;
  background:
    /* 顶部水面波纹高光 */
    linear-gradient(180deg, rgba(255,255,255,.85) 0%, rgba(255,255,255,.3) 8%, transparent 16%),
    /* 主体糖浆色：高亮版主题色 */
    linear-gradient(180deg,
      color-mix(in srgb, var(--card-color, #fff) 30%, white) 0%,
      var(--card-color, #fff) 80%);
  opacity: .7;
  transition: height .25s cubic-bezier(.5,0,.2,1);
  pointer-events: none;
  z-index: 0;
  /* 顶部波浪效果 */
  border-top: 2px solid rgba(255,255,255,.7);
  box-shadow: 0 -1px 6px rgba(255,255,255,.5);
}

.card-content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}
.card-icon {
  font-size: 28px;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 默认：白色剪影，更像 Candy Crush 按钮里的图案 */
  color: #fff;
  filter:
    drop-shadow(0 2px 0 rgba(0,0,0,.5))
    drop-shadow(0 0 5px rgba(255,255,255,.7));
  line-height: 1;
}
.card-icon svg { width: 100%; height: 100%; display: block; }
.card-name {
  font-size: 11px;
  letter-spacing: 1.5px;
  color: #fff;
  font-weight: 900;
  text-transform: uppercase;
  text-shadow:
    -1.5px 0 0 #2a042a, 1.5px 0 0 #2a042a,
    0 -1.5px 0 #2a042a, 0 1.5px 0 #2a042a,
    0 2px 0 rgba(0,0,0,.4);
}

/* 就绪状态：金色光环狂闪 */
.card-item.ready {
  border-color: #fff;
  box-shadow:
    0 0 0 3px #ffd93d,
    inset 0 0 0 2px var(--card-color, #fff),
    inset 0 2px 0 rgba(255,255,255,.55),
    inset 0 -3px 6px color-mix(in srgb, var(--card-color, #888) 60%, black),
    0 0 18px #ffd93d,
    0 4px 0 color-mix(in srgb, var(--card-color, #888) 40%, black),
    0 6px 14px rgba(0,0,0,.5);
  animation: cardReadyPulse 1.1s ease-in-out infinite;
}
.card-item.ready .card-fill {
  opacity: .9;
  height: 100% !important;
  background:
    linear-gradient(180deg, rgba(255,255,255,.7) 0%, transparent 25%),
    linear-gradient(180deg, #fff8a0, var(--card-color));
}
.card-item.ready .card-icon {
  color: #fff;
  filter:
    drop-shadow(0 2px 0 rgba(0,0,0,.6))
    drop-shadow(0 0 8px #fff)
    drop-shadow(0 0 14px var(--card-color, #fff));
  animation: cardIconBob .8s ease-in-out infinite alternate;
}
@keyframes cardIconBob {
  0%   { transform: translateY(0) scale(1); }
  100% { transform: translateY(-2px) scale(1.08); }
}

@keyframes cardReadyPulse {
  0%,100% {
    box-shadow:
      0 0 0 3px #ffd93d,
      inset 0 0 0 2px var(--card-color, #fff),
      inset 0 2px 0 rgba(255,255,255,.55),
      inset 0 -3px 6px color-mix(in srgb, var(--card-color, #888) 60%, black),
      0 0 18px #ffd93d,
      0 4px 0 color-mix(in srgb, var(--card-color, #888) 40%, black),
      0 6px 14px rgba(0,0,0,.5);
  }
  50% {
    box-shadow:
      0 0 0 3px #ffe34a,
      inset 0 0 0 2px var(--card-color, #fff),
      inset 0 2px 0 rgba(255,255,255,.65),
      inset 0 -3px 6px color-mix(in srgb, var(--card-color, #888) 60%, black),
      0 0 32px #ffd93d,
      0 4px 0 color-mix(in srgb, var(--card-color, #888) 40%, black),
      0 6px 18px rgba(255,217,61,.5);
  }
}
.card-ready-glow {
  position: absolute;
  inset: -4px;
  border-radius: 22px;
  pointer-events: none;
  opacity: 0;
  background: conic-gradient(from 0deg, transparent, rgba(255,255,255,.55), transparent 50%, rgba(255,255,255,.55), transparent);
  z-index: 0;
}
.card-item.ready .card-ready-glow {
  opacity: .7;
  animation: cardGlowSpin 2.4s linear infinite;
}
@keyframes cardGlowSpin { to { transform: rotate(360deg); } }
.card-item.flash { animation: cardFlashOnce .6s ease-out; }
@keyframes cardFlashOnce {
  0%   { transform: scale(1);    filter: brightness(1); }
  40%  { transform: scale(1.18); filter: brightness(2.2); }
  100% { transform: scale(1);    filter: brightness(1); }
}
.card-item.cast { animation: cardCast .7s ease-out; }
@keyframes cardCast {
  0%   { transform: scale(1);    filter: brightness(1); }
  20%  { transform: scale(1.25); filter: brightness(2.5); box-shadow: 0 0 30px #fff, 0 0 50px var(--card-color); }
  60%  { transform: scale(.86);  filter: brightness(1.4); }
  100% { transform: scale(1);    filter: brightness(1); }
}
.card-item.deny { animation: cardDeny .3s; }
@keyframes cardDeny {
  0%,100% { transform: translateX(0); }
  25% { transform: translateX(-6px); }
  75% { transform: translateX(6px); }
}

/* ============================================================
   MATCH-3 ZONE · 糖果托盘 + 圆润糖果棋子
   ============================================================ */
#match-zone {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background:
    /* 顶部光斑 */
    radial-gradient(ellipse at 50% -10%, rgba(255,180,220,.55) 0%, transparent 45%),
    /* 装饰糖果点缀 */
    radial-gradient(circle at 18% 22%, rgba(255,200,140,.35) 0 22px, transparent 24px),
    radial-gradient(circle at 82% 18%, rgba(180,140,255,.35) 0 26px, transparent 28px),
    radial-gradient(circle at 32% 80%, rgba(255,220,180,.3) 0 18px, transparent 20px),
    radial-gradient(circle at 78% 78%, rgba(220,180,255,.3) 0 20px, transparent 22px),
    /* 主紫蓝渐变（糖果空间） */
    linear-gradient(180deg,
      #4a1a8c 0%,
      #5b2098 25%,
      #6a26a8 55%,
      #4a1a8c 80%,
      #2a0e5e 100%);
  /* ✦ UI 优化（v2）：保持棋盘原本大小不变，仅通过容器左右 padding
     让棋盘"边缘相对屏幕边缘"有合理距离（≈ 28px 糖果柱 + 8px 间距 = 36px）。
     上下 padding 保持紧凑，让棋盘紧贴卡牌区不留大空白。 */
  padding: 6px 36px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* ✦ 顶部对齐：棋盘紧贴卡牌区 */
  justify-content: flex-start;
  overflow: hidden;
}
/* 左右糖果柱 —— 紧贴 #match-zone 内壁（即屏幕左右边缘），与棋盘自然形成 8px 安全间距 */
#match-zone::before,
#match-zone::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  /* ✦ 恢复 28px 标准糖果柱宽度，positioned at 屏幕边缘内侧 */
  width: 28px;
  pointer-events: none;
  background:
    repeating-linear-gradient(
      135deg,
      #ff4d8b 0px, #ff4d8b 6px,
      #fff 6px,    #fff 12px,
      #4da8ff 12px, #4da8ff 18px,
      #fff 18px,    #fff 24px
    );
  border-radius: 0 10px 10px 0;
  border: 2px solid #fff;
  border-left: none;
  box-shadow:
    inset 0 0 6px rgba(0,0,0,.25),
    0 0 8px rgba(0,0,0,.4);
  z-index: 0;
}
#match-zone::before { left: 0; }
#match-zone::after  {
  right: 0;
  border-radius: 10px 0 0 10px;
  border: 2px solid #fff;
  border-right: none;
}

/* ---------- Board · 糖果托盘 ---------- */
#board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: repeat(6, 1fr);
  gap: 3px;
  width: 100%;
  max-width: 380px;
  /* ✦ 保持棋盘原本尺寸：恢复合理内边距，不再为"挤占糖果柱空间"而压缩 */
  padding: 10px 8px;
  /* 糖果托盘：金色木框 + 紫色凹槽底 */
  background:
    /* 内部顶部高光 */
    linear-gradient(180deg, rgba(255,255,255,.18) 0%, transparent 25%),
    /* 凹陷紫底 */
    linear-gradient(180deg, rgba(60,20,110,.7) 0%, rgba(40,10,80,.85) 100%);
  border-radius: 16px;
  border: 3px solid #fff;
  /* ✦ 把外发光描边从 0 0 0 3px + 0 0 0 6px 收紧到 2px + 4px，
     总外侧厚度从 9px 缩到 6px，避免在小屏顶到糖果柱 */
  box-shadow:
    0 0 0 2px #ffd93d,
    0 0 0 4px #d97a00,
    inset 0 3px 6px rgba(20,5,40,.7),
    inset 0 -2px 0 rgba(255,255,255,.15),
    0 4px 0 #6a1a4a,
    0 8px 16px rgba(0,0,0,.55);
  touch-action: none;
  margin: 0 auto;
  flex-shrink: 0;
  z-index: 1;
}
#board::before,
#board::after {
  content: none;
  display: none;
}

/* 棋盘格子：糖纸凹槽 */
.cell {
  position: relative;
  border-radius: 12px;
  background:
    radial-gradient(ellipse at 50% 30%, rgba(255,255,255,.1) 0%, transparent 60%),
    rgba(20,5,40,.45);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform .15s ease-out, opacity .25s, filter .15s;
  will-change: transform;
  overflow: visible;
  box-shadow:
    inset 0 2px 3px rgba(20,5,40,.6),
    inset 0 -1px 0 rgba(255,255,255,.1);
  filter: drop-shadow(0 3px 3px rgba(20,5,40,.4));
}

/* ==========================================================
   糖果棋子（Candy Crush 风格）
   - 用 clip-path 多边形 = 糖果切面轮廓
   - 主体：超亮高饱和糖果色 + 强高光 + 厚白边
   - 顶部 ✦ 闪光 + 内层光泽
   ========================================================== */
.cell::before {
  content: '';
  position: absolute;
  inset: 8%;
  z-index: 0;
  pointer-events: none;
  clip-path: var(--gem-clip, circle(50%));
  background: var(--gem-bg, linear-gradient(160deg, #ddd 0%, #999 100%));
  /* 糖果浮雕效果：上亮一道 + 下深一圈 + 白色描边代替黑色 */
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.75),
    inset 0 -3px 6px rgba(0,0,0,.4),
    /* 强烈外发光 */
    0 0 0 2px rgba(255,255,255,.85);
  filter: drop-shadow(0 2px 4px rgba(0,0,0,.5));
}
/* ✦ 闪光 + 顶部弧光 */
.cell::after {
  content: '';
  position: absolute;
  left: 18%;
  top: 14%;
  width: 38%;
  height: 28%;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(0deg,
      transparent 30%, rgba(255,255,255,.95) 47%, #fff 50%, rgba(255,255,255,.95) 53%, transparent 70%),
    linear-gradient(90deg,
      transparent 30%, rgba(255,255,255,.95) 47%, #fff 50%, rgba(255,255,255,.95) 53%, transparent 70%),
    radial-gradient(ellipse 80% 60% at 55% 30%,
      rgba(255,255,255,.85) 0%, rgba(255,255,255,.35) 35%, transparent 70%);
  background-size: 3px 22px, 22px 3px, 100% 100%;
  background-position: 8px 4px, -1px 13px, 0 0;
  background-repeat: no-repeat, no-repeat, no-repeat;
  filter: drop-shadow(0 0 5px rgba(255,255,255,.95));
}
/* 中央元素 emoji */
.cell > span {
  position: relative;
  z-index: 3;
  font-size: clamp(18px, 3.8vw, 28px);
  line-height: 1;
  pointer-events: none;
  filter:
    drop-shadow(0 1px 0 rgba(0,0,0,.55))
    drop-shadow(0 0 4px rgba(255,255,255,.7));
  text-shadow: 0 0 6px rgba(255,255,255,.5);
  user-select: none;
}

.cell .gem-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  z-index: 4;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  filter: drop-shadow(0 3px 4px rgba(0,0,0,.35));
}
.cell .gem-img[hidden] { display: none; }

/* ============================================================
   每种棋子的糖果造型
   ============================================================ */

/* 🔥 FIRE · 红色糖球（圆形） */
.cell[data-type="fire"] {
  --gem-clip: circle(48% at 50% 50%);
  --gem-bg:
    radial-gradient(ellipse 65% 50% at 36% 26%, #fff8e6 0%, rgba(255,255,255,.5) 25%, transparent 55%),
    radial-gradient(circle at 50% 55%, #ff7060 0%, #ff2d4d 50%, #c80a30 100%);
}

/* ❄️ ICE · 蓝色冰糖（六角星形） */
.cell[data-type="ice"] {
  --gem-clip: polygon(50% 0%, 65% 25%, 100% 25%, 75% 50%, 100% 75%, 65% 75%, 50% 100%, 35% 75%, 0% 75%, 25% 50%, 0% 25%, 35% 25%);
  --gem-bg:
    radial-gradient(ellipse 70% 55% at 38% 28%, #f0fbff 0%, transparent 55%),
    linear-gradient(160deg, #b0ecff 0%, #58cdff 30%, #1ea0d8 65%, #0a4a8a 100%);
}

/* ⚡ THUNDER · 黄色棒棒糖（条纹圆） */
.cell[data-type="thunder"] {
  --gem-clip: circle(48% at 50% 50%);
  --gem-bg:
    /* 螺旋条纹 */
    repeating-conic-gradient(
      from 0deg at 50% 50%,
      #fff 0deg 18deg,
      #ffd93d 18deg 36deg,
      #ff8c2a 36deg 54deg,
      #ffd93d 54deg 72deg
    ),
    radial-gradient(ellipse 70% 55% at 38% 30%, #fffbe0 0%, transparent 55%);
}

/* 🌿 LEAF · 绿色果冻（八边形） */
.cell[data-type="leaf"] {
  --gem-clip: polygon(20% 4%, 80% 4%, 96% 20%, 96% 80%, 80% 96%, 20% 96%, 4% 80%, 4% 20%);
  --gem-bg:
    radial-gradient(ellipse 70% 50% at 36% 28%, #f0ffe2 0%, transparent 55%),
    linear-gradient(160deg, #aaf09a 0%, #58e860 30%, #1ea848 65%, #045a1c 100%);
}

/* 💎 GOLD · 紫色钻石（菱形） */
.cell[data-type="gold"] {
  --gem-clip: polygon(8% 22%, 30% 4%, 70% 4%, 92% 22%, 50% 98%);
  --gem-bg:
    linear-gradient(135deg, transparent 46%, rgba(255,255,255,.55) 50%, transparent 54%),
    linear-gradient(45deg,  transparent 46%, rgba(255,255,255,.4)  50%, transparent 54%),
    radial-gradient(ellipse 70% 50% at 38% 24%, #ffffff 0%, transparent 55%),
    linear-gradient(160deg, #fff0ff 0%, #ffafff 22%, #d04eff 50%, #7a1ad8 80%, #3a0a5a 100%);
}

/* selected */
.cell.selected { transform: scale(1.12); z-index: 5; }
.cell.selected::before {
  filter: brightness(1.25) saturate(1.3);
}
.cell.selected {
  outline: 3px solid #ffd93d;
  outline-offset: -3px;
  box-shadow:
    inset 0 0 0 3px #ffd93d,
    0 0 0 4px rgba(255,217,61,.6),
    0 0 18px rgba(255,217,61,.85);
}

/* matching */
.cell.matching { animation: cellMatch .55s cubic-bezier(.34,1.56,.64,1) forwards; z-index: 6; }
@keyframes cellMatch {
  0%   { transform: scale(1);    filter: brightness(1)   drop-shadow(0 0 0 transparent);  opacity: 1; }
  25%  { transform: scale(1.55); filter: brightness(2.2) drop-shadow(0 0 14px #fff);      opacity: 1; }
  45%  { transform: scale(1.7);  filter: brightness(2.8) drop-shadow(0 0 22px #fff);      opacity: 1; }
  70%  { transform: scale(1.5);  filter: brightness(2.2) drop-shadow(0 0 14px #fff);      opacity: 1; }
  100% { transform: scale(0);    filter: brightness(1)   drop-shadow(0 0 0 transparent);  opacity: 0; }
}
.cell.matching::before { animation: cellMatchHalo .55s ease-out forwards; }
@keyframes cellMatchHalo {
  0%   { transform: scale(.4) rotate(0deg);   opacity: 0; }
  35%  { transform: scale(1.6) rotate(120deg); opacity: 1; }
  70%  { transform: scale(2)   rotate(220deg); opacity: .85; }
  100% { transform: scale(2.6) rotate(360deg); opacity: 0; }
}

.cell.falling { animation: cellFall .35s ease-in; }
@keyframes cellFall {
  0%   { transform: translateY(-30%); opacity: 0; }
  100% { transform: translateY(0);    opacity: 1; }
}
.cell.swap-anim { transition: transform .2s; }
.cell.shake { animation: cellShake .3s; }
@keyframes cellShake {
  0%,100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

.cell.dragging {
  --drag-dx: 0px;
  --drag-dy: 0px;
  --drag-d: 0;
  z-index: 9;
  transition: none;
  transform:
    translate3d(var(--drag-dx), var(--drag-dy), 0)
    scale( calc(1.10 + var(--drag-d) * 0.06) )
    scaleX( calc(1 + (abs(var(--drag-dx)) / 60px) - (abs(var(--drag-dy)) / 90px)) )
    scaleY( calc(1 + (abs(var(--drag-dy)) / 60px) - (abs(var(--drag-dx)) / 90px)) );
  filter:
    brightness(1.18) saturate(1.25)
    drop-shadow(0 8px 10px rgba(80,40,120,.45));
}
.cell.dragging::before {
  animation: candySquish .55s cubic-bezier(.34,1.56,.64,1) infinite alternate;
}
.cell.dragging::after {
  transform: translate(calc(var(--drag-dx) * 0.15), calc(var(--drag-dy) * 0.15));
  filter: brightness(1.3);
}
@keyframes candySquish {
  0%   { transform: scale(1, 1); }
  100% { transform: scale(1.06, .94); }
}
@supports not (transform: scaleX(calc(abs(1px) / 1px))) {
  .cell.dragging {
    transform:
      translate3d(var(--drag-dx), var(--drag-dy), 0)
      scale(calc(1.12 + var(--drag-d) * 0.08));
  }
}

.cell.special-burst { animation: specialBurst .2s ease-out forwards; z-index: 8; }
@keyframes specialBurst {
  0%   { transform: scale(1);   filter: brightness(1)   drop-shadow(0 0 0 transparent); }
  50%  { transform: scale(1.7); filter: brightness(2.5) drop-shadow(0 0 20px #fff); }
  100% { transform: scale(2);   filter: brightness(3)   drop-shadow(0 0 30px #fff); }
}

/* Special candies */
.cell[data-special="bomb"]::before {
  background:
    radial-gradient(circle at 50% 40%, #fffbe0 0%, #ffd54a 30%, #ff5a3a 70%, #6a0000 100%);
  box-shadow: 0 0 24px #ffaa00, 0 4px 0 #6a0000, 0 6px 8px rgba(0,0,0,.4);
}
.cell[data-special="bomb"] > span {
  font-size: clamp(20px, 6vw, 30px);
  color: #fff;
  text-shadow: 0 1px 2px #000, 0 0 8px #ff5a3a;
  filter: drop-shadow(0 1px 1px #000);
}
.cell[data-special="line-h"]::before,
.cell[data-special="line-v"]::before {
  background:
    linear-gradient(90deg, #fff 0%, var(--gem-glow) 25%, #fff 50%, var(--gem-glow) 75%, #fff 100%);
  box-shadow: 0 0 16px var(--gem-glow), 0 4px 0 var(--gem-shadow), 0 6px 8px rgba(0,0,0,.35);
}
.cell[data-special] > span {
  font-size: clamp(16px, 5vw, 24px);
  color: #fff;
  text-shadow: 0 1px 2px #000;
  filter: drop-shadow(0 1px 1px #000);
}

/* combo display —— 糖果气泡字 */
#combo-display {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  background: none;
  border: none;
  box-shadow: none;
  padding: 0 4px;
  font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', 'PingFang SC', system-ui, cursive;
  /* ✦ 字号收紧，防止超长 combo 文字超出糖果柱 */
  font-size: clamp(16px, 5.4vw, 28px);
  font-weight: 900;
  font-style: italic;
  letter-spacing: 0.5px;
  color: #ffd93d;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  white-space: normal;
  text-align: center;
  /* ✦ 关键修复：之前 92vw 是相对视口，糖果柱左右共占 36px，
     这里改用 calc(100% - 48px) 严格限制在 #match-zone 糖果柱内侧，
     超出时自动换行而非溢出 */
  width: calc(100% - 48px);
  max-width: calc(100% - 48px);
  word-break: break-word;
  overflow-wrap: anywhere;
  line-height: 1;
  pointer-events: none;
  opacity: 0;
  z-index: 30;
}
#combo-display::before { content: none; }

#combo-display.show { animation: comboPop 1.2s ease-out; }
@keyframes comboPop {
  0%   { transform: translateX(-50%) scale(0)    rotate(-15deg); opacity: 0; }
  20%  { transform: translateX(-50%) scale(1.25) rotate(5deg);   opacity: 1; }
  60%  { transform: translateX(-50%) scale(1)    rotate(0);      opacity: 1; }
  100% { transform: translateX(-50%) scale(1.35); opacity: 0; }
}

.epic-line {
  display: inline-flex;
  justify-content: center;
  align-items: flex-end;
  white-space: nowrap;
}
.epic-line.line-2 {
  font-size: 0.78em;
  margin-top: 2px;
}
.epic-char {
  display: inline-block;
  color: #ffd93d;
  text-shadow:
    1px 1px 0 #6a1a4a,
    2px 2px 0 #6a1a4a,
    3px 3px 0 #4a0a3a,
    4px 5px 0 #2a042a,
    5px 7px 0 #1a0218,
    0 0 10px rgba(255,210,90,.55);
  -webkit-text-stroke: 1px #4a0a3a;
  transform-origin: 50% 80%;
  will-change: transform;
}

.flying-res {
  position: fixed;
  font-size: 24px;
  z-index: 50;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.4));
  will-change: transform;
}

.damage-num {
  position: absolute;
  font-size: 16px;
  font-weight: 900;
  color: #fff;
  text-shadow:
    -1px 0 0 #000, 1px 0 0 #000,
    0 -1px 0 #000, 0 1px 0 #000,
    0 0 5px currentColor;
  pointer-events: none;
  animation: dmgFloat .7s forwards;
  z-index: 7;
}
@keyframes dmgFloat {
  0%   { transform: translate(-50%,-50%) scale(.6);  opacity: 0; }
  20%  { transform: translate(-50%,-130%) scale(1.2); opacity: 1; }
  100% { transform: translate(-50%,-220%) scale(.9); opacity: 0; }
}

/* ---------- Start / Game over · 糖果对话框 ---------- */
#start-screen, #game-over {
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse at 50% 30%, rgba(255,180,220,.55), rgba(80,20,120,.65) 60%, rgba(20,5,40,.9) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
#start-screen:not(.hidden), #game-over:not(.hidden) {
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
#game-over.hidden, #start-screen.hidden { display: none !important; }

.start-card, .over-card {
  background:
    radial-gradient(ellipse at 50% 0%, rgba(255,255,255,.6), transparent 40%),
    linear-gradient(180deg, #ffe6f0 0%, #ffaad4 60%, #ff4d8b 100%);
  padding: 30px 24px;
  border-radius: 28px;
  border: 5px solid #fff;
  box-shadow:
    0 0 0 4px #ffd93d,
    0 0 0 8px #ff8c2a,
    0 8px 0 #6a1a4a,
    0 14px 26px rgba(0,0,0,.55),
    0 -2px 0 rgba(255,255,255,.7) inset;
  text-align: center;
  max-width: 320px;
  width: 86%;
}
.game-title {
  font-size: 44px;
  font-weight: 900;
  color: #fff;
  letter-spacing: 4px;
  font-family: "Baloo 2", "Comic Sans MS", system-ui, cursive;
  text-shadow:
    -2px 0 0 #8a1856, 2px 0 0 #8a1856,
    0 -2px 0 #8a1856, 0 2px 0 #8a1856,
    -3px -3px 0 #8a1856, 3px 3px 0 #8a1856,
    0 5px 0 #4a0a3a,
    0 8px 12px rgba(0,0,0,.5);
}
.game-title span {
  color: #ffd93d;
  -webkit-text-fill-color: initial;
}
.subtitle {
  font-size: 14px;
  color: #fff;
  letter-spacing: 6px;
  margin: 10px 0 20px;
  font-weight: 900;
  text-shadow: 0 2px 0 #8a1856, 0 3px 6px rgba(0,0,0,.4);
}
.rules {
  text-align: left;
  background: rgba(255,255,255,.92);
  padding: 14px;
  border-radius: 16px;
  margin: 16px 0;
  font-size: 13px;
  line-height: 1.7;
  color: #5a1856;
  border: 3px solid #fff;
  box-shadow: 0 0 0 2px #ff4d8b, 0 4px 8px rgba(0,0,0,.25);
}
.rules p { margin: 4px 0; }
.rules b { color: #b8246a; }

#start-btn, #restart-btn {
  width: 100%;
  padding: 14px;
  font-size: 18px;
  font-weight: 900;
  letter-spacing: 4px;
  color: #fff;
  font-family: "Baloo 2", "Comic Sans MS", system-ui, cursive;
  background:
    linear-gradient(180deg, rgba(255,255,255,.5) 0%, transparent 50%),
    linear-gradient(180deg, #6FE26F 0%, #2bc14a 100%);
  border: 4px solid #fff;
  border-radius: 22px;
  cursor: pointer;
  box-shadow:
    0 0 0 3px #1a8628,
    0 6px 0 #1a8628,
    0 9px 14px rgba(0,0,0,.4),
    0 -2px 0 rgba(255,255,255,.5) inset;
  transition: transform .12s, box-shadow .12s;
  margin-top: 10px;
  text-shadow: 0 2px 0 #1a8628, 0 3px 4px rgba(0,0,0,.4);
}
#start-btn:active, #restart-btn:active {
  transform: translateY(4px);
  box-shadow:
    0 0 0 3px #1a8628,
    0 2px 0 #1a8628,
    0 4px 8px rgba(0,0,0,.4),
    0 -2px 0 rgba(255,255,255,.5) inset;
}
#over-title {
  font-size: 34px;
  color: #fff;
  font-weight: 900;
  font-family: "Baloo 2", "Comic Sans MS", system-ui, cursive;
  text-shadow:
    -2px 0 0 #8a1856, 2px 0 0 #8a1856,
    0 -2px 0 #8a1856, 0 2px 0 #8a1856,
    0 4px 0 #4a0a3a;
  margin-bottom: 16px;
}
.over-card p {
  font-size: 15px;
  /* ✦ 用户需求 #4：GameOver 文字由暗红改为白色 */
  color: #fff;
  margin: 8px 0;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0,0,0,.35);
}
.over-card span { color: #fff; font-weight: 900; text-shadow: 0 1px 2px rgba(0,0,0,.45); }

/* ---------- Footer signature ---------- */
#signature {
  flex: 0 0 auto;
  height: 16px;
  line-height: 16px;
  text-align: center;
  font-size: 10px;
  color: #fff;
  background: linear-gradient(180deg, #4a0a3a, #1a0218);
  border-top: 2px solid #ffd93d;
  z-index: 99;
  pointer-events: auto;
  text-shadow: 0 1px 0 rgba(0,0,0,.5);
}
#signature a { color: #ffd93d; text-decoration: none; font-weight: 900; }

/* hurt flash */
#game-container.hurt-flash::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 200;
  border-radius: inherit;
  box-shadow: 0 0 100px 20px rgba(255,40,100,.55) inset;
  animation: hurtFlash .38s ease-out forwards;
}
@keyframes hurtFlash { 0%{opacity:0;}30%{opacity:1;}100%{opacity:0;} }

#game-container.heal-flash::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 200;
  border-radius: inherit;
  box-shadow: 0 0 100px 20px rgba(110,232,122,.55) inset;
  animation: healFlash .55s ease-out forwards;
}
@keyframes healFlash { 0%{opacity:0;}30%{opacity:1;}100%{opacity:0;} }

/* ---------- Card wash + epic banner ---------- */
.card-wash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 150;
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity .6s ease-out;
}
.card-wash:not(.fade) { opacity: .3 !important; }
.card-wash.fade { opacity: 0 !important; }

.snow-flake {
  position: absolute;
  color: #aaeeff;
  text-shadow: 0 0 6px #aaeeff;
  pointer-events: none;
  z-index: 30;
  animation: snowFall linear forwards;
}
@keyframes snowFall {
  0%   { transform: translateY(0)   rotate(0deg);   opacity: 0; }
  10%  { opacity: 1; }
  100% { transform: translateY(120%) rotate(540deg); opacity: 0; }
}

.diamond-dust {
  position: absolute;
  pointer-events: none;
  z-index: 30;
  filter: drop-shadow(0 0 4px currentColor);
  animation: diamondDust ease-out forwards;
}
@keyframes diamondDust {
  0%   { transform: scale(0)   rotate(0deg);   opacity: 0; }
  20%  { transform: scale(1.4) rotate(180deg); opacity: 1; }
  70%  { transform: scale(1)   rotate(540deg); opacity: .8; }
  100% { transform: scale(.4)  rotate(720deg) translateY(-30px); opacity: 0; }
}

.epic-banner {
  position: absolute;
  left: 50%; top: 38%;
  transform: translate(-50%,-50%);
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', 'PingFang SC', system-ui, cursive;
  font-size: clamp(28px, 9.5vw, 56px);
  font-weight: 900;
  font-style: italic;
  letter-spacing: 1px;
  line-height: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  white-space: normal;
  text-align: center;
  max-width: 92vw;
  color: #ffd93d;
  pointer-events: none;
  z-index: 999;
  --epic-tint: #ffd93d;
  animation: epicBannerShow var(--epic-life,1400ms) cubic-bezier(.2,1.6,.4,1) forwards;
}
.epic-banner::before { content: none; }
.epic-banner .epic-char {
  color: #ffd93d;
  text-shadow:
    1px 1px 0 #6a1a4a,
    2px 2px 0 #6a1a4a,
    3px 4px 0 #4a0a3a,
    5px 6px 0 #2a042a,
    7px 9px 0 #1a0218,
    9px 12px 0 #0a010a,
    0 0 18px rgba(255,210,90,.85),
    0 0 34px var(--epic-tint, #ff4d8b);
  -webkit-text-stroke: 1.5px #4a0a3a;
}
@keyframes epicBannerShow {
  0%   { transform: translate(-50%,-50%) scale(.2);   opacity: 0; filter: blur(8px); }
  10%  { transform: translate(-50%,-50%) scale(1.45); opacity: 1; filter: blur(0); }
  16%  { transform: translate(-50%,-50%) scale(1.25); }
  22%  { transform: translate(-50%,-50%) scale(1.40); }
  28%  { transform: translate(-50%,-50%) scale(1.22); }
  34%  { transform: translate(-50%,-50%) scale(1.36); }
  40%  { transform: translate(-50%,-50%) scale(1.20); }
  46%  { transform: translate(-50%,-50%) scale(1.32); }
  52%  { transform: translate(-50%,-50%) scale(1.18); }
  60%  { transform: translate(-50%,-50%) scale(1.25); }
  78%  { transform: translate(-50%,-50%) scale(1.15); opacity: 1; }
  100% { transform: translate(-50%,-64%) scale(1.05); opacity: 0; }
}
@media (max-width: 480px) {
  .epic-banner {
    font-size: clamp(24px, 8.4vw, 38px);
    letter-spacing: 0.5px;
    max-width: 94vw;
  }
}

.lightning-arc {
  position: absolute;
  height: 4px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,255,255,.8) 10%,
    #fff 50%,
    rgba(255,255,255,.8) 90%,
    transparent 100%);
  box-shadow: 0 0 8px #ffd93d, 0 0 16px #fff, 0 0 24px #ffd93d;
  transform-origin: 0% 50%;
  pointer-events: none;
  z-index: 40;
  animation: arcFlicker .3s ease-out forwards;
  filter: drop-shadow(0 0 4px #ffd93d);
}
@keyframes arcFlicker {
  0%   { opacity: 0; transform: scaleX(0) scaleY(.4); }
  20%  { opacity: 1; transform: scaleX(1) scaleY(1.6); }
  40%  { opacity: .7; transform: scaleX(1) scaleY(.8); }
  70%  { opacity: 1; transform: scaleX(1) scaleY(1.4); }
  100% { opacity: 0; transform: scaleX(1) scaleY(.6); }
}

/* ---------- Skill background animations ---------- */
.skill-bg {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 180;
  opacity: 0;
  animation: skillBgFade 2.6s ease-out forwards;
}
@keyframes skillBgFade {
  0% { opacity: 0; } 10% { opacity: .3; }
  85% { opacity: .3; } 100% { opacity: 0; }
}
.skill-bg-ice::before {
  content: '';
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(ellipse at center, rgba(170,230,255,.55) 0%, rgba(120,190,255,.25) 40%, transparent 75%),
    conic-gradient(from 0deg at 50% 50%,
      rgba(255,255,255,.15) 0deg, rgba(170,230,255,.55) 40deg,
      rgba(255,255,255,.10) 80deg, rgba(120,190,255,.45) 130deg,
      rgba(255,255,255,.20) 180deg, rgba(170,230,255,.55) 230deg,
      rgba(255,255,255,.10) 280deg, rgba(120,190,255,.50) 330deg,
      rgba(255,255,255,.15) 360deg);
  filter: blur(4px);
  animation: cycloneSpin 1.8s linear infinite;
}
.skill-bg-ice::after {
  content: '❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄ ❄';
  position: absolute;
  inset: 0;
  color: #eaf6ff;
  text-shadow: 0 0 8px #aaeeff, 0 0 18px #79d4ff;
  font-size: 22px;
  letter-spacing: 60px;
  white-space: pre-wrap;
  word-spacing: 28px;
  line-height: 70px;
  text-align: center;
  padding: 20px;
  animation: snowCascade 2.4s linear infinite;
  opacity: .9;
}
@keyframes cycloneSpin {
  0%   { transform: rotate(0deg) scale(1); }
  50%  { transform: rotate(180deg) scale(1.08); }
  100% { transform: rotate(360deg) scale(1); }
}
@keyframes snowCascade {
  0%   { transform: translate(-3%, -40%) rotate(-3deg); }
  50%  { transform: translate(3%, 0%) rotate(2deg); }
  100% { transform: translate(-3%, 40%) rotate(3deg); }
}
.skill-bg-fire { background: radial-gradient(ellipse at 50% 110%, rgba(120,20,5,.55) 0%, rgba(20,5,0,.35) 55%, transparent 100%); }
.fire-svg { position: absolute; left: 0; bottom: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.fire-svg .flame-tongue {
  transform-origin: var(--ox, 50%) 100%;
  filter:
    drop-shadow(0 -2px 8px rgba(255,180,60,.85))
    drop-shadow(0 0 16px rgba(255,90,20,.7));
  animation:
    flameDance var(--life, 1.4s) ease-in-out infinite alternate,
    flameGlow  var(--glow, 0.9s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s), var(--delay, 0s);
}
@keyframes flameDance {
  0%   { transform: scaleY(.92) scaleX(1.04) translateY(2%) rotate(var(--lean,-2deg)); }
  50%  { transform: scaleY(1.10) scaleX(.96) translateY(-3%) rotate(0deg); }
  100% { transform: scaleY(.96) scaleX(1.02) translateY(1%)  rotate(calc(var(--lean,2deg) * -1)); }
}
@keyframes flameGlow {
  0%   { filter: drop-shadow(0 -2px 6px rgba(255,180,60,.7)) drop-shadow(0 0 12px rgba(255,90,20,.6))  brightness(.95); }
  100% { filter: drop-shadow(0 -4px 14px rgba(255,220,90,1)) drop-shadow(0 0 24px rgba(255,120,40,.9)) brightness(1.25); }
}
.skill-bg-fire::before {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 30%;
  background:
    radial-gradient(ellipse at 25% 100%, rgba(255,90,30,.7)  0%, transparent 55%),
    radial-gradient(ellipse at 50% 100%, rgba(255,170,40,.85) 0%, transparent 65%),
    radial-gradient(ellipse at 75% 100%, rgba(255,80,20,.7)  0%, transparent 55%);
  filter: blur(6px);
  animation: fireBreath 0.42s ease-in-out infinite alternate;
}
.skill-bg-fire::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, transparent 60%, rgba(20,5,0,.4) 100%);
  pointer-events: none;
}
@keyframes fireBreath {
  0%   { transform: scaleY(1)    translateY(0);   filter: brightness(1); }
  100% { transform: scaleY(1.18) translateY(-3%); filter: brightness(1.35); }
}
.skill-bg-thunder {
  background: radial-gradient(ellipse at center, rgba(40,30,80,.4) 0%, rgba(10,5,25,.6) 100%);
  animation: thunderFlash 2.6s ease-out forwards, skillBgFade 2.6s ease-out forwards;
}
.skill-bg-thunder::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(105deg, transparent 48%, rgba(255,240,150,.95) 49%, #fff 50%, rgba(255,240,150,.95) 51%, transparent 52%),
    linear-gradient(75deg,  transparent 38%, rgba(180,220,255,.9)  39%, #fff 40%, rgba(180,220,255,.9)  41%, transparent 42%),
    linear-gradient(120deg, transparent 68%, rgba(255,230,100,.9)  69%, #fff 70%, rgba(255,230,100,.9)  71%, transparent 72%);
  filter: drop-shadow(0 0 20px #ffd93d) drop-shadow(0 0 40px #fff);
  animation: lightningStrike 0.6s steps(2) infinite;
}
.skill-bg-thunder::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 50%, rgba(255,255,255,.95) 0%, transparent 30%);
  opacity: 0;
  animation: lightningBoom 1.4s ease-out infinite;
}
@keyframes thunderFlash { 0%,100%{background-color:rgba(10,5,25,0);} 50%{background-color:rgba(40,30,80,.3);} }
@keyframes lightningStrike {
  0%   { opacity: 0; transform: translateX(0)   scaleY(1)    skewX(0deg);   filter: hue-rotate(0deg)  brightness(1); }
  8%   { opacity: 1; transform: translateX(-3%) scaleY(1.1)  skewX(-2deg);  filter: hue-rotate(20deg) brightness(1.6); }
  16%  { opacity: 0; }
  28%  { opacity: 1; transform: translateX(4%)  scaleY(.92)  skewX(3deg);   filter: hue-rotate(-15deg) brightness(1.8); }
  40%  { opacity: 0; }
  55%  { opacity: 1; transform: translateX(-2%) scaleY(1.05) skewX(-1deg);  filter: hue-rotate(10deg) brightness(1.5); }
  70%  { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes lightningBoom { 0%,25%,55%,80%{opacity:0;} 8%,32%,62%{opacity:.95; transform:scale(1.1);} 100%{opacity:0; transform:scale(1);} }

.skill-bg-leaf::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 10% 100%, rgba(110,232,122,.85) 0%, transparent 35%),
    radial-gradient(ellipse at 30% 100%, rgba(60,200,90,.85)  0%, transparent 40%),
    radial-gradient(ellipse at 55% 100%, rgba(140,255,160,.85) 0%, transparent 38%),
    radial-gradient(ellipse at 75% 100%, rgba(80,220,100,.85) 0%, transparent 42%),
    radial-gradient(ellipse at 95% 100%, rgba(120,240,140,.85) 0%, transparent 36%),
    linear-gradient(0deg, rgba(60,160,80,.5) 0%, transparent 60%);
  transform-origin: 50% 100%;
  animation: plantGrow 1.6s cubic-bezier(.2,.8,.3,1) forwards;
}
.skill-bg-leaf::after {
  content: '🌿  🍃  🌱  🌿  🍃  🌱  🌿  🍃  🌱  🌿  🍃  🌱  🌿  🍃  🌱  🌿  🍃  🌱';
  position: absolute;
  inset: 0;
  color: #6ee87a;
  text-shadow: 0 0 8px #6ee87a, 0 0 16px #2fa040;
  font-size: 28px;
  letter-spacing: 24px;
  word-spacing: 30px;
  line-height: 70px;
  text-align: center;
  padding: 20px;
  animation: leafFloat 2.4s ease-out forwards;
}
@keyframes plantGrow {
  0%   { transform: scaleY(0)   skewX(0deg); opacity: 0; }
  30%  { transform: scaleY(.5)  skewX(-3deg); opacity: 1; }
  55%  { transform: scaleY(.85) skewX(3deg);  opacity: 1; }
  75%  { transform: scaleY(1)   skewX(-2deg); }
  100% { transform: scaleY(1)   skewX(0deg);  opacity: 1; }
}
@keyframes leafFloat {
  0%   { transform: translate(-5%, 40%) scale(.4)  rotate(-15deg); opacity: 0; filter: blur(3px); }
  25%  { transform: translate(2%, 10%)  scale(.9)  rotate(8deg);   opacity: 1; filter: blur(0); }
  50%  { transform: translate(-3%, -10%) scale(1.05) rotate(-6deg); opacity: 1; }
  75%  { transform: translate(4%, -25%)  scale(1.1)  rotate(10deg); opacity: .8; }
  100% { transform: translate(-2%, -45%) scale(1.2)  rotate(-12deg); opacity: 0; }
}
.skill-bg-gold { perspective: 800px; }
.skill-bg-gold::before {
  content: '💎';
  position: absolute;
  left: 50%; top: 50%;
  font-size: clamp(180px, 40vmin, 360px);
  transform: translate(-50%, -50%) scale(0);
  filter: drop-shadow(0 0 30px #fff8aa) drop-shadow(0 0 60px #ffd93d);
  animation: diamondShatter 2.4s cubic-bezier(.3,.6,.4,1) forwards;
}
.skill-bg-gold::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    conic-gradient(from 0deg at 50% 50%,
      rgba(255,217,61,.8) 0deg, transparent 14deg,
      rgba(255,248,170,.7) 28deg, transparent 42deg,
      rgba(255,217,61,.8) 56deg, transparent 70deg,
      rgba(255,248,170,.7) 84deg, transparent 98deg,
      rgba(255,217,61,.8) 112deg, transparent 126deg,
      rgba(255,248,170,.7) 140deg, transparent 154deg,
      rgba(255,217,61,.8) 168deg, transparent 182deg,
      rgba(255,248,170,.7) 196deg, transparent 210deg,
      rgba(255,217,61,.8) 224deg, transparent 238deg,
      rgba(255,248,170,.7) 252deg, transparent 266deg,
      rgba(255,217,61,.8) 280deg, transparent 294deg,
      rgba(255,248,170,.7) 308deg, transparent 322deg,
      rgba(255,217,61,.8) 336deg, transparent 350deg);
  opacity: 0;
  mix-blend-mode: screen;
  animation: diamondRays 2.4s ease-out forwards;
}
@keyframes diamondShatter {
  0%   { transform: translate(-50%,-50%) scale(0)   rotate(0deg);   opacity: 0; }
  12%  { transform: translate(-50%,-50%) scale(0.9) rotate(15deg);  opacity: 1; }
  20%  { transform: translate(-50%,-50%) scale(1.3) rotate(-10deg); opacity: 1; }
  28%  { transform: translate(-50%,-50%) scale(1.0) rotate(25deg);  opacity: 1; }
  36%  { transform: translate(-50%,-50%) scale(1.4) rotate(-20deg); opacity: 1; }
  46%  { transform: translate(-50%,-50%) scale(1.05) rotate(35deg); opacity: 1; }
  56%  { transform: translate(-50%,-50%) scale(1.7)  rotate(-25deg); opacity: 1;
         filter: drop-shadow(0 0 60px #fff) drop-shadow(0 0 120px #ffd93d) brightness(1.8); }
  62%  { transform: translate(-50%,-50%) scale(2.6)  rotate(10deg);  opacity: .9;
         filter: drop-shadow(0 0 100px #fff) brightness(2.4); }
  72%  { transform: translate(-50%,-50%) scale(3.5)  rotate(60deg);  opacity: .5; }
  100% { transform: translate(-50%,-50%) scale(5.0)  rotate(120deg); opacity: 0;
         filter: drop-shadow(0 0 0 #fff) blur(10px); }
}
@keyframes diamondRays {
  0%   { opacity: 0; transform: scale(.4) rotate(0deg); }
  55%  { opacity: 0; transform: scale(.6) rotate(40deg); }
  62%  { opacity: 1; transform: scale(1.4) rotate(80deg); }
  78%  { opacity: .8; transform: scale(1.8) rotate(180deg); }
  100% { opacity: 0; transform: scale(2.4) rotate(320deg); }
}

/* ---------- Responsive ---------- */
@media (max-height: 700px) {
  #top-bar { height: 54px; }
  #card-bar { height: 76px; }
  #tower-zone { flex: 0 0 34%; }
  .game-title { font-size: 38px; }
  /* ✦ 仅压缩上下 padding，左右保持 36px 让糖果柱与棋盘维持合理距离 */
  #match-zone { padding: 8px 36px 10px; }
}
@media (max-height: 600px) {
  #top-bar { height: 48px; }
  #card-bar { height: 64px; }
  #tower-zone { flex: 0 0 32%; }
  #match-zone { padding: 6px 36px 8px; }
  #signature { height: 14px; line-height: 14px; font-size: 9px; }
}

/* ✦ 超矮屏（高度极小，如 iPhone SE 横置 / 小折叠屏） */
@media (max-height: 520px) {
  #top-bar  { height: 44px; }
  #card-bar { height: 58px; padding: 4px 6px; gap: 5px; }
  #tower-zone { flex: 0 0 30%; }
  #match-zone { padding: 4px 32px 6px; }
  .card-icon { font-size: 22px; width: 24px; height: 24px; }
  .card-name { font-size: 9px; letter-spacing: 1px; }
  .stat-block { height: 32px; padding: 0 8px; font-size: 12px; }
  .stat-block .icon { font-size: 16px; }
  #settings-btn { width: 32px; height: 32px; font-size: 18px; }
}

/* ✦ 超窄屏（≤375px，iPhone SE / Mini） */
@media (max-width: 375px) {
  #top-bar { padding: 0 6px; gap: 4px; }
  .stat-block { padding: 0 7px; gap: 5px; font-size: 12px; }
  .stat-block .icon { font-size: 18px; }
  .hp-block { max-width: 150px; padding: 0 8px; }
  .bar-wrap { height: 16px; }
  .bar-text { font-size: 10px; line-height: 16px; }
  #settings-btn { width: 34px; height: 34px; font-size: 18px; flex-shrink: 0; }
  #card-bar { padding: 6px 6px; gap: 5px; }
  .card-icon { font-size: 22px; width: 24px; height: 24px; }
  .card-name { font-size: 10px; letter-spacing: 0.5px; }
  /* ✦ 棋盘大小不变：糖果柱保持 24px（略收 4px 给小屏让点空间），
     仅调整 #match-zone 左右 padding 让棋盘距屏幕边缘合理 */
  #match-zone::before,
  #match-zone::after { width: 24px; }
  #match-zone { padding: 8px 30px 10px; }
  /* combo 文字进一步缩小，确保在两根糖果柱之间不溢出 */
  #combo-display {
    font-size: clamp(16px, 5.2vw, 24px);
    max-width: calc(100% - 50px);
    left: 50%;
    width: max-content;
  }
}

/* ✦ 极窄屏（≤320px，老款 iPhone SE 第一代） */
@media (max-width: 320px) {
  #top-bar { padding: 0 4px; gap: 3px; }
  .stat-block { padding: 0 5px; gap: 3px; font-size: 11px; height: 36px; }
  .stat-block .icon { font-size: 15px; }
  .hp-block { max-width: 130px; }
  .wave-block, .score-block { padding: 0 6px; }
  #settings-btn { width: 30px; height: 30px; font-size: 16px; }
  #card-bar { padding: 5px 4px; gap: 4px; }
  .card-icon { font-size: 20px; width: 22px; height: 22px; }
  .card-name { font-size: 9px; }
  /* ✦ 棋盘大小不变，糖果柱进一步收窄到 18px，padding 收到 22px */
  #match-zone::before,
  #match-zone::after { width: 18px; }
  #match-zone { padding: 6px 22px 8px; }
}

/* ✦ 横屏（landscape）—— 整体压扁，避免棋盘超出屏外 */
@media (orientation: landscape) and (max-height: 500px) {
  #top-bar  { height: 40px; }
  #card-bar { height: 54px; padding: 4px 8px; gap: 5px; }
  #tower-zone { flex: 0 0 28%; }
  /* ✦ 左右 padding 给糖果柱让位，棋盘自身大小不变 */
  #match-zone { padding: 4px 32px 6px; }
  .card-icon { font-size: 20px; width: 22px; height: 22px; }
  .card-name { font-size: 9px; }
  #combo-display { font-size: clamp(14px, 4vw, 22px); top: 4px; }
  .stat-block { height: 30px; padding: 0 8px; font-size: 11px; }
  .stat-block .icon { font-size: 14px; }
}

/* ===========================================================
   ✦ 4 连合成的特殊宝石（line-h / line-v）箭头剪影 + 弹性脉动
   - 箭头剪影：把 emoji 字符 ↔ / ↕ 渲染成"纯白剪影 + 蓝色发光描边"
     （配合 4 连特殊宝石的高级感，从普通彩色 emoji 升级为单色剪影）
   - 弹性脉动：宝石本身（emoji span）做 1 秒循环动画
       0%   → scale(1)
       30%  → scale(1.30)   ← 放大 130%
       65%  → scale(0.90)   ← 压缩 90%
       100% → scale(1)      ← 回弹 100%
     使用 cubic-bezier 实现"果冻"质感，不影响 .cell 自身的拖拽 / 爆裂 transform
   =========================================================== */
.cell[data-special="line-h"] > span,
.cell[data-special="line-v"] > span {
  /* 1) 强化"剪影"质感：纯白主体 + 浅蓝发光 + 黑色细描边 */
  color: #ffffff !important;
  text-shadow:
    0 0 2px #ffffff,
    0 0 6px rgba(255,255,255,.85),
    0 0 12px var(--gem-glow, #79d4ff),
    0 0 20px var(--gem-glow, #79d4ff),
    0 1px 2px rgba(0,0,0,.55) !important;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.5));

  /* 2) 弹性脉动循环（1 秒一周期） */
  display: inline-block;          /* 保证 transform 生效 */
  transform-origin: 50% 50%;
  animation: lineGemPulse 1s cubic-bezier(.34,1.56,.64,1) infinite;
  will-change: transform;
}

@keyframes lineGemPulse {
  0%   { transform: scale(1);    }
  30%  { transform: scale(1.30); }   /* 放大到 130% */
  65%  { transform: scale(0.90); }   /* 压缩到 90% */
  100% { transform: scale(1);    }   /* 回弹到 100% */
}

/* 爆裂瞬间（special-burst）由 .cell 整体 scale，
   此时让内部脉动暂停，避免两套 transform 叠加打架 */
.cell.special-burst[data-special="line-h"] > span,
.cell.special-burst[data-special="line-v"] > span {
  animation: none !important;
  transform: scale(1);
}