/* 雀定三国 —— 吞食天地画风（90 年代日式街机三国）
   黑漆底 + 金色双线框 + 大号等宽数字 + 朱红主按钮 + 硬投影 + 近直角
   手机竖屏优先：390×844 为主，375×667 为下限 */

:root {
  --lacquer: #0C0906;
  --panel:   #171108;
  --panel-2: #0E0A06;
  --gold:    #E8A33D;
  --gold-hi: #F8C860;
  --gold-dim:#8A6420;
  --crimson: #C42B20;
  --crim-hi: #E04A34;
  --paper:   #F6EAD0;
  --ink:     #141210;
  --blue:    #2F6DE0;
  --green:   #12A05C;
  --red:     #E23B30;
  --felt:    #12241C;
  --pad: 10px;
  --tile-w: 44px;
  --tile-h: 58px;
  /* 手游固定设计分辨率：所有布局按这个尺寸写死，再整体等比缩放 */
  --stage-w: 390px;
  --stage-h: 844px;
  /* 尾部必须挂中文字体：Courier New 没有汉字，走到 generic monospace 之后
     系统未必再往下找 —— iOS 上「牌局军令」那个输入框的中文 placeholder
     整排显示成「?」方框（模拟器实拍）。数字仍走 Courier，汉字落到宋体。 */
  --mono: 'Courier New', ui-monospace, 'Songti SC', 'STSong', 'PingFang SC', monospace;
  --serif: 'Kaiti SC', 'STKaiti', 'Songti SC', 'STSong', serif;
}

* { box-sizing: border-box; margin: 0; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }

html, body {
  height: 100%; overflow: hidden;
  background: #060403;
  display: flex; align-items: center; justify-content: center;
  color: var(--paper);
  font-family: var(--serif);
  overscroll-behavior: none;
  user-select: none;
}

/* ═══════════ 固定分辨率舞台 ═══════════
   游戏永远按 390×844 排版，由 JS 算出缩放比整体居中。
   这样手机 / 平板 / 桌面看到的构图完全一致（手游做法）。 */
#stage {
  position: relative; flex: none;
  width: var(--stage-w); height: var(--stage-h);
  transform-origin: 50% 50%;
  overflow: hidden;
  background: var(--lacquer);
  background-image:
    radial-gradient(140% 55% at 50% -8%, rgba(232,163,61,.09), transparent 62%),
    repeating-linear-gradient(135deg, rgba(255,255,255,.012) 0 2px, transparent 2px 7px);
  box-shadow: 0 0 0 1px #241A0E, 0 24px 70px rgba(0,0,0,.9);
}
#shake-root { position: relative; z-index: 1; height: 100%; will-change: transform; }

/* 场景淡底：当前郡县的画，铺在整个舞台后面 */
.scene-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-size: cover; background-position: 50% 42%;
  opacity: 0; transition: opacity .6s ease;
}
.scene-bg::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(12,9,6,.42), rgba(12,9,6,.56) 55%, rgba(12,9,6,.70));
}
.scene-bg.on { opacity: .95; }

.screen {
  position: relative;      /* 教学浮层相对这里定位 */
  height: var(--stage-h);
  padding: calc(env(safe-area-inset-top) + 8px) var(--pad) calc(env(safe-area-inset-bottom) + 10px);
  display: flex; flex-direction: column; gap: 7px;
}
/* 牌桌是**定高**的一列 flex，没有滚动 —— 内容一超高，最后那条
   （只留选中/提示/重洗/阵法表/设置）就被顶出屏幕，**点都点不到**。
   实测幕僚位从 6 涨到 8 时，幕僚块多一行 +96px，那条的底边跑到 923px，
   而屏幕只有 887px，elementFromPoint 打在「设置」上返回空。
   所以显式指定谁来吃挤压：牌桌区（felt）可收缩，其余各条钉死。
   这样即使以后某种语言的文案更高、或者屏幕更短，被压缩的也是牌面留白，
   而不是把操作按钮推出可视区。 */
.scr-table > .felt { flex: 1 1 auto; min-height: 0; }
.scr-table > .top,
.scr-table > .retinue,
.scr-table > .calc,
.scr-table > .counts,
.scr-table > .btns { flex: none; }
.overlay {
  position: absolute; inset: 0; z-index: 40; height: var(--stage-h);
  background: rgba(6,4,3,.72);
  backdrop-filter: blur(1.5px);
  align-items: center; justify-content: center;
}

/* ═══════════ 吞食天地式 黑底金双线框 ═══════════ */
.frame {
  border: 3px solid var(--gold);
  box-shadow: inset 0 0 0 2px var(--panel-2), inset 0 0 0 3px var(--gold-dim),
              4px 4px 0 rgba(0,0,0,.9);
  background: linear-gradient(180deg, rgba(23,17,8,.62), rgba(14,10,6,.70));
  backdrop-filter: blur(2px);
  border-radius: 2px;
  position: relative;
}

/* ═══════════ 按钮 ═══════════ */
.btn {
  appearance: none; cursor: pointer;
  border: 3px solid var(--gold);
  box-shadow: inset 0 0 0 2px #000, inset 0 0 0 3px var(--gold-dim), 4px 4px 0 #000;
  background: linear-gradient(180deg, rgba(27,18,7,.80), rgba(14,10,5,.86));
  backdrop-filter: blur(2px);
  color: var(--gold-hi);
  font: 900 15px/1 var(--serif);
  letter-spacing: .22em;
  padding: 11px 12px; border-radius: 2px;
  transition: transform .08s, filter .12s;
}
.btn:hover { filter: brightness(1.18); }
.btn:active { transform: translate(3px, 3px); box-shadow: inset 0 0 0 2px #000, inset 0 0 0 3px var(--gold-dim), 1px 1px 0 #000; }
.btn:disabled { opacity: .38; filter: grayscale(.7); cursor: not-allowed; }
.btn-red {
  background: linear-gradient(180deg, #D8402F, #9E211A);
  color: #FFEDD8; border-color: #F0B24A;
  box-shadow: inset 0 0 0 2px #5E1109, inset 0 0 0 3px #F0B24A, 4px 4px 0 #000;
}
.btn-red:active { box-shadow: inset 0 0 0 2px #5E1109, inset 0 0 0 3px #F0B24A, 1px 1px 0 #000; }
.btn-lg { padding: 14px 22px; font-size: 18px; letter-spacing: .3em; }
.btn-sm { padding: 9px 10px; font-size: 13px; letter-spacing: .12em; }
.btn-ghost {
  background: transparent; border-color: transparent; color: var(--gold-dim);
  box-shadow: none; letter-spacing: .1em;
}
.btn-ghost:active { transform: scale(.94); box-shadow: none; }

/* 按钮内嵌剩余次数：提示/重洗这类有限次的动作，次数必须长在按钮上 */
.btn-n {
  display: inline-block; min-width: 15px; margin-left: 5px; padding: 0 2px;
  font: 900 11px/15px var(--mono); font-style: normal; text-align: center;
  color: #1B1207; background: var(--gold-dim); border-radius: 2px; vertical-align: 1px;
}
.btn:not(.btn-ghost) .btn-n { background: var(--gold-hi); }
.btn.spent { opacity: .42; }
.btn.spent .btn-n { background: #6B5A3C; color: #221A0E; }

.blink { animation: bl 1.1s steps(2) infinite; }
@keyframes bl { 50% { opacity: .2 } }

/* ═══════════ 标题页 ═══════════ */
.scr-title { justify-content: center; align-items: center; gap: 10px; text-align: center; }
.title-art {
  width: 100%; max-width: 340px; aspect-ratio: 16/9;
  border: 3px solid var(--gold); box-shadow: inset 0 0 0 2px #000, 5px 5px 0 rgba(0,0,0,.9);
  background: #0E0A06 50% 40%/cover no-repeat; overflow: hidden;
}
.title-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.game-title {
  font: 900 44px/1 var(--serif); letter-spacing: .14em; color: var(--gold-hi);
  text-shadow: 3px 3px 0 #000, 0 0 22px rgba(232,163,61,.35);
}
.game-sub { color: var(--gold); letter-spacing: .52em; font-size: 12px; margin-top: 6px; }
.title-rule { padding: 10px 12px; text-align: left; max-width: 340px; width: 100%; font-size: 12.5px; line-height: 1.75; }
.title-rule b { color: var(--gold-hi); display: block; margin-bottom: 3px; letter-spacing: .18em; }
.title-rule em { color: var(--crim-hi); font-style: normal; font-weight: 900; }
/* 难度三档：标题页选一次，开局后不再变 */
.diff-row {
  display: grid; grid-template-columns: auto 1fr; gap: 4px 8px; align-items: center;
  max-width: 340px; width: 100%; font-size: 12px; color: #A08A5E; letter-spacing: .08em;
}
.diff-label { grid-column: 1; }
.diff-picks { grid-column: 2; display: flex; gap: 5px; }
.diff-pick { flex: 1; padding: 6px 0; font-size: 12px; letter-spacing: .12em; opacity: .55; }
.diff-pick.on {
  opacity: 1; color: var(--gold-hi); border-color: var(--gold-hi);
  box-shadow: inset 0 0 0 1px var(--gold-hi);
}
.diff-desc {
  grid-column: 1 / -1; margin: 0; min-height: 1.4em;
  font: 400 10.5px/1.4 var(--serif); letter-spacing: .02em; color: var(--gold-dim);
}
.seed-row {
  display: flex; align-items: center; gap: 8px; font-size: 12px; color: #A08A5E;
  max-width: 340px; width: 100%; letter-spacing: .08em;
}
.seed-row span { flex: none; }
.seed-help {
  flex: none; width: 22px; height: 22px; border-radius: 50%; cursor: pointer;
  border: 2px solid var(--gold-dim); background: transparent; color: var(--gold);
  font: 900 12px/1 var(--serif); padding: 0;
}
.seed-help:active { transform: scale(.92); }
.seed-row input {
  flex: 1; min-width: 0; background: #0A0705; border: 2px solid var(--gold-dim);
  /* 这里原来用 --mono，而军令是中文（placeholder「留空＝随机开局」、
     种子本身也能填「赤壁」）—— iOS 上整排渲染成「?」方框（模拟器实拍确认）。
     等宽对一个 16 字的短输入没有价值，换回正文字体。 */
  color: var(--paper); padding: 8px 9px; font: 15px/1.2 var(--serif); border-radius: 0;
}
/* 换语言后按钮变长（March / Continue / Scoring / Debug），390px 一行放不下 */
.title-btns { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: center; }
.title-btns .btn { white-space: nowrap; }
.title-btns .btn-lg { padding: 13px 18px; letter-spacing: .16em; }
/* 「文 / A」和「调试」是次级入口，缩小并排在一行末尾 */
.title-btns #btn-lang { padding: 8px 10px; letter-spacing: .06em; }
.press-start { font: 900 11px/1 var(--serif); color: var(--gold); letter-spacing: .35em; }
.credit { font-size: 9.5px; color: #5A4A33; line-height: 1.6; max-width: 320px; letter-spacing: .04em; }

/* ═══════════ 剧情 ═══════════ */
.scr-story { padding: 0; }
.story-box { width: min(360px, 94vw); display: flex; flex-direction: column;
  gap: 10px; align-items: stretch; }
.story-chapter { text-align: center; animation: chIn .6s ease-out; }
@keyframes chIn { from { opacity: 0; transform: translateY(-10px) } }
/* 注意：这三条必须比 `.story-chapter span` 更具体，否则印章会被当成普通副标题 */
.story-chapter .ch-no {
  display: grid; place-items: center; width: 46px; height: 46px; margin: 0 auto 9px;
  border: 3px solid var(--gold); background: var(--crimson);
  font: 900 23px/1 var(--serif); color: var(--paper);
  box-shadow: 4px 4px 0 #000;
}
.story-chapter b { display: block; font: 900 26px/1.2 var(--serif); letter-spacing: .16em; color: var(--gold-hi); text-shadow: 2px 2px 0 #000; }
.story-chapter .ch-sub { display: block; font-size: 11.5px; color: var(--gold-dim); letter-spacing: .16em; margin-top: 7px; }
.story-portrait { display: flex; justify-content: center; }
.story-portrait img {
  width: 150px; height: 150px; object-fit: cover; object-position: 50% 16%;
  border: 3px solid var(--gold);
  box-shadow: inset 0 0 0 2px #000, 5px 5px 0 rgba(0,0,0,.92);
  animation: picIn .32s cubic-bezier(0.22,1,0.36,1);
}
@keyframes picIn { from { opacity: 0; transform: translateY(8px) scale(.94) } }

/* 一句一屏：说话人名牌 + 正文 */
.story-name {
  display: inline-block; margin-bottom: 8px; padding: 4px 12px;
  border: 2px solid var(--gold); background: var(--crimson);
  font: 900 13px/1 var(--serif); letter-spacing: .16em; color: var(--paper);
  box-shadow: 3px 3px 0 #000;
}
.story-body { font-size: 15px; line-height: 1.95; min-height: 3.9em; }
.story-body.narration { color: #C0AE90; }
.story-body.accent { color: var(--crim-hi); font-weight: 900; }
.story-body.seal { color: var(--gold-hi); letter-spacing: .06em; }
.story-count { font: 900 10px/1 var(--mono); color: var(--gold-dim); letter-spacing: .1em; }
.story-text { padding: 14px 15px; min-height: 132px; text-align: left; font-size: 14.5px; line-height: 2;
  box-shadow: inset 0 0 0 2px var(--panel-2), inset 0 0 0 3px var(--gold-dim), 6px 6px 0 rgba(0,0,0,.92); }
.story-line { margin-bottom: 9px; }
.story-line:last-child { margin-bottom: 0; }
.story-who { color: var(--gold-hi); font-weight: 900; letter-spacing: .1em; margin-right: 6px; }
.story-who::after { content: '：'; }
.story-line.narration { color: #A9987C; font-size: 13.5px; }
.story-line.accent { color: var(--crim-hi); font-weight: 900; }
.story-line.seal { color: var(--gold-hi); letter-spacing: .08em; }
.story-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 0 2px; }
#story-next { font-size: 12px; color: var(--gold); letter-spacing: .2em; }

/* ═══════════ HUD ═══════════ */
.hud { display: flex; justify-content: space-between; align-items: center; padding: 7px 11px; gap: 8px; }
.hud-stage b { display: block; font: 900 15px/1.2 var(--serif); letter-spacing: .12em; color: var(--gold-hi); }
.hud-stage small { display: block; font-size: 9px; color: var(--gold-dim); letter-spacing: .34em; margin-top: 3px; }
.hud-nums { display: flex; gap: 11px; align-items: baseline; }
.nm { text-align: right; }
.nm span { display: block; font-size: 9px; color: var(--gold-dim); letter-spacing: .18em; margin-bottom: 2px; }
.nm b { font: 900 21px/1 var(--mono); color: var(--gold-hi); text-shadow: 2px 2px 0 #000; }
.nm .v-score { color: var(--paper); }
.nm .v-gold { color: var(--gold); }

.hpbar {
  height: 15px; border: 2px solid var(--gold); background: #1A0F0A;
  box-shadow: inset 0 0 0 1px #000; position: relative; overflow: hidden;
}
.hpbar i {
  display: block; height: 100%; width: 0;
  background: repeating-linear-gradient(90deg, var(--crimson) 0 7px, var(--crim-hi) 7px 9px);
  transition: width .45s cubic-bezier(0.22,1,0.36,1);
}
.hpbar em {
  position: absolute; right: 5px; top: 0; font: 900 10px/15px var(--mono);
  color: var(--gold-hi); font-style: normal; text-shadow: 1px 1px 0 #000;
}

/* 锁定生效中：规矩条转成告警色，提醒「现在真的被限制着」 */
.rule-strip.locked { border-color: var(--crim-hi); }
.rule-strip.locked .rule-tag { background: var(--crimson); color: #FFE9C8; }
.rule-strip.locked .rule-txt span { color: #FFC9B0; }

/* ═══════════ 诸侯条 ═══════════ */
.boss-strip { display: flex; gap: 9px; align-items: center; padding: 6px 9px; border-color: var(--crim-hi); }
.boss-mini img {
  width: 42px; height: 42px; object-fit: cover; object-position: 50% 10%;
  border: 2px solid var(--gold); display: block;
}
.boss-txt { flex: 1; min-width: 0; }
.boss-txt b { font: 900 14px/1.2 var(--serif); color: #F2C0BB; letter-spacing: .08em; }
.boss-txt span { display: block; font-size: 10.5px; color: #B79C74; line-height: 1.5; margin-top: 3px; }
.boss-tag {
  writing-mode: vertical-rl; font: 900 10px/1 var(--serif); letter-spacing: .25em;
  color: var(--crim-hi); border: 1px solid var(--crim-hi); padding: 5px 2px; background: rgba(196,43,32,.1);
}

/* ═══════════ 幕僚槽 ═══════════ */
.retinue { padding: 6px 8px 8px; }
.retinue-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font: 900 11px/1 var(--serif); letter-spacing: .3em; color: var(--gold-hi); margin-bottom: 6px;
}
.retinue-head b { font: 900 12px/1 var(--mono); color: var(--gold); letter-spacing: .06em; }
/* 满位：计数变红，配合货架标题上的「先辞退一位」 */
.retinue-head b.full { color: #ff9a6a; }
/* 3 列 × 2 行，头像做大到能看清脸 */
/* 幕僚块：左 3×2 大头像，右侧一竖条放锦囊（两行的最右边留给道具） */
.retinue-body { display: grid; grid-template-columns: 1fr 54px; gap: 6px; align-items: start; }
.slots { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 86px; gap: 5px; }
.charm-col { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.cc-head { font: 900 9px/1 var(--serif); letter-spacing: .14em; color: var(--gold-hi); margin-bottom: 1px; }
.charm-col .charms-list { flex-direction: column; gap: 4px; width: 100%; align-items: center; }
.charm-col .charm, .charm-col .charm-empty { width: 50px; height: 50px; }
.charm-col .charm .tip { left: auto; right: 100%; bottom: auto; top: 0; margin: 0 6px 0 0; transform: none; }
.slot-empty {
  border: 2px dashed #4A3A26; display: grid; place-items: center;
  color: #4A3A26; font: 900 10px/1 var(--serif); letter-spacing: .18em;
}
.item-chip {
  position: relative; cursor: pointer;
  transition: transform .18s cubic-bezier(0.22,1,0.36,1);
}
.slots .item-chip .face { width: 100% !important; height: 100% !important; }
.item-chip .name {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3; text-align: center;
  font: 900 9.5px/1.3 var(--serif); color: var(--paper); letter-spacing: .02em;
  background: linear-gradient(180deg, transparent, rgba(6,4,3,.94) 40%);
  padding: 7px 0 1px; text-shadow: 1px 1px 0 #000;
  white-space: nowrap; overflow: hidden;
}
.item-chip.perk .face { box-shadow: inset 0 0 0 1px #000, 0 0 0 2px var(--gold-hi), 3px 3px 0 rgba(0,0,0,.85); }

/* 传承牌：另起一行小图标，不占幕僚位 */
.perks { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 6px; padding-top: 6px; border-top: 1px solid #3A2E1A; }
/* 「传承」标签改成真元素（原来是 CSS content 硬编码，翻不了也没法挂说明） */
.perks-label {
  position: relative; cursor: help;
  font: 900 9px/26px var(--serif); letter-spacing: .2em; color: var(--gold-dim); margin-right: 2px;
  border-bottom: 1px dotted var(--gold-dim);
}
.perks-label:hover .tip { opacity: 1; }
.perks-label .tip {
  position: absolute; left: 0; bottom: 100%; margin-bottom: 6px; width: 188px; z-index: 24;
  background: #0A0705; border: 2px solid var(--gold); padding: 6px 8px;
  font: 700 10.5px/1.55 var(--serif); color: var(--paper); letter-spacing: .02em;
  box-shadow: 3px 3px 0 #000; opacity: 0; pointer-events: none; transition: opacity .14s;
  text-align: left; white-space: normal;
}
.perks-label .tip b { display: block; color: var(--gold-hi); margin-bottom: 3px; letter-spacing: .1em; }
.perks .item-chip { width: 30px; height: 30px; }
.perks .item-chip .face { width: 30px !important; height: 30px !important; }
.perks .item-chip .face-fac { font-size: 7px; padding: 1px 2px; }
.perks .name { display: none; }
.retinue-sm .slots { grid-template-columns: repeat(6, 1fr); grid-auto-rows: 62px; gap: 4px; }
/* 「连点两次辞退」的说明：夹在标题和计数之间，居中、字小，不跟两头抢地方 */
.retinue-hint {
  flex: 1 1 auto; min-width: 0; text-align: center; cursor: help;
  font: 400 8.5px/1.3 var(--serif); letter-spacing: .04em; color: var(--gold-dim);
}
.retinue-sm .item-chip .name { font-size: 8.5px; padding: 6px 0 1px; }

/* 军备（已激活的消耗牌） */
.armory { display: flex; gap: 6px; align-items: center; padding: 0 2px; }
.armory-chip {
  display: flex; align-items: center; gap: 5px; padding: 2px 8px 2px 2px;
  border: 2px solid var(--gold); background: rgba(232,163,61,.16);
  font: 700 10.5px/1 var(--serif); color: var(--gold-hi); letter-spacing: .04em;
  box-shadow: 2px 2px 0 rgba(0,0,0,.8);
}
.armory-chip .icon { border: 0; box-shadow: none; }
.armory-chip svg { display: block; }

/* ═══════════ 算式区 ═══════════ */
/* 固定 390×844 舞台下，计分区必须有硬上限：
   六位幕僚全触发 + 14 张牌名会把它顶到 226px，牌桌被挤到 130px，手牌直接被切掉。
   超出部分在自己内部滚，绝不外溢。 */
.calc { flex: 0 0 auto; min-height: 0; max-height: 196px; padding: 8px 11px 9px; text-align: center;
        overflow-y: auto; overscroll-behavior: contain; }
.calc.invalid { border-color: var(--crim-hi); }
.calc-name {
  font: 900 18px/1.2 var(--serif); letter-spacing: .18em; color: var(--gold-hi);
  text-shadow: 2px 2px 0 #000; margin-bottom: 7px;
}
.calc.invalid .calc-name { color: var(--crim-hi); }
.calc-row { display: flex; gap: 7px; align-items: stretch; justify-content: center; }
.blk {
  flex: 1; padding: 6px 0 7px; border: 2px solid #000;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.26), 4px 4px 0 #000; min-width: 0;
}
.blk-chip { background: var(--blue); }
.blk-mult { background: var(--crimson); }
.blk small { display: block; font-size: 9px; letter-spacing: .26em; opacity: .88; }
.blk b { font: 900 22px/1.15 var(--mono); text-shadow: 1px 1px 0 rgba(0,0,0,.5); }
.op { align-self: center; font: 900 15px/1 var(--mono); color: var(--gold-dim); }
.calc-total {
  align-self: center; min-width: 84px;
  font: 900 27px/1 var(--mono); color: var(--gold-hi); text-shadow: 2px 2px 0 #000;
}
.calc-hint { font-size: 10.5px; color: #A9987C; margin-top: 6px; letter-spacing: .04em; }
/* 没话说就不占位（原来 min-height:15px 会一直空着一行） */
.calc-hint:empty { display: none; }
/* 读牌行：引擎读到的牌名。字号刻意比提示大一点 —— 它是「牌面到底是几」的唯一权威 */
.calc-read {
  min-height: 16px; white-space: nowrap; overflow-x: auto; overscroll-behavior: contain;
  margin-top: 7px; padding: 2px 0 3px;
  scrollbar-width: none;
  font: 900 12px/1.3 var(--serif); letter-spacing: .1em; color: #E8D6A8;
  border-top: 1px solid #3A2E1A; border-bottom: 1px solid #3A2E1A;
}
.calc-read:empty { display: none; }

/* 分数拆解：每一项各加多少筹码、乘多少倍。颜色沿用筹码=蓝 / 倍率=红 */
/* 六位幕僚全触发时这里会涨到两三行，把牌桌挤得手牌都露不出来。
   390×844 装不下「幕僚两行 + 完整拆解 + 两行手牌」，所以：
   常态压成一行横向滚动（只占 22px），点一下展开成多行细看。
   展开时遮住一点牌桌可以接受 —— 那是玩家主动要看的。 */
.calc-parts {
  display: flex; flex-wrap: nowrap; gap: 2px; justify-content: flex-start; margin-top: 5px;
  overflow-x: auto; overscroll-behavior: contain; scrollbar-width: none; cursor: pointer;
}
.calc-parts::-webkit-scrollbar { display: none; }
.calc-parts.open {
  flex-wrap: wrap; justify-content: center;
  max-height: 76px; overflow-x: hidden; overflow-y: auto;
}
.calc-parts i { flex: none; }
.calc-parts:empty { display: none; }
.calc-parts i {
  display: inline-flex; align-items: baseline; gap: 2px; font-style: normal;
  padding: 1px 4px 2px; border: 1px solid #4A3A26; background: rgba(10,7,5,.5);
  font: 700 9.5px/1.45 var(--serif); letter-spacing: 0; color: #CBB894;
}
.calc-parts i.it { border-color: #7A6540; color: var(--gold-hi); background: rgba(60,40,12,.5); }
.calc-parts b  { font: 900 10px/1 var(--mono); color: #7FB6E8; }
.calc-parts em { font: 900 10px/1 var(--mono); font-style: normal; color: #FF9086; }
.calc.invalid .calc-read { color: #F0C0A0; }

/* ═══════════ 牌桌 ═══════════ */

.felt {
  flex: 1 1 auto; min-height: 160px; padding: 8px 7px 10px; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-end;
  background:
    radial-gradient(115% 72% at 50% 0%, rgba(62,142,110,.24), transparent 66%),
    linear-gradient(180deg, rgba(22,40,31,.50), rgba(18,36,28,.62));
  border-color: var(--gold-dim);
  box-shadow: inset 0 0 0 2px #000, inset 0 2px 16px rgba(0,0,0,.6), 0 3px 0 rgba(0,0,0,.75);
}
.felt-mark {
  position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  font: 900 66px/1 var(--serif); color: rgba(232,163,61,.045); letter-spacing: .3em;
}
.played {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 5px; justify-content: flex-end; padding: 2px 2px 5px;
}
.played::-webkit-scrollbar { display: none; }
.played-empty { margin: auto; font-size: 10.5px; color: #4E6659; letter-spacing: .18em; text-align: center; line-height: 2; }
.played-row { display: flex; align-items: center; gap: 6px; animation: pIn .3s cubic-bezier(0.22,1,0.36,1); }
@keyframes pIn { from { opacity: 0; transform: translateY(-8px) } }
.played-tiles { display: flex; gap: 1.5px; }
.played-tiles .tile { width: 21px; height: 28px; pointer-events: none; box-shadow: 2px 2px 0 #000;
  border-width: 1.5px; padding: 1.2px; border-radius: 3px; }
.played-meta { font-size: 10px; color: #8FA79A; white-space: nowrap; }
.played-meta b { color: var(--gold); font: 900 12px/1 var(--mono); }

.wall-strip {
  display: flex; align-items: center; gap: 6px; justify-content: center;
  font-size: 9px; color: #5E7368; letter-spacing: .18em; margin-bottom: 6px;
}
/* 牌墙余量：刻意做成 3px 细轨。
   它和顶部 15px 的得分进度条本是两回事（一个是打到目标分多少、一个是牌还剩多少），
   但先前两条都是等宽格子条，扫一眼像同一个东西重复了两遍 —— 降权到细线即可。 */
.wall-track {
  flex: 0 1 118px; height: 3px; background: #1B3025;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.6); overflow: hidden;
}
.wall-track b {
  display: block; height: 100%; width: 100%; background: var(--green);
  transition: width .32s cubic-bezier(0.22,1,0.36,1);
}

.hand { display: flex; flex-wrap: wrap; align-content: flex-end; justify-content: center; gap: 6px 4px; }

/* ═══════════ 牌 ═══════════ */
.tile {
  width: var(--tile-w); height: var(--tile-h); flex: none;
  border: 3px solid var(--ink); border-radius: 5px;
  box-shadow: 4px 4px 0 #000;                 /* 黑框式硬投影，立体感的来源 */
  background: var(--paper);
  /* 原版 p-[6%] 的 6% 是相对牌宽；CSS 的百分比 padding 会按父容器宽解析，
     所以这里必须用 calc 显式按牌宽算，否则牌面会被挤没。 */
  padding: calc(var(--tile-w) * 0.06);
  cursor: pointer; position: relative; overflow: hidden;
  transition: transform .12s cubic-bezier(0.22,1,0.36,1), box-shadow .12s;
}
.tile .tile-svg { width: 100%; height: 100%; display: block; }
.tile:hover { transform: translate(-1px,-4px); box-shadow: 6px 7px 0 #000; }
.tile:active { transform: translate(3px,3px); box-shadow: 1px 1px 0 #000; }
.tile.selected {
  transform: translateY(-12px);
  border-color: var(--gold-hi);
  box-shadow: 0 0 0 2px var(--gold-hi), 5px 8px 0 #000, 0 0 16px rgba(248,200,96,.45);
}
/* 封住的牌：不能打出，但可以选中舍掉，所以光标仍是可点的 */
.tile.sealed { cursor: pointer; filter: saturate(.4); }
.tile.sealed.selected { border-color: var(--crim-hi); box-shadow: 0 0 0 2px var(--crim-hi), 5px 8px 0 #000; }
.tile.hinted::after {
  content: ''; position: absolute; inset: 0; border: 3px solid var(--green);
  animation: hp .9s steps(2) infinite; pointer-events: none;
}
@keyframes hp { 50% { opacity: .25 } }

/* ═══════════ 计数 / 按钮组 ═══════════ */
/* 换到拉丁语言后这一行会溢出（Plays / Discards / Hints / Reshuffle 比中文长一倍），
   所以允许折行并把字距收紧。 */
.counts {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 3px 10px;
  font-size: 10px; color: var(--gold-dim); letter-spacing: .06em;
}
.counts .cnt { white-space: nowrap; }
.cnt b { color: var(--gold-hi); font: 900 14px/1 var(--mono); margin-left: 2px; }
.btns { display: flex; gap: 7px; }
.btns .btn { flex: 1; }
.btns .btn-play { flex: 1.7; font-size: 17px; }
.btns-sub { justify-content: center; gap: 2px; }
/* 五个次级按钮要在 390px 里一行排完，且自身不能折行
   （「只留选中」「阵法表」原本就被挤成两行，加了次数徽标后更明显） */
.btns-sub .btn {
  flex: 0 1 auto; white-space: nowrap;
  padding: 9px 5px; font-size: 12px; letter-spacing: .02em;
}
.btns-sub .btn-n { min-width: 13px; margin-left: 3px; font-size: 10px; line-height: 14px; }

/* ═══════════ 面板 ═══════════ */
.panel {
  width: min(342px, 93vw); padding: 17px 16px; text-align: center;
  box-shadow: inset 0 0 0 2px var(--panel-2), inset 0 0 0 3px var(--gold-dim), 7px 7px 0 rgba(0,0,0,.92);
  display: flex; flex-direction: column; gap: 11px;
  /* 按**舞台**高度封顶，不是按 dvh。dvh 是浏览器视口，而舞台是缩放过的：
     视口比舞台高时（横屏 720 的舞台放在 1080 的屏上）面板会长过舞台被裁掉。
     百分比相对 .screen.overlay，而它的高度就是 --stage-h。 */
  max-height: 88%; overflow-y: auto;
}
.panel-scroll { max-height: 82%; }
.panel-title {
  font: 900 23px/1 var(--serif); letter-spacing: .3em; color: var(--gold-hi);
  text-shadow: 2px 2px 0 #000;
}
.settle-rows { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; }
.settle-row { display: flex; justify-content: space-between; color: #A9987C; letter-spacing: .06em; }
.settle-row b { color: var(--gold-hi); font-family: var(--mono); }
.settle-total { font: 900 17px/1 var(--serif); color: var(--gold-hi); letter-spacing: .1em; }
.settle-total b { font-family: var(--mono); font-size: 22px; }
.hu-banner {
  border: 3px solid var(--gold-hi); background: rgba(196,43,32,.28); padding: 9px;
  font: 900 15px/1.5 var(--serif); letter-spacing: .12em; color: var(--gold-hi);
  animation: huIn .5s cubic-bezier(0.22,1,0.36,1);
}
@keyframes huIn { from { opacity: 0; transform: scale(.8) rotate(-3deg) } }
.hu-banner small { display: block; font-size: 11px; color: var(--paper); letter-spacing: .04em; margin-top: 4px; font-weight: 400; }
.over-lines { font-size: 13px; line-height: 1.95; color: #A9987C; }
.over-lines p { margin-bottom: 5px; }
.switch { display: flex; align-items: center; gap: 9px; font-size: 13.5px; color: #A9987C; letter-spacing: .08em; }

/* ═══════════ 诸侯登场 ═══════════ */
.boss-card {
  width: min(348px, 94vw); display: flex; flex-direction: column; align-items: center; gap: 10px;
  animation: bossIn .5s cubic-bezier(0.22,1,0.36,1);
}
@keyframes bossIn { from { opacity: 0; transform: scale(.88) } }
.boss-big-pic {
  width: 100%; height: 210px; border: 3px solid var(--gold);
  box-shadow: inset 0 0 0 2px #000, 6px 6px 0 rgba(0,0,0,.92); overflow: hidden; background: #0E0A06;
}
.boss-big-pic img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 14%; display: block; }
.boss-head { display: flex; gap: 12px; align-items: center; width: 100%; }
.boss-plate { flex: none; }
.boss-plate svg { display: block; height: 92px; width: 32px; }
.boss-head h2 { font: 900 29px/1 var(--serif); letter-spacing: .16em; color: var(--gold-hi); text-shadow: 3px 3px 0 #000; }
.boss-big-title { color: var(--gold); letter-spacing: .3em; font-size: 11px; margin-top: 7px; }
.boss-story { padding: 11px 13px; font-size: 13px; line-height: 1.95; color: #C9B48F; width: 100%; text-align: left; }
.boss-story p { margin-bottom: 5px; }
.boss-story p:last-child { margin-bottom: 0; }
.boss-rule-box {
  border: 2px solid var(--crim-hi); background: rgba(196,43,32,.14);
  padding: 8px 11px; font-size: 12px; line-height: 1.6; width: 100%; text-align: left;
}
.boss-rule-box b { color: var(--crim-hi); margin-right: 8px; letter-spacing: .14em; }

/* ═══════════ 市集 ═══════════ */
.shop-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 7px; }
.shop-scroll::-webkit-scrollbar { display: none; }
.shop-h {
  font: 900 14px/1 var(--serif); letter-spacing: .3em; color: var(--gold-hi);
  border-bottom: 2px solid var(--gold-dim); padding-bottom: 6px; margin-top: 4px;
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
}
/* <i> 是标题本身：英文比中文长得多（RETAINERS vs 幕僚），不给它 flex-shrink:0
   就会被右边那行小字挤出可视区 —— 实测英文截图里显示成「ETAINERS」「ROVISIONS」，
   首字母整个被切掉。标题不许压缩，要压缩就压右边那行小字（它已经能换行）。 */
.shop-h > i { flex: 0 0 auto; font-style: normal; }
/* 标题右侧那行小字有时挺长（「XX旧部已上架 · 最多带 7 位」/满位提示），
   原先它会被右边框切掉 —— 允许收缩换行，别让文案丢字。 */
.shop-h small {
  font-size: 9.5px; color: var(--gold-dim); letter-spacing: .1em; font-weight: 400;
  flex: 0 1 auto; min-width: 0; text-align: right; line-height: 1.35; padding-right: 2px;
}
.shop-h small.warn { color: #ff9a6a; letter-spacing: .04em; font-weight: 700; }
.shop-list { display: flex; flex-direction: column; gap: 6px; }
/* 招贤令并在锦囊后面，两块之间只留一个间距，不再各自起一节 */
#shop-charms + #shop-pack { margin-top: 6px; }
.shop-card {
  display: flex; gap: 9px; align-items: center; text-align: left; padding: 8px 9px;
  border: 2px solid var(--gold-dim);
  background: linear-gradient(180deg, rgba(23,17,8,.68), rgba(14,10,6,.76));
  backdrop-filter: blur(2px);
  box-shadow: 4px 4px 0 rgba(0,0,0,.85);
}
.shop-card.loot { border-color: var(--crim-hi); }
.shop-card.sold { opacity: .35; }
.shop-card.cant { opacity: .55; }
.shop-body { flex: 1; min-width: 0; }
.shop-name { font: 900 14.5px/1.2 var(--serif); letter-spacing: .06em; color: var(--paper); }
.tag {
  font-size: 9px; padding: 1px 5px; margin-left: 5px; vertical-align: 1.5px;
  border: 1px solid currentColor; letter-spacing: .06em; font-weight: 400;
}
.t-common { color: #A9987C; } .t-rare { color: #79B0F0; }
.t-legendary { color: var(--gold-hi); } .t-mythic { color: #F08A80; }
.t-loot { color: var(--crim-hi); background: rgba(196,43,32,.16); }
.shop-desc { font-size: 11px; color: #A9987C; line-height: 1.55; margin-top: 3px; }
.shop-story { font-size: 10px; color: #6E5F45; line-height: 1.5; margin-top: 3px; }
/* 典故引文（锦囊/军备）：和幕僚卡的本人小传区分开 */
.shop-story.quote { border-left: 2px solid #7A6540; padding-left: 5px; color: #877455; }
.shop-price { flex: none; }
.shop-note { text-align: center; font-size: 10px; color: var(--gold-dim); letter-spacing: .1em; padding: 6px 0 2px; }

/* ═══════════ 阵法表 ═══════════ */
.help-row { display: flex; gap: 10px; align-items: center; text-align: left; padding: 7px 0; border-bottom: 1px solid #3A2E1A; }
.help-row:last-of-type { border-bottom: 0; }
.help-tiles { display: flex; gap: 2px; }
.help-tiles .tile { width: 26px; height: 35px; pointer-events: none; box-shadow: 2px 2px 0 #000;
  border-width: 2px; padding: 1.5px; border-radius: 3px; }
.help-meta { flex: 1; }
.help-meta b { font-size: 13.5px; color: var(--paper); }
.help-meta span { display: block; font-size: 10.5px; color: #A9987C; margin-top: 2px; }
.help-meta .val { color: var(--gold-hi); font-family: var(--mono); font-weight: 900; }
.help-intro { font-size: 12px; line-height: 1.85; color: #A9987C; text-align: left; }
.help-intro b { color: var(--crim-hi); }

/* ═══════════ FX ═══════════ */
#fx-layer { position: absolute; inset: 0; pointer-events: none; z-index: 80; }
.pop {
  position: absolute; transform: translate(-50%,-50%) scale(.4);
  font: 900 19px/1 var(--mono); color: var(--gold-hi);
  text-shadow: 2px 2px 0 #000, 0 0 12px rgba(232,163,61,.55); white-space: nowrap;
  animation: popIn .22s cubic-bezier(0.22,1,0.36,1) forwards;
}
@keyframes popIn {
  0% { transform: translate(-50%,-50%) scale(0) }
  70% { transform: translate(-50%,-50%) scale(1.16) }
  100% { transform: translate(-50%,-50%) scale(1) }
}
.pop.crit { font-size: 31px; color: #FFD874; text-shadow: 0 0 22px rgba(255,216,116,.95), 3px 3px 0 #000; }
.pop.chips { color: #7FB6E8; font-size: 16px; }
.pop.mult  { color: #FF7A6E; font-size: 16px; }
.pop.gold  { color: var(--gold); font-size: 15px; }
.pop.small { font: 900 12px/1 var(--serif); color: #C9B48F; }

/* 大牌型全屏毛笔字 */
.meld-banner {
  position: fixed; left: 50%; top: 38%; transform: translate(-50%,-50%) scale(.5);
  font: 900 50px/1 var(--serif); letter-spacing: .18em; color: var(--gold-hi);
  text-shadow: 4px 4px 0 #000, 0 0 30px rgba(232,163,61,.7);
  z-index: 85; pointer-events: none; opacity: 0;
  animation: meldIn .6s cubic-bezier(0.22,1,0.36,1) forwards;
}
@keyframes meldIn {
  0% { opacity: 0; transform: translate(-50%,-50%) scale(.5) rotate(-6deg) }
  30% { opacity: 1; transform: translate(-50%,-50%) scale(1.1) rotate(1deg) }
  70% { opacity: 1; transform: translate(-50%,-50%) scale(1) rotate(0) }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(1.05) }
}
.meld-banner.hu { color: #FFE9A8; font-size: 58px; }

.ring {
  position: absolute; width: 12px; height: 12px; margin: -6px 0 0 -6px;
  border: 2px solid var(--gold); animation: ringOut .5s ease-out forwards;
}
@keyframes ringOut { to { width: 70px; height: 70px; margin: -35px 0 0 -35px; opacity: 0 } }
.flash { animation: fw .1s steps(2) 1; }
@keyframes fw { 50% { filter: brightness(3) saturate(0) } }

/* ═══════════ 暴击全屏演出 ═══════════
   四层叠加：闪光 / 放射线 / 暗角 / 横幅。lv1 大胜偏金，lv2 绝杀偏赤且更久。 */
.crit-burst { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.crit-burst i { position: absolute; inset: 0; display: block; }
.cb-flash {
  background: radial-gradient(60% 42% at 50% 40%, rgba(255,244,214,.92), rgba(255,214,120,.35) 55%, transparent 78%);
  animation: cbFlash .34s ease-out forwards;
}
.cb-rays {
  background: repeating-conic-gradient(from 0deg at 50% 42%,
    rgba(255,226,150,.62) 0deg 2.2deg, transparent 2.2deg 11deg);
  mask-image: radial-gradient(closest-side, transparent 14%, #000 34%, transparent 76%);
  animation: cbRays .58s cubic-bezier(0.16,1,0.3,1) forwards;
}
.cb-vig { box-shadow: inset 0 0 100px 26px rgba(120,58,10,.7); animation: cbVig .5s ease-out forwards; }
.cb-word {
  position: absolute; left: 50%; top: 40%; transform: translate(-50%,-50%) scale(.7);
  font: 900 46px/1 var(--serif); letter-spacing: .1em; white-space: nowrap;
  color: #FFE9A8; text-shadow: 0 0 26px rgba(255,216,116,.95), 4px 4px 0 #000, -2px -2px 0 #7A2A12;
  animation: cbWord .62s cubic-bezier(0.16,1,0.3,1) forwards;
}
.crit-burst.lv2 .cb-flash { background: radial-gradient(66% 46% at 50% 40%, rgba(255,248,232,.98), rgba(232,90,54,.44) 52%, transparent 80%); }
.crit-burst.lv2 .cb-rays { background: repeating-conic-gradient(from 0deg at 50% 42%, rgba(255,150,96,.72) 0deg 2.6deg, transparent 2.6deg 9deg); animation-duration: .86s; }
.crit-burst.lv2 .cb-vig { box-shadow: inset 0 0 130px 34px rgba(150,26,10,.82); }
.crit-burst.lv2 .cb-word { font-size: 62px; color: #FFF0C8; animation-duration: .9s; }
@keyframes cbFlash { 0% { opacity: 0 } 18% { opacity: 1 } 100% { opacity: 0 } }
@keyframes cbRays {
  0%   { opacity: 0; transform: scale(.34) rotate(-9deg) }
  22%  { opacity: 1; transform: scale(.92) rotate(0deg) }
  100% { opacity: 0; transform: scale(1.9) rotate(11deg) }
}
@keyframes cbVig { 0% { opacity: 0 } 30% { opacity: 1 } 100% { opacity: 0 } }
@keyframes cbWord {
  0%   { opacity: 0; transform: translate(-50%,-50%) scale(.62) }
  26%  { opacity: 1; transform: translate(-50%,-50%) scale(1.14) }
  46%  { transform: translate(-50%,-50%) scale(1) }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(1.06) translateY(-14px) }
}
.reduced-motion .crit-burst { display: none; }

#telegraph {
  position: absolute; inset: 0; pointer-events: none; z-index: 70; opacity: 0;
  box-shadow: inset 0 0 90px 22px rgba(196,43,32,.8); transition: opacity .16s;
}
#telegraph.on { opacity: 1; animation: tp .4s ease-in-out infinite; }
@keyframes tp { 50% { opacity: .5 } }

#toast {
  position: absolute; left: 50%; bottom: 112px; transform: translateX(-50%) translateY(12px);
  background: #0A0705; border: 2px solid var(--gold); padding: 8px 13px;
  font-size: 12.5px; color: var(--paper); letter-spacing: .04em;
  opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s;
  z-index: 90; max-width: 86vw; text-align: center; box-shadow: 3px 3px 0 #000;
}
#toast.on { opacity: 1; transform: translateX(-50%) translateY(0); }
/* 锦囊提示是「去看那张高亮的牌」，而 toast 默认位置正好压在手牌上 ——
   实测它盖住了自己指的那张牌。这一条抬到牌桌上方去。 */
#toast.high { bottom: auto; top: 108px; }

.hitstop *, .hitstop *::before, .hitstop *::after {
  animation-play-state: paused !important; transition: none !important;
}
.reduced-motion *, .reduced-motion *::before, .reduced-motion *::after {
  animation-duration: .01ms !important; transition-duration: .05ms !important;
}


/* ═══════════ 阵法表分节 ═══════════ */
.help-sec {
  font: 900 12px/1 var(--serif); letter-spacing: .28em; color: var(--paper);
  background: var(--gold-dim); border: 2px solid var(--gold);
  padding: 6px 9px; margin: 14px 0 6px; text-align: left;
  box-shadow: 3px 3px 0 #000;
}
.help-sec.gold { background: var(--crimson); border-color: var(--gold-hi); }
.help-tiles.wrap { flex-wrap: wrap; max-width: 152px; gap: 2px; }
.help-tiles.wrap .tile { width: 18px; height: 24px; border-width: 1.2px; box-shadow: 1px 1px 0 #000; padding: 1px; }
.help-row.hu { align-items: flex-start; }

/* ═══════════ 牌桌顶部：左信息 + 右大立绘（占满前两行） ═══════════ */
.top { display: grid; grid-template-columns: 1fr 104px; gap: 7px; align-items: stretch; }
.top-main { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.top-pic {
  position: relative; overflow: hidden;
  border: 3px solid var(--gold);
  box-shadow: inset 0 0 0 2px #000, 4px 4px 0 rgba(0,0,0,.9);
  background: #0E0A06;
}
.top-pic img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 14%; display: block; }
.top-pic::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 52%, rgba(8,5,3,.9));
}
.top-pic-cap {
  position: absolute; left: 0; right: 0; bottom: 3px; z-index: 2; text-align: center;
  font: 900 10px/1 var(--serif); letter-spacing: .16em; color: var(--gold-hi);
  text-shadow: 1px 1px 0 #000;
}
.top-pic.boss { border-color: var(--crim-hi); box-shadow: inset 0 0 0 2px #000, 4px 4px 0 rgba(0,0,0,.9), 0 0 16px rgba(224,74,52,.4); }
.top-pic.boss .top-pic-cap { color: #F2C0BB; }

/* 第二行：规矩条（诸侯关显示规则，平时显示地方志） */
.rule-strip { flex: 1; display: flex; gap: 8px; align-items: center; padding: 6px 9px; min-height: 0; }
.rule-strip.boss { border-color: var(--crim-hi); }
.rule-tag {
  writing-mode: vertical-rl; flex: none; align-self: stretch;
  font: 900 10px/1 var(--serif); letter-spacing: .22em; color: var(--gold-dim);
  border: 1px solid var(--gold-dim); padding: 3px 2px;
  display: grid; place-items: center;
}
.rule-strip.boss .rule-tag { color: var(--crim-hi); border-color: var(--crim-hi); background: rgba(196,43,32,.12); }
.rule-txt { flex: 1; min-width: 0; }
.rule-txt b { display: block; font: 900 12.5px/1.2 var(--serif); letter-spacing: .06em; color: var(--gold-hi); }
.rule-strip.boss .rule-txt b { color: #F2C0BB; }
.rule-txt span { display: block; font-size: 10.5px; color: #A9987C; line-height: 1.45; margin-top: 3px; }

/* ═══════════ 幕僚头像 ═══════════ */
.face {
  position: relative; display: inline-block; flex: none; overflow: hidden;
  border: 2px solid var(--ring, #8A6420); background: #0E0A06;
  box-shadow: inset 0 0 0 1px #000, 3px 3px 0 rgba(0,0,0,.85);
}
.face img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%; display: block; }
.face-fallback {
  position: absolute; inset: 0; display: grid; place-items: center;
  font: 900 22px/1 var(--serif); color: var(--paper); background: var(--tint, #4A3A26); font-style: normal;
}
.face-fac {
  position: absolute; right: 0; bottom: 0; z-index: 2;
  font: 900 9px/1 var(--serif); color: var(--paper);
  background: var(--tint, #4A3A26); border-left: 1px solid #000; border-top: 1px solid #000;
  padding: 1.5px 3px;
}
/* 商店卡里的大一点 */
.shop-card .face { box-shadow: inset 0 0 0 1px #000, 2px 2px 0 rgba(0,0,0,.8); }

/* 非法出牌：算式块整体压暗，避免让人以为是真实分数 */
.calc.invalid .blk { filter: saturate(.25) brightness(.55); }
.calc.invalid .calc-total { color: var(--crim-hi); }

/* 全幅事件插图（诸侯战败等），比半身立绘宽 */
.story-portrait.wide img {
  width: 100%; height: auto; aspect-ratio: 5 / 3;
  object-fit: cover; object-position: 50% 45%;
}

/* ═══════════ 锦囊（变牌道具） ═══════════ */
.charms { display: flex; align-items: center; gap: 7px; padding: 0 2px; }
.charms-tag {
  font: 900 10px/1 var(--serif); letter-spacing: .2em; color: var(--gold-dim);
  writing-mode: horizontal-tb; flex: none;
}
.charms-list { display: flex; gap: 6px; flex: 1; }
.charm {
  position: relative; flex: none; cursor: pointer;
  border: 2px solid var(--gold); background: linear-gradient(180deg, #3A2A0C, #1A1206);
  box-shadow: inset 0 0 0 1px #000, 3px 3px 0 rgba(0,0,0,.85);
  width: 42px; height: 42px; display: grid; place-items: center;
  transition: transform .12s cubic-bezier(0.22,1,0.36,1), filter .12s;
}
.charm b { font: 900 20px/1 var(--serif); color: var(--gold-hi); }
.charm:active { transform: translate(2px,2px); box-shadow: inset 0 0 0 1px #000, 1px 1px 0 #000; }
.charm.ready { border-color: #7BE8A8; box-shadow: inset 0 0 0 1px #000, 3px 3px 0 rgba(0,0,0,.85), 0 0 12px rgba(123,232,168,.55); }
.charm.ready b { color: #B6FFD2; }
.charm.cant { filter: grayscale(.7) brightness(.6); }
.charm-empty {
  width: 42px; height: 42px; flex: none; border: 2px dashed #4A3A26;
  display: grid; place-items: center; color: #4A3A26; font: 900 9px/1 var(--serif);
}
/* 变牌完成的闪光 */
.tile.transmuted { animation: tmute .5s cubic-bezier(0.22,1,0.36,1); }
@keyframes tmute {
  0% { transform: rotateY(90deg) scale(1.15); filter: brightness(3); }
  60% { transform: rotateY(0) scale(1.06); filter: brightness(1.6); }
  100% { transform: none; filter: none; }
}

/* ═══════════ 道具立绘（军备 / 锦囊） ═══════════ */
.icon {
  position: relative; display: inline-block; flex: none; overflow: hidden;
  border: 2px solid var(--gold); background: #1A1206;
  box-shadow: inset 0 0 0 1px #000, 3px 3px 0 rgba(0,0,0,.85);
}
.icon img { width: 100%; height: 100%; object-fit: cover; display: block; }
.icon-fallback {
  position: absolute; inset: 0; display: grid; place-items: center;
  font: 900 22px/1 var(--serif); color: #231704; background: var(--gold); font-style: normal;
}
/* 锦囊格里用真图替代单字 */
/* 注意：这里绝不能加 overflow:hidden —— 悬停说明气泡是 .charm 的绝对定位子元素，
   会被自己的容器剪掉，导致「鼠标移上去什么都不显示」。
   图标本来就是 100%×100%、名字条是 inset:auto 0 0 0，都在框内，用不着裁剪。 */
.charm { padding: 0; }
.charm .icon { width: 100% !important; height: 100% !important; border: 0; box-shadow: none; }
.charm b { position: absolute; inset: auto 0 0 0; font-size: 10px; line-height: 1.5;
  background: linear-gradient(180deg, transparent, rgba(6,4,3,.92) 50%); color: var(--gold-hi); }

/* ═══════════ 标题页背景（牌桌夜景） ═══════════ */
.title-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: url('../../assets/misc/title-bg.jpg') 50% 40%/cover no-repeat;
  opacity: 0; transition: opacity .8s ease;
}
.title-bg::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(12,9,6,.58), rgba(12,9,6,.74) 55%, rgba(12,9,6,.9));
}
.title-bg.on { opacity: 1; }

/* ═══════════ 招贤馆掌事 ═══════════ */
/* 招贤馆头图：52px 的小头像看不清掌事是谁，改成整幅立绘 + 底部压条 */
.shop-hero { position: relative; padding: 0; overflow: hidden; }
.shop-hero-img {
  display: block; width: 100%; height: 116px;
  object-fit: cover; object-position: 50% 42%;
}
.shop-hero-bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: flex-end; justify-content: space-between; gap: 8px;
  padding: 12px 9px 6px;
  background: linear-gradient(180deg, transparent, rgba(10,7,4,.62) 42%, rgba(10,7,4,.9));
}
.shop-hero-tt b {
  display: block; font: 900 15px/1.2 var(--serif); letter-spacing: .3em;
  color: var(--gold-hi); text-shadow: 2px 2px 0 #000;
}
.shop-hero-tt small {
  display: block; margin-top: 2px; font-size: 10px; letter-spacing: .04em;
  color: #D6C4A2; text-shadow: 1px 1px 0 #000;
}
.shop-hero .nm { text-align: right; text-shadow: 1px 1px 0 #000; }
.scr-shop .hud { gap: 10px; }
.scr-shop .hud-stage small { letter-spacing: .04em; font-size: 10px; color: #C0AE90; }

/* 商店还有内容可滑的提示 */
.scroll-hint {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 60px; z-index: 5; pointer-events: none;
  font: 900 10px/1 var(--serif); letter-spacing: .2em; color: var(--gold-hi);
  background: rgba(6,4,3,.9); border: 1px solid var(--gold); padding: 4px 10px;
  opacity: 0; transition: opacity .3s;
}
.scroll-hint.on { opacity: 1; animation: bl 1.2s steps(2) infinite; }
.shop-scroll { position: relative; }
/* 顶/底渐隐，暗示可滑动 */
.scr-shop { position: relative; }
.scr-shop::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 56px; height: 26px;
  background: linear-gradient(180deg, transparent, rgba(6,4,3,.85));
  pointer-events: none; z-index: 4;
}

/* 幕僚悬停显示技能 */
.item-chip .tip, .charm .tip {
  position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%);
  margin-bottom: 6px; width: 156px; z-index: 20;
  background: #0A0705; border: 2px solid var(--gold); padding: 6px 8px;
  font: 700 10.5px/1.55 var(--serif); color: var(--paper); letter-spacing: .02em;
  box-shadow: 3px 3px 0 #000; opacity: 0; pointer-events: none; transition: opacity .14s;
  text-align: left; white-space: normal;
}
.item-chip .tip b, .charm .tip b {
  display: block; color: var(--gold-hi); margin-bottom: 3px;
  /* .charm b 是锦囊图标底部那条绝对定位的名字带，气泡里的 <b> 会继承它、
     压在正文上。这里必须显式复位。 */
  position: static; inset: auto; background: none; font-size: inherit; line-height: 1.4;
}
.item-chip:hover .tip, .charm:hover .tip { opacity: 1; }
/* 稀有度：商店卡面上有，牌桌上只能从 tooltip 看到 */
.tip-tag {
  float: right; font: 900 9px/1.5 var(--serif); font-style: normal; letter-spacing: .12em;
  padding: 0 3px; border: 1px solid currentColor; opacity: .9;
}

/* 技能生效：描金一闪 + 抖一下，指明是麾下哪一位在出力 */
.item-chip.fired { animation: fired .6s cubic-bezier(0.22,1,0.36,1); z-index: 12; }
.item-chip.fired::before {
  content: ''; position: absolute; inset: -5px; pointer-events: none;
  border: 2px solid var(--gold-hi); box-shadow: 0 0 14px 3px rgba(248,200,96,.75);
  animation: firedRing .6s ease-out forwards;
}
@keyframes fired {
  0%   { transform: scale(1) rotate(0deg); filter: none; }
  22%  { transform: scale(1.16) rotate(-3deg); filter: brightness(1.7) saturate(1.3); }
  46%  { transform: scale(1.05) rotate(2.5deg); filter: brightness(1.25); }
  70%  { transform: scale(1.09) rotate(-1.2deg); filter: brightness(1.4); }
  100% { transform: scale(1) rotate(0deg); filter: none; }
}
@keyframes firedRing {
  0%   { opacity: 0; transform: scale(.86); }
  25%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.22); }
}
/* ── 幕僚格气泡的定位 ──
   .slots 是 3 列网格。原先这里按 nth-child(-n+2) / nth-last-child(-n+2) 夹边，
   那是两列布局留下的规则，在 3 列下两头都不对：
     · 第 1 列的第 4 格不在「前两个」里 → 气泡按居中排，左边缘跑到 x=-4（屏幕外）；
     · 第 1 行的气泡也朝上开 → 整个飘到幕僚框上面去，压在 HUD 上，
       看起来就像「这位幕僚的名字怎么跑最上面去了」。
   改成按列决定左右、按行决定上下。 */
/* 牌桌：3 列网格 */
#items-row .item-chip:nth-child(3n+1) .tip { left: 0; right: auto; transform: none; }
#items-row .item-chip:nth-child(3n)   .tip { left: auto; right: 0; transform: none; }
#items-row .item-chip:nth-child(-n+3) .tip { top: 100%; bottom: auto; margin: 6px 0 0; }
/* 商店：6 列，整块贴在屏幕顶上 —— 一律朝下开，两头各夹两列。
   注意幕僚位会长到 7/8，这一格网格会换行，所以必须按**列**（6n+k）夹，
   不能按绝对序号：第 7 位在第 2 行第 1 列，用 nth-child(n+5) 会把它当右列，
   气泡跑到 x=-79。 */
#shop-owned .item-chip .tip { top: 100%; bottom: auto; margin: 6px 0 0; }
#shop-owned .item-chip:nth-child(6n+1) .tip,
#shop-owned .item-chip:nth-child(6n+2) .tip { left: 0; right: auto; transform: none; }
#shop-owned .item-chip:nth-child(6n+5) .tip,
#shop-owned .item-chip:nth-child(6n) .tip { left: auto; right: 0; transform: none; }

/* 气泡指向它自己那一格 —— 不加这个小尖角，浮在别人头像上的气泡会被当成别人的名字 */
.item-chip .tip::after, .charm .tip::after {
  content: ''; position: absolute; width: 0; height: 0; border: 5px solid transparent;
}
/* 默认朝上开：尖角在下 */
.item-chip .tip::after { top: 100%; left: 12px; border-top-color: var(--gold); }
/* 朝下开的：尖角在上 */
#items-row .item-chip:nth-child(-n+3) .tip::after,
#shop-owned .item-chip .tip::after {
  top: auto; bottom: 100%; border-top-color: transparent; border-bottom-color: var(--gold);
}
/* 右对齐的气泡，尖角跟着挪到右边 */
#items-row .item-chip:nth-child(3n) .tip::after,
#shop-owned .item-chip:nth-child(6n+5) .tip::after,
#shop-owned .item-chip:nth-child(6n) .tip::after { left: auto; right: 12px; }
/* 锦囊竖条朝左开：尖角在右 */
.charm-col .charm .tip::after { top: 14px; left: 100%; border-left-color: var(--gold); }

/* 设置里的并排按钮 */
/* 并排按钮一律不许折行：「再　起　兵」带全角空格 + .3em 字距时会被挤成两行 */
.menu-row { display: flex; gap: 8px; }
.menu-row .btn { flex: 1; white-space: nowrap; }
.menu-row .btn-lg { padding: 14px 12px; letter-spacing: .18em; }

/* ═══════════ 调试台 ═══════════ */
.panel-wide { width: min(370px, 96vw); max-height: 92vh; overflow: auto; padding: 14px 12px; }
.dbg-grid { display: flex; gap: 8px; margin-bottom: 8px; }
.dbg-grid label {
  flex: 1; display: flex; align-items: center; gap: 6px;
  font: 900 11px/1 var(--serif); letter-spacing: .1em; color: var(--gold-dim);
}
#screen-debug input {
  flex: 1; min-width: 0; width: 100%; background: #0A0705; border: 2px solid var(--gold-dim);
  color: var(--gold-hi); font: 900 13px/1 var(--mono); padding: 6px 7px; outline: none;
}
.dbg-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 10px 0 4px; padding-bottom: 3px; border-bottom: 1px solid #3A2E1A;
  font: 900 12px/1 var(--serif); letter-spacing: .16em; color: var(--gold-hi); text-align: left;
}
.dbg-h small { font: 700 9.5px/1.4 var(--serif); letter-spacing: .02em; color: #8A7758; }
.dbg-h code { font: 700 9.5px/1 var(--mono); color: #C9B48F; }
.dbg-bosses { display: flex; flex-wrap: wrap; gap: 3px; }
.dbg-boss {
  flex: 1 0 auto; cursor: pointer; background: #150E07; border: 1px solid #4A3A26;
  color: #C9B48F; font: 700 9.5px/1.3 var(--serif); padding: 3px 4px;
}
.dbg-boss i { display: block; font: 900 10px/1 var(--mono); font-style: normal; color: var(--gold-dim); }
.dbg-boss:active { background: #2A1D0C; }
.dbg-pick {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 3px;
  max-height: 176px; overflow: auto; padding: 3px; border: 1px solid #3A2E1A; background: rgba(0,0,0,.3);
}
.dbg-pick-sm { grid-template-columns: repeat(3, 1fr); max-height: none; }
.dbg-chip {
  cursor: pointer; text-align: left; background: #150E07; border: 1px solid #4A3A26;
  padding: 3px 4px; color: #A9987C;
}
.dbg-chip b { display: block; font: 900 10.5px/1.3 var(--serif); color: var(--paper); }
.dbg-chip span { display: block; font: 700 8.5px/1.35 var(--serif); }
.dbg-chip.on { background: #3A2A0E; border-color: var(--gold-hi); }
.dbg-chip.on b { color: var(--gold-hi); }
.menu-row .btn { flex: 1; }

/* 小字对比度：原来 #6E5F45 / #5A4A33 在半透明底上看不清 */
.shop-story { color: #9A8460; }
.credit { color: #7A6952; }
.played-empty { color: #7E9A8C; }

/* 结局插图 */
.over-art {
  width: 100%; aspect-ratio: 5/3; overflow: hidden;
  border: 3px solid var(--gold); box-shadow: inset 0 0 0 2px #000, 5px 5px 0 rgba(0,0,0,.9);
  background: #0E0A06;
}
.over-art img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* 过关立绘（小关凯旋）。诸侯关走各自的击破分镜，这块会隐藏 */
.settle-art {
  position: relative; width: 100%; aspect-ratio: 5/3; overflow: hidden; margin: 2px 0 8px;
  border: 3px solid var(--gold); box-shadow: inset 0 0 0 2px #000, 5px 5px 0 rgba(0,0,0,.9);
  background: #0E0A06;
  animation: settleArtIn .42s cubic-bezier(0.22,1,0.36,1);
}
.settle-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.settle-art-cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 14px 8px 6px;
  font: 700 11px/1.5 var(--serif); letter-spacing: .04em; color: #E4D3AE; text-align: left;
  text-shadow: 1px 1px 0 #000;
  background: linear-gradient(180deg, transparent, rgba(10,7,4,.88));
}
@keyframes settleArtIn {
  from { opacity: 0; transform: scale(1.04) }
  to   { opacity: 1; transform: scale(1) }
}

/* 可复制的军令（种子）栏 */
.seed-box {
  display: flex; align-items: center; gap: 6px;
  border: 2px solid var(--gold-dim); background: #0A0705; padding: 5px 6px;
}
.seed-box-lb { flex: none; font: 900 10px/1 var(--serif); letter-spacing: .16em; color: #A08A5E; }
.seed-val {
  flex: 1; min-width: 0; background: transparent; border: 0; outline: none;
  color: var(--gold-hi); font: 900 14px/1 var(--mono); letter-spacing: .04em;
  user-select: text; -webkit-user-select: text; text-align: center;
}
.seed-box .btn { flex: none; padding: 6px 9px; font-size: 11px; letter-spacing: .06em; }

/* ═══════════ 三个存档位 ═══════════ */
.slot-list { display: flex; flex-direction: column; gap: 4px; }
.slot-row {
  display: flex; align-items: center; gap: 7px; padding: 4px 5px;
  border: 1px solid #4A3A26; background: rgba(10,7,5,.5);
}
.slot-row.empty { opacity: .62; }
.slot-no {
  flex: none; min-width: 30px; text-align: center; padding: 3px 2px;
  font: 900 11px/1 var(--serif); letter-spacing: .06em;
  color: #1B1207; background: var(--gold-dim);
}
.slot-lb {
  flex: 1; min-width: 0; text-align: left; font: 700 10px/1.4 var(--serif);
  color: #C9B48F; letter-spacing: .02em;
}
.slot-row .btn-sm { padding: 5px 8px; font-size: 11px; letter-spacing: .06em; }

/* 锦囊空格也要能看到说明（不然玩家不知道锦囊是干什么的） */
.charm-empty { position: relative; }
.charm-empty:hover .tip { opacity: 1; }
/* 空格气泡必须在任何容器里都是绝对定位的浮层。
   先前只给 .charm-col 写了定位，商店里的那份就以正文形式渲染出来，
   在图标上叠出一串糊字（用户截图里的「Empty Charm SlotCharm…」）。 */
.charm-empty .tip {
  position: absolute; left: auto; right: 100%; top: 0; bottom: auto; transform: none;
  margin: 0 6px 0 0; width: 164px; z-index: 20;
  background: #0A0705; border: 2px solid var(--gold); padding: 6px 8px;
  font: 700 10.5px/1.55 var(--serif); color: var(--paper); letter-spacing: .02em;
  box-shadow: 3px 3px 0 #000; opacity: 0; pointer-events: none; transition: opacity .14s;
  text-align: left; white-space: normal;
}
.charm-empty .tip b { display: block; color: var(--gold-hi); margin-bottom: 3px; }

/* 待确认辞退：连点两次才真的退人，第一次先亮红框 */
.item-chip.confirming { animation: sellWarn .7s steps(2) infinite; }
.item-chip.confirming::after {
  content: '再点一次'; position: absolute; left: 50%; top: -2px; transform: translate(-50%,-100%);
  white-space: nowrap; padding: 2px 5px; z-index: 22;
  background: var(--crimson); color: #FFEDD8; border: 1px solid var(--crim-hi);
  font: 900 9px/1.4 var(--serif); letter-spacing: .06em;
}
@keyframes sellWarn { 50% { filter: brightness(1.5) saturate(1.4) hue-rotate(-12deg) } }


/* ═══════════ 第一关教学 ═══════════
   贴在牌桌上方的指路条。不做遮罩弹窗 —— 新手第一次上手最忌讳「先读完再让你动」。 */
/* 浮层而不是行内块：德/法/西的教学文案会折到 4 行（86px），
   在固定 844 的舞台里直接把整屏顶出 45px。浮起来就不参与布局高度了。
   盖住一点牌桌可以接受 —— 教学本来就在指你看哪里。 */
.tut {
  position: absolute; left: var(--pad); right: var(--pad); bottom: 96px; z-index: 26;
  max-height: 108px; overflow-y: auto;
  display: flex; align-items: center; gap: 7px; padding: 6px 8px;
  border: 2px solid var(--gold-hi); background: linear-gradient(180deg, #2A1D0C, #170F06);
  box-shadow: inset 0 0 0 1px #000, 3px 3px 0 rgba(0,0,0,.85);
  animation: tutIn .3s cubic-bezier(0.22,1,0.36,1);
}
@keyframes tutIn { from { opacity: 0; transform: translateY(-6px) } }
.tut-step {
  flex: none; padding: 2px 5px; background: var(--gold-hi); color: #1B1207;
  font: 900 10px/1.4 var(--mono);
}
.tut-text { flex: 1; font: 700 11px/1.5 var(--serif); color: #F0E0BC; letter-spacing: .02em; }
.tut .btn-sm { flex: none; padding: 4px 6px; font-size: 10px; letter-spacing: .04em; }

/* 教学指向的目标：呼吸金框 */
.tut-target { position: relative; z-index: 30; animation: tutPulse 1.1s ease-in-out infinite; }
@keyframes tutPulse {
  0%,100% { box-shadow: 0 0 0 2px var(--gold-hi), 0 0 10px rgba(248,200,96,.5) }
  50%     { box-shadow: 0 0 0 3px #FFF0C8, 0 0 20px rgba(248,200,96,.95) }
}

/* ═══════════ 语言选择 ═══════════ */
/* 语言下拉：12+ 种语言用按钮网格排不下，交给原生 select（手机上是系统滚轮） */
.lang-pick { display: flex; align-items: center; gap: 8px; }
.lang-pick > span { flex: none; font: 900 10px/1 var(--serif); letter-spacing: .12em; color: var(--gold-dim); }
.lang-sel {
  flex: 1; min-width: 0; cursor: pointer; padding: 6px 8px;
  background: #150E07; border: 2px solid var(--gold); color: var(--gold-hi);
  font: 700 12px/1.3 var(--serif); letter-spacing: .04em;
  appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--gold-hi) 50%),
    linear-gradient(135deg, var(--gold-hi) 50%, transparent 50%);
  background-position: calc(100% - 14px) 52%, calc(100% - 9px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.lang-sel option { background: #150E07; color: #E8D6AE; }

/* 计数条与按钮里为了可翻译新增的 <i> 标签，纯语义容器不带样式 */
.counts .cnt i, .btn > i:not(.btn-n) { font-style: normal; letter-spacing: inherit; }

/* 开机画面的语言面板：点「文 / A」就地展开 */
.title-lang { margin-top: 8px; padding: 6px; border: 2px solid var(--gold); background: rgba(10,7,5,.82); }

/* 商店里的指路条：商店是滚动布局，所以这条跟着内容走（不像牌桌那条要浮起来） */
.tut-shop { position: static; margin: 4px 0 6px; max-height: none; }

/* ═══════════ 手牌多时：计分区与牌桌叠层，点哪层哪层在上 ═══════════
   张飞那关手牌 18 张要排三行，固定 844 的舞台里牌桌高度不够，第一行会被切掉。
   做法不是压缩牌（44px 已经是手机上的下限），而是让两层叠起来：
     · 默认（手牌 ≤14）：计分区完整展开，和现在一样
     · 手牌变多 → 计分区自动缩成一行（只留 筹码×倍率=总分），把高度让给牌桌
     · 点计分区 → 它浮起来盖住牌桌，看完整拆解
     · 点牌桌 → 计分区缩回去，牌完整可见
   遮挡是可接受的，因为两边玩家不会同时需要看。 */

.calc.compact { max-height: none; padding: 4px 11px 5px; cursor: pointer; }
.calc.compact .calc-name,
.calc.compact .calc-hint,
.calc.compact .calc-parts { display: none; }
.calc.compact .calc-row { gap: 5px; }
.calc.compact .blk { padding: 2px 0 3px; }
.calc.compact .blk b { font-size: 20px; }
.calc.compact .blk span { font-size: 8.5px; letter-spacing: .1em; }
.calc.compact .calc-eq { font-size: 22px; }
.calc.compact::after {
  content: attr(data-more); display: block; margin-top: 2px;
  font: 700 9px/1.3 var(--serif); color: var(--gold-dim); letter-spacing: .1em;
}

/* 点开的那一瞬间浮到牌桌之上 */
.calc.raised {
  position: absolute; left: var(--pad); right: var(--pad); z-index: 30;
  max-height: 62vh; overflow-y: auto;
  box-shadow: inset 0 0 0 2px #000, 6px 8px 0 rgba(0,0,0,.9);
}

/* 阵法表里胡牌那几行：主数字是「例牌实际总分」，胡牌自带加成缩小放在下面 */
.help-meta .sub { font: 700 9.5px/1.4 var(--mono); color: var(--gold-dim); letter-spacing: .04em; }

/* 教学期间锁住的牌与按钮：看得见但点不动，视线自然被金框那几个吸走 */
.tile.tut-locked { filter: saturate(.25) brightness(.55); cursor: default; pointer-events: none; }
.btn.tut-locked { filter: saturate(.2) brightness(.5); pointer-events: none; }

/* ═══════════ 付费解锁页（只在原生 App 里会弹） ═══════════ */
.pay-art {
  border: 2px solid var(--gold-dim); overflow: hidden; margin: 2px 0 8px;
  max-height: 132px; display: flex; align-items: center;
}
.pay-art img { width: 100%; display: block; object-fit: cover; object-position: 50% 30%; }
.pay-lead {
  /* .panel 是居中排版的，但这一段和下面的清单是要读的正文 —— 居中读起来累 */
  margin: 0 0 8px; font: 400 12.5px/1.65 var(--serif); color: var(--paper); letter-spacing: .02em;
  text-align: left;
}
.pay-list { margin: 0 0 12px; padding: 0; list-style: none; }
.pay-list li {
  position: relative; padding: 4px 0 4px 16px; text-align: left;
  font: 400 11.5px/1.5 var(--serif); color: #C4B393; letter-spacing: .02em;
}
/* 用「◈」而不是 emoji：iOS 上 emoji 字体缺失会渲染成方框（这台机器实测过） */
.pay-list li::before {
  content: '◈'; position: absolute; left: 0; top: 4px; color: var(--gold); font-size: 10px;
}
#btn-pay-buy { width: 100%; }
#btn-pay-buy b { font: 900 15px/1 var(--mono); letter-spacing: .04em; }
.pay-note {
  margin: 8px 0 0; font: 400 10px/1.5 var(--serif); color: var(--gold-dim); letter-spacing: .02em;
  text-align: left;
}

/* 提示指出「该对这张牌用锦囊」—— 和普通提示的金框区分开，用锦囊的青色 */
.tile.charm-hinted {
  box-shadow: 0 0 0 3px #2FB8A0, 0 0 14px 3px rgba(47,184,160,.55) !important;
  animation: charmPulse 1.1s ease-in-out infinite;
}
@keyframes charmPulse {
  0%, 100% { box-shadow: 0 0 0 3px #2FB8A0, 0 0 14px 3px rgba(47,184,160,.55); }
  50%      { box-shadow: 0 0 0 3px #6FE3CE, 0 0 20px 6px rgba(47,184,160,.85); }
}


/* ════════════════════════════════════════════════════════════════
   横屏构图（1280×720，桌面 / Steam）
   ════════════════════════════════════════════════════════════════
   竖屏那套一个字都不改：下面所有规则都挂在 body.landscape 下。
   舞台尺寸由 fx.js 写进 --stage-w/--stage-h，这里只管怎么排。

   关键手法：`display: contents` 把 .top 这个纯粹的分组容器「溶掉」，
   让它的两个孩子（.top-main 文字信息 / .top-pic 诸侯立绘）直接成为
   .scr-table 网格的成员 —— 这样一个是左栏、一个是右栏，不用改 HTML。
   ──────────────────────────────────────────────────────────────── */

/* 牌宽是倒推出来的：14 张要挤进中路一行。
   中路内宽 = 1280 − 左栏 220 − 右栏 248 − 列间距 22 − 舞台内边距 28 ≈ 762，
   牌桌自身内边距再吃掉约 20 → 742。14×(48+4) = 728，留一点余量。
   改左右栏宽度就必须重算这个数，否则手牌会悄悄折回两行。 */
body.landscape { --tile-w: 48px; --tile-h: 63px; --pad: 14px; }

body.landscape .scr-table > .top { display: contents; }

body.landscape .scr-table {
  display: grid;
  grid-template-columns: 220px 1fr 248px;
  /* 第 3 行给 1fr：牌桌吃掉所有多余高度，其余按内容 */
  grid-template-rows: auto auto 1fr auto;
  grid-template-areas:
    "build build build"
    "info  calc  boss"
    "cnt   felt  boss"
    "sub   btns  boss";
  gap: 9px 11px;
  align-content: start;
}

body.landscape .retinue  { grid-area: build; }
body.landscape .top-main { grid-area: info; display: flex; flex-direction: column; gap: 7px; }
body.landscape .counts   { grid-area: cnt; }
body.landscape .calc     { grid-area: calc; }
body.landscape .felt     { grid-area: felt; min-height: 0; }
body.landscape .btns     { grid-area: btns; }
/* ⚠ 必须排在 .btns 之后、且用两个类提高特异性：
   `.btns-sub` 元素的 class 是 "btns btns-sub"，同时命中上面那条 .btns 规则。
   写在前面或只用一个类，两排按钮会被塞进同一格重叠（实测出牌按钮里字全没了）。 */
body.landscape .btns.btns-sub { grid-area: sub; }
body.landscape .top-pic  { grid-area: boss; }
/* 兵器架平时是 hidden 的；出现时压在左栏底部，别顶开网格 */
body.landscape .armory   { grid-area: sub; }

/* 左栏三块自然堆在顶部：不加这条，counts 会被 1fr 那行拉成一整栏高，
   「出牌 3 / 提示 2」之间空出一大片 */
body.landscape .top-main,
body.landscape .counts,
body.landscape .btns.btns-sub { align-self: start; }

/* ── 顶条：这是玩家的「构筑」，横排 6 幕僚 + 3 锦囊 ── */
body.landscape .retinue-body {
  /* 幕僚占满，锦囊固定一条竖排在右端 */
  grid-template-columns: 1fr 178px;
  gap: 10px;
}
body.landscape .slots {
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: 96px;
}
body.landscape .charm-col { align-items: stretch; }
body.landscape .charm-col .cc-head { text-align: center; }
body.landscape .charm-col .charms-list {
  flex-direction: row; justify-content: center; gap: 8px;
}
body.landscape .charm-col .charm,
body.landscape .charm-col .charm-empty { width: 52px; height: 52px; }
/* 幕僚条挪到舞台最顶上之后，默认「往上弹」的 tooltip 会整个跑出画面
   （实测 top=-37）。横屏一律往下弹，并且首末两列贴边对齐 ——
   这套规则和招贤馆 #shop-owned 那个 6 列网格用的是同一套（见上文）。 */
body.landscape #items-row .item-chip .tip { top: 100%; bottom: auto; margin: 6px 0 0; }
body.landscape #items-row .item-chip:nth-child(6n+1) .tip,
body.landscape #items-row .item-chip:nth-child(6n+2) .tip { left: 0; right: auto; transform: none; }
body.landscape #items-row .item-chip:nth-child(6n+5) .tip,
body.landscape #items-row .item-chip:nth-child(6n) .tip { left: auto; right: 0; transform: none; }
/* 尖角跟着翻到气泡上边 */
body.landscape #items-row .item-chip .tip::after {
  top: auto; bottom: 100%; border-top-color: transparent; border-bottom-color: var(--gold);
}
body.landscape #items-row .item-chip:nth-child(6n+5) .tip::after,
body.landscape #items-row .item-chip:nth-child(6n) .tip::after { left: auto; right: 12px; }
/* 锦囊也一样往下开，尖角翻上去 */
body.landscape .charm-col .charm .tip::after {
  top: auto; bottom: 100%; left: 12px;
  border-left-color: transparent; border-bottom-color: var(--gold);
}
body.landscape .charms-list > :nth-last-child(1) .tip::after { left: auto; right: 12px; }
/* 锦囊挪到顶条右端后，tooltip 该往下弹而不是往左 */
body.landscape .charm-col .charm .tip {
  left: 50%; right: auto; top: 100%; bottom: auto;
  margin: 6px 0 0; transform: translateX(-50%);
}
/* 最右那个锦囊居中弹会超出舞台右边被裁掉（实测 1304 > 1280），改成右对齐 */
body.landscape .charms-list > :nth-last-child(1) .tip {
  left: auto; right: 0; transform: none;
}

/* ── 左栏：目标 / 已得 / 钱粮 / 规矩 / 计数 / 次要按钮 ── */
body.landscape .hud { flex-direction: column; align-items: stretch; gap: 9px; }
body.landscape .hud-nums { justify-content: space-between; }
body.landscape .rule-strip { align-items: flex-start; }
body.landscape .rule-txt span { -webkit-line-clamp: 4; }
body.landscape .counts {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 10px;
  justify-items: stretch;
}
/* 3 列而不是 2 列：6 个次要按钮排成 2 行，这一行的行高才不会把中路的
   出牌按钮一起撑成 140px 高（同一网格行，行高取最高者） */
body.landscape .btns-sub {
  /* minmax(0,1fr) 而不是 1fr：1fr 的最小尺寸是 auto，列会被长文案顶宽，
     三列加起来超过左栏 220px 就往左溢出画面 */
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px;
}
body.landscape .btns-sub .btn {
  width: 100%; padding: 6px 2px; font-size: 11px; border: 2px solid var(--gold-dim);
}

/* ── 中路：计分 → 牌桌 → 出牌按钮 ── */
body.landscape .calc { padding: 9px 12px 11px; }
/* 14 张手牌在这个宽度下一行放得下（14×58 = 812 < 中路可用宽），
   不再像竖屏那样折成 7×2 —— 一行摆开才像一副麻将手牌。 */
body.landscape .hand { gap: 8px 4px; }
/* 余牌条挪到牌桌**上沿**：竖屏它夹在已出牌和手牌之间还好，
   横屏牌桌矮、手牌选中时会上浮，正好撞进这条里（实测重叠） */
body.landscape .wall-strip { order: -1; margin-bottom: 4px; }
/* align-items:start —— 否则按钮会被拉伸到整行高度（实测出牌按钮 330×140）。
   `:not(.btns-sub)` 不能省：次要按钮那一排的 class 也含 .btns，
   不隔开的话 22px 的内边距会套到它们身上，把左栏那 220px 撑爆（实测溢出到 -23）。 */
body.landscape .btns:not(.btns-sub) { justify-content: center; align-items: start; gap: 14px; }
body.landscape .btns:not(.btns-sub) .btn { padding: 13px 22px; }
body.landscape .btn-play { min-width: 240px; }

/* ── 右栏：诸侯立绘。竖屏里它只是 54px 缩略图，这里给它一整条竖幅 ── */
body.landscape .top-pic {
  display: flex; flex-direction: column; align-items: stretch;
  min-height: 0;
}
body.landscape .top-pic img {
  width: 100%; flex: 1 1 auto; min-height: 0;
  object-fit: cover; object-position: 50% 22%;
}
body.landscape .top-pic-cap {
  position: static; text-align: center; padding: 5px 0 0; font-size: 12px;
}

/* 教学气泡：竖屏贴在牌桌上方；横屏它是绝对定位的浮层，钉在中路牌桌上沿 */
body.landscape .tut {
  left: 240px; right: 268px; bottom: 128px;
}

/* toast 竖屏默认在手牌上方（bottom:112px）；横屏那儿正好压在手牌上。
   实测各面板位置：计分 151–346、牌桌 355–561、手牌 485–548。
   放在牌桌上半部的空档（380）—— 不盖计分、不盖手牌，锦囊提示也照样看得见高亮那张牌。 */
body.landscape #toast,
body.landscape #toast.high { bottom: auto; top: 380px; }

/* ── 招贤馆：竖屏是一条长滚动列表，横屏拆成「左档案 / 右货架」 ──
   （竖屏下内容高 792px > 舞台 720，直接用会溢出） */
body.landscape .scr-shop {
  display: grid;
  grid-template-columns: 424px 1fr;
  /* 头图吃掉左栏多余高度（1fr）—— 这张招贤馆大图竖屏里只能露一条，
     横屏给它整栏，左边就不会下半截空着 */
  grid-template-rows: minmax(150px, 1fr) auto auto;
  grid-template-areas:
    "hero  goods"
    "owned goods"
    "btns  goods";
  gap: 10px 12px;
}
body.landscape .shop-hero   { grid-area: hero; min-height: 0; }
body.landscape .shop-hero-img { height: 100%; object-fit: cover; object-position: 50% 34%; }
body.landscape .scr-shop .retinue-sm { grid-area: owned; }
body.landscape .scr-shop .btns { grid-area: btns; align-self: start; }
body.landscape .scroll-hint { display: none; }

/* 货架给个框：不加的话货品下面那片空地直接露出背景图，像没排完版 */
body.landscape .shop-scroll {
  grid-area: goods; min-height: 0;
  border: 3px solid var(--gold-dim);
  box-shadow: inset 0 0 0 2px var(--panel-2), 4px 4px 0 rgba(0,0,0,.9);
  background: rgba(10,7,5,.55);
  padding: 10px 12px;
}

/* 货架两列排：1280 宽下单列卡片会拉得又长又空，两列刚好，也少滚一半 */
body.landscape .shop-list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px;
}
body.landscape .shop-h { grid-column: 1 / -1; }
body.landscape .shop-note { grid-column: 1 / -1; }

/* ── 阵法表：竖屏是 2348px 长的滚动表，横屏铺成三栏，基本一屏看完 ──
   注意是 #help-body（id 不是 class），选错了这条不会报错、只是静默无效 */
body.landscape #screen-help .panel { width: min(1120px, 92%); }
body.landscape #help-body { column-count: 3; column-gap: 20px; text-align: left; }
body.landscape #help-body .help-row,
body.landscape #help-body .help-sec { break-inside: avoid; }

/* ── 设置：竖屏是一长条，横屏两列，高度直接减半 ── */
body.landscape #screen-menu .panel { width: min(720px, 88%); }
body.landscape #screen-menu .panel > *:not(.panel-title) {
  break-inside: avoid;
}
body.landscape #screen-menu .panel {
  display: block; column-count: 2; column-gap: 20px;
}
body.landscape #screen-menu .panel-title { column-span: all; margin-bottom: 12px; }
body.landscape #screen-menu .panel > * { margin-bottom: 10px; }

/* ── 标题页：竖屏是一条居中列，横屏改成「左主视觉 / 右开局面板」 ──
   直接沿用竖屏那条列会让 1280 宽的屏幕两侧全空，第一印象很像手游套壳 */
body.landscape .scr-title {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  /* 四行全 auto —— 留一行 1fr 的话空白全塞进那一行，
     跨行的主视觉会和右栏错开半屏（实测右栏 30–278、主视觉 185–535） */
  grid-template-rows: repeat(4, auto);
  grid-template-areas:
    "art  logo"
    "art  diff"
    "art  seed"
    "art  btns";
  align-items: center;
  align-content: center;      /* 四行整体居中，右栏才不会全堆在上半屏 */
  gap: 14px 34px;
  padding: 30px 46px;
}
/* 主视觉是**横构图**：让它 align-self:stretch 会被拉成竖条，
   object-fit:cover 只剩中间那位将领（实测左右两位全裁掉了）。
   固定 16:10 让它保持横幅，垂直居中。 */
body.landscape .title-art {
  grid-area: art; align-self: center; justify-self: center;
  /* base 里有 max-width:340px（为手机定的），不覆盖的话横屏主视觉只有巴掌大 */
  width: 100%; max-width: 560px; height: auto; min-height: 0;
  aspect-ratio: 16 / 10;
}
body.landscape .title-main { grid-area: logo; align-self: end; }
body.landscape .diff-row   { grid-area: diff; }
body.landscape .seed-row   { grid-area: seed; }
body.landscape .title-btns { grid-area: btns; align-self: start; }
body.landscape .game-title { font-size: 46px; }
body.landscape .title-btns { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }

/* 键盘光标：← → 移动时描一道，和「选中」（金框上浮）区分开 */
.tile.kb-focus { outline: 3px solid #6FE3CE; outline-offset: 2px; }
