/* ==========================================================================
   NZEP 资料库 · assets/games/kards.css —— 卡兹 Kards 的牌桌样式与动效
   --------------------------------------------------------------------------
   这个文件只服务 /kards 那一页（kards.html + assets/games/kards-page.js）。
   类名统一 `k-` 前缀，**不覆盖 games.css 里任何既有类**（`g-` 那套照旧共用：
   g-btn / g-tag / g-input / g-note / w-toast / st-* 外壳），所以两份 CSS 可以各改各的。

   布局（照着 Kards 的牌桌）：
     对手 HQ 与军费（上） → 对手后方 → **前线（双方共用的交战区）** → 我的后方
     → 我的 HQ 与军费 → 手牌（底部一排，手机横向滑动） → 操作条
   两侧的"后方"是我方/对手各自摆单位的地方；前线是双方都能站人的那条线。

   卡面**全部用代码画**（DOM + CSS + 内联 SVG 图标）：不依赖任何外部图片，
   也不依赖网络字体。有 card.img（自定义卡包上传的图）时把它放进上半部。
   同一套卡面（.k-card）在手牌、场上单位、详情浮层三处复用，只在根节点加
   .k-onboard / .k-big 两个修饰类，不写三份。

   动效一律尊重 prefers-reduced-motion：开了就把 animation/transition 全关掉，
   内容照常显示（不是"看不见"，是"不动"）。
   ========================================================================== */

/* ---------------------------------------------------------------- 基础 */
.k-body { background: #f4f3ef; }
.k-body .st-bar { position: sticky; top: 0; z-index: 30; }
.k-body #kWho strong { color: #fff; }
.k-wrap { padding: .2rem 0 1.2rem; }
.k-title { font-family: var(--serif); font-size: 1.5rem; margin: .3rem 0 .1rem; }
.k-lead { color: var(--text-2); font-size: .88rem; line-height: 1.9; margin: 0 0 .9rem; }
.k-sec { margin: 1.1rem 0 0; }
.k-sec h2 { font-family: var(--serif); font-size: 1.05rem; margin: 0 0 .5rem; }
.k-hide { display: none !important; }
.k-tip { color: var(--text-3); font-size: .76rem; line-height: 1.8; }
.k-row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }

/* 军费/血量这类数字统一等宽，读得快 */
.k-num { font-family: var(--mono, ui-monospace, Consolas, monospace); font-weight: 700; }

/* ---------------------------------------------------------------- 大厅：卡包 */
.k-packs { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: .7rem; }
.k-pack {
  position: relative; border: 1px solid var(--eg-b-faint, #eaecf0); background: #fff;
  padding: .8rem .85rem .85rem; display: flex; flex-direction: column; gap: .45rem;
  border-top: 4px solid var(--k-band, #54595d);
}
.k-pack h3 { margin: 0; font-family: var(--serif); font-size: 1.06rem; display: flex; align-items: center; gap: .4rem; }
.k-pack .k-flag-chip {
  display: inline-block; font-size: .7rem; padding: 0 .3rem; border: 1px solid currentColor;
  color: var(--k-band, #54595d); font-weight: 700; letter-spacing: .06em;
}
.k-pack p { margin: 0; color: var(--text-2); font-size: .82rem; line-height: 1.8; }
.k-pack .k-pack-ops { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: auto; }

/* ---------------------------------------------------------------- 强度等级徽章
   2026-10-10：卡包实测强度 **1–16 级**（8 级 = 与对照组基准包五五开）。
   **纯显示** —— 不影响匹配、开房与规则。色阶从灰（1）到本站深红（9）。 */
.k-tier {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  font-size: .7rem; line-height: 1.6; padding: 0 .34rem; border-radius: 2px;
  border: 1px solid transparent; font-weight: 700; letter-spacing: .02em; cursor: help; min-width: 2.6rem;
}
  .k-tier-lv1 { background: #f4f5f6; border-color: #d6d3cc; color: #72777d; }
  .k-tier-lv2 { background: #eef0f2; border-color: #c8ccd1; color: #54595d; }
  .k-tier-lv3 { background: #e8ecef; border-color: #c8ccd1; color: #3f4650; }
  .k-tier-lv4 { background: #fdf0e6; border-color: #f0c9a8; color: #8a4b12; }
  .k-tier-lv5 { background: #fdf3e6; border-color: #eed9b8; color: #7f5a12; }
  .k-tier-lv6 { background: #fdf6e3; border-color: #e8d9a8; color: #7a5c00; }
  .k-tier-lv7 { background: #fdeee0; border-color: #f0c08e; color: #8a4b12; }
  .k-tier-lv8 { background: #fdf6e3; border-color: #e2c98a; color: #6f5100; }
  .k-tier-lv9 { background: #fbe6d5; border-color: #ecb98d; color: #8f4310; }
  .k-tier-lv10 { background: #fbe0d2; border-color: #e9a985; color: #9a3412; }
  .k-tier-lv11 { background: #f9d5c4; border-color: #e29a78; color: #9c2d0c; }
  .k-tier-lv12 { background: #f7c9b6; border-color: #dc8b66; color: #a11f08; }
  .k-tier-lv13 { background: #f2ae95; border-color: #cf6b44; color: #b01; }
  .k-tier-lv14 { background: #e79a80; border-color: #c25a35; color: #fff; }
  .k-tier-lv15 { background: #d97e63; border-color: #ad4526; color: #fff; }
  .k-tier-lv16 { background: #b01; border-color: #7d0009; color: #fff; }
/* 卡包列表里的那行说明（"等级是什么、不影响什么"） */
.k-tier-legend { margin: .3rem 0 .5rem; line-height: 1.8; }
.k-tier-legend b { font-family: var(--mono); }
.k-pack-row .k-tier { margin: 0 .1rem; }

/* 我的段位（放在大厅的卡片节里，外面已经有一层卡片，所以这里不再套边框） */
.k-mytier {
  display: flex; align-items: center; gap: .55rem .7rem; flex-wrap: wrap; line-height: 1.8;
}
.k-mytier .k-tname { font-family: var(--serif); font-size: 1.02rem; font-weight: 700; }
.k-mytier .k-prog { flex: 1 1 120px; min-width: 100px; height: 6px; background: #eceff1; position: relative; border-radius: 999px; overflow: hidden; }
.k-mytier .k-prog i { position: absolute; left: 0; top: 0; bottom: 0; background: #d9a400; border-radius: 999px; }

/* ---------------------------------------------------------------- 牌桌骨架 */
.k-table { display: flex; flex-direction: column; gap: .5rem; }
.k-side {
  border: 1px solid var(--eg-b-faint, #eaecf0); background: #fff; padding: .5rem .6rem;
  display: flex; flex-direction: column; gap: .45rem;
}
.k-side.them { border-top: 3px solid #b32424; }
.k-side.me { border-bottom: 3px solid #14866d; }

/* HQ 一行：血条 + 军费 + 牌堆/手牌数 */
.k-hq-row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.k-hq {
  display: flex; align-items: center; gap: .45rem; border: 1px solid #c8ccd1; background: #fbfbfa;
  padding: .25rem .5rem; min-width: 190px;
}
.k-hq .k-hq-name { font-weight: 700; font-size: .84rem; }
.k-hq .k-hp { position: relative; flex: 1 1 90px; height: 12px; background: #e7e3dc; min-width: 70px; }
.k-hq .k-hp i { position: absolute; left: 0; top: 0; bottom: 0; background: #14866d; transition: width .3s ease-out; }
.k-hq.low .k-hp i { background: #d9a400; }
.k-hq.crit .k-hp i { background: #b32424; }
.k-hq .k-hp b { position: absolute; right: .25rem; top: -1px; font-size: .72rem; font-family: var(--mono, monospace); }
.k-kredits { display: flex; align-items: center; gap: .3rem; font-size: .84rem; }
.k-kredits .k-gem {
  width: 1.05rem; height: 1.05rem; border-radius: 50%; background: #3366cc; color: #fff;
  font-size: .7rem; font-weight: 700; display: inline-flex; align-items: center; justify-content: center;
}
.k-meta { color: var(--text-3); font-size: .74rem; display: flex; gap: .5rem; flex-wrap: wrap; }

/* 三条线：对手后方 / 前线 / 我的后方 */
.k-line {
  border: 1px dashed #d6d3cc; background: #fbfbf8; min-height: 118px; padding: .35rem;
  display: flex; align-items: center; gap: .4rem; position: relative; overflow-x: auto;
}
.k-line > .k-line-label {
  position: absolute; left: .35rem; top: .2rem; font-size: .68rem; color: var(--text-3);
  letter-spacing: .08em; pointer-events: none;
}
.k-line.front { border-style: solid; border-color: #c9bfa6; background: #f7f3e8; min-height: 126px; }
.k-line .k-units { display: flex; gap: .4rem; align-items: flex-end; flex-wrap: nowrap; }
.k-line .k-units.mine { margin-left: auto; }
.k-empty { color: var(--text-3); font-size: .76rem; padding: .2rem .3rem; }

/* 部署区（选中单位牌时点亮） */
.k-zone { cursor: pointer; transition: box-shadow .15s ease-out, background .15s ease-out; }
.k-zone.on { background: #eef7f1; box-shadow: inset 0 0 0 2px #14866d; animation: k-zone-pulse 1.4s ease-in-out infinite; }
.k-zone.off { background: #f6f2f2; box-shadow: inset 0 0 0 2px #c8ccd1; cursor: not-allowed; }
.k-zone.on .k-line-label { color: #0f6b57; font-weight: 700; }

/* ---------------------------------------------------------------- 卡面（唯一一份） */
/* 2026-10-06 第二轮（用户原话：「这太瘦长了，预览卡面简洁有字数限制，超过某字数或
   空间不够多余将会省略为...，而卡牌名字最高30字数限制」）。
   上一版让卡面"长高"来塞下全文，结果就是"瘦长"。这一版是**固定高度的紧凑卡面**，
   优先级明确写死：**名字 > 徽标 > 简介**。
     · 高度 = --k-ch（固定值，不再是 min-height）：同一场景里所有卡一样高，
       最坏情况（连击+主动技能+被动触发×2+远程）也一样高，绝不把牌桌的行撑高；
     · 名字（第一优先）：单行、white-space: nowrap + text-overflow: ellipsis，
       永远占满自己那一行 —— 不许被压扁、不许与徽标重叠、不许被简介挤掉。
       字数上限 30（服务端 KARDS_LIMITS.cardName=30 + 编辑器输入框 maxlength=30），
       卡面宽度放不下时以「…」收尾（完整名字在 title 与详情面板里）；字号 ≥12.8px；
     · 徽标（第二优先）：连击N / 技能N / 被动N，**只占一行**，flex-wrap: nowrap；
       一行放不下时 chip 自己在内部省略（可收缩 + text-overflow: ellipsis），
       绝不换行去跟名字/简介抢空间；
     · 简介（最后优先）：-webkit-line-clamp 到 --k-lines 行，放不下以「…」收尾，
       横向靠 overflow-wrap: anywhere 折行。完整原文一律在详情面板
       （[data-k-detail-text] + mechHtml 的机制块）里一字不少，观战也能看。
   —— 具体数值（改这里就要同步改 tools/test-kards-ui.js 里 FACE 那张表与断言）：
     · 卡面高度（固定值，同一场景内**完全一致**）：
         手牌 / 编辑器预览：桌面 172px、≤760 宽 172px、≤420 宽 156px（--k-cw 118 / 104 / 96）
         场上单位      ：桌面 158px、≤760 宽 154px、≤420 宽 150px（--k-cw 100 / 88 / 82）
         详情放大卡    ：桌面 300px、≤760 宽 232px（--k-cw 210 / 150）
       高度是按"最坏情况那张"算的（名字 1 行 + 徽标 1 行 + 简介 --k-lines 行 + 数值 1 行
       + 场上还多一行状态），留 1–6px 余量，所以卡图（.k-art）永远不会被挤扁；
     · 名字：单行，≤30 字（硬上限），字号 12.8px（详情放大卡 16px）—— 绝不再小；
     · 简介：桌面手牌/预览 3 行、场上 2 行；≤420 宽一律 2 行（--k-lines）。
       字号 11.2px（≥11px 可读下限）；一行 ≈ 9–10 个汉字（@118px），
       也就是手牌 ≈ 27 字、场上 ≈ 15 字，多出来的「…」；
     · 徽标：最多 3 个 chip，只占 1 行（高 ≈13.8px），字号 10.24px（≥10px）。 */
.k-card {
  position: relative; flex: 0 0 auto;
  width: var(--k-cw, 118px); height: var(--k-ch, 172px);
  border: 1px solid #b9b4a8; background: #fffdf8; padding: .28rem .3rem .3rem;
  display: flex; flex-direction: column; gap: .18rem; overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .12);
  /* 阵营色带：自定义卡包用中性色 */
  border-top: 5px solid var(--k-band, #54595d);
  user-select: none; -webkit-user-select: none; touch-action: manipulation;
}
.k-card .k-art {
  height: 42px; background: var(--k-tint, #f0eeea); display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
}
.k-card .k-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.k-card .k-art .k-watermark {
  font-family: var(--serif); font-size: 1.5rem; font-weight: 700; color: var(--k-band, #54595d); opacity: .28;
}
.k-card .k-cost {
  position: absolute; left: .22rem; top: .3rem; width: 1.35rem; height: 1.35rem; border-radius: 50%;
  background: #3366cc; color: #fff; font-size: .78rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center; box-shadow: 0 0 0 2px #fff;
}
.k-card .k-cost.no { background: #9aa0a6; }
.k-card .k-kind {
  position: absolute; right: .22rem; top: .32rem; width: 1.2rem; height: 1.2rem;
  background: #fff; border: 1px solid #c8ccd1; display: flex; align-items: center; justify-content: center;
}
.k-card .k-kind svg { width: .95rem; height: .95rem; display: block; }
/* 名字：**第一优先**。永远单行、永远占满自己那一行（flex: 0 0 auto 不吃不让），
   放不下才在**自己的行内**省略成「…」—— 完整名字在 title 与详情面板里。
   绝不换行（换行会把卡面撑高＝又变成"瘦长"），也绝不被下面的徽标/简介挤扁。 */
.k-card .k-name {
  font-family: var(--serif); font-size: .8rem; font-weight: 700; line-height: 1.25; margin-top: .1rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  flex: 0 0 auto; max-width: 100%;
}
/* 简介：**最后优先**。-webkit-line-clamp 到 --k-lines 行，多出来的以「…」收尾；
   横向用 overflow-wrap: anywhere 折行（长英文/型号也不会顶破卡面）。
   height 用 calc 算成**整数行**（--k-fs × 1.4 × --k-lines）：flex 自由伸缩会在
   半行处截断（第二行只露出 2/3，字底被切），固定成整行 + overflow: hidden 才是
   干净的「…」收尾。剩下那点空间由 .k-stats 的 margin-top: auto 吃掉（数值行永远贴底）。 */
.k-card .k-text {
  font-size: var(--k-fs, .7rem); line-height: 1.4; color: var(--text-2);
  flex: 0 0 auto; height: calc(var(--k-fs, .7rem) * 1.4 * var(--k-lines, 3));
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--k-lines, 3);
  overflow: hidden; text-overflow: ellipsis;
  white-space: normal; overflow-wrap: anywhere; word-break: break-word;
}
.k-card .k-stats { display: flex; justify-content: space-between; align-items: flex-end; margin-top: auto; flex: 0 0 auto; }
.k-card .k-atk, .k-card .k-def {
  min-width: 1.25rem; height: 1.25rem; padding: 0 .18rem; border-radius: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .8rem; font-weight: 700; font-family: var(--mono, monospace);
}
.k-card .k-atk { background: #fdecec; color: #8f1c1c; border: 1px solid #e6c3c3; }
.k-card .k-def { background: #eef3fb; color: #24457f; border: 1px solid #c3d0e6; }
/* 受过伤的单位：防御数字标红（引擎给了 maxDefense 时才可能出现） */
.k-card .k-def.hurt { background: #fdecec; color: #8f1c1c; border-color: #e6c3c3; }
/* 每座位用的卡包名（引擎给了 packLabels 才显示） */
.k-meta .k-pack-name { color: #54595d; border: 1px solid #d6d3cc; padding: 0 .22rem; }
.k-card .k-order-mark {
  font-size: .64rem; color: #5b21b6; border: 1px solid #d6c7f5; background: #f6f1ff; padding: 0 .2rem;
}
.k-card .k-state { font-size: .62rem; color: var(--text-3); flex: 0 0 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.k-card .k-state.ready { color: #0f6b57; font-weight: 700; }
/* 远程标记：**必须单行**。窄卡面（82px）上「远程」两个字曾经折成两行，把数值行撑到 33px，
   于是卡面内容超界 → flex 拿 .k-art 去顶（图片卡的上半部被压成 7px）。现在 nowrap +
   可收缩省略：宁可省略号，也不换行。 */
.k-card .k-ranged {
  font-size: .6rem; color: #7a5c00; border: 1px solid #e3d5a8; background: #fff8e6; padding: 0 .2rem;
  white-space: nowrap; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
}

/* 场上单位的槽：只负责"可点语义"，不改变卡面尺寸 */
.k-unit-slot { display: flex; }
.k-card-slot { display: flex; }
/* 观战（只读）：槽上没有行动语义，点一下＝看详情 —— 光标给出手感 */
.k-unit-slot.k-ro { cursor: pointer; }

/* 手牌上的状态 */
.k-card.sel { transform: translateY(-10px); box-shadow: 0 10px 18px rgba(0, 0, 0, .28); }
.k-lift { transition: transform .16s cubic-bezier(.2, .8, .3, 1), box-shadow .16s ease-out; }
.k-card.dim { opacity: .55; }
.k-card.dim .k-cost { background: #9aa0a6; }
.k-card.playable { box-shadow: 0 0 0 2px #14866d, 0 1px 2px rgba(0, 0, 0, .12); }

/* 场上单位：小一号。卡面同样是**固定高度**（--k-onboard 那组数值），
   简介只给 2 行；名字依旧是第一优先、绝不被压。 */
.k-card.k-onboard { --k-cw: 100px; --k-ch: 158px; --k-lines: 2; --k-fs: .7rem; }
.k-card.k-onboard .k-art { height: 28px; }
.k-card.k-onboard.spent { filter: saturate(.5); opacity: .82; }
.k-card.k-onboard.spent::after {
  content: '已行动'; position: absolute; left: 0; right: 0; bottom: 0; text-align: center;
  font-size: .6rem; background: rgba(0, 0, 0, .45); color: #fff; padding: .1rem 0;
}
.k-card.k-onboard.mine.can-act { box-shadow: 0 0 0 2px #d9a400; }

/* 可打的目标 / 被选中的单位 */
.k-card.mine-sel { box-shadow: 0 0 0 3px #3366cc, 0 0 12px rgba(51, 102, 204, .5); }
.k-card.target { cursor: crosshair; animation: k-target 1.1s ease-in-out infinite; }
.k-hq.target { cursor: crosshair; box-shadow: 0 0 0 2px #b32424; animation: k-target 1.1s ease-in-out infinite; }

/* 详情浮层里的放大卡面：也**固定高度**（不再被超长文案撑长），简介最多 7 行；
   完整说明在右侧那一栏（[data-k-detail-text] + 机制块），放大卡只是"看一眼长什么样"。 */
.k-card.k-big { --k-cw: 210px; --k-ch: 300px; --k-lines: 7; --k-fs: .78rem; }
.k-card.k-big .k-art { height: 96px; }
.k-card.k-big .k-name { font-size: 1rem; }

/* ---------------------------------------------------------------- 手牌与操作条 */
.k-hand-wrap {
  border: 1px solid var(--eg-b-faint, #eaecf0); background: #fff; padding: .45rem .5rem;
  /* 手牌台只给下限高度：卡面固定高（--k-ch）以后再留一点余量就够了 */
  display: flex; gap: .4rem; overflow-x: auto; overflow-y: auto; min-height: calc(var(--k-ch, 172px) + 1rem);
  -webkit-overflow-scrolling: touch;
}
.k-hand-wrap.dim { opacity: .6; }
.k-bars {
  position: sticky; bottom: 0; z-index: 20; background: #ffffffee;
  border: 1px solid var(--eg-b-faint, #eaecf0); padding: .45rem .55rem;
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; backdrop-filter: blur(4px);
}
.k-turn { font-size: .84rem; display: flex; align-items: center; gap: .4rem; }
.k-turn .who { font-weight: 700; }
.k-turn .dot { width: .55rem; height: .55rem; border-radius: 50%; background: #c8ccd1; }
.k-turn.mine .dot { background: #14866d; animation: k-turn 1.4s ease-in-out infinite; }
.k-turn.over .dot { background: #b32424; }
.k-selinfo { font-size: .78rem; color: var(--text-2); min-height: 1.2em; }

/* 提示条（把服务端回来的中文原因显示出来，而不是只弹一下就没了） */
.k-hint { border-left: 4px solid #3366cc; background: #eaf3ff; padding: .4rem .55rem; font-size: .8rem; line-height: 1.7; }
.k-hint.warn { border-left-color: #d9a400; background: #fff8e6; }
.k-hint.bad { border-left-color: #b32424; background: #fdecec; }

/* 日志 / 聊天 */
.k-log { border: 1px solid var(--eg-b-faint, #eaecf0); background: #fff; max-height: 10rem; overflow: auto; }
.k-log div { padding: .28rem .5rem; border-bottom: 1px solid var(--eg-b-faint, #eaecf0); font-size: .78rem; color: var(--text-2); }
.k-log div:last-child { border-bottom: 0; }
.k-chat-list { max-height: 8rem; overflow: auto; padding: .35rem .5rem; display: flex; flex-direction: column; gap: .25rem; }
.k-chat-list .who { color: var(--text-3); font-size: .72rem; }
.k-chat-form { display: flex; gap: .4rem; padding: .4rem; border-top: 1px solid var(--eg-b-faint, #eaecf0); }

/* ---------------------------------------------------------------- 详情浮层 */
.k-detail {
  position: fixed; inset: 0; z-index: 60; background: rgba(20, 20, 20, .55);
  display: flex; align-items: center; justify-content: center; padding: 1rem;
}
.k-detail-box {
  background: #fff; border: 1px solid #191919; max-width: 34rem; width: 100%; max-height: 86vh; overflow: auto;
  padding: .9rem 1rem; display: flex; gap: .9rem; align-items: flex-start; flex-wrap: wrap;
}
.k-detail-box h3 { margin: 0 0 .3rem; font-family: var(--serif); font-size: 1.1rem; }
.k-detail-box p { margin: 0 0 .5rem; font-size: .84rem; line-height: 1.9; color: var(--text-2); white-space: pre-wrap; }
.k-detail-meta { display: flex; gap: .4rem; flex-wrap: wrap; margin-bottom: .5rem; }
/* 详情里的机制块（连击 / 主动技能 / 被动触发）：一行一条，把花费与效果都说全 ——
   观战看客只能看，这张牌"有什么本事"全靠这里读出来。 */
.k-detail-mech { font-size: .82rem; line-height: 1.85; color: var(--text-2); margin: 0 0 .35rem; }
.k-detail-mech b { color: var(--text-1, #202122); }
/* 能点开详情的战报行 / 卡表小卡：给出"可点"的手感（纯只读，不改任何状态） */
.k-log .k-log-hit { cursor: pointer; border-radius: 2px; }
.k-log .k-log-hit:hover { background: #eef3fb; }
.k-mini[data-k-insp] { cursor: pointer; }
.k-mini[data-k-insp]:hover { outline: 2px solid #2a54a8; outline-offset: 2px; }
@media (max-width: 760px) {
  /* 手机上能点的战报行也要够大（≥44px），别让人戳不中 */
  .k-log .k-log-hit { min-height: 44px; display: flex; align-items: center; }
}

/* ---------------------------------------------------------------- 结算横幅 */
.k-banner {
  position: fixed; left: 50%; top: 22%; transform: translate(-50%, -50%); z-index: 55;
  background: #191919ee; color: #fff; padding: .9rem 1.3rem; text-align: center; min-width: 12rem;
  border: 1px solid #000; pointer-events: none;
}
.k-banner b { display: block; font-family: var(--serif); font-size: 1.3rem; }
.k-banner span { font-size: .82rem; color: #d8d8d3; }

/* ---------------------------------------------------------------- 卡包管理（超管/特邀） */
.k-packs-admin { border: 1px solid var(--eg-b-faint, #eaecf0); background: #fff; padding: .7rem .8rem; }
.k-pack-row {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  border-bottom: 1px solid var(--eg-b-faint, #eaecf0); padding: .45rem 0;
}
.k-pack-row:last-child { border-bottom: 0; }
.k-card-form {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .45rem;
  border: 1px dashed #c8ccd1; padding: .5rem; margin: .4rem 0;
}
.k-card-form label { display: flex; flex-direction: column; gap: .2rem; font-size: .74rem; color: var(--text-2); }
.k-card-form input[type="text"], .k-card-form input[type="number"], .k-card-form select, .k-card-form textarea {
  font: inherit; font-size: .8rem; padding: .3rem .35rem; border: 1px solid #c8ccd1; background: #fff; min-height: 34px;
  /* 下拉里的效果名是长中文（「直接摧毁一个敌方单位（无视防御）（destroy）」），
     <select> 默认按内容撑宽 —— 手机上会把整页顶出横向滚动条。一律夹在容器里。 */
  max-width: 100%; min-width: 0; box-sizing: border-box;
}
.k-card-form textarea { min-height: 54px; resize: vertical; }

/* ---------------------------------------------------------------- 动效 */
@keyframes k-deal {
  0% { opacity: .25; transform: translateY(26px) scale(.92); }
  100% { opacity: 1; transform: none; }
}
.k-fx-deal { animation: k-deal .34s cubic-bezier(.22, .8, .3, 1) both; }

@keyframes k-drop {
  0% { opacity: .6; transform: translateY(-26px) scale(1.08); }
  65% { opacity: 1; transform: translateY(2px) scale(.985); }
  100% { opacity: 1; transform: none; }
}
.k-fx-drop { animation: k-drop .34s cubic-bezier(.3, 1.4, .5, 1) both; }

@keyframes k-lunge {
  0% { transform: none; }
  45% { transform: translateY(var(--k-dy, -16px)); }
  100% { transform: none; }
}
.k-fx-lunge { animation: k-lunge .3s ease-out; }

@keyframes k-hit {
  0%, 100% { transform: none; filter: none; }
  20% { transform: translateX(-4px); filter: brightness(1.5) saturate(2); }
  50% { transform: translateX(4px); filter: brightness(1.7) saturate(2); }
  70% { transform: translateX(-2px); }
}
.k-fx-hit { animation: k-hit .32s ease-in-out; }
/* 治疗/增益：往回"鼓"一下（绿色），跟受伤的红闪区分开 */
@keyframes k-heal {
  0%, 100% { box-shadow: 0 0 0 0 rgba(20, 134, 109, 0); }
  40% { box-shadow: 0 0 0 3px rgba(20, 134, 109, .55); transform: translateY(-2px); }
}
.k-fx-heal { animation: k-heal .42s ease-out; }

@keyframes k-hqhurt {
  0%, 100% { background: #fbfbfa; }
  30% { background: #fdecec; box-shadow: 0 0 0 2px #b32424 inset; }
}
.k-fx-hq { animation: k-hqhurt .42s ease-out; }

@keyframes k-turn { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@keyframes k-target {
  0%, 100% { box-shadow: 0 0 0 2px #b32424, 0 0 6px rgba(179, 36, 36, .4); }
  50% { box-shadow: 0 0 0 3px #e04b4b, 0 0 14px rgba(224, 75, 75, .7); }
}
@keyframes k-zone-pulse {
  0%, 100% { box-shadow: inset 0 0 0 2px #14866d; }
  50% { box-shadow: inset 0 0 0 3px #1ea97f; }
}
@keyframes k-shake {
  0%, 100% { transform: none; }
  20% { transform: translateX(-5px); }
  50% { transform: translateX(5px); }
  80% { transform: translateX(-3px); }
}
.k-fx-shake { animation: k-shake .3s ease-in-out; }
/* 阵亡：整个战场轻轻一震（配合 boom 音效）—— 幅度比 shake 小，因为它是"余震"不是"错误" */
@keyframes k-boom {
  0%, 100% { transform: none; filter: none; }
  18% { transform: translateY(2px) scale(.995); filter: brightness(1.06) saturate(1.15); }
  55% { transform: translateY(-1px); }
}
.k-fx-boom { animation: k-boom .48s ease-out; }

@keyframes k-banner {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.86); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
.k-fx-banner { animation: k-banner .38s cubic-bezier(.2, .9, .3, 1) both; }

/* 「减少动态效果」：动画与位移动效全关，但内容必须照常可见 */
@media (prefers-reduced-motion: reduce) {
  .k-fx-deal, .k-fx-drop, .k-fx-lunge, .k-fx-hit, .k-fx-heal, .k-fx-hq, .k-fx-shake, .k-fx-banner,
  .k-zone.on, .k-card.target, .k-hq.target, .k-turn.mine .dot {
    animation: none !important;
  }
  .k-card.sel, .k-lift, .k-hq .k-hp i { transition: none !important; }
  .k-card.sel { transform: none !important; box-shadow: 0 0 0 3px #3366cc !important; }
}
/* JS 也可以主动关（减少动效时给 <html> 加 .k-reduce） */
html.k-reduce .k-fx-deal, html.k-reduce .k-fx-drop, html.k-reduce .k-fx-lunge,
html.k-reduce .k-fx-hit, html.k-reduce .k-fx-heal, html.k-reduce .k-fx-hq, html.k-reduce .k-fx-shake,
html.k-reduce .k-fx-banner, html.k-reduce .k-zone.on, html.k-reduce .k-card.target,
html.k-reduce .k-fx-boom,
html.k-reduce .k-hq.target, html.k-reduce .k-turn.mine .dot { animation: none !important; }
html.k-reduce .k-card.sel { transform: none !important; }

/* ---------------------------------------------------------------- 快速匹配的等待面板
   （服务端排队 + 轮询 2 秒；这里只管长相：一行状态 + 一行说明 + 两个按钮） */
.k-match {
  border: 1px solid #c8ccd1; border-left: 4px solid #b01;
  background: #fff; padding: .85rem 1rem; margin-bottom: .8rem;
}
.k-match-head { font-family: var(--serif); font-size: 1.05rem; font-weight: 700; }
.k-match-line { margin: .35rem 0 .2rem; font-size: .92rem; line-height: 1.6; color: var(--tx2, #54595d); }
.k-match .k-tip { margin: .1rem 0 .5rem; }
.k-match .k-row { display: flex; gap: .5rem; flex-wrap: wrap; }

/* ---------------------------------------------------------------- 手机（390 宽）
   卡面还是**固定高度**，只是每档矮一点：手机上"紧凑"尤其重要（一屏要塞下三条线+手牌）。
   同一档里的所有卡依旧完全等高。**宽度别往窄里收**：卡面宽:高要维持"像一张卡"
   （场上最窄的一档 90×150 ≈ 0.60；上一版 84×460 ≈ 0.18 就是用户说的"瘦长"）。 */
@media (max-width: 760px) {
  :root, .k-body { --k-cw: 104px; --k-ch: 172px; }
  .k-card.k-onboard { --k-cw: 96px; --k-ch: 154px; }
  .k-card.k-onboard .k-art { height: 24px; }
  .k-line { min-height: 104px; }
  .k-line.front { min-height: 112px; }
  .k-hq { min-width: 0; flex: 1 1 auto; }
  .k-bars { position: sticky; bottom: 0; }
  .k-bars .g-btn { min-height: 44px; }
  .k-hand-wrap { gap: .3rem; }
  .k-detail-box { padding: .7rem .75rem; }
  .k-card.k-big { --k-cw: 150px; --k-ch: 232px; --k-lines: 5; }
  .k-card.k-big .k-art { height: 64px; }
}
@media (max-width: 420px) {
  :root, .k-body { --k-cw: 96px; --k-ch: 156px; }
  .k-card.k-onboard { --k-cw: 82px; --k-ch: 150px; }
  .k-card.k-onboard .k-art { height: 20px; }
  /* 2026-10-06 第二轮：手机上一律 2 行简介（--k-lines 由上面那档给），
     放不下就以「…」收尾 —— 全文在详情面板里。字号下限由 --k-fs 保证（≥ .7rem ≈ 11px）。 */
  .k-card { --k-lines: 2; }
}

/* ================================================================================
   敌我识别（2026-09-27 强化）
   --------------------------------------------------------------------------------
   用户原话：「敌我识别等于没有」。所以这一版三件事一起做：
     · 两边各是一整块**带标题的区域**（敌方在上 / 我方在下），底色与左边框都不同；
     · **不只靠颜色** —— 每张场上卡带一个「我方 / 敌方」文字徽标，标题里也有；
     · 前线拆成「敌方前线 / 我方前线」两段，各自标清归属（原来挤在一条线上靠位置猜）。
   ================================================================================ */
.k-side {
  border: 1px solid #d8d3c8; border-left-width: 6px; border-radius: 3px;
  padding: .45rem .55rem .6rem;
}
/* 底色用**实色**（background-color）打底，再叠一层渐变 ——
   只写渐变的话 getComputedStyle().backgroundColor 是透明的，
   "两侧底色不同"这种断言也就测不出来（用户要的"一眼分清"同样会打折）。 */
.k-side.them { background-color: #fdf2f1; background-image: linear-gradient(180deg, #fdf2f1, #fbf8f4); border-left-color: #b32424; }
.k-side.me { background-color: #eff8f5; background-image: linear-gradient(180deg, #eff8f5, #f8fbf9); border-left-color: #14866d; }
.k-side-head { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; font-size: .84rem; }
.k-side-head.them { color: #8f1c1c; }
.k-side-head.me { color: #0f6b57; }
.k-side-who { font-family: var(--serif); font-size: .96rem; }
.k-own-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.15rem; padding: .07rem .3rem; border-radius: 2px;
  font-size: .68rem; font-weight: 700; letter-spacing: .02em; flex: 0 0 auto;
}
.k-own-chip.them { background: #b32424; color: #fff; }
.k-own-chip.me { background: #14866d; color: #fff; }
/* 场上单位：把徽标叠在卡面左上角（不改卡面内部结构） */
.k-unit-slot { position: relative; }
.k-unit-slot > .k-own-chip { position: absolute; left: 0; top: 0; z-index: 4; }
/* 各条线按归属上色（除了位置，还有颜色与文字两道保险） */
.k-line.own-them { border-color: #e8cccc; background: #fdf6f5; }
.k-line.own-me { border-color: #c8e2da; background: #f4fbf9; }
.k-line.deployable { box-shadow: inset 0 0 0 2px #3366cc; background: #eef3fb; }
.k-drop-tip { font-size: .72rem; color: #3366cc; font-weight: 400; }
/* 打不了的目标：可见、但明确"不可点"（鼠标手势 + 去色），点它会给出中文原因 */
.k-unit-slot[data-k-act="target-no"] { cursor: not-allowed; }
.k-unit-slot[data-k-act="target-no"] .k-card { filter: grayscale(.25) brightness(.98); opacity: .85; }
/* 指令牌选目标：绿色十字准星 —— 跟"出击"的红色准星区分开（打人是红、帮人是绿） */
.k-unit-slot.order-target { cursor: crosshair; }
.k-unit-slot.order-target .k-card { box-shadow: 0 0 0 2px #1f8a5f; }
.k-unit-slot.order-target::after {
  content: '点它'; position: absolute; right: 2px; bottom: 2px; z-index: 5;
  font-size: .68rem; color: #fff; background: #1f8a5f; border-radius: 3px; padding: 0 .25rem;
}

/* 回合横幅：轮到你 / 等对手 / 本局结束 —— 三种状态颜色与文案都不同 */
.k-turnbar {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding: .55rem .75rem; border: 1px solid #c8ccd1; border-radius: 3px; background: #fff;
  font-size: .9rem;
}
.k-turnbar .k-tip { font-size: .78rem; }
.k-turnbar.mine { border-color: #14866d; background: #e9f8ef; color: #0f6b57; }
.k-turnbar.wait { border-color: #c8ccd1; background: #f4f6f8; color: #54595d; }
.k-turnbar.over { border-color: #b32424; background: #fdecec; color: #8f1c1c; }
.k-turnbar-dot { width: .62rem; height: .62rem; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.k-turnbar.mine .k-turnbar-dot { animation: k-turn 1.4s ease-in-out infinite; }

/* ---------------------------------------------------------------- 大厅（2026-10-14 重排）
   用户原话「太乱了」。原来是一条到底的竖排：门面（长规则 + 三个同权重按钮）→ 我的卡牌 →
   段位 → 「开始一局」四小条 → 可选卡牌 → 卡包强度，主次不分、越往下越长。
   现在按「先做下一件事」排成有层级的几节：
     页头（标题 + 段位小徽章 + 规则）→ 我的房间（一键回牌桌）→ 主列（快速匹配 / 公开房间）
     → 侧列（我的卡牌 / 我的段位 / 玩法与卡组入口）→ 卡包强度（整宽）
   手机上全部单列、不横向滚动；≥900px 两栏（1.55fr / 1fr）。间距只用 .5 / .65 / .8rem，
   卡片圆角 12–14px；主按钮=深红实心、次按钮=白底描边、幽灵=无框 —— 层级一眼分得开。
   配色只用页面已有的：深红 #b01（--link）、蓝 #3366cc（--c-blue）、绿 #14866d（--ok），
   没有引入新色板。 */
.k-lobby {
  --k-r: 14px;              /* 大卡片圆角 */
  --k-r-sm: 12px;           /* 卡中卡 / 房间卡圆角 */
  --k-gap: .8rem;
  --k-accent: #b01;         /* 站点既有深红，不是新配色 */
  --k-accent-dk: #7d0009;
  --k-line: #e2e4e8;
  --k-line-soft: #eceef1;
  --k-fill: #fafbfc;
}
/* 页头：一行标题 + 段位/战绩小徽章 + 规则入口 */
.k-lobby-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: .5rem .8rem; flex-wrap: wrap; margin: 0 0 .1rem;
}
.k-lobby-title { min-width: 0; }
.k-lobby .k-title { margin: 0; font-size: 1.35rem; line-height: 1.25; }
.k-tagline { margin: .15rem 0 0; color: var(--text-3); font-size: .78rem; line-height: 1.6; }
.k-lobby-head-ops { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.k-help-btn { min-height: 40px; }
/* 段位小徽章：数据没到就整块收掉（:empty），不占位也不显示"加载中" */
.k-top-tier {
  display: inline-flex; align-items: center; gap: .45rem; flex-wrap: wrap; max-width: 100%;
  border: 1px solid #eed9d9; background: #fdf7f7; border-radius: 999px;
  padding: .3rem .7rem .3rem .6rem; font-size: .76rem; line-height: 1.5; color: var(--text-2);
}
.k-top-tier:empty { display: none; }
.k-top-tier .k-tt-name { font-family: var(--serif); font-size: .88rem; font-weight: 700; color: #8f1c1c; }
.k-top-tier .k-tt-num { font-family: var(--mono); font-weight: 700; color: var(--text); }
.k-top-tier .k-tt-sep { width: 1px; height: .95em; background: #e2cfcf; flex: 0 0 auto; }
.k-top-tier .k-tt-rec { color: var(--text-3); }
/* 未登录 / 旧房被解散这类提示条：紧跟页头，不抢版面 */
.k-lobby > .g-note { margin: .55rem 0 0; border-radius: var(--k-r-sm); }

/* 卡片节：统一留白与圆角 */
.k-lobby .k-card-sec {
  margin: 0; min-width: 0; padding: .9rem .95rem 1rem;
  border: 1px solid var(--k-line); border-radius: var(--k-r); background: #fff;
  box-shadow: 0 1px 2px rgba(20, 22, 26, .03);
}
.k-lobby .k-card-sec h2 { font-family: var(--serif); font-size: 1rem; margin: 0; }
.k-sec-head { display: flex; align-items: center; gap: .45rem .55rem; flex-wrap: wrap; margin: 0 0 .6rem; }
.k-sec-head h2 { margin: 0; }
.k-sec-sub { color: var(--text-3); font-size: .74rem; line-height: 1.6; min-width: 0; }
.k-sec-tag {
  font-size: .68rem; line-height: 1.9; color: #8f1c1c; background: #fdf1f1;
  border: 1px solid #f0d5d5; border-radius: 999px; padding: 0 .5rem; flex: 0 0 auto;
}
.k-sec-link { margin-left: auto; min-height: 40px; padding: .2rem .55rem; font-size: .78rem; }

/* 我的房间：整宽，排在最上面 */
.k-lobby .k-myrooms-sec { margin: 0 0 var(--k-gap); }

/* 两栏：手机单列；≥900px 主列 1.55 : 侧列 1 */
.k-lobby-grid { display: grid; grid-template-columns: 1fr; gap: var(--k-gap); align-items: start; }
.k-lobby-col { display: flex; flex-direction: column; gap: var(--k-gap); min-width: 0; }
@media (min-width: 900px) {
  .k-lobby-grid { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
}

/* 快速匹配：当前卡牌一行 + 一个主按钮 + 一个次按钮 */
.k-quick-deck {
  display: flex; align-items: center; gap: .35rem .55rem; flex-wrap: wrap; min-width: 0;
  border: 1px solid var(--k-line-soft); background: #f7f9fd; border-radius: var(--k-r-sm);
  padding: .5rem .6rem;
}
.k-quick-deck-label { color: var(--text-3); font-size: .74rem; flex: 0 0 auto; }
.k-quick-deck .k-deck-name { font-size: .95rem; }
.k-quick-btns { display: flex; flex-direction: column; gap: .5rem; margin: .65rem 0 .45rem; }
.k-quick-btns .g-btn { width: 100%; min-height: 52px; font-size: .98rem; }
@media (min-width: 560px) {
  .k-quick-btns { flex-direction: row; }
  .k-quick-btns .g-btn { flex: 1 1 0; min-width: 0; }
}
.k-lobby .k-cta { box-shadow: 0 3px 12px rgba(179, 36, 36, .2); }
.k-lobby .k-cta:hover { box-shadow: 0 5px 16px rgba(179, 36, 36, .28); }

/* 匹配等待面板（openMatch 插进 #kMatchSpot；空着时不占位） */
.k-match-spot { margin-top: .55rem; }
.k-match-spot:empty { display: none; }
.k-lobby .k-match { margin: 0; border-radius: var(--k-r-sm); }

/* 公开房间：卡片网格（手机上单列，宽屏自动 2–3 列） */
.k-roomgrid { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; grid-template-columns: 1fr; }
@media (min-width: 620px) {
  .k-roomgrid { grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); }
}
.k-roomcard {
  display: flex; flex-direction: column; gap: .45rem; min-width: 0;
  border: 1px solid var(--k-line); border-radius: var(--k-r-sm); background: var(--k-fill);
  padding: .6rem .7rem;
  transition: border-color var(--t-fast, .14s), box-shadow var(--t-fast, .14s);
}
.k-roomcard:hover { border-color: #d3d7db; box-shadow: 0 2px 10px rgba(20, 22, 26, .06); }
.k-roomcard.is-playing { background: #fbfdff; border-color: #d5e2f5; }
.k-roomcard.is-mine { background: #fdf8f8; border-color: #eed9d9; }
.k-roomcard-top { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.k-roomcard-top .k-rcode { font-size: 1rem; letter-spacing: .08em; }
.k-roomcard-meta { display: flex; flex-direction: column; gap: .1rem; min-width: 0; font-size: .78rem; line-height: 1.6; }
.k-rcode { font-family: var(--mono); font-weight: 700; letter-spacing: .06em; }
.k-rplayers { color: #0f6b57; font-weight: 700; }
.k-rwho { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.k-roomcard-ops { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: auto; }
.k-roomcard-ops .g-btn { flex: 1 1 auto; min-height: 44px; min-width: 0; }

/* 空态（公开房 / 我的房间） */
.k-empty {
  border: 1px dashed #d8d3c8; border-radius: var(--k-r-sm); background: #fcfbf8;
  padding: .8rem .85rem; font-size: .8rem; line-height: 1.8; color: var(--text-2);
}
.k-empty.warn { border-color: #e6c3c3; background: #fdf7f7; color: #8f1c1c; }

/* 输房号：一行放完；窄屏输入框可收缩，绝不横向溢出 */
.k-code-row { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-top: .6rem; }
.k-code-label { flex: 0 0 auto; color: var(--text-3); font-size: .76rem; }
.k-code-input { flex: 1 1 6rem; min-width: 0; min-height: 44px; }
.k-code-row .g-btn { min-height: 44px; flex: 0 0 auto; }

/* 我的卡牌：卡片里再放一张卡（不重复描边） */
.k-lobby .k-deckcard {
  border: 1px solid var(--k-line-soft); border-radius: var(--k-r-sm); background: var(--k-fill);
  padding: .65rem .7rem; display: flex; flex-direction: column; gap: .45rem; min-width: 0;
}
.k-deckcard-bad { border-color: #e6c3c3; background: #fdf7f7; }
.k-deckcard-top { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.k-deckcard-name { font-family: var(--serif); font-size: 1.08rem; font-weight: 700; }
.k-deckcard-meta { color: var(--text-3); font-size: .8rem; }
.k-lobby .k-deckcard .g-btn { flex: 1 1 auto; min-width: 0; min-height: 44px; }
.k-deck-name { font-family: var(--serif); font-size: 1.02rem; }
.k-deck-meta { color: var(--text-3); font-size: .82rem; margin-left: .4rem; }

/* 玩法与卡组入口：一行 chip */
.k-chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.k-lobby a.g-btn { text-decoration: none; }
.k-lobby .k-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
  min-height: 40px; padding: .3rem .8rem; border-radius: 999px; font-size: .8rem;
  background: #fff; color: var(--text); white-space: nowrap;
}
.k-lobby .k-chip:hover { background: var(--bg-subtle, #f8f9fa); border-color: #c8ccd1; }
.k-lobby .k-chip:active { transform: translateY(1px); }

/* 按钮层级与反馈：主=深红实心、次=白底描边、幽灵=无框；按下有 1px 位移。
   chip 自己已经是胶囊形（999px），这里用 :not(.k-chip) 别把它的圆角盖回去。 */
.k-lobby .g-btn:not(.k-chip) {
  border-radius: 10px;
  transition: background-color var(--t-fast, .14s) ease, border-color var(--t-fast, .14s) ease,
    box-shadow var(--t-fast, .14s) ease, transform .08s ease;
}
.k-lobby .g-btn:not([disabled]):active { transform: translateY(1px); }
.k-lobby .g-btn:focus-visible { outline: 2px solid #3366cc; outline-offset: 2px; }
.k-lobby .g-btn.primary { background: var(--k-accent); border-color: #8f0009; color: #fff; }
.k-lobby .g-btn.primary:hover { background: var(--k-accent-dk); border-color: var(--k-accent-dk); }
.k-lobby .g-btn.ghost { color: var(--k-accent); }
.k-lobby .g-btn.ghost:hover { background: #fdf1f1; }
.k-lobby .g-tag { border-radius: 999px; padding: .05rem .5rem; line-height: 1.7; }

/* 卡包强度：整宽那一块 */
.k-lobby .k-packs-sec { margin-top: var(--k-gap); }
.k-lobby .k-packs-sec .k-rail { padding-bottom: .2rem; }

/* 弹窗外壳（三个弹窗共用；里面那套横向卡轨见下面那一节） */
.k-modal {
  position: fixed; inset: 0; z-index: 60; background: rgba(20, 22, 26, .45);
  display: flex; align-items: flex-start; justify-content: center; padding: 4vh 1rem 2rem; overflow: auto;
}
.k-modal-box {
  background: #fff; border-radius: 5px; border: 1px solid #cfd3d8; width: 100%; max-width: 640px;
  padding: .9rem 1rem 1rem; box-shadow: 0 12px 40px rgba(0, 0, 0, .28);
}
.k-modal-head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; border-bottom: 1px solid #eceef1; padding-bottom: .5rem; }
.k-modal-head b { font-family: var(--serif); font-size: 1.06rem; }
/* 「选择使用卡牌 / 可选卡牌 / 卡表」三个弹窗（2026-10-06 用户要求重做）
   --------------------------------------------------------------------------
   原来三档内置 + 我的 + 所有人可用的卡包**全铺在大厅里**，越往下越长；点「看看有什么牌」
   还会就地展开一大片卡表。现在：
     · 大厅只留入口按钮，卡都搬进弹窗（页面上不再有长列表，弹窗是 fixed，不撑高页面）；
     · 弹窗里是**横向卡轨**：卡并排、可左右滑、scroll-snap 一格一格停；
     · ✕ / 点背景 / Esc 都能关，打开时焦点落进窗口里（键盘用户不被关在外面）。
   `.k-modal-box` 用 margin:auto：内容矮时上下左右都居中，高过屏幕时自动退回
   "背景可滚动"，不会把顶端裁掉。 */
.k-modal-box { margin: auto; }
.k-modal-box.k-modal-wide { max-width: min(1200px, 96vw); }
/* 关着的「可选卡牌」弹窗留在 DOM 里（卡包同步要往里写），但不占位、不可见 */
.k-modal[data-k-deckbrowse]:not(.on) { display: none; }
/* 卡轨里的 hidden 要真的不见（.k-pack / .k-deck-row 自带 display:flex，会盖掉 UA 的 [hidden]） */
.k-modal [hidden] { display: none !important; }
.k-rail {
  display: flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch;
  gap: .5rem; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch; padding: .15rem .15rem .6rem;
}
.k-rail > * { scroll-snap-align: start; flex: 0 0 auto; }
/* 弹窗骨架：标题栏的 ✕ / 搜索条 / 页脚（都是 ≥44px 的点按目标） */
.k-modal-head .k-x { min-width: 44px; min-height: 44px; padding: 0 .5rem; font-size: 1rem; line-height: 1; }
.k-rail-bar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin: .6rem 0 0; }
.k-rail-q { flex: 1 1 220px; min-width: 0; min-height: 44px; }
.k-rail-n { flex: 0 0 auto; }
.k-modal-foot {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  border-top: 1px solid #eceef1; padding-top: .55rem; margin-top: .35rem;
}
.k-modal-foot .g-btn { min-height: 44px; }
.k-rail-empty { color: var(--tx3, #72777d); }
/* 已选中（还没确认）：绿色描边 + 一枚「✓ 已选中」。
   卡上的「用它 / 选为我的卡牌」按钮仍然立刻生效 —— 两条路并存，不改变原数据流。 */
.k-deck-row.sel, .k-pack.sel { outline: 2px solid #14866d; outline-offset: 2px; }
.k-deck-row.sel::before, .k-pack.sel::before {
  content: '✓ 已选中'; font-size: .72rem; color: #0f6b57; background: #e9f8ef;
  border-radius: 3px; padding: 0 .3rem; align-self: flex-start;
}
/* 弹窗里的卡：固定宽度、并排站好（手机上一屏一张半，滑着看；宽屏能同时看到好几张） */
.k-modal .k-packs {
  display: flex; flex-direction: row; flex-wrap: nowrap; gap: .5rem;
  overflow-x: auto; overflow-y: hidden; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
}
.k-modal .k-packs > .k-pack { flex: 0 0 auto; width: 17rem; max-width: 82vw; scroll-snap-align: start; }
/* 卡轨上的卡比大厅网格窄（272px）：标题里的阵营/张数/作者放不下时**换行**，
   不要把那行挤成一条竖排文字（原来在 240px 网格里也一样，只是没这么窄） */
.k-modal .k-pack h3 { flex-wrap: wrap; row-gap: .15rem; }
/* 弹窗里的按钮一律 ≥44px（手机点得准；宽屏也别做成小字按钮） */
.k-modal .k-pack .g-btn { min-height: 44px; }
/* 卡表弹窗：所有牌一条横向卡轨（原来是一大片换行网格） */
.k-modal .k-pack-preview {
  display: flex; flex-direction: row; flex-wrap: nowrap; gap: .4rem;
  overflow-x: auto; overflow-y: hidden; scroll-snap-type: x proximity;
  padding: .25rem .1rem .6rem; margin-top: .55rem;
}
.k-modal .k-pack-preview > .k-mini { flex: 0 0 auto; scroll-snap-align: center; }
/* 卡组卡：横排里的一张竖卡（原来是一行一条的竖向长列表） */
.k-deck-list {
  list-style: none; margin: .6rem 0 .35rem; padding: .15rem .15rem .6rem;
  display: flex; flex-direction: row; flex-wrap: nowrap; gap: .5rem;
  overflow-x: auto; overflow-y: hidden; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
}
.k-deck-row {
  display: flex; flex-direction: column; align-items: flex-start; gap: .3rem;
  border: 1px solid #e7e9ec; border-radius: 4px; padding: .55rem .6rem; background: #fff;
  width: 15rem; max-width: 80vw;
}
.k-deck-row .g-btn { width: 100%; min-height: 44px; }
.k-deck-row.on { border-color: #2a54a8; background: #f4f8ff; }
.k-deck-row.bad { opacity: .72; background: #fbf7f7; }
.k-deck-badge { font-size: .72rem; background: #eef1f5; color: #54595d; border-radius: 3px; padding: 0 .3rem; }
.k-deck-row.on .k-deck-badge { background: #dbe7fb; color: #2a54a8; }
.k-deck-name { font-weight: 600; }
.k-deck-n { color: var(--text-3); font-size: .8rem; margin-left: auto; }
.k-deck-cur { color: #2a54a8; font-size: .82rem; }
/* 被选中的卡包卡 / 来源标签（我的 / 公开 / 特邀共享 / 超管共享） */
.k-pack-on { box-shadow: inset 0 0 0 2px #2a54a8; }
.k-pack-tag { font-size: .72rem; color: #2a54a8; background: #eaf0fb; border-radius: 3px; padding: 0 .28rem; margin-left: .3rem; }

/* ---------------------------------------------------------------- 卡包编辑器（2026-10-01 重做）
   一行 = 左边字段 / 右边实时卡面预览；上面是模板克隆与批量改数值两条工具带 */
.k-editor-bar {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  border: 1px solid #e7e9ec; border-radius: 4px; background: #fafbfc; padding: .45rem .55rem; margin: .5rem 0;
}
.k-editor-bar select { padding: .3rem .4rem; border: 1px solid #c8ccd1; border-radius: 3px; background: #fff; max-width: 100%; }
.k-bulk .g-btn { min-height: 34px; padding: .25rem .5rem; font-size: .84rem; }
/* ---------------------------------------------------------------- 实时保存（2026-10-30）
   卡包编辑页停手约 0.9 秒自动存一次；状态条三态（保存中… / 已保存（时间）/ 保存失败 · 重试）
   + 本机草稿横幅（检测到未保存的草稿 → 恢复 / 丢弃）。
   手机上状态条与横幅按钮都要 ≥44px（跟这一页其它控件一个口径），并且一律 flex-wrap —— 390px 不横溢。 */
.k-save-wrap { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; min-width: 0; max-width: 100%; }
.k-save-state {
  font: inherit; font-size: .76rem; line-height: 1.25; padding: .3rem .5rem; min-height: 32px;
  border: 1px solid #d7dbe0; border-radius: 3px; background: #fff; color: var(--tx2, #54595d);
  max-width: 100%; box-sizing: border-box; overflow-wrap: anywhere; text-align: left;
}
.k-save-state[data-state="saving"] { color: #2a54a8; border-color: #b9cbe8; background: #f4f8ff; }
.k-save-state[data-state="saved"] { color: #0f6b57; border-color: #b9dcd2; background: #f0f8f5; }
.k-save-state[data-state="failed"] { color: #b32424; border-color: #e6b4b4; background: #fdecec; cursor: pointer; }
.k-save-state[data-state="blocked"] { color: #925408; border-color: #e8d3a8; background: #fff8e6; cursor: pointer; }
.k-save-err { flex: 1 1 100%; min-width: 0; font-size: .74rem; line-height: 1.5; color: #b32424; overflow-wrap: anywhere; }
.k-save-err.warn { color: #925408; }
.k-draft-banner {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  border: 1px solid #e8d3a8; border-left: 4px solid #d9a400; background: #fff8e6;
  padding: .5rem .6rem; margin: .5rem 0; font-size: .82rem; line-height: 1.7;
}
.k-draft-banner .k-draft-text { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; }
.k-draft-banner .k-draft-ops { display: flex; gap: .4rem; flex-wrap: wrap; }
.k-draft-banner .g-btn { min-height: 36px; }
@media (max-width: 760px) {
  .k-save-state { min-height: 44px; padding: .4rem .6rem; font-size: .8rem; }
  .k-draft-banner .g-btn { min-height: 44px; flex: 1 1 auto; }
}
.k-row-form { display: grid; grid-template-columns: minmax(0, 1fr) 190px; gap: .7rem; align-items: start; }
.k-row-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: .45rem; }
.k-row-side { display: flex; flex-direction: column; gap: .4rem; }
.k-card-preview { display: flex; justify-content: center; }
.k-card-preview .k-card { max-width: 168px; }
.k-row-ops { display: flex; flex-wrap: wrap; gap: .3rem; }
.k-row-ops .g-btn { min-height: 32px; padding: .25rem .45rem; font-size: .8rem; }
.k-op-row { display: flex; gap: .35rem; align-items: center; flex-wrap: wrap; margin: .2rem 0; }
.k-op-num { display: inline-flex; align-items: center; gap: .25rem; font-size: .8rem; color: var(--tx2, #54595d); }
.k-op-num input { width: 62px; }
/* ---------------------------------------------------------------- 强自定义编辑器（2026-10-05）
   连击 / 主动技能 / 被动触发三块。手机上是竖排（.k-adv-box 在窄屏里单列），
   效果行本来就 flex-wrap，所以窄屏不会横向溢出。 */
.k-adv-note {
  border-left: 4px solid #2a54a8; background: #f4f7fd; padding: .5rem .6rem;
  font-size: .82rem; line-height: 1.85; color: var(--tx2, #54595d); margin: .5rem 0;
}
.k-adv-box { grid-column: 1 / -1; display: flex; flex-direction: column; gap: .5rem; margin-top: .2rem; }
.k-adv-sec { border: 1px dashed #d8d3c8; border-radius: 4px; padding: .45rem .55rem; background: #fcfbf8; }
.k-adv-head {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  font-size: .78rem; font-weight: 700; color: var(--tx2, #54595d); margin-bottom: .3rem;
}
.k-adv-head .g-btn { min-height: 30px; padding: .2rem .45rem; font-size: .78rem; margin-left: auto; }
.k-abil-row, .k-trig-row {
  display: flex; flex-wrap: wrap; gap: .35rem; align-items: flex-end;
  border-top: 1px dashed #ececec; padding-top: .35rem; margin-top: .3rem;
}
.k-abil-row:first-of-type, .k-trig-row:first-of-type { border-top: 0; }
.k-adv-name input { width: 150px; }
.k-adv-cost input { width: 64px; }
.k-adv-when select { max-width: 190px; }
.k-op-wrap { display: block; flex: 1 1 100%; grid-column: 1 / -1; font-size: .74rem; color: var(--text-2); }
.k-op-wrap select { max-width: 100%; }
.k-op-list { display: block; }
.k-op-none { color: var(--tx3, #72777d); }
/* 条件（cond）里的子效果列表（2026-10-10）：缩进 + 左边一条竖线，一眼看出"这些效果是条件的" */
.k-op-sub {
  display: block; margin: .25rem 0 .25rem .6rem; padding: .3rem .4rem .3rem .5rem;
  border-left: 3px solid #c9d4e8; background: #f7f9fd; border-radius: 0 4px 4px 0;
}
.k-op-sub > .k-op-list > .k-op-row { margin: .15rem 0; }
.k-op-num select { max-width: 170px; }
.k-op-num input[type="text"] { width: 110px; }
/* 手机（≤760px）：技能/触发的每个字段各占一行，输入框铺满 —— 窄屏上并排会挤成"点不准" */
@media (max-width: 760px) {
  .k-abil-row, .k-trig-row { flex-direction: column; align-items: stretch; }
  .k-adv-name input, .k-adv-cost input, .k-adv-when select { width: 100%; max-width: 100%; }
  .k-adv-head .g-btn { margin-left: 0; }
  .k-op-row select, .k-op-row .k-op-num input { max-width: 100%; }
}
/* 卡面上的强自定义标记（连击2 / 技能1 / 被动1）—— 一眼看出这张牌"有东西"。
   2026-10-06 第二轮：**第二优先**、只占一行（flex-wrap: nowrap），
   一行放不下时 chip 在自己的框里省略成「…」（可收缩 + text-overflow），
   绝不换行去挤名字（名字是第一优先）或抢简介的行数。
   最多 3 个 chip（服务端 abilities/triggers 上限各 3、attacks 1–3）。 */
.k-badges {
  display: flex; flex-wrap: nowrap; gap: 3px; padding: 0 1px;
  flex: 0 0 auto; overflow: hidden; max-width: 100%;
}
.k-badge {
  font-size: .64rem; line-height: 1.35; padding: 0 4px; border-radius: 2px;
  background: rgba(32, 33, 34, .72); color: #fff; white-space: nowrap;
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.k-badge-combo { background: rgba(179, 36, 36, .86); }
.k-badge-skill { background: rgba(42, 84, 168, .86); }
.k-badge-trig { background: rgba(15, 107, 87, .86); }
/* 技能惩罚的卡面徽标（2026-10-17）：「代价 5」—— 与连击/技能/被动同一行，颜色偏琥珀色 */
.k-badge-pen { background: rgba(146, 84, 8, .88); }
/* 技能惩罚编辑器（可折叠的一块）：四个数字 + 一个开关，窄屏单列 */
.k-pen-sec > summary { cursor: pointer; list-style: none; margin-bottom: .25rem; }
.k-pen-sec > summary::-webkit-details-marker { display: none; }
.k-pen-sec > summary::before { content: '▸ '; color: #925408; }
.k-pen-sec[open] > summary::before { content: '▾ '; }
.k-pen-grid { display: flex; flex-wrap: wrap; gap: .35rem .7rem; align-items: flex-end; padding-top: .2rem; }
.k-pen-field {
  display: inline-flex; align-items: center; gap: .25rem;
  font-size: .78rem; color: var(--tx2, #54595d);
}
.k-pen-field input[type="number"] { width: 66px; }
.k-pen-note { font-size: .74rem; line-height: 1.6; color: var(--tx2, #54595d); margin-top: .3rem; }
.k-pen-note.warn { color: #b32424; }
@media (max-width: 760px) {
  .k-pen-field { flex: 1 1 100%; }
  .k-pen-field input[type="number"] { width: 100%; }
}
.k-skill-btn { min-height: 34px; }
@media (max-width: 760px) {
  .k-row-form { grid-template-columns: 1fr; }
  .k-row-side { flex-direction: row; align-items: center; justify-content: space-between; }
  .k-card-preview .k-card { max-width: 132px; }
}
.k-help {
  margin-top: .7rem; border-top: 1px dashed #d8d3c8; padding-top: .6rem;
  font-size: .84rem; line-height: 1.95; color: var(--tx2, #54595d); white-space: pre-wrap;
}
.k-pack-n { margin-left: auto; font-size: .74rem; color: var(--tx3, #72777d); font-weight: 400; }
/* 别人的公开卡包：作者标签（跟张数挤在一行，别把标题撑破） */
.k-pack-by { font-size: .72rem; color: var(--tx3, #72777d); font-weight: 400; margin-left: .35rem; }
/* 张数不够开局的包：整张卡降一点饱和，按钮是 disabled（别给必然失败的按钮） */
.k-pack-bad { opacity: .72; }
.k-pack .k-tip.warn { color: #b32424; }
.k-pack-preview { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: .55rem; }
.k-card.k-mini-card { --k-cw: 94px; --k-ch: 124px; }
.k-card.k-mini-card .k-art { height: 26px; }
.k-card.k-mini-card .k-text { display: none; }
.k-mytier .k-tier-badge { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.k-statgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: .4rem; margin: .55rem 0 .5rem; }
.k-stat { border: 1px solid #e6e8ea; background: #fafbfc; border-radius: 10px; text-align: center; padding: .3rem 0; }
.k-stat b { display: block; font-family: var(--serif); font-size: 1.06rem; line-height: 1.2; }
.k-stat span { font-size: .72rem; color: var(--tx3, #72777d); }

/* 手机：大厅单列；牌桌两侧标题与徽标仍然要看得清 */
@media (max-width: 760px) {
  .k-lobby-grid { grid-template-columns: 1fr; }
  .k-side { padding: .4rem .45rem .5rem; border-left-width: 5px; }
  .k-side-who { font-size: .9rem; }
  .k-turnbar { font-size: .86rem; }
  .k-statgrid { gap: .3rem; }
  /* 手机上大厅里所有按钮都要够大（含卡包卡与匹配/房号那两行） */
  .k-lobby .g-btn, .k-pack .g-btn { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .k-turnbar.mine .k-turnbar-dot { animation: none !important; }
}
html.k-reduce .k-turnbar.mine .k-turnbar-dot { animation: none !important; }

/* ==========================================================================
   牌桌观感（2026-10-01 第二轮：**撤掉深色配色**，保留沉浸式布局与全屏）
   --------------------------------------------------------------------------
   用户反馈：深底那套"色搭"不要了。现在改成跟站点一致的**浅色纸面战场**：
   浅灰绿底 + 纸面卡 + 红/绿阵营淡色块；布局（全幅、粘底操作条、手牌台、全屏）保留。
   注意：两侧阵营仍**必须**有互不相同的 background-color（套件按计算样式比对敌我）。
   动效另见文件末尾的"动效升级"一节。
   ========================================================================== */
.k-room .k-wrap { max-width: none; }
.k-room .k-table {
  position: relative;
  padding: .5rem .55rem .65rem;
  gap: .4rem;
  background-color: #eef1ee;
  background-image:
    radial-gradient(120% 70% at 50% -10%, #ffffff 0%, #f3f5f2 45%, #e9ede8 100%),
    repeating-linear-gradient(0deg, rgba(0, 0, 0, .022) 0 1px, transparent 1px 7px);
  color: var(--text-1, #202122);
  border: 1px solid #d8dcd6;
  box-shadow: inset 0 0 40px rgba(96, 108, 96, .08);
  overflow: hidden;
}
.k-room .k-side {
  border: 1px solid #dfe3de;
  border-left: 4px solid #b32424;
  background-color: #fdf4f4;
  background-image: linear-gradient(180deg, rgba(179, 36, 36, .07), rgba(179, 36, 36, .02));
  box-shadow: 0 2px 10px rgba(32, 33, 34, .07);
  border-radius: 4px;
}
.k-room .k-side.me {
  border-left-color: #14866d;
  background-color: #f2faf8;
  background-image: linear-gradient(0deg, rgba(20, 134, 109, .08), rgba(20, 134, 109, .02));
}
.k-room .k-line {
  border: 1px solid #e3e6e0;
  background-color: rgba(255, 255, 255, .62);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8);
  border-radius: 3px;
}
.k-room .k-line.front {
  border-color: #ddcfab;
  background-color: #fbf7ea;
  background-image: linear-gradient(180deg, rgba(226, 200, 140, .16), rgba(226, 200, 140, .04));
}
.k-room .k-line.own-them { border-color: #eccfcf; background-color: #fdf4f4; background-image: linear-gradient(180deg, rgba(179, 36, 36, .07), rgba(179, 36, 36, .02)); }
.k-room .k-line.own-me { border-color: #cbe6dd; background-color: #f2faf8; background-image: linear-gradient(0deg, rgba(20, 134, 109, .07), rgba(20, 134, 109, .02)); }
.k-room .k-line > .k-line-label { color: #6c7371; }
.k-room .k-zone.on { background: #e6f6f0; box-shadow: inset 0 0 0 2px #14866d; }
.k-room .k-zone.off { background: #f6f3f3; box-shadow: inset 0 0 0 2px #c8ccd1; }
.k-room .k-zone.on .k-line-label { color: #0f6b57; }
.k-room .k-drop-tip { color: #14866d; }
/* HQ = 指挥所（浅色卡片风，但比普通块更"立"） */
.k-room .k-hq {
  border: 1px solid #cfd4cd;
  background-color: #fff;
  background-image: linear-gradient(180deg, #fff, #f7f9f6);
  box-shadow: 0 2px 8px rgba(32, 33, 34, .08);
  border-radius: 4px;
}
.k-room .k-hq .k-hp { background: #e7e3dc; height: 13px; border-radius: 2px; }
.k-room .k-hq .k-hp b { text-shadow: none; }
.k-room .k-kredits .k-gem { box-shadow: 0 0 0 2px rgba(51, 102, 204, .14); }
/* 回合横幅：悬浮胶囊（浅色） */
.k-room .k-turnbar {
  border: 1px solid #d8dcd6; border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  box-shadow: 0 3px 12px rgba(32, 33, 34, .1);
  padding: .45rem .8rem;
}
.k-room .k-turnbar.mine { border-color: #9fd8c6; box-shadow: 0 3px 14px rgba(20, 134, 109, .18); }
.k-room .k-turnbar.mine b { color: #0f6b57; }
.k-room .k-turnbar.wait b { color: #8a6a00; }
/* 手牌台 + 粘底操作条 */
.k-room .k-hand-wrap {
  background: linear-gradient(0deg, rgba(255, 255, 255, .95), rgba(255, 255, 255, .35));
  border-top: 1px solid #e1e4df;
  padding: .5rem .4rem .35rem; border-radius: 4px;
}
.k-room .k-hand-wrap.dim { opacity: .6; filter: saturate(.7); }
.k-room .k-bars {
  position: sticky; bottom: 0; z-index: 12;
  background: rgba(255, 255, 255, .94);
  border-top: 1px solid #dfe3de;
  box-shadow: 0 -2px 12px rgba(32, 33, 34, .07);
  padding: .5rem .55rem; border-radius: 4px 4px 0 0;
}
.k-room .k-log, .k-room .k-chat { background: #fbfcfa; border: 1px solid #e3e6e0; border-radius: 4px; }
.k-room .k-fs-btn { margin-left: auto; }
@media (min-width: 900px) {
  /* 宽屏：手牌轻微扇形摊开（悬停/选中抬起）—— 手机上保持横向滚动，不缩不可点 */
  .k-room .k-hand-wrap .k-card-slot:nth-child(odd) .k-card { transform: rotate(-1.1deg); }
  .k-room .k-hand-wrap .k-card-slot:nth-child(even) .k-card { transform: rotate(1.1deg); }
  .k-room .k-hand-wrap .k-card-slot .k-card:hover { transform: translateY(-12px) scale(1.03); }
  .k-room .k-hand-wrap .k-card-slot .k-card.sel { transform: translateY(-14px) scale(1.04); }
}
/* 兜底沉浸（不支持 Fullscreen API 时）：把站点外壳收起来，只留牌桌 */
html.k-immersive .st-bar, html.k-immersive .st-foot { display: none !important; }
html.k-immersive .st-main { padding: 0 !important; max-width: none !important; }

/* ---------------------------------------------------------------- 动效升级（2026-10-01）
   ① 拖动出牌：跟随指针的幽灵卡 + 落点高亮
   ② 击杀卡牌：被击杀的那张卡从原位飞出、碎裂淡出，并冒一个「击杀」标
   ③ 掉血/治疗：飘数字（HQ 更大一号） */
.k-fxlayer { position: fixed; inset: 0; z-index: 55; pointer-events: none; }
.k-drag-ghost {
  position: fixed; z-index: 56; pointer-events: none;
  transform: translate(-50%, -50%) rotate(-3deg) scale(1.06);
  filter: drop-shadow(0 10px 18px rgba(0, 0, 0, .32));
  opacity: .96;
}
.k-drag-ghost .k-card { box-shadow: 0 12px 22px rgba(0, 0, 0, .3); }
html.k-dragging { cursor: grabbing; }
html.k-dragging .k-card { cursor: grabbing; touch-action: none; }
.k-drop-on { outline: 2px dashed #14866d; outline-offset: 2px; }
.k-drop-on .k-card { box-shadow: 0 0 0 2px #35d3a6; }
@keyframes k-kill-fly {
  0% { opacity: 1; transform: none; filter: none; }
  35% { opacity: 1; transform: translateY(-10px) rotate(-4deg) scale(1.05); filter: brightness(1.25); }
  100% { opacity: 0; transform: translateY(-46px) rotate(9deg) scale(.82); filter: grayscale(1) brightness(1.4); }
}
.k-kill {
  position: fixed; z-index: 57; pointer-events: none;
  animation: k-kill-fly .85s cubic-bezier(.3, .1, .3, 1) forwards;
}
.k-kill .k-kill-mark {
  position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%);
  font-family: var(--serif); font-size: .9rem; font-weight: 700; letter-spacing: .08em;
  color: #b32424; background: rgba(255, 255, 255, .92); border: 1px solid #e6c3c3;
  border-radius: 3px; padding: 0 .3rem;
}
@keyframes k-dmg-float {
  0% { opacity: 0; transform: translate(-50%, 6px) scale(.9); }
  25% { opacity: 1; transform: translate(-50%, -4px) scale(1.06); }
  100% { opacity: 0; transform: translate(-50%, -30px) scale(1); }
}
.k-dmg {
  position: fixed; z-index: 58; pointer-events: none;
  font-family: var(--mono, monospace); font-weight: 700; font-size: .95rem;
  color: #fff; background: #b32424; border-radius: 3px; padding: .05rem .3rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .28);
  animation: k-dmg-float 1.05s ease-out forwards;
}
.k-dmg.heal { background: #14866d; }
.k-dmg.hq { font-size: 1.15rem; padding: .1rem .4rem; }
html.k-reduce .k-kill, html.k-reduce .k-dmg { animation: none !important; opacity: 0 !important; }
html.k-reduce .k-drag-ghost { transition: none !important; }
/* ---------------------------------------------------------------------------
   等候室（2026-10-12）
   用户报「卡兹建房永远卡在正在读取这一局…」：以前整个等人阶段只画一行"读取中"，
   没有座位表也没有人数，朋友进来了也看不出来。现在没开局时画这一屏（真等候室），
   "正在读取这一局…"只留给**真的已开局、局面还没回来**的那一小段时间。
   --------------------------------------------------------------------------- */
.k-wait-top { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin: .2rem 0 .55rem; }
.k-wait-count { font-weight: 700; }
.k-seats { display: flex; flex-direction: column; gap: .35rem; margin: .3rem 0 .2rem; }
.k-seat {
  display: flex; gap: .5rem; align-items: center; min-height: 44px;
  padding: .45rem .65rem; border-radius: 10px;
  background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .10);
}
.k-seat.empty { color: var(--text-3, #93a0ad); border-style: dashed; background: rgba(255, 255, 255, .02); }
.k-seatno { font-weight: 700; min-width: 3.8rem; }
.k-seatname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.k-wait-note { font-size: .8rem; line-height: 1.55; color: var(--text-3, #93a0ad); margin-top: .55rem; }

/* ---------------------------------------------------------------------------
   超管调试面板（小悬浮窗，2026-10-07）
   用户要求：「给超管做一个卡兹开发者调试面板（小悬浮窗），超管游玩卡兹可以点开面板
   调血量调卡牌防御血量等功能（效果仅单局有效）」。

   层级 850：**低于**结算弹窗（settle.js 的 9999）与开局转盘（spin.js 的 900），
   **高于**牌桌 HUD（st-bar 30 / 操作条 20 / 特效层 55–58）与详情浮层（60）——
   不盖结算、不跟转盘抢层级、也不压操作条。
   位置：左下角、操作条**上方**（bottom 64/116），这样既压不到 sticky 的操作条，
   也不会跟底部居中的提示条（.w-toast，bottom 约 19px、z 300）抢地方。
   触摸目标：按钮与输入框都 ≥44px（手机上不给人"戳不中"的控件）。
   窄屏：面板宽度吃满可视宽度并 flex 换行，**绝不横向溢出**（390px 宽实测不溢出）。
   --------------------------------------------------------------------------- */
.k-dev-btn {
  position: fixed; left: 8px; bottom: 64px; z-index: 850;
  min-height: 44px; min-width: 44px; padding: 0 .75rem;
  border: 1px solid #191919; border-radius: 22px; background: #ffd45e; color: #191919;
  font: inherit; font-size: .84rem; font-weight: 700; line-height: 1; cursor: pointer;
  box-shadow: 0 4px 12px -4px rgba(0, 0, 0, .5);
}
.k-dev-btn:hover { background: #ffe08a; }
.k-dev-panel {
  position: fixed; left: 8px; bottom: 116px; z-index: 850;
  width: 340px; max-width: calc(100vw - 16px);
  max-height: 62vh; display: flex; flex-direction: column;
  background: #fffdf7; color: #202122; border: 1px solid #191919; border-radius: 8px;
  box-shadow: 0 12px 28px -12px rgba(0, 0, 0, .55);
  font-size: .8rem; line-height: 1.7; box-sizing: border-box;
}
.k-dev-head {
  display: flex; align-items: center; gap: .3rem; flex: 0 0 auto;
  min-height: 44px; padding: .15rem .3rem .15rem .5rem;
  background: #fff3cf; border-bottom: 1px solid #e6d9a8; border-radius: 8px 8px 0 0;
  cursor: move; touch-action: none; user-select: none;
}
.k-dev-head b { font-family: var(--serif); font-size: .86rem; }
.k-dev-grow { flex: 1 1 auto; }
.k-dev-badge {
  font-size: .66rem; padding: 0 .26rem; border: 1px solid currentColor; border-radius: 3px;
  color: #8a6d00; white-space: nowrap;
}
.k-dev-badge.on { color: #14866d; }
.k-dev-icon {
  width: 44px; height: 44px; flex: 0 0 auto; padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: #54595d; font: inherit; font-size: 1rem; cursor: pointer;
}
.k-dev-icon:hover { background: rgba(0, 0, 0, .07); }
.k-dev-body { overflow-y: auto; overflow-x: hidden; padding: .45rem .5rem .55rem; -webkit-overflow-scrolling: touch; }
.k-dev-panel.k-dev-min .k-dev-body { display: none; }
.k-dev-tip {
  font-size: .72rem; line-height: 1.65; color: #464a4e; background: #f3f5f2;
  border-left: 3px solid #b9b9b9; border-radius: 2px; padding: .26rem .4rem; margin: 0 0 .3rem;
}
.k-dev-tip.warn { border-left-color: #d9a400; background: #fff8e6; }
.k-dev-note {
  font-size: .72rem; line-height: 1.65; color: #0f6b57; background: #e9f7f2;
  border-radius: 2px; padding: .26rem .4rem; margin: 0 0 .3rem; word-break: break-word;
}
.k-dev-note.bad { color: #b32424; background: #fdecec; }
.k-dev-seat {
  border: 1px solid #e3e6e0; background: #fff; border-radius: 6px;
  padding: .38rem .42rem; margin: 0 0 .45rem;
}
.k-dev-seathead { font-size: .8rem; margin-bottom: .28rem; }
.k-dev-stat { display: flex; align-items: center; gap: .28rem; flex-wrap: wrap; margin-bottom: .28rem; }
.k-dev-lbl { font-size: .72rem; color: #54595d; }
.k-dev-hint { font-size: .66rem; color: #8a8f94; }
.k-dev-f { display: inline-flex; align-items: center; gap: .16rem; font-size: .7rem; color: #54595d; }
.k-dev-f input {
  width: 3.6rem; min-height: 44px; box-sizing: border-box; padding: 0 .25rem;
  border: 1px solid #c8ccd1; border-radius: 4px; background: #fff; color: #202122;
  font: inherit; font-size: .82rem; text-align: center;
}
.k-dev-f input[disabled] { background: #f1f2f3; color: #6b6f73; }
.k-dev-zone { font-size: .7rem; font-weight: 700; color: #8a6d00; margin: .3rem 0 .1rem; }
.k-dev-row { border-top: 1px dashed #eceff1; padding: .3rem 0 .1rem; }
.k-dev-name {
  font-size: .76rem; font-weight: 700; margin-bottom: .16rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.k-dev-warn { margin-left: .25rem; font-weight: 400; font-size: .66rem; color: #8a6d00; border: 1px solid #d9c37a; border-radius: 3px; padding: 0 .2rem; }
.k-dev-fs { display: flex; flex-wrap: wrap; gap: .25rem; }
.k-dev-acts { display: flex; flex-wrap: wrap; gap: .25rem; margin: .25rem 0 .15rem; }
.k-dev-apply, .k-dev-preset {
  min-height: 44px; padding: 0 .5rem; border-radius: 4px; font: inherit;
  font-size: .76rem; cursor: pointer; white-space: nowrap;
}
.k-dev-apply { border: 1px solid #3366cc; background: #eaf3ff; color: #1b3f7a; font-weight: 700; }
.k-dev-preset { border: 1px solid #d9a400; background: #fff8e6; color: #7a5c00; }
.k-dev-apply:hover { background: #dbe9ff; }
.k-dev-preset:hover { background: #fff1cc; }
.k-dev-empty { font-size: .72rem; color: #8a8f94; padding: 0 0 .25rem; }
.k-dev-foot { font-size: .66rem; color: #8a8f94; line-height: 1.6; border-top: 1px solid #eceff1; padding-top: .3rem; }
/* 「授权」块（2026-10-08 调试权限下放）：**只有超管**看得到 —— 昵称/ID + 回合数 + 「授权」，
   下面是当前生效的授权列表（昵称 · 剩 N 回合 · 收回）。它就在同一个浮窗里（用户要求
   "就在调试面板里"），靠 flex-wrap 换行，390px 宽的手机上也不横向溢出；控件一律 ≥44px。 */
.k-dev-grant {
  border: 1px solid #e3e6e0; background: #fff; border-radius: 6px;
  padding: .38rem .42rem; margin: 0 0 .45rem;
}
.k-dev-grantform { display: flex; flex-wrap: wrap; gap: .25rem; align-items: center; }
.k-dev-grant-in {
  min-height: 44px; min-width: 0; box-sizing: border-box; padding: 0 .35rem;
  border: 1px solid #c8ccd1; border-radius: 4px; background: #fff; color: #202122;
  font: inherit; font-size: .78rem;
}
.k-dev-grant-in[data-k-dev-grant-input="user"] { flex: 1 1 7.5rem; }
.k-dev-grant-in[data-k-dev-grant-input="turns"] { flex: 0 1 4rem; text-align: center; }
.k-dev-grant-go, .k-dev-grant-rev {
  min-height: 44px; padding: 0 .6rem; border-radius: 4px; font: inherit;
  font-size: .76rem; cursor: pointer; white-space: nowrap;
}
.k-dev-grant-go { border: 1px solid #14866d; background: #e9f7f2; color: #0f6b57; font-weight: 700; }
.k-dev-grant-go:hover { background: #d8f0e8; }
.k-dev-grant-go[disabled] { opacity: .6; cursor: default; }
.k-dev-grant-rev { border: 1px solid #b32424; background: #fdecec; color: #8c1c1c; }
.k-dev-grant-rev:hover { background: #f9dcdc; }
.k-dev-grant-tip { font-size: .68rem; line-height: 1.6; color: #54595d; margin: .25rem 0 .1rem; }
.k-dev-grant-list { margin-top: .2rem; }
.k-dev-grant-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem;
  border-top: 1px dashed #eceff1; padding: .25rem 0;
}
.k-dev-grant-nick {
  font-size: .76rem; font-weight: 700; max-width: 8.5rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.k-dev-grant-left { font-size: .72rem; color: #0f6b57; font-weight: 700; }
@media (max-width: 430px) {
  /* 手机上：面板吃满可视宽度（减去两边各 6px），输入框略窄一点，绝不横向溢出 */
  .k-dev-btn { left: 6px; bottom: 58px; }
  .k-dev-panel { left: 6px; right: 6px; width: auto; max-width: none; bottom: 110px; max-height: 56vh; }
  .k-dev-f input { width: 3.3rem; }
  /* 「授权」块：昵称列再窄一点、输入框换成整行，保证 390px 宽不横向溢出 */
  .k-dev-grant-nick { max-width: 6rem; }
  .k-dev-grant-in[data-k-dev-grant-input="user"] { flex: 1 1 6rem; }
}

/* ==================== 手机端大厅修复（2026-10-10） ====================
   用户报「手机卡兹大厅适配有问题」。实测（390×844 真机视口 + 无头 Chrome 量）：
     · .k-lobby-grid 的内容宽被撑到 4043px、.k-wrap 变成横向滚动容器 —— 手机上得左右拖着看；
     · 单张 .k-pack 宽 435px（比视口 390 还宽）。
   原因：
     ① grid 子项默认 min-width:auto —— 格子里的横向卡轨（flex + nowrap）会把整列顶开；
     ② 卡轨里的 .k-pack 没有宽度约束（只有弹窗那条 `.k-modal .k-packs > .k-pack` 有），
        于是被简介文字撑成 435px。
   下面是覆盖规则（同特异性后定义者胜，不动上面任何一条既有规则）。
   2026-10-14 大厅重排后：两栏模板移到上面「大厅」那一节（≥900px 才分栏），
   这里只留**宽度约束** —— 卡片节与卡轨都不得把 grid 子项撑开。 */
.k-lobby-grid > * { min-width: 0; }
.k-lobby .k-card-sec { min-width: 0; }
.k-lobby-col { min-width: 0; }
.k-rail { min-width: 0; max-width: 100%; }
/* 卡轨里的卡包卡：与弹窗同口径（17rem / 最多 82vw）。窄屏再放宽到 84vw，一屏放得下一张半 */
.k-rail > .k-pack { width: 17rem; max-width: 82vw; }
@media (max-width: 480px) {
  .k-rail > .k-pack { width: 84vw; max-width: 84vw; }
  .k-pack h3 { font-size: 1rem; }
}
