/* ============ 东方逆转 极简演示 样式 · 幻想乡自然风景淡绿主题 ============ */
:root {
  --bg0: #e7f2db;
  --bg1: #d8e9c9;
  --bg2: #c3dcb0;
  --panel: rgba(255, 255, 255, 0.6);
  --line: rgba(96, 132, 92, 0.3);
  --txt: #2e4527;
  --dim: #64805c;
  --accent: #c99400;
  --accent2: #e0a316;
  --blue: #2e7bd6;
  --red: #d04848;
  --green: #1f9d5c;
  --purple: #8a5ad6;

  /* ---------- 表面 / 墨色梯级（白色与黑色按透明度分档） ----------
     用法：面板、卡片、浮层底 → --surf-*；投影、遮罩、深色字底 → --ink-*。
     ⚠️ 档位名 = 透明度（--surf-85 = rgba(255,255,255,.85)）：改档位只需改这一行，正文不再写死 rgba。
     新增取色优先复用现有档位；确实需要新档位时在这里补一行。 */
  --surf-96: rgba(255, 255, 255, .96); --surf-95: rgba(255, 255, 255, .95); --surf-93: rgba(255, 255, 255, .93);
  --surf-92: rgba(255, 255, 255, .92); --surf-9: rgba(255, 255, 255, .9);   --surf-88: rgba(255, 255, 255, .88);
  --surf-85: rgba(255, 255, 255, .85); --surf-84: rgba(255, 255, 255, .84); --surf-82: rgba(255, 255, 255, .82);
  --surf-8: rgba(255, 255, 255, .8);   --surf-78: rgba(255, 255, 255, .78); --surf-75: rgba(255, 255, 255, .75);
  --surf-74: rgba(255, 255, 255, .74); --surf-72: rgba(255, 255, 255, .72); --surf-7: rgba(255, 255, 255, .7);
  --surf-68: rgba(255, 255, 255, .68); --surf-66: rgba(255, 255, 255, .66); --surf-65: rgba(255, 255, 255, .65);
  --surf-62: rgba(255, 255, 255, .62); --surf-6: rgba(255, 255, 255, .6);   --surf-55: rgba(255, 255, 255, .55);
  --surf-5: rgba(255, 255, 255, .5);   --surf-46: rgba(255, 255, 255, .46); --surf-42: rgba(255, 255, 255, .42);
  --surf-4: rgba(255, 255, 255, .4);   --surf-38: rgba(255, 255, 255, .38); --surf-35: rgba(255, 255, 255, .35);
  --surf-34: rgba(255, 255, 255, .34); --surf-3: rgba(255, 255, 255, .3);   --surf-28: rgba(255, 255, 255, .28);
  --surf-25: rgba(255, 255, 255, .25); --surf-22: rgba(255, 255, 255, .22); --surf-2: rgba(255, 255, 255, .2);
  --surf-18: rgba(255, 255, 255, .18); --surf-15: rgba(255, 255, 255, .15); --surf-14: rgba(255, 255, 255, .14);
  --surf-12: rgba(255, 255, 255, .12); --surf-10: rgba(255, 255, 255, .1);  --surf-9l: rgba(255, 255, 255, .09);
  --surf-8l: rgba(255, 255, 255, .08); --surf-6l: rgba(255, 255, 255, .06); --surf-5l: rgba(255, 255, 255, .05);

  --ink-92: rgba(0, 0, 0, .92); --ink-9: rgba(0, 0, 0, .9);   --ink-85: rgba(0, 0, 0, .85);
  --ink-8: rgba(0, 0, 0, .8);   --ink-78: rgba(0, 0, 0, .78); --ink-7: rgba(0, 0, 0, .7);
  --ink-62: rgba(0, 0, 0, .62); --ink-6: rgba(0, 0, 0, .6);   --ink-55: rgba(0, 0, 0, .55);
  --ink-5: rgba(0, 0, 0, .5);   --ink-45: rgba(0, 0, 0, .45); --ink-4: rgba(0, 0, 0, .4);
  --ink-35: rgba(0, 0, 0, .35); --ink-3: rgba(0, 0, 0, .3);   --ink-25: rgba(0, 0, 0, .25);
  --ink-12: rgba(0, 0, 0, .12); --ink-5l: rgba(0, 0, 0, .05); --ink-2: rgba(0, 0, 0, .02);

  /* ---------- 语义色 ---------- */
  --up: #4ade8f;                        /* 卡面数值上升（迷你卡战力 / 手牌战力 / chip 数字） */
  --down: #ff6d6d;                      /* 卡面数值下降 */
  --dim2: #78906f;                      /* 三级文字（比 --dim 更淡） */
  --hint: #6f8a68;                      /* 页脚 / 提示小字 */
  --up-ink: #8a6500;                    /* 浅底上“变好”的深金字 */
  --down-ink: #e03131;                  /* 浅底上“变差”的红字 */
  --border: rgba(108, 148, 100, .35);   /* 通用绿描边 */
  --border-2: rgba(108, 148, 100, .32); /* 通用绿描边（淡一档） */
  --frame: rgba(126, 168, 118, .55);    /* 面板 / 弹窗外框 */
  --shadow-green: rgba(46, 78, 40, .3); /* 面板抬起投影 */
  --gold-95: rgba(242, 201, 76, .95);   /* 高亮 / 可移动描边 */
  --gold-9: rgba(242, 201, 76, .9);     /* 高亮（淡一档） */

  /* ---------- 圆角梯级（正文只用这 7 档） ---------- */
  --r-1: 8px; --r-2: 10px; --r-3: 12px; --r-4: 14px; --r-5: 16px; --r-6: 18px; --r-pill: 999px;

  /* ---------- 地形主题变量的兜底值 ----------
     各地形在自己的 `.location.<id> { … }` 调色板里覆盖这些变量，正文只由那 7 条公共规则读它们。
     这里的值是「该地形没声明该项时的默认」，取自 .location 基底与 .location .loc-effect 的既有取值。 */
  --locbg: rgba(255, 255, 255, .6);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: inherit; --locheadline: var(--surf-28);
  --locmid: inherit; --locmidline: rgba(108, 142, 100, .3);
  --locopp: rgba(202, 228, 252, .22); --locoppline: rgba(108, 142, 100, .3);
  --loczone: linear-gradient(180deg, rgba(255, 218, 120, .16), transparent 70%);
  --locink: var(--locink-light); --locguide: rgba(96, 132, 92, .3); --locquad: rgba(120, 152, 108, .18);
  /* 地形效果文字的两个对比色：浅底用深墨、深底用近白（各地形按 --locmid 亮度二选一，见各调色板） */
  --locink-light: #1a1f2e; --locink-dark: #ffffff;

  /* ---------- z-index 阶梯（自下而上；组件内部的小层级 0~6 仍直写数字） ----------
     卡面内部叠层（图片 < 角标 < 遮罩 < 卡名 < 封印 ❗…）刻意保持 0~6 这几个小值不动；
     跨组件的层级一律走这里的变量，新增浮层请在对应区段取号，不要再写字面值。 */
  --z-corner: 30;        /* 左下 / 右下常驻操作按钮 */
  --z-screen-deck: 45;   /* 卡组设置页整页 */
  --z-deck-toast: 46;    /* 卡组页顶部提示条（须盖住卡组页自身） */
  --z-modal: 50;         /* 全部 .modal-mask 弹窗（同一层，靠 DOM 顺序决定先后） */
  --z-challenge: 58;     /* 挑战码弹窗（须盖住其它弹窗） */
  --z-zoom: 60;          /* 卡牌放大查看 */
  --z-screen-home: 200;  /* 主页面整页 */
  --z-home-modal-battle: 210;   /* 主页面流程上的出战卡组选择 */
  --z-home-modal-settings: 211; /* 设置 */
  --z-home-modal: 212;          /* 挑战码 / 新手引导 / 联机房间（三者同层，按 DOM 顺序） */
  --z-home-modal-codex: 213;    /* 图鉴 */
  --z-home-modal-zoom: 214;     /* 卡牌放大 */
  --z-home-modal-net: 215;      /* 联机相关（最高的一层主页面弹窗） */
  --z-fx-energy-star: 9400;     /* 以下为全屏演出层，恒在最上层 */
  --z-fx-energy-pop: 9410;
  --z-fx-cost: 9500;
  --z-fx-discard: 9510;
  --z-fx-gs: 9520;
  --z-fx-gs-note: 9525;
  --z-fx-peer-gone: 9700;       /* 掉线提示：压过一切 */
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

body {
  font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
  /* 幻想乡的自然光：暖阳穿过晨雾，草地与远山 */
  background:
    radial-gradient(1100px 620px at 12% -6%, rgba(255, 248, 205, .85), transparent 60%),
    radial-gradient(900px 520px at 105% 4%, rgba(208, 240, 255, .6), transparent 60%),
    radial-gradient(1200px 820px at 55% 118%, rgba(146, 216, 150, .5), transparent 65%),
    linear-gradient(168deg, #eef5df 0%, #dbeccf 45%, #d1e6bf 100%);
  color: var(--txt);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  user-select: none;
}

/* ---------- 顶部 ---------- */
.topbar {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 10px 20px;
  background: linear-gradient(180deg, var(--surf-85), var(--surf-42));
  border-bottom: 1px solid rgba(104, 140, 96, .3);
  flex-wrap: wrap;
}
/* 「⚡ 东方逆转」＝返回主页面的入口（原来那格「← 主页」按钮已去掉，顶栏省一格） */
.brand { display: flex; align-items: center; gap: 10px; cursor: pointer; transition: opacity .15s, transform .12s; }
.brand:hover { opacity: .82; }
.brand:active { transform: scale(.98); }
.brand .logo { font-size: 30px; filter: drop-shadow(0 0 8px rgba(214, 166, 20, .55)); }
.brand h1 { font-size: 20px; letter-spacing: 2px; color: var(--txt); }
.brand .sub { font-size: 11px; color: var(--dim); }

.hud { display: flex; gap: 10px; margin-left: auto; align-items: center; }
/* 顶栏右侧一组：赌注 + 加倍（手机端整组贴第一行最右，桌面端仍与 HUD 同排） */
.hud-right { display: flex; align-items: center; gap: 10px; }
.hud-item {
  background: var(--surf-66);
  border: 1px solid var(--border);
  border-radius: var(--r-2);
  padding: 4px 12px;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.hud-label { font-size: 11px; color: var(--dim); }
.hud-value { font-size: 20px; font-weight: 700; }
.hud-unit { font-size: 11px; color: var(--dim); }
/* 回合数带标签显示（「回合：1/6」）：其他 HUD 标签在手机上会隐藏，只有它保留文字 */
.hud-turn-label { font-size: 12px; font-weight: 800; color: var(--txt); letter-spacing: .5px; }
.hud-item.cubes .cube {
  font-size: 20px; font-weight: 800; color: #a97e00;
  text-shadow: 0 0 8px rgba(255, 200, 0, .35);
}
.cube-pips { display: flex; gap: 2px; align-items: center; }
.cube-pips span { width: 7px; height: 7px; border-radius: 50%; background: rgba(120, 152, 108, .4); }
.cube-pips span.on { background: #c99400; box-shadow: 0 0 6px rgba(201, 148, 0, .55); }

.top-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* 按钮文案＝图标(.bt-ico) + 文字(.bt-txt) 两段：≤700px 只显示图标，两者之间的空隙由这里的
   margin 给出（与 .deck-top-actions 同款做法） */
.top-actions .bt-ico { margin-right: 4px; }
/* v144：开发调试「切换立场」激活态（落牌进敌方） */
.top-actions #btnSwitchSide.side-enemy {
  background: #5a2a2a;
  color: #ffe8e8;
  border-color: #a05050;
}

.btn {
  border: 1px solid rgba(108, 148, 100, .4);
  background: var(--surf-66);
  color: var(--txt);
  border-radius: var(--r-1);
  padding: 7px 14px;
  font-size: 13px;
  cursor: pointer;
  transition: transform .08s, background .2s, border-color .2s, color .2s;
}
.btn:hover:not(:disabled) { background: var(--surf-95); border-color: rgba(124, 168, 110, .6); }
.btn:active:not(:disabled) { transform: scale(.96); }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn-snap {
  background: linear-gradient(135deg, #c2271d, #ff5d2e);
  border-color: #ffb36b;
  font-weight: 700; color: #fff;
  text-shadow: 0 1px 2px var(--ink-4);
}
.btn-snap:hover:not(:disabled) { background: linear-gradient(135deg, #e03a1f, #ff7a3c); }
.btn-danger { border-color: rgba(208, 72, 72, .5); color: #d04848; }
.btn-danger:hover:not(:disabled) { background: rgba(255, 230, 230, .9); }
.btn-ghost { opacity: .8; }
.btn-primary {
  background: linear-gradient(135deg, #e0a316, #f4c948);
  color: #3d2c00; font-weight: 700; border: none;
  padding: 10px 26px; font-size: 15px; border-radius: var(--r-2);
}

/* ---------- 布局 ---------- */
.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  grid-template-rows: minmax(0, 1fr);
  gap: 14px;
  padding: 14px 18px;
  flex: 1;
  min-height: 0;
}
@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; grid-template-rows: auto; }
  .side { order: 2; }
}

.board-wrap { display: flex; flex-direction: column; gap: 10px; min-width: 0; min-height: 0; }

/* 场地：撑满左侧可用空间（原日志栏让出的高度） */
.board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: minmax(0, 1fr);
  gap: 12px;
  flex: 1;
  min-height: 430px;
}
@media (max-width: 640px) {
  .board { grid-template-columns: 1fr; grid-template-rows: auto; }
}

/* ---------- 区域（草木色透光面板） ---------- */
.location {
  background: linear-gradient(180deg, var(--surf-84), rgba(244, 250, 235, .55));
  border: 1px solid rgba(122, 168, 116, .42);
  border-radius: var(--r-4);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  box-shadow: 0 3px 12px rgba(84, 122, 74, .14);
  transition: border-color .3s, box-shadow .3s, background .3s;
  position: relative;
}
.location.mansion  { border-color: rgba(202, 152, 30, .6); }
.location.slot2     { border-color: rgba(138, 112, 206, .55); }
.location.rainbow   { border-color: rgba(196, 150, 72, .6); }
.location.cucumber  { border-color: rgba(120, 176, 96, .55); }
.location.dragon    { border-color: rgba(88, 176, 198, .6); }
.location.lake      { border-color: rgba(116, 168, 224, .6); }
.location.needle    { border-color: rgba(168, 132, 214, .6); }
.location.tanabata  { border-color: rgba(196, 108, 150, .55); }
.location.underworld { border-color: rgba(108, 120, 140, .6); }
.location.reactor   { border-color: rgba(255, 122, 72, .6); }
.location.geyser    { border-color: rgba(47, 143, 136, .6); }
.location.terakoya  { border-color: rgba(168, 118, 60, .6); }
.location.komakusa  { border-color: rgba(226, 186, 84, .65); }
.location.dicetable { border-color: rgba(214, 180, 92, .6); }
.location.ghostmansion { border-color: rgba(150, 190, 215, .55); }
.location.concert      { border-color: rgba(255, 122, 196, .6); }
.location.magicstorm   { border-color: rgba(96, 200, 220, .6); }
.location.barrier      { border-color: rgba(111, 154, 138, .6); }
.location.dormouse     { border-color: rgba(143, 131, 184, .6); }
.location.fairyshrine  { border-color: rgba(207, 95, 74, .6); }
.location.sealingclub  { border-color: rgba(196, 150, 255, .6); }
.location.yukarihouse  { border-color: rgba(214, 180, 255, .62); }
.location.houraipharmacy { border-color: rgba(64, 176, 140, .55); }
.location.calmsea      { border-color: rgba(79, 168, 200, .6); }
.location.dharma       { border-color: rgba(120, 120, 138, .65); }
.location.falsemoon    { border-color: rgba(201, 196, 232, .65); }
.location.moriyashrine { border-color: rgba(120, 200, 130, .6); }
/* 聚变反应炉：暗红色为主的主题底 */
/* ---------- 地形主题的公共形态（新增地形只需补一条 .location.<id> 调色板） ----------
   每个地形只声明一组 --loc* 变量，下面几条规则把它们铺到各部件上：
     .loc-head 头部带 / .loc-mid 中间带 / .zone.opp 对手半场 / .zone.player-zone 自己半场
     / .loc-effect 效果文字 / .cell-guide 空格引导线 / .slot-row.quad::before 格位底纹
   ⚠️ 深底浅字的主题必须同时给 --locink；各变量的兜底值见 :root 段末尾的 --loc* 定义。 */
.location .loc-head { background: var(--lochead); border-bottom-color: var(--locheadline); }
.location .loc-mid { background: var(--locmid); border-bottom-color: var(--locmidline); }
.location .zone.opp { background: var(--locopp); border-bottom-color: var(--locoppline); }
.location .zone.player-zone { background: var(--loczone); }
.location .loc-effect { color: var(--locink); }
/* 底色深浅各半（上半深、下半浅）的这两处地形：效果文字跨在两色之间，
   单靠白字或黑字都读不清 ⇒ 给文字条垫一层薄底衬，保证文字始终落在同一亮度上。 */
.location.needle .loc-effect { background: rgba(12, 16, 24, .55); border-radius: var(--r-1); padding: 2px 8px; }
.location.sealingclub .loc-effect { background: rgba(12, 16, 24, .55); border-radius: var(--r-1); padding: 2px 8px; }
.location .cell-guide { border-color: var(--locguide); }
.location .zone .slot-row.quad::before { background: var(--locquad); }

.location.reactor {
  --locbg: linear-gradient(180deg, #47100b 0%, #5c1509 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(130, 32, 18, .92), rgba(96, 20, 10, .86));
  --locheadline: rgba(255, 150, 110, .4);
  --locmid: linear-gradient(180deg, rgba(64, 13, 9, .45), rgba(56, 11, 8, .55));
  --locmidline: rgba(255, 150, 110, .3);
  --locopp: rgba(110, 24, 14, .28);
  --locoppline: rgba(255, 170, 130, .25);
  --loczone: linear-gradient(180deg, rgba(255, 130, 88, .16), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(255, 200, 170, .28);
  --locquad: rgba(255, 190, 160, .22);
}
.location.reactor .loc-name { color: #ffe0cf; }
.location.reactor .slot-count { color: #ffe3d0; background: rgba(58, 12, 8, .78); }

/* 间歇泉：成套青绿水汽主题（主底浅青；边框/表头深青）；
   效果＝每回合结束本区双方已翻开卡牌永久 −1 战力（decay） */
.location.geyser {
  --locbg: #e3f4f2;
  --locborder: #2f8f88;
  --lochead: linear-gradient(180deg, #2f8f88, #1f6f6a);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-72), rgba(214, 240, 237, .58));
  --locmidline: rgba(47, 143, 136, .3);
  --locopp: rgba(47, 143, 136, .10);
  --locoppline: rgba(47, 143, 136, .25);
  --loczone: linear-gradient(180deg, rgba(47, 143, 136, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(47, 143, 136, .4);
  --locquad: rgba(47, 143, 136, .3);
}
.location.geyser .loc-name { color: #ffffff; }
.location.geyser .slot-count { color: #1f625e; background: var(--surf-85); }

/* 寺子屋：成套和纸米色 + 木质棕主题（主底和纸米白；边框/表头木棕）；
   效果＝每回合结束本区双方已翻开卡牌永久 +1 战力（grow，间歇泉的正向镜像） */
.location.terakoya {
  --locbg: #f7efdf;
  --locborder: #a8763c;
  --lochead: linear-gradient(180deg, #a8763c, #87592a);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-74), rgba(243, 230, 206, .6));
  --locmidline: rgba(168, 118, 60, .3);
  --locopp: rgba(168, 118, 60, .10);
  --locoppline: rgba(168, 118, 60, .25);
  --loczone: linear-gradient(180deg, rgba(168, 118, 60, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(168, 118, 60, .4);
  --locquad: rgba(168, 118, 60, .3);
}
.location.terakoya .loc-name { color: #ffffff; }
.location.terakoya .slot-count { color: #7a5320; background: var(--surf-85); }

/* 驹草赌场：暗紫 + 金 的赌场主题（暗底浅字，风格同聚变反应炉）；
   效果＝在此区域翻开的卡牌永久随机 +1 / −1 战力（gamble） */
.location.komakusa {
  --locbg: linear-gradient(180deg, #2a1c41 0%, #3b2657 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(96, 62, 140, .94), rgba(69, 43, 105, .9));
  --locheadline: rgba(240, 208, 122, .45);
  --locmid: linear-gradient(180deg, rgba(58, 36, 92, .55), rgba(44, 27, 71, .68));
  --locmidline: rgba(240, 208, 122, .3);
  --locopp: rgba(88, 56, 138, .3);
  --locoppline: rgba(240, 208, 122, .22);
  --loczone: linear-gradient(180deg, rgba(180, 140, 240, .16), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(240, 208, 122, .3);
  --locquad: rgba(240, 208, 122, .22);
}
.location.komakusa .loc-name { color: #ffeec2; }
.location.komakusa .slot-count { color: #ffeec2; background: rgba(38, 24, 62, .8); }

/* 骰子赌桌：绿呢赌桌 + 金边主题（暗底浅字，风格同驹草赌场/聚变反应炉）；
   效果＝第 4 回合结束时本区所有卡牌各自随机永久 +1 / −1 战力（dice） */
.location.dicetable {
  --locbg: linear-gradient(180deg, #10362a 0%, #1a4c38 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(30, 96, 70, .94), rgba(21, 68, 49, .9));
  --locheadline: rgba(226, 196, 120, .45);
  --locmid: linear-gradient(180deg, rgba(20, 66, 48, .55), rgba(14, 46, 34, .68));
  --locmidline: rgba(226, 196, 120, .3);
  --locopp: rgba(30, 92, 66, .32);
  --locoppline: rgba(226, 196, 120, .22);
  --loczone: linear-gradient(180deg, rgba(150, 226, 180, .14), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(226, 196, 120, .3);
  --locquad: rgba(226, 196, 120, .22);
}
.location.dicetable .loc-name { color: #eaf7e6; }
.location.dicetable .slot-count { color: #eaf7e6; background: rgba(12, 40, 30, .8); }

/* 幽灵洋馆：暗夜石板蓝 + 幽蓝微光主题（暗底浅字）；
   效果＝区域出现时双方各生成 1 张「幽灵」（spawn），幽灵每回合开始会飘走 */
.location.ghostmansion {
  --locbg: linear-gradient(180deg, #1b2230 0%, #2a3345 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(52, 66, 92, .95), rgba(38, 49, 70, .92));
  --locheadline: rgba(178, 214, 236, .4);
  --locmid: linear-gradient(180deg, rgba(38, 48, 68, .55), rgba(26, 34, 50, .68));
  --locmidline: rgba(178, 214, 236, .28);
  --locopp: rgba(120, 160, 195, .14);
  --locoppline: rgba(178, 214, 236, .2);
  --loczone: linear-gradient(180deg, rgba(160, 200, 235, .12), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(178, 214, 236, .26);
  --locquad: rgba(178, 214, 236, .2);
}
.location.ghostmansion .loc-name { color: #dceaf7; }
.location.ghostmansion .slot-count { color: #dceaf7; background: rgba(18, 24, 36, .8); }

/* 演唱会：暗紫舞台 + 霓虹粉主题（暗底浅字）；
   效果＝第 5 回合结束时本区双方所有已翻开卡牌永久 +2 战力（rally） */
.location.concert {
  --locbg: linear-gradient(180deg, #3a1440 0%, #5a1a52 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(180, 44, 120, .95), rgba(130, 30, 92, .92));
  --locheadline: rgba(255, 190, 226, .45);
  --locmid: linear-gradient(180deg, rgba(120, 30, 92, .5), rgba(80, 20, 66, .62));
  --locmidline: rgba(255, 190, 226, .3);
  --locopp: rgba(200, 60, 140, .22);
  --locoppline: rgba(255, 190, 226, .22);
  --loczone: linear-gradient(180deg, rgba(255, 140, 200, .16), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(255, 190, 226, .3);
  --locquad: rgba(255, 190, 226, .22);
}
.location.concert .loc-name { color: #ffe6f5; }
.location.concert .slot-count { color: #ffe6f5; background: rgba(60, 12, 44, .8); }

/* 魔力风暴：暗青蓝风暴 + 电光青主题（暗底浅字）；
   效果＝在此区域翻开的卡牌，揭示效果结算后被吹到另一个随机区域（gust） */
.location.magicstorm {
  --locbg: linear-gradient(180deg, #14293a 0%, #1d4052 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(38, 92, 116, .95), rgba(26, 68, 88, .92));
  --locheadline: rgba(150, 232, 246, .42);
  --locmid: linear-gradient(180deg, rgba(26, 68, 88, .55), rgba(16, 46, 62, .68));
  --locmidline: rgba(150, 232, 246, .3);
  --locopp: rgba(90, 180, 205, .16);
  --locoppline: rgba(150, 232, 246, .22);
  --loczone: linear-gradient(180deg, rgba(140, 225, 245, .13), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(150, 232, 246, .28);
  --locquad: rgba(150, 232, 246, .2);
}
.location.magicstorm .loc-name { color: #dff6fb; }
.location.magicstorm .slot-count { color: #dff6fb; background: rgba(14, 34, 46, .82); }

/* 幽明结界：清透青玉雾主题（浅底深字，与「冥界」的灰暗主题区分）；
   效果＝每回合结束双方总卡牌数 ≥6 时本区崩塌成「冥界」（collapse） */
.location.barrier {
  --locbg: #e6f0ea;
  --locborder: #6f9a8a;
  --lochead: linear-gradient(180deg, #6f9a8a, #54806f);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-72), rgba(214, 234, 226, .6));
  --locmidline: rgba(111, 154, 138, .3);
  --locopp: rgba(111, 154, 138, .10);
  --locoppline: rgba(111, 154, 138, .25);
  --loczone: linear-gradient(180deg, rgba(111, 154, 138, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(111, 154, 138, .4);
  --locquad: rgba(111, 154, 138, .3);
}
.location.barrier .loc-name { color: #ffffff; }
.location.barrier .slot-count { color: #35604f; background: var(--surf-85); }

/* 睡鼠神祠：淡紫灰「安眠」主题（浅底深字）；
   效果＝此区域双方卡牌都不会被摧毁（prot，与「蕾蒂」同一判定入口） */
.location.dormouse {
  --locbg: #eeeaf6;
  --locborder: #8f83b8;
  --lochead: linear-gradient(180deg, #8f83b8, #6f6497);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-74), rgba(226, 221, 242, .6));
  --locmidline: rgba(143, 131, 184, .3);
  --locopp: rgba(143, 131, 184, .10);
  --locoppline: rgba(143, 131, 184, .25);
  --loczone: linear-gradient(180deg, rgba(143, 131, 184, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(143, 131, 184, .4);
  --locquad: rgba(143, 131, 184, .3);
}
.location.dormouse .loc-name { color: #ffffff; }
.location.dormouse .slot-count { color: #554b7d; background: var(--surf-85); }

/* 妖精神社：奶油底 + 朱红灯笼主题（浅底深字）；
   效果＝区域出现时双方各生成 1 张随机 1 费人物卡（spawn.cost） */
.location.fairyshrine {
  --locbg: #fbeee3;
  --locborder: #cf5f4a;
  --lochead: linear-gradient(180deg, #cf5f4a, #a8462f);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-74), rgba(247, 226, 214, .62));
  --locmidline: rgba(207, 95, 74, .3);
  --locopp: rgba(207, 95, 74, .10);
  --locoppline: rgba(207, 95, 74, .25);
  --loczone: linear-gradient(180deg, rgba(207, 95, 74, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(207, 95, 74, .4);
  --locquad: rgba(207, 95, 74, .3);
}
.location.fairyshrine .loc-name { color: #ffffff; }
.location.fairyshrine .slot-count { color: #8f3a26; background: var(--surf-85); }

/* 秘封俱乐部（v199 新增）：深紫罗兰夜幕 + 星象感（深底浅字）；
   效果＝第 5 回合开始时本区域变成随机另一个地形（xformTurn，并结算其「出现时」效果）
   —— 星点由 ::before 平铺铺在列底，故四个直接子块抬到 z-index 1 之上（口径同「未揭示」列）。 */
.location.sealingclub {
  --locbg: linear-gradient(180deg, #1b1236 0%, #2a1d55 52%, #140d28 100%);
  --locborder: rgba(196, 150, 255, .6);
  --lochead: linear-gradient(180deg, rgba(58, 38, 104, .94), rgba(38, 24, 74, .9));
  --locheadline: rgba(196, 150, 255, .4);
  --locmid: linear-gradient(180deg, rgba(64, 44, 116, .55), rgba(30, 20, 60, .42));
  --locmidline: rgba(150, 120, 210, .35);
  --locopp: var(--surf-6l);
  --locoppline: rgba(196, 150, 255, .22);
  --loczone: linear-gradient(180deg, rgba(140, 110, 220, .10), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(190, 160, 240, .3);
  --locquad: rgba(200, 170, 255, .22);
}
.location.sealingclub > .loc-head,
.location.sealingclub > .loc-mid,
.location.sealingclub > .zone { position: relative; z-index: 1; }
.location.sealingclub::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .85;
  background-image:
    radial-gradient(1.6px 1.6px at 20% 30%, var(--surf-9), transparent 55%),
    radial-gradient(1.2px 1.2px at 70% 15%, rgba(215, 200, 255, .85), transparent 55%),
    radial-gradient(1.8px 1.8px at 45% 75%, var(--surf-8), transparent 55%),
    radial-gradient(1.1px 1.1px at 85% 60%, rgba(200, 225, 255, .8), transparent 55%),
    radial-gradient(1.3px 1.3px at 30% 88%, var(--surf-75), transparent 55%),
    radial-gradient(1px 1px at 60% 45%, rgba(230, 215, 255, .7), transparent 55%);
  background-size: 120px 140px, 160px 110px, 140px 150px, 130px 120px, 150px 130px, 100px 100px;
  background-repeat: repeat;
}
.location.sealingclub .loc-name { color: #f2e9ff; }
.location.sealingclub .slot-count { color: #f2e9ff; background: rgba(30, 18, 58, .82); }

/* 八云紫的家（v200 新增）：深靛紫 + 白色裂隙纹理（深底浅字）；
   效果＝回合结束时双方各从后往前添加 1 张「隙间」（gap，该侧可用格数逐回合 −1）
   —— 裂隙由 ::before 叠在列底，故四个直接子块抬到 z-index 1 之上（口径同「秘封俱乐部」）。 */
.location.yukarihouse {
  --locbg: linear-gradient(180deg, #141a3c 0%, #1d2456 55%, #0e1230 100%);
  --locborder: rgba(214, 180, 255, .62);
  --lochead: linear-gradient(180deg, rgba(44, 40, 96, .9), rgba(28, 26, 68, .86));
  --locheadline: rgba(214, 180, 255, .42);
  --locmid: linear-gradient(180deg, rgba(52, 46, 112, .5), rgba(22, 20, 52, .4));
  --locmidline: rgba(160, 140, 220, .34);
  --locopp: var(--surf-6l);
  --locoppline: rgba(214, 180, 255, .22);
  --loczone: linear-gradient(180deg, rgba(130, 110, 220, .10), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(200, 180, 250, .3);
  --locquad: rgba(205, 190, 255, .22);
}
.location.yukarihouse > .loc-head,
.location.yukarihouse > .loc-mid,
.location.yukarihouse > .zone { position: relative; z-index: 1; }
.location.yukarihouse::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .55;
  background-image:
    linear-gradient(74deg, transparent 47.5%, var(--surf-55) 47.85%, var(--surf-8) 48%, transparent 48.4%),
    linear-gradient(-63deg, transparent 61.5%, rgba(214, 200, 255, .45) 61.85%, var(--surf-65) 62%, transparent 62.45%),
    linear-gradient(87deg, transparent 81.3%, var(--surf-38) 81.7%, transparent 82.15%);
}
.location.yukarihouse .loc-name { color: #f1ecff; }
.location.yukarihouse .slot-count { color: #f1ecff; background: rgba(20, 18, 46, .84); }

/* 蓬莱药局（v201 新增）：米白 + 薄荷绿「药局/处方」主题（浅底深字）；
   效果＝此区域双方所有卡牌都不会被减攻（noDown，负的战力增量一律被拦下） */
.location.houraipharmacy {
  --locbg: linear-gradient(180deg, #f7fbf5 0%, #eaf7ef 55%, #dff2e6 100%);
  --locborder: #40b08c;
  --lochead: linear-gradient(180deg, #4fbd97, #2f8e70);
  --locheadline: var(--surf-35);
  --locmid: linear-gradient(180deg, var(--surf-78), rgba(224, 244, 233, .62));
  --locmidline: rgba(64, 176, 140, .32);
  --locopp: rgba(64, 176, 140, .10);
  --locoppline: rgba(64, 176, 140, .26);
  --loczone: linear-gradient(180deg, rgba(64, 176, 140, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(64, 176, 140, .4);
  --locquad: rgba(64, 176, 140, .28);
}
.location.houraipharmacy .loc-name { color: #ffffff; }
.location.houraipharmacy .slot-count { color: #1f6b52; background: var(--surf-88); }

/* ==================== v202：静海（🌊）+ 区域「抹除文本」（地形字段 mute） ====================
   地形主题：深蓝静水（暗底浅字，与「蓬莱药局」的浅底深字相反）；
   效果＝此区域双方所有卡牌失去卡牌文字（卡面效果一律不发动，离场/换地形即恢复）。
   另外两条是「被抹除」的显示口径：只作用于**放大视图**（场上的牌），图鉴里的静态卡面不变。 */
.location.calmsea {
  --locbg: linear-gradient(180deg, #0b1f2f 0%, #10344a 55%, #0a1c29 100%);
  --locborder: #4fa8c8;
  --lochead: linear-gradient(180deg, #2c6f8f, #1b4c66);
  --locheadline: rgba(160, 224, 255, .35);
  --locmid: linear-gradient(180deg, rgba(18, 52, 74, .78), rgba(10, 30, 44, .72));
  --locmidline: rgba(120, 200, 235, .32);
  --locopp: rgba(79, 168, 200, .10);
  --locoppline: rgba(120, 200, 235, .26);
  --loczone: linear-gradient(180deg, rgba(79, 168, 200, .08), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(120, 200, 235, .38);
  --locquad: rgba(120, 200, 235, .26);
}
.location.calmsea .loc-name { color: #eaf7ff; }
.location.calmsea .slot-count { color: #eaf7ff; background: rgba(8, 26, 40, .82); }
/* 放大视图：文本被抹除的牌 —— 卡面效果文本照常显示（它写的是这张牌原本有什么），失效由详情区那一行状态提示说明 */
.zoom-info .mute-note { color: #1d7fa8; }

/* ==================== 「法界」（🌑 区域「封锁揭示」：地形字段 noReveal） ====================
   地形主题：墨黑（暗底浅字、地名纯白）；
   效果＝本区双方所有卡牌无法触发「揭示」效果（只封揭示，持续 / 时机 / 防护与地形类效果照常；离场 / 换地形即恢复）。
   另一条是「揭示被封锁」的显示口径：只作用于**放大视图**的纯揭示牌（场上靠地形配色区分，与静海同款）。 */
.location.dharma {
  --locbg: linear-gradient(180deg, #0a0a0d 0%, #17171c 55%, #08080a 100%);
  --locborder: rgba(120, 120, 138, .65);
  --lochead: linear-gradient(180deg, #2b2b34, #131317);
  --locheadline: rgba(210, 210, 228, .32);
  --locmid: linear-gradient(180deg, rgba(24, 24, 30, .82), rgba(10, 10, 14, .74));
  --locmidline: rgba(190, 190, 212, .28);
  --locopp: rgba(130, 130, 152, .10);
  --locoppline: rgba(190, 190, 212, .24);
  --loczone: linear-gradient(180deg, rgba(130, 130, 152, .08), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(190, 190, 212, .34);
  --locquad: rgba(190, 190, 212, .22);
}
.location.dharma .loc-name { color: #ffffff; }
.location.dharma .slot-count { color: #ffffff; background: var(--ink-78); }
.zoom-info .noreveal-note { color: #55555f; }

/* ==================== 「封印」（卡牌效果键 mute，卡级**永久**抹除文本）====================
   被封印的牌在**场上 / 手牌 / 三池面板 / 放大视图**四处都叠一个 ❗ 并把艺术区置灰：
   ❗ 只标封印（静海那类区域抹除靠地形配色 + 放大视图里那一行状态提示区分）；卡面效果文本照常显示
   （它写的是这张牌原本有什么），失效由提示行说明 —— 卡面窄，文字另按 .card-face.sealed 置灰划线。
   ⚠️ 只作用于**实例**渲染 —— 图鉴（card-browser）与卡组页（deck-page）按 def 渲染，不显示。 */
.mini-card .mc-seal {
  position: absolute;
  top: 6%; left: 0; right: 0;
  text-align: center;
  font-size: clamp(16px, 2.4vh + .8vw, 32px);
  line-height: 1;
  z-index: 6; /* 压在 .mc-mod(5) / 费用与战力(5) / 卡名(4) / 遮罩(3) / 图片(2) 之上 */
  pointer-events: none;
  text-shadow: 0 2px 10px var(--ink-9), 0 0 16px rgba(255, 96, 96, .55);
}
.mini-card.sealed .mini-img,
.mini-card.sealed .mc-icon { filter: grayscale(1) brightness(.78); }
.mini-card.sealed .mc-name { opacity: .55; }
.hc-seal {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--seal-fs, 30px);
  line-height: 1;
  z-index: 4; /* 压在 .hc-img(2) 之上 */
  pointer-events: none;
  text-shadow: 0 2px 10px var(--ink-9), 0 0 18px rgba(255, 96, 96, .55);
}
.card-face .hc-icon { position: relative; } /* 无图卡的艺术区＝emoji 块，❗ 也要能定位到它正中 */
.card-face.sealed .hc-img,
.card-face.sealed .hc-art .hc-icon,
.card-face.sealed.no-img .hc-icon { filter: grayscale(1) brightness(.78); }
.card-face.sealed .hc-text { opacity: .42; text-decoration: line-through; }
.zoom-info .seal-note { color: #a3541f; }

/* ==================== v203：虚假之月（🌕）+ 区域「延长回合」（地形字段 extraRound） ====================
   地形主题：夜空中的赝品之月 —— 深靛蓝紫夜空 + 银白月晕（与「秘封俱乐部」的紫、「八云紫的家」的
   淡紫刻意区分：本块更暗、更冷、以银白为主）；
   效果＝此地形在场时本局共有第 7 回合（延长机制的口径见 data/locations.js 的 `extraRound=`）。 */
.location.falsemoon {
  --locbg: linear-gradient(180deg, #141a2e 0%, #232a48 52%, #101527 100%);
  --locborder: #c9c4e8;
  --lochead: linear-gradient(180deg, #4a4a78, #2c2c50);
  --locheadline: rgba(226, 222, 255, .38);
  --locmid: linear-gradient(180deg, rgba(38, 42, 72, .8), rgba(20, 23, 42, .74));
  --locmidline: rgba(200, 195, 240, .32);
  --locopp: rgba(180, 176, 235, .10);
  --locoppline: rgba(200, 195, 240, .26);
  --loczone: linear-gradient(180deg, rgba(180, 176, 235, .09), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(208, 202, 250, .38);
  --locquad: rgba(208, 202, 250, .24);
}
.location.falsemoon .loc-name { color: #f4f1ff; }
.location.falsemoon .slot-count { color: #f4f1ff; background: rgba(14, 16, 32, .84); }

/* ==================== v208：守矢神社（🌾）+ 区域「揭示重复触发」（地形字段 repeatReveal） ====================
   地形主题：翠绿神社 —— 深林绿底 + 常青树与注連縄的亮绿（与「迷途竹林」的竹青、「幽明结界」的灰绿
   刻意区分：本块更饱和、更亮，偏“神社境内的常青树”意象）；
   效果＝在此区域翻开的揭示牌，其揭示效果再重复触发一次（口径见 data/locations.js 的 `repeatReveal=`）。 */
.location.moriyashrine {
  --locbg: linear-gradient(180deg, #0d2b1c 0%, #14492e 55%, #0a2116 100%);
  --locborder: #78c882;
  --lochead: linear-gradient(180deg, #2f7a47, #1b5230);
  --locheadline: rgba(190, 240, 190, .38);
  --locmid: linear-gradient(180deg, rgba(20, 73, 46, .8), rgba(10, 33, 22, .74));
  --locmidline: rgba(150, 225, 160, .32);
  --locopp: rgba(120, 200, 130, .10);
  --locoppline: rgba(150, 225, 160, .26);
  --loczone: linear-gradient(180deg, rgba(120, 200, 130, .09), transparent 70%);
  --locink: var(--locink-dark);
  --locguide: rgba(160, 230, 170, .38);
  --locquad: rgba(160, 230, 170, .24);
}
.location.moriyashrine .loc-name { color: #eefbf0; }
.location.moriyashrine .slot-count { color: #eefbf0; background: rgba(8, 30, 18, .82); }

/* ==================== v211：东风谷早苗「揭示再触发」的可见演出 ====================
   早苗每次结算 `retrigger`（她在守矢神社里翻开时结算两次）时：
     ① `.retrigger-ring` —— 早苗卡位上的**淡绿光环扩散**（两圈，外层宽/内层窄）；
     ② `.retrigger-hit-ring` —— 每张被再触发的目标卡上**金白闪光**。
   两个元素都由 js/game.js 的 playRetriggerAura / playRetriggerHit **动态创建到 body 悬浮层**
   （`position:fixed` + 按卡面 getBoundingClientRect 定位，z-index 9450 / 9440、`pointer-events:none`）。
   ⚠️ 为什么不用卡面本体的 `box-shadow`/`transform`：`.mini-card` 自带 `overflow: hidden`（会裁掉外阴影），
   且翻面时挂的 `.played-now`（`flipIn` 关键帧）**同样动 `transform`/`box-shadow`**，会与卡面上的动画打架；
   放 body 悬浮层与 v80 的「+N」绿环（`.gain-ring`）同一路数，**不受重建与裁切影响**，也不会留孤儿节点
   （动画播完由 JS 的 setTimeout 移除）。时长常量在 js/game.js：`RETRIGGER_AURA_MS` / `RETRIGGER_HIT_MS`。 */
.retrigger-ring {
  border: 2px solid rgba(150, 245, 175, .95);
  box-shadow: 0 0 14px rgba(126, 230, 158, .85), inset 0 0 12px rgba(126, 230, 158, .5);
  animation: retriggerRingOut 760ms ease-out forwards;
}
@keyframes retriggerRingOut {
  0%   { transform: scale(.82); opacity: 0; }
  16%  { transform: scale(1.0); opacity: 1; }
  100% { transform: scale(1.0) translateY(0); opacity: 0;
         box-shadow: 0 0 0 var(--rr-grow, 22px) rgba(126, 230, 158, 0), inset 0 0 4px rgba(126, 230, 158, 0);
         border-color: rgba(150, 245, 175, 0); }
}
.retrigger-hit-ring {
  border: 2px solid rgba(255, 224, 140, .95);
  box-shadow: 0 0 16px rgba(255, 214, 106, .9), inset 0 0 10px rgba(255, 214, 106, .45);
  animation: retriggerHitRing 420ms ease-out forwards;
}
@keyframes retriggerHitRing {
  0%   { transform: scale(1.14); opacity: 0; }
  22%  { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 0;
         box-shadow: 0 0 26px 8px rgba(255, 214, 106, 0); border-color: rgba(255, 224, 140, 0); }
}

/* 辉针城：反转区意象——上下各半（上黑下白） */
.location.needle {
  --locbg: linear-gradient(180deg, #191a20 0%, #20222b 49.9%, #f5f5ee 50.1%, #ffffff 100%);
  --locborder: rgba(126, 168, 118, .55);
  --lochead: linear-gradient(180deg, rgba(30, 32, 42, .97), rgba(22, 23, 30, .94));
  --locheadline: rgba(215, 215, 225, .4);
  --locmid: linear-gradient(180deg, rgba(32, 34, 46, .5), rgba(120, 122, 136, .28));
  --locmidline: rgba(150, 152, 168, .35);
  --locopp: rgba(28, 30, 40, .55);
  --locoppline: var(--surf-22);
  --loczone: rgba(28, 30, 40, .5);
  --locink: var(--locink-dark);
  --locguide: rgba(120, 122, 140, .35);
  --locquad: rgba(120, 122, 145, .3);
}
.location.needle .loc-name { color: #eef0f8; }
.location.needle .loc-effect { text-shadow: 0 1px 2px var(--ink-25); }

/* 冥界：成套浅灰主题（主底浅灰；边框/表头深灰） */
.location.underworld {
  --locbg: #e4e5e3;
  --locborder: #6c7076;
  --lochead: linear-gradient(180deg, #5a5e66, #484c54);
  --locheadline: var(--surf-25);
  --locmid: linear-gradient(180deg, var(--surf-65), rgba(235, 236, 234, .5));
  --locmidline: rgba(108, 112, 118, .3);
  --locopp: rgba(108, 112, 118, .12);
  --locoppline: rgba(108, 112, 118, .25);
  --loczone: linear-gradient(180deg, rgba(108, 112, 118, .08), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(108, 112, 118, .4);
  --locquad: rgba(108, 112, 118, .35);
}
.location.underworld .loc-name { color: #ffffff; }
.location.underworld .slot-count { color: #4a4e55; background: var(--surf-85); }

/* 雾之湖：成套浅蓝主题（主底浅蓝；边框/表头深蓝） */
.location.lake {
  --locbg: #e8f3fb;
  --locborder: #2f6fa8;
  --lochead: linear-gradient(180deg, #2f6fa8, #24598f);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-7), rgba(224, 240, 252, .55));
  --locmidline: rgba(47, 111, 168, .3);
  --locopp: rgba(47, 111, 168, .10);
  --locoppline: rgba(47, 111, 168, .25);
  --loczone: linear-gradient(180deg, rgba(47, 111, 168, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(47, 111, 168, .4);
  --locquad: rgba(47, 111, 168, .3);
}
.location.lake .loc-name { color: #ffffff; }
.location.lake .slot-count { color: #2d5f8e; background: var(--surf-85); }

/* 迷途竹林：中等明暗绿色纯色主题 */
.location.slot2 {
  --locbg: #9fcb90;
  --locborder: #4d7a3a;
  --lochead: linear-gradient(180deg, #4d7a3a, #3d652c);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-5), rgba(215, 236, 200, .45));
  --locmidline: rgba(77, 122, 58, .35);
  --locopp: var(--surf-10);
  --locoppline: rgba(77, 122, 58, .3);
  --loczone: linear-gradient(180deg, var(--surf-12), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(77, 122, 58, .5);
  --locquad: var(--surf-4);
}
.location.slot2 .loc-name { color: #ffffff; }
.location.slot2 .slot-count { color: #2f5520; background: var(--surf-85); }

/* 红魔馆：纯淡红主题（浅红主底 + 深红边框/表头） */
.location.mansion {
  --locbg: #f5dbd5;
  --locborder: #a23a33;
  --lochead: linear-gradient(180deg, #a23a33, #8a2e28);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-6), rgba(250, 220, 212, .5));
  --locmidline: rgba(162, 58, 51, .3);
  --locopp: rgba(162, 58, 51, .09);
  --locoppline: rgba(162, 58, 51, .25);
  --loczone: linear-gradient(180deg, rgba(162, 58, 51, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(162, 58, 51, .35);
  --locquad: rgba(162, 58, 51, .25);
}
.location.mansion .loc-name { color: #ffffff; }
.location.mansion .slot-count { color: #8a2e28; background: var(--surf-85); }

/* 虹龙洞：淡黄纯色主题（浅黄主底 + 金黄/棕深色边框与表头） */
.location.rainbow {
  --locbg: #f7edc6;
  --locborder: #b78a30;
  --lochead: linear-gradient(180deg, #b78a30, #9c711f);
  --locheadline: var(--surf-3);
  --locmid: linear-gradient(180deg, var(--surf-55), rgba(246, 236, 190, .5));
  --locmidline: rgba(183, 138, 48, .32);
  --locopp: rgba(183, 138, 48, .10);
  --locoppline: rgba(183, 138, 48, .26);
  --loczone: linear-gradient(180deg, rgba(183, 138, 48, .08), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(183, 138, 48, .4);
  --locquad: rgba(183, 138, 48, .3);
}
.location.rainbow .loc-name { color: #ffffff; }
.location.rainbow .slot-count { color: #7a5b0a; background: var(--surf-85); }

/* 黄瓜田：淡绿色主题（浅绿主底 + 草绿边框/表头） */
.location.cucumber {
  --locbg: #e8f5df;
  --locborder: #6aa84f;
  --lochead: linear-gradient(180deg, #6aa84f, #558a3f);
  --locheadline: var(--surf-3);
  --locmid: linear-gradient(180deg, var(--surf-6), rgba(228, 242, 216, .55));
  --locmidline: rgba(106, 168, 79, .32);
  --locopp: rgba(106, 168, 79, .10);
  --locoppline: rgba(106, 168, 79, .26);
  --loczone: linear-gradient(180deg, rgba(106, 168, 79, .08), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(106, 168, 79, .4);
  --locquad: rgba(106, 168, 79, .3);
}
.location.cucumber .loc-name { color: #ffffff; }
.location.cucumber .slot-count { color: #3f6b2e; background: var(--surf-85); }

/* 七夕坂：淡粉纯色主题（浅粉主底 + 深粉边框/表头） */
.location.tanabata {
  --locbg: #f8e3ea;
  --locborder: #b65f86;
  --lochead: linear-gradient(180deg, #b65f86, #9a4a6e);
  --locheadline: var(--surf-3);
  --locmid: linear-gradient(180deg, var(--surf-6), rgba(248, 222, 232, .55));
  --locmidline: rgba(182, 95, 134, .32);
  --locopp: rgba(182, 95, 134, .10);
  --locoppline: rgba(182, 95, 134, .26);
  --loczone: linear-gradient(180deg, rgba(182, 95, 134, .08), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(182, 95, 134, .4);
  --locquad: rgba(182, 95, 134, .3);
}
.location.tanabata .loc-name { color: #ffffff; }
.location.tanabata .slot-count { color: #a04a70; background: var(--surf-85); }

/* 龙神像：很浅的灰色主题（比冥界 #e4e5e3 更浅）+ 深灰边框/表头 */
.location.dragon {
  --locbg: #f2f2f0;
  --locborder: #8b9097;
  --lochead: linear-gradient(180deg, #6b7078, #545962);
  --locheadline: var(--surf-28);
  --locmid: linear-gradient(180deg, var(--surf-7), rgba(238, 239, 237, .55));
  --locmidline: rgba(139, 144, 151, .3);
  --locopp: rgba(139, 144, 151, .09);
  --locoppline: rgba(139, 144, 151, .25);
  --loczone: linear-gradient(180deg, rgba(139, 144, 151, .07), transparent 70%);
  --locink: var(--locink-light);
  --locguide: rgba(139, 144, 151, .38);
  --locquad: rgba(139, 144, 151, .3);
}
.location.dragon .loc-name { color: #ffffff; }
.location.dragon .slot-count { color: #52575f; background: var(--surf-85); }
/* 未揭示地形（v75）：淡紫灰“未解之谜”底色 + 虚线边框 + 随机散布的地形小图标，
   传达“这一块可能是随机池里任意一种地形”（图标/位置/角度由 JS 开局随机生成）；
   保持浅色底以保证暗牌与卡面可读（见 .unreveal-decor） */
.location.unreveal {
  isolation: isolate;
  background:
    radial-gradient(520px 300px at 12% -8%, rgba(148, 146, 255, .16), transparent 62%),
    radial-gradient(640px 320px at 108% 112%, rgba(214, 148, 255, .12), transparent 60%),
    linear-gradient(180deg, #edeff9 0%, #e4e7f5 48%, #daddf0 100%);
  border: 1px dashed rgba(140, 142, 208, .85);
  box-shadow: 0 3px 14px rgba(96, 100, 176, .18);
}
.location.unreveal > .loc-head,
.location.unreveal > .loc-mid,
.location.unreveal > .zone { position: relative; z-index: 1; }
.location.unreveal .loc-head {
  background: linear-gradient(180deg, rgba(124, 126, 200, .92), rgba(104, 107, 182, .9));
  border-bottom: 1px dashed var(--surf-55);
}
.location.unreveal .loc-name { color: #ffffff; text-shadow: 0 1px 2px rgba(46, 50, 110, .35); }
.location.unreveal .loc-mid {
  background: linear-gradient(180deg, var(--surf-68), rgba(224, 227, 248, .55));
  border-bottom: 1px dashed rgba(138, 140, 200, .5);
}
.location.unreveal .loc-effect { color: #42478a; font-weight: 700; }
.location.unreveal .zone.opp {
  background: rgba(216, 218, 246, .38);
  border-bottom: 1px dashed rgba(138, 140, 200, .4);
}
.location.unreveal .zone.player-zone {
  background: linear-gradient(180deg, var(--surf-46), rgba(226, 229, 250, .2));
}
.location.unreveal .slot-count { color: #3c4172; background: var(--surf-9); }
.location.unreveal .cell-guide { border-color: rgba(150, 152, 208, .5); }
.location.unreveal .zone .slot-row.quad::before { background: rgba(140, 142, 205, .2); }

/* 随机散布的地形小图标层：绝对铺满整列、垫在内容之下、不可交互；缓慢上下漂浮 */
.unreveal-decor {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.unreveal-decor span {
  position: absolute;
  opacity: .24;
  filter: saturate(.3);
  user-select: none;
  pointer-events: none;
  will-change: transform;
  line-height: 1;
  animation: unrevealDrift ease-in-out infinite alternate;
}
@keyframes unrevealDrift {
  0%   { transform: translateY(0) rotate(var(--rot, 0deg)); }
  100% { transform: translateY(-9px) rotate(var(--rot, 0deg)); }
}

/* 未开放区域（minTurn，如七夕坂第 5 回合前）：整体灰色遮罩 */
.location.locked::after {
  content: "🔒";
  position: absolute;
  inset: 0;
  background: rgba(96, 106, 118, .5);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  z-index: 5;
  border-radius: inherit;
  pointer-events: none;
}
/* “每回合可移动一次”的牌（射命丸文）视觉 */
.mini-card.can-fly { outline: 2px dashed var(--gold-95); outline-offset: -2px; cursor: grab; }
.mini-card.fly-moving { box-shadow: 0 0 0 3px var(--gold-95), 0 0 14px rgba(242, 201, 76, .55); }
.mini-card .mc-fly {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 3px;
  background: rgba(255, 238, 150, .96);
  color: #7a5c00;
  font-size: 9px;
  font-weight: 800;
  padding: 0 5px;
  border-radius: 6px;
  z-index: 4;
  white-space: nowrap;
}
.location.hoverable { cursor: pointer; }
/* ---------- v205：区域「已破碎」（天界 `shatter` 摧毁后的列） ----------
   整列被一块损坏面板占据：**看不出原本是哪块地形、没有双方总点数的数字、也没有格位**，
   只写「已破碎」。列 DOM 由 js/game.js 的 renderShatteredColumn 整个换成
   `.location.shattered-loc > .shatter-block`，因此这里不需要（也不该有）.loc-head / .loc-mid / .zone。 */
.location.shattered-loc {
  border-color: rgba(126, 112, 112, .6);
  background:
    repeating-linear-gradient(135deg, rgba(30, 25, 31, .95) 0 11px, rgba(41, 34, 43, .95) 11px 22px);
  box-shadow: inset 0 0 46px var(--ink-62), 0 3px 12px rgba(28, 18, 24, .38);
  overflow: hidden;
}
/* 两道贯穿整列的裂纹 + 一层暗角（纯装饰，不挡任何交互） */
.location.shattered-loc::before,
.location.shattered-loc::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
}
.location.shattered-loc::before {
  background:
    linear-gradient(112deg, transparent 46.2%, var(--surf-22) 47.3%, var(--ink-6) 48.4%, transparent 49.6%),
    linear-gradient(64deg, transparent 59.6%, var(--surf-15) 60.9%, var(--ink-55) 62.2%, transparent 63.4%),
    linear-gradient(155deg, transparent 28%, var(--surf-10) 29.4%, var(--ink-45) 30.6%, transparent 32%);
}
.location.shattered-loc::after {
  background: radial-gradient(circle at 50% 42%, rgba(255, 176, 132, .1), transparent 64%);
}
.shatter-block {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 18px 12px;
  text-align: center;
  cursor: not-allowed;
  user-select: none;
}
.shatter-block .shatter-glyph {
  font-size: 34px;
  line-height: 1;
  filter: grayscale(.45);
  opacity: .92;
}
.shatter-block .shatter-name {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 5px;
  color: #ded0cb;
  text-shadow: 0 1px 0 var(--ink-8), 0 0 14px rgba(255, 120, 76, .26);
}
.shatter-block .shatter-sub {
  font-size: 11.5px;
  letter-spacing: .5px;
  color: rgba(222, 208, 203, .6);
}
@media (max-width: 640px) {
  .shatter-block { gap: 4px; padding: 12px 8px; }
  .shatter-block .shatter-glyph { font-size: 26px; }
  .shatter-block .shatter-name { font-size: 16px; letter-spacing: 3px; }
  .shatter-block .shatter-sub { font-size: 10px; }
}

.loc-head {
  padding: 6px 10px 5px;
  border-bottom: 1px solid rgba(124, 164, 110, .35);
  background: linear-gradient(180deg, rgba(186, 214, 160, .5), rgba(214, 232, 190, .35));
}
.loc-name { font-size: 14px; font-weight: 700; display: flex; justify-content: space-between; align-items: center; color: var(--txt); }
.loc-name .icon { font-size: 15px; }

/* 中间带：对手总点数 → 区域效果 → 己方总点数 */
.loc-mid {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  border-bottom: 1px solid rgba(124, 164, 110, .3);
  background: linear-gradient(180deg, var(--surf-5), rgba(238, 247, 226, .4));
}
.loc-mid .loc-effect {
  margin: 0;
  text-align: center;
  font-size: 12.5px;
  color: var(--dim);
  line-height: 1.35;
  display: flex;
  align-items: center;
  gap: 5px;
}
.loc-mid .loc-effect .le-icon { font-size: 15px; }
/* 总点数横幅：默认蓝色；该区领先的一方亮黄色（由 renderZones 动态加 .lead） */
.loc-total {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 800;
  line-height: 1;
  padding: 3px 16px;
  border-radius: var(--r-pill);
  color: #2c66b0;
  background: rgba(208, 229, 250, .9);
  border: 1px solid rgba(92, 152, 226, .55);
  text-shadow: 0 0 6px rgba(150, 202, 255, .4);
  transition: color .25s, background .25s, border-color .25s, text-shadow .25s, transform .3s ease;
}
/* v85→v86：终局演出——胜方总点数横幅 700ms 放大高亮（金色光晕，结束回落平滑） */
.loc-total.settle-win {
  animation: settleWin .7s ease-out forwards;
}
@keyframes settleWin {
  0%   { transform: scale(1); filter: brightness(1); }
  28%  { transform: scale(1.3); filter: brightness(1.55); box-shadow: 0 0 0 6px rgba(255, 205, 70, .55); }
  62%  { transform: scale(1.1); filter: brightness(1.25); box-shadow: 0 0 0 16px rgba(255, 205, 70, 0); }
  100% { transform: scale(1.2); filter: brightness(1.22); }
}
.loc-total .lt-label { font-size: 11px; font-weight: 700; opacity: .9; }
.loc-total .lt-num { min-width: 30px; text-align: center; font-size: 22px; }
.loc-total .lt-unit { font-size: 11px; opacity: .75; font-weight: 600; }
.loc-total.lead {
  color: #966600;
  background: rgba(255, 238, 165, .95);
  border: 1px solid rgba(222, 160, 20, .75);
  text-shadow: 0 0 8px rgba(255, 205, 60, .6);
}

.zone {
  flex: 1;
  min-height: 118px;
  display: flex;
  flex-direction: column;
  padding: 5px 6px;
  gap: 4px;
  position: relative;
}
.zone.opp { border-bottom: 1px dashed rgba(108, 142, 100, .3); background: rgba(202, 228, 252, .22); }
/* 每个玩家的卡位：固定 2 行 × 2 列、铺满整块区域；第一张永远占左上格，
   后续按 右上 → 左下 → 右下 填空，不会因张数变化而移动已有卡牌 */
.zone .slot-row {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: 5px;
  padding: 1px;
}
.slot-count {
  font-size: 10px; color: var(--dim); position: absolute;
  bottom: 6px; left: 9px; z-index: 3;
  background: var(--surf-8); border-radius: 6px; padding: 0 6px;
}
.zone.player-zone { background: linear-gradient(180deg, rgba(255, 218, 120, .16), transparent 70%); }

/* ---------- 卡牌（桌面上，放大到撑满各自的 1/4 格位） ----------
   ⚠️ 这是**另一套 DOM**（不是 cardFaceHTML 的 .card-face）：满铺立绘 + 暗牌 + 永久加成角标 +
   移动徽标等只在场上出现的东西。角标尺寸走下面这组 --mc-* 变量，断点里只改变量。 */
.mini-card {
  --mc-cost-fs: 14px; --mc-cost-min: 22px;
  --mc-p-fs: 15px; --mc-p-min: 24px;
  --mc-spell-fs: 14px;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  border-radius: var(--r-2);
  background: var(--cgrad);
  color: #fff;
  position: relative;
  font-weight: 700;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 10px 4px 8px;
  text-align: center;
  box-shadow: 0 2px 6px rgba(46, 78, 40, .35), inset 0 0 0 1px var(--surf-18);
  border: 1px solid var(--surf-22);
  transform-origin: center;
  overflow: hidden;
}
/* 大体积卡：占满整侧 2×2 格位（occ>1，如伊吹萃香占满 4 格） */
.mini-card.big-occ {
  grid-column: 1 / -1;
  grid-row: 1 / -1;
  border-radius: var(--r-3);
  box-shadow: 0 2px 8px rgba(46, 78, 40, .4), inset 0 0 0 1px var(--surf-3), 0 0 0 3px rgba(242, 201, 76, .35);
}
/* 费用（左上角，白色） */
.mini-card .mc-cost {
  position: absolute; top: 4px; left: 5px;
  min-width: var(--mc-cost-min); text-align: center;
  font-size: var(--mc-cost-fs); font-weight: 800; color: #fff;
  background: var(--ink-5);
  border: 1px solid var(--surf-6);
  border-radius: 6px;
  padding: 0 5px;
  box-shadow: 0 1px 3px var(--ink-5);
  z-index: 2;
}
/* 当前战力（右上角）：与基础威力相同=白，更高=绿，更低=红 */
.mini-card .p {
  position: absolute; top: 4px; right: 5px; left: auto;
  min-width: var(--mc-p-min); padding: 1px 5px; text-align: center;
  font-size: var(--mc-p-fs); border-radius: 6px;
  background: #10131c; border: 1px solid var(--surf-6); color: #fff;
  box-shadow: 0 1px 3px var(--ink-5);
  z-index: 2;
}
.mini-card .p.up { color: var(--up); border-color: var(--up); text-shadow: 0 0 6px rgba(70, 222, 143, .65); }
.mini-card .p.down { color: var(--down); border-color: var(--down); text-shadow: 0 0 6px rgba(255, 109, 109, .65); }
/* v170：法术卡（def.spell）——只显示能量花费，不显示战力；右上角战力位改为一个「✦」星标
   （v178：星标**不写「法术」二字**；尺寸/位置与战力数字 `.mini-card .p` 对齐，用淡紫配色区分） */
.mini-card .mc-spell {
  position: absolute; top: 4px; right: 5px; left: auto;
  min-width: var(--mc-p-min); padding: 1px 5px; text-align: center;
  font-size: var(--mc-spell-fs); line-height: 1.15; border-radius: 6px;
  color: #d9c9ff; background: rgba(38, 26, 72, .82);
  border: 1px solid rgba(168, 140, 255, .65);
  box-shadow: 0 1px 3px var(--ink-5), 0 0 8px rgba(140, 110, 255, .35);
  text-shadow: 0 0 6px rgba(160, 130, 255, .5);
  z-index: 2;
}
.mini-card.spell { box-shadow: inset 0 0 0 1px rgba(168, 140, 255, .45), 0 2px 8px rgba(30, 20, 60, .45); }
.mini-card .mc-icon { font-size: clamp(20px, 3.4vh + 1vw, 42px); line-height: 1; text-shadow: 0 2px 4px var(--ink-5); }
.mini-card .mc-name { font-size: clamp(11px, 1.1vw + .4vh, 16px); line-height: 1.2; text-shadow: 0 1px 2px var(--ink-8); }
.mini-card .mc-mod {
  position: absolute; right: 5px; bottom: 4px; z-index: 2;
  font-size: 12px; color: #fff; background: var(--ink-55);
  border-radius: 6px; padding: 0 6px;
}
.mini-card .mc-q { font-size: clamp(26px, 5vh, 52px); line-height: 1; color: #9fb0cf; text-shadow: 0 2px 6px var(--ink-6); }
.mini-card .mc-tag { font-size: 12px; color: #9fb0cf; }
/* 已翻开的牌可点击放大查看 */
.mini-card.can-inspect { cursor: pointer; }
.mini-card.can-inspect:hover {
  filter: brightness(1.18);
  box-shadow: 0 0 0 2px rgba(255, 210, 63, .75), 0 4px 12px rgba(46, 78, 40, .35);
  transform: translateY(-2px);
  z-index: 4;
}
.mini-card.played-now { animation: flipIn .5s ease-out; box-shadow: 0 0 0 2px var(--accent), 0 2px 8px var(--shadow-green); }
/* v80→v83：卡牌“永久 +N 战力”的绿色小动画（1000ms）
   卡面本体只做短暂提亮；绿环扩散与“+N”气泡放在独立 body 悬浮层（.gain-ring），
   不会被 renderZones 重建缩略卡而中途打断；气泡末段 70%→100%（≈300ms）渐隐。 */
.mini-card.buff-gain {
  animation: buffGainGlow 1s ease-out;
}
@keyframes buffGainGlow {
  0%   { filter: brightness(1); }
  50%  { filter: brightness(1.5) saturate(1.3); }
  100% { filter: brightness(1); }
}
.gain-ring {
  pointer-events: none;
  animation: buffGainRing 1s ease-out;
}
@keyframes buffGainRing {
  0%   { box-shadow: 0 0 0 0 rgba(64, 214, 120, .8); }
  100% { box-shadow: 0 0 0 22px rgba(64, 214, 120, 0); }
}
.buff-gain-pop {
  position: absolute;
  left: 50%;
  top: 26%;
  transform: translateX(-50%);
  color: #3be27c;
  font-weight: 900;
  /* v82：气泡字号加大，突出 +N 数值 */
  font-size: clamp(26px, 3.6vw, 46px);
  line-height: 1;
  white-space: nowrap;
  letter-spacing: 1px;
  text-shadow:
    0 0 6px rgba(80, 235, 140, 1),
    0 0 18px rgba(64, 224, 120, .9),
    0 2px 3px var(--ink-7);
  pointer-events: none;
  animation: buffGainPop 1s ease-out forwards;
}
@keyframes buffGainPop {
  0%   { opacity: 0; transform: translate(-50%, 18px) scale(.7); }
  18%  { opacity: 1; transform: translate(-50%, -6px) scale(1.5); }
  45%  { opacity: 1; transform: translate(-50%, -14px) scale(1.28); }
  70%  { opacity: 1; transform: translate(-50%, -22px) scale(1.12); }
  100% { opacity: 0; transform: translate(-50%, -40px) scale(1); }
}

/* v84：卡牌“永久 -N 战力”的红色同款动画（结构与绿色版一一对应）
   卡面短暂泛红压暗；红环 + 红色 -N 气泡同置于 body 悬浮层，末段约 300ms 渐隐 */
.mini-card.buff-loss {
  animation: buffLossGlow 1s ease-out;
}
@keyframes buffLossGlow {
  0%   { filter: brightness(1); }
  50%  { filter: brightness(1.3) saturate(1.5); }
  100% { filter: brightness(1); }
}
.gain-ring.loss {
  animation: buffLossRing 1s ease-out;
}
@keyframes buffLossRing {
  0%   { box-shadow: 0 0 0 0 rgba(255, 96, 96, .8); }
  100% { box-shadow: 0 0 0 22px rgba(255, 96, 96, 0); }
}
.buff-gain-pop.loss {
  color: #ff8a8a;
  text-shadow:
    0 0 6px rgba(255, 130, 130, 1),
    0 0 18px rgba(255, 90, 90, .9),
    0 2px 3px var(--ink-7);
}

/* v169：卡牌“费用修改”的数字着色与演出（现由桑尼米尔克 k='costUp' 触发）
   口径与战力数字一致：费用数字**变高=红、变低=绿**（白色=印刷费用）。
   场上缩略卡（.mc-cost）与卡面费用宝珠（.cost-orb）各自独立着色，
   因此战力/费用可以同时是红色而不会互相干扰。 */
.mini-card .mc-cost.up { color: var(--down); border-color: var(--down); text-shadow: 0 0 6px rgba(255, 109, 109, .7); }
.mini-card .mc-cost.down { color: var(--up); border-color: var(--up); text-shadow: 0 0 6px rgba(70, 222, 143, .7); }
.cost-orb.up { color: #ff8a8a; border-color: var(--down); box-shadow: 0 0 6px rgba(255, 109, 109, .55); }
.cost-orb.down { color: #7bf0b0; border-color: var(--up); box-shadow: 0 0 6px rgba(70, 222, 143, .55); }
/* 卡位上的费用变化小光环（白→橙）。文字气泡复用 .buff-gain-pop 的浮起动画，
   但字号缩小——它写的是「卡名 费用 +1」这种长文案，不是单个数字。 */
.gain-ring.cost-ring {
  animation: costHiRing 1s ease-out;
}
@keyframes costHiRing {
  0%   { box-shadow: 0 0 0 0 rgba(255, 196, 92, .85); }
  100% { box-shadow: 0 0 0 14px rgba(255, 196, 92, 0); }
}
.buff-gain-pop.cost-pop {
  font-size: clamp(13px, 1.5vw, 19px);
  letter-spacing: 0;
  max-width: none;
}
.mini-card.cost-changed { box-shadow: 0 0 0 2px rgba(255, 196, 92, .9), 0 2px 10px rgba(255, 170, 60, .5); }

/* v169（修订）：桑尼米尔克加费的**完整卡牌揭示演出**——
   中央弹出被加费那张手牌的**完整卡面**（配图 / 卡名 / 战力）+ 费用从 N 涨到 N+1（可读的三段式），
   解决“小气泡文字太小、看不出是谁被加费”的问题。整段约 2.4s：
   弹入(scale) → 抖动一下 → 停留展示 → 整体上浮淡出，期间金色光环脉动两下。
   元素放 body 悬浮层（z-index 9500），不受盘面重渲染影响，也不挡操作（pointer-events:none）。 */
.cost-reveal {
  position: fixed;
  left: 50%;
  top: 38%;
  z-index: var(--z-fx-cost);
  pointer-events: none;
  animation: costRevealAnim 2.4s cubic-bezier(.2,.8,.3,1) forwards;
}
.cost-reveal-ring {
  position: absolute;
  inset: -16px;
  border-radius: 22px;
  animation: costRevealRing 2.4s ease-out forwards;
}
@keyframes costRevealRing {
  0%   { box-shadow: 0 0 0 0 rgba(255, 196, 92, .85); }
  30%  { box-shadow: 0 0 0 16px rgba(255, 196, 92, .30); }
  55%  { box-shadow: 0 0 0 4px rgba(255, 196, 92, .55); }
  100% { box-shadow: 0 0 0 30px rgba(255, 196, 92, 0); }
}
@keyframes costRevealAnim {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.5) rotate(-3deg); }
  10%  { opacity: 1; transform: translate(-50%, -50%) scale(1.1) rotate(1.5deg); }
  15%  { transform: translate(-50%, -50%) scale(.97) rotate(-3deg); }
  20%  { transform: translate(-50%, -50%) scale(1.04) rotate(2.5deg); }
  25%  { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  78%  { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  100% { opacity: 0; transform: translate(-50%, calc(-50% - 30px)) scale(.95) rotate(0deg); }
}
.cost-reveal-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.cost-reveal-tag {
  padding: 3px 12px;
  border-radius: var(--r-pill);
  background: rgba(20, 14, 4, .88);
  border: 1px solid rgba(255, 196, 92, .8);
  color: #ffd08a;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .5px;
  white-space: nowrap;
  box-shadow: 0 2px 10px var(--ink-45);
}
.cost-reveal-card {
  position: relative;
  width: 138px;
  height: 190px;
  overflow: hidden;
  border-radius: var(--r-4);
  border: 2px solid #ffc45c;
  background: var(--cgrad, #26304a);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  box-shadow: 0 14px 30px var(--ink-55), 0 0 0 4px rgba(255, 196, 92, .18);
}
.cost-reveal-card.no-img { background: var(--cgrad, linear-gradient(150deg, #2e5f96, #7cc0ff)); }
.cost-reveal-card .rc-art {
  width: 108px;
  height: 108px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cost-reveal-card .rc-art img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cost-reveal-card .rc-art .rc-emoji { font-size: 54px; line-height: 1; filter: drop-shadow(0 3px 5px var(--ink-5)); }
.cost-reveal-card.has-img .rc-art .rc-emoji { display: none; }
.cost-reveal-card .rc-name {
  max-width: 124px;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  text-align: center;
  text-shadow: 0 1px 3px var(--ink-85);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 费用横幅：印刷费用（旧，划掉）→ 修正后的费用（新，涨红 / 降绿）——只展示费用的变化 */
.cost-reveal-cost {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  border-radius: var(--r-2);
  background: rgba(12, 10, 20, .92);
  border: 1px solid rgba(255, 196, 92, .7);
  box-shadow: 0 4px 14px var(--ink-45);
  font-weight: 800;
  white-space: nowrap;
}
.cost-reveal-cost .rc-label { font-size: 11px; font-weight: 700; color: #ffd08a; }
.rc-old { color: #e8ecf5; font-size: 22px; opacity: .8; }
.rc-old s { text-decoration-thickness: 2px; text-decoration-color: var(--down); }
.rc-arrow { color: #ffc45c; font-size: 17px; }
.rc-new { font-size: 26px; color: var(--down); text-shadow: 0 0 8px rgba(255, 109, 109, .85); }
.rc-new.down { color: var(--up); text-shadow: 0 0 8px rgba(70, 222, 143, .85); }
.cost-reveal-note {
  font-size: 11.5px;
  color: #ffe6b8;
  text-shadow: 0 1px 3px var(--ink-85);
  white-space: nowrap;
}
@media (max-width: 700px) {
  .cost-reveal-card { width: 110px; height: 152px; }
  .cost-reveal-card .rc-art { width: 84px; height: 84px; }
  .cost-reveal-card .rc-art .rc-emoji { font-size: 42px; }
  .cost-reveal-card .rc-name { font-size: 12px; max-width: 100px; }
  .cost-reveal-cost { gap: 5px; padding: 3px 8px; }
  .rc-old { font-size: 18px; }
  .rc-new { font-size: 22px; }
  .cost-reveal-tag { font-size: 11px; padding: 2px 9px; }
  .cost-reveal-note { font-size: 10.5px; }
}

/* ---- v185：开局「登场」演出（`gs` 卡，现仅 7 费「哆来咪」）----
   遮幕淡入 → 卡面放大弹入（紫金光环脉冲 + 梦之星光迸发）→ 停留展示 → 上浮淡出，约 1.8s
   （时长与 game.js 的 playGameStartReveal DUR 对齐，**改时长要两边一起改**；演完才开始抽初始手牌）。
   结构：.gs-reveal（全屏层，pointer-events:none）
         ├ .gs-reveal-veil（暗色径向遮幕）
         └ .gs-reveal-inner（动画主体：整体缩放/抖动）
             └ .gs-reveal-item ×N（position:relative，＝“登场块”）
                 ├ .gs-reveal-ring（光环脉冲，v186 起挂在本块上 → 覆盖标签与摘要，且恒为第一子元素，
                 │                   故卡面永远画在光环之上；外阴影在边框盒内被裁掉，不会罩住文字）
                 ├ .gs-reveal-tag（顶部来源标签）
                 ├ .gs-reveal-cardwrap → .zoom-card.gs-reveal-card（大卡面）
                 └ .gs-reveal-note（底部效果摘要）
   卡面复用 .card-face.zoom-card.hand-card + cardFaceHTML()，故配色/比例与手牌与图鉴完全一致。 */
.gs-reveal {
  position: fixed;
  inset: 0;
  z-index: var(--z-fx-gs);
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.gs-reveal-veil {
  position: absolute;
  inset: 0;
  background: radial-gradient(closest-side at 50% 45%, rgba(28, 18, 52, .58), rgba(6, 4, 16, .86));
  animation: gsVeilFade 1.8s ease-out forwards;
}
@keyframes gsVeilFade {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  80%  { opacity: 1; }
  100% { opacity: 0; }
}
.gs-reveal-inner {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 20px;
  animation: gsCardPop 1.8s cubic-bezier(.2, .8, .3, 1) forwards;
}
@keyframes gsCardPop {
  0%   { opacity: 0; transform: scale(.42) translateY(26px); filter: brightness(1.8) blur(3px); }
  14%  { opacity: 1; transform: scale(1.09) translateY(0); filter: brightness(1.4) blur(0); }
  20%  { transform: scale(.96) rotate(-1.8deg); }
  26%  { transform: scale(1.03) rotate(1.2deg); }
  32%  { transform: scale(1) rotate(0deg); filter: brightness(1); }
  80%  { opacity: 1; transform: scale(1) translateY(0); }
  100% { opacity: 0; transform: scale(.96) translateY(-28px); filter: brightness(1.3); }
}
/* v186：登场块=顶部标签 + 卡面 + 底部摘要；光环挂在本块上（`position:relative` 作定位基准），
   因此脉冲在**幅度最小时也把上下两条文字说明圈在里面**（原来光环只套卡面，文字落在光环之外）。 */
.gs-reveal-item { position: relative; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.gs-reveal-tag {
  padding: 4px 14px;
  border-radius: var(--r-pill);
  background: rgba(26, 14, 48, .9);
  border: 1px solid rgba(201, 166, 255, .85);
  color: #e2ccff;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .5px;
  white-space: nowrap;
  box-shadow: 0 2px 12px var(--ink-5), 0 0 14px rgba(160, 110, 255, .35);
}
.gs-reveal-cardwrap { position: relative; }
/* 光环：以「登场块」为基准外扩一点（左右 16px / 上下 8px）——最小幅度时也完整覆盖标签与摘要 */
.gs-reveal-ring {
  position: absolute;
  inset: -8px -16px;
  border-radius: 24px;
  animation: gsRingPulse 1.8s ease-out forwards;
}
/* 脉冲两下：① 26% 强脉冲 ② 55% 次脉冲；v186 把**最小幅度抬高**——
   起止不再是 0 扩散（那样最小瞬间几乎看不见、也盖不到上下文字），而是常驻 3~4px 描边
   + 12~14px 金色柔光，两次脉冲之间（55% 谷底）也保持 12px 扩散。
   百分比按 1.8s 全长折算：强脉冲 ≈0.47s、谷底 ≈0.99s、次脉冲 ≈1.17s（30%→80% 为停留段）。 */
@keyframes gsRingPulse {
  0%   { box-shadow: 0 0 0 3px rgba(201, 166, 255, .7), 0 0 26px 12px rgba(255, 214, 120, .34); }
  26%  { box-shadow: 0 0 0 22px rgba(201, 166, 255, .3), 0 0 38px 16px rgba(255, 214, 120, .5); }
  55%  { box-shadow: 0 0 0 12px rgba(201, 166, 255, .45), 0 0 30px 14px rgba(255, 214, 120, .4); }
  80%  { box-shadow: 0 0 0 8px rgba(201, 166, 255, .35), 0 0 26px 12px rgba(255, 214, 120, .3); }
  100% { box-shadow: 0 0 0 4px rgba(201, 166, 255, .18), 0 0 20px 10px rgba(255, 214, 120, .12); }
}
/* 提高一级特异度（.gs-reveal .gs-reveal-card）以压过 .card-face 自身的 box-shadow */
.gs-reveal .gs-reveal-card {
  box-shadow: 0 22px 54px var(--ink-62), 0 0 0 3px rgba(201, 166, 255, .35), 0 0 44px rgba(150, 110, 255, .4);
}
.gs-reveal-note {
  padding: 4px 14px;
  border-radius: var(--r-pill);
  background: rgba(14, 10, 26, .88);
  border: 1px solid rgba(201, 166, 255, .5);
  color: #ffe6b8;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
/* 星光粒子：复用 .energy-star 的飞行关键帧，换成紫金辉光并提到遮幕之上 */
.energy-star.gs-star { z-index: var(--z-fx-gs-note); text-shadow: 0 0 10px rgba(198, 160, 255, .95), 0 2px 5px var(--ink-55); }
@media (max-width: 700px) {
  /* 登场卡面（.gs-reveal-card 带 .zoom-card）：小屏只改这一行变量 + 卡宽/内边距 */
  .gs-reveal .zoom-card {
    --badge: 34px; --badge-fs: 16px; --spell-fs: 16px;
    --art-w: 100%; --art-m: 6px auto 4px;
    --name-fs: 17px; --text-fs: 12.5px; --text-lh: 1.5;
    width: 186px;
    padding: 9px 10px 13px;
  }
  .gs-reveal .zoom-card .hc-text { margin-top: 8px; }
  .gs-reveal-tag { font-size: 11px; padding: 3px 10px; }
  .gs-reveal-note { font-size: 10.5px; padding: 3px 10px; }
}

/* v169：额外能量（斯塔萨菲雅 k='energyNext'）的两段演出
   ① 登记段（揭示当刻、卡位上）：卡位金光闪一下 + 金色光环扩散 + 星光迸发 + 「能量 +1」气泡；
   ② 到账段（下回合开始、顶栏能量框上）：同款但锚点换成能量框，并配合 #energyBonus 的绿色角标。
   所有元素都在 body 悬浮层（z-index 9400）且 pointer-events:none，不挡操作。 */
.energy-card-flash { animation: energyCardFlash 1.4s ease-out; pointer-events: none; }
@keyframes energyCardFlash {
  0%   { background: rgba(255, 226, 140, 0); box-shadow: 0 0 0 0 rgba(255, 214, 92, .85); }
  18%  { background: rgba(255, 236, 170, .45); box-shadow: 0 0 22px 8px rgba(255, 214, 92, .75); }
  45%  { background: rgba(255, 236, 170, .16); box-shadow: 0 0 10px 3px rgba(255, 214, 92, .4); }
  100% { background: rgba(255, 226, 140, 0); box-shadow: 0 0 0 0 rgba(255, 214, 92, 0); }
}
.energy-box-flash { animation: energyBoxFlash 1.4s ease-out; pointer-events: none; }
@keyframes energyBoxFlash {
  0%   { background: rgba(90, 235, 150, 0); box-shadow: 0 0 0 0 rgba(90, 235, 150, .9); }
  20%  { background: rgba(150, 255, 195, .45); box-shadow: 0 0 22px 9px rgba(90, 235, 150, .8); }
  50%  { background: rgba(150, 255, 195, .15); box-shadow: 0 0 10px 3px rgba(90, 235, 150, .45); }
  100% { background: rgba(90, 235, 150, 0); box-shadow: 0 0 0 0 rgba(90, 235, 150, 0); }
}
.energy-ring { animation: energyRingPulse 1.4s ease-out; pointer-events: none; }
@keyframes energyRingPulse {
  0%   { box-shadow: 0 0 0 0 rgba(255, 214, 92, .8); }
  60%  { box-shadow: 0 0 0 16px rgba(255, 214, 92, .28); }
  100% { box-shadow: 0 0 0 30px rgba(255, 214, 92, 0); }
}
/* 星光迸发粒子：起点由 JS 写入 left/top，终点由 --edx/--edy 给出 */
.energy-star {
  position: fixed;
  transform: translate(-50%, -50%);
  z-index: var(--z-fx-energy-star);
  pointer-events: none;
  line-height: 1;
  text-shadow: 0 0 8px rgba(255, 214, 92, .95), 0 2px 4px var(--ink-5);
  animation: energyStarFly .95s cubic-bezier(.2, .7, .3, 1) forwards;
}
@keyframes energyStarFly {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.4) rotate(0deg); }
  22%  { opacity: 1; transform: translate(-50%, -50%) scale(1.35) rotate(20deg); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--edx, 0px)), calc(-50% + var(--edy, -40px))) scale(.7) rotate(80deg); }
}
/* v170：法术消散的星光（复用 .energy-star 的飞行关键帧，只把辉光换成淡紫） */
.energy-star.spell-star { text-shadow: 0 0 9px rgba(178, 150, 255, .95), 0 2px 4px var(--ink-5); }
/* 「能量 +N」气泡（主行大号金字 + 副行小字说明），锚点坐标由 JS 写入 */
.energy-pop {
  position: fixed;
  transform: translate(-50%, -50%);
  z-index: var(--z-fx-energy-pop);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  pointer-events: none;
  white-space: nowrap;
  animation: energyPop 1.6s ease-out forwards;
}
.energy-pop .ep-main {
  font-size: clamp(20px, 2.6vw, 30px);
  font-weight: 900;
  color: #ffe08a;
  letter-spacing: .5px;
  text-shadow: 0 0 10px rgba(255, 200, 60, .95), 0 0 22px rgba(255, 168, 40, .8), 0 2px 4px var(--ink-7);
}
.energy-pop .ep-sub {
  font-size: 12px;
  font-weight: 700;
  color: #fff6da;
  padding: 1px 8px;
  border-radius: var(--r-pill);
  background: rgba(20, 14, 4, .8);
  border: 1px solid rgba(255, 214, 92, .6);
  text-shadow: 0 1px 2px var(--ink-8);
}
@keyframes energyPop {
  0%   { opacity: 0; transform: translate(-50%, -30%) scale(.55); }
  16%  { opacity: 1; transform: translate(-50%, -60%) scale(1.18); }
  34%  { opacity: 1; transform: translate(-50%, -72%) scale(1); }
  74%  { opacity: 1; transform: translate(-50%, -96%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -130%) scale(.94); }
}
@media (max-width: 700px) {
  .energy-pop .ep-main { font-size: 20px; }
  .energy-pop .ep-sub { font-size: 11px; }
}

/* 洗入卡组（`shuffleIn`）的轻量演出 —— 锚点＝**计数块**
   （玩家侧＝底部「手牌：N/7」#handCountVal；对手侧＝侧栏「牌库 N 张」#aiDeck）：
   计数闪光 + 外扩光环（合并在同一条动画里，避免两条 animation 互相覆盖，同 .energy-box-flash
   与 .energy-ring 并存时的老问题）+ 星光迸发（复用 .energy-star 的飞行关键帧）+ 「洗入卡组」气泡
   （复用 .energy-pop 的结构与关键帧，只把主行改成青蓝色）。全部在 body 悬浮层、不挡操作。 */
.deck-shuffle-flash { animation: deckShuffleFlash 1.4s ease-out; pointer-events: none; }
@keyframes deckShuffleFlash {
  0%   { background: rgba(150, 220, 255, 0); box-shadow: 0 0 0 0 rgba(120, 200, 255, .9), 0 0 0 0 rgba(120, 200, 255, 0); }
  20%  { background: rgba(186, 234, 255, .5); box-shadow: 0 0 20px 8px rgba(110, 196, 255, .8), 0 0 0 6px rgba(120, 200, 255, .35); }
  55%  { background: rgba(186, 234, 255, .16); box-shadow: 0 0 10px 3px rgba(110, 196, 255, .4), 0 0 0 16px rgba(120, 200, 255, .14); }
  100% { background: rgba(150, 220, 255, 0); box-shadow: 0 0 0 0 rgba(110, 196, 255, 0), 0 0 0 26px rgba(120, 200, 255, 0); }
}
.energy-star.deck-star { text-shadow: 0 0 9px rgba(150, 220, 255, .95), 0 2px 4px var(--ink-5); }
.energy-pop.deck-pop .ep-main {
  color: #d8f0ff;
  text-shadow: 0 0 10px rgba(120, 200, 255, .95), 0 0 22px rgba(60, 150, 255, .75), 0 2px 4px var(--ink-7);
}
.energy-pop.deck-pop .ep-sub { border-color: rgba(150, 220, 255, .6); }

/* v90：场上“生成/落场”卡牌的诞生演出（1s，节奏同 ±N）——凝聚显形：
   小到弹大 + 提亮 + 淡青光环扩散，尾段回稳 */
.mini-card.spawned-now {
  animation: spawnIn 1s ease-out;
}
@keyframes spawnIn {
  0%   { transform: scale(.45); filter: brightness(1.7); box-shadow: 0 0 0 0 rgba(120, 208, 255, .6); }
  24%  { transform: scale(1.16); filter: brightness(1.45); box-shadow: 0 0 0 6px rgba(120, 208, 255, .42); }
  48%  { transform: scale(.99); filter: brightness(1.12); box-shadow: 0 0 0 12px rgba(120, 208, 255, 0); }
  72%  { transform: scale(1.04); filter: brightness(1.02); }
  100% { transform: scale(1); filter: brightness(1); box-shadow: 0 0 0 0 rgba(120, 208, 255, 0); }
}

/* v90：加入手牌的卡“滑入”演出（1s，节奏同 ±N）——底部弹起 + 过冲回稳 + 提亮 */
.hand-card.hand-new {
  animation: handIn 1s ease-out;
}
@keyframes handIn {
  0%   { transform: translateY(16px) scale(.7); opacity: 0; filter: brightness(1.6); }
  24%  { transform: translateY(-4px) scale(1.08); opacity: 1; filter: brightness(1.3); }
  50%  { transform: translateY(0) scale(.98); opacity: 1; filter: brightness(1.05); }
  75%  { transform: translateY(0) scale(1.03); }
  100% { transform: translateY(0) scale(1); opacity: 1; filter: brightness(1); }
}

/* v91→v95：抽牌入场（每回合/开局抽牌）——浏览器原生 CSS transform“从屏幕右侧滑入”；
   为避免平移把手牌容器可滚动区域撑大、桌面端闪横向滚动条，
   动画期间由 JS 给 #hand 加 .draw-anim（overflow-x:hidden）临时抑制 */
.hand-card.hand-drawn {
  animation: handDrawIn .65s cubic-bezier(.2, .85, .3, 1);
}
@keyframes handDrawIn {
  0%   { transform: translateX(110vw) scale(.9); opacity: .4; }
  70%  { transform: translateX(-1.2vw) scale(1.03); opacity: 1; }
  100% { transform: translateX(0) scale(1); opacity: 1; }
}
.hand.draw-anim { overflow-x: hidden; }
/* v100→v101：暗牌翻开 = 从小到大缩放入场（0.5s，同生成 token 的“凝聚显形”观感） */
@keyframes flipIn {
  0%   { transform: scale(.3); opacity: .25; filter: brightness(1.7); }
  40%  { transform: scale(1.12); opacity: 1; filter: brightness(1.35); }
  70%  { transform: scale(.97); filter: brightness(1.05); }
  100% { transform: scale(1); opacity: 1; filter: brightness(1); }
}

/* ---------- 手牌（居中放置，两侧让位给左下/右下角按钮） ---------- */
.hand-wrap {
  padding: 8px 0 14px;
  border-top: 1px solid rgba(108, 146, 100, .32);
  background: linear-gradient(0deg, var(--surf-68), var(--surf-25));
}
.energy-pips {
  display: flex;
  gap: 5px;
  margin-bottom: 8px;
  justify-content: center;
  padding: 0 170px;
  /* v186：条数＝本回合当前可用能量（不再补灰色占位），用完时整排为空——
     保留一条的高度，避免手牌区随条数变化上下跳动 */
  min-height: 9px;
}
/* 基础样式＝“未点亮”的灰条；v186 起渲染层只产出 .pip.on（有几条可用就画几条），
   灰底保留作样式备用（例如日后要显示“本回合上限 / 剩余”两段式）。 */
.pip { width: 26px; height: 9px; border-radius: 5px; background: rgba(126, 160, 112, .42); transition: background .3s, box-shadow .3s; }
.pip.on { background: linear-gradient(90deg, #e0a316, #f2c94c); box-shadow: 0 0 8px rgba(226, 180, 40, .6); }

.hand {
  display: flex;
  gap: 10px;
  align-items: stretch;
  min-height: 150px;
  overflow-x: auto;
  justify-content: safe center;
  padding: 4px 170px;
}
@media (max-width: 700px) {
  .hand, .energy-pips { padding-left: 76px; padding-right: 76px; }
}
.hand-empty { color: #6f8b66; font-size: 13px; display: flex; align-items: center; justify-content: center; width: 100%; border: 1px dashed rgba(108, 146, 100, .45); border-radius: var(--r-2); padding: 20px; text-align: center; }

/* ==================== 卡面（.card-face）====================
   手牌 / 对手手牌情报 / 图鉴 / 指定卡牌 / 三池 / 卡组编辑槽 / 卡组池 / 放大弹窗 / 衍生卡 /
   登场演出 / 弃牌演出 —— 这些都是 js/game.js 的 cardFaceHTML() 产出的**同一套 DOM**：
     角标行(.hc-top：.cost-orb 与 .p 或 .hc-spell) → 立绘区(.hc-art > .hc-img，缺图时 emoji 兜底)
     → 卡名(.hc-name) → 效果文案(.hc-text)；封印时艺术区叠 ❗(.hc-seal)。
   根元素由 game.js 的 cardFaceEl() 统一挂上 `.card-face` 与该上下文自己的类
   （.hand-card / .zoom-card / .codex-card / .deck-pool-card / .deck-card-slot …），
   并注入 `--cgrad`（费用档渐变）。

   ★ 尺寸只走下面这组变量：新增界面或调尺寸时**只在该上下文（或其断点）里改变量**，
   不要再分别重写 .cost-orb / .p / .hc-spell（那三个必须同进同退，漏一个就错位）；
   上下文没声明的档位自动继承基准值。`.mini-card`（场上缩略卡）是另一套 DOM，用它自己的 --mc-* 变量。 */
.card-face {
  --badge: 26px;        /* 角标直径：费用宝珠 / 战力 / ✦ 三枚同一尺寸 */
  --badge-fs: 13px;     /* 角标数字字号 */
  --badge-bw: 2px;      /* 角标圆环描边 */
  --spell-fs: 14px;     /* ✦ 的字号（比数字略大） */
  --seal-fs: 30px;      /* 封印 ❗ */
  --icon-fs: 30px;      /* 缺图卡的艺术区＝emoji 块 */
  --art-icon-fs: 32px;  /* 立绘区内垫底的 emoji */
  --art-w: calc(100% - 4px);
  --art-m: 4px auto 2px;
  --art-r: var(--r-1);
  --name-fs: 12.5px;
  --text-fs: 8.8px;
  --text-lh: 1.3;

  border-radius: var(--r-3);
  padding: 6px 6px 8px;
  background: var(--cgrad);
  color: #fff;
  border: 2px solid var(--surf-25);
  box-shadow: 0 6px 14px rgba(46, 78, 40, .35), inset 0 0 0 1px var(--surf-14);
  cursor: pointer;
  position: relative;
  transition: transform .12s, box-shadow .12s, filter .12s;
  display: flex;
  flex-direction: column;
}
/* 手牌条里的排布（其余卡面在网格 / 弹窗里，不吃这两条） */
.hand-card { flex: 0 0 auto; width: 86px; }
.hand-card:hover:not(.unaffordable) { transform: translateY(-8px); box-shadow: 0 14px 22px rgba(46, 78, 40, .4); }
.hand-card.selected {
  border-color: #f2c94c;
  transform: translateY(-12px);
  box-shadow: 0 0 0 3px rgba(242, 201, 76, .8), 0 16px 26px rgba(46, 78, 40, .45);
}
.hand-card.unaffordable { opacity: .55; filter: grayscale(.5); cursor: not-allowed; }
.card-face .hc-top { display: flex; justify-content: space-between; align-items: center; }
/* 费用宝珠 / 战力 / ✦：外观各自的取色规则保持原有特异度（.up/.down 着色靠它压过本行） */
.cost-orb { width: var(--badge); height: var(--badge); border-radius: 50%; background: #12244a; border: var(--badge-bw) solid #6aa8ff; color: #bcd9ff; font-size: var(--badge-fs); font-weight: 800; display: flex; align-items: center; justify-content: center; }
.card-face .p {
  width: var(--badge); height: var(--badge); border-radius: 50%;
  background: #1c0f08; border: var(--badge-bw) solid var(--accent);
  color: #ffd23f; font-size: var(--badge-fs); font-weight: 800;
  display: flex; align-items: center; justify-content: center;
  text-shadow: 0 0 4px rgba(255, 210, 63, .5);
}
.card-face .hc-icon { font-size: var(--icon-fs); text-align: center; margin: 4px 0 2px; filter: drop-shadow(0 2px 3px var(--ink-5)); }
/* 法术卡（def.spell）：卡框不显示战力，右上角战力位改画一个「✦」（不写「法术」二字） */
.card-face .hc-spell {
  width: var(--badge); height: var(--badge); flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--spell-fs); border-radius: 50%;
  color: #d9c9ff; background: rgba(38, 26, 72, .85);
  border: var(--badge-bw) solid rgba(168, 140, 255, .65);
  text-shadow: 0 0 6px rgba(160, 130, 255, .5);
}
/* 缺图卡的艺术区＝emoji 块：与有图卡的 .hc-art 同尺寸（正方形），手牌各卡高度才不会参差。
   ⚠️ 宽度恒为 calc(100% - 4px)：它**不跟** --art-w —— 放大 / 衍生 / 弃牌那几个上下文里，
   有图卡的立绘区是按 px 收窄的（240 / min(136px,36vw) 等），而缺图块一直吃卡宽的百分比，
   两者本来就不一样（现状如此，未在本轮改动）。 */
.card-face.no-img .hc-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(100% - 4px);
  aspect-ratio: 1 / 1;
  margin: 4px auto 2px;
  border-radius: var(--r-1);
  background: rgba(120, 150, 110, .14);
  filter: none;
}
.card-face .hc-name { font-size: var(--name-fs); font-weight: 800; text-align: center; text-shadow: 0 1px 2px var(--ink-8); }
.card-face .hc-text { font-size: var(--text-fs); line-height: var(--text-lh); color: var(--surf-88); margin-top: 4px; flex: 1; text-shadow: 0 1px 2px var(--ink-8); }
/* 手牌区的效果文字：最多两行，超长省略号截断（完整文案可右键手牌或点击放大查看） */
#hand .hand-card .hc-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em; /* v103：统一预留两行，短文案卡不再矮一截 */
}

/* ---------- 日志 ---------- */
.log {
  border: 1px solid var(--border-2);
  border-radius: var(--r-3);
  background: var(--surf-66);
  padding: 8px 12px;
  height: 110px;
  overflow-y: auto;
  font-size: 12px;
  line-height: 1.7;
}
.log .entry { opacity: .9; color: #4c6347; }
.log .entry .t { color: #8aa282; margin-right: 6px; }
.log .entry.p { color: var(--up-ink); }
.log .entry.a { color: #2c62b0; }
.log .entry.sys { color: var(--green); }
.log .entry.snap { color: #a97e00; font-weight: 700; }
.log .entry.danger { color: var(--red); }
.log .entry.win { color: #8a5b00; font-weight: 800; }

/* ---------- 侧栏 ---------- */
.side { display: flex; flex-direction: column; gap: 12px; min-width: 0; min-height: 0; overflow-y: auto; padding-right: 2px; }

/* 对局信息（日志）区块：位于玩法说明下方，占满侧栏剩余高度 */
.log-block { display: flex; flex-direction: column; gap: 6px; flex: 1; min-height: 140px; }
.log-block .side-title { margin-bottom: 0; }
.log-block .log { height: auto; flex: 1; min-height: 0; max-height: none; }
.opponent {
  background: var(--surf-66); border: 1px solid var(--border-2); border-radius: var(--r-3); padding: 10px;
}
.side-title { font-size: 12px; color: var(--dim); margin-bottom: 8px; }
.avatar-row { display: flex; gap: 10px; align-items: center; }
.avatar { width: 52px; height: 52px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 26px; }
/* 联机时这个格子里放的是对手在设置里选的那张卡图（js/net.js 的 setAv；没选/对不上就退回 👤） */
.avatar img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.av-ai { background: linear-gradient(135deg, #28477a, #3e5d99); border: 2px solid #5d7cbd; }
.mini-stats { font-size: 12px; color: var(--dim); display: flex; flex-direction: column; gap: 3px; flex: 1 1 auto; min-width: 0; }
.mini-stats .ai-energy { color: #3d6b8c; font-weight: 700; }
.ai-spy-btn { flex: 0 0 auto; margin-left: auto; padding: 5px 10px; font-size: 12px; font-weight: 700; }
.ai-spy-modal { max-width: min(720px, 94vw); width: 94vw; text-align: left; padding: 18px 18px 16px; }
.ai-spy-modal .codex-head { margin-bottom: 10px; }
.ai-spy-sec { margin-bottom: 14px; }
.ai-spy-h {
  font-size: 13px;
  font-weight: 800;
  color: var(--txt);
  margin-bottom: 8px;
  letter-spacing: .5px;
}
.ai-spy-h span { color: var(--dim); font-weight: 700; }
.ai-spy-note { font-size: 11px; font-weight: 600; color: var(--dim2); }
.ai-spy-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
  max-height: 28vh;
  overflow-y: auto;
  padding: 4px 2px 8px;
  scrollbar-width: thin;
}
.ai-spy-grid .ai-spy-card { width: 100%; cursor: pointer; }
.ai-spy-grid .ai-spy-card:hover { border-color: rgba(242, 201, 76, .85); box-shadow: 0 0 0 2px rgba(242, 201, 76, .45); }
.ai-spy-empty {
  grid-column: 1 / -1;
  color: #7a8a6f;
  font-size: 13px;
  padding: 16px 0;
  text-align: center;
}
.snap-tag {
  margin-top: 8px; text-align: center; font-size: 12px; font-weight: 700;
  color: #a97e00; border: 1px solid rgba(201, 148, 0, .5); border-radius: var(--r-1); padding: 3px;
  animation: blink 1s infinite;
}
@keyframes blink { 50% { opacity: .45; } }

.status-card {
  border: 1px solid var(--border-2);
  background: linear-gradient(180deg, var(--surf-72), rgba(240, 248, 230, .4));
  border-radius: var(--r-3);
  padding: 10px 12px;
  font-size: 13px;
  color: var(--dim);
}
.status-card .status-text { color: var(--txt); line-height: 1.55; min-height: 40px; }
.status-card.busy .status-text { color: var(--green); }

.rules { background: var(--surf-62); border: 1px solid var(--border-2); border-radius: var(--r-3); padding: 10px 12px; font-size: 11.5px; color: var(--dim); line-height: 1.7; }
.rules h3 { color: var(--txt); font-size: 12.5px; margin-bottom: 6px; }
.rules ul { padding-left: 16px; }

/* ---------- 弹窗 ---------- */
.modal-mask {
  position: fixed; inset: 0;
  background: rgba(44, 62, 40, .42);
  backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  z-index: var(--z-modal);
}
.modal {
  background: linear-gradient(180deg, #f8fcf1, #e5efd9);
  border: 1px solid var(--frame);
  border-radius: var(--r-6);
  padding: 30px 44px;
  text-align: center;
  box-shadow: 0 20px 60px var(--shadow-green);
  animation: rise .3s ease;
  max-width: 92vw;
  color: var(--txt);
}
@keyframes rise { from { transform: translateY(18px); opacity: 0; } }
.modal-emblem { font-size: 56px; }
.modal h2 { font-size: 26px; margin: 8px 0 6px; letter-spacing: 2px; color: var(--txt); }
.modal-sub { color: var(--dim); font-size: 14px; margin-bottom: 14px; }
.modal-cubes { font-size: 18px; font-weight: 800; margin-bottom: 20px; }
.modal-cubes.win { color: var(--up-ink); }
.modal-cubes.lose { color: var(--red); }
.modal-cubes.draw { color: var(--dim); }

.foot { text-align: center; font-size: 11px; color: var(--hint); padding: 8px; border-top: 1px solid rgba(108, 146, 100, .25); }

.hidden { display: none !important; }

/* ============ 左下/右下 常驻操作按钮 ============ */
.corner-actions {
  position: fixed;
  bottom: 16px;
  z-index: var(--z-corner);
  display: flex;
  gap: 8px;
}
.corner-left { left: 16px; }
.corner-right { right: 16px; }
.corner-actions .btn {
  font-size: 14px;
  padding: 10px 18px;
  border-radius: var(--r-2);
  box-shadow: 0 6px 16px var(--shadow-green);
  backdrop-filter: blur(4px);
  background: var(--surf-92);
  border-color: rgba(124, 164, 112, .45);
}
.btn-pass {
  border-color: rgba(201, 148, 0, .6);
  color: #7a5c00;
  font-weight: 700;
}
.btn-pass:hover:not(:disabled) { border-color: #c99400; background: rgba(255, 228, 130, .6); }
@media (max-width: 640px) {
}

/* 底部能量块上的「↺」——提示它可点（重置本回合暗出的牌） */
.reset-mark {
  margin-left: 6px;
  color: #b57708;
  font-size: 15px;
  opacity: .85;
}
/* v169：能量框上的「额外能量」角标（斯塔萨菲雅 → 下回合 +1 能量）——
   显示本回合能量里由「额外能量」机制多出来的点数，回合结束随下次能量结算归零。 */
.energy-bonus {
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: linear-gradient(150deg, #1f6f4a, #48d68a);
  border: 1px solid #8af0b6;
  color: #eaffef;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .3px;
  box-shadow: 0 0 8px rgba(72, 214, 138, .55);
  animation: energyBonusPop .5s ease-out;
}
@keyframes energyBonusPop {
  0%   { transform: scale(.5); opacity: 0; }
  60%  { transform: scale(1.22); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ============ 重置确认弹窗 ============ */
.undo-modal { max-width: 360px; width: 90vw; padding: 26px 30px; }
.undo-modal .modal-emblem { font-size: 40px; }
.undo-text { color: var(--dim); font-size: 14px; line-height: 1.8; margin: 10px 0 20px; }
.undo-btns, .modal-btns { display: flex; gap: 10px; justify-content: center; }
.undo-btns .btn, .modal-btns .btn { min-width: 96px; }
/* 开发者“指定卡牌”弹窗 */
.pick-actions { display: flex; justify-content: center; gap: 10px; margin-top: 14px; }
.codex-card.pick-picked { border-color: #f2c94c; box-shadow: 0 0 0 3px rgba(242, 201, 76, .85), 0 8px 18px rgba(46, 78, 40, .4); transform: translateY(-4px); }

/* v148：开发者「指定地形」弹窗
   v149 修复「区域 2 / 区域 3 点不到」：
     - 区域选择条移到标题下方并作为**三等分按钮组**，始终在弹窗可见区内（不再被 88vh 裁掉）；
     - 只有地形网格滚动（flex:1 + min-height:0 + max-height），选择条与「替换」按钮设为 flex:0 0 auto 不被压缩；
     - 该弹窗所在遮罩允许滚动，矮屏/手机端也能滚到「替换」按钮。 */
.pick-loc-modal .loc-pick-grid {
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  flex: 1 1 auto;
  min-height: 0;
  max-height: 46vh;
}
.pick-loc-modal .pick-loc-zone-row,
.pick-loc-modal .pick-actions { flex: 0 0 auto; }
.pick-loc-modal .codex-tip.warn { color: #c0392b; font-weight: 700; }
/* 「指定地形」「指定卡牌」「添加石块」（v206）三个调试弹窗：内容超高时遮罩可滚动，控件永不被 88vh 裁掉 */
#pickLocMask, #pickMask, #addStoneMask { overflow-y: auto; align-items: flex-start; padding: 10px; }
#pickLocMask > .pick-loc-modal, #pickMask > .codex-modal, #addStoneMask > .add-stone-modal { margin: auto; }
/* 弹窗内只有卡牌/地形网格滚动，底部按钮条固定可见（v149） */
.codex-modal .codex-grid { flex: 1 1 auto; min-height: 0; }
.pick-actions { flex: 0 0 auto; flex-wrap: wrap; align-items: center; }
/* v150：「出现时」效果开关（开发者「指定地形」） */
.plz-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #3d5535;
  cursor: pointer;
  user-select: none;
  padding: 4px 10px;
  border: 1px dashed rgba(108, 148, 100, .5);
  border-radius: var(--r-1);
  background: var(--surf-5);
}
.plz-check input { width: 14px; height: 14px; accent-color: #3d6b3a; cursor: pointer; }
.plz-check:hover { border-color: var(--gold-9); background: rgba(255, 250, 226, .9); }
.loc-pick-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
  padding: 12px 12px 10px;
  border: 2px solid rgba(70, 100, 60, .35);
  border-radius: var(--r-3);
  background: linear-gradient(160deg, #f4f8ef, #e4eed9);
  color: var(--txt);
  cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.loc-pick-card:hover {
  border-color: rgba(242, 201, 76, .85);
  box-shadow: 0 0 0 2px rgba(242, 201, 76, .45);
  transform: translateY(-2px);
}
.loc-pick-card.pick-picked {
  border-color: #f2c94c;
  box-shadow: 0 0 0 3px rgba(242, 201, 76, .85), 0 8px 18px rgba(46, 78, 40, .35);
  transform: translateY(-3px);
}
.loc-pick-card .lpc-icon { font-size: 28px; line-height: 1; }
.loc-pick-card .lpc-name { font-size: 15px; font-weight: 800; letter-spacing: .5px; }
.loc-pick-card .lpc-eff {
  font-size: 11px;
  line-height: 1.35;
  color: #5a7352;
  min-height: 2.7em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.loc-pick-card .lpc-meta { font-size: 10px; color: #7a9070; margin-top: 2px; }
/* 区域选择条：三等分按钮组（v149） */
.pick-loc-zone-row {
  display: grid;
  grid-template-columns: auto repeat(3, minmax(0, 1fr));
  align-items: center;
  gap: 8px;
  padding: 2px 2px 8px;
  border-bottom: 1px dashed var(--border);
  position: relative;
  z-index: 2; /* 保险：永远盖在地形网格之上，避免被滚动内容压住 */
}
.pick-loc-zone-row .plz-label {
  font-size: 13px;
  font-weight: 700;
  color: #3d5535;
  margin-right: 4px;
  white-space: nowrap;
}
.pick-loc-zone-row .plz-btn {
  width: 100%;
  padding: 9px 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  pointer-events: auto;
}
.pick-loc-zone-row .plz-btn:hover:not(.active) {
  border-color: var(--gold-9);
  background: rgba(255, 250, 226, .95);
}
.pick-loc-zone-row .plz-btn.active {
  background: #3d6b3a;
  color: #f4ffe8;
  border-color: var(--txt);
  font-weight: 700;
  opacity: 1;
  box-shadow: 0 0 0 2px rgba(242, 201, 76, .6);
}
@media (max-width: 520px) {
  .pick-loc-zone-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .pick-loc-zone-row .plz-label { grid-column: 1 / -1; margin: 0 0 2px; }
}

/* ============ v206：开发者「🪨 添加石块」弹窗 ============
   结构＝标题 + 区域选择条（复用 .pick-loc-zone-row / .plz-btn）+ 数量行（◀ 输入框 ▶）+ 确认按钮。
   数量输入框**隐藏原生上下箭头**，只用我们自己的 ◀ ▶ 两个箭头按钮调数值。 */
.add-stone-modal { max-width: 470px; }
/* 复用「指定地形」的区域选择条时补一条：该弹窗里没有会滚动的网格，
   但选择条与按钮条仍固定不压缩（`.pick-loc-modal` 的那条作用域不覆盖这里） */
.add-stone-modal .pick-loc-zone-row,
.add-stone-modal .pick-actions { flex: 0 0 auto; }
.add-stone-body { padding: 16px 2px 6px; }
.as-count {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.as-count-label,
.as-count-unit {
  font-size: 13px;
  font-weight: 700;
  color: #3d5535;
  white-space: nowrap;
}
.as-step {
  width: 40px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-2);
  border: 1px solid rgba(108, 148, 100, .55);
  background: var(--surf-72);
  color: var(--txt);
  font-size: 15px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  transition: border-color .15s, background .15s, transform .1s;
}
.as-step:hover:not(:disabled) { border-color: var(--gold-95); background: rgba(255, 250, 226, .95); }
.as-step:active:not(:disabled) { transform: scale(.92); }
.as-step:disabled { opacity: .38; cursor: not-allowed; }
.as-input {
  width: 76px;
  height: 38px;
  text-align: center;
  font-size: 18px;
  font-weight: 800;
  color: var(--txt);
  border-radius: var(--r-2);
  border: 1px solid rgba(108, 148, 100, .55);
  background: var(--surf-88);
  font-family: inherit;
  padding: 0 4px;
}
.as-input:focus { outline: none; border-color: #3d6b3a; box-shadow: 0 0 0 3px rgba(61, 107, 58, .18); }
/* 隐藏原生 number 上下箭头（只保留我们自己的 ◀ ▶ 两个箭头按钮） */
.as-input::-webkit-outer-spin-button,
.as-input::-webkit-inner-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
.as-input { -moz-appearance: textfield; appearance: textfield; }
.as-note {
  margin: 14px 0 0;
  font-size: 12px;
  line-height: 1.7;
  color: var(--dim);
  text-align: center;
}
@media (max-width: 520px) {
  .as-input { width: 62px; font-size: 16px; }
  .as-step { width: 34px; height: 34px; }
  .as-count { gap: 6px; }
  .as-count-label, .as-count-unit { font-size: 12px; }
}

/* ============ 图鉴 / 放大卡牌 ============ */
.codex-modal {
  width: min(1040px, 94vw);
  max-height: 88vh;
  padding: 16px 18px;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
}
.codex-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.codex-head h2 { font-size: 20px; letter-spacing: 1px; margin: 0; color: var(--txt); }
.codex-count { color: var(--dim); font-size: 12px; }
.codex-tip { color: var(--dim2); font-size: 11px; }
.codex-close { margin-left: auto; }

.codex-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: 12px;
  overflow-y: auto;
  padding: 6px 2px 10px;
  min-height: 0;
}
.codex-card { width: 100%; }
.codex-card:hover { border-color: rgba(242, 201, 76, .85); box-shadow: 0 0 0 2px rgba(242, 201, 76, .45); }

/* 放大查看 */
.zoom-mask { z-index: var(--z-zoom); }
.zoom-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 26px 40px 22px;
  background: linear-gradient(180deg, #f8fcf1, #e5efd9);
  border: 1px solid var(--frame);
  border-radius: var(--r-6);
  box-shadow: 0 20px 60px var(--shadow-green);
  max-height: 92vh;
  overflow-y: auto;
  max-width: 96vw;
}
/* 放大卡面：桌面的尺寸档（衍生卡 / 登场 / 弃牌都带 .zoom-card，只在自己的上下文里改这几行） */
.zoom-card {
  --badge: 46px; --badge-fs: 21px; --badge-bw: 2.5px; --spell-fs: 21px;
  --seal-fs: 64px;
  --icon-fs: 64px; --art-icon-fs: 76px;
  --art-w: 240px; --art-m: 8px auto 6px; --art-r: var(--r-4);
  --name-fs: 22px; --text-fs: 15px; --text-lh: 1.6;
  width: 250px;
  padding: 12px 14px 18px;
  border-radius: var(--r-6);
  animation: rise .28s ease;
}
.zoom-card .hc-icon { margin: 10px 0 4px; }
.zoom-card .hc-name { margin-top: 4px; }
.zoom-card .hc-text { margin-top: 12px; }

/* 放大查看的详情区（卡图**下方**那一块）：**只写卡面说不了的当前状态** —— 卡图 / 卡名 / 费用与威力角标 /
   效果文本都在卡面上，这里不再复述（数值条与效果分类标签已取消）。从上到下：状态行（费用递减计数）→
   边界提示（封印 / 静海 / 法界）→ 没有卡面文本时的兜底说明；空块不占位。
   ⚠️ 战力构成段（.power-panel）不在这里 —— 它独立占弹窗**顶部**。 */
.zoom-info { text-align: center; color: var(--dim); font-size: 14px; line-height: 1.9; max-width: 440px; }
.zoom-info.no-text { display: none; } /* 状态 / 提示 / 兜底都没有（多数图鉴卡与手牌卡）⇒ 整块收起，不留空白 */
.zm-state {
  background: rgba(242, 201, 76, .16);
  border: 1px solid rgba(200, 156, 40, .38);
  border-radius: var(--r-2);
  padding: 4px 14px;
  margin: 0 auto 6px;
  color: #7a5a00;
  font-weight: 700;
}
.zm-note { margin: 0 auto 6px; color: #a3541f; font-weight: 700; }
.zm-desc { margin-top: 4px; color: var(--txt); }

/* 放大视图：主卡信息与右侧“衍生卡牌”并排 */
.zoom-row {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: flex-start;
  justify-content: center;
  width: 100%;
}
.zoom-main-col { display: flex; flex-direction: column; align-items: center; gap: 14px; max-width: 460px; }
.zoom-deriv {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 16px 18px 18px;
  border: 1px dashed rgba(126, 168, 118, .6);
  border-radius: var(--r-6);
  background: rgba(238, 247, 226, .55);
  min-width: 196px;
  align-self: stretch;
  justify-content: flex-start;
}
.zoom-deriv .deriv-head { font-size: 13px; font-weight: 800; color: var(--dim); letter-spacing: 2px; white-space: nowrap; }
/* 放大视图里的衍生小卡（.zoom-card + .deriv-card）：
   · 角标固定小一号 —— 用 `.zoom-card.deriv-card` 这条规避开「≤700 的手牌档」把它一起收小；
   · 卡宽与文字则与放大主卡同档：≤700 吃手牌档、≤640 吃放大手机档（现状如此，未在本轮改动）。 */
.zoom-card.deriv-card { --badge: 34px; --badge-fs: 16px; --spell-fs: 16px; }
.deriv-card {
  --icon-fs: 46px;
  --name-fs: 17px; --text-fs: 11px; --text-lh: 1.5;
  width: 260px;
}
.deriv-card .hc-icon { margin: 6px 0 2px; }
.deriv-card .hc-text { margin-top: 8px; overflow-wrap: anywhere; }
@media (max-width: 760px) {
  .zoom-row { flex-direction: column; align-items: center; }
  .zoom-deriv { width: min(320px, 92vw); }
}

/* 衍生卡牌区（桌面）：把详情弹窗放宽，保证「本体卡 + 衍生卡」两列都能完整展示 */
.zoom-stage { width: min(880px, 96vw); }
.zoom-row { justify-content: center; }
.zoom-main-col { flex: 1 1 auto; }
.zoom-deriv { flex-shrink: 0; min-width: 300px; align-self: stretch; }
/* ⚠️ 衍生卡的立绘区沿用 .zoom-card 的 --art-w（240px）：卡宽 260px − 内边距 28px ＝ 232px，
   立绘区比内容宽度大 8px。这是**现状**（下面那条 224px 的历史覆写被 .zoom-card 的规则压住，
   从未生效），本轮不动它，留给阶段 3 一起收。 */

/* v102：没有衍生卡的卡牌详情弹窗整体收窄（renderDeriv 加 .no-deriv） */
.zoom-stage.no-deriv {
  width: min(520px, 94vw);
  padding: 22px 26px;
}
@media (max-width: 760px) {
  .zoom-stage.no-deriv { width: 94vw; padding: 18px 12px; }
}

/* 放大/手牌卡面上的增减益威力配色 */
.hand-card .p.up { color: var(--up); border-color: var(--up); }
.hand-card .p.down { color: var(--down); border-color: var(--down); }

/* ===== 战力影响历史：放大弹窗**顶部**独立的一条「战力构成」段 =====
   铺在卡图之上、不占详情区；形态＝一列**小方块**（高度大于宽度），每枚一次战力增减：
   上方 `±N`、下方来源，横向铺开，来源多时左右滑 —— 不做纵向滚动、不撑高弹窗。
   只出现在场上已翻开卡的放大弹窗里（手牌 / 图鉴 / 牌池隐藏）。 */
.zoom-mask { gap: 24px; flex-wrap: wrap; align-items: center; align-content: center; padding: 18px; overflow: auto; }
.power-panel {
  width: 100%;
  padding: 10px 14px 12px;
  border: 1px solid rgba(126, 168, 118, .45);
  border-radius: var(--r-4);
  background: rgba(238, 247, 226, .62);
  text-align: left;
}
.pp-label { font-size: 11px; font-weight: 800; letter-spacing: 2px; color: var(--dim); margin-bottom: 6px; }
.pp-rows {
  display: flex;
  align-items: stretch;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 3px;
  scrollbar-width: thin;
}
.pp-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  flex: 0 0 auto;
  width: 52px;
  min-height: 52px;
  padding: 4px 2px;
  border-radius: var(--r-2);
  background: rgba(122, 158, 110, .14);
  border: 1px solid rgba(108, 148, 100, .34);
  color: #4a5f44;
}
.pp-chip .pp-num { font-size: 15px; font-weight: 800; line-height: 1.15; font-variant-numeric: tabular-nums; }
.pp-chip .pp-lab {
  font-style: normal;
  font-size: 9.5px;
  line-height: 1.2;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #5c7355;
}
.pp-chip.up .pp-num { color: #1f9e57; }    /* 提高 +N：绿 */
.pp-chip.down .pp-num { color: var(--down-ink); }  /* 降低 −N：红 */
.pp-chip.base .pp-num { color: var(--txt); }
.pp-chip.pp-total { background: rgba(242, 201, 76, .2); border-color: rgba(200, 156, 40, .55); }
.pp-chip.pp-total .pp-num { color: #7a5a00; }

/* ============ 卡牌图片素材（assets/cards/） ============ */
/* 手牌/图鉴/放大卡面：图片占方形艺术区；缺图时垫底 emoji 透出 */
.hc-art {
  position: relative;
  width: var(--art-w, calc(100% - 4px));
  aspect-ratio: 1 / 1;
  margin: var(--art-m, 4px auto 2px);
  border-radius: var(--art-r, var(--r-1));
  overflow: hidden;
  background: rgba(120, 150, 110, .12);
  flex: 0 0 auto;
}
.hc-art .hc-icon {
  position: absolute; inset: 0; margin: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--art-icon-fs, 32px);
}
.hc-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 2;
  border-radius: inherit;
}
/* 立绘区宽度 / 圆角 / 外边距全部由 .card-face 的 --art-w / --art-r / --art-m 给出，
   手牌与图鉴等上下文不吃额外覆写（原来是这里的 .hand-card .hc-art 与 .zoom-card .hc-art 两条） */

/* 场上缩略卡（2×2 格位）：有图时，图片保持正方形，
   边长 = 卡位高度（横向居中），完整显示不裁切；
   左右两侧的余量留给 费用(左) / 战力(右) 数字 */
.mini-card.has-art { overflow: hidden; }
.mini-card.has-art .mini-img {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  height: 100%;
  width: auto;
  aspect-ratio: 1 / 1;
  transform: translateX(-50%);
  object-fit: cover;
  object-position: center;
  z-index: 2;
}
.mini-card.has-art .mc-shade {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--ink-2) 40%, var(--ink-45) 100%);
  z-index: 3;
}
.mini-card.has-art .mc-icon {
  position: absolute; top: 50%; left: 0; right: 0;
  transform: translateY(-50%);
  text-align: center; margin: 0;
  z-index: 1;
  font-size: clamp(16px, 2.6vh, 26px);
  opacity: .9;
}
.mini-card.has-art .mc-cost {
  top: 50%;
  left: 3px;
  transform: translateY(-50%);
  z-index: 5;
}
.mini-card.has-art .p {
  top: 50%;
  right: 3px;
  left: auto;
  transform: translateY(-50%);
  z-index: 5;
}
.mini-card.has-art .mc-name {
  position: absolute;
  bottom: 3px;
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  z-index: 4;
  font-size: clamp(10px, 1vw + .4vh, 13px);
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: calc(100% - 96px);
  text-shadow: 0 1px 3px var(--ink-92);
}
.mini-card.has-art .mc-mod { z-index: 5; }

/* ============ 2×2 格位线 + 空位/隙间占位 ============ */
/* 所有区域的敌我两侧都画出 2×2 浅灰网格（中线随 gap 落在两格之间） */
.zone .slot-row { position: relative; }
.zone .slot-row.quad::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    linear-gradient(to right, transparent calc(50% - 1px), rgba(150, 158, 150, .5) 50%, transparent calc(50% + 1px)),
    linear-gradient(to bottom, transparent calc(50% - 1px), rgba(150, 158, 150, .5) 50%, transparent calc(50% + 1px));
}
/* max=4 时空格位的浅灰虚线框 */
.cell-guide {
  border: 1px dashed rgba(150, 158, 150, .45);
  border-radius: var(--r-1);
  background: var(--surf-9l);
}
/* max<4 时空格位的透明占位（保持左上→右下锚定） */
.cell-spacer { display: block; }
/* 不允许放卡的格位：灰色「隙间」占位卡，开局即生成、不可操作 */
.slot-gap {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border-radius: 9px;
  background: linear-gradient(160deg, #57515f, #322e3c);
  border: 1px dashed rgba(198, 180, 240, .35);
  color: #c6b4e8;
  cursor: default;
  user-select: none;
  box-shadow: inset 0 0 10px var(--ink-35);
}
.slot-gap .gap-glyph { font-size: 15px; line-height: 1; opacity: .85; letter-spacing: 1px; }
.slot-gap .gap-name { font-size: 10px; opacity: .9; text-shadow: 0 0 6px rgba(150, 120, 230, .6); }
.slot-gap:hover { filter: none; box-shadow: inset 0 0 10px var(--ink-35); }

/* ================================================================
   手机 / 触屏适配（追加在文件末尾，级联优先级高于前面的断点规则）
   ----------------------------------------------------------------
   1. ≤900px（手机竖屏 / 小平板竖屏）：切「App 壳」布局 —— 页面不再
      整页滚动，顶栏 + 状态条固定在上、手牌条固定在下，只有中间的
      场地/侧栏区域滚动，保证任何时候都能看到回合/能量与手牌。
   2. ≤700px 进一步紧凑：顶栏、HUD、手牌、按钮收小，把高度让给场地。
   3. 触屏细节：禁双击缩放/长按菜单，消除点按高亮，可点元素
      touch-action: manipulation（去掉 300ms 延迟与误缩放）。
   4. 全面屏安全区：刘海/圆角/Home 条用 env(safe-area-inset-*) 让位。
   ================================================================ */

/* -- 安全区变量（无刘海设备为 0） -- */
:root {
  --sa-top: env(safe-area-inset-top, 0px);
  --sa-right: env(safe-area-inset-right, 0px);
  --sa-bottom: env(safe-area-inset-bottom, 0px);
  --sa-left: env(safe-area-inset-left, 0px);
}

/* -- 触屏基础（全屏宽均生效，桌面无副作用） -- */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { -webkit-tap-highlight-color: transparent; }
.btn,
.hand-card,
.codex-card,
.location.hoverable,
.mini-card.can-inspect,
.energy-chip {
  touch-action: manipulation;
}

/* 手机端状态条：默认隐藏（桌面仍用侧栏 #statusCard） */
.mob-status { display: none; }

/* ========== 断点一：≤900px —— App 壳 ========== */
@media (max-width: 900px) {
  html, body { height: 100%; overflow: hidden; }
  body { height: 100vh; min-height: 0; }
  @supports (height: 100dvh) {
    body { height: 100dvh; min-height: 0; }
  }

  /* 顶栏：可换行 + 避开刘海/圆角（「加倍」现在**在手机上也显示**，见 ≤700px 的两行排布） */
  .topbar {
    flex-wrap: wrap;
    row-gap: 6px;
    padding: calc(8px + var(--sa-top)) calc(10px + var(--sa-right)) 8px calc(10px + var(--sa-left));
  }

  /* 状态条常驻：**默认只占 1 行**（长提示点一下展开看全文），同步更新见 js/game.js 的 setStatus() */
  .mob-status {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    flex: 0 0 auto;
    padding: 6px 12px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--txt);
    background: linear-gradient(180deg, var(--surf-78), rgba(246, 251, 240, .5));
    border-top: 1px solid rgba(108, 148, 100, .18);
    border-bottom: 1px solid rgba(108, 148, 100, .3);
  }
  .mob-status .status-text {
    flex: 1 1 auto;
    min-width: 0;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .mob-status.open .status-text { -webkit-line-clamp: 6; }
  /* 文案被截断时才给「展开」提示（.clamped 由 setStatus() 量出来挂上） */
  .mob-status.clamped { cursor: pointer; }
  .mob-status.clamped::after { content: '▾'; flex: 0 0 auto; color: var(--dim); font-size: 11px; line-height: 1.7; }
  .mob-status.clamped.open::after { content: '▴'; }
  .mob-status.busy .status-text { color: var(--green); }

  /* 中间主区：唯一滚动区域（覆盖桌面 grid 为纵向 flex） */
  .layout {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    gap: 12px;
    padding: 10px 12px 8px;
    scrollbar-width: thin;
  }
  .board-wrap { flex: 0 0 auto; min-height: 0; }
  .side { order: 2; flex: 0 0 auto; }

  /* 底部手牌区固定不收缩（v109：底部留白加大，避开角落“认输/结束回合”按钮） */
  .hand-wrap {
    flex: 0 0 auto;
    padding-bottom: calc(42px + var(--sa-bottom));
  }
  /* 手牌横向滚动：隐藏滚动条，更干净 */
  .hand { scrollbar-width: none; }
  .hand::-webkit-scrollbar { display: none; }

  /* 底部三块（认输 / 能量+手牌 / 结束回合）整体贴到最下沿 —— 只留 4px + 安全区
     （安全区在刘海屏上自动让开 Home 条；手牌区的下内边距仍是 42/48px，不会盖住手牌） */
  .corner-actions { bottom: calc(4px + var(--sa-bottom)); }
  .corner-left { left: calc(12px + var(--sa-left)); }
  .corner-right { right: calc(12px + var(--sa-right)); }
  .corner-actions .btn { padding: 9px 13px; font-size: 13px; }

  .foot { display: none; }
}

/* ========== 断点二：≤700px —— 紧凑排版 ========== */
@media (max-width: 700px) {
  /* 顶栏改成**两行网格**（手机上按钮不再挤成一排图标）：
       第一行：品牌（左，点它回主页面）· 「回合：x/N」居中 · 右侧一组＝赌注 + 加倍（加倍在最右端）
       第二行：图鉴 / 重新开始（**带文字**；开发调试按钮也在这一行，联机时「重新开始」被 JS 收掉）
     `display: contents` 让 .hud 的两个子块直接成为网格项，省掉一层容器。 */
  .topbar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 8px;
    row-gap: 6px;
    padding: calc(6px + var(--sa-top)) calc(8px + var(--sa-right)) 6px calc(8px + var(--sa-left));
  }
  .brand { grid-area: 1 / 1; justify-self: start; min-width: 0; }
  .brand .logo { font-size: 23px; }
  .brand h1 { font-size: 16px; letter-spacing: 1px; }
  .brand .sub { display: none; }

  .hud { display: contents; }
  #turnBox { grid-area: 1 / 2; justify-self: center; }
  .hud-right { grid-area: 1 / 3; justify-self: end; gap: 6px; }
  .hud-item { padding: 3px 9px; gap: 4px; }
  .hud-label { display: none; }
  .hud-value, .hud-item.cubes .cube { font-size: 16px; }
  .cube-pips span { width: 6px; height: 6px; }
  /* 第二行＝图鉴 / 重新开始（**带文字**）+ 开发调试按钮：整行**靠右对齐** */
  .top-actions { grid-area: 2 / 1 / 3 / 4; gap: 6px; justify-content: flex-end; }
  .btn { padding: 6px 10px; font-size: 12px; }

  .layout { gap: 10px; padding: 8px 10px 6px; }
  .board { gap: 10px; min-height: 0; }

  /* 底部手牌：卡片收小；v109 底部再抬高避开按钮 */
  .hand-wrap { padding-top: 4px; padding-bottom: calc(48px + var(--sa-bottom)); }
  /* 能量点并入顶栏能量框（顶栏已显示「剩余 / 上限 ↺」，点它就能重置暗牌）：
     手机上不再让这条单独占一行 —— 高度直接让给场地 */
  .energy-pips { display: none; }
  .hand {
    min-height: 118px;
    gap: 8px;
    padding-top: 2px;
    padding-bottom: 2px;
    padding-left: 84px;
    padding-right: 84px;
  }
  /* 手牌卡面（≤700px 的尺寸档）：只改变量；其余带 .hand-card 的卡面
     （图鉴 / 卡组页 / 放大弹窗等）会在各自断点里再覆盖自己那几档 */
  .hand-card {
    --badge: 21px; --badge-fs: 11px; --badge-bw: 1.5px; --spell-fs: 11px;
    --icon-fs: 25px; --art-icon-fs: 25px;
    --art-m: 3px auto 1px;
    --name-fs: 11px; --text-fs: 7.6px; --text-lh: 1.25;
    width: 72px;
    padding: 4px 4px 6px;
    border-radius: var(--r-2);
  }
  .hand-card .hc-icon { margin: 2px 0 0; }
  .hand-card .hc-text { margin-top: 2px; }
}

/* ========== 断点三：≤640px —— 三区域横向并列（手机竖屏） ==========
   手机窄屏不纵向堆叠，改为三列紧凑横排：
   每列 ≥112px（屏再窄则整板可横向微滚动），列高由内容撑起，
   头部/中间带/卡位/分数均按窄列收小，保证一屏能同时看到三块区域。 */
@media (max-width: 640px) {
  /* v104：三块区域等分占满整宽，不再整板横向滚动；单行网格使三列始终等高 */
  .board {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: minmax(0, 1fr);
    gap: 6px;
    min-height: 0;
    overflow: hidden;
  }

  .location { border-radius: var(--r-3); min-height: 0; height: 100%; }
  .loc-head { padding: 4px 6px 3px; }
  .loc-name { font-size: 12.5px; }
  .loc-name .icon { font-size: 13px; }
  .loc-mid { gap: 3px; padding: 5px 4px; }
  .loc-mid .loc-effect { font-size: 10.5px; gap: 3px; }
  .loc-total { gap: 4px; padding: 2px 6px; }
  .loc-total .lt-label { font-size: 9.5px; }
  .loc-total .lt-num { font-size: 15px; min-width: 20px; }
  .zone { min-height: 112px; gap: 3px; padding: 4px 4px; }
  .zone .slot-row { gap: 3px; padding: 0; }
  .slot-count { font-size: 8.5px; bottom: 3px; left: 5px; }
  .mini-card {
    --mc-cost-fs: 11px; --mc-cost-min: 16px;
    --mc-p-fs: 12px; --mc-p-min: 17px; --mc-spell-fs: 12px;
    padding: 4px 2px 3px;
    border-radius: var(--r-1);
  }
  .mini-card .mc-cost { top: 2px; left: 2px; padding: 0 3px; border-radius: 5px; }
  .mini-card .p, .mini-card .mc-spell { top: 2px; right: 2px; padding: 0 3px; border-radius: 5px; }
  .slot-gap { border-radius: var(--r-1); }
  .slot-gap .gap-glyph { font-size: 12px; }
  .slot-gap .gap-name { font-size: 8px; }
}

/* ========== 断点四：≤560px —— 弹窗 / 图鉴适配小屏 ========== */
@media (max-width: 520px) {
  .modal { padding: 24px 16px; border-radius: var(--r-4); max-height: 88vh; overflow-y: auto; }
  .modal h2 { font-size: 22px; }
  .codex-modal {
    width: 100vw;
    max-height: 94vh;
    padding: 10px 8px 14px;
    border-radius: 16px 16px 0 0;
    border-bottom: none;
  }
  .codex-head { gap: 6px; }
  .codex-tip { display: none; }
  .codex-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
  .undo-btns .btn, .modal-btns .btn { min-width: 0; flex: 1; }
  .undo-btns, .modal-btns { gap: 8px; }
}

/* ========== 矮视口（手机横屏 / 小平板横放）——本文件唯一的 max-height 档 ==========
   场地高度优先：压缩顶部与手牌、隐藏能量小点；同时对局开始的卡面揭示也收小。
   ⚠️ 阈值 620px（原 640/620/560 三档合并而来）：521~620px 高度区间现在也吃这一套收小规则。 */
@media (max-height: 620px) {
  .gs-reveal .zoom-card { --text-fs: 11.5px; width: 168px; }
  .brand .sub { display: none; }
  .brand h1 { font-size: 15px; }
  .brand .logo { font-size: 22px; }
  .hud-item { padding: 2px 8px; }
  .energy-pips { display: none; }
  .hand-wrap { padding-top: 2px; }
  .hand { min-height: 96px; }
  .hand-card { width: 66px; }
}

/* v92：图鉴 / 指定卡牌页 —— 费用筛选条（全部 / 0-1 / 2 / 3 / 4 / 5 / 6 费） */
/* v178：图鉴 / 「指定卡牌」的两层筛选 —— 第 1 层「卡池切换」按钮条
   （普通卡牌池 / 衍生卡牌池），第 2 层是它下面的费用档 .card-filter-bar。
   卡组页 #deckFilter 仍是原来的扁平筛选条，不受这里影响。 */
.card-pool-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 2px 18px 6px;
}
.card-pool-bar .pool-btn {
  appearance: none;
  font: inherit;
  flex: 1 1 0;
  min-width: 118px;
  border: 1px solid rgba(124, 164, 110, .55);
  background: #ffffff;
  color: #3d5a33;
  border-radius: var(--r-2);
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s, box-shadow .15s;
}
.card-pool-bar .pool-btn:hover { border-color: #7daa62; background: #f2f9ea; }
.card-pool-bar .pool-btn.active {
  background: linear-gradient(160deg, #4a8a3c, #2f5f27);
  color: #ffffff;
  border-color: #2f5f27;
  box-shadow: 0 0 0 2px rgba(63, 122, 51, .25), 0 2px 6px rgba(47, 95, 39, .22);
}
.card-filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 2px 18px 12px;
}
.card-filter-bar .chip {
  appearance: none;
  font: inherit;
  border: 1px solid rgba(124, 164, 110, .55);
  background: #ffffff;
  color: #3d5a33;
  border-radius: var(--r-pill);
  padding: 3px 13px;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s, box-shadow .15s;
}
.card-filter-bar .chip:hover { border-color: #7daa62; background: #f2f9ea; }
.card-filter-bar .chip.active {
  background: #3f7a33;
  color: #ffffff;
  border-color: #2f5f27;
  box-shadow: 0 0 0 2px rgba(63, 122, 51, .25);
}
.codex-empty {
  grid-column: 1 / -1;
  color: #7a8a6f;
  padding: 28px 0;
  text-align: center;
  font-size: 14px;
}
/* v97：衍生卡牌（token）在网格里的视觉区分 */
.codex-grid .codex-card.token-card {
  outline: 1px dashed rgba(120, 92, 170, .6);
  outline-offset: -2px;
}

/* v106→v108：手机端(≤640)地形列收口（v108 更正：效果“讲解说明”仍保留在中间带原位；
   仅隐藏列底部的“已放 x/4 / 第 N 回合揭晓/开放”小字） */
@media (max-width: 640px) {
  .slot-count { display: none; }
}

/* v110→v111：手机端（≤640px）图鉴 / 指定卡牌弹窗的卡片简略显示——
   只隐藏效果文字说明（保留卡名），保留 卡名/费用/战力 + 图片（或 emoji） */
@media (max-width: 640px) {
  #codexGrid .codex-card .hc-text,
  #pickGrid .codex-card .hc-text { display: none; }
  #codexGrid .codex-card,
  #pickGrid .codex-card {
    --badge: 20px; --badge-fs: 10px; --spell-fs: 10px;
    --icon-fs: 30px; --art-icon-fs: 30px;
    padding: 5px 3px 7px;
  }
  /* ⚠️ 立绘区的上下边距在这里**只能用带 #id 的选择器**：≤700px 那条 `.hand-card .hc-art { margin-top: 6px }`
     特异度高于 `.hc-art`，只有 ID 级选择器能把它按回 3px（与改动前的取值一致）。 */
  #codexGrid .codex-card .hc-art,
  #pickGrid .codex-card .hc-art { margin: 3px auto 2px; }
  #codexGrid,
  #pickGrid {
    grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
    gap: 8px;
  }
}

/* v112：手机端（≤640px）卡牌详情弹窗收小 —— 缩小卡牌本体与立绘，
   让“场上卡牌 + 战力影响历史”等详情不再过大 */
@media (max-width: 640px) {
  .zoom-stage {
    width: min(440px, 94vw);
    padding: 14px 10px;
    gap: 12px;
  }
  .zoom-card {
    --badge: 30px; --badge-fs: 14px; --badge-bw: 2px; --spell-fs: 14px;
    --icon-fs: 34px; --art-icon-fs: 34px;
    --art-w: min(140px, 46vw); --art-m: 4px auto 3px; --art-r: var(--r-2);
    --name-fs: 15px; --text-fs: 12px; --text-lh: 1.45;
    width: min(176px, 58vw);
    padding: 8px 8px 12px;
    border-radius: var(--r-4);
  }
  .zoom-card .hc-text { margin-top: 8px; }
  .zoom-info { max-width: 330px; font-size: 12.5px; line-height: 1.7; }
  .power-panel { padding: 8px 10px 10px; }
  .pp-chip { width: 44px; min-height: 44px; }
  .pp-chip .pp-num { font-size: 13px; }
  .pp-chip .pp-lab { font-size: 9px; }
}

/* v113：手机端（≤700px）手牌高度压缩——
   费用/战力角标不再占独立一行，改为绝对定位于卡片上部并下移约一半、
   轻微遮挡立绘顶部；省出的行高让卡片整体变矮 */
@media (max-width: 700px) {
  .hand-card { padding-top: 2px; }
  .hand-card .hc-top {
    position: absolute;
    left: 3px;
    right: 3px;
    top: 4px;               /* v113→v114：仅轻压立绘上缘（约为原来的半压程度） */
    z-index: 3;
    pointer-events: none;
  }
  .hand-card .hc-art { margin-top: 6px; }
  .hand-card.no-img .hc-icon { margin-top: 6px; }
}

/* v115：手机端手牌侧边距收窄 —— 角落按钮在 v109 已与手牌垂直分开，
   不再需要 84px 让位；收窄后手牌内容可居中/贴边，避免左侧空出一张牌的空间 */
@media (max-width: 900px) {
  .energy-pips { padding-left: 14px; padding-right: 14px; }
  .hand { padding-left: 14px; padding-right: 14px; }
}

/* 认输 与 结束回合 中间：能量块 + 手牌计数（两块居中并排） */
.corner-center {
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  align-items: center;
}
.hand-count-chip {
  font-size: 13px;
  font-weight: 800;
  color: var(--txt);
  background: var(--surf-92);
  border: 1px solid rgba(124, 164, 112, .45);
  border-radius: var(--r-pill);
  padding: 6px 16px;
  box-shadow: 0 6px 16px var(--shadow-green);
  backdrop-filter: blur(4px);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* 底部两块计数都可点（.corner-center 整体是 pointer-events:none，只有它们各自放开）：
   .energy-chip ＝ 重置本回合暗出的牌；.hand-chip ＝ 在「手牌：N/7」与「牌库：N」之间切换 */
.energy-chip,
.hand-chip { pointer-events: auto; cursor: pointer; transition: border-color .2s, box-shadow .2s, background .2s; }
.hand-chip:hover {
  border-color: rgba(124, 168, 110, .85);
  box-shadow: 0 0 12px rgba(124, 168, 110, .3);
  background: #f2f9ea;
}
.hand-chip:active { transform: scale(.97); }
@media (max-width: 700px) {
  /* 底部三块（认输 / 两块计数 / 跳过回合）要挤在同一行：内边距与间距收紧，
     否则 360px 宽的机器上中间两块会与两侧按钮叠在一起 */
  .corner-center { gap: 5px; }
  .hand-count-chip { font-size: 12px; padding: 4px 10px; }
}
/* 极窄屏（≤350px）兜底：只留数字，避免与两侧按钮重叠（能量块上的 ↺ 仍在，仍可点） */
@media (max-width: 350px) {
  .chip-label { display: none; }
}

/* 底部能量块：**重置本回合暗出牌的唯一入口**（顶栏不再有能量框）。
   文字用金黄色，与计数块区分。 */
.energy-chip {
  color: #9c6a00;   /* 金黄色（白底约 4.7:1，再亮就看不清了 —— 与全站其它金色 #c99400 / #b57708 同一族） */
  border-color: rgba(201, 148, 0, .45);
}
.energy-chip #energyChipVal { color: #8a5d00; }
.energy-chip:hover {
  border-color: #c99400;
  box-shadow: 0 0 12px rgba(224, 163, 22, .35);
  background: rgba(255, 240, 190, .9);
}
.energy-chip:active { transform: scale(.97); }
@media (max-width: 700px) {
  .energy-chip { font-size: 12px; padding: 4px 9px; }
}

/* ===== 底部三块**同高对齐** =====
   认输 / 结束回合（.corner-actions .btn）与中央的「能量 / 手牌」计数块用一个显式高度：
   改前计数块的字号与内边距都比按钮小，矮了约 10px。这里统一 height + 居中排布，
   不再依赖各自的字体度量（放最后，压过上面按断点写的内边距）。 */
.corner-actions .btn,
.hand-count-chip {
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-top: 0;
  padding-bottom: 0;
}

/* ============================================================
   v120：主页面（打开游戏先显示本页）／v121：卡组设置页面共用本段规则
   - 标记在 index.html（#homeScreen / #deckScreen 静态结构），
     <body class="in-home"> / <body class="in-deck"> 时对应页面显示；
   - 独立页面均为全屏不透明层（主页面 z-index 200、卡组页 45），
     同时 body:is(.in-home, .in-deck) 期间把游戏区整体 display:none——
     游戏侧 fixed 悬浮层演出（gain-ring 9400 / fly-card / 碎片）在元素尺寸为 0 时
     本就会自行退出，隐藏后更不会串到页面上；
   - 配色沿用幻想乡淡绿主题（:root 变量），背景漂浮图标同 v75「未揭示」列手法。
   ============================================================ */
body:is(.in-home, .in-deck) { overflow: hidden; }
/* v121：进入独立页面（主页面 / 卡组设置页）时隐藏整个游戏区；
   卡组页**不**隐藏 .modal-mask——放大查看卡牌复用游戏的 #zoomMask（z-index 60），
   需盖在卡组页（z-index 45）之上。 */
body:is(.in-home, .in-deck) .topbar,
body:is(.in-home, .in-deck) .layout,
body:is(.in-home, .in-deck) .mob-status,
body:is(.in-home, .in-deck) .hand-wrap,
body:is(.in-home, .in-deck) .foot,
body:is(.in-home, .in-deck) .corner-actions { display: none; }
/* 主页面态：连游戏弹窗一起隐藏（主页面不承载任何游戏弹窗） */
body.in-home .modal-mask { display: none; }
/* v137：出战卡组选择弹窗挂在主页流程上，需盖过首页（z-index 200） */
body.in-home #battleDeckMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal-battle);
}
/* 挑战码弹窗（主页面「🔗 挑战码」打开）：与图鉴同为"挂在主页流程上的游戏弹窗"，需盖过首页（z-index 200） */
body.in-home #challengeMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal);
}
/* 挑战码弹窗要能开在**结算弹窗之上**：两者都是 .modal-mask（z-index 50），不抬起来就会被
   DOM 里更靠后的结算弹窗盖住 —— 表现是"点了生成挑战码，什么都没出现"（框里其实已经有码了） */
#challengeMask {
  z-index: var(--z-challenge);
}

.home-screen {
  position: fixed;
  inset: 0;
  z-index: var(--z-screen-home);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: hidden;
  background:
    radial-gradient(1000px 560px at 50% -12%, rgba(255, 248, 205, .92), transparent 62%),
    radial-gradient(860px 540px at 6% 110%, rgba(146, 216, 150, .5), transparent 62%),
    radial-gradient(780px 500px at 98% 106%, rgba(208, 240, 255, .58), transparent 62%),
    linear-gradient(168deg, #f2f8e6 0%, #dfeecd 48%, #d2e7bf 100%);
}

/* 背景装饰：随机散布的地形/道具图标，缓慢漂浮（不挡交互） */
.home-decor { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.home-decor span {
  position: absolute;
  opacity: .28;
  filter: saturate(.85);
  animation: homeFloat 7s ease-in-out infinite;
  will-change: transform;
}
@keyframes homeFloat {
  0%, 100% { transform: translateY(0) rotate(var(--rot, 0deg)); }
  50% { transform: translateY(-14px) rotate(calc(var(--rot, 0deg) + 8deg)); }
}

.home-inner {
  position: relative;
  z-index: 1;
  width: min(520px, 94vw);
  max-height: 94vh;
  overflow-y: auto;
  padding: 30px 30px 20px;
  text-align: center;
  border-radius: 22px;
  border: 1px solid var(--frame);
  background: linear-gradient(180deg, var(--surf-93), rgba(243, 250, 233, .9));
  box-shadow: 0 24px 70px rgba(46, 78, 40, .28);
  animation: rise .34s ease;
}

.home-brand { margin-bottom: 22px; }
.home-logo { display: block; font-size: 54px; line-height: 1; filter: drop-shadow(0 0 12px rgba(214, 166, 20, .6)); }
.home-title { font-size: 34px; letter-spacing: 8px; margin: 8px 0 6px; color: var(--txt); }
.home-sub { font-size: 12.5px; color: var(--dim); }

/* 主入口按钮 */
.home-menu { display: flex; flex-direction: column; gap: 12px; }
.home-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 16px;
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  color: var(--txt);
  cursor: pointer;
  border: 1px solid rgba(108, 148, 100, .45);
  border-radius: var(--r-4);
  background: var(--surf-72);
  transition: transform .08s, background .2s, border-color .2s, box-shadow .2s;
}
.home-btn:hover {
  background: #fff;
  border-color: rgba(124, 168, 110, .75);
  box-shadow: 0 10px 24px rgba(46, 78, 40, .16);
  transform: translateY(-1px);
}
.home-btn:active { transform: scale(.985); }
.home-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.home-btn.primary {
  border: none;
  color: #3d2c00;
  background: linear-gradient(135deg, #e0a316, #f4c948);
  box-shadow: 0 12px 26px rgba(201, 148, 0, .34);
}
.home-btn.primary:hover { background: linear-gradient(135deg, #eab022, #ffd85e); }
/* 联机入口（.home-btn.net）：写法与「开始对战」(.home-btn.primary) 完全同款 —— 无边款、渐变底、
   同强度的光晕投影，只是把金色换成淡蓝（深蓝字）；一眼与其余入口分开 ——
   它是唯一会连自己的房间服务（worker/）的入口，其余都是本地功能。
   ⚠️ 同 .home-btn.dev：必须写在 .home-btn:hover 之后（同为 (0,2,0)，靠顺序压过白底 hover）。 */
.home-btn.net {
  border: none;
  color: #1f3f5c;
  background: linear-gradient(135deg, #7cc4ec, #b6e2fb);
  box-shadow: 0 12px 26px rgba(46, 130, 190, .34);
}
.home-btn.net:hover { background: linear-gradient(135deg, #8fcdf0, #cbe9fd); }
.home-btn.net .hb-sub { color: rgba(31, 63, 92, .78); }
.home-btn.net .hb-arrow { color: rgba(31, 63, 92, .55); }
/* 开发调试入口（.home-btn.dev）：淡绿渐变底 + 黑字，与旁边淡蓝的联机入口、金色主入口一眼分开。
   ⚠️ 必须写在 .home-btn:hover 之后：两者同为 (0,2,0)，靠顺序压过白底 hover。 */
.home-btn.dev {
  color: #000;
  border: none;
  background: linear-gradient(135deg, #45b47f, #7ad6a8);
  box-shadow: 0 10px 24px rgba(69, 180, 127, .34);
}
.home-btn.dev:hover {
  background: linear-gradient(135deg, #57c490, #93e2bd);
  box-shadow: 0 12px 28px rgba(69, 180, 127, .44);
}
.home-btn.dev .hb-sub { color: rgba(0, 0, 0, .72); }
.home-btn.dev .hb-arrow { color: rgba(0, 0, 0, .5); }
.hb-icon { flex: 0 0 auto; width: 34px; font-size: 26px; text-align: center; filter: drop-shadow(0 2px 6px var(--ink-12)); }
.hb-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.hb-main { font-size: 17px; font-weight: 800; letter-spacing: 1px; }
.hb-sub { font-size: 11.5px; line-height: 1.35; color: var(--dim); }
.home-btn.primary .hb-sub { color: rgba(61, 44, 0, .74); }
.hb-arrow { flex: 0 0 auto; margin-left: auto; font-size: 20px; color: rgba(46, 69, 39, .45); }
.home-btn.primary .hb-arrow { color: rgba(61, 44, 0, .5); }

/* 占位页面提示（后续页面实装前的反馈） */
.home-toast {
  margin-top: 16px;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 700;
  color: var(--up-ink);
  background: rgba(255, 248, 214, .96);
  border: 1px solid rgba(201, 148, 0, .45);
  border-radius: var(--r-3);
  box-shadow: 0 10px 24px rgba(46, 78, 40, .16);
}
.home-toast.pop { animation: rise .26s ease; }

.home-foot { margin-top: 18px; font-size: 11px; color: var(--hint); }

/* 手机端：收紧主页面卡片，保证三个按钮一屏可见 */
@media (max-width: 640px) {
  .home-screen { padding: 16px; }
  .home-inner { padding: 24px 18px 16px; border-radius: var(--r-6); }
  .home-logo { font-size: 44px; }
  .home-title { font-size: 27px; letter-spacing: 5px; }
  .home-sub { font-size: 11.5px; }
  .home-btn { padding: 12px 13px; gap: 11px; }
  .hb-icon { width: 28px; font-size: 22px; }
  .hb-main { font-size: 15.5px; }
  .hb-sub { font-size: 11px; }
}
@media (max-height: 620px) {
  .home-brand { margin-bottom: 14px; }
  .home-logo { font-size: 38px; }
  .home-title { font-size: 26px; margin: 4px 0 4px; }
  .home-btn { padding: 10px 14px; }
}

/* ============================================================
   v121：卡组设置页面
   - 结构：index.html 的 #deckScreen（静态骨架）+ js/deck-page.js（卡组位/卡牌网格）；
   - 版面：整页纵向 flex —— 上方 .deck-bar flex:1、下方 .deck-pool flex:2
     （≈ 1/3 : 2/3，与参考图一致）；
   - 层级：.deck-screen z-index 45（游戏弹窗 modal-mask 50 / zoom-mask 60 之上仍可见，
     所以点卡牌可复用 showZoom() 放大查看）；进入本页时 body.in-deck 隐藏游戏区；
   - 卡面复用游戏手牌样式（.card-face.hand-card + cardFaceHTML），仅覆盖宽度以适配网格。
   ============================================================ */
.deck-screen {
  position: fixed;
  inset: 0;
  z-index: var(--z-screen-deck);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
  overflow: hidden;
  color: var(--txt);
  background:
    radial-gradient(900px 460px at 50% -10%, rgba(255, 248, 205, .85), transparent 62%),
    radial-gradient(760px 460px at 4% 108%, rgba(146, 216, 150, .45), transparent 62%),
    linear-gradient(168deg, #f2f8e6 0%, #dfeecd 46%, #d2e7bf 100%);
}

/* ---------- 上方 1/3：标题 + 卡组栏 ---------- */
.deck-bar {
  flex: 1 1 0;
  min-height: 172px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-6);
  background: var(--surf-62);
  box-shadow: 0 14px 34px rgba(46, 78, 40, .14);
}
.deck-top { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.deck-title { display: flex; align-items: center; gap: 10px; }
.dt-icon { font-size: 26px; filter: drop-shadow(0 2px 6px var(--ink-12)); }
.deck-title h2 { font-size: 18px; letter-spacing: 2px; margin: 0; color: var(--txt); }
.dt-sub { font-size: 11px; color: var(--dim); }
.dt-sub b { color: #a97e00; }
.deck-top-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.deck-top-actions .bt-ico { margin-right: 4px; }
.deck-hint { font-size: 11px; color: var(--dim2); }

/* v134：bar-head 放在 deck-top 内；桌面默认整行占满（仍在标题/按钮下方单独一行） */
.deck-bar-head {
  flex: 1 1 100%;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: nowrap;
  min-width: 0;
}
.db-title {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--txt);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
/* v130：编辑态标题行只显示正在编辑的卡组名，用金色与浏览态的「我的卡组」区分 */
.deck-screen.edit-mode .db-title { color: #a97e00; }
.db-count { flex: 0 0 auto; font-size: 12px; font-weight: 800; color: #a97e00; font-variant-numeric: tabular-nums; }
.db-count.full { color: var(--green); } /* v125：编辑态卡组满 12 / 12 时转绿 */
.db-tip { flex: 0 1 auto; font-size: 11px; color: var(--dim2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 卡组位横向滚动条：容量 20 套，最左为「＋ 新建卡组」 */
.deck-slots {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: stretch;
  gap: 10px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 2px 2px 8px;
  scrollbar-width: thin;
}
.deck-slot {
  position: relative; /* v124：缩略图右上角悬浮操作按钮的定位基准 */
  flex: 0 0 auto;
  width: 120px;
  padding: 8px;
  color: var(--txt);
  border: 1px solid rgba(108, 148, 100, .42);
  border-radius: var(--r-4);
  background: linear-gradient(180deg, var(--surf-88), rgba(240, 248, 231, .72));
  transition: transform .08s, box-shadow .2s, border-color .2s, background .2s;
}
.deck-slot:hover { transform: translateY(-2px); box-shadow: 0 10px 22px rgba(46, 78, 40, .18); border-color: rgba(124, 168, 110, .8); }
.deck-slot:active { transform: scale(.98); }
.deck-slot.active { border-color: #e0a316; box-shadow: 0 0 0 2px rgba(224, 163, 22, .45), 0 10px 22px rgba(46, 78, 40, .18); }
.deck-slot.new { border-style: dashed; border-color: rgba(201, 148, 0, .6); background: rgba(255, 248, 214, .62); }
.deck-slot.new.full { opacity: .6; }
/* v122：新建卡组时，新卡组位播一次入场动画（动态列表扩展的观感） */
.deck-slot.just-added { animation: deckSlotIn .34s cubic-bezier(.2, .8, .3, 1.1); }
@keyframes deckSlotIn {
  from { opacity: 0; transform: translateY(8px) scale(.82); }
  to { opacity: 1; transform: none; }
}

/* v124：卡组位主体（缩略图 + 名称 + 张数）——点击 = 选中该卡组。
   卡组位本身改成容器 div，主体放进内部 button：这样缩略图上的「修改 / 删除」
   两个悬浮按钮与主体同层、既合法嵌套又互不串点击。 */
.ds-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 100%;
  height: 100%;
  padding: 0;
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  text-align: center;
  cursor: pointer;
  border: none;
  background: none;
}
.ds-main:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-2); }

/* v124：缩略图右上角悬浮的操作按钮（v129 起**只剩 🗑️ 删除卡组**——
   修改卡组改为点卡组位任意位置直接进入，故不再有 ✏️）。
   默认隐藏（不占点击热区），鼠标悬停或键盘聚焦时淡入；触屏无 hover → 常驻显示。 */
.ds-actions {
  position: absolute;
  top: 10px;
  right: 3px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .15s, visibility .15s;
}
.deck-slot:hover .ds-actions,
.deck-slot:focus-within .ds-actions { opacity: 1; visibility: visible; pointer-events: auto; }
.ds-act {
  width: 25px;
  height: 25px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 12.5px;
  line-height: 1;
  cursor: pointer;
  background: var(--surf-96);
  border: 1px solid rgba(108, 148, 100, .45);
  border-radius: 50%;
  box-shadow: 0 3px 8px rgba(46, 78, 40, .22);
  transition: transform .08s, background .15s, border-color .15s;
}
.ds-act:hover { transform: scale(1.1); }
.ds-act.del:hover { background: #ffe9e9; border-color: #d04848; }
.ds-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (hover: none) { /* 触屏设备没有 hover：常驻显示悬浮按钮 */
  .ds-actions { opacity: 1; visibility: visible; pointer-events: auto; }
}

/* ---------- v125：编辑卡组（点卡组位上的 ✏️ 后，卡组栏变成该卡组的 12 个卡槽）
   v126：卡槽改为**自适应网格**（不再横向滚动）——宽屏 1 行 12 格，≤1000px 变 2 行 × 6 格，
   每格按可用宽度自动缩放，因此任何宽度都能一次看全 12 个空位。 ---------- */
.deck-slots.edit-mode {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: auto;
  align-content: start;
  gap: 8px;
  padding: 2px;
  overflow-x: hidden;
  overflow-y: auto;
}
/* 编辑态上栏按**内容自适应高度**（v126）：12 格填满后不再多出一片空白，
   省下的高度全部让给下方卡池；极端矮屏（横屏手机）才用 max-height 兜底、
   由 .deck-slots 纵向滚动。 */
.deck-screen.edit-mode .deck-bar { flex: 0 0 auto; max-height: 62%; }
/* 已放卡槽 = 卡面（.card-face 提供卡面外观与尺寸变量，这里只覆盖宽度 / 悬停位移 / 卡名截断） */
.deck-card-slot { width: 100%; }
.deck-card-slot .hc-text { display: none; } /* 卡槽紧凑：只留 费用 / 战力 / 立绘 / 卡名 */
.deck-card-slot .hc-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.deck-card-slot:hover:not(.unaffordable) { transform: translateY(-2px); }
/* 空卡槽 = 与卡面同构的“幽灵卡”（尺寸与已放卡槽完全一致，见 js/deck-page.js 注释）：
   角标行(.dcs-top) / 正方形立绘区(.dcs-art) / 卡名行(.dcs-hint)，三段的尺寸与边距
   分别读 .deck-card-slot 上的 --badge / --name-fs（角标行与卡名），立绘区与已放卡槽同宽。 */
.deck-card-slot.empty {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 6px 6px 8px;
  color: #7d947a;
  border: 2px dashed rgba(108, 148, 100, .5); /* 与 .card-face 的 2px 实线边框同宽 */
  border-radius: var(--r-3);
  background: var(--surf-34);
}
.dcs-top { flex: 0 0 auto; height: var(--badge, 26px); } /* = 角标高度：跟着 .deck-card-slot 的 --badge 走 */
.dcs-art {
  flex: 0 0 auto;
  width: calc(100% - 4px); /* = 手牌卡面的立绘区宽度 */
  aspect-ratio: 1 / 1;
  margin: 4px auto 2px;    /* = .hc-art 边距 */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-1);
  background: rgba(120, 150, 110, .13);
}
.dcs-idx { font-size: 22px; font-weight: 800; opacity: .75; }
.dcs-hint { font-size: var(--name-fs, 12.5px); font-weight: 800; } /* = 卡名字号/字重，行高一致 */

/* v126：编辑态下“已在卡组里”的卡牌 = 灰色遮罩 + 不可点击（移出请点上方卡槽） */
.deck-pool-card.in-deck { cursor: default; }
.deck-pool-card.in-deck::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 4;
  border-radius: inherit;
  background: rgba(58, 68, 58, .52); /* 灰色遮罩 */
  pointer-events: none;
}
.deck-pool-card.in-deck .hc-art,
.deck-pool-card.in-deck .hc-icon { filter: grayscale(1); }
.deck-pool-card.in-deck:hover:not(.unaffordable) {
  transform: none; /* 已选卡不再上浮，明确“不可操作” */
  box-shadow: 0 6px 14px rgba(46, 78, 40, .35), inset 0 0 0 1px var(--surf-14);
}

/* ≤1000px：一行摆不下 12 格 → 2 行 × 6 格（手机端即用户要求的 2×6） */
@media (max-width: 1000px) {
  .deck-slots.edit-mode { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
/* ≤700px（手机）：卡槽适当缩小，保证 12 格在卡组栏里一屏看全；顶部按钮只留图标省高度。
   空位(.empty)与卡面(.filled)的每一段尺寸都同步缩小，两者仍保持完全一致的高度。
   v134：编辑态把「卡组名 N/12」与一排操作按钮收进同一行（隐藏「卡组设置」页标题腾位）。 */
@media (max-width: 700px) {
  .deck-slots.edit-mode { gap: 5px; }
  /* 卡槽（已放卡面与空位幽灵卡共用这一档：变量声明在 .deck-card-slot 上，两者自动一致） */
  .deck-card-slot {
    --badge: 16px; --badge-fs: 8.5px; --badge-bw: 1px; --spell-fs: 8.5px;
    --name-fs: 8.5px;
    padding: 3px 3px 4px;
    border-radius: var(--r-1);
  }
  .deck-card-slot .hc-art { margin: 2px auto 1px; }
  .deck-card-slot.empty { padding: 3px 3px 4px; border-radius: var(--r-1); }
  .dcs-art { margin: 2px auto 1px; border-radius: var(--r-1); }
  .dcs-idx { font-size: 15px; }
  .deck-top-actions .bt-txt { display: none; }        /* 顶部按钮只留图标（title 仍可悬停查看） */
  .deck-top-actions .bt-ico { margin-right: 0; }
  .deck-top-actions .btn { padding: 6px 10px; font-size: 14px; }

  /* 编辑态：一行 = 卡组名 N/12 + ✏️🧹✓← */
  .deck-screen.edit-mode .deck-top {
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
  }
  .deck-screen.edit-mode .deck-title { display: none; }
  .deck-screen.edit-mode .deck-bar-head {
    flex: 1 1 auto;
    min-width: 0;
    align-items: center;
  }
  .deck-screen.edit-mode .db-tip { display: none; }
  .deck-screen.edit-mode .deck-top-actions {
    flex: 0 0 auto;
    margin-left: 0;
    gap: 6px;
  }
}

/* 卡组缩略：三张卡背叠放（占位卡组为空，故中央显示「＋」）
   height: min(100%, 133px) —— 卡位够高时按 5:7 卡形（133 ≈ 95×7/5，正好等于
   卡位内宽 92%），卡位偏矮时退回 100% 高度，两种情况都保持卡牌宽高比不拉伸。 */
.ds-thumb { position: relative; flex: 1 1 auto; min-height: 0; width: 100%; display: flex; align-items: center; justify-content: center; }
.ds-stack { position: relative; height: min(100%, 133px); aspect-ratio: 5 / 7; }
.ds-back {
  position: absolute;
  inset: 0;
  border-radius: 7px;
  border: 1px solid var(--surf-34);
  background: linear-gradient(160deg, #2b314a, #151929); /* 同游戏暗牌卡背 */
  box-shadow: 0 5px 12px var(--ink-3);
}
.ds-back:nth-child(1) { transform: translateX(-11px) rotate(-8deg); }
.ds-back:nth-child(2) { transform: translateY(-2px); }
.ds-back:nth-child(3) { transform: translateX(11px) rotate(8deg); }
.ds-emblem {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  font-weight: 800;
  color: #ffe9a8;
  text-shadow: 0 2px 6px var(--ink-6);
}
.ds-plus {
  display: flex;
  align-items: center;
  justify-content: center;
  height: min(100%, 133px);
  aspect-ratio: 5 / 7;
  font-size: 30px;
  font-weight: 700;
  color: rgba(90, 120, 84, .5);
  border: 1px dashed rgba(108, 148, 100, .5);
  border-radius: var(--r-2);
}
.ds-plus.big { font-size: 38px; color: rgba(201, 148, 0, .75); border-color: rgba(201, 148, 0, .5); }
.ds-name { max-width: 100%; font-size: 12px; font-weight: 800; letter-spacing: .5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ds-count { font-size: 10.5px; color: var(--dim); font-variant-numeric: tabular-nums; }
.ds-count.full { font-weight: 800; color: var(--green); }

/* ---------- 下方 2/3：全部卡牌（不含衍生卡牌） ---------- */
.deck-pool {
  flex: 2 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-6);
  background: var(--surf-5);
  box-shadow: 0 14px 34px rgba(46, 78, 40, .12);
}
.deck-pool-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.dp-title { font-size: 13px; font-weight: 800; letter-spacing: 1px; color: var(--txt); }
.dp-count { font-size: 11.5px; color: var(--dim); }
.dp-active { font-size: 11.5px; font-weight: 700; color: #a97e00; }
.dp-tip { margin-left: auto; font-size: 11px; color: var(--dim2); }

/* v131：卡组页费用筛选条（复用图鉴 .card-filter-bar / .chip，内边距适配卡池区） */
.deck-filter-bar { padding: 0 2px 4px; flex-shrink: 0; }
.deck-grid .deck-pool-card.token-card {
  outline: 1px dashed rgba(120, 92, 170, .6);
  outline-offset: -2px;
}

.deck-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 10px;
  align-content: start; /* 卡少时不把行纵向撑满整块卡池 */
  align-items: start;   /* 卡片按内容高度，不被单元格拉长 */
  overflow-y: auto;
  padding: 6px 2px 10px;
  scrollbar-width: thin;
}
.deck-pool-card { width: 100%; height: auto; }
/* v133：卡池卡面高度统一（对齐手牌 v103）——效果文字固定两行；卡名单行省略；
   无图卡由 JS 加 .no-img，emoji 占正方形立绘区，与有图卡同高 */
.deck-pool-card .hc-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 0 0 auto;
}
.deck-pool-card .hc-text {
  flex: 0 0 auto;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em; /* 短文案 / 白板「—」也占两行，避免矮一截 */
}
.deck-pool-card:hover { border-color: rgba(242, 201, 76, .85); box-shadow: 0 0 0 2px rgba(242, 201, 76, .45); }

/* 卡组改名弹窗（v129）：复用 .undo-modal 尺寸，中间一个居中的文本输入框 */
.deck-rename-modal { max-width: 380px; width: 92vw; }
.deck-rename-modal h2 { color: var(--txt); }
.deck-rename-input {
  width: 100%;
  margin: 10px 0 6px;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 16px;   /* ≥16px：iOS 上聚焦时不会自动放大页面 */
  font-weight: 700;
  color: var(--txt);
  text-align: center;
  background: #fff;
  border: 2px solid rgba(108, 148, 100, .45);
  border-radius: var(--r-2);
  outline: none;
}
.deck-rename-input::placeholder { color: #9aae94; font-weight: 400; }
.deck-rename-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(224, 163, 22, .22); }
.deck-rename-tip { min-height: 17px; margin-bottom: 14px; font-size: 11.5px; color: var(--dim2); }
.deck-rename-tip.warn { font-weight: 700; color: #d04848; }

/* 卡组导入 / 导出弹窗：复用 .undo-modal 尺寸，中间一个等宽小字的文本域
   （导出码是一行长文本，故左对齐 + 等宽；导入时同一个框就是粘贴入口） */
.deck-import-modal { max-width: 460px; width: 94vw; }
.deck-import-modal h2 { color: var(--txt); }
.deck-import-input {
  width: 100%;
  min-height: 84px;
  margin: 10px 0 6px;
  padding: 10px 12px;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 12px;
  line-height: 1.5;
  color: var(--txt);
  word-break: break-all;
  resize: vertical;
  background: #fff;
  border: 2px solid rgba(108, 148, 100, .45);
  border-radius: var(--r-2);
  outline: none;
}
.deck-import-input::placeholder { font-family: inherit; color: #9aae94; }
.deck-import-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(224, 163, 22, .22); }
.deck-import-tip { min-height: 17px; margin-bottom: 14px; font-size: 11.5px; color: var(--dim2); }
.deck-import-tip.warn { font-weight: 700; color: #d04848; }

/* v137：开始对战 · 选出战卡组 */
.battle-deck-modal { max-width: 420px; width: 92vw; padding: 26px 24px 22px; text-align: left; }
.battle-deck-modal h2,
.battle-deck-modal .modal-emblem,
.battle-deck-modal .modal-sub { text-align: center; }
.battle-deck-modal .modal-sub { margin-bottom: 12px; }
.battle-deck-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: min(42vh, 320px);
  overflow-y: auto;
  margin-bottom: 16px;
  padding: 2px;
  scrollbar-width: thin;
}
.battle-deck-item {
  appearance: none;
  font: inherit;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  text-align: left;
  color: var(--txt);
  background: var(--surf-82);
  border: 2px solid rgba(108, 148, 100, .4);
  border-radius: var(--r-3);
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.battle-deck-item:hover { border-color: rgba(124, 168, 110, .85); background: #f2f9ea; }
.battle-deck-item.selected {
  border-color: #e0a316;
  background: #fff8e6;
  box-shadow: 0 0 0 2px rgba(224, 163, 22, .35);
}
.bd-name { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 「随机卡组」兜底项（单机且一套满编卡组都没有时才出现）：**淡紫底** + 紫虚线描边 + 🎲，
   一眼看出它不是正式卡组；选中态也留在紫色（只加深）——换成上面的金色 .selected 就把这层提示盖掉了 */
.battle-deck-item.special { border-style: dashed; border-color: rgba(138, 90, 214, .5); background: #f4effc; }
.battle-deck-item.special:hover { border-color: rgba(138, 90, 214, .9); background: #ece2fa; }
.battle-deck-item.special.selected { border-color: var(--purple); background: #e6d9f8; box-shadow: 0 0 0 2px rgba(138, 90, 214, .3); }
.battle-deck-item.special .bd-name { color: #5b3c96; }
.battle-deck-item .bd-ico { flex: 0 0 auto; font-size: 15px; line-height: 1; }
/* v154：卡组位不再显示费用构成（.bd-curve）与「12 / 12」徽标（.bd-count）——整行只留卡组名，
   手机端与电脑端一致；12 张信息保留在卡组位的悬停提示（title）里 */
.battle-deck-empty {
  text-align: center;
  color: var(--dim2);
  font-size: 13px;
  line-height: 1.55;
  padding: 18px 8px 22px;
}
.battle-deck-modal .undo-btns { justify-content: center; flex-wrap: wrap; gap: 8px; }

/* 卡组页确认弹窗（v124 删除卡组 / v125 清空卡组共用）：复用 .undo-modal 尺寸，
   标题/图标带一点危险色（文案与按钮由 js/deck-page.js openConfirm() 动态填充） */
.deck-confirm-modal h2 { color: #b23b3b; }
.deck-confirm-modal .modal-emblem { filter: drop-shadow(0 4px 10px rgba(208, 72, 72, .35)); }
/* 危险度较低的确认（danger:false）时按钮改回主色，标题保持普通绿字 */
.deck-confirm-modal h2.safe { color: var(--txt); }

/* 占位交互提示条 */
.deck-toast {
  position: fixed;
  left: 50%;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: var(--z-deck-toast);
  max-width: 88vw;
  padding: 10px 16px;
  font-size: 12.5px;
  font-weight: 700;
  text-align: center;
  color: var(--up-ink);
  background: rgba(255, 248, 214, .97);
  border: 1px solid rgba(201, 148, 0, .45);
  border-radius: var(--r-pill);
  box-shadow: 0 10px 24px rgba(46, 78, 40, .22);
}
.deck-toast.pop { animation: rise .26s ease; }

/* 手机端：卡组位收窄、卡牌网格紧凑（与图鉴 ≤640px 口径一致） */
@media (max-width: 640px) {
  .deck-screen { padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px)); gap: 10px; }
  .deck-bar { min-height: 148px; padding: 10px; border-radius: var(--r-4); }
  .deck-title h2 { font-size: 16px; letter-spacing: 1px; }
  .dt-icon { font-size: 22px; }
  .deck-hint, .db-tip, .dp-tip { display: none; }
  .deck-slot { width: 96px; padding: 6px; border-radius: var(--r-3); }
  .ds-main { gap: 4px; }
  .ds-actions { top: 7px; right: 1px; gap: 4px; }
  .ds-act { width: 22px; height: 22px; font-size: 11px; }
  .ds-stack, .ds-plus { height: min(100%, 108px); } /* 96px 卡位内宽 84×92% ≈ 77 → 77×7/5 ≈ 108 */
  .ds-name { font-size: 10.5px; }
  .ds-count { font-size: 9.5px; }
  .deck-pool { padding: 10px; border-radius: var(--r-4); }
  /* v128：手机端卡池卡片缩小 —— 最小列宽 84px → 74px，每行由 3 张提升到**至少 4 张**
     （360~430px 宽手机 ≈ 4 张 / 480px ≈ 5 张 / 640px ≈ 7 张；更宽窗口仍由基础
      minmax(104px) 控制，保证每行 ≥4 张） */
  .deck-grid { grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); gap: 6px; }
  /* 手机端卡片简略显示：隐藏效果文字（同图鉴 #codexGrid 的 ≤640px 口径） */
  .deck-grid .deck-pool-card .hc-text { display: none; }
  .deck-grid .deck-pool-card {
    --badge: 19px; --badge-fs: 9.5px; --spell-fs: 9.5px;
    --name-fs: 10.5px;
  }
  /* 小卡下长卡名（如「帕秋莉·诺蕾姬」）改为省略号，避免溢出到相邻卡上 */
  .deck-grid .deck-pool-card .hc-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
@media (max-height: 620px) and (min-width: 641px) {
  .deck-bar { min-height: 150px; }
  .deck-slot { width: 104px; }
}
/* 极窄屏兜底 —— 固定 4 列，保证「每行至少 4 张卡」在任何手机宽度下都成立 */
@media (max-width: 520px) {
  .deck-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ============================================================
   v172：主页面「📖 新手引导」（#homeBtnGuide 按钮 + #guideMask 弹窗）
   - 按钮 = 主页面三个主入口**下方**的次级入口：虚线描边、更矮更轻，
     与 .home-btn 同宽同圆角，保证主页面的按钮列仍然对齐；
     文案与图标都写在 index.html 里（本段只管样式）。
   - 弹窗 = 复用 .modal-mask + .codex-modal（已带 z-index 50 / max-height:88vh /
     纵向 flex），.guide-modal 把宽度收窄到 680px；正文放 .guide-body
     （flex:1 + min-height:0 + overflow-y:auto）→ **只有正文滚动，
     标题与底部按钮常驻可见**（矮屏与手机端同口径）。
   - 主页面态：`body.in-home .modal-mask { display: none }`（本文件上方主页面段）
     会连弹窗一起隐藏，故照 #battleDeckMask 的写法单独放开显示，
     z-index 212 盖过首页层（#homeScreen 为 200）。
   ============================================================ */
body.in-home #guideMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal);
}

/* 主页面最下方的新手引导入口（放在三个主入口之下） */
.home-guide-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 12px;
  padding: 10px 14px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .5px;
  color: #4d6b46;
  cursor: pointer;
  border: 1px dashed rgba(108, 148, 100, .62);
  border-radius: var(--r-3);
  background: var(--surf-5);
  transition: transform .08s, background .2s, border-color .2s, box-shadow .2s, color .2s;
}
.home-guide-btn:hover {
  color: var(--txt);
  background: #fff;
  border-color: rgba(124, 168, 110, .9);
  box-shadow: 0 8px 20px rgba(46, 78, 40, .14);
  transform: translateY(-1px);
}
.home-guide-btn:active { transform: scale(.985); }
.home-guide-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.home-guide-btn .hg-ico { font-size: 16px; line-height: 1; }

/* 新手引导弹窗：正文可滚动，标题与底部按钮固定 */
.guide-modal { width: min(680px, 94vw); max-width: min(680px, 94vw); }
.guide-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 2px 6px 6px 2px;
  scrollbar-width: thin;
}
.guide-sec { margin-bottom: 15px; }
.guide-sec:last-child { margin-bottom: 4px; }
.guide-sec h3 {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 6px;
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--txt);
}
.guide-sec h3 .gs-ico { font-size: 17px; line-height: 1; }
.guide-sec ul { margin: 0; padding-left: 18px; }
.guide-sec li { margin-bottom: 4px; font-size: 12.8px; line-height: 1.72; color: #3f5b39; }
.guide-sec li b { color: #24401f; }
.guide-actions { flex: 0 0 auto; flex-wrap: wrap; }

@media (max-width: 640px) {
  .home-guide-btn { margin-top: 10px; padding: 9px 12px; font-size: 12px; }
  .guide-modal { width: 94vw; max-width: 94vw; padding: 14px 14px 12px; }
  .guide-sec h3 { font-size: 13.5px; }
  .guide-sec li { font-size: 12.2px; line-height: 1.68; }
  .guide-actions .btn { flex: 1 1 auto; min-width: 0; }
}

/* ============================================================
   v174：主页面「⚙️ 设置」（#homeBtnSettings 按钮 + #settingsMask 弹窗）
   - 按钮 = 主入口列里紧接「开发调试」的那一项（在「开发调试」与「挑战码」之间），
     样式复用 .home-btn（不加新样式），
     副标题由 home.js 同步为「对手 AI 强度：<当前档位>」，故这里只需要给弹窗写样式；
   - 弹窗 = 复用 .modal-mask + .codex-modal（z-index 50 / max-height:88vh / 纵向 flex），
     .settings-modal 收窄到 520px；正文 .settings-body 可滚动（同 .guide-body 口径），
     标题与底部按钮常驻；
   - 三档难度选项由 home.js 从 window.AI.LEVELS 渲染成 .ai-level-opt 按钮，
     选中项加 .on（描边 + 勾标 + 浅绿底），保证一眼看出当前强度；
   - 主页面态：`body.in-home .modal-mask { display: none }` 会把弹窗一起隐藏，
     照 #battleDeckMask(210) / #guideMask(212) 的写法单独放开显示，
     z-index 211 —— 低于新手引导（212），高于出战卡组弹窗（210）。
   ============================================================ */
body.in-home #settingsMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal-settings);
}

.settings-modal { width: min(520px, 94vw); max-width: min(520px, 94vw); }
.settings-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 2px 6px 6px 2px;
  scrollbar-width: thin;
}
.settings-sec { margin-bottom: 15px; }
.settings-sec:last-child { margin-bottom: 4px; }
.settings-sec h3 {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 6px;
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--txt);
}
.settings-sec h3 .ss-ico { font-size: 17px; line-height: 1; }
.settings-note { margin: 0 0 10px; font-size: 12.2px; line-height: 1.6; color: var(--dim); }
.settings-list { margin: 0; padding-left: 18px; }
.settings-list li { margin-bottom: 4px; font-size: 12.8px; line-height: 1.72; color: #3f5b39; }
.settings-list li b { color: #24401f; }
.settings-actions { flex: 0 0 auto; justify-content: flex-end; }

/* 三档难度选项（单选式按钮组） */
.ai-level-list { display: flex; flex-direction: column; gap: 8px; }
.ai-level-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 13px;
  font-family: inherit;
  text-align: left;
  color: var(--txt);
  cursor: pointer;
  border: 1px solid rgba(108, 148, 100, .45);
  border-radius: var(--r-3);
  background: var(--surf-72);
  transition: transform .08s, background .2s, border-color .2s, box-shadow .2s;
}
.ai-level-opt:hover {
  background: #fff;
  border-color: rgba(124, 168, 110, .8);
  box-shadow: 0 8px 20px rgba(46, 78, 40, .14);
  transform: translateY(-1px);
}
.ai-level-opt:active { transform: scale(.99); }
.ai-level-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ai-level-opt .alo-mark {
  flex: 0 0 auto;
  width: 20px;
  font-size: 15px;
  text-align: center;
  color: transparent;
}
.ai-level-opt.on {
  border-color: rgba(212, 160, 22, .95);
  background: linear-gradient(180deg, #fffbef, #fff5d8);
  box-shadow: 0 8px 20px rgba(201, 148, 0, .18);
}
.ai-level-opt.on .alo-mark { color: #c8901a; }
.ai-level-opt .alo-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ai-level-opt .alo-name { font-size: 14.5px; font-weight: 800; letter-spacing: .5px; }
.ai-level-opt .alo-desc { font-size: 11.5px; line-height: 1.45; color: var(--dim); }
.ai-level-opt.on .alo-desc { color: #6d5a1c; }
.ai-level-opt .alo-badge {
  flex: 0 0 auto;
  margin-left: auto;
  padding: 2px 7px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .5px;
  color: #3d2c00;
  border-radius: var(--r-pill);
  background: linear-gradient(135deg, #e0a316, #f4c948);
}
/* v175：默认档的灰色「默认」徽标（当该项不是当前选中档时显示） */
.ai-level-opt .alo-badge.soft {
  color: #4d6b46;
  font-weight: 700;
  background: rgba(126, 168, 118, .22);
  border: 1px solid var(--border);
}

/* 设置弹窗「玩家资料」段（昵称 + 头像）：联机时把这两样显示给对手（js/home.js 的 profile / js/net.js 的 hello.avatar） */
.player-row { display: flex; align-items: center; gap: 10px; margin: 10px 0 4px; }
.player-label { flex: 0 0 auto; font-size: 12.5px; font-weight: 800; color: #4d6b46; letter-spacing: .5px; }
.player-name-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 7px 10px;
  font-size: 13px;
  font-family: inherit;
  color: #33502d;
  background: #fff;
  border: 1px solid rgba(126, 168, 118, .5);
  border-radius: var(--r-1);
}
.player-name-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.player-av-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 12px 0 6px;
  font-size: 12.5px;
  font-weight: 800;
  color: #4d6b46;
  letter-spacing: .5px;
}
.player-av-tip { font-weight: 400; font-size: 11px; letter-spacing: 0; color: var(--dim2); }
/* 头像选择：卡图小网格（可滚动），选中项加绿框 */
.avatar-pick {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
  gap: 6px;
  max-height: 186px;
  overflow-y: auto;
  padding: 5px;
  background: #fbfdf7;
  border: 1px solid rgba(120, 144, 111, .3);
  border-radius: var(--r-2);
}
.avatar-opt {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  cursor: pointer;
  background: #fff; /* 卡图是透明背景 PNG，格子底色统一用白（与侧栏 / 房间弹窗的头像格一致） */
  border: 2px solid transparent;
  border-radius: 9px;
}
.avatar-opt img { display: block; width: 100%; height: 100%; object-fit: cover; }
.avatar-opt .avatar-opt-ico { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; font-size: 20px; }
.avatar-opt:hover { border-color: rgba(126, 168, 118, .9); }
.avatar-opt.on { border-color: #2f7d4f; box-shadow: 0 0 0 2px rgba(47, 125, 79, .22); }
.avatar-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

@media (max-width: 640px) {
  .settings-modal { width: 94vw; max-width: 94vw; padding: 14px 14px 12px; }
  .settings-sec h3 { font-size: 13.5px; }
  .settings-list li { font-size: 12.2px; line-height: 1.68; }
  .ai-level-opt { padding: 10px 11px; }
  .ai-level-opt .alo-name { font-size: 13.5px; }
  .ai-level-opt .alo-desc { font-size: 11px; }
  .settings-actions .btn { flex: 1 1 auto; min-width: 0; }
  .avatar-pick { grid-template-columns: repeat(auto-fill, minmax(42px, 1fr)); max-height: 160px; }
}

/* ============================================================
   v181：主页面「📚 图鉴」入口（#homeBtnCodex 按钮 + 复用既有图鉴弹窗）
   - 按钮 = 主入口列里紧接「卡组设置」下方的那一项，样式**复用 .home-btn**
     （不加新样式；图标用 📚，与对局顶栏的「📖 图鉴」呼应，也与「📖 新手引导」区分开），
     交互见 js/home.js 的 openCodex / closeCodex / isCodexOpen。
   - 弹窗 = **完全复用**既有图鉴弹窗 #codexMask（js/card-browser.js 的 window.CardBrowser，
     与对局顶栏「📖 图鉴」是同一个弹窗），本段只负责“在主页面态把它放出来”：
       ① 主页面态 `body.in-home .modal-mask { display: none }`（本文件主页面段）会把弹窗
          一起隐藏，故照 #battleDeckMask(210) / #settingsMask(211) / #guideMask(212) 的写法
          单独放开显示，z-index 213 —— 图鉴是用户主动打开的顶层内容，与其它主页面弹窗互斥
          （home.js 的 openCodex 会先关掉新手引导 / 设置 / 出战卡组弹窗）；
       ② 图鉴里点卡会调 showZoom() 弹出放大层 #zoomMask（游戏里 z-index 60），主页面态
          同样被隐藏，故再放开一条 z-index 214，保证“放大查看”盖在图鉴之上。
   - 卡组设置页（body.in-deck）本来就不隐藏 .modal-mask（见上方主页面段注释），无需加规则。
   ============================================================ */
body.in-home #codexMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal-codex);
}
body.in-home #zoomMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal-zoom);
}

/* ============================================================
   v187：特殊牌池（侧栏入口 #pileCard + 弹窗 #pileMask）
   数据口径见 js/game.js 的 PILE_KINDS / pushToPile / recordDestroy / recordSpellExile
   段与 docs/现有机制.md §6「特殊牌池」条；本段只管样式。
   - 入口区块 .pile-card：侧栏 #sidePanel 的第一个区块（地形区域的下方、对手信息的上方），
     外观沿用 .opponent / .rules 的白色透光卡片，里面两个按钮各带一个计数徽标；
   - 弹窗 .pile-modal：复用 .codex-modal / .codex-head / .card-filter-bar(.chip) /
     .codex-grid / .codex-card / .codex-empty 的既有样式，另补三处：
       ① .pile-grid 的高度上限（弹窗内网格自身滚动）；
       ② 每张卡的“入池顺序”小字（.pile-cell 容器 + .pile-cap 小字 + .pile-ord 序号药丸）
          ——**不叠在卡面上**（卡面左上角是费用宝珠、右上角是战力），改为卡片下方独立一行，
          手机端同样可见；
       ③ **三个池的卡牌尺寸统一**（固定轨道宽 `--pile-card-w` + 卡名/效果文字各预留固定行数，
          详见下方 `.pile-grid` 段的口径注释）。
   ============================================================ */
.pile-card {
  background: var(--surf-66);
  border: 1px solid var(--border-2);
  border-radius: var(--r-3);
  padding: 10px;
}
.pile-card .side-title { margin-bottom: 6px; }
.pile-btns { display: flex; flex-direction: column; gap: 6px; }
.pile-btn {
  display: flex; align-items: center; gap: 6px;
  width: 100%; padding: 6px 10px;
  font-size: 12.5px; font-weight: 700; text-align: left;
}
.pile-btn .pb-ico { flex: 0 0 auto; font-size: 13px; }
.pile-btn .pb-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pile-btn .pb-count {
  flex: 0 0 auto; min-width: 22px; text-align: center;
  font-size: 11.5px; font-weight: 800; color: #3d5a33;
  background: #eef6e4; border: 1px solid rgba(124, 164, 110, .55);
  border-radius: var(--r-pill); padding: 1px 6px;
}
.pile-modal { width: min(900px, 94vw); max-width: min(900px, 94vw); --pile-card-w: 116px; }
/* v187：**三个池（摧毁池 / 弃牌池 / 放逐池）的卡牌尺寸完全统一** —— 口径：
     ① **宽度**：网格改用**固定轨道宽** `var(--pile-card-w)`（不再用 `minmax(..., 1fr)` 随容器
        拉伸），并 `justify-content: center` 让余量落在两侧 —— 因此**任何池、任何屏宽、
        第几行第几张都是同一个宽度**（响应式只在断点处整体改这一个变量）；
     ② **高度**：卡内各段全部固定 —— 顶部角标行 26px、艺术区（有图 `.hc-art` / 缺图 emoji
        兜底）都是 `aspect-ratio: 1/1` 的正方形、卡名预留 2 行、效果文字固定 2 行，
        于是“宽度一致 ⇔ 高度一致”，长文案卡与白板卡同高；
     ③ 卡名不再把卡撑高：短名在 2 行区域内垂直居中（现有最长卡名 10 字＝正好 2 行）；
     ④ 效果文字超 2 行省略号截断（与手牌 `#hand` 同款口径），完整文案点卡放大查看。 */
.pile-grid {
  grid-template-columns: repeat(auto-fill, var(--pile-card-w));
  justify-content: center;
  max-height: 58vh;
}
.pile-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pile-cell .codex-card { width: 100%; }
.pile-cell .hc-name {
  line-height: 1.3; min-height: 2.6em;
  display: flex; align-items: center; justify-content: center;
}
.pile-cell .hc-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em;
}
.pile-cap {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  min-width: 0;
  font-size: 10.5px; font-weight: 700; color: var(--dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pile-ord {
  flex: 0 0 auto;
  background: linear-gradient(135deg, #e0a316, #f4c948);
  color: #3d2c00; font-weight: 800;
  border-radius: var(--r-pill); padding: 1px 6px;
}
.pile-turn { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 700px) {
  .pile-btn { font-size: 12px; padding: 6px 8px; }
  .pile-grid { max-height: 52vh; }
}
@media (max-width: 640px) {
  /* 手机端：卡牌整体缩小（仍走同一个变量 → 三个池依旧完全同宽同高），
     并按图鉴 / 指定卡牌的既有口径隐藏效果文字（对所有卡一视同仁，故高度仍统一） */
  .pile-modal { --pile-card-w: 92px; }
  #pileGrid { gap: 8px; }
  #pileGrid .codex-card .hc-text { display: none; }
  #pileGrid .codex-card { padding: 5px 3px 7px; }
}

/* ==================== v189：弃牌演出（`discard` 效果键） ====================
   口径：弃牌 = 把牌从**手牌**移出 → 进该方「弃牌池」；演出**双方可见**（任何一种归属组合都一样）：
   中央弹出**被弃那张牌的完整卡面**（JS 用 cardFaceHTML + .zoom-card 生成，配图/费用/战力/卡名/
   效果文案与手牌完全一致）→ **从右上到左下**斜切一刀、卡面裂成两半 → 两半沿对角线的垂直方向
   分离（上半三角往左上飞、下半三角往右下飞，带轻微旋转）并淡出，全程约 **1.6s**。
   ⚠️ 时长与 js/game.js 的 `DISCARD_ANIM_MS`（1600）对齐，改时长要两边一起改。
   ⏱️ **节奏（v190 微调，用户口径：切得晚一点、消散快一点）**：卡面弹入后**停留展示约 0.4s**
   （让玩家看清是哪张牌）→ 约 **0.68s** 才斜切一刀 → 两半在 **约 0.62s** 内**快速**分离并消散，
   整段约 **1.6s** 收尾（原来是 0.32s 就切、之后慢慢飘 1.6s）。

   结构（每张被弃的牌一个 .discard-card-wrap，多张时并排）：
     .discard-reveal                       全屏悬浮层（pointer-events:none，不挡操作）
       ├ .discard-reveal-tag               「🗑️ 弃牌 · 谁的手牌 · 来源」
       ├ .discard-reveal-inner
       │   └ .discard-card-wrap ×N         每张一个块（弹入 + 错开用 --discard-stagger）
       │       ├ .discard-face             基准整卡（切开那一瞬隐去，与两半像素级重合）
       │       ├ .discard-half-a           clip-path 上半三角（0 0, 100% 0, 0 100%）
       │       │   └ .discard-face         同一张卡面的拷贝（绝对定位，与基准对齐）
       │       ├ .discard-half-b           clip-path 下半三角（100% 0, 100% 100%, 0 100%）
       │       │   └ .discard-face         同上
       │       └ .discard-slash-layer      裁到卡面范围内的斩击层
       │           └ .discard-slash        斜向光刃（角度由 JS 按卡面长宽比写入 --discard-slash-angle）
       └ .discard-reveal-note              「「X」→ 移入谁的弃牌池（现 N 张）」
   时间轴（1.6s）：0~17% 卡面放大弹入落定 → 17%~42% 停留展示（看清是哪张牌）→ 42.5%（≈0.68s）
   斩击线闪一刀、同时裂成两半 → 42.5%~81% 两半**快速**分离渐隐（≈0.62s）→ 88%~100% 整层淡出；
   JS 在 1.6s + 余量后用 setTimeout 移除整层（不依赖 Web Animations）。 */
.discard-reveal {
  position: fixed;
  left: 50%;
  top: 42%;
  transform: translate(-50%, -50%);
  z-index: var(--z-fx-discard);
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  /* 只动 opacity（不要动 transform，否则会覆盖上面的居中位移） */
  animation: discardRevealFade 1.6s ease-out forwards;
  /* 多张并排时逐张错开会把末张的“切开 + 消散”整体后移，故整层的时长按最大错开量一起延长
     （--discard-tail 由 JS 按张数写入），保证末张的消散仍在整层淡出之前播完 */
  animation-duration: calc(1.6s + var(--discard-tail, 0ms));
}
@keyframes discardRevealFade {
  0%   { opacity: 0; }
  4%   { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0; }
}
.discard-reveal-tag {
  padding: 3px 12px;
  border-radius: var(--r-pill);
  background: rgba(24, 12, 16, .9);
  border: 1px solid rgba(255, 138, 138, .75);
  color: #ffc9c9;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .5px;
  white-space: nowrap;
  box-shadow: 0 2px 10px var(--ink-45);
}
.discard-reveal-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 16px;
  max-width: 94vw;
}
.discard-reveal-note {
  font-size: 11.5px;
  font-weight: 700;
  color: #ffe2e2;
  text-shadow: 0 1px 3px var(--ink-9);
  white-space: nowrap;
}
/* 卡面：复用 .zoom-card（250px 大卡），但**关掉自带的 rise 动画**——基准卡与两半的拷贝必须
   严格重合，任何额外位移都会让“切开”露出错位。 */
.discard-reveal .zoom-card { animation: none; }
.discard-card-wrap {
  position: relative;
  animation: discardPop 1.6s cubic-bezier(.2, .8, .3, 1) forwards;
  animation-delay: var(--discard-stagger, 0ms);
}
/* 0~17%（≈0~0.27s）：放大弹入落定，随后**停在原地展示**到 42.5%（≈0.68s）才被切开 */
@keyframes discardPop {
  0%   { opacity: 0; transform: scale(.55) rotate(-4deg); }
  8%   { opacity: 1; transform: scale(1.07) rotate(2deg); }
  11%  { transform: scale(.97) rotate(-1.5deg); }
  14%  { transform: scale(1.02) rotate(.6deg); }
  17%  { transform: scale(1) rotate(0deg); }
  100% { transform: scale(1) rotate(0deg); }
}
/* 基准整卡：切开那一瞬（42.5%＝≈0.68s）隐去，把画面让给两半 */
.discard-card-wrap > .discard-face {
  animation: discardBaseFade 1.6s linear forwards;
  animation-delay: var(--discard-stagger, 0ms);
}
@keyframes discardBaseFade {
  0%, 42.4% { opacity: 1; }
  42.5%, 100% { opacity: 0; }
}
/* 斜切的两半：切线＝右上角 → 左下角（clip-path 三角），各自内含一份同样的卡面拷贝。
   消散**快**：延迟到 0.68s（切点）才开始，且只有 0.62s（v190 由 1.6s 缩短）。 */
.discard-half {
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation-duration: 620ms;
  animation-timing-function: cubic-bezier(.22, .72, .3, 1);
  animation-fill-mode: forwards;
  animation-delay: calc(var(--discard-stagger, 0ms) + 680ms); /* 与 discardPop 的 42.5% 对齐 */
}
.discard-half > .discard-face {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
}
.discard-half-a {
  clip-path: polygon(0 0, 100% 0, 0 100%); /* 上半三角（含左上角）→ 往左上飞 */
  animation-name: discardHalfA;
}
.discard-half-b {
  clip-path: polygon(100% 0, 100% 100%, 0 100%); /* 下半三角（含右下角）→ 往右下飞 */
  animation-name: discardHalfB;
}
@keyframes discardHalfA {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0deg); }
  14%  { opacity: 1; transform: translate(-7px, -9px) rotate(-1.6deg); }
  55%  { opacity: 1; transform: translate(-26px, -34px) rotate(-6deg); }
  100% { opacity: 0; transform: translate(-44px, -56px) rotate(-9deg); }
}
@keyframes discardHalfB {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0deg); }
  14%  { opacity: 1; transform: translate(7px, 9px) rotate(1.6deg); }
  55%  { opacity: 1; transform: translate(28px, 36px) rotate(6deg); }
  100% { opacity: 0; transform: translate(46px, 58px) rotate(9deg); }
}
/* 斩击层：裁到卡面圆角范围内，光刃沿对角线「右上 → 左下」扫过并只闪一下 */
.discard-slash-layer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: var(--r-6);
  pointer-events: none;
}
.discard-slash {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 200%;
  height: 3px;
  margin: -1.5px 0 0 -100%;
  /* 角度由 JS 按卡面实测长宽比写入（atan2(h, w)），故严格贴着右上→左下那条对角线 */
  transform: rotate(var(--discard-slash-angle, 45deg));
  background: linear-gradient(90deg, rgba(255,255,255,0) 0%, #ffffff 45%, #fff3cf 55%, rgba(255,255,255,0) 100%);
  background-size: 220% 100%;
  background-position: 130% 0;
  box-shadow: 0 0 12px var(--surf-9), 0 0 26px rgba(255, 206, 140, .7);
  opacity: 0;
  animation: discardSlash 1.6s ease-out forwards;
  animation-delay: var(--discard-stagger, 0ms);
}
/* 光带从斜线右端（右上）扫向左端（左下）——只在 42.5%（≈0.68s）切开那一刻亮一下（约 0.25s） */
@keyframes discardSlash {
  0%, 39%   { opacity: 0; background-position: 130% 0; }
  42.5%     { opacity: 1; background-position: 112% 0; }
  47%       { opacity: 1; background-position: 10% 0; }
  53%       { opacity: .9; background-position: -30% 0; }
  62%       { opacity: 0; background-position: -45% 0; }
  100%      { opacity: 0; background-position: -45% 0; }
}
@media (max-width: 700px) {
  .discard-reveal { top: 40%; gap: 7px; }
  .discard-reveal-inner { gap: 10px; }
  .discard-reveal .zoom-card {
    --badge: 30px; --badge-fs: 14px; --badge-bw: 2px; --spell-fs: 14px;
    --icon-fs: 40px; --art-icon-fs: 40px;
    --art-w: min(136px, 36vw); --art-m: 6px auto 4px; --art-r: var(--r-2);
    --name-fs: 15px; --text-fs: 11.5px; --text-lh: 1.45;
    width: min(150px, 40vw);
    padding: 8px 9px 12px;
    border-radius: var(--r-4);
  }
  .discard-reveal .zoom-card .hc-text { margin-top: 8px; }
  .discard-reveal-tag { font-size: 11px; padding: 2px 9px; }
  .discard-reveal-note { font-size: 10.5px; }
  .discard-slash-layer { border-radius: var(--r-4); }
}

/* ============================================================
   联机对战（js/net.js）
   ============================================================ */
body.in-home #netMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal);
}
/* 「对手已掉线，将退出房间」提示（js/net.js）：**这一屏最靠前的一层** —— 结算弹窗 50 / 放大层 60 / 演出层 9400+ 都在它下面；
   主页面态下同样要能显示（玩家可能正在主页面等对手点「再来一局」），故另放开一条 in-home 规则（215：高于放大层 214）。 */
.peer-gone-mask { z-index: var(--z-fx-peer-gone); }
body.in-home #peerGoneMask:not(.hidden) { display: flex; z-index: var(--z-home-modal-net); }
.peer-gone-modal { width: min(460px, 94vw); max-width: min(460px, 94vw); }
.net-modal { width: min(520px, 94vw); max-width: min(520px, 94vw); }
/* 房间信息（房间码 · 你的身份 · 对手进没进来）：这是弹窗里最该一眼看清的一行，字号给足 */
.net-room-info {
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #4d6b46;
  margin-bottom: 10px;
  word-break: break-all;
}
/* 双方就位面板：两行「你是谁 / 对面是谁」+ 各自的状态（已准备 / 等待中 / 版本不一致） */
.net-players {
  margin-bottom: 10px;
  border: 1px solid rgba(120, 144, 111, .35);
  border-radius: var(--r-2);
  overflow: hidden;
}
.np-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 12px; font-size: 14px; }
.np-row + .np-row { border-top: 1px solid rgba(120, 144, 111, .22); }
.np-who { flex: 1 1 auto; min-width: 0; font-weight: 700; color: #4d6b46; }
.np-state { color: var(--dim2); }
/* 双方名单里的小头像：在设置里选过卡图就放图，没选就用 emoji（js/net.js 的 setAv） */
.np-av {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  overflow: hidden;
  font-size: 15px;
  background: #fff; /* 同 .av-net：卡图带透明通道，底色用白 */
  border-radius: 7px;
}
.np-av img { display: block; width: 100%; height: 100%; object-fit: cover; }
.np-state.ok { font-weight: 700; color: #2f7d4f; }
.np-state.warn { font-weight: 700; color: #d04848; }
/* 版本不一致：把两边的卡牌数据哈希与页面引擎指纹并排摆出来，排查不必开控制台 */
.net-version {
  margin-bottom: 10px;
  padding: 8px 10px;
  border-radius: var(--r-2);
  background: rgba(208, 72, 72, .08);
  border: 1px solid rgba(208, 72, 72, .3);
}
.nv-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; color: #a04040; }
.nv-row b { font-family: ui-monospace, Consolas, monospace; }
.net-room-row { margin-bottom: 8px; }
/* 创建房间的选码弹窗（js/net.js 的 ui.create → askCreate）：随机码一条路、自定义码一条路。
   层级给 --z-home-modal-net（高于房间弹窗 212），选完码就收起来、把后面的房间弹窗露出来。 */
body.in-home #netCodeMask:not(.hidden) {
  display: flex;
  z-index: var(--z-home-modal-net);
}
.net-code-modal { width: min(400px, 92vw); max-width: min(400px, 92vw); }
.net-code-modal .modal-sub { font-size: 12.5px; line-height: 1.6; }
.net-code-random { width: 100%; }
.net-code-or { margin: 10px 0; font-size: 11.5px; color: var(--dim2); text-align: center; }
.net-code-row { display: flex; flex-wrap: wrap; gap: 8px; }
/* 窄屏时按钮换到下一行（flex-wrap），不用另写媒体查询 */
.net-code-row .net-code-input { flex: 1 1 140px; width: auto; min-width: 0; }
.net-code-row .btn { flex: 1 1 auto; }
.net-room-input {
  width: 100%;
  height: 42px;
  margin-bottom: 0;
  text-align: center;
  letter-spacing: 4px;
  font-size: 17px;
  font-weight: 700;
  text-transform: uppercase;
}
/* 房间弹窗的提示行（net.js 的 ui.tip 写入，warn ＝ 需要玩家处理的错误）：这里的字是"要读的"，别给 11px 的小字 */
.net-tip { min-height: 36px; margin-bottom: 14px; font-size: 13px; line-height: 1.55; color: #5d7a55; }
.net-tip.warn { font-weight: 700; color: #d04848; }
.net-actions { flex-wrap: wrap; }
/* 房间弹窗的按钮（创建 / 加入 / 我已准备 / 复制房间码 / 退出）：与放大后的名单、提示行配套，别让按钮比正文还小 */
.net-actions .btn { font-size: 14.5px; padding: 9px 16px; }
/* 房主专用的「踢出对手」：做成"警示色"，跟普通操作（复制 / 退出）区分开 */
.net-kick { color: #a04040; border-color: rgba(208, 72, 72, .45); }
.net-kick:hover:not(:disabled) { background: rgba(208, 72, 72, .08); border-color: rgba(208, 72, 72, .7); }
/* 服务器地址：小字收在弹窗底部，不占主视线 */
.net-server { margin-top: 10px; font-size: 10.5px; color: #93a88b; word-break: break-all; }

/* 对局中的联机状态条：六段各自成块，配色＝等你出牌中性 / 已提交蓝 / 对手离线或超时红 / 对账一致绿 */
.net-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 14px;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 700;
  color: #cfe6c4;
  background: rgba(38, 58, 40, .92);
  border-bottom: 1px solid rgba(224, 163, 22, .35);
}
.nb-seg { white-space: nowrap; }
.nb-room { letter-spacing: 2px; color: #ffe08a; }
.nb-role { color: #a8c89c; }
.nb-peer.bad { color: #ff8f8f; }
.nb-phase.sent { color: #7fd1ff; }
.nb-phase.bad { color: #ff8f8f; }
.nb-phase.ok { color: #9fe08a; }
.nb-hash.ok { color: #9fe08a; }
.nb-hash.bad { color: #ff8f8f; }
/* 倒计时：进度条随剩余秒数缩短，剩余不足 HURRY_AT 秒时整段转告警色 */
.nb-time {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  border-radius: var(--r-1);
  background: var(--surf-8l);
  overflow: hidden;
}
.nb-time i { position: absolute; left: 0; top: 0; bottom: 0; width: 100%; background: rgba(127, 209, 255, .28); }
.nb-time b { position: relative; font-size: 11px; color: #cfe6c4; }
.nb-time.hurry i { background: rgba(255, 143, 143, .3); }
.nb-time.hurry b { font-weight: 700; color: #ff8f8f; }

/* 对手信息区（联机）：头像换成玩家配色，下面一行写对手这一手的提交状态 */
/* 联机时的对手头像：卡图是**透明背景**的 PNG，格子底色会从人物周围透出来 ⇒ 底色白、边框浅灰 */
.av-net { background: #fff; border: 2px solid #d5d9d1; }
.opp-turn-tag {
  margin-top: 8px;
  padding: 4px 8px;
  border-radius: var(--r-1);
  text-align: center;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--dim2);
  background: rgba(120, 144, 111, .12);
}
.opp-turn-tag.sent { color: #2b7fb8; background: rgba(43, 127, 184, .14); }

@media (max-width: 900px) {
  .net-bar { gap: 4px 10px; padding: 5px 8px; font-size: 11px; }
  .net-actions .btn { flex: 1; min-width: 0; }
}

/* ---------- 地形效果文字的取色（必须排在文件最后） ----------
   ⚠️ 正文靠前处有 `.loc-mid .loc-effect { color: var(--dim) }`（本文件 L1091 附近），
   它与上面的 `.location .loc-effect` 特异性相同（都是 20）⇒ **谁在后面谁生效**。
   各地形的取色现在只剩一条 `--locink` 变量（收口前是 `.location.<id> .loc-effect` 这种特异性 30 的规则，
   能压过它），所以这条必须放在 `.loc-mid .loc-effect` **之后**，否则全地形文字会掉回 --dim 浅绿。 */
.loc-mid .location .loc-effect,
.location.zone .loc-effect,
.location .loc-mid .loc-effect { color: var(--locink); }
