﻿:root {
  /* 页面基调（沿用，不改） */
  --bg: #0f1117;
  --panel: #171a23;
  --panel-2: #1d212c;
  --border: #272c3a;
  --text: #e6e9f0;
  --dim: #8a93a6;
  --dim-2: #5d6577;
  --accent: #4da3ff;
  --danger: #ff6b5a;
  /* ★ T-ENG-042：手牌「固定 7 槽」的推导常量 —— 手牌组宽 = 槽数×牌宽 + (槽数−1)×牌距。
     **7 槽 = 手牌上限 handSize**（见 data/rules.json → battle.handSize）：6 张时第 7 槽空着但占位
     ⇒ 右侧按钮组永不位移。改槽数/牌宽只改这三个变量（牌宽须与 `.card` 的 width 一致）。 */
  --hand-slots: 7;
  --card-w: 96px;
  --card-gap: 11px;
  --gold: #f5c542;
  --a-bang: #ff6b5a;
  --a-o: #4da3ff;
  --a-x: #8a93a6;
  --a-q: #b07cf0;

  /* 舞台（§2） */
  --stage-bg: #12141b;
  --ground: #cdc2a0;
  --ground-edge: #a89c7d;

  /* 剪影（§3.5 / §8） */
  --fig-ally-fill: #191b22;
  --fig-ally-keyline: #d8e2f0;
  --fig-enemy-fill: #1c1815;
  --fig-enemy-keyline: #e0d0b4;
  --fig-shadow: rgba(20, 15, 8, 0.32);

  /* 状态与四属性（色相固定，不随底色变 —— §5 / §8） */
  --state-hit: #ff6b5a;
  --state-block: #b8e6ef;
  --fx-strong: #ff6b5a;
  --fx-trick: #b07cf0;
  --fx-steady: #4da3ff;
  --fx-null: #8a93a6;
  --fx-keyline: #15110b;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 -apple-system, "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

body { display: flex; flex-direction: column; overflow: hidden; }
/* ★ T-ENG-040：main 此前是**无样式的块**，把 body 的 flex 链断掉了 ⇒ 里面 .board 的 flex:1 失效、
   页面底部堆出一条空带。补成 flex 列并占满剩余高度 ⇒ 两行 grid 里的 1fr 手牌行才能真正吃掉余量。 */
main { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.dim { color: var(--dim); }

/* ---------- 通用控件 ---------- */

.btn {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  padding: 8px 18px;
  border-radius: 8px;
  font-size: 14px;
  cursor: pointer;
  transition: background .12s, border-color .12s, transform .06s;
}
.btn:hover:not(:disabled) { background: #252a37; border-color: #39405180; }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .38; cursor: not-allowed; }
.btn-primary { background: #1f4d8a; border-color: #2f6bb8; font-weight: 600; }
.btn-primary:hover:not(:disabled) { background: #245aa0; }
.btn-ghost { background: transparent; }
.btn-ghost:hover:not(:disabled) { background: #1e2230; }

.inp {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  padding: 7px 10px;
  border-radius: 8px;
  width: 90px;
  font-size: 14px;
}
.inp-wide { width: 130px; }
.inp:focus { outline: none; border-color: var(--accent); }

/* ---------- 遮罩层 ---------- */

.overlay {
  position: fixed;
  inset: 0;
  background: #0b0d12ee;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  backdrop-filter: blur(3px);
}
.overlay[hidden] { display: none; }

/* ---------- 卡片面板（改密码遮罩复用 .setup-*） ----------
   ★ T-ENG-060：原来这里是「开局面板」的样式（选双方职业 + 血量 + 种子 + 开始按钮）。
   面板已整套删除，只剩 `.setup-card / .setup-row / .setup-row-end / .setup-label`
   被 `#pwdModal`（改密码）继续复用 ⇒ 保留这四条。
   同时删除：`.picks` / `.pick*`（开局面板的角色按钮）与 `.rps-*`（猜拳遮罩）—— 均已无引用。 */

.setup-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 26px 30px;
  width: min(560px, 92vw);
  display: flex;
  flex-direction: column;
  gap: 18px;
  box-shadow: 0 24px 70px #0009;
}
.setup-row { display: flex; align-items: center; gap: 12px; }
.setup-row-end { justify-content: flex-end; }
.setup-label { color: var(--dim); width: 40px; flex: none; }

/* ---------- 顶栏 ---------- */

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 18px;             /* ★ T-ENG-029：还原 pre-eng-026 原值（4px → 10px） */
  border-bottom: 1px solid var(--border);
  flex: none;
}
.topbar-left, .topbar-right { display: flex; align-items: center; gap: 12px; }
/* ★ T-ENG-029：026 里**没有**这条 `.topbar .btn` 规则（它是 026 为压薄顶栏临时加的）——
   删除它即还原：顶栏按钮回到 `.btn` 的 padding 8px 18px / font-size 14px */
.title { font-weight: 600; letter-spacing: .5px; }

.tag {
  font-size: 12px;
  color: var(--dim);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 10px;
}
.tag-phase-attack { color: #ffd08a; border-color: #6b5424; background: #2a2113; }
.tag-phase-defense { color: #9fd0ff; border-color: #24506b; background: #132129; }
.tag-phase-finished { color: var(--dim); }

/* ---------- 棋盘：撤掉左栏后 = 舞台 + 招式表 ---------- */

.board {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 232px;
  grid-template-rows: auto 1fr;    /* ★ T-ENG-040：第 1 行 = 舞台（按内容），**第 2 行 = 手牌区吃掉剩余高度**
                                      ⇒ 按钮搬进牌行省下的高度由手牌框消化，页面底部不留空带 */
  gap: 6px;                      /* ★ T-ENG-034：12 → 6（省 6px） */
  /* ★ T-ENG-034（用户裁决「两处分摊」）：左右 18 → 12（省 12px）+ gap 省 6px = 合计 **+18px**，
     目的是让 1484 视口下 arena = 1484 − 12×2 − 6 − 232 − 2(舞台 1px 边框×2) = **1220** ⇒ 舞台零裁切。
     ⚠️ 左右取 12 与上下 padding 数值相同**只是凑那 18px 的巧合**，不是"四边等距"的设计意图。
     ★ T-ENG-040：手牌区搬进第 2 行后，这个横向账**一个字没变**（两列宽不变、gap 不变）⇒ chrome 仍 264 ✓ */
  align-items: start;
  align-content: stretch;        /* ★ T-ENG-040：两行铺满 board（第 2 行 1fr 吃掉余量）⇒ 无底部空带 */
  padding: 12px 12px;
}

/* ---------- 战斗舞台 ---------- */

.stage {
  grid-area: 1 / 1;              /* ★ T-ENG-040：显式占第 1 行第 1 列 */
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 0;                /* ★ T-ENG-029：还原 pre-eng-026 原值（2px → 8px） */
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow: hidden;
}

.arena {
  position: relative;
  width: 100%;
  height: 422px;             /* 交手区 422（含顶部 HUD 100）；出牌层已按 T-ENG-028 取消 */
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow: hidden;
}

/* 舞台的坐标真源：1220×422（§2；顶部 HUD 占 y 0–100）。窗口不够宽时由 JS 等比缩小。 */
.world {
  flex: none;
  position: relative;
  width: 1220px;
  height: 422px;
  background: var(--stage-bg);
  border-radius: 12px;
  overflow: hidden;
  transform-origin: center center;
}

.ground { position: absolute; inset: 0; width: 1220px; height: 422px; }
.ground .quad { fill: var(--ground); }
.ground .edge { stroke: var(--ground-edge); stroke-width: 2; }

/* ---------- 顶部 HUD（高 100）：[敌头像][敌血条] 「第 X 回合」 [我血条][我头像] ---------- */
/* 血条从【外侧】扣 ⇒ 靠中间那一端固定、外侧端移动；两条都向两侧收缩，中间轮次的空间恒定。 */

.hudbar {
  position: absolute; left: 0; top: 0; width: 1220px; height: 100px;
  display: flex; align-items: stretch; z-index: 8;
  background: #12151d;
  /* ★ 用 inset 硬线而不是 border：border 会把内容高度压到 98 ⇒ 血条就不是 100 了 */
  box-shadow: inset 0 -2px 0 var(--border);
}
.hb-side { display: flex; align-items: stretch; flex: 1 1 0; min-width: 0; }

/* 头像 100×100（内容由 app.js 的 avatarOf(side) 单一入口产出） */
.avatar { flex: none; width: 100px; height: 100px; position: relative; overflow: hidden; background: #0e1119; }
.hb-foe .avatar { border-right: 2px solid var(--border); }
.hb-me .avatar { border-left: 2px solid var(--border); }
.avatar-inner { position: absolute; inset: 0; }
/* 把剪影的「头 + 肩」挪进 100×100 框：人物盒 520×360，头部约在 (260,148) ⇒ 左上偏移 (-210,-100) */
.avatar-fig { position: absolute; left: 0; top: 0; transform: translate(-210px, -100px); }

.hpbox { position: relative; flex: 1 1 0; min-width: 0; }
.hp2 { position: absolute; inset: 0; background: #3a1a1c; }
/* ★ 扣血方向（T-ENG-036 用户裁决）：填充贴【外端】。
   口径：血量减少 ⇒ **空出来的区域从靠「第X回合」的那一端（内端）开始，向外侧长**；填充始终贴外端。
   布局 = [敌头像][敌血条][轮次][我血条][我头像] ⇒ 敌条外端 = 左、我条外端 = 右。
   （旧版两条都贴内端 ⇒ 空出来的部分从外侧往中间长，正是用户说的「外向内扣血」，已否掉 —— 别再改回去。） */
.hb-foe .hpghost, .hb-foe .hpfill { position: absolute; top: 0; bottom: 0; left: 0; }
.hb-me .hpghost, .hb-me .hpfill { position: absolute; top: 0; bottom: 0; right: 0; }
.hpghost { background: #d8dce6; opacity: .30; transition: width .85s ease .25s; }
.hpfill { background: var(--danger); transition: width .32s ease; z-index: 1; }
.hptext {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between;
  padding: 0 14px; pointer-events: none; z-index: 2;
}
.hpnum { font-size: 22px; font-weight: 700; color: #fff; text-shadow: 1px 1px 0 #000; font-variant-numeric: tabular-nums; }
.hud-name { font-size: 12px; color: #fff; opacity: .85; letter-spacing: .5px; text-shadow: 1px 1px 0 #000; }

/* ★ T-ENG-060：血条下方的「三轴」补充行（武器本名 · 招式谱名；人物名走上面的 .hud-name）。
   血条盒高 100px，号码（22px）垂直居中 ⇒ 这行贴底 6px，与号码不重叠。
   双端（内外端）都居中，两侧对称；名字过长时省略号收尾，不撑破血条。 */
.hud-axes {
  position: absolute; left: 0; right: 0; bottom: 6px; z-index: 2;
  padding: 0 10px;
  font-size: 11px; line-height: 1; color: #cfd8e8; opacity: .82;
  letter-spacing: .3px; text-shadow: 1px 1px 0 #000;
  text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none;
}

/* 中央：第 X 回合（两侧留间隙，与血条不重叠） */
.hb-turn {
  flex: none; width: 170px; display: flex; align-items: center; justify-content: center;
  border-left: 2px solid var(--border); border-right: 2px solid var(--border); background: #0e1119;
}
.hb-turn span { font-size: 18px; font-weight: 700; color: var(--text); letter-spacing: 1px; white-space: nowrap; }

/* ---------- 人物剪影 ---------- */
/* .fig 的定位/尺寸由 web/silhouette.js 设定（position:absolute；底中 = 脚点）。 */

#figFoe { z-index: 2; }
#figMe { z-index: 3; }
.fig .pose { width: 100%; height: 100%; transform-origin: 50% 100%; will-change: transform; }
.fig .sil { width: 100%; height: 100%; display: block; overflow: visible; }

/* ★ T-ENG-046（用户裁决）：①「竖排招式名」**整块删除** —— 原 `.skillname`（竖排、挂攻击方身后）
   与 `.skillname.out` 连同样式一并移除；app.js 的 showSkillName/hideSkillName 也已删。
   验收有「竖排招式名已删除（计数 = 0）」门禁守着。 */

/* ---------- 招式名③：两人之间「巨大化」—— 发招演出主视觉 ---------- */
/*
 * ✍️ 关于 §12.1「不要发光」：这里**没有用扩散光晕**。
 *   - `-webkit-text-stroke: 3px #fff` = **实心描边**（字形轮廓，无模糊）；
 *   - `text-shadow: 3px 3px 0 #fff` = **硬投影**：有 3px 偏移、**模糊半径写死 0** ⇒ 只产生实心影子。
 *   （§12.1 禁的是 `0 0 12px #fff` 这种**无偏移 + 有模糊**的扩散光晕。）
 *   `paint-order: stroke fill` 让白描边先画、红字压在上面 ⇒ 描边只在外圈，不吃掉红。
 */
.skillbig {
  position: absolute;
  /* ★ T-ENG-037：left **不再写死** —— 由 app.js 在创建时设 `el.style.left = LAYOUT.CENTER_X`（= 舞台中心 610）
     原因：原先写死 562（照 (690+434.4)/2 手算）⇒ 脚点一移就漂。现在"人物居中"与"招式名居中"同一个来源。 */
  bottom: 270px;                /* ★ bottom 是「距容器底距离」：真源加高 100 后该值不变，y 自然 52→152 */
                                /*   （两人静止头顶 68/75 ⇒ +100 = 168/175；152 仍在其上方） */
  transform: translateX(-50%);
  transform-origin: 50% 100%;   /* 放大入场只向上长 ⇒ 不会向下压到人物 */
  z-index: 6;                   /* 高于人物(2/3)与特效(5)；低于血条(8)——血条是 UI 且与名不重叠 */
  font-size: 48px;
  line-height: 1;
  font-weight: 900;
  letter-spacing: .04em;
  color: var(--danger);         /* #ff6b5a（项目既有色，未新引入色系） */
  -webkit-text-stroke: 3px #fff;
  paint-order: stroke fill;
  text-shadow: 3px 3px 0 #fff;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity .16s linear;
}
/* 放大入场：幅度刻意只留 ~5%（见报告：再大就会顶出舞台顶边） */
@keyframes skillBigIn { from { transform: translateX(-50%) scale(1.05); opacity: 0; } to { transform: translateX(-50%) scale(1); opacity: 1; } }
.skillbig.in { opacity: 1; animation: skillBigIn .22s cubic-bezier(.2, .9, .2, 1) both; }

/* 受击闪红：硬切、无过渡（§4.3）。JS 直接改 .figure 的 fill。 */

/* ---------- 特效层 ---------- */

.fx {
  position: absolute;
  inset: 0;
  width: 1220px;
  height: 422px;
  pointer-events: none;
  z-index: 5;
  overflow: visible;
}

@keyframes fx-ring { from { transform: scale(.2); opacity: 1; } to { transform: scale(1); opacity: 0; } }
@keyframes fx-spike { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes fx-spark { from { transform: scale(.2); opacity: 1; } to { transform: scale(1.6); opacity: 0; } }
@keyframes fx-arc { 0% { opacity: 0; } 14% { opacity: 1; } 62% { opacity: 1; } 100% { opacity: 0; } }
@keyframes fx-dmg {
  0% { opacity: 0; transform: translateY(4px) scale(.8); }
  20% { opacity: 1; transform: translateY(-6px) scale(1.1); }
  60% { opacity: 1; transform: translateY(-18px) scale(1); }
  100% { opacity: 0; transform: translateY(-24px) scale(1); }
}
@keyframes fx-sway { 0%, 100% { transform: translateY(-2px); } 50% { transform: translateY(2px); } }

/* ---------- 出牌层（我方完整卡牌 + 招式分组 + 逐段滑出） ---------- */

/* 放在 .world 之外、.arena 之内 ⇒ **不参与等比缩放** ⇒ 牌恒为 96×134（可读尺寸） */
/* ---------- 双方已出的牌：47×66 缩小牌，各自挂在血条下方（对称排列） ---------- */
/* ★ 方向的关键：两行都用 flex。
   - 敌方行 left 对齐 + 从左往右用掉 ⇒ 移掉最左一组后，**其余自动左移**；
   - 我方行 right 对齐 + DOM 里按段**倒序**放（第 1 段在最右）⇒ 移掉最右一组后，**其余自动右移**。 */
.cardrow {
  position: absolute; top: 114px;                 /* 血条底 100 + 14px（≥ §7.6 的 12px） */
  display: flex; align-items: flex-start; gap: 9px;   /* 组间 9px */
}
.cardrow-foe { left: 100px; }                     /* 左边缘 = 敌血条左端 */
.cardrow-me { right: 100px; }                     /* 右边缘 = 我血条右端（1220 − 1120） */
/* 一组 = 一段（同招式的牌紧挨；组内 2px ≪ 组间 9px） */
.cgroup { position: relative; display: flex; gap: 2px; flex: none; }
/* 先量位再飞牌：pending 期间占位但不可见（visibility 保留布局 ⇒ getBoundingClientRect 仍然准） */
.cardrow.pending { visibility: hidden; }
.cwrap { width: 47px; height: 66px; position: relative; flex: none; }
.ccard {
  position: absolute; left: 0; top: 0; transform-origin: top left;
  transform: scale(0.489583, 0.492537);           /* 96×134 → 47×66（非等比 0.6% 差，肉眼无感） */
  cursor: default; pointer-events: none;
}
/* 招式名 ②：贴在本组牌**下方**。原位"组上方"已无空间（上方 14px 是血条安全距），下方两行都不会碰到人物
   （敌牌带 x 100→347 vs 敌剪影 402+；我牌带 x 873→1120 vs 我剪影 558→724）。 */
.cname {
  position: absolute; left: 0; top: calc(100% + 3px);
  font-size: 13px; line-height: 1; color: var(--text); opacity: .9;
  white-space: nowrap; pointer-events: none;
}
/* 用掉 ⇒ 淡出并移除（移除后 flex 自动补位） */
.cgroup.out { transition: opacity .18s linear; opacity: 0; }

/* ★ T-ENG-046 ③ 招式牌特效（敌我共用；挂在 .cwrap 上 ⇒ **在 scale 层之外**，不会跟着 0.49 缩小）
   语汇：沿牌外沿一圈**硬边实心火舌** + 一圈 **2px 实线硬环**（只描边、不填充）。
   §12 合规：不发光（无 blur / 无扩散 box-shadow）、不渐变（纯色硬切）、同帧 2 层、2 种彩色、
             描边 = 2px（≥2 ✓）、外扩仅 6px（不越界）。
   ★★ §5「键线」的**有意例外**（已获 team-lead 裁定采纳，非遗漏）★★
     §5 要求"每个特效形状带 1.5px 近黑硬键线 #15110b"，其**动机**是「属性色落在地台 #cdc2a0 上
     对比度只有 1.3–1.7:1」——而**出牌区（#playMe/#playFoe）恒在舞台深底上、不压地台** ⇒ 键线在该处
     **没有存在理由**；且本特效用 clip-path 画火舌（clip-path 无法描边）。⇒ 有意不加键线，别当漏做补。
     若 art-director 要把例外固化进规格（§5 加一句"出牌区特效例外"），改这几行即可。
   参数全部走 CSS 变量（JS 侧同名常量见 app.js 的 FX_*，art-director 可一处改）。 */
:root {
  --fx-flame: var(--danger);     /* 火舌色（项目既有色） */
  --fx-flame2: var(--gold);      /* 火舌高亮态（项目既有色）—— 明暗两态硬切，不用渐变 */
  --fx-ring-w: 2px;              /* 硬环粗（屏幕 px） */
  --fx-h: 6px;                   /* 火舌外凸高度（屏幕 px） */
  --fx-dur: 620ms;               /* 摆动周期 */
}
.cwrap.skillfx::before {          /* 火舌：一个 clip-path 尖刺环（外沿锯齿 + 内挖空 ⇒ 只留一圈尖刺） */
  content: ''; position: absolute; inset: calc(-1 * var(--fx-h)); pointer-events: none;
  background: var(--fx-flame);
  clip-path: polygon(evenodd,
    0% 22%, 6% 0%, 12% 22%, 18% 0%, 25% 22%, 31% 0%, 37% 22%, 43% 0%, 50% 22%, 56% 0%, 62% 22%, 68% 0%, 75% 22%, 81% 0%, 87% 22%, 93% 0%, 100% 22%,
    100% 78%, 94% 100%, 88% 78%, 81% 100%, 75% 78%, 69% 100%, 62% 78%, 56% 100%, 50% 78%, 44% 100%, 37% 78%, 31% 100%, 25% 78%, 19% 100%, 12% 78%, 6% 100%, 0% 78%,
    10% 8%, 10% 92%, 90% 92%, 90% 8%);
  animation: fxFlick var(--fx-dur) steps(1, end) infinite;
  animation-delay: var(--fx-delay, 0ms);
}
.cwrap.skillfx::after {           /* 硬环：只描边、不填充（§5 语汇同族） */
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border: var(--fx-ring-w) solid var(--fx-flame);
  border-radius: 6px;
  animation: fxRing var(--fx-dur) steps(1, end) infinite;
  animation-delay: var(--fx-delay, 0ms);
}
/* 明暗两态**硬切**（steps ⇒ 无渐变、无发光） */
@keyframes fxFlick { 0%, 49% { background: var(--fx-flame); } 50%, 100% { background: var(--fx-flame2); } }
@keyframes fxRing { 0%, 49% { border-color: var(--fx-flame); } 50%, 100% { border-color: var(--fx-flame2); } }

.badge-idle {
  display: inline-block;
  font-size: 12px;
  color: var(--gold);
  border: 1px dashed #6b5424;
  background: #2a2113;
  border-radius: 6px;
  padding: 3px 10px;
}

/* ---------- 招式表 ---------- */

.manual {
  grid-column: 2;                /* ★ T-ENG-040：侧栏跨两行 ⇒ 比舞台高（"加长"） */
  grid-row: 1 / span 2;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  min-height: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  overflow: hidden;              /* ⇒ 它自己的 min-content 贡献为 0，两行高度由舞台/手牌区决定，不会被它撑开 */
  transition: opacity .2s;
}
.manual.dimmed { opacity: .4; }
.manual-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 12px; color: var(--dim); margin-bottom: 8px; flex: none;
}
/* ★ T-ENG-040：侧栏上半 = 人物半身像（占位：复用 createFighter 的剪影；换真立绘只改 app.js 的 portraitOf()） */
.portrait {
  flex: none; position: relative; overflow: hidden;
  /* ★ T-ENG-041：= 取景窗 180×133（app.js 的 PORTRAIT_FX/FY 常量）⇒ 上半身像，框比高更宽（h/w ≈ 0.74） */
  aspect-ratio: 180 / 133;
  margin-bottom: 10px;
  border: 1px solid var(--border); border-radius: 8px; background: #0e1119;
}
.portrait .sil { position: absolute; transform-origin: 0 0; }
.manual-list { overflow-y: auto; min-height: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.manual-list::-webkit-scrollbar { width: 8px; }
.manual-list::-webkit-scrollbar-thumb { background: #2c323f; border-radius: 8px; }

.skill {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  padding: 5px 8px; border-radius: 7px; border: 1px solid transparent; font-size: 13px;
}
.skill.hot { border-color: #3f7a4a; background: #16281b; }
.skill-notation { color: var(--dim); font-size: 12px; }
.skill.hot .skill-notation { color: #7fd08c; }

/* ★ T-ENG-040：动作表（.actions-list）与其标题（.manual-head-2）已按裁决删除 —— 见 index.html 的注释 */

/* ---------- 手牌区 ---------- */

.handbar {
  grid-area: 2 / 1;              /* ★ T-ENG-040：进 board 第 2 行、与舞台同列 ⇒ 宽度自动等于舞台（不再单算） */
  align-self: stretch;           /* ★ T-ENG-040：撑满第 2 行（1fr）⇒ 省下的高度由它消化，底部不留空带 */
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  display: flex; flex-direction: column; justify-content: center; gap: 8px;   /* ★ T-ENG-040：框内内容垂直居中 */
  min-height: 0;
  overflow: hidden;
}
/* 牌行：左 = 手牌组（**固定 7 槽**，卡牌左对齐）；右 = 四个按钮（贴右内缘）
   ★ T-ENG-042 空间账：手牌框内宽 1196 = 7 槽 738 + 组间 41 + 按钮组 417 ⇒ 正好装满、不溢出 */
.handrow { display: flex; justify-content: space-between; align-items: center; gap: 41px; }   /* ★ T-ENG-042：组间 12→41（= 余量全给它；组内 11 的 3.7 倍） */
/* ★ T-ENG-042：牌行的 4 个按钮做成**和牌一样大**（96×134，圆角同牌 11px，文字 22px 居中）。
   只作用于 `.handrow .actions` 里的这 4 个 —— 开始/重开/再来一局用的是别的容器，尺寸一点不变。 */
.handrow .actions .btn {
  width: var(--card-w); height: 134px; min-width: 0; min-height: 0; padding: 0;
  border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; white-space: nowrap;
}
.handhead { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: var(--dim); margin-bottom: 7px; }
.handhead-left { display: flex; gap: 10px; align-items: baseline; }
.handhead-right { display: flex; align-items: center; gap: 12px; }

.foestate { font-size: 12px; color: var(--dim-2); }
.foestate.locked { color: #7fd08c; }

.timer { position: relative; width: 34px; height: 34px; flex: none; }
.timer-svg { width: 34px; height: 34px; transform: rotate(-90deg); }
.timer-bg { fill: none; stroke: #2a3040; stroke-width: 3.4; }
.timer-fg {
  fill: none; stroke: var(--accent); stroke-width: 3.4; stroke-linecap: round;
  stroke-dasharray: 97.4; stroke-dashoffset: 0;
}
.timer.warn .timer-fg { stroke: var(--gold); }
.timer.danger .timer-fg { stroke: var(--danger); }
.timer.danger { animation: pulse .8s infinite; }
.timer-num {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text);
}
.timer.hidden { visibility: hidden; }

/* ★ T-ENG-042：手牌组 = **固定 7 槽宽**（由 --hand-slots/--card-w/--card-gap 推导，不写魔法数 738），
   卡牌**左对齐**。这样 6 张时第 7 槽空着但占位 ⇒ 右侧按钮组纹丝不动（用户要求"按钮不要跑到第七张牌的位置"）。 */
.hand {
  width: calc(var(--hand-slots) * var(--card-w) + (var(--hand-slots) - 1) * var(--card-gap));
  flex: none; min-width: 0;
  display: flex; gap: var(--card-gap); flex-wrap: wrap; min-height: 134px; justify-content: flex-start; align-content: center;
}

/* ---------- 手牌（96 × 134 · 三国杀式牌面） ---------- */
/* 牌面信息 = 四个元素：.star（星数）/ .act（架势名）/ .attr（属性）/ .ord（选牌序号）。
   ⚠️ 动作「编号」只是后台通用的位置代号（保证不同武器匹配招式时通用），
      已从牌面删除、不对玩家显示（见 app.js 的 cardFace / playCard）。
   内细线用 ::before、上下装饰线用 ::after，避免为此改 app.js。 */

.card {
  position: relative;
  width: 96px;
  height: 134px;
  border-radius: 11px;
  border: 2px solid #232838;                        /* 外框 2px 深色 */
  color: var(--text);
  cursor: pointer;
  padding: 0;
  flex: none;
  /* 底 = 属性淡染（上层，随 data-attr 变）+ 深色渐变（下层） */
  background:
    linear-gradient(168deg, var(--tint-1, transparent) 0%, var(--tint-2, transparent) 100%),
    linear-gradient(168deg, #262c3d 0%, #171b26 58%, #12151d 100%);
  transition: transform .12s, border-color .12s, box-shadow .12s;
}
/* 内细线：内缩 6px、1px、属性色 —— 三国杀式「内外双框」 */
.card::before {
  content: '';
  position: absolute;
  inset: 6px;
  border: 1px solid var(--card-attr, #6b7285);
  border-radius: 6px;
  pointer-events: none;
}
/* 上下装饰分隔线（同一伪元素用 border-top / border-bottom 画出两条） */
.card::after {
  content: '';
  position: absolute;
  left: 12px; right: 12px; top: 36px; bottom: 40px;
  border-top: 1px solid rgba(214, 222, 240, .16);
  border-bottom: 1px solid rgba(214, 222, 240, .16);
  pointer-events: none;
}
.card:hover:not(:disabled) { border-color: #3c465c; transform: translateY(-2px); }
.card:disabled { cursor: default; }
.card.on {
  border-color: var(--gold);
  box-shadow: 0 0 0 1px #f5c54255, 0 8px 22px #00000070;
  transform: translateY(-12px);
}
.card.on::before { border-color: var(--gold); }

/* ★ T-ENG-043 手牌三组动画 —— 步距/槽数一律由 --card-w/--card-gap/--hand-slots 推导，不写死派生数 */
/* ① 发牌：从**第 N 槽**滑到自己的槽（--deal-dx = (N−1−i)×步距，由 JS 按常量算出）；错峰 70ms */
@keyframes dealIn { from { transform: translateX(var(--deal-dx, 0px)); opacity: 0; } to { transform: none; opacity: 1; } }
.card.deal { animation: dealIn 320ms cubic-bezier(.2, .9, .2, 1) var(--deal-delay, 0ms) both; }
/* ② 刷新出局：逐张左移到**第 1 槽**并淡出（--out-dx = −i×步距） */
@keyframes outTo1 { to { transform: translateX(var(--out-dx, 0px)); opacity: 0; } }
.card.out1 { animation: outTo1 220ms ease-in var(--out-delay, 0ms) both; }
/* ③ 归拢：FLIP —— JS 先给反向位移，再 transition 回 0（260ms） */
/* （★ T-ENG-043：旧的 `.card.enter` + `@keyframes cardIn` 淡入已被上面的 `deal` 发牌动画取代，一并删除） */

.card .star { position: absolute; top: 6px; left: 9px; font-size: 26px; font-weight: 700; line-height: 1; z-index: 1; }
.card .act {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 48px; font-weight: 600; line-height: 1; z-index: 1;
}
.card .attr { position: absolute; right: 8px; bottom: 6px; font-size: 18px; font-weight: 700; line-height: 1; z-index: 1; }
/* 选牌序号 = 圆环徽标（T-ENG-035：用户要"更显眼"）—— 跨上边、**半突出牌外**。
   · D=22（原先是 12px 裸数字）｜环 2px var(--gold)（与选中高亮同色系）
   · top:-13px = −(D/2 + 卡片 border 2px) ⇒ **圆心正好落在牌的外沿上** ⇒ 实测超出牌上边 11px（= D/2）
   · 底色用不透明的 #12151c（手牌区底色）：否则牌面属性淡染透上来，数字读不清
   · box-sizing:border-box ⇒ 2px 环不会把 D 撑成 26；flex 居中 + line-height:1 ⇒ 数字真正居中（不靠 padding 凑）
   · .card/.hand/.handbar 都没有 overflow ⇒ 牌外那半个不会被裁；徽标默认 pointer-events:auto
     ⇒ 点牌外那半个圆也能命中并冒泡到 <button> 触发选牌 */
.card .ord {
  position: absolute; top: -13px; right: 8px;
  width: 22px; height: 22px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--gold); border-radius: 50%;
  background: #12151c; color: var(--gold);
  font-size: 13px; font-weight: 800; line-height: 1;
  z-index: 2;
}

/* 四属性：内线色 / 淡染底（同一个 data-attr 机制驱动） */
.card[data-attr="！"] { --card-attr: var(--a-bang); --tint-1: rgba(255, 107, 90, .34); --tint-2: rgba(255, 107, 90, .14); }
.card[data-attr="？"] { --card-attr: var(--a-q);    --tint-1: rgba(176, 124, 240, .34); --tint-2: rgba(176, 124, 240, .14); }
.card[data-attr="O"] { --card-attr: var(--a-o);    --tint-1: rgba(77, 163, 255, .34);  --tint-2: rgba(77, 163, 255, .14); }
.card[data-attr="X"] { --card-attr: var(--a-x);    --tint-1: rgba(138, 147, 166, .30); --tint-2: rgba(138, 147, 166, .12); }
.card[data-attr="！"] .attr { color: var(--a-bang); }
.card[data-attr="O"] .attr { color: var(--a-o); }
.card[data-attr="X"] .attr { color: var(--a-x); }
.card[data-attr="？"] .attr { color: var(--a-q); }

/* 飞牌残影 */
/* ★ T-ENG-044：被出牌的"同位不可见副本"——只负责在重绘后继续给 flyCards 当 rect 取样源。
   不可见刻意用**类**（不是内联 opacity/visibility）：flyCards 会把克隆件 className 换成 'card ghost'，
   类一去掉 visibility 就恢复 ⇒ 残影可见地飞出去。 */
.card.ghost-src { position: fixed; visibility: hidden; pointer-events: none; z-index: 0; }

.ghost {
  position: fixed;
  pointer-events: none;
  z-index: 99;
  transition: transform .38s cubic-bezier(.2, .75, .3, 1);
  will-change: transform;
}

/* ---------- 试算区（★ T-ENG-040 起：.playbar 里只剩 #preview，作为牌行下方一行） ---------- */

/* ★ T-ENG-055：**钉死试算区高度** —— #preview 内容在 14px(.dim, 行盒21) 与 17px(.pv-total, 行盒25.5)
   之间切换，而这一列在垂直方向居中 ⇒ 高度差 4.5px 被上下各分 2.25px，**把手牌整排上下推**（用户报的抖动）。
   做法：① 统一行盒（`.playbar` 定死 line-height，`.dim` 与 `.pv-total` 同高 ⇒ 单行永远 21px）
        ② `.playbar` 固定高度 = 改前的自然高（30 = 内容21 + padding-top8 + border1）⇒ **不改变静态布局**
        ③ 超出（多段换行）**裁切而不推挤** —— 布局稳定优先（team-lead 明确允许"裁切/溢出但不推挤"）。
   ⚠️ 不许靠调小 .pv-total 或删多段信息来回避（那是改产品信息量）。 */
.playbar {
  display: flex; align-items: center; gap: 16px;
  margin-top: 2px; padding-top: 8px; border-top: 1px solid var(--border);
  height: 30px;              /* ★ T-ENG-055：固定高（= 改前自然高，静态布局零变化） */
  overflow: hidden;          /* ★ 内容变高/换行时裁切，不在布局上传播 */
  line-height: 21px;         /* ★ 统一行盒：.dim(14px) 与 .pv-total(17px) 单行同高 */
}
.preview { flex: 1; min-width: 0; font-size: 14px; }
.preview .pv-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.preview .pv-total { font-weight: 700; font-size: 17px; }
.preview .pv-seg { color: var(--dim); }
.preview .pv-name { color: var(--accent); }
.preview.bad { color: var(--danger); }
.actions { display: flex; gap: var(--card-gap); flex: none; }   /* ★ T-ENG-042：9→11（与卡牌间距一致） */

/* ---------- 结算 ---------- */

.overlay-end { background: #0b0d12d0; }
.result-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  padding: 30px 46px; text-align: center;
  display: flex; flex-direction: column; gap: 10px; align-items: center;
  box-shadow: 0 24px 70px #0009;
}
.result-title { font-size: 26px; font-weight: 700; }
.result-title.win { color: #6fd07f; }
.result-title.lose { color: var(--danger); }
.result-title.draw { color: var(--dim); }
.result-sub { color: var(--dim); font-size: 13px; }

/* ---------- 动画 ---------- */

/* ★ T-ENG-060：`@keyframes pop` 已随猜拳遮罩（`.rps-hand.throw`）删除 —— 唯一使用方已不存在。 */
/* （★ T-ENG-043：`@keyframes cardIn` 已随 `.card.enter` 一起删除 —— 发牌动画改用 `dealIn`） */
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .55; }
}
