:root {
  /* 大屏不做 fluid 字阶：1vw 在 1920px 上是 19px，会把标题撑爆 */
  --fs-xs: .78rem;  --fs-sm: .86rem;  --fs-md: .95rem;
  --fs-lg: 1.05rem; --fs-xl: 1.22rem; --fs-2xl: 1.5rem; --fs-num: 1.2rem;
  --pad-page: 1.3rem;
}
/* 势力色不再在大屏单独定义——此前这里另有一套取值（--ta #9C5A86 vs 手机端 #7a4ffb 等
   6 项全不一致、且漏了圣冠），同一局里两个屏幕并排看必然露馅。
   现统一由 common.css 的冷银主题令牌提供唯一取值。 */
* { box-sizing: border-box; }
body { font-family: system-ui, "Microsoft YaHei", sans-serif; background: #f5f7fa; color: #26282c; margin: 0; }

header { display: flex; align-items: center; gap: 1.5rem; padding: .8rem 1.2rem; background: #1f2a3a; color: #fff; }
header h1 { margin: 0; font-size: 1.3rem; }
#room, #phase { font-size: .95rem; }
#room-code { font-weight: 700; letter-spacing: .25em; font-size: 1.15rem; }

.panel { background: #fff; border: 1px solid #e2e5ea; border-radius: 10px; padding: .9rem 1rem; margin: .8rem 1.2rem; }
h2 { margin: .1rem 0 .6rem; font-size: 1.1rem; }
h3 { margin: .3rem 0 .6rem; font-size: 1rem; }

/* 开局设置 */
.row { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: .8rem; }
.row label { display: flex; flex-direction: column; font-size: .9rem; color: #4a505a; gap: .3rem; }
.row select, .row input { padding: .4rem .5rem; font-size: 1rem; border: 1px solid #c4c9d2; border-radius: 6px; }
#btn-create { font-size: 1.05rem; padding: .6rem 1.4rem; }

/* 控制条（精简） */
.controlbar { background: #fff; border: 1px solid #e2e5ea; border-radius: 10px; padding: .7rem 1rem; margin: .8rem 1.2rem; }
.banner { background: #fdeaea; color: #b23a3a; border: 1px solid #f0b4b4; border-radius: 6px; padding: .6rem .8rem; margin-bottom: .6rem; }
#controls { display: flex; gap: .8rem; align-items: center; flex-wrap: wrap; }
#controls button { padding: .5rem 1rem; font-size: .95rem; border: none; border-radius: 8px; background: #3a6fb2; color: #fff; font-weight: 700; cursor: pointer; }
#controls button:disabled { background: #c2cad6; cursor: not-allowed; }
.hint { color: #8a6d3b; font-size: .85rem; }

/* 战局舞台：左地图 + 右战报（M5 并排） */
#stage { display: flex; gap: 1rem; align-items: flex-start; margin: .4rem 1.2rem 1.5rem; }
#map-panel { flex: 1 1 auto; min-width: 0; }
#battle-panel { flex: 0 0 360px; max-height: 82vh; overflow: auto; }

/* 大屏地图 */
#map-wrap { position: relative; width: 100%; background: #0e2c4e; border-radius: 8px; overflow: visible; line-height: 0; }
#map-img { width: 100%; display: block; border-radius: 8px; }
#map-markers { position: absolute; inset: 0; pointer-events: none; }
.mk { position: absolute; transform: translate(-50%, -50%); text-align: center; }
.mk .dot { width: 15px; height: 15px; border-radius: 50%; border: 2px solid #14202c; box-sizing: border-box; margin: 0 auto; }
.mk.cap .dot { box-shadow: 0 0 0 3px #FFD34D; }
.mk .cnt { font-size: 11px; font-weight: 700; color: #fff; text-shadow: 0 0 3px #000; line-height: 1; margin-top: 1px; }

/* 席位环绕（M5） */
#seats { position: absolute; inset: 0; pointer-events: none; }
.seat {
  position: absolute; transform: translate(-50%, -50%);
  width: 160px; background: rgba(255, 255, 255, .97); border: 1px solid #d0d5de;
  border-left: 5px solid #9aa3b2; border-radius: 10px; padding: .45rem .55rem;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .18); pointer-events: auto; font-size: .82rem;
}
.seat.faction-CR { border-left-color: var(--cr); }
.seat.faction-TA { border-left-color: var(--ta); }
.seat.faction-EL { border-left-color: var(--el); }
.seat.faction-HO { border-left-color: #9aa0aa; }
.seat.faction-XU { border-left-color: var(--xu); }
.seat.faction-AZ { border-left-color: var(--az); }
.seat-head { display: flex; align-items: center; gap: .4rem; }
.seat .crest { width: 30px; height: 30px; object-fit: contain; border-radius: 5px; background: #f0f2f6; flex: 0 0 auto; }
.seat .crest-none { display: flex; align-items: center; justify-content: center; color: #9aa3b2; font-weight: 700; }
.seat-name { font-weight: 700; font-size: .9rem; line-height: 1.1; }
.seat .offline { background: #b23a3a; color: #fff; font-size: .68rem; padding: .05rem .35rem; border-radius: 4px; }
/* ★ 2026-09-20（批次 C：人机）：席位标记组（人机 / AI 接管中 / 离线）——
   统一由 .seat-tags 接管右对齐（原来 .offline 自带 margin-left:auto，若再加一个
   同级标记会让两个 auto margin 把标记撕到两头）。 */
.seat-tags { margin-left: auto; display: inline-flex; align-items: center; gap: .25rem; }
.seat-ai-tag { background: #3a6fb2; color: #fff; font-size: .68rem; padding: .05rem .35rem; border-radius: 4px; white-space: nowrap; }
.seat-ai-tag.bot { background: #5a6b8c; }
.seat-fac { font-size: .8rem; color: #4a505a; margin: .2rem 0 .1rem; }
.seat-res { font-size: .78rem; color: #3a404a; margin-bottom: .35rem; }
.seat-btns { display: grid; grid-template-columns: 1fr 1fr; gap: .3rem; }
.seat-btns button { padding: .3rem 0; font-size: .8rem; border: none; border-radius: 6px; background: #eef1f6; color: #2f3a4a; cursor: pointer; font-weight: 600; }
.seat-btns button:hover { background: #dde4ee; }

.legend { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: .6rem; font-size: .85rem; }
.legend span { display: inline-flex; align-items: center; gap: .3rem; }
.legend i { width: 12px; height: 12px; border-radius: 50%; display: inline-block; border: 1px solid #14202c; }

/* 右上角重连二维码 */
#qr-corner {
  position: fixed; top: 1rem; right: 1rem; z-index: 100;
  display: flex; align-items: center; gap: .6rem; background: rgba(255, 255, 255, .96);
  border: 1px solid #d0d5de; border-radius: 10px; padding: .5rem .7rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .12); max-width: 260px;
}
#qr-corner[hidden] { display: none !important; }
#qr-corner img { width: 80px; height: 80px; border-radius: 6px; }
#qr-corner .qr-info { font-size: .8rem; line-height: 1.45; }
#qr-corner .qr-title { font-weight: 700; color: #26282c; }
#qr-corner .qr-room { color: #4a505a; }
#qr-corner #qr-link { display: block; color: #3a6fb2; word-break: break-all; max-width: 150px; font-size: .72rem; }

/* （2C-A 已移除战斗战报：原 #battle-list / .battle-card 浅色基础样式删除） */

/* 城防标识（A2）：地图标记右上角小盾 */
.mk .fort-badge { font-size: 10px; font-weight: 700; color: #8a6d2f;
  text-shadow: 0 0 3px #fff; line-height: 1; margin-top: 1px; }

/* 回合结算摘要（A1） */
#settlement-card { margin-bottom: .9rem; }
#settlement-card:empty { display: none; }
#settlement-card .st-head { font-size: 1rem; font-weight: 700; color: #26282c;
  border-bottom: 1px dashed #dfe3ea; padding-bottom: .3rem; margin-bottom: .5rem; }
#settlement-card .st-over { margin-left: .6rem; font-size: .85rem; color: #8a6d2f; }
#settlement-card .st-sec { font-size: .84rem; font-weight: 700; color: #6b7280;
  margin: .5rem 0 .25rem; }
#settlement-card .st-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .35rem .8rem; }
#settlement-card .st-cell { display: flex; align-items: center; gap: .35rem;
  flex-wrap: wrap; font-size: .86rem; color: #4a505a; }
#settlement-card i { width: 10px; height: 10px; border-radius: 50%;
  display: inline-block; flex: none; }
#settlement-card .st-row { display: flex; align-items: center; gap: .45rem;
  flex-wrap: wrap; font-size: .86rem; color: #4a505a; padding: .1rem 0; }
#settlement-card .st-fac { font-weight: 700; }
#settlement-card .st-num { color: #26282c; }
#settlement-card .st-sub { color: #8a909c; font-size: .8rem; }
#settlement-card .st-cap { font-weight: 700; color: #2e8b2e; }
#settlement-card .st-rank { font-weight: 700; color: #8a909c; }
#settlement-card .st-crown { font-size: .95rem; }
#settlement-card .st-win-row { background: #fdf6e3; border-radius: 6px;
  padding: .2rem .4rem; }
#settlement-card .st-row.st-win-row .st-fac { color: #b23a3a; }

/* 事件横幅（M4/M5+ 含缩略图） */
.banner.event { background: linear-gradient(90deg, #fff4d6, #ffe2b0); color: #7a4b00; border-color: #f0c878; font-weight: 700; display: flex; align-items: center; gap: .7rem; }
#event-banner-img { height: 42px; width: auto; border-radius: 5px; border: 1px solid #dcb070; display: block; }
#event-banner-img[hidden] { display: none; }

/* ===== B3：交战地域（地区卡翻面）地图标识 ===== */
.mk.hot .dot { box-shadow: 0 0 0 3px #b23a3a, 0 0 10px rgba(178,58,58,.7); }
.mk .hot-badge { font-size: 11px; font-weight: 700; color: #b23a3a;
  text-shadow: 0 0 3px #fff; line-height: 1; margin-top: 1px; }

/* ===== B1/B2：④b 执行顺序揭示 / ④c 移动执行明细 ===== */
#exec-order-card, #move-report-card { margin-bottom: .9rem; }
#exec-order-card:empty, #move-report-card:empty { display: none; }
#exec-order-card .st-head, #move-report-card .st-head {
  font-size: 1rem; font-weight: 700; color: #26282c;
  border-bottom: 1px dashed #dfe3ea; padding-bottom: .3rem; margin-bottom: .5rem; }
#exec-order-card .st-sub, #move-report-card .st-sub {
  margin-left: .6rem; font-size: .82rem; font-weight: 400; color: #8a909c; }
#exec-order-card .eo-row, #move-report-card .mr-row {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  font-size: .88rem; color: #4a505a; padding: .12rem 0; }
#exec-order-card .eo-idx { width: 1.3rem; text-align: center; font-weight: 700; color: #8a909c; }
#exec-order-card i, #move-report-card i { width: 10px; height: 10px; border-radius: 50%;
  display: inline-block; flex: none; }
#exec-order-card .eo-fac, #move-report-card .eo-fac { font-weight: 700; color: #26282c; }
#exec-order-card .eo-d6 { color: #7a4ffb; font-weight: 700; }
#move-report-card .mr-st { font-weight: 700; font-size: .78rem; padding: .05rem .4rem;
  border-radius: 6px; color: #fff; }
#move-report-card .mr-st.moved { background: #2e8b2e; }
#move-report-card .mr-st.stopped { background: #b23a3a; }
#move-report-card .mr-st.void { background: #9aa3b2; }
#move-report-card .mr-at { color: #b23a3a; font-size: .84rem; }
#move-report-card .mr-why { color: #8a909c; font-size: .8rem; }
/* ★ EV2：移动执行明细的兵团编号「N 号」格（不补零；无该字段时不渲染此格） */
#move-report-card .mr-no { color: #8a909c; font-size: .78rem; white-space: nowrap; }

/* 事件阶段抽牌/投骰动画层 */
#event-overlay {
  position: fixed; inset: 0; z-index: 150;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: rgba(15, 25, 38, .78); backdrop-filter: blur(2px);
  transition: opacity .5s ease;
}
#event-overlay[hidden] { display: none !important; }
#event-overlay.fade-out { opacity: 0; pointer-events: none; }

/* 3D 翻牌容器 */
.event-card-flip {
  width: 260px; height: 370px; position: relative;
  transform-style: preserve-3d; perspective: 1000px;
  animation: cardEnter .45s ease-out forwards, cardFlip .6s ease-in-out .55s forwards;
}
.event-card-face {
  position: absolute; inset: 0; border-radius: 14px;
  backface-visibility: hidden;
  box-shadow: 0 16px 50px rgba(0, 0, 0, .45);
  overflow: hidden; border: 6px solid #fff;
}
.event-card-back {
  background: url("/static/event/back.webp") center/cover no-repeat, #2b3a52;
  transform: rotateY(0deg);
}
.event-card-front {
  transform: rotateY(180deg);
  background: #111;
}
.event-card-front img { width: 100%; height: 100%; object-fit: cover; display: block; }

@keyframes cardEnter {
  0% { transform: scale(.2) translateY(-120px); opacity: 0; }
  100% { transform: scale(1) translateY(0); opacity: 1; }
}
@keyframes cardFlip {
  0% { transform: rotateY(0deg); }
  100% { transform: rotateY(180deg); }
}

#event-title {
  margin-top: 1.2rem; padding: .4rem 1rem; border-radius: 8px;
  background: rgba(255, 255, 255, .95); color: #5a3a00;
  font-size: 1.25rem; font-weight: 700; box-shadow: 0 4px 14px rgba(0,0,0,.25);
  opacity: 0; transform: translateY(8px);
  transition: opacity .4s ease, transform .4s ease;
}
#event-title.show { opacity: 1; transform: translateY(0); }

#event-result {
  margin-top: .8rem; padding: .5rem 1.1rem; border-radius: 8px;
  background: rgba(255, 255, 255, .92); color: #2c3a4a;
  font-size: 1.05rem; max-width: 620px; text-align: center; line-height: 1.45;
  opacity: 0; transform: translateY(8px);
  transition: opacity .4s ease, transform .4s ease;
}
#event-result.show { opacity: 1; transform: translateY(0); }

#event-dice-tray {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0; pointer-events: none;
}

@keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

/* 骰子 */
.event-die {
  position: absolute; width: 56px; height: 56px;
  background: #fff; border-radius: 12px; box-shadow: 0 5px 16px rgba(0,0,0,.35);
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
  padding: 7px; box-sizing: border-box;
  animation: diePop .25s ease-out backwards, dieRoll .8s ease-in-out 1.2s;
}
.event-die-center {
  position: relative; width: 120px; height: 120px;
  background: #fff; border-radius: 20px; box-shadow: 0 8px 30px rgba(0,0,0,.45);
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
  padding: 14px; box-sizing: border-box;
  animation: diePop .35s ease-out backwards, dieRoll 1s ease-in-out 1.2s;
}
.event-die .pip, .event-die-center .pip { background: #1f2a3a; border-radius: 50%; }

@keyframes diePop {
  0% { transform: scale(0); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes dieRoll {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-25deg) translateX(-8px); }
  50% { transform: rotate(20deg) translateX(6px); }
  75% { transform: rotate(-10deg); }
}

/* 席位交互弹窗（M5） */
#modal-root { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; }
#modal-root:empty { display: none; }
.modal-mask { position: absolute; inset: 0; background: rgba(0, 0, 0, .4); }
.modal { position: relative; width: min(520px, 92vw); max-height: 84vh; overflow: auto; background: #fff; border-radius: 12px; box-shadow: 0 10px 40px rgba(0, 0, 0, .3); }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: .7rem 1rem; border-bottom: 1px solid #e8ebf0; font-weight: 700; font-size: 1.05rem; position: sticky; top: 0; background: #fff; }
.modal-close { border: none; background: #eef1f6; border-radius: 6px; width: 30px; height: 30px; cursor: pointer; font-size: 1rem; color: #4a505a; }
.modal-body { padding: .8rem 1rem 1.1rem; }
.m-empty { color: #8a909c; font-size: .92rem; line-height: 1.5; }
.m-sub { font-weight: 700; color: #3a404a; margin: .8rem 0 .3rem; font-size: .9rem; }
.m-pol { display: flex; align-items: center; gap: .5rem; padding: .4rem .5rem; border-radius: 7px; background: #f7f9fc; margin-bottom: .35rem; }
.m-pol.done { background: #eef7ee; }
.m-pol-name { font-weight: 600; flex: 1; }
.m-tag { font-size: .72rem; background: #eef1f6; color: #4a505a; padding: .05rem .4rem; border-radius: 4px; }
.m-pol-state { font-size: .78rem; color: #2e8b2e; font-weight: 700; }
.m-node:not(.done) .m-pol-state { color: #e2574c; font-weight: 700; }
.m-unit { display: flex; justify-content: space-between; align-items: center; padding: .35rem .5rem; border-radius: 7px; background: #f7f9fc; margin-bottom: .3rem; }
.m-unit-name { font-weight: 600; }
.m-unit-cnt { font-weight: 700; color: #3a6fb2; }
.m-note { font-size: .78rem; color: #9aa3b2; margin-top: .5rem; }
/* ★ 2026-09-20（批次 C-2/C-3）：席位弹窗底部的「AI 接管 / 取消接管」开关 */
.m-takeover { margin-top: 1rem; padding-top: .8rem; border-top: 1px solid #e8ebf0; }
.ai-takeover-btn { border: 1px solid #b9c6d8; background: #eef3fa; color: #2f3a4a; border-radius: 7px; padding: .45rem .8rem; cursor: pointer; font-weight: 700; font-size: .9rem; }
.ai-takeover-btn:hover { border-color: #3a6fb2; color: #1d4e86; }
.ai-takeover-btn.on { background: #3a6fb2; color: #fff; border-color: #3a6fb2; }
.m-takeover .m-sub { font-weight: 400; }
.m-cards { display: flex; flex-wrap: wrap; gap: .4rem; }
.m-card { background: #eef1f6; border-radius: 6px; padding: .3rem .6rem; font-size: .88rem; }
.m-rel { padding: .35rem .5rem; border-radius: 7px; background: #f7f9fc; margin-bottom: .3rem; }
.m-hero { padding: .4rem .5rem; border-radius: 7px; background: #f7f9fc; margin-bottom: .35rem; font-weight: 600; }

@media (max-width: 920px) {
  #stage { flex-direction: column; }
  #battle-panel { flex: 1 1 auto; max-height: none; width: 100%; }
}

/* ================= 批次 C：整编播报 / 侦察流水 ================= */
#rg-sc-card:empty { display: none; }
#rg-sc-card .rgs-h { font-size: .92rem; font-weight: 700; color: #2d3446;
  margin: .5rem 0 .2rem; }
#rg-sc-card .rgs-sub { font-size: .76rem; font-weight: 400; color: #9aa3b2;
  margin-left: .5rem; }
#rg-sc-card .rgs-row { font-size: .86rem; color: #4a5568; padding: .14rem 0;
  border-bottom: 1px dashed #eef1f6; }

/* ═══════════════════════════════════════════════════════════════════════════
   大屏皮肤 · 冷银主题覆盖层
   ───────────────────────────────────────────────────────────────────────────
   追加式覆盖：上面既有规则一行没删，出问题删掉本区块即完全回到原状。
   视觉主张 = 「深色金属装帧 包裹 明亮地图」——地图是亮制图风，把它当珠宝框起来。

   ★ 硬约束：地图容器（#map-wrap / #map-markers / #seats）的 border 与 padding
     一律不能动。markers 与席位用 inset:0 + 百分比定位，加边框会让整层整体偏移。
     要框只能用 box-shadow / background。
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 底色：藏青 + 极淡斜纹，避免大片死黑 ── */
body {
  font-family: var(--ff-sans);
  background-color: var(--bg-0);
  background-image:
    radial-gradient(120% 70% at 50% -10%, rgba(110,168,220,.10), transparent 60%),
    repeating-linear-gradient(115deg, rgba(255,255,255,.014) 0 1px, transparent 1px 3px);
  background-attachment: fixed;
  color: var(--tx-1);
}

/* ── 页头：金属条 ── */
header {
  background: linear-gradient(180deg, #1c2739, var(--bg-1));
  border-bottom: 1px solid transparent;
  border-image: var(--mt-silver) 1;
  box-shadow: 0 2px 14px rgba(0,0,0,.55);
  padding: .75rem var(--pad-page);
}
header h1 {
  font-family: var(--ff-serif); font-weight: 600;
  letter-spacing: .16em; font-size: 1.42rem;
  background: var(--mt-silver);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
#room { font-size: var(--fs-md); color: var(--tx-2); }
#room-code {
  font-family: var(--ff-serif); font-weight: 600; color: var(--tx-1);
  letter-spacing: .3em; font-size: var(--fs-2xl);
}
#phase { display: inline-flex; align-items: center; gap: .15rem;
  font-size: var(--fs-md); color: var(--tx-2); }
#phase-name {
  font-family: var(--ff-serif); font-weight: 600;
  font-size: var(--fs-lg); letter-spacing: .07em;
  color: #cfe4fb; padding: .1rem .6rem; margin: 0 .25rem;
  border-radius: var(--r-xs);
  background: linear-gradient(180deg, rgba(110,168,220,.24), rgba(110,168,220,.06));
  border: 1px solid rgba(110,168,220,.45);
  box-shadow: 0 0 12px rgba(110,168,220,.18);
}
#round { font-family: var(--ff-serif); font-weight: 600; color: var(--tx-1); }

/* ── 面板：银渐变 1px 描边 + 内高光 + 四角 L 形装饰 ── */
.panel, .controlbar {
  position: relative;
  background: linear-gradient(var(--bg-1), var(--bg-1)) padding-box,
              var(--mt-silver) border-box;
  border: 1px solid transparent;
  border-radius: var(--r);
  box-shadow: var(--sh-1), var(--sh-inset);
  margin: .8rem var(--pad-page);
  padding: .9rem var(--pad-page);
}
/* 只有 map-panel 与 setup 加角饰：battle-panel 是 overflow:auto，绝对定位角饰会跟着滚 */
#setup::before, #setup::after, #map-panel::before, #map-panel::after {
  content: ""; position: absolute; width: 15px; height: 15px;
  pointer-events: none; opacity: .55;
  border: 1px solid var(--mt-silver-solid);
}
#setup::before, #map-panel::before { top: 5px; left: 5px; border-right: 0; border-bottom: 0; }
#setup::after,  #map-panel::after  { bottom: 5px; right: 5px; border-left: 0; border-top: 0; }

h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); color: var(--tx-2); }

/* ── 开局设置 ── */
.row { gap: 1.1rem; }
.row label { font-size: var(--fs-sm); color: var(--tx-2); letter-spacing: .04em; }
.row select, .row input { min-width: 9rem; }
#btn-create {
  margin-top: .4rem;
  background: var(--mt-gold) border-box;
  color: var(--tx-inv); font-weight: 700;
  padding: .6rem 1.8rem; font-size: var(--fs-lg);
  box-shadow: 0 3px 14px rgba(201,162,79,.28), var(--sh-inset);
}

/* ── 控制条 ── */
#controls { gap: .8rem; }
#controls button {
  background: var(--mt-gold) border-box;
  border: 1px solid transparent; border-radius: var(--r-sm);
  color: var(--tx-inv); font-family: var(--ff-serif); font-weight: 700;
  padding: .5rem 1.3rem; font-size: var(--fs-md);
  box-shadow: 0 3px 12px rgba(201,162,79,.25), var(--sh-inset);
  transition: filter .15s ease;
}
#controls button:not(:disabled):hover { filter: brightness(1.12); }
#controls button:disabled { background: var(--bg-3) border-box; color: var(--tx-4);
  box-shadow: none; }
.hint { color: var(--warn); font-size: var(--fs-sm); }
.banner {
  background: linear-gradient(180deg, rgba(226,87,76,.16), rgba(226,87,76,.06));
  border: 1px solid rgba(226,87,76,.5);
  color: #ffb9b2; border-radius: var(--r-sm); font-size: var(--fs-md);
}
.banner.event {
  background: linear-gradient(90deg, rgba(192,57,43,.22), rgba(18,26,38,.9));
  border-color: rgba(201,162,79,.55); color: #f0dcae;
  font-family: var(--ff-serif);
}
#event-banner-img { border: 1px solid rgba(201,162,79,.5); border-radius: var(--r-xs); }

/* ── 战局舞台 ── */
#stage { margin: .4rem var(--pad-page) 1.5rem; gap: 1rem; }
#map-panel { padding-bottom: .6rem; }
#map-wrap {
  background: radial-gradient(80% 70% at 50% 40%, #101a26, #070b11);
  border-radius: var(--r-sm);
  /* 只保留外框。★ 内暗角不能写在这里：box-shadow 的 inset 画在**子内容之下**，
     会被 #map-img 整块盖住，等于没写。改挂 #map-markers::before（见下）。 */
  box-shadow: 0 0 0 1px var(--mt-silver-solid),
              0 0 0 5px rgba(10,15,22,.9),
              0 12px 40px rgba(0,0,0,.6);
}
#map-img { border-radius: var(--r-sm); }
/* 内暗角挂在这一层：#map-markers 在 #seats 之下，压暗地图边缘但不会压暗席位卡 */
#map-markers::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: var(--r-sm);
  box-shadow: inset 0 0 70px rgba(0,0,0,.5);
}

.mk .dot { border: 2px solid rgba(6,10,16,.9); box-shadow: 0 0 6px rgba(0,0,0,.7); }
.mk .cnt { font-family: var(--ff-serif); font-weight: 600; font-size: 12px;
  color: #fff; text-shadow: 0 0 4px #000, 0 0 8px #000; }
.mk.cap .dot { box-shadow: 0 0 0 3px #ffd34d, 0 0 14px rgba(255,211,77,.6); }
.mk.hot .dot { box-shadow: 0 0 0 3px var(--gem-lt), 0 0 16px rgba(226,87,76,.75); }
.mk .fort-badge { color: #ffd98a; text-shadow: 0 0 4px #000, 0 0 6px #000; }
.mk .hot-badge  { color: #ff8f85; text-shadow: 0 0 4px #000, 0 0 6px #000; }

/* 图例 */
.legend { gap: .8rem; font-size: var(--fs-sm); color: var(--tx-2);
  border-top: 1px solid var(--bg-4); padding-top: .5rem; }
.legend i { border: 1px solid rgba(0,0,0,.7);
  box-shadow: 0 0 0 1px rgba(255,255,255,.16); }
.legend-note { color: var(--tx-3); }

/* ── 席位环绕卡 ── */
.seat {
  /* 宽度保持 160px 不动：席位坐标由 JS 按百分比给出（translate(-50%,-50%)），
     改宽度会改变各席位相对地图的占位范围，属于布局变量，不属美化范畴。 */
  width: 160px;
  /* ★ 修既有 bug：#map-wrap 设了 line-height:0（为去掉 <img> 的基线间隙），
     席位卡继承了它却没复位 —— 卡内每行文字行高都是 0，玩家名/势力/资源三行压成一坨。
     这是深色改版之前就存在的，一并修掉。 */
  line-height: var(--lh);
  background: linear-gradient(180deg, rgba(26,36,52,.96), rgba(14,20,30,.96));
  border: 1px solid rgba(170,182,198,.35);
  border-left: 4px solid var(--neutral);
  border-radius: var(--r);
  box-shadow: 0 6px 22px rgba(0,0,0,.6);
  color: var(--tx-1);
  padding: .5rem .6rem;
}
.seat.faction-HO { border-left-color: var(--ho); }
.seat .crest { background: rgba(255,255,255,.07);
  border: 1px solid rgba(170,182,198,.3); border-radius: var(--r-xs); width: 32px; height: 32px; }
.seat .crest-none { background: rgba(255,255,255,.05); color: var(--tx-3); }
.seat-name { font-family: var(--ff-serif); font-weight: 600; font-size: var(--fs-md);
  color: var(--tx-1); }
.seat .offline { background: var(--gem); }
/* ★ 2026-09-20（批次 C：人机）：深色主题下的席位标记配色 */
.seat-ai-tag { background: #3f6ea8; }
.seat-ai-tag.bot { background: #46567a; }
.seat-fac { color: var(--tx-2); font-size: var(--fs-xs); }
.seat-res { color: var(--tx-2); font-size: var(--fs-xs); }
.seat-res b { color: var(--tx-1); }
.seat-btns button {
  background: linear-gradient(180deg, var(--bg-3), var(--bg-2));
  border: 1px solid rgba(170,182,198,.3); color: var(--tx-1);
  font-family: var(--ff-sans); font-weight: 600;
}
.seat-btns button:hover { background: var(--bg-4); border-color: var(--accent); }

/* ── 右上角二维码 ── */
#qr-corner {
  background: linear-gradient(180deg, rgba(26,36,52,.96), rgba(14,20,30,.96));
  border: 1px solid rgba(170,182,198,.35);
  color: var(--tx-1); box-shadow: var(--sh-2);
}
#qr-corner img { border: 1px solid rgba(255,255,255,.85); background: #fff; }
#qr-corner .qr-title { color: var(--tx-1); }
#qr-corner .qr-room { color: var(--tx-2); }
#qr-corner #qr-link { color: var(--accent); }

/* ── 右侧战报栏 ── */
#battle-panel { padding-right: .7rem; }
/* （2C-A 已移除战斗战报：#battle-list / .battle-card / .battle-empty 的宿主元素不再存在，深色覆盖一并删除） */

/* 结算 / 执行顺序 / 移动明细 / 整编侦察 卡片：内嵌子块，统一用深底细描边 */
#settlement-card .st-head, #exec-order-card .st-head,
#move-report-card .st-head, #rg-sc-card .rgs-h {
  font-family: var(--ff-serif); font-weight: 600; color: var(--tx-1);
  border-bottom: 1px solid var(--bg-4);
}
#settlement-card .st-sub, #exec-order-card .st-sub, #move-report-card .st-sub,
#rg-sc-card .rgs-sub { color: var(--tx-3); }
#settlement-card .st-sec { color: var(--tx-2); }
#settlement-card .st-cell, #settlement-card .st-row,
#exec-order-card .eo-row, #move-report-card .mr-row, #rg-sc-card .rgs-row {
  color: var(--tx-2); border-bottom-color: var(--bg-4);
}
#settlement-card .st-num, #exec-order-card .eo-fac, #move-report-card .eo-fac {
  color: var(--tx-1); }
#settlement-card .st-sub, #move-report-card .mr-why { color: var(--tx-3); }
#settlement-card .st-cap { color: var(--ok); }
#settlement-card .st-rank { color: var(--tx-3); }
#settlement-card .st-over { color: var(--warn); }
#exec-order-card .eo-idx { color: var(--tx-3); }
#exec-order-card .eo-d6 { color: var(--magic); }
#settlement-card .st-win-row {
  background: linear-gradient(90deg, rgba(192,57,43,.20), transparent);
  border-left: 3px solid var(--gem); border-radius: var(--r-xs);
}
#settlement-card .st-row.st-win-row .st-fac { color: var(--gem-lt); }
#move-report-card .mr-at { color: var(--bad); }
#move-report-card .mr-st.moved { background: rgba(69,196,106,.9); color: #06170c; }
#move-report-card .mr-st.stopped { background: var(--gem); color: #fff; }
#move-report-card .mr-st.void { background: var(--bg-4); color: var(--tx-3); }

/* ── 事件抽牌动画层 ── */
#event-overlay { background: rgba(6,10,16,.9); backdrop-filter: blur(3px); }
.event-card-face {
  border: 3px solid transparent; border-radius: var(--r-lg);
  background: linear-gradient(#0a0f16, #0a0f16) padding-box,
              var(--mt-silver) border-box;
  box-shadow: 0 20px 60px rgba(0,0,0,.75), 0 0 46px rgba(110,168,220,.16);
}
.event-card-back {
  background: url("/static/event/back.webp") center/cover no-repeat padding-box,
              var(--mt-silver) border-box;
}
.event-card-front {
  background: linear-gradient(#0a0f16, #0a0f16) padding-box,
              var(--mt-silver) border-box;
}
#event-title {
  background: var(--mt-gold) border-box;
  color: var(--tx-inv); font-family: var(--ff-serif); font-weight: 700;
  border-radius: var(--r-sm); box-shadow: 0 6px 24px rgba(0,0,0,.6);
}
#event-result {
  background: linear-gradient(180deg, rgba(26,36,52,.96), rgba(14,20,30,.96));
  border: 1px solid rgba(170,182,198,.4);
  color: var(--tx-1); border-radius: var(--r);
  box-shadow: var(--sh-2);
}
/* 骰子保持白面：深色幕布上白色最醒目，这是正确的对比做法，别改成金属 */
.event-die, .event-die-center {
  background: linear-gradient(160deg, #ffffff, #d8e0ea);
  box-shadow: 0 6px 20px rgba(0,0,0,.6), inset 0 0 0 1px rgba(170,182,198,.7);
}
.event-die .pip, .event-die-center .pip { background: #121a26; }

/* ── 席位交互弹窗 ── */
.modal-mask { background: rgba(6,10,16,.72); backdrop-filter: blur(2px); }
.modal {
  background: linear-gradient(var(--bg-1), var(--bg-1)) padding-box,
              var(--mt-silver) border-box;
  border: 1px solid transparent; border-radius: var(--r-lg);
  box-shadow: var(--sh-2); color: var(--tx-1);
}
.modal-head {
  background: linear-gradient(180deg, #1c2739, var(--bg-1));
  border-bottom: 1px solid transparent; border-image: var(--mt-silver) 1;
  color: var(--tx-1); font-family: var(--ff-serif);
}
.modal-close { background: var(--bg-3); border: 1px solid var(--bg-4); color: var(--tx-2); }
.modal-close:hover { color: var(--tx-1); border-color: var(--accent); }
.m-empty, .m-note { color: var(--tx-3); }
.m-sub { color: var(--tx-2); }
/* ★ 2026-09-20（批次 C-2/C-3）：深色主题下的「AI 接管」开关 */
.m-takeover { border-top-color: var(--bg-4); }
.ai-takeover-btn { background: var(--bg-3); border-color: rgba(170,182,198,.3); color: var(--tx-1); font-family: var(--ff-sans); }
.ai-takeover-btn:hover { color: var(--tx-1); border-color: var(--accent); }
.ai-takeover-btn.on { background: var(--accent); color: #0b1219; border-color: var(--accent); }
.m-pol, .m-unit, .m-rel, .m-hero {
  background: rgba(32,44,60,.6); border: 1px solid var(--bg-4); }
.m-pol.done { background: rgba(69,196,106,.12); border-color: rgba(69,196,106,.35); }
.m-pol-name, .m-unit-name, .m-hero { color: var(--tx-1); }
.m-tag { background: var(--bg-4); color: var(--tx-2); }
.m-pol-state { color: var(--ok); }
.m-node:not(.done) .m-pol-state { color: var(--bad); }
.m-unit-cnt { color: var(--accent); }
.m-card { background: var(--bg-3); border: 1px solid var(--bg-4); color: var(--tx-2); }

/* ── ★ B-2（2026-09-19）：存档 / 读档面板（沿用 .modal 框架，补槽位列表样式）── */
.sv-modal { width: min(660px, 94vw); }
.sv-newbar { display: flex; gap: .5rem; margin-bottom: .5rem; }
.sv-input {
  flex: 1; padding: .45rem .6rem; border-radius: var(--r-sm, 6px);
  border: 1px solid var(--bg-4); background: var(--bg-2); color: var(--tx-1);
  font-size: .92rem;
}
.sv-input::placeholder { color: var(--tx-4); }
.sv-btn {
  padding: .4rem .7rem; border-radius: var(--r-sm, 6px); cursor: pointer;
  border: 1px solid var(--bg-4); background: var(--bg-3); color: var(--tx-2);
  font-weight: 700; font-size: .85rem;
}
.sv-btn:hover { border-color: var(--accent); color: var(--tx-1); }
.sv-btn:disabled { opacity: .4; cursor: not-allowed; }
.sv-cloudrow { opacity: .8; }
.sv-btn.primary {
  background: var(--mt-gold) border-box; border: 1px solid transparent; color: var(--tx-inv);
}
.sv-btn.danger { border-color: rgba(226, 87, 76, .5); color: var(--bad); }
.sv-status { min-height: 1.1rem; font-size: .82rem; color: var(--ok); margin: .1rem 0 .3rem; }
.sv-sec { font-size: .82rem; font-weight: 700; color: var(--tx-3); margin: .4rem 0 .35rem; }
.sv-list { display: flex; flex-direction: column; gap: .35rem; max-height: 46vh; overflow: auto; }
.sv-row {
  display: flex; align-items: center; gap: .5rem; padding: .45rem .55rem;
  border: 1px solid var(--bg-4); border-radius: var(--r-sm, 6px);
  background: rgba(32, 44, 60, .5);
}
.sv-info { flex: 1; min-width: 0; }
.sv-name { font-weight: 700; color: var(--tx-1); font-family: var(--ff-serif); }
.sv-meta { font-size: .78rem; color: var(--tx-3); margin-top: .1rem; }
.sv-acts { display: flex; gap: .3rem; flex: none; }
.sv-empty { color: var(--tx-3); font-size: .9rem; padding: .6rem 0; }
.sv-note { font-size: .76rem; color: var(--tx-3); margin-top: .6rem; line-height: 1.5; }
.sv-note code { color: var(--accent); }
/* ★ 2026-09-19：槽位来源徽章（本地 / 旧目录·只读） */
.sv-src {
  font-size: .66rem; font-weight: 700; padding: .02rem .32rem;
  border-radius: 4px; margin-left: .35rem; vertical-align: middle;
}
.sv-src.local { background: var(--bg-4); color: var(--tx-3); }
.sv-src.legacy { background: rgba(224, 169, 60, .18); color: var(--warn); }


/* ══════════════════════════════════════════════════════════════════════════
   M14+ 事件阶段：牌面必须真的翻出来 + 牌名/类别/结算结果可读
   ──────────────────────────────────────────────────────────────────────────
   ① 翻牌修复（真实渲染对照实验定位）：
      `.event-card-flip` 上并列了**两条都带 `forwards` 填充**的动画
      （cardEnter 管进场、cardFlip 管翻转）。实测容器的终态计算值确实是
      rotateY(180deg)，但合成层没有把终态画出来 —— 于是「前面板」（同为
      rotateY(180deg)，净转 360°）被判为背面剔除，屏幕上只剩牌背，
      玩家永远看不到牌面。去掉 cardEnter 的 `forwards` 即恢复正常：
      cardEnter 的终态本就是恒等变换（scale(1) translateY(0)），不填充也不会跳。
      对照结论：只留 cardFlip ✅ / cardEnter 去 forwards ✅ /
      两条款序颠倒 ❌ / cardEnter 改只动 opacity ❌。
   ② 横幅：牌名 + 类别 + 结算摘要；点击可重看牌面。
   ③ 翻牌层的结算结果：逐势力「生效了什么 / 为什么没生效」。
   ④ 战报分区：事件触发与结算过程留痕。
   ══════════════════════════════════════════════════════════════════════════ */
.event-card-flip {
  /* 唯一改动：去掉 cardEnter 的 forwards（见上方①），其余沿用原声明 */
  animation: cardEnter .45s ease-out, cardFlip .6s ease-in-out .55s forwards;
}

/* ── 事件横幅：牌面缩略 + 牌名/类别 + 一句话结算摘要 ── */
#event-banner {
  align-items: center; gap: var(--sp-3); cursor: pointer;
  background: linear-gradient(180deg, rgba(26,36,52,.96), rgba(14,20,30,.96));
  border: 1px solid rgba(170,182,198,.35); border-radius: var(--r);
  padding: var(--sp-2) var(--sp-3);
}
#event-banner:hover { border-color: var(--accent); }
#event-banner-img {
  height: 76px; width: auto; border-radius: var(--r-xs);
  background: var(--bg-1);
}
#event-banner .evb-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#event-banner-text {
  font-family: var(--ff-serif); font-size: var(--fs-lg); font-weight: 700;
  color: var(--tx-1); letter-spacing: var(--ls-title);
}
#event-banner-text .evb-cat {
  font-family: var(--ff-sans); font-size: var(--fs-xs); font-weight: 400;
  color: var(--tx-3); letter-spacing: 0; margin-left: .5rem;
}
#event-banner-sub {
  font-size: var(--fs-sm); color: var(--tx-2); line-height: var(--lh);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 62vw;
}

/* ── 翻牌层：标题（牌名 + 类别）与结算结果 ── */
#event-title .evt-cat {
  font-family: var(--ff-sans); font-size: var(--fs-sm); font-weight: 400;
  opacity: .75; margin-left: .5rem;
}
#event-result { max-width: min(760px, 88vw); }
#event-result .evr-head {
  font-family: var(--ff-serif); font-weight: 700; color: var(--accent);
  margin-bottom: .35rem;
}
#event-result .evr-row {
  display: flex; gap: .5rem; align-items: baseline;
  font-size: var(--fs-sm); padding: .16rem 0; text-align: left;
}
#event-result .evr-fac {
  min-width: 6.2em; color: var(--tx-1); font-weight: 700; flex: 0 0 auto;
}
#event-result .evr-fac .evr-roll { color: var(--tx-3); font-weight: 400; margin-left: .3rem; }
#event-result .evr-txt { color: var(--tx-2); }
#event-result .evr-row.ok .evr-txt { color: var(--ok); }
#event-result .evr-row.no .evr-txt { color: var(--tx-3); }
#event-result .evr-item {
  font-size: var(--fs-xs); color: var(--tx-3); padding-left: 6.7em;
}

/* ── 战报分区：事件留痕 ── */
#event-log-card { margin-bottom: var(--sp-3); }
#event-log-card .evl-h {
  font-family: var(--ff-serif); font-size: var(--fs-md); color: var(--tx-1);
  border-bottom: 1px solid var(--bg-4); padding-bottom: .25rem; margin-bottom: .4rem;
  display: flex; align-items: baseline; gap: .5rem;
}
#event-log-card .evl-h .evl-sub {
  font-family: var(--ff-sans); font-size: var(--fs-xs); color: var(--tx-3);
}
#event-log-card .evl-row {
  background: rgba(32,44,60,.5); border: 1px solid var(--bg-4);
  border-left: 3px solid var(--accent); border-radius: var(--r-xs);
  padding: .35rem .5rem; margin-bottom: .3rem;
}
#event-log-card .evl-top {
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
}
#event-log-card .evl-card {
  font-family: var(--ff-serif); font-weight: 700; color: var(--tx-1);
  font-size: var(--fs-sm);
}
#event-log-card .evl-rd { font-size: var(--fs-xs); color: var(--tx-3); }
#event-log-card .evl-sum {
  font-size: var(--fs-xs); color: var(--tx-2); margin-top: .2rem; line-height: var(--lh);
}
/* 事件牌「说明」行：加粗 + 左侧警示色条 + 略放大字号，解决「看不懂」*/
#event-log-card .evl-rules {
  display: block; color: var(--tx-1); font-weight: 600;
  font-size: var(--fs-sm);
  border-left: 2px solid var(--warn); padding-left: .45rem; margin-top: .3rem;
}
#event-log-card .evl-pending { border-left-color: var(--warn); }
#event-log-card .empty { color: var(--tx-3); font-size: var(--fs-sm); }

/* ═══════════════════════════════════════════════════════════════════
   规则书 §3 第 6 步 · 随机首发英雄揭晓层
   （★ 覆盖层：原文不删，回滚 = 删本块。样式参考 #event-overlay 的浮层口径）
   ═══════════════════════════════════════════════════════════════════ */
#starter-reveal {
  position: fixed; inset: 0; z-index: 160;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.1rem; padding: 2rem;
  background: rgba(6, 10, 16, .92); backdrop-filter: blur(4px);
}
#starter-reveal[hidden] { display: none !important; }
#starter-reveal .sr-head {
  font-family: var(--ff-serif); font-size: 1.7rem; letter-spacing: .34em;
  color: var(--accent); text-shadow: 0 0 18px rgba(110, 168, 220, .45);
}
#starter-reveal-cards { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }
#starter-reveal .sr-card {
  width: 186px; border-top: 3px solid var(--accent);
  background: linear-gradient(180deg, var(--bg-2), rgba(18, 26, 38, .92));
  border-radius: var(--r-xs); padding: .5rem .5rem .65rem;
  animation: srIn .45s ease-out backwards;
}
#starter-reveal .sr-card:nth-child(2) { animation-delay: .12s; }
#starter-reveal .sr-card:nth-child(3) { animation-delay: .24s; }
#starter-reveal .sr-card:nth-child(4) { animation-delay: .36s; }
#starter-reveal .sr-card:nth-child(5) { animation-delay: .48s; }
#starter-reveal .sr-card:nth-child(6) { animation-delay: .60s; }
#starter-reveal .sr-fac { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .1em; }
#starter-reveal .sr-img { position: relative; margin: .35rem 0; }
#starter-reveal .sr-img img { display: block; width: 100%; border-radius: 4px; }
#starter-reveal .sr-img .sr-noimg { display: none; }
#starter-reveal .sr-img.miss .sr-noimg {
  display: flex; align-items: center; justify-content: center;
  height: 250px; color: var(--tx-4); font-size: var(--fs-xs);
  border: 1px dashed var(--bg-4); border-radius: 4px;
}
#starter-reveal .sr-name { font-family: var(--ff-serif); font-size: var(--fs-sm); color: var(--tx-1); }
#starter-reveal .sr-title { font-size: var(--fs-xs); color: var(--tx-3); }
#starter-reveal .sr-foot { font-size: var(--fs-xs); color: var(--tx-3); }
#starter-reveal .sr-foot b { color: var(--tx-1); }
#starter-reveal button {
  padding: .5rem 1.6rem; border: 1px solid var(--accent); border-radius: 8px;
  background: rgba(110, 168, 220, .12); color: var(--tx-1);
  cursor: pointer; font-size: var(--fs-sm);
}
@keyframes srIn { from { opacity: 0; transform: translateY(14px) scale(.96); } }

/* ═══════════════════════════════════════════════════════════════════════════
   需求3/4 · 地图兵团标记改版（覆盖式追加层，回滚 = 删本块）
   旧版：15px 圆点 + 圆点**下方**一行计数 → 标记块向下伸出一截，
        既小到看不清计数，又会压住烘焙在地图里的地域编号。
   新版：26px 圆 + 数字画在**圆内**；城防/交战/敌方一律改挂**圆外角标**
        （绝对定位，不占布局）→ 标记块占地恒为「一个圆」，不再向下外扩。
   ★ .mk 的 width/height 是 translate(-50%,-50%) 的居中依据，改尺寸时一并改。
   ═══════════════════════════════════════════════════════════════════════════ */
.mk { width: 26px; height: 26px; }
.mk .dot {
  width: 26px; height: 26px; margin: 0;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid rgba(6,10,16,.9);
  box-shadow: 0 0 0 1px rgba(6,10,16,.85), 0 0 7px rgba(0,0,0,.8);
}
.mk .dot .cnt {
  font-family: var(--ff-serif); font-size: 13px; font-weight: 700;
  line-height: 1; color: #fff; margin: 0;
  text-shadow: 0 0 3px #000, 0 0 6px #000;
}
.mk.cap .dot { box-shadow: 0 0 0 3px #ffd34d, 0 0 14px rgba(255,211,77,.6); }
.mk.hot .dot { box-shadow: 0 0 0 3px var(--gem-lt), 0 0 16px rgba(226,87,76,.75); }
.mk .fort-badge {
  position: absolute; right: -9px; top: -9px; margin: 0;
  font-size: 10px; font-weight: 700; line-height: 1;
  color: #ffd98a; text-shadow: 0 0 4px #000, 0 0 6px #000;
}
.mk .hot-badge {
  position: absolute; right: -8px; bottom: -7px; margin: 0;
  font-size: 11px; font-weight: 700; line-height: 1;
  color: #ff8f85; text-shadow: 0 0 4px #000, 0 0 6px #000;
}
/* 敌方角标：该地域存在**非归属势力**的兵团（需求3「角标示敌」） */
.mk .foe-badge {
  position: absolute; left: -5px; top: -5px;
  width: 9px; height: 9px; border-radius: 2px;
  background: var(--gem-lt); border: 1.5px solid rgba(6,10,16,.9);
  box-shadow: 0 0 4px rgba(0,0,0,.8);
}

/* ═══════════════════════════════════════════════════════════════════════════
   需求3：标记退到地域编号徽章**上方**
   ═══════════════════════════════════════════════════════════════════════════
   底图里每个地域都有一个「编号徽章 + 名称/资源文字带」，而且是**烘焙进 PNG 像素**的，
   无法由 CSS 让位；标记放大到 26px 后，在屏幕上比徽章本体（源图约 155×120px，
   按大屏 ~1100px 宽渲染后只剩约 14×11px）更大，继续居中必然盖住编号。

   解法：锚点由「徽章中心」改为「徽章上沿」（region_layout.json 的 badge.t），
   再用 translate(-100%) 把整个标记抬到锚点之上，留 3px 缝隙。
   ★ 定位只用百分比 + 自身高度，**不读容器像素高度** —— 所以窗口缩放、投影换分辨率、
     手机横竖屏，避让量都自动跟着标记自身尺寸走，不需要任何 resize 重算。
   ★ .mk.mk-above 是双类选择器，优先级高于基础 .mk 单类规则，无需 !important。 */
.mk.mk-above {
  transform: translate(-50%, calc(-100% - 3px));
}

/* ═══════════════════════════════════════════════════════════════════════════
   R9（2026-09-18）：坐席「国策」弹窗改为**树状总览**（覆盖层，原文不删）
   ───────────────────────────────────────────────────────────────────────────
   原先是一份平铺清单（一项一行，只有「名字 + 已/未开发」），读不出「谁是谁的前置、
   现在能开发到第几层」。改为与手机端同构的三段树：支线（主轴）→ 层级（轴上的节点）
   → 国策卡（按层级缩进挂出），并列出每条效果文本与结算时机。
   结构由 host.js 的 openSeatPanel(kind="policy") 产出。
   ═══════════════════════════════════════════════════════════════════════════ */
.m-pol-head { margin: .1rem 0 .6rem; font-weight: 700; color: var(--tx-2); }
.m-pol-head b { color: var(--accent); }

.m-branch { margin: .2rem 0 .8rem; }
.m-br-head {
  display: flex; align-items: baseline; justify-content: space-between;
  padding: .3rem .5rem; margin-bottom: .3rem;
  background: linear-gradient(180deg, var(--bg-3), var(--bg-2));
  border: 1px solid var(--bg-4); border-radius: var(--r-xs);
}
.m-br-name { font-family: var(--ff-serif); font-weight: 700; color: #cfe4fb; }
.m-br-prog { font-size: .82rem; color: var(--tx-3); }

/* 主轴 + 层级节点 + 按层级缩进的挂接短杆 */
.m-tree { position: relative; margin-left: .35rem; padding-left: 1.2rem; }
.m-tree::before {
  content: ""; position: absolute; left: .4rem; top: .3rem; bottom: .3rem;
  width: 2px; border-radius: 2px;
  background: linear-gradient(180deg, rgba(110,168,220,.55), rgba(110,168,220,.10));
}
.m-lv { position: relative; margin: .6rem 0 .3rem; color: var(--tx-3); font-weight: 700; }
.m-lv .m-lv-dot {
  position: absolute; left: -1.2rem; top: .12rem;
  width: .62rem; height: .62rem; border-radius: 50%;
  background: var(--bg-1); border: 2px solid var(--accent);
}
.m-node {
  position: relative; margin: .3rem 0 .3rem calc(var(--depth, 0) * .55rem);
  padding: .45rem .6rem; border-radius: var(--r-sm);
  background: linear-gradient(180deg, var(--bg-2), rgba(18,26,38,.9));
  border: 1px solid rgba(226,87,76,.38);
}
.m-node::before {
  content: ""; position: absolute; left: -.8rem; top: 1rem;
  width: .8rem; height: 2px; background: rgba(226,87,76,.5);
}
.m-node.done { border-color: rgba(69,196,106,.45); }
.m-node.done::before { background: rgba(69,196,106,.6); }
.m-node-top { display: flex; align-items: baseline; gap: .5rem; }
.m-node-top .m-pol-name { flex: 1; color: var(--tx-1); font-family: var(--ff-serif); }
/* ★ 2026-09-22：国策开发状态标签 —— 已开发=绿 var(--ok) / 未开发=红 var(--bad)。
   与手机端同一口径；`.m-node:not(.done)` 优先级 (0,3,0) 高于本块 (0,2,0)，未开发落红。 */
.m-node-top .m-pol-state {
  flex: none; border-radius: 999px; padding: .05rem .45rem;
  border: 1px solid rgba(69,196,106,.45);
  background: rgba(69,196,106,.16); color: var(--ok); font-weight: 700;
}
.m-node:not(.done) .m-pol-state {
  color: var(--bad);
  background: rgba(226,87,76,.14);
  border-color: rgba(226,87,76,.42);
}
.m-node-sub { display: flex; gap: .3rem; flex-wrap: wrap; margin-top: .25rem; }
.m-tag.warn { background: rgba(224,169,60,.18); color: var(--warn); }
.m-tag.ok { background: rgba(69,196,106,.16); color: var(--ok); }
.m-peffs {
  margin-top: .35rem; padding-top: .3rem; border-top: 1px dashed var(--bg-4);
  display: flex; flex-direction: column; gap: .16rem;
}
.m-peff { font-size: .82rem; color: var(--tx-2); display: flex; gap: .35rem; flex-wrap: wrap; }
.m-peff::before { content: "◆"; color: var(--accent); font-size: .7rem; }
.m-peff .m-pe-when {
  flex: none; font-size: .72rem; padding: .02rem .3rem; border-radius: var(--r-xs);
  background: var(--bg-4); color: var(--tx-3);
}

/* ★ 2026-09-19：国策详情弹窗（点击席位弹窗里的国策节点） */
.pd-meta { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .5rem; }
.pd-m { font-size: .76rem; padding: .12rem .45rem; border-radius: 999px;
  background: var(--bg-4); color: var(--tx-2); }
/* ★ 2026-09-22：详情弹窗的开发状态标签，与树节点胶囊同一口径（该家族无描边，故只染底+字） */
.pd-m-st.ok { background: rgba(69,196,106,.18); color: var(--ok); font-weight: 700; }
.pd-m-st.todo { background: rgba(226,87,76,.16); color: var(--bad); font-weight: 700; }
.pd-sec { font-size: .82rem; font-weight: 700; color: var(--tx-1); margin: .6rem 0 .3rem;
  border-left: 3px solid var(--accent); padding-left: .45rem; }
.pd-effs { display: flex; flex-direction: column; gap: .35rem; }
.pd-eff { background: var(--bg-3); border: 1px solid var(--bg-4); border-radius: 8px; padding: .4rem .55rem; }
.pd-eff-name { font-weight: 600; color: var(--tx-1); font-size: .88rem; }
.pd-eff-when { display: inline-block; font-size: .72rem; padding: .02rem .35rem; border-radius: var(--r-xs);
  background: rgba(110,168,220,.18); color: #5b86bf; margin-top: .15rem; }
.pd-eff-note { font-size: .76rem; color: var(--tx-3); margin-top: .15rem; line-height: 1.4; }
.pd-conds { display: flex; flex-direction: column; gap: .25rem; }
.pd-cond { font-size: .8rem; color: var(--tx-2); }
/* ★ EV2：国策详情弹窗头部的卡牌图（服务端 policy_view.card_url；404 时 onerror 隐藏） */
.pd-cardimg { display: block; max-width: 320px; max-height: 440px; width: auto; height: auto;
  margin: 0 auto .6rem; border-radius: 10px; border: 1px solid var(--bg-4);
  object-fit: contain; cursor: zoom-in; }

/* ============================================================================
   大屏（主持人）布局改版 v1 —— 追加式覆盖层（2026-09-19 落地）
   ============================================================================
   纪律：不删原文一行（回滚 = 删掉本块）。

   ── 为什么需要这一层 ────────────────────────────────────────────────────
   原布局是「文档流」：header → 控制条 → #stage(flex)。地图是 1:1 正方形
   （11811x11811 原图），没有任何高度约束 → 宽度铺满时高度也铺满。1920x1080
   实测整页 1786px，比视口高 706px。席位又用 46% 半径的圆环叠在地图上，
   y=96% 那两张正好落在首屏之外。

   ── 本层要解决的 5 件事（对应用户反馈）────────────────────────────────
   ① 一屏装不下        → body 改 100vh grid，地图用容器查询取「可用正方形」
   ② 席位盖住地图      → 席位从「地图上的浮层」改为「地图左右两列独立栏」
   ③ 席位跑到地图下方  → 同上；列内垂直居中，总高固定
   ④ 推进按钮太占地方  → #controls 移入 header，压成 12px 工具组
   ⑤ 顶部横幅信息太少  → header 加 12 段阶段轨；信息条加常驻「本阶段在做什么」
   ============================================================================ */

/* ── 底座：整页一屏，纵向三段 ───────────────────────────────────────── */
html, body { height: 100%; overflow: hidden; }
body {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: 0;
}

/* ── 顶栏：品牌 | 阶段轨 | 阶段名 + 控制按钮组 ───────────────────────── */
header { height: 52px; padding: 0 var(--pad-page); gap: 1rem; }
header h1 { font-size: 1.02rem; letter-spacing: .06em; margin: 0; line-height: 1.1; }
.hd-brand { display: flex; align-items: baseline; gap: .7rem; }
.hd-right { display: flex; align-items: center; gap: .8rem; margin-left: auto; }
#phase { font-size: var(--fs-sm); white-space: nowrap; }

/* 阶段轨：12 段，一眼看出走到哪、还剩什么。
   大屏是给 3 米外看的公共屏 —— 所以用「短名 + 13px」，而不是 10.5px 全名。
   当前段的完整名在右边 #phase 里显示，两者互补。 */
#phase-rail { display: flex; align-items: center; gap: 2px; margin: 0; padding: 0; list-style: none; }
#phase-rail li {
  font-size: 13px; line-height: 1; padding: 6px 8px; white-space: nowrap;
  color: var(--tx-3); background: rgba(255,255,255,.03);
  border: 1px solid transparent; border-radius: 3px;
}
#phase-rail li.done { color: var(--tx-3); opacity: .5; }
#phase-rail li.now {
  color: #0b0f16; font-weight: 700; font-size: 13.5px;
  background: linear-gradient(180deg, #e6ecf5, #a9b6c8);
  border-color: #f2f6fb;
  box-shadow: 0 0 10px rgba(190,214,240,.35);
}
#phase-rail li.next { color: var(--tx-1); background: rgba(255,255,255,.07); }

/* 控制按钮：从「一整条」压成顶栏右侧的工具组 */
#controls { display: flex; align-items: center; gap: .32rem; }
#controls button {
  padding: .3rem .55rem; font-size: 12px; line-height: 1.25;
  background: linear-gradient(180deg, rgba(40,54,76,.95), rgba(20,29,44,.95));
  border: 1px solid rgba(170,182,198,.34); border-radius: var(--r-sm);
  color: var(--tx-1); cursor: pointer; white-space: nowrap;
}
#controls button:hover:not(:disabled) { border-color: #cfd8e4; }
#controls select { padding: .22rem .3rem; font-size: 12px; }
#controls .hint { font-size: 12px; color: var(--tx-2); white-space: nowrap; }

/* ── 信息条：原控制条。按钮搬走后只剩横幅 —— 再加常驻阶段提示 ───────── */
#manage.controlbar {
  margin: 0 var(--pad-page) .3rem; padding: .34rem var(--pad-page);
  display: flex; align-items: center; gap: .7rem; flex-wrap: nowrap;
  /* ★ 2D-2 机制3：本行是 nowrap 且 `.legend{margin-left:auto}` 钉在右端 —— 长 Banner/事件
     文案变长时会把右侧图例顶出视口右缘，再被 body{overflow:hidden} 裁掉（像「右侧内容
     右移/消失」）。加 overflow:hidden 兜底 + 让可收缩的子项能收。 */
  overflow: hidden;
  min-width: 0;
}
#manage .stage-hint, #manage .banner, #manage #event-banner { min-width: 0; }
.stage-hint { display: flex; align-items: baseline; gap: .55rem; font-size: var(--fs-sm);
  color: var(--tx-2); white-space: nowrap; flex: 0 1 auto; overflow: hidden; }
.stage-hint b { color: var(--tx-1); font-weight: 600; }
#manage .banner { flex: 0 1 auto; margin: 0; padding: .22rem .5rem; font-size: var(--fs-sm); }
#event-banner { display: flex; align-items: center; gap: .5rem; min-width: 0; }
#event-banner-img { height: 38px; width: auto; border-radius: 3px; }

/* 图例与二维码都收进信息条 —— 让地图本体零遮挡。
   ★ 地图图片自身在底部烧印了「回合指示 1~15」条，任何浮层都得避开地图本体。 */
#manage .legend {
  display: flex; flex-wrap: nowrap; flex: 0 1 auto;
  gap: .45rem .7rem; margin: 0 0 0 auto;
  border: none; padding: 0; font-size: 11px; line-height: 1.3; white-space: nowrap;
  /* ★ 2D-2 机制3：由 `0 0 auto`（拒绝收缩）改为可收缩 + 裁切，空间不足时先压缩图例，不再顶出视口 */
  min-width: 0; overflow: hidden;
}
#qr-corner {
  position: static; flex: 0 0 auto; margin: 0; padding: .18rem .4rem; gap: .4rem; max-width: 236px;
  background: none; border-color: rgba(170,182,198,.22); box-shadow: none;
}
#qr-corner img { width: 38px; height: 38px; }
#qr-corner .qr-title { font-size: 11px; }
#qr-corner .qr-room { font-size: 10px; }
#qr-corner #qr-link { font-size: 9px; word-break: break-all; }

/* ── 舞台：左席位 / 地图 / 右席位 / 战报，四列吃满一屏 ──────────────── */
#stage {
  display: grid;
  /* 批次 2C-A：坐席再收（190→170）、战报再宽（440→480）。固定列合计不变（820），
     故地图 1fr 宽度不变 —— 净效果＝席位让宽给战报。 */
  grid-template-columns: 170px minmax(0, 1fr) 170px 480px;
  gap: 8px;
  margin: 0 var(--pad-page) .5rem;
  min-height: 0;
  align-items: stretch;
}
.seat-col { display: flex; flex-direction: column; gap: 8px; justify-content: center; min-height: 0; }
.seat-col .seat { width: auto; }
/* 席位不再按百分比绝对定位 —— 改由 .seat-col 的 flex 列排布 */
.seat { position: relative; transform: none; }

/* 地图格：container-type:size 拿到「本格子的可用宽高」，再取其中较小的那个做边长。
   这样地图永远是 1:1、永远填满而不溢出 —— 不需要 JS 参与尺寸计算。 */
#map-panel {
  position: relative; margin: 0; padding: 0;
  background: none; border: none; box-shadow: none;
  container-type: size;
  display: grid; place-items: center;
  min-height: 0;
}
#map-panel::before, #map-panel::after { display: none; }
#map-wrap {
  position: relative;
  width: min(100cqw, 100cqh);
  height: auto; aspect-ratio: 1 / 1;
  line-height: 0;
}
#map-img { width: 100%; height: 100%; object-fit: contain; border-radius: var(--r-sm); }
#map-markers { position: absolute; inset: 0; }

/* 战报栏：满高，内部滚动 */
#battle-panel { max-height: none; height: 100%; margin: 0; overflow: auto; }

/* ── 窄屏：1440 / 1366 的笔记本与大屏 ────────────────────────────────
   ★ 不能只靠 1920 调好。实测 1440 下若沿用「完整阶段名」（936px），顶栏内容宽会到
     1628px，被 body 的 overflow:hidden 裁掉右侧 168px —— 玩家点不到「下一阶段」。 */
@media (max-width: 1680px) {
  #phase-rail li { font-size: 12px; padding: 5px 6px; }
  #stage { grid-template-columns: 158px minmax(0, 1fr) 158px 440px; gap: 8px; }
  #manage .legend { font-size: 10px; gap: .25rem .5rem; }
}
@media (max-width: 1480px) {
  #phase-rail li { font-size: 11px; padding: 5px 5px; }
  #controls button, #controls select, #controls .hint { font-size: 11px; }
  #controls button { padding: .26rem .45rem; }
  #stage { grid-template-columns: 146px minmax(0, 1fr) 146px 404px; gap: 6px; }
  #manage .legend { display: none; }        /* 空间不足时图例让位给战局信息 */
}

/* ===== [hidden] 例外补漏（2026-09-19）=====
   HTML 的 `hidden` 属性靠 UA 样式 `[hidden]{display:none}` 生效，而**任何显式 display
   规则都会把它盖掉**（同优先级按后来者胜）。本文件给 `#stage` 写了 `display:grid`、
   给 `#manage.controlbar` 写了 `display:flex` —— 于是这两个容器的 `hidden` **彻底失效**：
   房间还没创建，空舞台与图例条就已经铺在开局设置面板下面（实测：一大片空白 + 悬空的
   小地图 + 右下空战报框 + 左下孤立方块）。
   本文件其余容器（#qr-corner / #event-overlay / #starter-reveal / #event-banner-img）
   都补过这条例外，唯独漏了这两个。 */
#stage[hidden], #manage[hidden] { display: none !important; }
/* 图例同理：`#manage .legend{display:flex}` 也会盖掉 `hidden`。
   SETUP 阶段（还没开局）把图例收起来 —— 它讲的是对局信息（圈中数字＝兵团数）。 */
#manage .legend[hidden] { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   游戏封面 · 方案 D「六军会盟」（2026-09-19）
   ───────────────────────────────────────────────────────────────────────────
   追加覆盖层，不改上方任何既有规则；回滚 = 删掉本块。
   坐标沿用设计稿 `设计资产库/UI原型/封面/方案D_六军会盟.html` 的 1920×1080
   绝对定位，由 host.js 按视口算 `--cv-s` 整块缩放 —— 设计稿能 1:1 落地，
   且任意分辨率都不走形（用 vw/clamp 重写反而会到处变形）。
   全部造型带 `.cv-` 前缀：页面里已有一个 <h1> 和一堆裸标签规则，不隔离会串味。
   ═══════════════════════════════════════════════════════════════════════════ */
#cover { position: fixed; inset: 0; z-index: 900; overflow: hidden; background: #05080c;
  opacity: 1; transition: opacity .55s ease, visibility .55s ease; }
#cover.cv-off { opacity: 0; visibility: hidden; pointer-events: none; }

/* 主视觉铺满**真实视口**（不是 1920 舞台），超宽屏两侧才不会露黑边 */
#cover .cv-art { position: absolute; inset: 0;
  background: url("/static/cover.jpg") center / cover no-repeat;
  transform: scale(1.02); }
#cover .cv-veil { position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(5,8,12,.80) 0%, rgba(5,8,12,.34) 12%, transparent 26%),
    radial-gradient(1500px 900px at 50% 42%, transparent 40%, rgba(4,7,11,.42) 78%, rgba(4,7,11,.72) 100%); }
#cover .cv-veil-bot { position: absolute; left: 0; right: 0; bottom: 0; height: 548px;
  background: linear-gradient(180deg, rgba(5,8,12,0) 0%, rgba(5,8,12,.50) 30%,
              rgba(5,8,12,.84) 60%, rgba(5,8,12,.94) 84%, rgba(5,8,12,.97) 100%); }
/* ★ 标题背后的径向暗化：插画是复杂纹理（军阵 / 草地），只靠底部渐变压不住金色标题。
   判据不是「我看得清」，而是「缩到 30% 还看得清」。 */
#cover .cv-halo { position: absolute; left: 50%; bottom: 186px; width: 1560px; height: 580px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(4,7,11,.80) 0%, rgba(4,7,11,.48) 48%, transparent 78%); }

#cover .cv-stage { position: absolute; left: 50%; top: 50%; width: 1920px; height: 1080px;
  transform-origin: 50% 50%; transform: translate(-50%, -50%) scale(var(--cv-s, 1));
  font-family: var(--ff-serif); color: var(--tx-1); }

#cover .cv-top { position: absolute; left: 96px; right: 96px; top: 66px;
  display: flex; justify-content: space-between; align-items: center; }
#cover .cv-brand { display: flex; align-items: center; gap: 20px; }
#cover .cv-brand img { width: 48px; height: 48px; object-fit: contain;
  filter: drop-shadow(0 0 12px rgba(229,184,78,.55)) drop-shadow(0 2px 6px rgba(0,0,0,.8)); }
#cover .cv-brand span { font-size: 21px; letter-spacing: .36em; text-indent: .36em;
  color: #e2e9f4; text-shadow: 0 2px 8px rgba(0,0,0,.9); }
#cover .cv-brand em { font-style: normal; color: #8b9bb0; font-size: 16px; letter-spacing: .3em; }
#cover .cv-ver { font-size: 15px; letter-spacing: .24em; color: #93a1b4;
  text-shadow: 0 2px 8px rgba(0,0,0,.9); }

#cover .cv-title { position: absolute; left: 0; right: 0; top: 694px; text-align: center;
  font-size: 108px; line-height: 1; font-weight: 700; letter-spacing: .12em; text-indent: .12em;
  background: linear-gradient(178deg,#fff8dd 0%,#ffeba9 18%,#dcb054 42%,#9d7828 58%,#f2d994 76%,#cba44f 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  /* 背景是插画，阴影要够重才读得清：贴边硬影 + 中距柔影 + 外圈暖光 */
  filter: drop-shadow(0 3px 0 rgba(0,0,0,.9)) drop-shadow(0 8px 26px rgba(0,0,0,.92))
          drop-shadow(0 0 52px rgba(255,214,120,.26)); }
#cover .cv-div { position: absolute; left: 0; right: 0; top: 822px;
  display: flex; align-items: center; justify-content: center; gap: 24px; }
#cover .cv-div i { display: block; height: 1px; width: 280px; }
#cover .cv-div i.l { background: linear-gradient(90deg, transparent, #9aa8bc 44%, #e8f0fa 100%); }
#cover .cv-div i.r { background: linear-gradient(270deg, transparent, #9aa8bc 44%, #e8f0fa 100%); }
#cover .cv-div .gem { width: 10px; height: 10px; transform: rotate(45deg);
  background: linear-gradient(158deg,#f08a7c,#b83226 45%,#7d1c14);
  box-shadow: 0 0 14px rgba(192,57,43,.85); }
#cover .cv-sub { position: absolute; left: 0; right: 0; top: 840px; text-align: center;
  font-size: 37px; letter-spacing: .8em; text-indent: .8em; color: #eaf1fa;
  text-shadow: 0 2px 0 rgba(0,0,0,.85), 0 4px 18px rgba(0,0,0,.9); }
#cover .cv-crowns { position: absolute; left: 0; right: 0; top: 900px; text-align: center;
  font-size: 17px; letter-spacing: .34em; text-indent: .34em; color: #93a1b4;
  text-shadow: 0 2px 8px rgba(0,0,0,.95); }
#cover .cv-crowns i { font-style: normal; margin: 0 6px; opacity: .5; }
#cover .cv-crowns b { font-weight: 400; }
#cover .cv-crowns .c1 { color: var(--cr); } #cover .cv-crowns .c2 { color: var(--ta); }
#cover .cv-crowns .c3 { color: var(--el); } #cover .cv-crowns .c4 { color: var(--ho); }
#cover .cv-crowns .c5 { color: var(--xu); } #cover .cv-crowns .c6 { color: var(--az); }

#cover .cv-actions { position: absolute; left: 0; right: 0; top: 944px; text-align: center; }
#cover .cv-btn-main { position: relative; display: inline-flex; align-items: center; gap: 18px;
  padding: 16px 54px; font-family: var(--ff-serif); font-size: 28px; letter-spacing: .3em;
  text-indent: .3em; color: #ffeec2; cursor: pointer; border: none;
  background: linear-gradient(180deg,#1b2430,#0c141d);
  clip-path: polygon(14px 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 14px 100%, 0 50%);
  box-shadow: 0 12px 36px rgba(0,0,0,.78), 0 0 52px rgba(201,162,79,.26); }
#cover .cv-btn-main::before { content: ""; position: absolute; inset: 0; padding: 2px;
  background: var(--mt-gold);
  clip-path: polygon(14px 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 14px 100%, 0 50%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude; }
#cover .cv-btn-main:hover { filter: brightness(1.14); }
#cover .cv-btn-main:active { transform: translateY(1px); }
#cover .cv-btn-main .tri { width: 0; height: 0; border-left: 14px solid #f0d68f;
  border-top: 9px solid transparent; border-bottom: 9px solid transparent;
  filter: drop-shadow(0 0 8px rgba(240,214,143,.85)); }

/* ═══════════════════════════════════════════════════════════════════════════
   邀请弹窗 · 大二维码（2026-09-19）
   ───────────────────────────────────────────────────────────────────────────
   为什么改：二维码常驻在信息条里时被压到 **38×38** —— 而 segno 出的 SVG 是 33×33
   模块，38px 下**每模块约 1 个像素**，手机摄像头解不出来（用户报的「二维码太小，
   扫码都扫不出来」）。
   （顺手纠正一处我自己的误判：我一开始以为"信息条在 SETUP 阶段收起、所以二维码
   压根看不见"——实测建房后 `#manage` 是可见的，问题就只有尺寸。）
   现在：顶栏「邀请玩家」按钮 → 居中大二维码 440×440（每模块约 9.6px）。
   追加覆盖层，回滚 = 删本块 + index.html 里的 #qr-modal。
   ⚠ 二维码是 segno 输出的 SVG（黑线 + **透明底**），必须坐在**白底**上 ——
     直接放深色面板上就是"深底黑线"，既看不见也扫不出来。
   ═══════════════════════════════════════════════════════════════════════════ */
#qr-modal { position: fixed; inset: 0; z-index: 950; display: flex;
  align-items: center; justify-content: center;
  background: rgba(4,7,11,.86);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
#qr-modal[hidden] { display: none !important; }   /* ★ display:flex 会盖掉 hidden 属性 */
#btn-qr[hidden] { display: none !important; }

#qr-modal .qm-panel { position: relative; display: flex; align-items: center; gap: 50px;
  padding: 46px 58px; border-radius: var(--r-lg); border: 1px solid transparent;
  background:
    linear-gradient(180deg, rgba(20,29,41,.985), rgba(11,17,25,.985)) padding-box,
    var(--mt-silver) border-box;
  box-shadow: var(--sh-2), 0 0 80px rgba(110,168,220,.18); }
#qr-modal .qm-close { position: absolute; top: 12px; right: 14px; width: 42px; height: 42px;
  font-size: 26px; line-height: 1; color: var(--tx-2); background: none;
  border: 0; border-radius: 8px; cursor: pointer; }
#qr-modal .qm-close:hover { color: var(--tx-1); background: rgba(255,255,255,.08); }

/* 白底托住二维码 */
#qr-modal .qm-qrbox { flex: 0 0 auto; width: 440px; height: 440px; padding: 24px;
  background: #fff; border-radius: 10px; box-shadow: 0 10px 34px rgba(0,0,0,.55); }
#qr-modal #qr-corner img { width: 100%; height: 100%; display: block;
  border: 0; background: none; }

/* 旧样式的覆盖：信息条里那套（static 定位 / max-width:236px / 38px 图）在弹窗里必须失效 */
#qr-modal #qr-corner { position: static; display: flex; align-items: center; gap: 50px;
  margin: 0; padding: 0; max-width: none; background: none; border: 0; box-shadow: none; }
#qr-modal #qr-corner .qr-info { flex: 0 0 auto; width: 470px; }

#qr-modal .qm-title { font-size: 30px; font-weight: 700; color: var(--tx-1); letter-spacing: .08em; }
#qr-modal .qm-sub { margin-top: 8px; font-size: 15px; color: var(--tx-3); }
#qr-modal .qm-label { margin-top: 26px; font-size: 12px; letter-spacing: .24em; color: var(--tx-3); }
#qr-modal .qm-room { margin-top: 4px; font-family: var(--ff-serif); font-size: 60px;
  font-weight: 700; line-height: 1.1; letter-spacing: .16em; color: var(--cr);
  text-shadow: 0 2px 0 rgba(0,0,0,.5); }
#qr-modal #qr-link { display: block; margin-top: 4px; font-size: 15px; color: var(--accent);
  word-break: break-all; max-width: none; user-select: text; }
#qr-modal .qm-note { margin-top: 22px; padding-top: 16px; font-size: 12px; line-height: 1.65;
  color: var(--tx-4); border-top: 1px solid rgba(170,182,198,.16); }

/* ═══════════════════════════════════════════════════════════════════════════
   战斗演出 · 卡牌对战（2026-09-19）
   ───────────────────────────────────────────────────────────────────────────
   用户要求：「战斗阶段发生战斗按顺序做一个卡牌对战的对话效果，加强代入感 ——
   XX 兵团 VS XX 兵团 → 两张兵种卡出现在地图中间（有英雄就带上英雄卡）→
   显示双方发动了什么技能、什么效果 → 显示士气档（高涨/一般/低落）→
   显示进攻方投骰点数（给投点做一个画面）→ 计算伤害、扣防御方血量并显示 XX/YY
   → 防御方同样逻辑 → 幸存者显示剩余血量。」
   数据源 = `PUBLIC_STATE.battles[].steps`（服务端结构化事件流），此处**只做表现**。
   ⚠ `#bsp[hidden]` 必须显式写：本项目已多次踩到「显式 display 盖掉 hidden」。
   ═══════════════════════════════════════════════════════════════════════════ */
#bsp { position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center;
  background: rgba(4,7,11,.84); backdrop-filter: blur(3px); }
#bsp[hidden] { display: none !important; }
.bsp-stage { width: 1600px; max-width: 96vw; font-family: var(--ff), sans-serif; }

.bsp-head { text-align: center; margin-bottom: 18px; }
.bsp-region { display: block; font-size: 16px; letter-spacing: .22em; color: var(--tx-3); }
.bsp-vs { display: block; margin-top: 6px; font-family: var(--ff-serif); font-size: 46px;
  font-weight: 700; letter-spacing: .1em; color: #f0d68f;
  text-shadow: 0 2px 0 rgba(0,0,0,.7), 0 0 24px rgba(240,214,143,.35); }

.bsp-cards { display: grid; grid-template-columns: 1fr 260px 1fr; align-items: start; gap: 18px; }
.bsp-side { display: flex; flex-direction: column; align-items: center; gap: 12px;
  opacity: 0; transform: translateY(26px); transition: opacity .32s ease, transform .32s ease; }
.bsp-side.on { opacity: 1; transform: none; }

.bsp-row { display: flex; align-items: flex-start; justify-content: center; gap: 16px; }
.bsp-card { display: flex; flex-direction: column; align-items: center; }
.bsp-card img { display: block; height: 372px; width: auto; border-radius: 10px;
  border: 1px solid rgba(170,182,198,.45); box-shadow: 0 12px 34px rgba(0,0,0,.65); }
.bsp-card.hero img { height: 268px; border-color: rgba(240,214,143,.7);
  box-shadow: 0 12px 34px rgba(0,0,0,.65), 0 0 22px rgba(240,214,143,.18); }
/* 卡名放在卡片**下方**而不是叠在图上：兵种卡面自带标题，叠加会糊成两层字 */
.bsp-card .bsp-tag { padding: 8px 4px 0; font-size: 16px; text-align: center; color: var(--tx-2); }
.bsp-card.hero .bsp-tag { color: #f0d68f; }
/* ★ EV2：出战卡兵种名旁的兵团编号徽标「N 号」（不补零；老战报无 corps_no 不渲染） */
.bsp-card .bsp-tag .bsp-no { display: inline-block; margin: 0 6px; padding: 0 .5em;
  border-radius: 999px; background: rgba(255,255,255,.14); font-size: 13px;
  line-height: 1.5; color: #cfd6e4; vertical-align: 1px; }

.bsp-who { font-size: 16px; letter-spacing: .18em; color: var(--tx-3); }
/* ★ 2026-09-20（批次 D · ⑪）：出战卡攻击类型小标签（物攻/魔攻/混合） */
.bsp-type { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 6px;
  font-size: 13px; letter-spacing: .04em; color: #3a2a05;
  background: linear-gradient(180deg, #f0d68f, #d8b25a); }
.bsp-name { font-family: var(--ff-serif); font-size: 24px; color: var(--tx-1); }

.bsp-hp { width: 430px; }
.bsp-hpbar { position: relative; height: 16px; border-radius: 8px; overflow: hidden;
  background: rgba(255,255,255,.09); border: 1px solid rgba(170,182,198,.3); }
.bsp-hpbar i { position: absolute; inset: 0 auto 0 0; display: block;
  background: linear-gradient(90deg, #6fbf77, #a8d97f); transition: width .5s ease; }
.bsp-hpbar.low i { background: linear-gradient(90deg, #c8483b, #e0813f); }
.bsp-hptxt { margin-top: 5px; text-align: center; font-size: 21px; font-weight: 700;
  color: var(--tx-1); letter-spacing: .06em; }

.bsp-tags { width: 430px; min-height: 4px; display: flex; flex-direction: column; gap: 6px; }
.bsp-tagline { padding: 8px 14px; border-radius: 6px; font-size: 15px; line-height: 1.45;
  color: #eaf1fa; background: rgba(12,18,26,.9); border-left: 3px solid #8fa6c2;
  animation: bsp-in .28s ease both; }
.bsp-tagline.skill { border-left-color: #f0d68f; }
.bsp-tagline.morale { border-left-color: #9b6bff; }
.bsp-tagline.dmg { border-left-color: #e0564a; color: #ffd9d3; }
@keyframes bsp-in { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; } }

.bsp-mid { display: flex; align-items: center; justify-content: center; padding-top: 150px; }
.bsp-dice { width: 172px; height: 172px; border-radius: 18px; display: flex;
  flex-direction: column; align-items: center; justify-content: center;
  background: linear-gradient(160deg, #1b2431, #0b1119);
  border: 1px solid rgba(240,214,143,.6); box-shadow: 0 0 30px rgba(240,214,143,.22); }
.bsp-dice[hidden] { display: none !important; }
.bsp-dice span { font-family: var(--ff-serif); font-size: 86px; font-weight: 700;
  line-height: 1; color: #f0d68f; }
.bsp-dice em { margin-top: 6px; font-size: 12px; letter-spacing: .2em; color: var(--tx-3);
  font-style: normal; }
.bsp-dice.rolling { animation: bsp-shake .12s linear infinite; }
@keyframes bsp-shake { 0% { transform: translate(0,0); } 50% { transform: translate(2px,-2px); }
  100% { transform: translate(0,0); } }

.bsp-result { margin-top: 22px; text-align: center; padding: 14px 20px;
  border-radius: 10px; background: rgba(12,18,26,.92);
  border: 1px solid rgba(170,182,198,.35); animation: bsp-in .3s ease both; }
.bsp-result[hidden] { display: none !important; }
.bsp-result b { font-family: var(--ff-serif); font-size: 30px; letter-spacing: .1em;
  color: #f0d68f; }
.bsp-result div { margin-top: 8px; font-size: 18px; color: var(--tx-2); }


/* ══════════════════════════════════════════════════════════════════════════
   大屏卡面放大 v1（2026-09-19 · 追加覆盖层，回滚 = 删本块）
   ──────────────────────────────────────────────────────────────────────────
   ① 事件翻牌层自适应：卡高跟随视口 → 1920×1080 / 1440×900 / 1366×768 三档实测
      恒定留 53px 余量，绝不溢出；结果区限制在 22vh 内可滚动，避免长文案把卡挤出屏。
   ② 点击放大浮层 #card-zoom：卡高 = 视口高 − 144px，独立层、不占版面。
      实测卡宽 641 / 518 / 427（现状 254），正文行高 9.8 / 7.9 / 6.5 px（现状 3.9 px）。
   ★ 为什么不放大演出层的卡（.bsp-card img 372/268）：实测现状在 1366×768 上
     内容高已达 847 > 视口 768（本来就溢出 79px），再放大只会更糟 —— 要看清走浮层。
   数据与对照图：UI原型/大屏改版/大屏卡面放大方案_v1.md
   ══════════════════════════════════════════════════════════════════════════ */
#event-overlay .event-card-flip {
  width: calc((100vh - 320px) * 0.684);
  height: calc(100vh - 320px);
}
#event-result {
  max-height: 22vh;
  overflow-y: auto;
}

#card-zoom {
  position: fixed; inset: 0; z-index: 170;
  display: flex; align-items: center; justify-content: center;
  background: rgba(4, 7, 11, .92); backdrop-filter: blur(4px);
  cursor: zoom-out;
}
#card-zoom[hidden] { display: none !important; }
#card-zoom img {
  height: calc(100vh - 144px); width: auto; display: block;
  border-radius: 14px; box-shadow: 0 24px 70px rgba(0, 0, 0, .8);
  border: 1px solid rgba(170, 182, 198, .35);
}
#card-zoom .cz-hint {
  position: absolute; left: 0; right: 0; bottom: 22px; text-align: center;
  font-size: var(--fs-sm); color: var(--tx-3);
}
/* 可点暗示：只改光标，不动任何尺寸 */
#event-card-front img, .bsp-card img { cursor: zoom-in; }


/* ══════════════════════════════════════════════════════════════════════════
   席位面板卡面 + 国策进度 v1（2026-09-19 · 追加覆盖层，回滚 = 删本块）
   ──────────────────────────────────────────────────────────────────────────
   ① 修 z-index：放大浮层原为 170，而席位弹窗容器 #modal-root 是 200 →
      从弹窗里点卡会「放大到弹窗背后」，看起来像没反应。提高到 260。
   ② 席位弹窗里的卡面行（英雄 / 兵种）：缩略图宽 ~86px（≥80px 才会被
      cardZoomInit 的全局点击判据接住，见 host.js 的 80px 门槛）。
   ③ 席位条上的国策开发进度（公开信息）。
   ══════════════════════════════════════════════════════════════════════════ */
#card-zoom { z-index: 260; }

.seat-pol {
  font-size: var(--fs-xs); color: var(--tx-2); margin: -.15rem 0 .35rem;
  letter-spacing: .02em;
}
.seat-pol b { color: var(--tx-1); }

.m-cardrow {
  display: flex; align-items: flex-start; gap: .55rem;
  padding: .4rem .5rem; margin-bottom: .35rem;
  border-radius: 7px; background: rgba(32, 44, 60, .6);
  border: 1px solid var(--bg-4);
}
.m-cardrow img.m-cardimg {
  width: 86px; height: 126px; object-fit: cover; border-radius: 5px;
  border: 1px solid rgba(170, 182, 198, .35); cursor: zoom-in;
  flex: 0 0 auto; background: rgba(8, 12, 18, .6);
}
.m-cardrow .m-cardinfo { flex: 1 1 auto; min-width: 0; }
.m-cardrow .m-cardinfo .m-hero,
.m-cardrow .m-cardinfo .m-unit { margin-bottom: .2rem; }
.m-cardrow .m-cardinfo .m-sub { margin: .15rem 0 0; }


/* ══════════════════════════════════════════════════════════════════════════
   地图：占领色徽章层 + 分势力兵团圈 v1（2026-09-19 · 追加覆盖层，回滚 = 删本块）
   ──────────────────────────────────────────────────────────────────────────
   ① #map-badges：地域编号徽章的占领色。**不改底图**（底图里那个 11811² PNG 的
      徽章底色是初始归属，且同一构图还有 mini / vendor 多份副本，改图要同步一圈）。
      这里用 mix-blend-mode:color —— 只取覆盖层的**色相+饱和度**、明度仍来自底图，
      于是编号白字、深色描边、金色外框全部原样保留，只把底色换成占领方颜色。
      逐帧重建 → 结算后即时变更（host.js drawMapOverlay）。
   ② 兵团标记改「每方一个圈」：`.mk` 尺寸改由 --dot 控制（多圈时自动缩小），
      圈内数字 = **该势力**在此地域的兵团数（旧版是全桌总数挤在一个圈里）。
   ══════════════════════════════════════════════════════════════════════════ */
#map-badges { position: absolute; inset: 0; pointer-events: none; }
#map-badges i {
  position: absolute; display: block; border-radius: 2px;
  mix-blend-mode: color;
  transition: background-color .35s ease;   /* 占领后颜色渐变，避免突然跳色 */
}

.mk { width: auto; height: var(--dot, 26px); }
.mk .dots {
  display: flex; align-items: center; justify-content: center;
  gap: 2px; height: var(--dot, 26px); border-radius: 999px;
}
.mk .dots .dot {
  width: var(--dot, 26px); height: var(--dot, 26px); box-sizing: border-box;
  margin: 0; border-radius: 50%; display: flex; align-items: center;
  justify-content: center;
  border: 2px solid rgba(6, 10, 16, .9);
  box-shadow: 0 0 0 1px rgba(6, 10, 16, .85), 0 0 7px rgba(0, 0, 0, .8);
}
.mk .dots .dot .cnt {
  margin: 0; font-family: var(--ff-serif); font-weight: 700; line-height: 1;
  font-size: var(--dotfs, 13px); color: #fff;
  text-shadow: 0 0 3px #000, 0 0 6px #000;
}
/* 首都圈：环在**整排**圈上（多圈时不会被某个势力的颜色带跑） */
.mk.cap .dots { box-shadow: 0 0 0 3px #ffd34d, 0 0 14px rgba(255, 211, 77, .6); }
/* 交战圈：环仍按红，加在整排上 */
.mk.hot .dots { box-shadow: 0 0 0 3px var(--gem-lt), 0 0 16px rgba(226, 87, 76, .75); }
.mk.cap.hot .dots { box-shadow: 0 0 0 3px #ffd34d, 0 0 16px rgba(226, 87, 76, .75); }

/* ★ 批次 2D：放大浮层内，标记物的 gap / border / 环 也随 canvas 等比（主图仍 px）。
   基准 = canvas 宽（scale=1 时 = inner 边长 ≈993.6）：2px→0.2012cqw、1px→0.1006cqw、
   3px→0.3019cqw、7px→0.7045cqw、14px→1.4090cqw、16px→1.6103cqw。
   ⚠ 只作用于 `#host-map-zoom-markers`，**不动**主图 `#map-markers`。 */
#host-map-zoom-markers .mk .dots { gap: 0.2012cqw; }
#host-map-zoom-markers .mk .dots .dot {
  border-width: 0.2012cqw;
  box-shadow: 0 0 0 0.1006cqw rgba(6, 10, 16, .85), 0 0 0.7045cqw rgba(0, 0, 0, .8);
}
#host-map-zoom-markers .mk.cap .dots { box-shadow: 0 0 0 0.3019cqw #ffd34d, 0 0 1.4090cqw rgba(255, 211, 77, .6); }
#host-map-zoom-markers .mk.hot .dots { box-shadow: 0 0 0 0.3019cqw var(--gem-lt), 0 0 1.6103cqw rgba(226, 87, 76, .75); }
#host-map-zoom-markers .mk.cap.hot .dots { box-shadow: 0 0 0 0.3019cqw #ffd34d, 0 0 1.6103cqw rgba(226, 87, 76, .75); }

/* ── ★ 2026-09-19 修正：环状 box-shadow 画在「宽度靠子元素撑开」的容器上 ──────
   病灶：环画在 `.dots` 上，而没有兵团时 `.dots` 宽 0 → `0×26` + 3px 扩散
   = 6×32 的黄色竖条（实测 6 条 = 6 个首都）。
   处置：`.mk.cap` 的金环已随「首都标识移到编号框右侧」一并退休（host.js 不再发
   `cap` 类），此规则只为**仍保留环**的 `.mk.hot` 兜底最小尺寸。 */
.mk.hot .dots { min-width: var(--dot, 26px); }

/* ── ★ 首都标识 v2：编号框右侧一颗小星 ──────────────────────────────────────
   用户反馈 v1（标记金环 + ★ 圆盘）太大、太占地方 → 改成贴在编号框右边的小星。
   尺寸用 cqw/cqh：`#map-panel` 是 `container-type:size`，地图边长 = min(cw, ch)，
   所以 `min(0.85cqw, 0.85cqh)` 恒等于地图边长的 0.85%（1920 大屏 ≈ 8.5px）——
   换分辨率自动等比，不需要 JS 算尺寸。
   位置由 host.js 按 `region_layout.json` 的 badge 框算出：左边缘贴框右侧、垂直居中。 */
#map-badges .cap-star, #host-map-zoom-badges .cap-star {
  position: absolute; transform: translateY(-50%);
  font-family: var(--ff-serif); font-size: min(0.85cqw, 0.85cqh); line-height: 1;
  font-weight: 700; color: #ffd34d;
  text-shadow: 0 0 2px #000, 0 0 4px #000, 0 0 7px rgba(0, 0, 0, .9);
}

/* ── ★ 地域标记物 v1（2026-09-19）：城防 / 产出 ±N / 焦土·荆棘 ────────────────
   素材 = 设计库里做好的实体指示物（`设定集/_token_design/实物尺寸` → 随仓库落在
   `server/static/markers/`，满足自包含红线）。
   贴在编号框**左侧**（右侧留给首都星、上方留给兵团圈），行**右端**对齐框左沿：
   `translate(-100%, -50%)` ── 位置与标记实际尺寸无关，换分辨率不用重算。
   ⚠ 尺寸**必须**用 cqw/cqh（`#map-panel` 是 container-type:size，地图边长 = min(cw,ch)）：
     这一行是「宽度自适应」的绝对定位 flex 容器，若给图片写百分比宽度会形成
     循环依赖（% 相对父宽、父宽又由子宽决定），实测会被解析成错误的基准值 ——
     标记缩到 6px、整行被推离编号框 450px。`min(1.45cqw,1.45cqh)` = 地图边长 1.45%
     = 徽章高（170.9 / 11811），与所有徽章等高，且无循环。 */
#map-badges .mod-tokens {
  position: absolute; transform: translate(-100%, -50%);
  display: flex; align-items: center; gap: 1px;
}
#map-badges .mod-tokens img {
  width: min(1.45cqw, 1.45cqh); height: auto; display: block;
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, .85));
}

/* ═══════════════════════════════════════════════════════════════════════════
   房间创建屏改版 · 六国会盟厅（ERD-UX-01 / ERD-ART-01 落地）
   ───────────────────────────────────────────────────────────────────────────
   追加式覆盖层：上方既有规则**一行未删**，回滚 = 删掉本块。
   造型全部 scoped 在 #setup 之下（前缀 .st-），避免与既有 .panel/.seat/.mk 等串味。
   令牌 100% 取自 common.css 冷银主题层；**不引入新颜色 / 字体 / 渐变**。
   金色预算：全屏只有 #btn-create（.st-cta）一枚金块；段切/卡片选中态一律
   「亮银面 + 深字 + --accent 内圈」（两位成员交叉评审后的裁决）。
   坐标 = 1920×1080 设计稿绝对像素，整块按 JS 给的 --cv-s（**数字**）等比缩放。
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 全屏舞台层（脱离文档流；与 #cover 同位阶，故给 901 压在其上） ── */
#setup {
  position: fixed; inset: 0; z-index: 901; margin: 0; padding: 0;
  border: 0; border-radius: 0; box-shadow: none; overflow: hidden;
  background: #05080c;
  font-family: var(--ff-serif); color: var(--tx-1);
}
#setup[hidden], #setup[data-st-state="off"] { display: none !important; }
/* .panel 给 #setup 加的四角 L 饰在此无意义（满屏），关掉 */
#setup::before, #setup::after { display: none; }

/* ── Layer 0：会盟厅厅堂 —— cover.jpg 常驻压暗，只压暗不模糊（零 GPU 代价） ── */
#setup .st-bg {
  position: absolute; inset: 0;
  background: url("/static/cover.jpg") center / cover no-repeat;
  transform: scale(1.02);           /* 吃掉缩放插值产生的边 */
}
#setup .st-veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(5,8,12,.86) 0%, rgba(5,8,12,.60) 14%,
                    rgba(5,8,12,.52) 40%, rgba(5,8,12,.66) 100%),
    radial-gradient(1500px 900px at 62% 40%, transparent 34%,
                    rgba(4,7,11,.55) 76%, rgba(4,7,11,.86) 100%);
}
#setup .st-veil-l {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(4,7,11,.80) 0%, rgba(4,7,11,.52) 34%,
                              rgba(4,7,11,.12) 56%, transparent 70%);
}

/* ── 1920×1080 舞台（--cv-s 由 host.js 给数字，见文件头注释） ── */
#setup .st-stage {
  position: absolute; left: 50%; top: 50%; width: 1920px; height: 1080px;
  transform-origin: 50% 50%;
  transform: translate(-50%, -50%) scale(var(--cv-s, 1));
  font-family: var(--ff-serif); color: var(--tx-1);
}

/* ── 金属面板底座 + 四角 L 饰（padding-box/border-box 双值，单值会被内层盖掉） ── */
#setup .st-pnl {
  position: absolute; border: 1px solid transparent; border-radius: var(--r);
  background: linear-gradient(180deg, rgba(24,34,47,.90), rgba(12,18,26,.94)) padding-box,
              var(--mt-silver) border-box;
  box-shadow: var(--sh-1), var(--sh-inset);
}
#setup .st-pnl::before, #setup .st-pnl::after {
  content: ""; position: absolute; width: 15px; height: 15px;
  pointer-events: none; opacity: .55; border: 1px solid var(--mt-silver-solid);
}
#setup .st-pnl::before { top: 5px; left: 5px; border-right: 0; border-bottom: 0; }
#setup .st-pnl::after  { bottom: 5px; right: 5px; border-left: 0; border-top: 0; }

/* ── 区标题：serif 34 + 红宝石菱形前缀（沿用 h2::before 既有语法） ── */
#setup .st-sech {
  display: flex; align-items: center; gap: 12px; font-family: var(--ff-serif);
  font-size: 34px; font-weight: 600; color: var(--tx-1); letter-spacing: .06em; line-height: 1;
}
#setup .st-sech .gem {
  width: 11px; height: 11px; transform: rotate(45deg); flex: none;
  background: var(--mt-gem); box-shadow: 0 0 10px rgba(192,57,43,.6);
}
#setup .st-sech small {
  font-family: var(--ff-sans); font-size: 14px; font-weight: 400;
  color: var(--tx-3); letter-spacing: .08em;
}
#setup .st-sech.sm { font-size: 22px; }
#setup .st-sech.sm .gem { width: 8px; height: 8px; }

/* ── 顶栏 ── */
#setup .st-top {
  position: absolute; left: 96px; top: 44px; width: 1728px; height: 80px;
  display: flex; align-items: center; justify-content: space-between;
}
#setup .st-brand { display: flex; align-items: center; gap: 18px; }
#setup .st-brand img {
  width: 52px; height: 52px; object-fit: contain;
  filter: drop-shadow(0 0 12px rgba(229,184,78,.5)) drop-shadow(0 2px 6px rgba(0,0,0,.85));
}
#setup .st-brand .st-bt { font-size: 22px; letter-spacing: .34em; color: #e2e9f4; text-shadow: 0 2px 8px rgba(0,0,0,.9); }
#setup .st-brand .st-bs { font-style: normal; color: #8b9bb0; font-size: 15px; letter-spacing: .28em; margin-left: 12px; }
#setup .st-roomchip {
  display: flex; align-items: center; gap: 14px; padding: 10px 22px; border-radius: var(--r-sm);
  border: 1px solid transparent; font-family: var(--ff-sans); font-size: 15px; letter-spacing: .14em;
  background: linear-gradient(180deg, rgba(32,44,60,.85), rgba(16,24,34,.9)) padding-box, var(--mt-silver) border-box;
  color: var(--tx-3);
}
#setup .st-roomchip b { font-family: var(--ff-serif); font-size: 24px; letter-spacing: .22em; color: var(--tx-4); }
/* lobby 态：房间码原地点亮（金描边 + 亮字） */
#setup[data-st-state="lobby"] .st-roomchip {
  background: linear-gradient(180deg, rgba(32,44,60,.85), rgba(16,24,34,.9)) padding-box, var(--mt-gold) border-box;
  color: var(--tx-2);
}
#setup[data-st-state="lobby"] .st-roomchip b { color: var(--tx-1); text-shadow: 0 0 14px rgba(229,184,78,.5); }

/* ── 区① 剧本 ── */
#setup .st-script {
  left: 96px; top: 148px; width: 700px; height: 812px; padding: 26px 28px;
  display: flex; flex-direction: column;
}
#setup .st-script > .st-sech { margin-bottom: 22px; }
#setup .st-grp { margin-bottom: 26px; }
#setup .st-grp:last-of-type { margin-bottom: 0; }
#setup .st-grph {
  display: flex; align-items: baseline; gap: 10px; font-family: var(--ff-serif);
  font-size: 19px; color: var(--tx-2); letter-spacing: .1em; margin: 0 0 12px;
}
#setup .st-grph i { font-style: normal; font-family: var(--ff-sans); font-size: 13px; color: var(--tx-4); letter-spacing: .04em; }

/* 游戏模式：2 张大卡 314×180（本屏视觉最重的一对） */
#setup .st-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
#setup .st-card {
  position: relative; height: 180px; padding: 22px 22px 18px; border-radius: var(--r);
  border: 1px solid transparent; overflow: hidden; cursor: pointer; text-align: left;
  font-family: inherit; color: inherit; display: flex; flex-direction: column;
  background: linear-gradient(180deg, rgba(26,36,50,.92), rgba(12,19,28,.95)) padding-box, var(--mt-silver) border-box;
  box-shadow: var(--sh-1), var(--sh-inset);
}
#setup .st-card .st-ttl { font-family: var(--ff-serif); font-size: 24px; color: var(--tx-1); letter-spacing: .06em; }
#setup .st-card .st-sub { font-family: var(--ff-sans); font-size: 16px; color: var(--tx-3); line-height: 1.6; margin-top: 12px; }
#setup .st-card .st-topline { position: absolute; left: 0; right: 0; top: 0; height: 3px; background: var(--mt-teal); opacity: .9; }
#setup .st-card .st-gemdot {
  position: absolute; right: 16px; top: 14px; width: 9px; height: 9px; transform: rotate(45deg);
  background: var(--mt-gem); box-shadow: 0 0 10px rgba(192,57,43,.7);
}
#setup .st-card:hover { filter: brightness(1.1); }
/* 选中态：亮银面 + --accent 内圈（不走金 —— 金色让给主 CTA） */
#setup .st-card.sel {
  border: 1px solid transparent;
  background: linear-gradient(180deg, rgba(46,60,78,.95), rgba(18,27,38,.97)) padding-box, var(--mt-silver) border-box;
  box-shadow: inset 0 0 0 2px var(--accent), 0 3px 16px rgba(0,0,0,.5);
}
#setup .st-card.sel .st-sub { color: var(--tx-2); }
/* 「征服」选中＝红宝石描边 + 红光（危险剧本烧起来；不是金） */
#setup .st-card[data-mode="conquest"].sel {
  background: linear-gradient(180deg, rgba(58,30,28,.95), rgba(20,12,12,.97)) padding-box, var(--mt-gem) border-box;
  box-shadow: inset 0 0 0 2px rgba(226,87,76,.5), 0 0 20px rgba(192,57,43,.35);
}

/* 段切（势力模式 / 首发英雄）：槽下凹，选中＝银亮面 + 深字 + --accent 内圈 */
#setup .st-seg {
  display: inline-flex; gap: 4px; padding: 4px; border-radius: var(--r-sm);
  background: rgba(6,10,16,.5); box-shadow: inset 0 1px 2px rgba(0,0,0,.6);
  border: 1px solid rgba(170,182,198,.35);
}
#setup .st-seg button {
  font-family: var(--ff-serif); font-size: 17px; color: var(--tx-2); padding: 9px 20px;
  border-radius: var(--r-xs); letter-spacing: .05em; line-height: 1;
  background: transparent; border: 0; cursor: pointer;
}
#setup .st-seg button:hover { color: var(--tx-1); }
#setup .st-seg button.on {
  background: var(--mt-silver); color: var(--tx-inv); font-weight: 700;
  box-shadow: inset 0 0 0 2px var(--accent), 0 2px 8px rgba(0,0,0,.55);
}
#setup .st-note { font-family: var(--ff-sans); font-size: 14px; color: var(--tx-3); line-height: 1.55; margin-top: 10px; }

/* 盟书摘要：吃掉区① 底部余量（margin-top:auto 顶到底） */
#setup .st-oath { margin-top: auto; padding-top: 20px; border-top: 1px solid rgba(170,182,198,.16); }
#setup .st-oath-rule { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }
#setup .st-oath-rule i { flex: 1; height: 1px; }
#setup .st-oath-rule i:first-child { background: linear-gradient(90deg, transparent, rgba(154,168,188,.5)); }
#setup .st-oath-rule i:last-child  { background: linear-gradient(90deg, rgba(154,168,188,.5), transparent); }
#setup .st-oath-rule .gem {
  width: 9px; height: 9px; transform: rotate(45deg); flex: none;
  background: var(--mt-gem); box-shadow: 0 0 8px rgba(192,57,43,.55);
}
#setup .st-oath-t {
  font-family: var(--ff-serif); font-size: 28px; font-weight: 600; letter-spacing: .34em;
  text-indent: .34em; text-align: center; color: var(--tx-1);
  text-shadow: 0 2px 0 rgba(0,0,0,.85), 0 5px 18px rgba(0,0,0,.85);
}
#setup .st-oath-s { font-family: var(--ff-sans); font-size: 15px; color: var(--tx-3); text-align: center; line-height: 1.8; margin-top: 12px; }
#setup .st-oath-kv {
  font-family: var(--ff-sans); font-size: 14px; color: var(--tx-2); text-align: center;
  letter-spacing: .08em; margin-top: 10px; font-variant-numeric: tabular-nums;
}

/* ── 区② 会盟席位 ── */
#setup .st-seats {
  left: 820px; top: 148px; width: 1004px; height: 488px; padding: 24px 28px;
  display: flex; flex-direction: column;
}
#setup .st-seatsbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: 16px; flex-wrap: wrap;
}
#setup .st-sum { display: flex; gap: 20px; font-family: var(--ff-sans); font-size: 15px; color: var(--tx-3); letter-spacing: .06em; }
#setup .st-sum b { font-family: var(--ff-serif); font-size: 22px; color: var(--tx-1); font-variant-numeric: tabular-nums; margin-left: 6px; }
#setup .st-seatacts { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
#setup .st-steppers { display: flex; gap: 22px; }
#setup .st-stp { display: flex; align-items: center; gap: 10px; }
#setup .st-stp .lb { font-family: var(--ff-sans); font-size: 14px; color: var(--tx-2); letter-spacing: .06em; }
/* ± 槽位器：一条凹槽内 [−] 数值 [＋] */
#setup .st-stp .box {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px; border-radius: var(--r-sm);
  background: rgba(6,10,16,.5); box-shadow: inset 0 1px 2px rgba(0,0,0,.6);
  border: 1px solid rgba(170,182,198,.35);
}
#setup .st-stp .u {
  width: 30px; height: 30px; display: grid; place-items: center; font-size: 18px; padding: 0;
  color: var(--tx-2); border-radius: var(--r-xs); border: 1px solid rgba(170,182,198,.3);
  cursor: pointer; line-height: 1; background: transparent; font-family: var(--ff-sans);
}
#setup .st-stp .u:hover:not(:disabled) { color: var(--tx-1); border-color: var(--accent); }
#setup .st-stp .u:active:not(:disabled) { transform: translateY(1px); }
#setup .st-stp .u:disabled { opacity: .38; filter: grayscale(.5); cursor: not-allowed; }
#setup .st-stp .v {
  font-family: var(--ff-serif); font-size: 22px; font-weight: 600; color: var(--tx-1);
  font-variant-numeric: tabular-nums; min-width: 34px; text-align: center;   /* 防数字跳动时整行左右抖 */
}

/* 6 纹章棋盘 3×2（本屏签名元素） */
#setup .st-board {
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 1fr);
  gap: 14px; margin-top: 16px; flex: 1; min-height: 0;
}
#setup .st-tile {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; border: 1px solid transparent; border-radius: var(--r); overflow: hidden;
  background: linear-gradient(180deg, var(--bg-2), rgba(12,18,26,.92)) padding-box, var(--mt-silver) border-box;
  box-shadow: var(--sh-1), var(--sh-inset);
}
#setup .st-tile::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: radial-gradient(closest-side at 50% 116%, color-mix(in srgb, var(--c) 34%, transparent), transparent 74%);
}
#setup .st-tile img {
  width: 64px; height: 64px; object-fit: contain; position: relative;
  filter: grayscale(.6) brightness(.85) drop-shadow(0 0 10px color-mix(in srgb, var(--c) 40%, transparent));
}
#setup .st-tile .nm { position: relative; font-family: var(--ff-serif); font-size: 18px; color: var(--tx-2); letter-spacing: .06em; }
#setup .st-tile .stt { position: relative; font-family: var(--ff-sans); font-size: 12px; color: var(--tx-4); letter-spacing: .06em; }
#setup .st-tile .dot {
  position: absolute; left: 14px; top: 13px; width: 9px; height: 9px; border-radius: 50%;
  border: 1.5px solid var(--mt-silver-solid);
}
/* 已被真人认领：青绿描边 + 满饱和纹章 + 实心青绿点（颜色 + 明度 + 图形三编码） */
#setup .st-tile.claim {
  border: 1px solid transparent;
  background: linear-gradient(180deg, rgba(28,48,44,.92), rgba(11,22,20,.95)) padding-box, var(--mt-teal) border-box;
}
#setup .st-tile.claim img { filter: none; }
#setup .st-tile.claim .nm { color: var(--tx-1); }
#setup .st-tile.claim .stt { color: var(--mt-teal-solid); }
#setup .st-tile.claim .dot { background: var(--mt-teal-solid); border-color: var(--mt-teal-solid); box-shadow: 0 0 8px rgba(95,179,160,.8); }
/* 人机占据：银描边 + 方形「齿轮」点（形状编码，不靠色） */
#setup .st-tile.bot .stt { color: var(--tx-3); }
#setup .st-tile.bot .dot { border-radius: 2px; border-color: var(--tx-2); }
/* 封印（随机模式未分配）：整块压暗 + 锁 */
#setup .st-tile.sealed { background: linear-gradient(180deg, rgba(14,20,29,.95), rgba(9,13,19,.97)) padding-box, var(--mt-silver) border-box; }
#setup .st-tile.sealed img { filter: brightness(.32) grayscale(.85); }
#setup .st-tile.sealed .nm { color: var(--tx-4); }
#setup .st-tile .lock { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); font-size: 22px; color: var(--tx-3); }
/* 中立 / 未参战（人数<6）：压暗 + 45° 斜纹 */
#setup .st-tile.neutral { opacity: .35; }
#setup .st-tile.neutral::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(45deg, rgba(255,255,255,.05) 0 6px, transparent 6px 12px);
}

/* ── 区③ 大陆预览（氛围 + 预期；不可点击，防误触） ── */
#setup .st-map {
  left: 820px; top: 660px; width: 1004px; height: 300px; padding: 20px 28px;
  display: flex; gap: 24px;
}
#setup .st-mapbox {
  position: relative; width: 62%; border-radius: var(--r-sm); overflow: hidden;
  border: 1px solid rgba(170,182,198,.28); background: #0b1119;
}
#setup .st-mapbox img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 46%;
  filter: saturate(.55) brightness(.62);
}
#setup .st-mapbox::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(closest-side at 50% 50%, transparent 42%, rgba(4,7,11,.72) 100%);
}
#setup .st-mapright { flex: 1; display: flex; flex-direction: column; justify-content: space-between; padding: 2px 0; }
#setup .st-chips { display: flex; flex-direction: column; gap: 9px; }
#setup .st-chip { display: flex; align-items: center; gap: 10px; font-family: var(--ff-sans); font-size: 14px; color: var(--tx-2); }
#setup .st-chip i { width: 26px; height: 8px; border-radius: 2px; background: var(--c); box-shadow: 0 0 0 1.5px rgba(0,0,0,.55); flex: none; }
#setup .st-flow { display: flex; align-items: center; gap: 8px; font-family: var(--ff-sans); font-size: 14px; color: var(--tx-4); }
#setup .st-flow b { font-weight: 400; }
#setup .st-flow b.on { color: var(--mt-teal-solid); }
#setup .st-flow .arw { opacity: .5; }

/* ── 底栏 ── */
#setup .st-foot {
  position: absolute; left: 96px; top: 984px; width: 1728px; height: 52px;
  display: flex; align-items: center; justify-content: space-between;
}
#setup .st-fold { display: flex; align-items: center; gap: 16px; }
#setup .st-btnfold {
  display: flex; align-items: center; gap: 8px; font-family: var(--ff-sans); font-size: 15px;
  color: var(--tx-3); letter-spacing: .06em; background: transparent; border: 0; cursor: pointer; padding: 0;
}
#setup .st-btnfold:hover { color: var(--tx-2); }
#setup .st-btnfold .cv { font-size: 12px; transition: transform .2s ease; }
#setup .st-btnfold[aria-expanded="true"] .cv { transform: rotate(180deg); }
#setup .st-digest { font-family: var(--ff-sans); font-size: 15px; color: var(--tx-2); letter-spacing: .04em; }
#setup .st-acts { display: flex; align-items: center; gap: 14px; justify-content: flex-end; }
#setup .st-acts .slot { display: flex; align-items: center; }
#setup .st-btn {
  font-family: var(--ff-sans); font-size: 17px; letter-spacing: .08em; padding: 12px 26px;
  border-radius: var(--r-sm); border: 1px solid transparent; cursor: pointer; line-height: 1;
  background: linear-gradient(180deg, rgba(32,44,60,.9), rgba(16,24,34,.95)) padding-box, var(--mt-silver) border-box;
  color: var(--tx-2); box-shadow: var(--sh-inset);
}
#setup .st-btn:hover { filter: brightness(1.15); }
#setup .st-btn:disabled { opacity: .45; cursor: not-allowed; filter: grayscale(.4); }
/* 「继续上次房间」＝青绿描边（有可恢复对局） */
#setup .st-btn.st-teal {
  background: linear-gradient(180deg, rgba(20,42,38,.9), rgba(10,22,20,.95)) padding-box, var(--mt-teal) border-box;
  color: var(--tx-1);
}
/* 主 CTA：全屏唯一金色块 */
#setup .st-btn.st-cta {
  font-family: var(--ff-serif); font-size: 26px; font-weight: 700; padding: 13px 46px; color: var(--tx-inv);
  background: var(--mt-gold) border-box; box-shadow: 0 3px 14px rgba(201,162,79,.28), var(--sh-inset);
}
#setup .st-btn.st-cta:hover { filter: brightness(1.12); }
#setup .st-btn.st-cta:disabled { filter: grayscale(.5) brightness(.9); }

/* ── 主持参数折页（Tier C：从底栏向上推出） ── */
#setup .st-foldpanel {
  position: absolute; left: 96px; bottom: 96px; width: 860px; padding: 18px 22px; z-index: 2;
  border: 1px solid transparent; border-radius: var(--r);
  background: linear-gradient(180deg, rgba(24,34,47,.97), rgba(12,18,26,.98)) padding-box, var(--mt-silver) border-box;
  box-shadow: var(--sh-2);
}
/* ★ 必须显式写：任何 display 规则都会盖掉 UA 的 [hidden]{display:none}（项目已多次踩） */
#setup .st-foldpanel[hidden] { display: none !important; }
#setup .st-frow { display: flex; align-items: flex-end; gap: 22px; margin-top: 14px; flex-wrap: wrap; }
#setup .st-fld { display: flex; flex-direction: column; gap: 6px; font-family: var(--ff-sans); font-size: 14px; color: var(--tx-2); letter-spacing: .06em; }
#setup .st-fld.st-check { flex-direction: row; align-items: center; gap: 8px; padding-bottom: 10px; letter-spacing: .02em; }
/* Tier C 原生控件造型化（视觉规格 §4.5）：金属底 + 银描边 + 统一高 40，
   箭头自绘 data-uri（★ 不用 ::after —— <select> 是替换元素，部分引擎不渲染伪元素）。
   色值全部取自既有令牌（--bg-3/--bg-2/--mt-silver/--mt-teal；箭头 #6d7c91 == --tx-3）。 */
#setup .st-fld input[type="number"],
#setup .st-fld select {
  font-family: var(--ff-sans); font-size: 15px; color: var(--tx-1); min-width: 9rem; height: 40px;
  padding: 0 12px; border-radius: var(--r-sm); border: 1px solid transparent;
  background: linear-gradient(180deg, var(--bg-3), var(--bg-2)) padding-box, var(--mt-silver) border-box;
}
#setup .st-fld select {
  appearance: none; -webkit-appearance: none; padding-right: 32px;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1 L6 6 L11 1' stroke='%236d7c91' fill='none' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E"),
    linear-gradient(180deg, var(--bg-3), var(--bg-2)),
    var(--mt-silver);
  background-repeat: no-repeat;
  background-position: right 10px center, 0 0, 0 0;
  background-size: 12px 8px, 100% 100%, 100% 100%;
  background-clip: padding-box, padding-box, border-box;
  background-origin: padding-box, padding-box, border-box;
}
#setup .st-fld input[type="number"]:hover,
#setup .st-fld select:hover { filter: brightness(1.15); }
#setup .st-fld input[type="number"]:focus,
#setup .st-fld select:focus {
  outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent);
  box-shadow: 0 0 12px rgba(110,168,220,.35);
}
/* checkbox → 金属开关（44×24 凹槽 + 20px 银圆盘）：**纯渐变，不用伪元素**（跨引擎稳，规避替换元素的伪元素坑）。
   开 = 青绿描边 + 圆盘右移；关 = 银描边 + 圆盘左移。文字标签常驻（见 HTML）。 */
#setup .st-fld input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; margin: 0; cursor: pointer; flex: 0 0 auto;
  width: 44px; height: 24px; border-radius: 12px; border: 1px solid transparent;
  background:
    radial-gradient(circle at 12px 50%, #e8eef7 0 8px, transparent 8.6px) padding-box,
    linear-gradient(180deg, var(--bg-3), var(--bg-2)) padding-box,
    var(--mt-silver) border-box;
}
#setup .st-fld input[type="checkbox"]:checked {
  background:
    radial-gradient(circle at 32px 50%, #e8eef7 0 8px, transparent 8.6px) padding-box,
    linear-gradient(180deg, rgba(20,42,38,.95), rgba(10,22,20,.98)) padding-box,
    var(--mt-teal) border-box;
}
#setup .st-fld input[type="checkbox"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── 契约锚点：Tier A/B 原生控件（视觉隐藏，由新控件双向驱动；值仍可读写） ── */
#setup .st-native { display: none; }

/* ── 会盟厅显示期间：#modal-root（存档 / 读档面板）必须抬到 #setup(901) 之上 ──
   否则「读档」按钮点开后弹窗被会盟厅盖住（z-index 200 < 901）。
   ★ 只在会盟厅态抬高：对局态保持 200 —— #card-zoom(260) 依赖它「压在席位弹窗之上」。 */
body[data-conclave="1"] #modal-root { z-index: 940; }

/* ── 会盟厅显示期间：audio.js 的「背景音乐」浮标避让底栏 CTA ──────────────────
   背景：`#erd-audio-btn` 由 audio.js 以 MIX_CSS 注入（`#erd-audio-btn{right:14px;bottom:14px}`，
   特异性 1-0-0，**bottom 声明无 !important**）→ 本选择器 1-1-1 稳压，无需 !important。
   ★ ERD-HOSTFIX-01 修正 —— 上一版只对了 16:9，**非 16:9 全中招**（16:10 笔记本 1440×900 /
     1680×1050 / 1920×1200、平板竖屏、超宽超高等，浮标会下沉去盖 CTA，中心甚至点不到）。
   关键：舞台**垂直居中** ⇒ cv = min(100vw/1920, 100vh/1080)，
         stageTop = (100vh − 1080·cv)/2 = 50vh − 540·cv；
         CTA `#btn-create` 在舞台内设计顶边 y=986 ⇒ 屏幕上 CTA 顶 = 50vh + 446·cv。
   要让浮标（高 44，视口固定）底边压在 CTA 顶上方 gap 处：
         浮标 bottom 偏移 = 100vh − (stageTop + 986·cv) + gap = 50vh − 446·cv + gap （gap=12px）
   ★ 上一版 `96·cv + 10px` **把 50vh 这一项丢了** —— 只在 16:9 上近似成立，一旦窗口比 16:9
     更「方/更窄/更高」，50vh 变小而浮标底边反而更低，就压到 CTA。
   验算（代入上式，gap=12）：1920×1080→106 ｜ 1366×768→78.8 ｜ 1280×800→114.7 ｜
     1440×900→127.5 ｜ 1920×1200→166 ｜ 2560×1080→106 ｜ 1180×820→147.9 ｜ 844×390→46 ｜
     900×1400→502.9
   面板 `#erd-audio-panel` 同幅上移（比浮标再高 52 = 按钮高 44 + 间隙 8），保持「面板悬于按钮之上」，
   且底边始终高于 CTA 顶。 */
body[data-conclave="1"] #erd-audio-btn {
  bottom: calc(50vh - 446 * min(100vw / 1920, 100vh / 1080) + 12px);
}
body[data-conclave="1"] #erd-audio-panel {
  bottom: calc(50vh - 446 * min(100vw / 1920, 100vh / 1080) + 64px);
}


/* ══════════════════════════════════════════════════════════════════════════
   批次 2B-B（大屏 · host）：四项修复 —— 追加覆盖层，不改上方既有规则；
   回滚 = 删掉本块。
     ① 地图放大浮层：#host-map-zoom 补全 CSS + 明确关闭按钮 + 可拖可缩
     ② 战报面板：#battle-panel 重排为 7 个固定高度分区（区内滚、外层不滚）
     ③ 技能效果区：.sk-* 样式（此前无任何样式）
     ④ 席位缩小：往地图收，让宽给战报
   ══════════════════════════════════════════════════════════════════════════ */

/* ── ① 地图放大浮层 ─────────────────────────────────────────────────────
   病灶（用户实测「关不掉、大得离谱、还拖不动」）：
     · #host-map-zoom 几乎没有 CSS → 只是普通 div，<img> 按原始尺寸(11811²)撑开
       ＝「大得离谱」；
     · 无遮罩、无关闭按钮；host.js 只允许点 e.target===hmz 关，而 inner 铺满
       → 永远点不到空白＝「关不掉」；
     · hmzClamp 在 scale≈1 时把平移清零，且画布基准是原始尺寸 → 「拖不动」。
   修法：全屏 fixed + 半透明遮罩 + flex 居中；inner 受视口约束成正方形；
   画布铺满 inner，<img> object-fit:contain 等比 fit（scale=1 即整体可见）；
   加 × 关闭按钮 + 遮罩空白关 + Esc 关；hmzClamp 改「溢出量」边界（见 host.js）。 */
#host-map-zoom {
  /* ★ QA CONCERN-1：z-index 必须**高于常驻音频按钮** #erd-audio-btn（audio.js 注入，
     z-index:9000，right/bottom:14px）—— 否则它会盖住浮层右下角的「复位」并**拦截点击**。
     浮层是模态，本就该压在常驻控件之上。 */
  position: fixed; inset: 0; z-index: 9100;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6, 10, 16, .88);
}
#host-map-zoom[hidden] { display: none !important; }

#host-map-zoom-inner {
  position: relative;
  width: min(92vw, 92vh); height: min(92vw, 92vh);
  overflow: hidden; border-radius: 12px;
  background: #0e2c4e;
  box-shadow: 0 16px 60px rgba(0, 0, 0, .6), 0 0 0 1px rgba(170, 182, 198, .22);
  touch-action: none; cursor: grab;
  /* 作为尺寸查询容器：让浮层内 .cap-star / .mod-tokens 的 cqw/cqh 以「地图盒」为基准
     （与主图 #map-panel 同口径）；否则无匹配容器时 cqw 会退化成视口宽。 */
  container-type: size;
}
#host-map-zoom-inner:active { cursor: grabbing; }

#host-map-canvas {
  /* ★ 批次 2D：定位模型由「inset:0 + JS transform:scale()」改为
     「left/top:50% + JS 按缩放设 width/height=base*scale + translate(-50%,-50%) 自居中」。
     旧模型把 ≈base px 的图整块 scale 放大 → 放大后糊；新模型是**按缩放后的真实尺寸布局**，
     浏览器从 11811² 原图重新采样 ⇒ 清晰。width/height 默认 100%（=inner 边长，scale=1
     时与旧表现完全一致），JS 会写具体 px 覆盖。 */
  position: absolute; left: 50%; top: 50%;
  width: 100%; height: 100%;
  transform-origin: 50% 50%;
  will-change: transform;
  /* ★ 批次 2D：canvas 自身设为尺寸查询容器 —— 浮层内 `.cap-star` / `.mod-tokens img`
     用 cqw/cqh 定尺寸；旧模型靠 transform 整体缩放，现在 canvas 的尺寸随 scale 变，
     故 cq 基准必须落在 canvas 上才能与地图一起等比放大（否则放大后 ★/标记物不放大、
     相对地图缩水）。scale=1 时 canvas==inner，表现与旧版一致。 */
  container-type: size;
}
#host-map-canvas > img {
  width: 100%; height: 100%; display: block;
  object-fit: contain; user-select: none; -webkit-user-drag: none; pointer-events: none;
}
#host-map-zoom-badges, #host-map-zoom-markers { position: absolute; inset: 0; pointer-events: none; }
#host-map-zoom-frontier { position: absolute; inset: 0; pointer-events: none; }

/* 放大浮层里的占领色徽章 / 地域标记物（与主图 #map-badges 同源，样式补齐） */
#host-map-zoom-badges i {
  position: absolute; display: block; border-radius: 2px;
  mix-blend-mode: color; transition: background-color .35s ease;
}
#host-map-zoom-badges .mod-tokens {
  position: absolute; transform: translate(-100%, -50%);
  display: flex; align-items: center; gap: 1px;
}
#host-map-zoom-badges .mod-tokens img {
  width: min(1.45cqw, 1.45cqh); height: auto; display: block;
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, .85));
}

/* 关闭按钮（右上 ×） */
.hmz-close {
  position: absolute; right: 20px; top: 20px; z-index: 2;
  width: 46px; height: 46px; border-radius: 50%; cursor: pointer;
  font-size: 22px; line-height: 1; color: #fff; font-weight: 700;
  border: 1px solid rgba(255, 255, 255, .38);
  background: rgba(20, 29, 44, .86);
}
.hmz-close:hover { background: #b23a3a; border-color: #fff; }

/* 缩放控制条 + 底部提示 */
.hmz-zoom-ctl {
  position: absolute; right: 24px; bottom: 24px;
  display: flex; flex-direction: column; gap: 8px;
}
#host-map-zoom .hmz-btn {
  width: 46px; height: 46px; border-radius: 10px; cursor: pointer;
  font-size: 20px; line-height: 1; color: #e8eef8;
  border: 1px solid rgba(170, 182, 198, .42);
  background: linear-gradient(180deg, rgba(40, 54, 76, .96), rgba(20, 29, 44, .96));
}
#host-map-zoom .hmz-btn:hover { border-color: #cfd8e4; }
.hmz-hint {
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
  font-size: 13px; color: rgba(226, 233, 244, .85); white-space: nowrap;
  background: rgba(6, 10, 16, .62); padding: 5px 14px; border-radius: 999px;
}

/* ── ② 战报面板（2C-A）：收敛为 3 个固定高度分区 + 与席位一致的深色处理 ──
   ①「结算·事件·外交」②「命令执行」③「技能效果」；区内滚（.bp-b），外层不滚。
   底色由白/淡白改为深蓝灰（对齐 .seat 深色卡），消除「突兀」的白块。 */
#battle-panel {
  display: flex; flex-direction: column; gap: 8px;
  height: 100%; max-height: none; margin: 0;
  padding: .6rem .65rem;
  overflow: hidden;                 /* 外层绝不出现滚动条 */
  background: linear-gradient(180deg, rgba(26,36,52,.96), rgba(14,20,30,.96)) padding-box,
              var(--mt-silver) border-box;
  border: 1px solid transparent; border-radius: var(--r);
  box-shadow: var(--sh-1), var(--sh-inset);
  color: var(--tx-1);
}
#battle-panel > .bp-sec {
  display: flex; flex-direction: column; min-height: 0;
  border: 1px solid rgba(170,182,198,.24); border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .04);   /* 深色下的「抬升面」，不再是白 */
  overflow: hidden;
}
#battle-panel > .bp-sec > .bp-h {
  flex: 0 0 auto; display: flex; align-items: center; gap: .45rem;
  padding: .44rem .7rem; font-size: .95rem; font-weight: 700; letter-spacing: .03em;
  color: var(--tx-1);
  background: linear-gradient(180deg, rgba(110,168,220,.18), rgba(110,168,220,.05));
  border-bottom: 1px solid rgba(170,182,198,.22);
}
#battle-panel > .bp-sec > .bp-b {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: .55rem .7rem;
  color: var(--tx-2);
}
/* 固定比例分配（总高恒定 → 1920×1080 下 4 区都可见、无外滚条）。
   结算·事件·外交 : 命令执行 : 技能效果 : 战斗日志 = 4 : 3 : 4 : 5。
   ④ 战斗日志给到最大份额 —— 它是新增的「可回看」区，内容最长的正是它。 */
#battle-panel > .bp-sec[data-sec="info"]  { flex: 4 4 0; }
#battle-panel > .bp-sec[data-sec="exec"]  { flex: 3 3 0; }
#battle-panel > .bp-sec[data-sec="skill"] { flex: 4 4 0; }
#battle-panel > .bp-sec[data-sec="blog"]  { flex: 5 5 0; }
/* ① 内部分段（结算／事件／整编·侦察／外交），各带小标题 */
#battle-panel .bp-sub { margin-bottom: .55rem; }
#battle-panel .bp-sub:last-child { margin-bottom: 0; }
#battle-panel .bp-sub-h {
  font-size: .78rem; font-weight: 700; letter-spacing: .1em; color: var(--tx-3);
  margin: .1rem 0 .3rem; padding-bottom: .18rem;
  border-bottom: 1px solid rgba(170,182,198,.16);
}
/* 让「分区体」成为**唯一**滚动条：清掉旧卡片为堆叠预留的大外边距
   （战斗卡列表已移除，故不再有 #battle-list 一条）。 */
#battle-panel .bp-b #settlement-card,
#battle-panel .bp-b #exec-order-card,
#battle-panel .bp-b #move-report-card,
#battle-panel .bp-b #rg-sc-card,
#battle-panel .bp-b #diplo-card { margin-bottom: 0; }
#battle-panel .bp-b .log { max-height: none; }

/* ★ 2D-2 机制1（2026-09-21）：分区体只允许**纵向**滚动。
   `overflow-y:auto` 时另一轴 `visible` 会按 CSS 规则**计算成 `auto`** ⇒ 长内容 / 长不可断串
   （URL、长英文、无空格串）会被**横向滚走并停在终点**（正是用户报的「偏到一定程度就停住」），
   而外层 `#battle-panel{overflow:hidden}` 又把越界部分裁掉 ⇒ 看起来「战报栏内容不见了」。
   修法：显式 `overflow-x:hidden` + 长串 `overflow-wrap:anywhere`（会参与 min-content 计算，
   比 break-word 更能防溢出）。 */
#battle-panel .bp-b {
  overflow-x: hidden;
  overflow-wrap: anywhere;
  word-break: break-word;
  min-width: 0;
}
/* flex/grid 子项默认 `min-width:auto` **拒绝收缩** → 长串会把分区体撑破（再被横向滚走）。
   逐类补 `min-width:0`；断行由上面的 `overflow-wrap` 继承生效。 */
#battle-panel .bp-b .st-cell,
#battle-panel .bp-b .st-row,
#battle-panel .bp-b .eo-row,
#battle-panel .bp-b .mr-row,
#battle-panel .bp-b .evl-row,
#battle-panel .bp-b .evl-top,
#battle-panel .bp-b .evl-card,
#battle-panel .bp-b .rgs-row,
#battle-panel .bp-b .log,
#battle-panel .bp-b .sk-row,
#battle-panel .bp-b .sk-fx,
#battle-panel .bp-b .bl-item,
#battle-panel .bp-b .bl-body,
#battle-panel .bp-b .bl-cards,
#battle-panel .bp-b .bl-card,
#battle-panel .bp-b .bl-step { min-width: 0; }

/* ── ③ 技能效果区（.sk-*）—— 2C-A 深色化 + 放大字号/行距 ── */
#battle-panel .sk-row {
  font-size: .9rem; color: var(--tx-2); padding: .38rem 0; line-height: 1.55;
  border-bottom: 1px dashed rgba(170,182,198,.18);
}
#battle-panel .sk-row:last-child { border-bottom: 0; }
#battle-panel .sk-rd {
  display: inline-block; min-width: 2rem; font-weight: 700;
  color: var(--tx-3); font-size: .82rem;
}
#battle-panel .sk-fx {
  margin-top: .3rem; padding: .42rem .6rem; border-radius: var(--r-sm);
  background: rgba(110,168,220,.14); color: var(--tx-1);
  border: 1px solid rgba(110,168,220,.26);
  font-size: .88rem; line-height: 1.55;
}
#battle-panel .sk-empty { color: var(--tx-3); font-size: .9rem; }
/* 被动 / 战斗触发技能小节（数据源 payload.battle_history[].battles[].steps[] t==="skill"） */
#battle-panel .sk-sub {
  margin: .65rem 0 .2rem; padding-top: .45rem; font-weight: 700;
  color: var(--accent); font-size: .88rem; letter-spacing: .04em;
  border-top: 1px solid rgba(170,182,198,.22);
}
#battle-panel .sk-passive { background: rgba(110,168,220,.07); border-radius: var(--r-xs); }
#battle-panel .sk-passive .sk-rd { color: var(--accent); }

/* ── ④ 战斗日志区（.bl-*）—— 批次3。与 ①/②/③ 同口径：深色抬升面 + 区内滚 + 竖排列表。
   长文本换行**继承** `.bp-b` 的 overflow-wrap:anywhere（红线：不改该规则）。 ── */
#battle-panel .bp-h-note {
  margin-left: auto; font-weight: 500; font-size: .8rem;
  color: var(--tx-3); letter-spacing: .02em;
}
#battle-panel .bl-empty { color: var(--tx-3); font-size: .9rem; }
#battle-panel .bl-item {
  padding: .1rem 0; border-bottom: 1px dashed rgba(170,182,198,.18);
}
#battle-panel .bl-item:last-child { border-bottom: 0; }
#battle-panel .bl-item > summary {
  cursor: pointer; list-style: none; padding: .36rem 0;
  font-size: .9rem; color: var(--tx-1); line-height: 1.5;
}
#battle-panel .bl-item > summary::-webkit-details-marker { display: none; }
#battle-panel .bl-item > summary::before { content: "▸ "; color: var(--accent); }
#battle-panel .bl-item[open] > summary::before { content: "▾ "; }
#battle-panel .bl-region { font-weight: 700; }
#battle-panel .bl-win { font-size: .8rem; margin-left: .3rem; }
#battle-panel .bl-win.ak { color: #8fce8f; }
#battle-panel .bl-win.df { color: #d79a6a; }
#battle-panel .bl-win.na { color: var(--tx-3); }
#battle-panel .bl-body { padding: .1rem 0 .5rem .2rem; }
#battle-panel .bl-cards { display: flex; gap: .7rem; margin: .05rem 0 .4rem; }
#battle-panel .bl-card {
  flex: 1 1 0; font-size: .86rem; color: var(--tx-2); line-height: 1.55;
}
#battle-panel .bl-role {
  display: inline-block; min-width: 1.5rem; font-weight: 700; color: var(--accent);
}
#battle-panel .bl-hp { color: var(--tx-3); font-size: .82rem; }
#battle-panel .bl-step {
  font-size: .88rem; color: var(--tx-2); line-height: 1.55; padding: .2rem 0;
}
#battle-panel .bl-step .bl-ico { display: inline-block; min-width: 1.1rem; }
#battle-panel .bl-band { font-weight: 700; }
#battle-panel .bl-band.hi { color: #e0b24a; }
#battle-panel .bl-band.nm { color: var(--tx-2); }
#battle-panel .bl-band.lo { color: #d47a7a; }
#battle-panel .bl-nosteps { font-size: .84rem; color: var(--tx-3); font-style: italic; }

/* ── ④ 席位再缩、往地图收：把宽度让给战报（2C-A）。字号以「可读」为底，不再更小 ── */
#stage .seat-col { gap: 5px; }
#stage .seat-col .seat { padding: .34rem .42rem; font-size: .76rem; }
#stage .seat-col .seat .crest { width: 23px; height: 23px; }
#stage .seat-col .seat .seat-name { font-size: .8rem; }
#stage .seat-col .seat .seat-fac { font-size: .72rem; margin: .12rem 0 .07rem; }
#stage .seat-col .seat .seat-res { font-size: .7rem; margin-bottom: .24rem; }
#stage .seat-col .seat .seat-pol { font-size: .7rem; }
#stage .seat-col .seat-btns { gap: .2rem; }
#stage .seat-col .seat-btns button { padding: .21rem 0; font-size: .72rem; }


/* ══════════════════════════════════════════════════════════════════════════
   批次 2F（2026-09-21）：养伤英雄徽章 + 主持人代赎回
   ──────────────────────────────────────────────────────────────────────────
   用户裁定（6 条）：负伤回合 R ⇒ R+1 不可赎、R+2 的**行政阶段**可赎；费用固定不吃折扣；
   不占招募额度；入口在行政阶段；赎回后回**待命区**、须在整编环节再上场；待命英雄不会负伤。
   数据契约（PUBLIC_STATE.players[].heroes[]）：wounded_since / rounds_left / redeemable /
   redeem_cost。配色沿用冷银主题令牌，不引入新颜色族。
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 席位条上的养伤标记（与 .seat-ai-tag 同处 .seat-tags，统一右对齐） ── */
.seat-wound {
  color: #fff; font-size: .68rem; padding: .05rem .35rem;
  border-radius: 4px; white-space: nowrap;
}
.seat-wound.wait { background: #8a6d3b; }   /* 仍需强制休养：琥珀 */
.seat-wound.ok   { background: #2e8b57; }   /* 已到可赎时点：绿 */

/* ── 英雄弹窗：养伤徽章 ── */
.m-wound {
  display: inline-block; font-size: var(--fs-xs); font-weight: 700;
  padding: .1rem .5rem; border-radius: 5px; margin: .1rem 0 .2rem;
  background: rgba(138,109,59,.22); border: 1px solid rgba(138,109,59,.5);
  color: #e6cf9a;
}
.m-wound.ok {
  background: rgba(46,139,87,.22); border-color: rgba(46,139,87,.55); color: #9fe0b8;
}
.m-wound .m-wound-hint {
  display: block; font-weight: 400; font-size: .72rem; opacity: .85; margin-top: .1rem;
}

/* ── 英雄弹窗：代赎回入口（按钮 + 固定价说明） ── */
.m-redeem { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; margin-top: .3rem; }
.m-redeem-btn {
  font-family: var(--ff-sans); font-weight: 700; font-size: .86rem;
  border: 1px solid var(--accent); background: rgba(58,111,178,.16);
  color: var(--tx-1); border-radius: 7px; padding: .42rem .85rem; cursor: pointer;
  white-space: nowrap;
}
.m-redeem-btn:hover { background: var(--accent); color: #0b1219; }
.m-redeem-btn:disabled {
  opacity: .55; cursor: not-allowed; background: var(--bg-3);
  border-color: rgba(170,182,198,.3); color: var(--tx-3);
}
.m-redeem-cost { font-size: var(--fs-xs); color: var(--tx-2); }

/* ── 弹窗顶部反馈横幅（赎回成功 / 失败 / 等待） ── */
.m-redeem-msg {
  margin: 0 0 .65rem; padding: .5rem .7rem; border-radius: 7px;
  font-size: var(--fs-sm); line-height: 1.45;
}
.m-redeem-msg.ok   { background: rgba(46,139,87,.18);  border: 1px solid rgba(46,139,87,.5);  color: #9fe0b8; }
.m-redeem-msg.err  { background: rgba(178,58,58,.18);  border: 1px solid rgba(178,58,58,.5);  color: #f0b4b4; }
.m-redeem-msg.wait { background: rgba(138,109,59,.18); border: 1px solid rgba(138,109,59,.5); color: #e6cf9a; }


/* ══════════════════════════════════════════════════════════════════════════
   批次 2G-B（2026-09-21）：席位弹窗「国策树」—— 名称 / 前置条件 / 效果描述 补全
   ──────────────────────────────────────────────────────────────────────────
   原节点只用一枚「前置未满足/已满足」标签表示前置、且效果行只印内部时机码（T50…）。
   现：前置按 `par_names` 明列 + 门槛（英雄前置/持续控制）明列 + 效果描述 `note` 成行。
   ══════════════════════════════════════════════════════════════════════════ */
.m-par {
  font-size: .78rem; line-height: 1.4; margin-top: .22rem;
  padding: .12rem .42rem; border-radius: var(--r-xs);
}
.m-par.ok   { color: var(--ok);   background: rgba(69,196,106,.12); border: 1px solid rgba(69,196,106,.28); }
.m-par.miss { color: var(--warn); background: rgba(224,169,60,.14); border: 1px solid rgba(224,169,60,.32); }
.m-peff-name { flex: none; font-weight: 600; color: var(--tx-1); }
.m-peff-note {
  flex-basis: 100%; font-size: .76rem; line-height: 1.42; color: var(--tx-3);
  padding-left: .1rem;
}


/* ══════════════════════════════════════════════════════════════════════════
   批次 2G-B②（2026-09-21）：技能区区分「国家技能卡」与英雄技能
   ──────────────────────────────────────────────────────────────────────────
   服务端 2G-A 起，卡片路径（龙焰 / 禁咒…）也写 `skill_log` 且带 `card:true`。
   前端据服务端**既有字段**换用「打出」句式 + 卡牌徽章，不新增协议。
   规则作用域对齐既有 `#battle-panel .sk-*` 前缀（#skill-log 位于 #battle-panel 内）。
   ══════════════════════════════════════════════════════════════════════════ */
#battle-panel .sk-card-row { background: rgba(224,169,60,.07); border-radius: var(--r-xs); }
#battle-panel .sk-card {
  display: inline-block; font-size: .66rem; line-height: 1;
  padding: .13rem .34rem; margin: 0 .26rem 0 .1rem; vertical-align: 1px;
  border-radius: 4px; font-weight: 700; color: #1a1206;
  background: #e0a93c; box-shadow: 0 0 0 1px rgba(224,169,60,.45);
}
/* 卡片说明行（`skill_log[].desc`，仅卡片、空则不出行）——弱化，与效果行区分 */
#battle-panel .sk-card-desc {
  flex-basis: 100%; margin: .12rem 0 .06rem; padding-left: .1rem;
  font-size: .76rem; line-height: 1.42; color: var(--tx-3); font-style: italic;
}


/* ══════════════════════════════════════════════════════════════════════════
   批次 2G-B④（2026-09-21）：结算卡 · 终局原因条（提前灭国 vs 计时满局）
   ──────────────────────────────────────────────────────────────────────────
   读 `payload.settlement.victory.reason`（5 种码）→ 人话。仅终局出现，非终局不占位。
   ══════════════════════════════════════════════════════════════════════════ */
#settlement-card .st-reason {
  margin: .1rem 0 .5rem; padding: .34rem .55rem; border-radius: var(--r-xs);
  font-size: .82rem; line-height: 1.4; font-weight: 600;
  color: var(--warn);
  background: rgba(224,169,60,.13); border: 1px solid rgba(224,169,60,.34);
}


/* ══════════════════════════════════════════════════════════════════════════
   EV6-1（T56 响应窗长文案撑爆布局）· 追加覆盖层，回滚 = 删本块
   ──────────────────────────────────────────────────────────────────────────
   根因链：body 改 display:grid 但没写 grid-template-columns → 单条隐式 auto 轨
   取所有行项目 min-content 最大值 → #controls .hint 的 nowrap 长文案（含完整命令
   路径，单行 700px+）把 header 的 min-content 撑爆 → 整页跟着变宽，#battle-panel
   出屏（1024 视口实测 right=1044）。处置：hint 可收缩截断 + header 及其每个直接
   子项 min-width:0（对应 markup：.hd-brand / #phase-rail / .hd-right）。 */
#controls .hint {
  min-width: 0; max-width: 30vw;
  overflow: hidden; text-overflow: ellipsis;
}
header { min-width: 0; overflow: hidden; }
.hd-brand, #phase-rail, .hd-right { min-width: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   EV6-2（bsp 演出双溢出）· 追加覆盖层，回滚 = 删本块
   ──────────────────────────────────────────────────────────────────────────
   ① 横向：.bsp-cards 是 1fr 260px 1fr，但两侧 .bsp-hp/.bsp-tags 写死 width:430px
      → 1fr 轨 min-content=430 → 实际 430/260/430=1156px，塞进 max-width:96vw 的
      .bsp-stage（Pad 竖屏 1024 时溢出 173px）。处置：1fr 改 minmax(0,1fr)、
      430px 改 min(430px,100%)。
   ② 垂直：.bsp-tags 逐行追加使 .bsp-stage 总高变大 → #bsp flex 再居中 → 卡牌上顶。
      处置：tags 定高 150px 内部滚动（锚底），JS 追加后滚到最新（host.js）。
   ③ 保险：.bsp-stage 限高 94vh 收成纵向 flex —— 矮视口也不出屏。 */
.bsp-cards { grid-template-columns: minmax(0, 1fr) 260px minmax(0, 1fr); }
.bsp-hp   { width: min(430px, 100%); }
.bsp-tags {
  width: min(430px, 100%);
  height: 150px;                 /* 定高锚底：播报再多不再撑高 .bsp-stage */
  overflow-y: auto;
  /* ★ 不用 justify-content:flex-end：列向 flex 容器里 flex-end 造成的「顶端溢出」
     落在不可滚动区（CSS Overflow 规范只扩 end 侧），前几行会永久看不到。
     用首行 margin-top:auto 复刻「内容不足时锚底」——溢出时 margin 归 0，
     溢出方向落在可滚动的 end 侧，配合 JS scrollTop=scrollHeight 恒见最新行。 */
}
.bsp-tags .bsp-tagline:first-child { margin-top: auto; }

.bsp-stage {
  max-height: 94vh;
  display: flex; flex-direction: column;
}
.bsp-stage .bsp-head { flex: 0 0 auto; }
.bsp-stage .bsp-cards { flex: 0 0 auto; }
.bsp-stage .bsp-result { flex: 0 0 auto; }


/* ══════════════════════════════════════════════════════════════════════════
   EV-88PAD（2026-09-28 · 序号425）· 8.8 寸 Pad 大屏自适应 · 追加覆盖层，回滚 = 删本块
   ──────────────────────────────────────────────────────────────────────────
   A1 · bsp 演出高度自适应：卡图/播报区原为定高（372/268/150px），内容恒 ≈666px，
        在矮视口（vh≤770）下伤害/结果行溢出屏底。改 min(px, vh) 自限 —— 不加媒体查询，
        1920×1080 下 36vh=389>372，取值不变，桌面零变化。
   A2 · 顶栏适配（≤1366 阶段轨缩字号；≤1280 阶段轨隐藏 + header 解除 52px 定高，
        让 #controls 折行可见不再被裁）。
   B  · #stage 固定四列在窄视口下地图被挤报废（1024 只剩 268px、800 竖屏仅 44px），
        给 1280/1024 两档收列宽；≤920 复活被 :1055 display:grid 覆盖的竖排断点。
   ★ 以上全部带媒体查询或 min() 自限，1920 桌面布局不受任何影响。
   ══════════════════════════════════════════════════════════════════════════ */

/* A1 · bsp 高度自适应（为 8.8 寸 Pad 适配；1920 桌面不受影响——min() 在大视口取原定高） */
.bsp-card img { height: min(372px, 36vh); }
.bsp-card.hero img { height: min(268px, 26vh); }
.bsp-tags { height: min(150px, 16vh); }

/* A2 · 顶栏：≤1366 阶段轨隐藏 —— 实测 1480 档的 11px 下 rail 已溢出 58px，缩到 10px 仍溢出 42px
   （「收尾」li 压住 #phase 徽章），窄档救不回来；#phase 徽章已显示当前阶段名，rail 冗余让位。
   （8.8 寸 Pad 适配；1920 桌面不受影响） */
@media (max-width: 1366px) {
  #phase-rail { display: none; }
}
/* A2 · 顶栏：≤1280 header 解除 52px 定高，#controls 折行可见不再被裁（8.8 寸 Pad 适配；1920 桌面不受影响） */
@media (max-width: 1280px) {
  header { height: auto; min-height: 52px; }
}
/* B · #stage：≤1280 收席位/战报列宽，把宽度还给地图（8.8 寸 Pad 适配；1920 桌面不受影响） */
@media (max-width: 1280px) {
  #stage { grid-template-columns: 120px minmax(0, 1fr) 120px 320px; gap: 6px; }
}
/* B · #stage：≤1024 再收一档，地图列（第 2 列）用 minmax 拿剩余宽（8.8 寸 Pad 适配；1920 桌面不受影响） */
@media (max-width: 1024px) {
  #stage { grid-template-columns: 100px minmax(0, 1fr) 100px 280px; }
}
/* B · #stage：≤920 竖排堆叠 —— 复活 :290 死断点的意图（:1055 的 display:grid 在其后覆盖了它，
   故本条必须写在文件后部以维持覆盖关系）（8.8 寸 Pad 适配；1920 桌面不受影响） */
@media (max-width: 920px) {
  #stage { display: flex; flex-direction: column; }
  #battle-panel { flex: 0 0 auto; width: 100%; max-height: 60vh; }
}





/* ══════════════════════════════════════════════════════════════════════════
   EV-HOSTTOP（2026-09-28 · 序号428）· Pad 顶栏重排（A 档两行分工）· 追加覆盖层，回滚 = 删本块
   ──────────────────────────────────────────────────────────────────────────
   现状（ev_hosttop_r1 真浏览器量化）：1080×675 下 h1 被 #room-code 的
   --fs-2xl+.3em 挤成两行；#controls 自然折成两行且基线错位 1px、select 比按钮
   高 2px、行右端悬空 296px。本块做「两行分工」重排：
     行1 = 标题 + 房码 ｜ 阶段徽章（右对齐）
     行2 = 全部按钮单行（实测 ~590px，1080/1024 均容得下）+ 响应窗控件右收
   基座两条（媒体查询外）：#phase 移出 .hd-right 后用 auto margin 复刻原
   「随按钮组右对齐」的桌面位置 —— margin-right:-0.2rem 把 header gap 1rem
   补回原组内 gap .8rem，1920 桌面 boundingBox 逐项零变化。
   ★ 所有结构性规则锁在 ≤1120；≤1280 仅加「等高/基线/列距」无结构修正。
   ══════════════════════════════════════════════════════════════════════════ */

/* 序号428 基座：#phase 成为 header 直接子元素后，复刻 1920 桌面原位置（零变化） */
#phase { margin-left: auto; margin-right: -0.2rem; }
.hd-right { margin-left: 0; }

/* 序号428 · ≤1280：select 与按钮统一高 26px、基线对齐、列距统一 8px
   （不改变单行结构，仅消除 1-2px 基线错位；1920 桌面不受影响） */
@media (max-width: 1280px) {
  #controls { gap: 8px; }
  #controls button, #controls select { height: 26px; box-sizing: border-box; }
  /* span 内 select/按钮原是 inline 基线对齐（差 1px）——改 flex 居中 + 与列距同宽 */
  #resp-control { display: inline-flex; align-items: center; gap: 8px; }
}

/* 序号428 Pad 顶栏重排（≤1120）：两行分工；1920 桌面不受影响 */
@media (max-width: 1120px) {
  header { flex-wrap: wrap; row-gap: 8px; padding: .45rem var(--pad-page); }
  .hd-brand { flex: 0 0 auto; }
  /* 行1 右端：阶段徽章（收复基座的 -0.2rem 补偿） */
  #phase { margin-right: 0; min-width: 0; }
  /* 行2：按钮群整行落下（flex-basis 100% 强制换行），单行不折；
     #controls 撑满整行，#resp-control 的 auto margin 才有剩余空间可右收 */
  .hd-right { flex: 1 1 100%; }
  #controls { flex-wrap: nowrap; gap: 8px; flex: 1 1 auto; }
  /* 响应窗控件右收；条件按钮（继续/开始/掷签）hidden 时 flex 自然补位不留洞 */
  #resp-control { margin-left: auto; }
  /* 标题不换行；房码降一级字号防挤压 */
  header h1 { white-space: nowrap; }
  #room-code { font-size: var(--fs-lg); letter-spacing: .2em; }
}
