* { box-sizing: border-box; }
body {
  margin: 0; padding: 18px; font-family: system-ui, "PingFang SC", sans-serif;
  background: #0c0c0e; color: #c9c2bd;
}
.panel {
  max-width: 980px; margin: 0 auto; background: #16161a; border: 1px solid #2a2a30;
  border-radius: 12px; padding: 20px; box-shadow: 0 0 24px rgba(0,0,0,0.6);
}
.hidden { display: none; }
h1 { margin: 0 0 4px; font-size: 30px; letter-spacing: 14px; color: #c0392b; text-align: center; }
.sub { text-align: center; color: #6d6d75; margin: 0 0 18px; font-size: 13px; letter-spacing: 2px; }
input, select {
  width: 100%; padding: 10px 12px; margin-bottom: 12px; background: #0f0f12;
  border: 1px solid #33333a; border-radius: 8px; color: #d8d2cc; font-size: 14px;
}
.lbl { font-size: 12px; color: #6d6d75; display: block; margin-bottom: 6px; }
button {
  padding: 9px 16px; border: 1px solid #5a1f1f; border-radius: 8px;
  background: #2a1212; color: #e0b4b4; font-size: 13px; cursor: pointer; margin: 3px;
}
button:hover:not(:disabled) { background: #3d1a1a; }
button:disabled { opacity: 0.35; cursor: not-allowed; }
.top { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; flex-wrap: wrap; }
#roomTag { font-weight: 600; color: #d8d2cc; }
.tag { font-size: 12px; color: #8a8a92; margin-left: 10px; }
#selfBox { margin-left: auto; font-size: 13px; }
#leaveBtn { margin-left: 0; }
.layout { display: flex; gap: 18px; flex-wrap: wrap; }
#game.panel { max-width: 1280px; }
.left { flex: 1 1 620px; max-width: 720px; }
.left { flex: 1 1 520px; }
.right { flex: 1 1 320px; }
/* ---------- 棋盘：等距伪 3D（参考 FOR THE KING 的桌面沙盘） ---------- */
.board-wrap {
  margin: 0 auto 34px; max-width: 640px;
  perspective: 1000px; perspective-origin: 50% 46%;
  padding: 10px 10px 20px; border-radius: 14px;
  background:
    radial-gradient(ellipse at 50% 118%, rgba(90, 68, 38, 0.30), transparent 62%),
    radial-gradient(circle at 50% 40%, #141210, #06060a 70%);
  box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.9);
}
.board {
  position: relative; width: 100%; aspect-ratio: 1 / 1;
  transform: rotateX(30deg); transform-style: preserve-3d;
  background:
    repeating-linear-gradient(0deg, rgba(132, 118, 92, 0.030) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(90deg, rgba(132, 118, 92, 0.030) 0 1px, transparent 1px 24px),
    radial-gradient(circle at 50% 42%, color-mix(in srgb, var(--theme, #504024) 26%, transparent), transparent 62%),
    radial-gradient(circle at 24% 78%, rgba(28, 42, 56, 0.35), transparent 55%),
    #08080b;
  border: 1px solid rgba(90, 72, 44, 0.35); border-radius: 14px; overflow: visible;
  box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.9);
}
.roads { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }
/* 还没探明的路：暗色虚线，暗示「有路，但不知道通向哪」 */
.road { stroke: #262633; stroke-width: 0.62; stroke-dasharray: 1.4 2.4; }
.road.known { stroke: #7a6440; stroke-width: 1.15; stroke-dasharray: none; }

/* 视野渐隐：跟自己越远越暗，迷雾边界是化开的，不是一刀切 */
.sight {
  position: absolute; inset: -6%; z-index: 5; pointer-events: none;
  background: radial-gradient(circle at var(--sx, 50%) var(--sy, 50%),
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) var(--s0, 28%),
    rgba(3, 3, 6, 0.38) var(--s1, 50%),
    rgba(2, 2, 4, 0.62) var(--s2, 86%));
}

/* 地块 = 外层定位（不裁切，棋子才能站到地块外）+ 内层六边形薄片（三层渐变做出厚度） */
.node {
  position: absolute; transform: translate(-50%, -50%);
  width: 7.9%; aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: #b8b0aa;
  transition: filter .15s ease, transform .15s ease;
}
.node .hex {
  position: absolute; inset: 0;
  clip-path: polygon(50% 0%, 94% 26%, 94% 74%, 50% 100%, 6% 74%, 6% 26%);
  background: linear-gradient(165deg, #3a3a48 0%, #22222c 40%, #10101a 100%);
  /* 侧壁 + 落影：地块像一块被抬起的厚砖 */
  filter: drop-shadow(0 5px 6px rgba(0, 0, 0, 0.8));
}
/* 侧壁：同形状的暗色六边形向下错开一点，露出来就是「砖的厚度」 */
.node .hex::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  transform: translateY(13%);
  clip-path: polygon(50% 0%, 94% 26%, 94% 74%, 50% 100%, 6% 74%, 6% 26%);
  background: linear-gradient(180deg, #17171f, #05050a);
}
.node .hex::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 118%, var(--tint, transparent), transparent 72%);
  opacity: 0.65;
}
.node.fog .hex { background: linear-gradient(165deg, #16161f 0%, #0b0b12 50%, #06060a 100%); }
.node.fog .hex::before { background: #04040a; }
.node.fog .hex::after { opacity: 0; }
.node.fog { color: #3d3d4a; }
/* 迷雾：格面发虚、边缘糊掉，连砖的厚度都看不清——一眼就知道这块没探明 */
.node.fog .hex { filter: blur(0.8px) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6)); }
.node.fog .ni { opacity: 0.45; font-size: 11px; }
/* 已探明的地块：边缘一圈极淡的暖光，跟雾区分开 */
.node.seen .hex { box-shadow: inset 0 0 0 1px rgba(236, 205, 155, 0.10); }
.node.seen.lit .hex { box-shadow: inset 0 0 16px rgba(240, 200, 120, 0.18), inset 0 0 0 1px rgba(240, 200, 120, 0.18); }
/* 棋盘右上角的迷雾读数（在外框里，不跟着棋盘倾斜） */
.board-wrap { position: relative; }
.fogstat {
  position: absolute; right: 14px; top: 14px; z-index: 12;
  font-size: 10.5px; letter-spacing: 0.5px; color: #8d857c;
  background: rgba(8, 8, 12, 0.82); border: 1px solid rgba(120, 100, 70, 0.35);
  border-radius: 4px; padding: 3px 7px; white-space: nowrap;
}
.fogstat b { color: #d8b98a; font-weight: 600; }
.fs-lamp { color: #9a8a5e; }
.node.lit .hex { background: linear-gradient(165deg, #322a1c 0%, #201a10 45%, #0e0b07 100%); }
.node.lit { color: #bda67f; }
.node.item { --tint: #2f8a5c; }
.node.task { --tint: #8a7a2a; }
.node.encounter { --tint: #8a2a2a; }
.node.treasure { --tint: #7a2a8a; }
.node.event { --tint: #2a5a8a; }
.node.lamp { --tint: #f0d070; color: #f6dd93; }
.node.lamp .hex { background: linear-gradient(165deg, #4a3a16 0%, #2a2110 45%, #14100a 100%); }
.node.beam .hex { animation: lampPulse 2.4s ease-in-out infinite; }
.node.here { transform: translate(-50%, -50%) translateZ(10px) scale(1.12); z-index: 4; }
.node.here .hex { filter: drop-shadow(0 0 7px rgba(192, 57, 43, 0.95)) drop-shadow(0 4px 4px rgba(0, 0, 0, 0.7)); }
.node.reachable { cursor: pointer; }
.node.reachable .hex { animation: reachPulse 1.5s ease-in-out infinite; }
.node.reachable .hex::after {
  content: ''; position: absolute; inset: 0;
  box-shadow: inset 0 0 0 2px rgba(246, 221, 147, 0.9), inset 0 0 12px rgba(240, 208, 112, 0.55);
  border-radius: 2px;
}
.node.reachable:hover { transform: translate(-50%, -50%) translateZ(12px) scale(1.1); }
.node.reachable:hover .hex { filter: drop-shadow(0 0 12px rgba(240, 208, 112, 1)) drop-shadow(0 5px 5px rgba(0, 0, 0, 0.7)); }
@keyframes lampPulse {
  0%, 100% { filter: drop-shadow(0 0 4px rgba(240, 208, 112, 0.45)) drop-shadow(0 3px 3px rgba(0, 0, 0, 0.7)); }
  50% { filter: drop-shadow(0 0 13px rgba(240, 208, 112, 0.95)) drop-shadow(0 3px 3px rgba(0, 0, 0, 0.7)); }
}
@keyframes reachPulse {
  0%, 100% { filter: drop-shadow(0 0 5px rgba(240, 208, 112, 0.55)) drop-shadow(0 3px 3px rgba(0, 0, 0, 0.7)); }
  50% { filter: drop-shadow(0 0 12px rgba(240, 208, 112, 0.95)) drop-shadow(0 3px 3px rgba(0, 0, 0, 0.7)); }
}
.node .ni { position: relative; z-index: 2; line-height: 1; text-shadow: 0 1px 2px #000; }
.lampbar { font-size: 12px; color: #d8a85a; margin-top: 4px; }

/* 棋子：小人模型（SVG）。棋盘是斜的，棋子反向旋转立起来 */
.tokens {
  position: absolute; display: flex; gap: 2px; z-index: 5;
  transform: rotateX(-30deg) translate(16%, -20%);
  transform-origin: 50% 100%;
}
.tok { position: relative; width: 30px; height: 41px; display: flex; align-items: flex-end; justify-content: center; }
.tok .fig { width: 100%; height: 100%; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.8)); }
.tok.you { filter: drop-shadow(0 0 4px rgba(192, 57, 43, 0.95)); }
.tok.acting { filter: drop-shadow(0 0 6px rgba(240, 120, 90, 1)); }
.tokname {
  position: absolute; bottom: -11px; left: 50%; transform: translateX(-50%);
  font-size: 9px; line-height: 1.2; color: #d8d0c9; white-space: nowrap;
  background: rgba(6, 6, 10, 0.78); border-radius: 3px; padding: 0 3px;
}
.buffs { position: absolute; bottom: 33px; left: 50%; transform: translateX(-50%); display: flex; gap: 2px; white-space: nowrap; z-index: 6; }
.buff {
  font-size: 9px; line-height: 1; padding: 1px 3px; border-radius: 4px; font-style: normal;
  background: #3a1d12; color: #f0a95c; border: 1px solid #8a4a22;
  box-shadow: 0 0 4px rgba(240, 140, 60, 0.4);
}
.actions { margin-top: 16px; min-height: 40px; }
.players { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.pcard {
  border: 1px solid #2a2a30; border-radius: 8px; padding: 8px 10px; background: #121216;
  display: flex; gap: 8px; align-items: center;
}
.pcard.current { border-color: #c0392b; box-shadow: 0 0 10px rgba(192, 57, 43, 0.25); }
.pcard.dead { opacity: 0.5; }
.pfig { width: 26px; height: 36px; flex: 0 0 auto; }
.pfig .fig { width: 100%; height: 100%; }
.pbody { flex: 1 1 auto; min-width: 0; }
.pcard .pn { font-weight: 600; font-size: 13px; }
.pcard .pm { font-size: 11px; color: #8a8a92; }
.kick-btn {
  flex: 0 0 auto; padding: 3px 9px; font-size: 11px; cursor: pointer;
  background: #2a1212; color: #c0392b; border: 1px solid #4a1a1a; border-radius: 5px;
}
.kick-btn:hover { background: #4a1a1a; color: #e0655f; }
.rc-lock { font-size: 11px; margin-right: 2px; opacity: 0.8; }
.hpbar { height: 7px; background: #2a1212; border-radius: 4px; overflow: hidden; margin-top: 5px; }
.hpfill { height: 100%; background: #8a1f1f; }
.log {
  background: #0f0f12; border: 1px solid #2a2a30; border-radius: 8px; padding: 10px;
  font-size: 12px; color: #9a9aa2; max-height: 220px; overflow-y: auto; line-height: 1.7;
}
.log .ann { color: #c0392b; }
.chat { background: #0f0f12; border: 1px solid #2a2a30; border-radius: 8px; padding: 8px; margin-top: 10px; }
.chat-msgs { max-height: 130px; overflow-y: auto; font-size: 12px; color: #b8b0aa; line-height: 1.7; margin-bottom: 6px; }
.chat-msgs .cn { color: #d8a85a; font-weight: 600; }
.chat-input { display: flex; gap: 6px; }
.chat-input input { margin-bottom: 0; flex: 1; }
.chat-input button { margin: 0; }
.err { color: #e0574f; font-size: 12px; min-height: 16px; margin-top: 8px; }
.identity-box { background: #1a0e0e; border: 1px solid #5a1f1f; border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; }
.identity-box .iname { color: #c0392b; font-weight: 600; }
.identity-box .igoal { font-size: 12px; color: #b8a0a0; }
.identity-box .done { color: #4f9a6a; }
.skillline { font-size: 12px; color: #8f8f98; margin-top: 2px; }
.hero-skill { font-size: 12px; color: #8f8f98; line-height: 1.6; margin: -6px 0 12px; min-height: 32px; }

/* ---------- 大厅：化身卡牌（参考三国杀选将） ---------- */
.lobby-inputs { display: flex; gap: 12px; }
.lobby-inputs > div { flex: 1 1 0; }
.hero-cards {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
  gap: 10px; margin: 4px 0 14px;
}
.hcard {
  position: relative; border: 1px solid #2c2c34; border-radius: 10px;
  background: linear-gradient(180deg, #191920 0%, #101015 70%, #0b0b0f 100%);
  padding: 8px 8px 10px; cursor: pointer; overflow: hidden;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
  display: flex; flex-direction: column;
}
.hcard::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 0%, rgba(120, 90, 60, 0.22), transparent 60%);
  pointer-events: none;
}
.hcard:hover { transform: translateY(-4px) rotateX(3deg); border-color: #5a4a34; box-shadow: 0 10px 22px rgba(0, 0, 0, 0.6); }
.hcard.picked {
  border-color: #a03a2a;
  box-shadow: 0 0 0 1px rgba(192, 57, 43, 0.5), 0 10px 24px rgba(120, 20, 12, 0.45);
  background: linear-gradient(180deg, #221316 0%, #140d10 70%, #0b0709 100%);
}
.hport { height: 116px; display: flex; align-items: flex-end; justify-content: center; }
.hport .fig { height: 100%; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.75)); }
.hname { text-align: center; font-size: 14px; font-weight: 700; letter-spacing: 2px; color: #e2d8cf; margin-top: 4px; }
.hskill { font-size: 11px; color: #8b8b95; line-height: 1.5; margin-top: 4px; min-height: 46px; }
.hskill b { color: #d8a85a; }
.hpick {
  position: absolute; top: 6px; right: 6px; font-size: 10px; color: #f0b9a9;
  background: #5a1f1f; border: 1px solid #a03a2a; border-radius: 4px; padding: 1px 4px;
  opacity: 0; transition: opacity .15s;
}
.hcard.picked .hpick { opacity: 1; }
button.primary {
  width: 100%; padding: 12px; font-size: 15px; letter-spacing: 4px;
  background: linear-gradient(180deg, #3a1515, #240c0c); border-color: #7a2a2a; color: #f0c9b9;
}
button.primary:hover:not(:disabled) { background: linear-gradient(180deg, #4d1c1c, #2e0f0f); }

/* ---------- 身份抽取：翻牌 ---------- */
/* 遮罩不用纯黑：留一层暗红光晕，让牌从黑暗里「浮」出来，
   否则整屏一片死黑，牌本身就没什么存在感 */
.overlay {
  position: fixed; inset: 0; z-index: 60;
  background:
    radial-gradient(ellipse at 50% 36%, rgba(104, 30, 20, .34), transparent 56%),
    radial-gradient(ellipse at 50% 100%, rgba(46, 14, 10, .30), transparent 60%),
    rgba(3, 3, 5, .84);
  display: none; align-items: center; justify-content: center;
  backdrop-filter: blur(7px) saturate(.9); -webkit-backdrop-filter: blur(7px) saturate(.9);
}
.overlay.show { display: flex; }
.draw-wrap { text-align: center; }
.draw-title {
  letter-spacing: 10px; color: #d8452f; font-size: 13.5px; margin-bottom: 16px;
  text-shadow: 0 0 22px rgba(216, 69, 47, .45);
}
/* 牌放大了一档：原来 236×336 放在 1440 宽的屏上只有一小张，撑不起「抽身份」这个仪式 */
.idcard {
  width: clamp(248px, 28vh, 296px); height: clamp(352px, 40vh, 414px);
  margin: 0 auto; perspective: 1400px; cursor: pointer;
  filter: drop-shadow(0 24px 48px rgba(0, 0, 0, .82));
}
.idcard-inner {
  position: relative; width: 100%; height: 100%;
  transform-style: preserve-3d; transition: transform .95s cubic-bezier(.2, .8, .2, 1);
}
.idcard.flipped .idcard-inner { transform: rotateY(180deg); }
.idface {
  position: absolute; inset: 0; backface-visibility: hidden; border-radius: 13px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 18px; overflow: hidden;
}
.idback {
  background:
    repeating-linear-gradient(45deg, rgba(56, 19, 19, .50) 0 13px, rgba(26, 9, 9, .50) 13px 26px),
    radial-gradient(circle at 50% 40%, #2c1313, #0a0506 82%);
  border: 1px solid #6e2622; color: #8d4a44;
  box-shadow:
    inset 0 0 52px rgba(0, 0, 0, .92),
    inset 0 0 0 1px rgba(214, 120, 92, .14),
    0 0 34px rgba(150, 40, 28, .18);
}
/* 「伪」不再半透明到看不见：它是这张牌唯一的记号，该亮起来 */
.idback .ib-mark {
  font-size: 96px; letter-spacing: 0; color: #c0392b; opacity: .94;
  text-shadow: 0 0 26px rgba(192, 57, 43, .78), 0 0 68px rgba(192, 57, 43, .38);
}
.idback .ib-tip {
  margin-top: 18px; padding: 6px 15px; border-radius: 999px;
  font-size: 11.5px; letter-spacing: 3px; color: #f4d3c6;
  background: rgba(126, 36, 27, .38); border: 1px solid rgba(202, 92, 70, .52);
  animation: idTap 1.8s ease-in-out infinite;
}
@keyframes idTap {
  0%, 100% { opacity: .66; transform: translateY(0); }
  50% { opacity: 1; transform: translateY(-2px); }
}
.idfront {
  transform: rotateY(180deg);
  background:
    radial-gradient(circle at 50% -8%, rgba(96, 28, 22, .95), transparent 58%),
    linear-gradient(180deg, #1f1011, #120a0b 74%);
  border: 1px solid #8a3028; color: #e6d8d0;
  box-shadow:
    0 16px 40px rgba(0, 0, 0, .7),
    inset 0 0 34px rgba(192, 57, 43, .16),
    inset 0 1px 0 rgba(255, 205, 175, .10);
  justify-content: flex-start; gap: 0;
  /* 底部留出一条「印记带」：印章独占这块，文字永远压不到它 */
  padding: 20px 18px 78px; text-align: center;
}
/* 印记带的分隔线 */
.idfront::after {
  content: ''; position: absolute; left: 26px; right: 26px; bottom: 66px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(138, 48, 40, .55), transparent);
  z-index: 1;
}
/* 牌面内容统一压在水印之上：水印只当底纹，绝不能盖住字 */
.idfront > * { position: relative; z-index: 1; }
.if-camp {
  font-size: 10px; letter-spacing: 2.5px; color: #d99a86;
  padding: 3px 11px; border-radius: 999px;
  background: rgba(140, 44, 34, .22); border: 1px solid rgba(170, 66, 50, .38);
}
.if-name {
  font-size: clamp(26px, 3.4vh, 33px); font-weight: 800; letter-spacing: 7px;
  color: #f4dfd0; margin: 13px 0 6px;
  text-shadow: 0 0 20px rgba(192, 57, 43, .72);
}
.if-goal { font-size: 12.5px; line-height: 1.75; color: #cfbcb4; padding: 0 2px; }
/* 任务块单独垫一层暗底：水印颜色再淡，压在纯渐变上也还是会糊字 */
.if-task {
  margin: 15px 0 0; padding: 10px 12px 11px; text-align: left;
  font-size: 11px; line-height: 1.75; color: #bda8a0;
  background: rgba(8, 5, 7, .62);
  border: 1px solid rgba(138, 48, 40, .36); border-radius: 9px;
  box-shadow: inset 0 1px 0 rgba(255, 190, 160, .05);
}
.if-task b { display: block; color: #d8a85a; font-size: 10px; letter-spacing: 2px; margin-bottom: 5px; }
.if-note { color: #857069; font-size: 10px; }
/* 牌底的身份印记：做成一方盖上去的印，而不是压满整牌的大字水印 ——
   原来那个 104px 的「灯」正好落在身份任务文字上，字全糊了。 */
.if-seal {
  position: absolute; left: 50%; bottom: 15px; z-index: 0;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  transform: translateX(-50%) rotate(-7deg);
  font-size: 25px; font-weight: 800; line-height: 1; letter-spacing: 0;
  color: rgba(214, 96, 72, .62);
  border: 1.5px solid rgba(198, 76, 56, .40); border-radius: 7px;
  background: rgba(150, 44, 30, .07);
  box-shadow: inset 0 0 12px rgba(190, 60, 40, .16);
  pointer-events: none; user-select: none;
}
.draw-tip { font-size: 12px; color: #9c8b84; margin-top: 16px; letter-spacing: 1px; }
/* 规则说明挪到牌外：字号能放大到读得清，也不占牌面留白 */
.draw-note {
  max-width: 330px; margin: 9px auto 0;
  font-size: 11px; line-height: 1.72; color: #a2918a; text-align: center;
}
.draw-note b { color: #d09480; font-weight: 500; }
#idDone { width: 210px; margin-top: 14px; }


/* ---------- 大厅底部 & 地图图鉴入口 ---------- */
.lobby-foot { display: flex; align-items: center; gap: 14px; margin-top: 2px; }
.lobby-foot button.primary { flex: 1 1 auto; width: auto; }
.atlas-link {
  flex: 0 0 auto; font-size: 12px; color: #9a8f86; text-decoration: none;
  border: 1px solid #333; border-radius: 8px; padding: 10px 12px; white-space: nowrap;
  transition: color .15s, border-color .15s, background .15s;
}
.atlas-link:hover { color: #e0c0a8; border-color: #6a4a34; background: #1b1410; }

/* ---------- 地图图鉴页 ---------- */
.atlas { max-width: 1180px; }
.map-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; margin: 6px 0 16px; }
.mcard {
  border: 1px solid #26262e; border-radius: 12px; padding: 10px 12px 12px;
  background: linear-gradient(180deg, #14141a 0%, #0d0d12 100%);
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.mcard:hover { transform: translateY(-3px); border-color: #4a3a2a; box-shadow: 0 12px 26px rgba(0, 0, 0, 0.55); }
.mini-wrap {
  perspective: 700px; perspective-origin: 50% 46%;
  padding: 6px; border-radius: 10px; margin-bottom: 8px;
  background: radial-gradient(ellipse at 50% 116%, color-mix(in srgb, var(--theme, #3a3a48) 45%, transparent), transparent 62%),
              radial-gradient(circle at 50% 38%, #12120f, #06060a 72%);
  box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.85);
}
.mini {
  position: relative; width: 100%; aspect-ratio: 1 / 1;
  transform: rotateX(32deg); transform-style: preserve-3d;
  background: radial-gradient(circle at 50% 42%, color-mix(in srgb, var(--theme, #3a3a48) 30%, transparent), transparent 65%), #08080b;
  border: 1px solid rgba(90, 72, 44, 0.30); border-radius: 10px;
}
.mini .roads { position: absolute; inset: 0; width: 100%; height: 100%; }
.mini .roads line { stroke: #7a6440; stroke-width: 0.5; }
/* 缩略图里的地块：小六边形，按索引给一点色差，看起来像撒开的地砖 */
.mini .mn {
  position: absolute; width: 6.4%; aspect-ratio: 1; transform: translate(-50%, -50%) rotateX(-32deg);
  clip-path: polygon(50% 0%, 94% 26%, 94% 74%, 50% 100%, 6% 74%, 6% 26%);
  background: color-mix(in srgb, var(--theme, #4a4a58) 55%, #14141c);
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.6);
  opacity: calc(0.75 + (var(--t, 0) / 400));
}
.mhead { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.mhead b { font-size: 14px; letter-spacing: 2px; color: #e2d8cf; }
.mstat { font-size: 11px; color: #7d7d88; }
.mdesc { font-size: 11.5px; line-height: 1.7; color: #8b8b95; margin: 6px 0 0; }
.atlas-tip { font-size: 11.5px; line-height: 1.8; color: #7d7d88; }
.atlas-tip b { color: #b9a184; font-weight: 500; }

/* ---------- 迷雾视觉加强 ---------- */
.node { z-index: 3; }
.node.fog {
  color: #35353f;
  /* 雾里的地块：边缘糊掉、微微透出冷雾，像被水汽盖住 */
  filter: blur(0.6px) saturate(0.5);
}
.node.fog .hex {
  /* 亮度必须略高于棋盘底，否则雾块会「沉进」背景里，看起来像地图缺了一块 */
  background: radial-gradient(circle at 42% 34%, #262632 0%, #191922 46%, #0e0e15 100%);
}
.node.fog .hex::before { background: linear-gradient(180deg, #101017, #06060b); }
/* 一圈极淡的雾气，浮在雾格上方 */
.node.fog::before {
  content: ''; position: absolute; inset: -34%; border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, rgba(108, 116, 142, 0.16), rgba(70, 76, 96, 0.05) 52%, transparent 70%);
  filter: blur(5px); pointer-events: none;
  animation: fogDrift 9s ease-in-out infinite alternate;
}
@keyframes fogDrift {
  from { transform: scale(0.94) translate(0, 0); opacity: 0.55; }
  to   { transform: scale(1.10) translate(3%, -2%); opacity: 0.90; }
}
.node.fog .ni { opacity: 0.62; font-weight: 400; color: #5b5b6e; text-shadow: 0 0 6px rgba(120,130,160,0.35); }

/* 棋盘下方的规则说明 */
.fog-legend {
  max-width: 640px; margin: -22px auto 16px; padding: 0 12px;
  font-size: 11.5px; line-height: 1.85; color: #7b7b86; text-align: left;
}
.fog-legend b { color: #c6a377; font-weight: 600; }

/* 引路灯是信标：要能穿透视野渐隐，远远就看见那点光 */
.node.beam { z-index: 6; }

/* ============ SVG 场景版棋盘（暖色夕阳 · 松林 · 六角砖） ============ */
.left { max-width: 780px; }
.board-wrap {
  max-width: 700px; padding: 0; overflow: hidden;
  perspective: none; border-radius: 18px;
  background: #2a1a20;
  box-shadow: 0 22px 48px rgba(0, 0, 0, 0.62), inset 0 0 0 1px rgba(214, 168, 112, 0.22);
}
.board {
  transform: none; aspect-ratio: 1 / 1;
  background: none; border: 0; border-radius: 0; box-shadow: none;
  overflow: hidden;
}
svg.scene { display: block; width: 100%; height: 100%; }
svg.scene text { user-select: none; pointer-events: none; }
.sc-tile.can { cursor: pointer; }
.sc-tile.can:hover > polygon:nth-child(2) { filter: brightness(1.12); }

/* 读数挪到左下，右上角留给人物头像条 */
.fogstat { left: 14px; right: auto; top: auto; bottom: 14px; }

/* 左上角行动条 */
.hud-move {
  position: absolute; left: 14px; top: 14px; z-index: 12;
  display: flex; align-items: baseline; gap: 7px;
  padding: 6px 15px; border-radius: 20px;
  background: rgba(30, 19, 15, 0.80); border: 1px solid rgba(214, 168, 112, 0.50);
  color: #f2e2cb; font-size: 12.5px; letter-spacing: 1.4px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
}
.hud-move b { font-size: 19px; line-height: 1; color: #ffd98c; font-weight: 700; }
.hud-move .hm-lbl { font-size: 11px; color: #c9b295; letter-spacing: 2px; }
.hud-move .dim { color: #b9a48c; letter-spacing: 0.6px; }

/* 右上角人物头像条 */
.hud-players {
  position: absolute; right: 12px; top: 12px; z-index: 12;
  display: flex; flex-direction: row-reverse; gap: 6px; flex-wrap: wrap; max-width: 62%;
}
.hpc {
  display: flex; align-items: center; gap: 5px; padding: 2px 9px 2px 2px;
  border-radius: 20px; background: rgba(26, 17, 13, 0.82);
  border: 1px solid rgba(196, 152, 104, 0.38);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.42);
}
.hpc .face { width: 26px; height: 26px; display: block; border-radius: 50%; }
.hpc-name { font-size: 11px; color: #ecdcC6; letter-spacing: 0.4px; }
.hpc-hp { font-size: 9px; color: #e0685a; letter-spacing: 1px; }
.hpc.cur { border-color: #ffd98c; box-shadow: 0 0 12px rgba(255, 202, 120, 0.42); }
.hpc.you .hpc-name { color: #ffe8bf; }
.hpc.dead { opacity: 0.42; filter: grayscale(1); }

/* 装饰层不接收点击，否则会挡住可走地块的点击判定 */
svg.scene .sc-wash, svg.scene .sc-props, svg.scene .sc-mist, svg.scene .lampglow { pointer-events: none; }

/* ================================================================
   动起来：地块呼吸、棋子走动、灯光摇曳、骰子滚动、事件浮层
   —— 所有动画只用 transform / opacity / stroke，避免每帧重排
   ================================================================ */

/* 棋盘放大一档：地图扩到 200 格后靠镜头取景，画布本身给足尺寸 */
.left { max-width: 860px; flex: 1 1 700px; }
.board-wrap { max-width: 780px; }
.board { position: relative; }

/* ---------- 地块：状态切换是淡入淡出，不是瞬切 ---------- */
.sc-tile { pointer-events: none; }
.sc-tile.can { pointer-events: auto; cursor: pointer; }
.sc-tile .face-fog, .sc-tile .face-known { transition: opacity .45s ease; }
.sc-tile.fog .face-known { opacity: 0; }
.sc-tile:not(.fog) .face-fog { opacity: 0; }
.sc-tile .hl { opacity: 0; transition: opacity .3s ease, stroke-width .2s; }
.sc-tile.can .hl {
  opacity: 1;
  animation: reachPulse 2.4s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
.sc-tile.can:hover .hl { stroke-width: 6.5; opacity: 1; }
@keyframes reachPulse {
  0%, 100% { opacity: 0.55; stroke-width: 3.2; }
  50%      { opacity: 1;    stroke-width: 5; }
}
/* 点了之后先亮一下，让人知道「这一下点到了」 */
.sc-tile.pending .hl { opacity: 1; stroke: #ffe6a8; stroke-width: 7; animation: pendingFlash .5s ease-out; }
@keyframes pendingFlash {
  0%   { opacity: 1; stroke-width: 12; }
  100% { opacity: 1; stroke-width: 5; }
}
/* 落地涟漪 */
.sc-tile.landed .hl { opacity: 1; stroke: #ffd98c; animation: landRing .72s ease-out forwards; }
@keyframes landRing {
  0%   { opacity: 1; stroke-width: 3; }
  35%  { opacity: 0.95; stroke-width: 11; }
  100% { opacity: 0; stroke-width: 2; }
}
/* 灯照到的地块：暖光会呼吸 */
.sc-tile .litwash { opacity: 0; transition: opacity .7s ease; pointer-events: none; }
.sc-tile.lit .litwash {
  opacity: .55;
  animation: lampBreathe 3.8s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
@keyframes lampBreathe {
  0%, 100% { opacity: .34; }
  50%      { opacity: .62; }
}

/* ---------- 迷雾：会飘 ---------- */
.sc-mist .mistpuff { opacity: 0; transition: opacity .8s ease; }
.sc-mist .mistpuff.on {
  opacity: 1;
  animation: mistDrift 11s ease-in-out infinite alternate;
  animation-delay: var(--fd, 0s);
}
@keyframes mistDrift {
  from { transform: translate(0, 0) scale(0.96); }
  to   { transform: translate(9px, -6px) scale(1.06); }
}

/* ---------- 棋子：走动、落地弹跳、呼吸 ---------- */
.sc-units { pointer-events: none; }
.unit {
  transition: transform .3s cubic-bezier(.33, 1.1, .5, 1);
  transform-box: view-box;
}
.unit.jump { transition: none; }
.unit .art {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transform: scale(var(--as, 2));
  animation: unitIdle 4.4s ease-in-out infinite;
}
@keyframes unitIdle {
  0%, 100% { transform: scale(var(--as, 2)) translateY(0); }
  50%      { transform: scale(var(--as, 2)) translateY(-1.4px); }
}
.unit.hop .unit-inner { animation: unitHop .34s cubic-bezier(.3, .9, .4, 1); }
@keyframes unitHop {
  0%   { transform: translateY(0); }
  45%  { transform: translateY(-9px); }
  70%  { transform: translateY(-2px); }
  100% { transform: translateY(0); }
}
.unit.spawn { animation: unitIn .5s ease-out; }
@keyframes unitIn {
  from { opacity: 0; transform-box: fill-box; }
  to   { opacity: 1; }
}
.unit.gone { animation: unitOut .45s ease-in forwards; }
@keyframes unitOut {
  to { opacity: 0; }
}
.unit .halo { animation: haloBreathe 2.8s ease-in-out infinite; }
@keyframes haloBreathe {
  0%, 100% { rx: 28; opacity: .55; }
  50%      { rx: 34; opacity: .9; }
}
.unit .selfring { animation: selfRing 2.6s ease-in-out infinite; }
@keyframes selfRing {
  0%, 100% { opacity: .45; }
  50%      { opacity: .95; }
}
.unit.dead { opacity: .62; }
.unit.dead .nprect { fill: rgba(40, 14, 14, 0.85); stroke: rgba(190, 80, 70, 0.5); }
.unit.cur .nprect { stroke: rgba(255, 208, 130, 0.9); }
.unit .buff { animation: buffBob 3s ease-in-out infinite; animation-delay: calc(var(--bi, 0) * .3s); }
@keyframes buffBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}

/* ---------- 引路灯：火光会跳 ---------- */
.lamp .lamp-glow { animation: lampPulse 3.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.lamp .lamp-ring { animation: lampRing 3.4s ease-out infinite; transform-box: fill-box; transform-origin: center; }
.lamp .lamp-core .flame { animation: flameFlick .9s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.lamp:nth-child(2) .lamp-glow { animation-delay: .7s; }
.lamp:nth-child(3) .lamp-glow { animation-delay: 1.4s; }
.lamp:nth-child(4) .lamp-glow { animation-delay: 2.1s; }
@keyframes lampPulse {
  0%, 100% { opacity: .72; transform: scale(0.94); }
  50%      { opacity: 1;   transform: scale(1.08); }
}
@keyframes lampRing {
  0%   { opacity: .55; transform: scale(0.7); }
  70%  { opacity: .10; transform: scale(1.5); }
  100% { opacity: 0;   transform: scale(1.6); }
}
@keyframes flameFlick {
  0%, 100% { opacity: 1;   transform: scale(1); }
  35%      { opacity: .78; transform: scale(1.12, .9); }
  65%      { opacity: .95; transform: scale(.92, 1.08); }
}
.sc-lamps.reignite .lamp-glow { animation: reignite 1.3s ease-out; }
@keyframes reignite {
  0%   { opacity: 0; transform: scale(.3); }
  40%  { opacity: 1; transform: scale(1.6); }
  100% { opacity: .8; transform: scale(1); }
}

/* ---------- 路线预览 ---------- */
.sc-path .pathline {
  animation: dashMove .7s linear infinite;
  filter: drop-shadow(0 0 3px rgba(160, 240, 120, .7));
}
@keyframes dashMove { to { stroke-dashoffset: -19; } }
.sc-path .stepdot { animation: dotPop .22s cubic-bezier(.2, 1.5, .4, 1) both; }
@keyframes dotPop {
  from { opacity: 0; transform: scale(.4); transform-box: fill-box; transform-origin: center; }
  to   { opacity: 1; transform: scale(1); }
}

/* ---------- 入场：整幅沙盘淡入 ---------- */
svg.scene.enter { animation: sceneIn .8s ease-out; }
@keyframes sceneIn {
  from { opacity: 0; transform: scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ---------- HUD ---------- */
.hud-move.pop b { animation: popNum .38s cubic-bezier(.2, 1.6, .4, 1); }
@keyframes popNum {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.45); color: #fff3cf; }
  100% { transform: scale(1); }
}
.hud-move.hidden { display: none; }
.cam-btn {
  position: absolute; right: 12px; bottom: 12px; z-index: 12;
  padding: 4px 10px; font-size: 11px; letter-spacing: .5px;
  color: #cbb69a; background: rgba(26, 17, 13, .82);
  border: 1px solid rgba(196, 152, 104, .38); border-radius: 14px; margin: 0;
}
.cam-btn:hover { background: rgba(48, 32, 22, .9); color: #ffe0b4; }
.cam-btn.full { border-color: #ffd98c; color: #ffe6b8; }
.fogstat { font-size: 10.5px; }

/* ---------- 顶部：回合标签 / 按钮 ---------- */
.top-btns { display: flex; gap: 6px; align-items: center; }
button.ghost {
  background: #17171c; border-color: #33333c; color: #9a939c;
  padding: 6px 12px; font-size: 12px;
}
button.ghost.off { color: #6a5a5a; }
.turn-tag {
  margin-left: 10px; padding: 2px 10px; border-radius: 12px;
  font-size: 11.5px; letter-spacing: 1px;
  color: #f0d9b6; background: rgba(90, 60, 30, .5); border: 1px solid rgba(200, 150, 90, .35);
}
.turn-tag.mine {
  color: #22150c; background: linear-gradient(180deg, #ffd98c, #e0a95e);
  border-color: #ffe6b8; font-weight: 700;
  animation: tagPulse 1.8s ease-in-out infinite;
}
@keyframes tagPulse {
  0%, 100% { box-shadow: 0 0 0 rgba(255, 210, 140, 0); }
  50%      { box-shadow: 0 0 14px rgba(255, 210, 140, .55); }
}

/* ---------- 自身信息 ---------- */
.self-line { color: #d9d2c9; }
.skillline { font-size: 11.5px; color: #8a848c; margin-top: 2px; }
.skillline.warn { color: #e0a45c; }
.bad { color: #d05040; }
.dead-line { color: #c0392b; margin-top: 2px; }
.buffs-line { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 4px; }
.buffchip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border-radius: 10px; font-size: 10.5px;
  color: #f0d6a8; background: rgba(80, 52, 22, .55); border: 1px solid rgba(214, 168, 112, .4);
}
.buffchip b { color: #ffd98c; font-weight: 600; }
.buffchip i { font-style: normal; color: #c9a97a; }
.lampbar { font-size: 11px; color: #9a8f7c; margin-top: 4px; }
.lampbar b { color: #ffd98c; }
.identity-box { background: #131317; border: 1px solid #2c2c34; border-radius: 8px; padding: 8px 10px; margin-top: 6px; }
.igoal { font-size: 11.5px; color: #98929a; margin-top: 2px; }
.iname { color: #d8b98a; font-weight: 600; letter-spacing: 1px; }
.done { color: #7fc46a; }

/* ---------- 操作区 ---------- */
.actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.actions button { margin: 0; }
.mvinfo {
  width: 100%; font-size: 13px; color: #d8c9b4; margin-bottom: 4px;
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.mvinfo b { color: #ffd98c; font-size: 17px; }
.mvinfo span { font-size: 11px; color: #857d78; }
button.primary {
  background: linear-gradient(180deg, #a8352b, #7d1f18); border-color: #c04a3a; color: #ffe8de;
}
button.primary:hover:not(:disabled) { background: linear-gradient(180deg, #c44134, #94261d); }
button.dice-btn {
  background: linear-gradient(180deg, #f0cf94, #cfa055); border-color: #ffe6b8; color: #2a1608;
  font-weight: 800; letter-spacing: 2px; font-size: 15px; padding: 11px 26px;
  animation: diceBtn 2.2s ease-in-out infinite;
}
button.dice-btn:hover:not(:disabled) { animation: none; background: linear-gradient(180deg, #ffe0ab, #dfae62); }
@keyframes diceBtn {
  0%, 100% { box-shadow: 0 0 0 rgba(255, 210, 140, 0); }
  50%      { box-shadow: 0 0 18px rgba(255, 210, 140, .55); }
}
button.danger { background: #2b1414; border-color: #7a2a24; color: #efb2a6; }

/* ---------- 玩家卡 ---------- */
.pcard.mine { border-color: #4a3a22; }
.pcard .act { color: #ffd98c; font-size: 10px; letter-spacing: 1px; }
.pcard .idtag { color: #c0392b; }
.pcard .minibuff {
  display: inline-block; padding: 0 4px; border-radius: 6px;
  background: rgba(80, 52, 22, .5); color: #f0d6a8; font-size: 10px;
}

/* ---------- 战报 ---------- */
.log .lg { display: flex; gap: 6px; align-items: baseline; line-height: 1.55; }
.log .lg-ic { opacity: .65; flex: 0 0 auto; width: 12px; text-align: center; font-size: 11px; }
.log .lg.kill { color: #d06052; }
.log .lg.item { color: #a8c08a; }
.log .lg.lamp { color: #d8b46a; }
.log .lg.task { color: #c9a86a; }
.log .lg.trap { color: #c87a5a; }
.log .lg.guard { color: #b09a7a; }
.log .lg.teleport { color: #8fa8c0; }
.log .lg.win { color: #ffd98c; }
.log .lg.move { color: #6f6a66; }
.log-more {
  width: 100%; margin: 6px 0 0; padding: 5px; font-size: 11px;
  background: #141418; border-color: #2a2a32; color: #7d777f;
}
.log-more.hidden { display: none; }

/* ================================================================
   FX 图层
   ================================================================ */
.fx-root { position: fixed; inset: 0; z-index: 60; pointer-events: none; }

.fx-vignette {
  position: absolute; inset: 0; opacity: 0;
  box-shadow: inset 0 0 140px 40px rgba(180, 18, 18, .8);
  transition: opacity .45s ease;
}
.fx-vignette.on { animation: vigPulse .75s ease-out; }
@keyframes vigPulse {
  0%   { opacity: 0; }
  18%  { opacity: 1; }
  100% { opacity: 0; }
}

/* 幕布公告 */
.fx-banner {
  position: absolute; left: 50%; top: 22%; transform: translateX(-50%);
  opacity: 0; transition: opacity .35s ease; text-align: center; white-space: nowrap;
}
.fx-banner.show { opacity: 1; }
.bn-inner {
  transform: translateY(-12px) scale(.94);
  transition: transform .45s cubic-bezier(.2, 1.4, .4, 1);
  padding: 14px 30px; border-radius: 14px;
  background: radial-gradient(ellipse at 50% 0%, rgba(120, 30, 24, .92), rgba(18, 10, 10, .92));
  border: 1px solid rgba(210, 120, 90, .45);
  box-shadow: 0 22px 50px rgba(0, 0, 0, .7);
}
.fx-banner.show .bn-inner { transform: none; }
.bn-ico { font-size: 30px; line-height: 1; color: #ffb9a0; margin-bottom: 4px; }
.bn-title {
  font-size: 30px; letter-spacing: 8px; font-weight: 800; color: #ffe6d4;
  font-family: Georgia, "Songti SC", serif;
  text-shadow: 0 2px 14px rgba(200, 60, 30, .8);
}
.bn-sub { margin-top: 5px; font-size: 12.5px; letter-spacing: 2px; color: #d0a894; }
.bn-inner.tone-lamp { background: radial-gradient(ellipse at 50% 0%, rgba(150, 110, 40, .92), rgba(18, 12, 8, .94)); border-color: rgba(230, 190, 110, .5); }
.bn-inner.tone-lamp .bn-ico, .bn-inner.tone-lamp .bn-title { color: #ffe0a0; }
.bn-inner.tone-turn { background: radial-gradient(ellipse at 50% 0%, rgba(60, 90, 60, .9), rgba(10, 14, 10, .94)); border-color: rgba(150, 210, 130, .45); }
.bn-inner.tone-turn .bn-ico, .bn-inner.tone-turn .bn-title { color: #d6ffbe; }
.bn-inner.tone-turn .bn-title { letter-spacing: 12px; }
.bn-inner.tone-win { background: radial-gradient(ellipse at 50% 0%, rgba(150, 120, 40, .94), rgba(20, 14, 8, .95)); border-color: rgba(255, 216, 140, .6); }
.bn-inner.tone-win .bn-title { color: #ffe9b8; letter-spacing: 10px; }
.bn-inner.tone-ward { background: radial-gradient(ellipse at 50% 0%, rgba(50, 80, 90, .9), rgba(8, 12, 14, .94)); border-color: rgba(150, 210, 220, .45); }
.bn-inner.tone-ward .bn-title { color: #cdf2f8; }

/* 事件卡片 */
.fx-toasts {
  position: absolute; left: 50%; transform: translateX(-50%);
  /* 必须让开顶栏（top:10 + 高 28~34）和「剩余步数」条（top:50~54）
     —— 原来写死 top:14px，第一张卡片正好盖住房间名/阶段/轮到你。 */
  top: calc(88px + var(--safe-t));
  display: flex; flex-direction: column; gap: 6px; align-items: stretch;
  width: min(92vw, 400px);
  pointer-events: none;
  max-height: 46vh; overflow: hidden;
}
.toast {
  display: flex; gap: 9px; align-items: center;
  padding: 8px 12px; border-radius: 10px;
  background: rgba(26, 18, 15, .94); border: 1px solid rgba(200, 160, 110, .32);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
  animation: toastIn .34s cubic-bezier(.2, 1.3, .4, 1);
}
.toast.out { animation: toastOut .36s ease-in forwards; }
@keyframes toastIn {
  from { opacity: 0; transform: translateY(-10px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes toastOut {
  to { opacity: 0; transform: translateY(-6px) scale(.98); }
}
.toast .t-ico {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; color: #ffd98c; background: rgba(90, 62, 30, .55);
  border: 1px solid rgba(214, 168, 112, .4);
}
.toast .t-body { display: flex; flex-direction: column; line-height: 1.35; min-width: 0; }
.toast .t-body b { font-size: 12.5px; color: #f4e6d4; font-weight: 600; }
.toast .t-body i { font-style: normal; font-size: 11px; color: #9a8f86; }
.toast.tone-kill .t-ico { color: #ff9a86; background: rgba(110, 30, 24, .6); border-color: rgba(200, 90, 70, .5); }
.toast.tone-item .t-ico { color: #cfe8a8; background: rgba(60, 90, 40, .55); }
.toast.tone-lamp .t-ico { color: #ffe0a0; background: rgba(120, 88, 30, .6); }
.toast.tone-trap .t-ico { color: #ffb090; background: rgba(110, 50, 26, .6); }
.toast.tone-teleport .t-ico { color: #b6d4ee; background: rgba(40, 62, 90, .6); }
.toast.tone-grow .t-ico { color: #ffe0a0; background: rgba(96, 74, 26, .6); }

/* 浮动文字 */
.fx-floats { position: absolute; inset: 0; }
.float {
  position: absolute; transform: translate(-50%, -50%);
  font-size: 16px; font-weight: 800; letter-spacing: 1px;
  color: #ffe6b8; text-shadow: 0 2px 8px rgba(0, 0, 0, .9), 0 0 14px rgba(255, 200, 120, .5);
  animation: floatUp 1.2s ease-out forwards;
}
.float.tone-item { color: #d6f0ac; }
.float.tone-buff { color: #ffe0a0; }
@keyframes floatUp {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.7); }
  25%  { opacity: 1; transform: translate(-50%, -70%) scale(1.12); }
  100% { opacity: 0; transform: translate(-50%, -150%) scale(1); }
}

/* 骰子 */
.fx-dice {
  position: fixed; inset: 0; z-index: 72;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.fx-dice .dice-stage {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 18px 30px 14px; border-radius: 16px;
  background: radial-gradient(ellipse at 50% 20%, rgba(60, 40, 22, .92), rgba(12, 8, 8, .94));
  border: 1px solid rgba(214, 168, 112, .45);
  box-shadow: 0 26px 60px rgba(0, 0, 0, .75);
  animation: diceIn .22s ease-out;
}
.fx-dice.out .dice-stage { animation: diceOut .26s ease-in forwards; }
@keyframes diceIn {
  from { opacity: 0; transform: scale(.86) translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes diceOut {
  to { opacity: 0; transform: scale(.94); }
}
.dice-who { font-size: 11px; letter-spacing: 3px; color: #c9ab84; }
.dice-slot { animation: tumble .3s linear infinite; }
.dice-slot.tick { animation: tick .1s ease-out; }
.dice-slot.settle { animation: diceSettle .42s cubic-bezier(.2, 1.5, .4, 1); }
@keyframes tumble {
  0%   { transform: rotate(-6deg) translateY(0); }
  50%  { transform: rotate(7deg) translateY(-5px); }
  100% { transform: rotate(-6deg) translateY(0); }
}
@keyframes tick {
  0% { transform: scale(.94); }
  100% { transform: scale(1); }
}
@keyframes diceSettle {
  0%   { transform: scale(1.35) rotate(8deg); }
  60%  { transform: scale(.94) rotate(-3deg); }
  100% { transform: scale(1) rotate(0); }
}
.die {
  width: 82px; height: 82px; border-radius: 14px; position: relative;
  background: linear-gradient(150deg, #fff8e8, #d9c09a);
  box-shadow: 0 10px 22px rgba(0, 0, 0, .65), inset 0 -6px 0 rgba(120, 90, 60, .25),
              inset 0 3px 6px rgba(255, 255, 255, .8);
}
.die .pip {
  position: absolute; inset: 13%;
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
}
.die .pip i { width: 13px; height: 13px; border-radius: 50%; justify-self: center; align-self: center; }
.die .pip i.on { background: #2c1a10; box-shadow: inset 0 1px 1px rgba(255, 255, 255, .35); }
.dice-out { font-size: 12px; letter-spacing: 2px; color: #cdb695; }
.dice-out b { font-size: 22px; color: #ffd98c; letter-spacing: 0; }

/* 震屏 / 回合高亮 */
.fx-shake { animation: shake .42s cubic-bezier(.36, .07, .19, .97); }
@keyframes shake {
  10%, 90% { transform: translate(-1px, 0); }
  20%, 80% { transform: translate(2px, -1px); }
  30%, 50%, 70% { transform: translate(-3px, 1px); }
  40%, 60% { transform: translate(3px, 0); }
}
.fx-turnglow {
  animation: turnGlow 1.3s ease-out;
}
@keyframes turnGlow {
  0%   { box-shadow: 0 0 0 rgba(255, 210, 140, 0), 0 22px 48px rgba(0, 0, 0, .62); }
  40%  { box-shadow: 0 0 46px rgba(255, 210, 140, .55), 0 22px 48px rgba(0, 0, 0, .62); }
  100% { box-shadow: 0 0 0 rgba(255, 210, 140, 0), 0 22px 48px rgba(0, 0, 0, .62); }
}

/* ================================================================
   游戏界面 = 一屏应用外壳（fixed 铺满视口）
   —— 棋盘按剩余高度自适应，行动按钮永远在可视区内，不再被折叠
   ================================================================ */
#game.panel {
  position: fixed; inset: 6px; max-width: none; margin: 0;
  display: flex; flex-direction: column; overflow: hidden;
  padding: 12px 14px;
  background: radial-gradient(ellipse at 20% 0%, #1b1417, #0c0b0e 62%);
}
#game.hidden { display: none; }
#game .top { flex: 0 0 auto; margin-bottom: 10px; }
#game .layout {
  flex: 1 1 auto; min-height: 0; flex-wrap: nowrap; gap: 14px;
  align-items: stretch;
}
#game .left {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  max-width: none; flex: 1 1 auto;
}
#game .board-wrap {
  flex: 1 1 auto; min-height: 0; max-width: none; margin: 0;
  border-radius: 14px; overflow: hidden;
  background: #0b0709;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.66), inset 0 0 0 1px rgba(196, 152, 104, 0.18);
}
#game .board {
  width: 100%; height: 100%; aspect-ratio: auto;
  position: relative; border-radius: 0; overflow: hidden;
}
#game .board canvas, #game .board-canvas {
  display: block; width: 100% !important; height: 100% !important;
  touch-action: none; cursor: grab;
}
#game .board canvas:active { cursor: grabbing; }
#game .fog-legend { flex: 0 0 auto; margin: 7px 0 0; }
#game .actions { flex: 0 0 auto; margin-top: 9px; min-height: 0; }

#game .right {
  display: flex; flex-direction: column; gap: 9px; min-height: 0;
  flex: 0 0 344px; width: 344px;
}
#game #players { flex: 0 0 auto; }
#game .log { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
#game .log-more { flex: 0 0 auto; }
#game .chat { flex: 0 0 auto; margin-top: 0; }

/* 窄屏：右侧栏降到下方并允许整体滚动 */
@media (max-width: 1080px) {
  #game .layout { flex-wrap: wrap; overflow-y: auto; }
  #game .board-wrap { flex: 0 0 auto; height: 62vh; }
  #game .right { flex: 1 1 100%; width: auto; }
  #game .log { flex: 0 0 auto; max-height: 220px; }
}

/* ---------- 小地图：大地图导航 ---------- */
.minimap {
  position: absolute; left: 12px; bottom: 44px; z-index: 12;
  border-radius: 9px;
  background: rgba(9, 7, 10, 0.74);
  border: 1px solid rgba(150, 120, 80, 0.34);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.55), inset 0 0 26px rgba(0, 0, 0, 0.5);
  cursor: crosshair;
  touch-action: none;
  opacity: 0.94;
  transition: opacity .18s;
}
.minimap:hover { opacity: 1; }
@media (max-width: 1180px) {
  .minimap { width: 132px !important; height: 132px !important; bottom: 40px; }
}
@media (max-height: 760px) {
  .minimap { width: 128px !important; height: 128px !important; }
}

/* ---------- 语音聊天 ---------- */
.voice-btn {
  position: absolute; right: 12px; bottom: 44px; z-index: 12;
  display: flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 16px;
  font-size: 11px; letter-spacing: .5px; cursor: pointer;
  color: #b9a894;
  background: rgba(18, 13, 12, 0.86);
  border: 1px solid rgba(150, 120, 88, 0.42);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
  transition: color .18s, border-color .18s, background .18s;
  font-family: inherit;
}
.voice-btn:hover { color: #e8d2b4; border-color: rgba(196, 152, 104, 0.7); }
.voice-btn.on {
  color: #9ee06a; border-color: rgba(158, 224, 106, 0.62);
  background: rgba(20, 34, 16, 0.88);
}
.voice-btn.muted { color: #e8b457; border-color: rgba(232, 180, 87, 0.55); }
.voice-btn.dead { color: #d9604f; border-color: rgba(217, 96, 79, 0.55); cursor: not-allowed; }
.voice-btn.err { color: #d9604f; border-color: rgba(217, 96, 79, 0.55); }
.voice-btn:disabled { opacity: .6; }

/* 头像条：开麦小点 + 说话光环 */
.hpc { position: relative; }
.hpc.von::after {
  content: ''; position: absolute; left: 4px; top: 4px;
  width: 6px; height: 6px; border-radius: 50%;
  background: #9ee06a; box-shadow: 0 0 6px rgba(158, 224, 106, .9);
}
.hpc.talking {
  border-color: rgba(158, 224, 106, 0.9);
  box-shadow: 0 0 0 1px rgba(158, 224, 106, .55), 0 0 18px rgba(158, 224, 106, .5);
  animation: talkPulse 1s ease-in-out infinite;
}
@keyframes talkPulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(158, 224, 106, .5), 0 0 10px rgba(158, 224, 106, .34); }
  50%      { box-shadow: 0 0 0 2px rgba(158, 224, 106, .92), 0 0 24px rgba(158, 224, 106, .62); }
}

/* toast 的重复计数（同一条消息合并成 ×N） */
.toast .t-count { margin-left: 6px; font-size: 10px; color: #ffd98c; opacity: .85; }

/* ---------- 背包：道具是「摆出来的小模型」，不是一段文字 ---------- */
.bag { flex: 1 1 100%; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bag-head {
  flex: 0 0 auto; font-size: 11px; color: #7d7570; letter-spacing: 2px;
  display: flex; align-items: baseline; gap: 2px; padding-right: 2px;
}
.bag-head b { color: #d8b98a; font-size: 14px; }
.bag-head i { font-style: normal; color: #5f5852; }
.bag-list { display: flex; gap: 8px; flex-wrap: wrap; }
.bag-empty { font-size: 11.5px; color: #6a6460; }

.item-card {
  position: relative; width: 84px; padding: 5px 4px 7px; margin: 0;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  background: linear-gradient(180deg, #1c1a20 0%, #121116 100%);
  border: 1px solid #2f2b34; border-radius: 10px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04), 0 2px 6px rgba(0, 0, 0, .5);
  transition: transform .14s ease, border-color .14s ease, box-shadow .14s ease;
  color: inherit; font: inherit; cursor: pointer;
}
.item-card:hover, .item-card.hot {
  transform: translateY(-3px); border-color: #7a5a34;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), 0 6px 16px rgba(0, 0, 0, .6), 0 0 0 1px rgba(200, 150, 90, .18);
}
.item-card .ic-art { display: block; line-height: 0; filter: drop-shadow(0 3px 4px rgba(0, 0, 0, .55)); }
.item-card .ic-art svg { display: block; }
.item-card .ic-name { font-size: 11.5px; color: #ddd2c4; letter-spacing: .5px; }
.item-card .ic-eff { font-size: 10px; color: #8f8578; }
.item-card .ic-badge {
  position: absolute; top: -6px; right: -4px; font-size: 9px; line-height: 1;
  padding: 2px 5px; border-radius: 6px; letter-spacing: 1px;
  background: linear-gradient(180deg, #7a5cae, #452a72); border: 1px solid #b79ce8;
  color: #f0e4ff; box-shadow: 0 0 8px rgba(150, 110, 220, .45);
}
.item-card.relic { border-color: #4a3a66; background: linear-gradient(180deg, #221d30 0%, #141019 100%); }
.item-card.relic:hover, .item-card.relic.hot { border-color: #8a6ac0; box-shadow: 0 6px 18px rgba(0, 0, 0, .6), 0 0 0 1px rgba(160, 120, 230, .3); }
.item-card.relic .ic-name { color: #e3d8f4; }

/* ---------- 悬停说明框 ---------- */
.item-tip {
  position: fixed; z-index: 9998; width: 274px; padding: 12px 13px 11px;
  background: linear-gradient(180deg, #191720 0%, #100f14 100%);
  border: 1px solid #3c3448; border-radius: 11px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .72), inset 0 1px 0 rgba(255, 255, 255, .05);
  color: #cfc7bd; pointer-events: auto;
  animation: tipIn .13s ease-out;
}
.item-tip[hidden] { display: none !important; }
@keyframes tipIn { from { opacity: 0; transform: translateY(4px) scale(.98); } to { opacity: 1; transform: none; } }
.item-tip::after {
  content: ''; position: absolute; left: var(--ax, 50%); width: 10px; height: 10px;
  background: #14121a; border-right: 1px solid #3c3448; border-bottom: 1px solid #3c3448;
  transform: translateX(-50%) rotate(45deg);
}
.item-tip.up::after { bottom: -6px; }
.item-tip.down::after { top: -6px; transform: translateX(-50%) rotate(225deg); }

.tip-top { display: flex; align-items: center; gap: 9px; }
.tip-art { flex: 0 0 auto; line-height: 0; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, .6)); }
.tip-name { font-size: 15px; color: #f0e6d8; letter-spacing: 1px; }
.tip-cat { font-size: 10px; margin-top: 3px; letter-spacing: 1px; }
.tip-cat.common { color: #8f8578; }
.tip-cat.relic { color: #b79ce8; }
.tip-effect {
  margin-top: 9px; padding: 6px 9px; border-radius: 7px; font-size: 14px; letter-spacing: .5px;
  color: #ffdfa6; background: rgba(255, 200, 120, .07); border-left: 2px solid #b98a3c;
}
.tip-meta { display: flex; gap: 12px; margin-top: 7px; font-size: 11px; color: #918a82; }
.tip-meta b { color: #6f6860; font-weight: 400; margin-right: 4px; }
.tip-detail { margin-top: 8px; font-size: 11.5px; line-height: 1.66; color: #a49b91; }
.tip-foot { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.tip-use {
  padding: 5px 14px; margin: 0; font-size: 12px; border-radius: 7px;
  background: linear-gradient(180deg, #a8352b, #7d1f18); border-color: #c04a3a; color: #ffe8de;
}
.tip-use:hover { background: linear-gradient(180deg, #c44134, #94261d); }
.tip-hint { font-size: 10px; color: #655f59; }

/* ---------- 多端加入（大厅）：局域网地址 + 二维码 ---------- */
.joinbox {
  margin: 4px 0 14px; border: 1px solid #2a2a30; border-radius: 10px;
  background: #121216; overflow: hidden;
}
.joinbox-head {
  display: flex; align-items: baseline; gap: 9px; padding: 8px 12px;
  background: #17171c; border-bottom: 1px solid #24242a;
}
.joinbox-head span { font-size: 13px; color: #d8b98a; letter-spacing: 2px; }
.joinbox-head i { font-style: normal; font-size: 11px; color: #6d6d75; }
.joinbox-body { display: flex; gap: 14px; padding: 12px; align-items: center; }
.join-gate { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 14px 8px; }
.join-start-btn {
  padding: 10px 32px; font-size: 14px; letter-spacing: 3px; cursor: pointer;
  background: linear-gradient(180deg, #2e4a42, #1c2f2a); color: #c8e6dc;
  border: 1px solid #3d6a5c; border-radius: 8px;
}
.join-start-btn:hover:not(:disabled) { background: linear-gradient(180deg, #3d6a5c, #274a3e); }
.join-start-btn:disabled { opacity: 0.6; cursor: wait; }
.join-gate-tip { font-size: 11px; color: #5f5852; text-align: center; }
.join-panel { display: flex; gap: 14px; align-items: center; width: 100%; }
.join-panel.hidden { display: none; }
.join-qr {
  flex: 0 0 auto; width: 116px; height: 116px; padding: 6px;
  background: #e8e2d6; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
}
.join-qr svg { width: 100%; height: 100%; display: block; }
.join-qr-ph { font-size: 10px; color: #4a4640; text-align: center; padding: 4px; line-height: 1.4; }
.join-info { flex: 1 1 auto; min-width: 0; }
.join-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
.join-url {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 12.5px; color: #9fd6c8; text-decoration: none;
  border-bottom: 1px dashed #3a5a52; word-break: break-all;
}
.join-url:hover { color: #c8f0e6; border-bottom-color: #6a9a8c; }
.join-iface { font-size: 10px; color: #5f5852; }
.join-copy { padding: 2px 8px; margin: 0; font-size: 10.5px; border-radius: 5px; background: #241a1a; }
.join-copy.ok { color: #7fc46a; border-color: #3a5a34; }
.join-tip { font-size: 11.5px; color: #b06a5a; }
.join-note { font-size: 11px; color: #7d7570; line-height: 1.65; margin-top: 2px; }
.join-note b { color: #c9a97a; }

/* ---------- 手机 / 平板：单列、手指友好的尺寸与手势 ---------- */
@media (max-width: 820px) {
  body { padding: 10px; }
  .panel { padding: 14px; border-radius: 10px; }
  h1 { font-size: 25px; letter-spacing: 10px; }
  .sub { margin-bottom: 12px; }
  .joinbox-body { flex-wrap: wrap; gap: 10px; }
  .join-panel { flex-wrap: wrap; gap: 10px; }
  .join-qr { width: 104px; height: 104px; }
  .hero-cards { gap: 8px; }
  .hcard { flex: 1 1 calc(50% - 8px); }

  /* 注意：这里只管大厅/通用排版。
     游戏内的浮层尺寸全部由下面 V4 的「紧凑档」统一收口——
     以前这里留着 #selfBox{width:100%} 这种旧布局的 ID 规则，
     优先级比 .self-box 高，会把左下状态卡撑满整条底部、把行动坞压扁。 */
  .bag { gap: 8px; }
  .bag-list { overflow-x: auto; padding-bottom: 2px; -webkit-overflow-scrolling: touch; }
  .item-card { width: 76px; }
  .item-tip { width: min(276px, calc(100vw - 20px)); }
  .tip-detail { font-size: 12px; }
  .chat-input input { font-size: 16px; }   /* iOS 小于 16px 会自动放大页面 */
}

/* 背包行：常驻在操作区下方 */
.bag-row { margin-top: 9px; }
.bag-row:empty { display: none; }

/* ---------- 大厅：正在等待的局 ---------- */
.rooms { margin: 0 0 14px; }
.rooms-head {
  display: flex; align-items: baseline; gap: 9px; margin-bottom: 7px;
  font-size: 12px; color: #8f8578; letter-spacing: 2px;
}
.rooms-head i { font-style: normal; font-size: 10.5px; color: #5f5852; letter-spacing: 0; }
.room-list { display: flex; flex-wrap: wrap; gap: 8px; }
.room-empty { font-size: 11.5px; color: #6a6460; padding: 8px 2px; }
.room-card {
  flex: 1 1 168px; min-width: 150px; margin: 0; padding: 8px 10px; text-align: left;
  display: flex; flex-direction: column; gap: 2px;
  background: linear-gradient(180deg, #1b1a20 0%, #121116 100%);
  border: 1px solid #2f2b34; border-radius: 9px; color: inherit; font: inherit; cursor: pointer;
  transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}
.room-card:hover:not(:disabled) {
  transform: translateY(-2px); border-color: #6c8a5c;
  box-shadow: 0 6px 16px rgba(0, 0, 0, .55), 0 0 0 1px rgba(130, 200, 120, .12);
}
.room-card:disabled { opacity: .5; cursor: default; }
.room-card .rc-name { font-size: 13px; color: #d8c9a8; letter-spacing: 1px; }
.room-card .rc-meta { font-size: 10.5px; color: #8b8378; }
.room-card .rc-players {
  font-size: 10.5px; color: #6f6860; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@keyframes pulseBtn { 0%, 100% { box-shadow: 0 0 0 0 rgba(200, 160, 90, .5); } 50% { box-shadow: 0 0 0 6px rgba(200, 160, 90, 0); } }
button.pulse { animation: pulseBtn .6s ease 2; }

/* ---------- 掉线标记 / 网络条 ---------- */
.offtag {
  display: inline-block; padding: 0 4px; border-radius: 4px; font-size: 10px;
  color: #e0b0a4; background: rgba(200, 90, 70, .16); border: 1px solid #6a3a30;
}
.pcard.offline { opacity: .62; filter: saturate(.5); }
.pcard.offline .pfig { position: relative; }
.netbar {
  position: fixed; left: 50%; top: 10px; transform: translate(-50%, -24px);
  z-index: 9999; padding: 8px 16px; border-radius: 10px;
  font-size: 12.5px; color: #ffe0c8; letter-spacing: .5px;
  background: linear-gradient(180deg, #3a1e18, #24110e); border: 1px solid #7a3a2a;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .6); pointer-events: auto;
  opacity: 0; transition: opacity .2s ease, transform .2s ease;
  max-width: 360px; min-width: 220px;
}
.netbar.on { opacity: 1; transform: translate(-50%, 0); }
.netbar.failed { background: linear-gradient(180deg, #3a1218, #240a0e); border-color: #7a2a3a; }
.netbar.queued { background: linear-gradient(180deg, #2a2418, #1a150e); border-color: #7a5a2a; }
.nb-row { display: flex; align-items: center; gap: 8px; }
.nb-sub { font-size: 11px; color: #c8a888; margin-top: 3px; }
.nb-sub b { color: #ffd98c; font-weight: 500; }
.nb-retry {
  margin-top: 6px; padding: 3px 12px; font-size: 11px; cursor: pointer;
  background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.18);
  border-radius: 5px; color: #ffe0c8;
}
.nb-retry:hover { background: rgba(255,255,255,0.14); }
.nb-spinner {
  width: 14px; height: 14px; border: 2px solid rgba(255,200,150,0.25);
  border-top-color: #ffd98c; border-radius: 50%; flex: 0 0 auto;
  animation: nbSpin 0.8s linear infinite;
}
.nb-dot {
  width: 8px; height: 8px; background: #d8a85a; border-radius: 50%;
  flex: 0 0 auto; animation: nbPulse 1.2s ease infinite;
}
@keyframes nbSpin { to { transform: rotate(360deg); } }
@keyframes nbPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ---------- 新手引导浮层 ---------- */
.tutor-overlay {
  position: fixed; inset: 0; z-index: 10000;
  background: rgba(8, 6, 10, 0.72); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
}
.tutor-overlay.hidden { display: none; }
.tutor-card {
  width: 360px; max-width: 92vw; padding: 24px 28px;
  background: #16121a; border: 1px solid #3a2a38; border-radius: 14px;
  box-shadow: 0 16px 48px rgba(0,0,0,0.55);
}
.tutor-step { font-size: 11px; color: #6d6d75; letter-spacing: 2px; margin-bottom: 6px; }
.tutor-title { margin: 0 0 8px; font-size: 17px; font-weight: 500; color: #e8d8c4; letter-spacing: 1px; }
.tutor-text { margin: 0 0 16px; font-size: 13px; line-height: 1.8; color: #a89c90; }
.tutor-img { display: flex; justify-content: center; margin-bottom: 16px; }
.tutor-actions { display: flex; justify-content: space-between; gap: 10px; }
.tutor-skip {
  background: none; border: 1px solid #3a2a38; color: #6d6d75;
  padding: 6px 14px; font-size: 12px; border-radius: 6px; cursor: pointer;
}
.tutor-skip:hover { color: #9a8a7a; border-color: #5a4a58; }
.tutor-next {
  padding: 6px 22px; font-size: 13px;
}

/* ---------- 战绩成就面板 ---------- */
.stats-panel {
  position: fixed; inset: 0; z-index: 9998;
  background: rgba(8, 6, 10, 0.72); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
}
.stats-panel.hidden { display: none; }
.stats-card {
  width: 420px; max-width: 92vw; max-height: 80vh; overflow-y: auto;
  padding: 20px 24px; background: #16121a; border: 1px solid #3a2a38; border-radius: 14px;
}
.stats-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
.stats-head h3 { margin: 0; font-size: 16px; font-weight: 500; color: #e8d8c4; letter-spacing: 1px; }
.stats-close { background: none; border: none; color: #6d6d75; font-size: 16px; cursor: pointer; padding: 4px; }
.stats-close:hover { color: #c8b8a8; }
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 18px; }
.stat-item {
  background: #1e1822; border-radius: 8px; padding: 10px 8px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.stat-item b { font-size: 20px; font-weight: 500; color: #d8b98a; }
.stat-item span { font-size: 10.5px; color: #6d6d75; }
.ach-grid { display: flex; flex-direction: column; gap: 8px; }
.ach-item {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px;
  background: #1e1822; border-radius: 8px; border: 1px solid #2a2032;
}
.ach-item.ach-done { border-color: #3a5a34; }
.ach-icon { font-size: 20px; width: 32px; text-align: center; flex: 0 0 auto; }
.ach-info { flex: 1 1 auto; min-width: 0; }
.ach-name { font-size: 13px; font-weight: 500; color: #c8b8a8; }
.ach-desc { font-size: 11px; color: #5a4a52; }
.ach-done .ach-name { color: #9fc46a; }
.ach-check { font-size: 14px; color: #7fc46a; flex: 0 0 auto; }

/* 首屏加载占位：脚本还在路上时给一句人话，别让人对着空白以为坏了 */
.hero-loading {
  grid-column: 1 / -1; padding: 26px 10px; text-align: center;
  font-size: 12px; color: #6a6156; letter-spacing: .06em;
  border: 1px dashed rgba(140, 120, 100, .22); border-radius: 10px;
  background: rgba(20, 16, 14, .35); animation: hlPulse 1.6s ease-in-out infinite;
}
@keyframes hlPulse { 0%, 100% { opacity: .55 } 50% { opacity: 1 } }

/* 开局前的棋盘占位：没开局时 board 是空的，画布一片黑。
   以前玩家看到的就是一块黑屏 + 左下角「探索 0/0」，很容易当成游戏坏了。 */
.board-veil {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; pointer-events: none; text-align: center; padding: 0 24px;
  background: radial-gradient(ellipse at 50% 45%, rgba(28, 20, 18, .35), rgba(6, 5, 8, .78) 72%);
}
.board-veil b {
  font-size: 17px; font-weight: 600; color: #cfc7b6; letter-spacing: .08em;
}
.board-veil span {
  font-size: 12px; color: #857c6e; line-height: 1.7; letter-spacing: .04em;
}
.board-veil i {
  font-style: normal; font-size: 11px; color: #6d6459; margin-top: 2px;
}



/* ================================================================
   V4 · 全屏游戏 HUD
   ----------------------------------------------------------------
   原则：3D 画面铺满整个窗口，所有按键/道具/面板都是浮在画面上的
   HUD 层，没有任何控件占用画面之外的空间。
   浮层容器一律 pointer-events:none，只有真正的控件吃事件，
   这样鼠标/手指空着拖的地方依然是在拖镜头。
   ================================================================ */

:root {
  --gold: #c9a227;
  --gold-2: #b8863f;
  --blood: #b8422f;
  --ink: #ded4c6;
  --ink-dim: #9a9083;
  --ink-faint: #6d665c;
  --hud: rgba(11, 9, 13, .80);
  --hud-2: rgba(19, 16, 22, .92);
  --hud-line: rgba(160, 126, 74, .26);
  --hud-line-2: rgba(160, 126, 74, .13);
  --glass-blur: blur(14px) saturate(1.1);
  --shadow: 0 12px 34px rgba(0, 0, 0, .62), inset 0 1px 0 rgba(255, 233, 195, .07);
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  /* 底部三块的分区余量：左（自己卡）| 中（行动坞）| 右（小地图/视角键） */
  --dock-l: 274px;
  --dock-r: 172px;
}

html, body { height: 100%; }
body {
  padding: 0; margin: 0; overflow-x: hidden;
  background: #050407; color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}
body.in-game { overflow: hidden; height: 100dvh; overscroll-behavior: none; }
body.in-game #lobby { display: none; }
::selection { background: rgba(201, 162, 39, .3); }

.hidden { display: none !important; }

/* ---------------- 首屏加载 ---------------- */
.boot {
  position: fixed; inset: 0; z-index: 900; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 18px;
  background: radial-gradient(ellipse at 50% 42%, #171119, #050407 68%);
  transition: opacity .5s ease, visibility .5s;
}
.boot.off { opacity: 0; visibility: hidden; pointer-events: none; }
.boot-mark {
  font-size: 54px; letter-spacing: 0; color: var(--gold); opacity: .92;
  text-shadow: 0 0 40px rgba(201, 162, 39, .45);
  animation: bootPulse 2.4s ease-in-out infinite;
}
@keyframes bootPulse { 0%, 100% { opacity: .55; transform: scale(.98) } 50% { opacity: 1; transform: scale(1.02) } }
.boot-bar { width: 176px; height: 2px; background: rgba(201, 162, 39, .16); border-radius: 2px; overflow: hidden; }
.boot-bar i {
  display: block; width: 40%; height: 100%; border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  animation: bootSlide 1.5s ease-in-out infinite;
}
@keyframes bootSlide { 0% { transform: translateX(-120%) } 100% { transform: translateX(360%) } }
.boot-txt { font-size: 11.5px; letter-spacing: 4px; color: var(--ink-faint); }

/* ---------------- 主菜单（大厅） ---------------- */
#lobby.panel {
  max-width: none; margin: 0; padding: 0; background: none;
  border: 0; border-radius: 0; box-shadow: none;
  min-height: 100vh; min-height: 100dvh; position: relative;
}
.menu-bg {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse at 22% 18%, rgba(120, 42, 32, .22), transparent 48%),
    radial-gradient(ellipse at 78% 82%, rgba(60, 46, 96, .18), transparent 52%),
    radial-gradient(ellipse at 50% 50%, #14101a, #050407 72%);
}
.menu-bg::after {
  content: ''; position: absolute; inset: 0; opacity: .5;
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 3px);
}
.lobby-grid {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: minmax(0, 1fr) 336px;
  gap: 16px; padding: 18px; height: 100vh; height: 100dvh;
}
.lobby-main {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
  background: linear-gradient(180deg, rgba(23, 19, 27, .86), rgba(13, 11, 16, .92));
  border: 1px solid var(--hud-line); border-radius: 16px;
  padding: 18px 20px 14px; box-shadow: var(--shadow);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.menu-head { flex: 0 0 auto; padding-bottom: 12px; border-bottom: 1px solid var(--hud-line-2); margin-bottom: 12px; }
.menu-head h1 {
  font-size: clamp(30px, 5.4vh, 52px); letter-spacing: 22px; margin: 0 0 2px;
  color: #e7d9c4; text-align: left; text-shadow: 0 0 34px rgba(184, 66, 47, .34);
}
.menu-head .sub { margin: 0; text-align: left; font-size: 12px; letter-spacing: 3px; color: var(--ink-faint); }
.menu-card { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }

.lobby-inputs {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 136px;
  gap: 10px; align-items: end; flex: 0 0 auto;
}
.lobby-inputs input {
  margin-bottom: 0; padding: 10px 12px; font-size: 13.5px;
  background: rgba(9, 8, 12, .82); border: 1px solid rgba(120, 100, 70, .28);
  border-radius: 9px; color: #e6ddd0; transition: border-color .15s, box-shadow .15s;
}
.lobby-inputs input:focus {
  outline: none; border-color: var(--gold-2);
  box-shadow: 0 0 0 3px rgba(184, 134, 63, .13);
}
.lobby-inputs .lbl { margin-bottom: 5px; font-size: 11px; letter-spacing: 1.5px; }
.join-cell button {
  width: 100%; height: 39px; margin: 0; padding: 0 8px;
  font-size: 14px; letter-spacing: 4px; border-radius: 9px;
}

.lbl-row { display: flex; align-items: baseline; gap: 10px; margin: 14px 0 4px; }
.lbl-row .lbl { margin: 0; }
.lbl-note { font-style: normal; font-size: 10.5px; color: var(--ink-faint); }

#heroCards {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 188px));
  justify-content: start; grid-auto-rows: 190px; align-content: start;
  gap: 9px; margin: 6px 0 10px; padding-right: 6px;
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 26px), transparent 100%);
  mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 26px), transparent 100%);
}
#heroCards::-webkit-scrollbar { width: 6px; }
#heroCards::-webkit-scrollbar-thumb { background: #322b38; border-radius: 3px; }
#heroCards .hcard { padding: 9px 8px 10px; border-radius: 11px; }
#heroCards .hport { flex: 1 1 auto; height: auto; min-height: 48px; overflow: hidden; }
#heroCards .hname { flex: 0 0 auto; font-size: 13.5px; letter-spacing: 1.5px; margin-top: 3px; }
#heroCards .hskill {
  flex: 0 0 auto; font-size: 10.5px; line-height: 1.5; min-height: 0; margin-top: 3px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.hero-loading {
  grid-column: 1 / -1; font-size: 12px; color: var(--ink-faint); padding: 24px 0; text-align: center;
  border: 1px dashed rgba(140, 120, 100, .22); border-radius: 10px; margin: 0;
}

.lobby-foot { flex: 0 0 auto; display: flex; justify-content: flex-end; align-items: center; gap: 8px; }
.menu-link {
  padding: 8px 14px; font-size: 11.5px; letter-spacing: 1.5px; margin: 0;
  background: rgba(24, 20, 26, .9); border: 1px solid rgba(120, 100, 70, .3);
  border-radius: 9px; color: var(--ink-dim); text-decoration: none; cursor: pointer;
  font-family: inherit; transition: all .15s;
}
.menu-link:hover { color: #f0dfc6; border-color: var(--gold-2); background: rgba(48, 34, 22, .9); }
#loginErr { margin: 8px 0 0; min-height: 16px; }

/* ---------------- 快速匹配 ----------------
   和大厅里「房间号 + 潜入房间」并列的第二条路：一个按钮进队列，凑够人自动开局。
   视觉上比「潜入房间」更主动（暗红描边 + 呼吸光），因为对陌生人来说这才是主入口。 */
.match-row { flex: 0 0 auto; margin-top: 12px; }
.match-btn {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  width: 100%; height: 42px; margin: 0; padding: 0 16px;
  border: 1px solid rgba(184, 66, 47, .55); border-radius: 10px;
  background:
    linear-gradient(180deg, rgba(60, 22, 18, .92), rgba(28, 12, 12, .96));
  color: #f0dcc8; font-family: inherit; cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 210, 170, .1), 0 0 0 0 rgba(184, 66, 47, .5);
  animation: matchPulse 3.4s ease-in-out infinite;
  transition: border-color .15s, background .15s, transform .12s;
}
.match-btn:hover:not(:disabled) {
  border-color: rgba(220, 96, 66, .9);
  background: linear-gradient(180deg, rgba(84, 30, 22, .95), rgba(38, 15, 14, .97));
}
.match-btn:active:not(:disabled) { transform: translateY(1px); }
.match-btn .mb-main { font-size: 14px; letter-spacing: 5px; }
.match-btn .mb-sub { font-size: 10.5px; letter-spacing: 1px; color: #a08a76; }
.match-btn:disabled { animation: none; opacity: 1; cursor: default; border-color: rgba(120, 100, 70, .3); }
.match-btn.busy { background: linear-gradient(180deg, rgba(44, 20, 17, .94), rgba(20, 12, 11, .96)); }
.match-btn.busy .mb-sub { color: #8a6a52; }
@keyframes matchPulse {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255, 210, 170, .1), 0 0 0 0 rgba(184, 66, 47, .42); }
  50% { box-shadow: inset 0 1px 0 rgba(255, 210, 170, .1), 0 0 16px 1px rgba(184, 66, 47, .22); }
}

.match-panel {
  margin-top: 8px; padding: 9px 12px 10px;
  border: 1px solid rgba(160, 126, 74, .22); border-radius: 10px;
  background: rgba(9, 8, 12, .72);
}
.match-panel .mp-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.match-panel .mp-top span { font-size: 11.5px; letter-spacing: 1px; color: var(--ink-dim); }
.match-panel .mp-top b { font-size: 13px; color: #e2c58a; letter-spacing: 1.5px; }
.match-panel .mp-bar {
  position: relative; height: 4px; margin: 7px 0 8px; border-radius: 3px;
  background: rgba(120, 100, 70, .18); overflow: hidden;
}
.match-panel .mp-bar span {
  display: block; height: 100%; width: 25%; border-radius: 3px;
  background: linear-gradient(90deg, #7d2f22, #cf7a4a);
  box-shadow: 0 0 10px rgba(207, 122, 74, .45);
  transition: width .35s ease;
}
.match-panel .mp-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.match-panel .mp-foot i { font-style: normal; font-size: 10px; line-height: 1.5; color: var(--ink-faint); }
.match-panel .mp-foot button {
  flex: 0 0 auto; margin: 0; padding: 4px 12px; font-size: 10.5px; letter-spacing: 1px;
  border-radius: 7px; background: rgba(24, 20, 26, .9); border-color: rgba(120, 100, 70, .3);
  color: var(--ink-dim); font-family: inherit;
}
.match-panel .mp-foot button:hover { color: #f0dfc6; border-color: var(--gold-2); }
.match-panel.done { border-color: rgba(120, 190, 120, .35); }
.match-panel.done .mp-bar span { width: 100% !important; background: linear-gradient(90deg, #3f7a45, #7fc98a); }

/* 大厅实时人数。放在匹配按钮下面一行 —— 没有这个数字，
   点「快速匹配」等于在赌有没有人，社交游戏最怕的就是这个。 */
.hall-stat {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-top: 7px; font-size: 10.5px; letter-spacing: .5px; color: var(--ink-faint);
}
.hall-stat[hidden] { display: none; }
.hall-stat .dot {
  width: 5px; height: 5px; border-radius: 50%; background: #6f9c62;
  box-shadow: 0 0 6px rgba(111, 156, 98, .85); flex: 0 0 auto;
}
.hall-stat .dot.off { background: #7a6a58; box-shadow: none; }
.hall-stat b { font-weight: 400; color: #d8c49a; }
.hall-stat .sep { opacity: .3; }

@media (max-width: 900px) {
  .match-btn { height: 46px; flex-direction: column; gap: 2px; }
  .match-btn .mb-main { letter-spacing: 4px; }
  .match-row { margin-top: 10px; }
}


.lobby-side { display: flex; flex-direction: column; gap: 12px; min-height: 0; }
.lobby-side .joinbox {
  flex: 0 0 auto; margin: 0; border-radius: 14px;
  background: linear-gradient(180deg, rgba(23, 19, 27, .86), rgba(13, 11, 16, .92));
  border: 1px solid var(--hud-line); box-shadow: var(--shadow);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.lobby-side .joinbox-body { flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px 14px; }
.lobby-side .join-panel { flex-direction: column; align-items: stretch; gap: 8px; }
.lobby-side .join-qr { width: 120px; height: 120px; margin: 0 auto; }
.lobby-side .join-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1px 6px; align-items: center; margin-bottom: 7px; }
.lobby-side .join-url { grid-column: 1; font-size: 11px; }
.lobby-side .join-copy { grid-column: 2; margin: 0; }
.lobby-side .join-iface { grid-column: 1 / -1; font-size: 9.5px; }
.lobby-side .join-note { font-size: 10.5px; line-height: 1.6; }

.lobby-side .rooms {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; margin: 0;
  background: linear-gradient(180deg, rgba(23, 19, 27, .86), rgba(13, 11, 16, .92));
  border: 1px solid var(--hud-line); border-radius: 14px; padding: 12px 12px;
  box-shadow: var(--shadow); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.rooms-head { flex: 0 0 auto; }
#roomList { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* ================================================================
   对局外壳：整屏只有一个 3D 画面，其余全是浮层
   ================================================================ */
#game.panel {
  position: fixed; inset: 0; display: block; width: 100%; height: 100vh; height: 100dvh;
  max-width: none; margin: 0; padding: 0; overflow: hidden;
  background: #050407; border: 0; border-radius: 0; box-shadow: none;
  touch-action: none;
}
#game.panel.hidden { display: none !important; }

.stage { position: absolute; inset: 0; z-index: 0; overflow: hidden; background: #050407; }
#game .board-wrap {
  position: absolute; inset: 0; margin: 0; padding: 0; border-radius: 0;
  max-width: none !important; perspective: none; background: none;
  height: auto !important; min-height: 0 !important;
}
#board { width: 100%; height: 100%; aspect-ratio: auto; transform: none; border: 0; border-radius: 0; }
.board-canvas { display: block; width: 100% !important; height: 100% !important; }

/* 暗角：让 HUD 上的字在亮地块上也读得清 */
.stage::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 46%, transparent 34%, rgba(4, 3, 6, .46) 100%),
    linear-gradient(180deg, rgba(4, 3, 6, .66) 0, transparent 15%, transparent 74%, rgba(4, 3, 6, .78) 100%);
}

/* ---------------- HUD 通用件 ---------------- */
.hud-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 30px;
  padding: 0 12px; border-radius: 9px; font-size: 12px; letter-spacing: .5px;
  background: var(--hud); border: 1px solid var(--hud-line);
  color: var(--ink); box-shadow: var(--shadow); white-space: nowrap;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  margin: 0;
}
#roomTag.hud-chip { max-width: 42vw; overflow: hidden; text-overflow: ellipsis; }
#phaseTag.hud-chip { color: var(--ink-dim); }

.hud-ico {
  width: 32px; height: 32px; padding: 0; margin: 0; border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1; font-family: inherit;
  background: var(--hud); border: 1px solid var(--hud-line); color: var(--ink-dim);
  box-shadow: var(--shadow); cursor: pointer;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  transition: color .14s, border-color .14s, background .14s, transform .1s;
}
.hud-ico:hover { color: #f4e3c6; border-color: var(--gold-2); background: rgba(40, 29, 20, .92); }
.hud-ico:active { transform: scale(.94); }
.hud-ico.quit:hover { color: #ffb4a4; border-color: #8a3326; background: rgba(60, 20, 16, .92); }
.hud-ico.off { opacity: .45; }

/* ---------------- 顶部：左信息 / 右系统键 ---------------- */
#game .top {
  position: absolute; z-index: 30; display: flex; align-items: center; flex-wrap: nowrap; gap: 8px;
  top: calc(10px + var(--safe-t)); left: calc(10px + var(--safe-l)); right: calc(10px + var(--safe-r));
  height: auto; margin: 0; padding: 0; background: none; border: 0;
  pointer-events: none;
}
.top-left { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; min-width: 0; pointer-events: auto; }
.top-btns { margin-left: auto; display: flex; align-items: center; gap: 6px; pointer-events: auto; flex: 0 0 auto; }

.turn-tag {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;
  border-radius: 9px; font-size: 12px; letter-spacing: 1px; white-space: nowrap; margin: 0;
  background: rgba(30, 22, 18, .9); border: 1px solid rgba(150, 110, 60, .34); color: #d7c2a2;
  box-shadow: var(--shadow); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.turn-tag.mine {
  background: linear-gradient(180deg, rgba(120, 38, 28, .92), rgba(70, 22, 18, .92));
  border-color: rgba(214, 122, 84, .7); color: #ffdcc2;
  box-shadow: 0 0 0 1px rgba(214, 122, 84, .2), 0 8px 26px rgba(140, 40, 24, .46);
  animation: turnPulse 1.9s ease-in-out infinite;
}
@keyframes turnPulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(214, 122, 84, .18), 0 8px 22px rgba(140, 40, 24, .34) }
  50% { box-shadow: 0 0 0 2px rgba(224, 140, 100, .34), 0 8px 30px rgba(180, 56, 32, .58) }
}

/* ---------------- 左下：自己 ---------------- */
.self-box {
  position: absolute; z-index: 32; left: calc(10px + var(--safe-l)); bottom: calc(10px + var(--safe-b));
  width: 250px; margin: 0; padding: 10px 12px; cursor: pointer; overflow: hidden;
  background: var(--hud-2); border: 1px solid var(--hud-line); border-radius: 13px;
  box-shadow: var(--shadow); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  transition: width .18s ease, max-height .18s ease, background .18s;
}
.self-box:hover { border-color: rgba(184, 134, 63, .46); }
.self-box::after {
  content: '⌃'; position: absolute; top: 8px; right: 10px; font-size: 11px; color: var(--ink-faint);
  transition: transform .18s;
}
.self-box.open {
  width: 336px; max-width: calc(100vw - 24px); max-height: 66vh; overflow-y: auto; cursor: default;
  background: rgba(13, 11, 16, .97); border-color: rgba(184, 134, 63, .5); z-index: 60;
}
.self-box.open::after { content: '⌄'; transform: none; }

.sc-top { display: flex; align-items: center; gap: 9px; }
.sc-ava { flex: 0 0 34px; width: 34px; height: 40px; }
.sc-ava svg { width: 100%; height: 100%; display: block; }
.sc-main { flex: 1 1 auto; min-width: 0; }
.sc-name {
  font-size: 12.5px; color: #eadfcc; letter-spacing: .5px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px;
}
.sc-name b { font-weight: 600; }
.sc-hero { font-size: 10.5px; color: var(--ink-faint); letter-spacing: 1px; }
.sc-bars { display: flex; align-items: center; gap: 5px; margin-top: 5px; }
.hp-pips { display: flex; gap: 3px; }
.hp-pips i {
  width: 13px; height: 5px; border-radius: 2px; background: rgba(180, 60, 44, .82);
  box-shadow: 0 0 6px rgba(184, 66, 47, .4);
}
.hp-pips i.off { background: rgba(90, 82, 76, .45); box-shadow: none; }
.sc-stat { font-size: 10px; color: var(--ink-faint); letter-spacing: .5px; margin-left: auto; white-space: nowrap; }
.sc-badges { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.sc-badge {
  font-size: 9.5px; padding: 2px 7px; border-radius: 5px; letter-spacing: .5px;
  background: rgba(46, 34, 22, .9); border: 1px solid rgba(150, 118, 70, .32); color: #cdb894;
}
.sc-badge.warn { background: rgba(70, 24, 20, .9); border-color: rgba(180, 70, 52, .44); color: #edb8a8; }
.sc-badge.good { background: rgba(22, 44, 32, .9); border-color: rgba(60, 140, 96, .38); color: #a9d9bd; }

/* 展开后的详情：收起来时整块不占高度 */
.sc-detail { display: none; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--hud-line-2); }
.self-box.open .sc-detail { display: block; }
.sc-detail .skillline { font-size: 11px; line-height: 1.65; color: #b3a893; margin: 0 0 7px; }
.sc-detail .skillline.warn { color: #e2a08c; }
.sc-detail .buffs-line { margin: 0 0 7px; }
.sc-detail .identity-box { margin: 8px 0 0; padding: 9px 10px; border-radius: 9px; background: rgba(30, 22, 17, .72); border: 1px solid rgba(150, 118, 70, .26); }
.sc-detail .iname { font-size: 12px; color: #e3c79a; letter-spacing: 1px; }
.sc-detail .igoal { font-size: 10.5px; color: #a99d8a; line-height: 1.65; margin-top: 3px; }
.sc-detail .done { color: #8fc9a3; }
.sc-detail .dead-line { font-size: 11px; color: #d99a8a; margin-top: 6px; }
.sc-detail .lampbar { font-size: 10px; color: var(--ink-faint); line-height: 1.6; margin-top: 8px; padding-top: 7px; border-top: 1px dashed var(--hud-line-2); }
.sc-detail .lampbar b { color: #d9bd86; }
.sc-detail .bad { color: #e08c78; }

/* ---------------- 底部中央：行动 + 背包热键栏 ---------------- */
/* 用「中间带」而不是「居中 + max-width 算术」：
   左边让出自己卡、右边让出小地图与视角键，行动坞永远填满剩下的宽度。
   以前 max-width: calc(100vw - 620px) 在 1024 宽的窗口上只剩 404px，
   窗口再窄一点就退化成一个字宽的按钮。 */
.dock {
  position: absolute; z-index: 31;
  left: calc(var(--dock-l) + var(--safe-l));
  right: calc(var(--dock-r) + var(--safe-r));
  bottom: calc(10px + var(--safe-b));
  transform: none; width: auto; max-width: none; min-height: 0;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  margin: 0; padding: 0; background: none; border: 0;
  pointer-events: none;
}
.dock > * { pointer-events: auto; }
.actions {
  display: flex; align-items: center; justify-content: center; gap: 7px; flex-wrap: wrap;
  margin: 0; padding: 0; background: none; border: 0; max-width: 100%;
}
.actions:empty { display: none; }
.actions .pm { display: none; }
.actions .mvinfo {
  font-size: 11.5px; color: #cbb99c; white-space: nowrap;
  padding: 7px 13px; border-radius: 9px; background: var(--hud); border: 1px solid var(--hud-line);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); box-shadow: var(--shadow);
}
.actions .mvinfo b { color: #f0d9ae; font-size: 13px; }
.actions .mvinfo span { color: var(--ink-faint); margin-left: 6px; font-size: 10.5px; }
.actions button {
  margin: 0; padding: 10px 18px; font-size: 13px; letter-spacing: 1.5px; border-radius: 10px;
  border: 1px solid rgba(150, 118, 70, .38); background: rgba(30, 24, 20, .92); color: #e2d3bb;
  box-shadow: var(--shadow); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  transition: all .14s; white-space: nowrap; font-family: inherit;
}
.actions button:hover:not(:disabled) { background: rgba(48, 36, 26, .96); border-color: var(--gold-2); color: #fdf0d8; transform: translateY(-1px); }
.actions button:active:not(:disabled) { transform: translateY(0) scale(.98); }
.actions button.primary {
  background: linear-gradient(180deg, #b5432c, #7d2a1b); border-color: rgba(226, 140, 110, .5);
  color: #ffe6d2; text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
  box-shadow: 0 8px 24px rgba(140, 40, 24, .42), inset 0 1px 0 rgba(255, 210, 180, .18);
}
.actions button.primary:hover:not(:disabled) { background: linear-gradient(180deg, #c94e34, #8e2f1e); }
.actions button.danger {
  background: linear-gradient(180deg, rgba(96, 26, 22, .95), rgba(58, 16, 14, .95));
  border-color: rgba(198, 84, 64, .5); color: #f2c4b6;
}
.actions button.dice-btn {
  padding: 12px 44px !important; font-size: 15px !important; letter-spacing: 8px;
  background: linear-gradient(180deg, #c9a227, #8d6b16); border-color: rgba(240, 214, 140, .5);
  color: #2a1d08; font-weight: 700; text-shadow: none;
  box-shadow: 0 10px 30px rgba(180, 140, 30, .34), inset 0 1px 0 rgba(255, 245, 210, .5);
  animation: diceReady 2.2s ease-in-out infinite;
}
@keyframes diceReady {
  0%, 100% { box-shadow: 0 10px 30px rgba(180, 140, 30, .28), inset 0 1px 0 rgba(255, 245, 210, .45) }
  50% { box-shadow: 0 10px 38px rgba(215, 170, 40, .55), inset 0 1px 0 rgba(255, 245, 210, .7) }
}
.actions button.dice-btn:hover { background: linear-gradient(180deg, #dcb431, #9c7719); }

/* 背包热键栏：贴在行动条下方，一格一格 */
.bag-row {
  display: flex; align-items: flex-end; justify-content: center; gap: 7px;
  margin: 0; padding: 0; background: none; border: 0;
  max-width: 100%; overflow-x: auto; overflow-y: hidden;
}
.bag-row::-webkit-scrollbar { height: 4px; }
.bag-row::-webkit-scrollbar-thumb { background: #372f3d; border-radius: 2px; }
.bag-row .bag { display: flex; align-items: flex-end; gap: 7px; padding: 0; border: 0; background: none; }
.bag-row .bag-head { display: none; }
.bag-row .bag-empty {
  font-size: 10.5px; color: var(--ink-faint); white-space: nowrap; padding: 7px 12px;
  border-radius: 9px; background: var(--hud); border: 1px dashed rgba(140, 120, 100, .22);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.bag-row .bag-list { display: flex; gap: 7px; align-items: flex-end; }
.bag-row .item-card {
  width: 74px; flex: 0 0 auto; padding: 5px 4px 6px; border-radius: 10px;
  background: rgba(16, 13, 18, .9); border: 1px solid rgba(150, 118, 70, .3);
  box-shadow: var(--shadow); transition: all .14s;
}
.bag-row .item-card:hover, .bag-row .item-card.hot {
  border-color: #d0a35a; background: rgba(40, 30, 22, .96); transform: translateY(-3px);
}
.bag-row .item-card .ic-name { font-size: 10px; }
.bag-row .item-card .ic-eff { display: none; }
.bag-row .item-card.relic { border-color: rgba(150, 110, 190, .42); }

#game.turn-mine .dock .actions button:not(.danger) { border-color: rgba(190, 140, 80, .5); }
#game.turn-mine .self-box { border-color: rgba(184, 134, 63, .5); }

/* ---------------- 右侧抽屉 ---------------- */
.side {
  position: absolute; z-index: 34; right: calc(8px + var(--safe-r));
  top: calc(56px + var(--safe-t)); bottom: calc(168px + var(--safe-b));
  display: flex; flex-direction: row-reverse; align-items: flex-start; gap: 0;
  margin: 0; padding: 0; left: auto; background: none; border: 0; overflow: visible;
  pointer-events: none;
}
.side-rail {
  pointer-events: auto; flex: 0 0 52px; width: 52px; border-radius: 12px; max-height: 100%; overflow: hidden;
  display: flex; flex-direction: column; gap: 5px; padding: 6px 5px;
  background: var(--hud); border: 1px solid var(--hud-line); box-shadow: var(--shadow);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.rail-head {
  flex: 0 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column; gap: 4px; align-items: center;
}
.rail-head::-webkit-scrollbar { width: 0; }
.rail-head .hpc {
  width: 100%; padding: 3px 0 2px; border-radius: 8px; background: rgba(30, 26, 24, .82);
  border: 1px solid transparent; display: flex; flex-direction: column; align-items: center; gap: 0;
  cursor: pointer; flex: 0 0 auto; transition: all .14s;
}
.rail-head .hpc:hover { background: rgba(48, 36, 26, .9); }
.rail-head .hpc svg { width: 27px; height: 31px; }
.rail-head .hpc .hpc-name {
  font-size: 8.5px; max-width: 42px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #b6ac9e;
}
.rail-head .hpc .hpc-hp { font-size: 6.5px; letter-spacing: -1px; line-height: 1.1; color: #d26450; }
.rail-head .hpc.cur { border-color: #d67a54; box-shadow: 0 0 10px rgba(214, 122, 84, .34); }
.rail-head .hpc.you { background: rgba(56, 32, 26, .92); }
.rail-head .hpc.dead { opacity: .38; filter: grayscale(1); }
.rail-tabs { flex: 0 0 auto; display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
.rail-btn {
  width: 100%; margin: 0; padding: 8px 0; font-size: 14px; line-height: 1; font-family: inherit;
  background: rgba(23, 20, 27, .9); border: 1px solid rgba(120, 104, 80, .26);
  color: #a99c8c; border-radius: 8px; cursor: pointer; transition: all .14s;
}
.rail-btn:hover { color: #f0dcc0; border-color: var(--gold-2); }
.rail-btn.on { color: #f3d9b0; border-color: #b8863f; background: #2a1e14; }

.side-panel {
  pointer-events: auto; flex: 0 0 0; width: 0; overflow: hidden; height: 100%; max-height: 100%;
  display: flex; flex-direction: column; min-height: 0;
  transition: width .2s cubic-bezier(.3, .9, .3, 1), flex-basis .2s cubic-bezier(.3, .9, .3, 1);
  /* 收起时必须 border-width:0 + 透明底：border-box 下 width:0 仍会画出 2px 边框，
     以前那两条边在画面上就是一根从顶到底的竖线。 */
  background: transparent; border: 0; border-radius: 12px;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.side.open .side-panel {
  flex-basis: 316px; width: 316px; margin-right: 8px;
  background: var(--hud-2); border: 1px solid var(--hud-line); box-shadow: var(--shadow);
}
.side-tabs { flex: 0 0 auto; display: flex; gap: 4px; padding: 8px 8px 6px; }
.stab {
  flex: 1 1 0; margin: 0; padding: 6px 4px; font-size: 11.5px; font-family: inherit;
  background: rgba(20, 18, 26, .9); border: 1px solid rgba(120, 104, 80, .22);
  color: #8d8478; border-radius: 8px; cursor: pointer;
}
.stab.on { background: #2a1a16; border-color: #6d3b2c; color: #ecceb4; }
.side-x { flex: 0 0 30px; }
.side-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding: 0 8px 8px; }
.pane { display: none; }
.pane.on { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
#players.pane.on { overflow-y: auto; gap: 6px; }
#players .pcard { margin: 0; }
.side-body .log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: 0; max-height: none;
  background: rgba(10, 9, 13, .8); border: 1px solid rgba(70, 62, 80, .5); border-radius: 9px;
  padding: 8px 10px; font-size: 11.5px; line-height: 1.7;
}
.side-body .chat { flex: 1 1 auto; min-height: 0; margin: 0; flex-direction: column; }
.side-body .chat-msgs { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; }
.side-body .pane:not(.on) { display: none !important; }
.side-body .pane.on { display: flex; }
#logMore { display: none !important; }

/* ---------------- 棋盘上的悬浮件（小地图 / 视角 / 语音 / 步数） ---------------- */
.hud-move {
  position: absolute; z-index: 20; left: 50%; top: calc(54px + var(--safe-t)); transform: translateX(-50%);
  margin: 0; padding: 6px 15px; border-radius: 10px; font-size: 12px; white-space: nowrap;
  background: var(--hud); border: 1px solid var(--hud-line); color: #cdbda4;
  box-shadow: var(--shadow); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  pointer-events: none;
}
.hud-move b { color: #f2d7a8; font-size: 15px; margin-left: 3px; }
.hud-move .hm-lbl { color: var(--ink-faint); font-size: 10.5px; letter-spacing: 1px; }
.hud-move .dim { color: var(--ink-faint); }
.hud-move.pop { animation: hudPop .3s ease; }
@keyframes hudPop { 0% { transform: translateX(-50%) scale(1.14) } 100% { transform: translateX(-50%) scale(1) } }

.fogstat {
  position: absolute; z-index: 19; left: calc(10px + var(--safe-l)); top: calc(54px + var(--safe-t));
  /* 必须显式 bottom:auto —— 上面老规则里有一条 bottom:14px，
     top 与 bottom 同时存在会让这块自动撑高，在画面左侧变成一根 700px 的竖条。 */
  right: auto; bottom: auto;
  margin: 0; padding: 5px 11px; border-radius: 9px; font-size: 10.5px; color: var(--ink-faint);
  background: rgba(11, 9, 13, .64); border: 1px solid rgba(92, 74, 46, .2);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); pointer-events: none;
}
.fogstat b { color: #b9a888; }
.fogstat .fs-lamp { color: #d9bd86; }

.minimap {
  position: absolute; z-index: 19; right: calc(10px + var(--safe-r)); bottom: calc(10px + var(--safe-b));
  left: auto; top: auto; width: 138px !important; height: 138px !important;
  border-radius: 10px; border: 1px solid var(--hud-line); background: rgba(8, 7, 10, .82);
  opacity: .82; box-shadow: var(--shadow); cursor: crosshair; touch-action: none;
}
.minimap:hover { opacity: 1; }

.cam-btn {
  position: absolute; z-index: 19; right: calc(158px + var(--safe-r)); bottom: calc(10px + var(--safe-b));
  left: auto; top: auto; margin: 0; padding: 6px 11px; font-size: 11px; font-family: inherit;
  background: var(--hud); border: 1px solid var(--hud-line); color: #a99c8c; border-radius: 9px;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow); cursor: pointer;
}
.cam-btn.full { color: #f0d9ae; border-color: var(--gold-2); }

.voice-btn {
  position: absolute; z-index: 19; right: calc(158px + var(--safe-r)); bottom: calc(44px + var(--safe-b));
  left: auto; top: auto; margin: 0; padding: 6px 11px; font-size: 11px; font-family: inherit;
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--hud); border: 1px solid var(--hud-line); color: #a99c8c; border-radius: 9px;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow); cursor: pointer;
}
.voice-btn.on { color: #9fe0bb; border-color: rgba(70, 160, 110, .5); }
.voice-btn.mute { color: #e0a08f; border-color: rgba(180, 70, 52, .44); }
.voice-btn svg { display: block; }
/* 麦序闸门：审判外 / 还没轮到 / 已说完 */
.voice-btn.gated { color: #7d7469; border-color: rgba(150, 138, 120, .3); cursor: not-allowed; opacity: .82; }
.voice-btn.wait { color: #c8b48a; border-color: rgba(196, 158, 84, .42); }
.voice-btn.dead { color: #d9604f; border-color: rgba(217, 96, 79, 0.55); cursor: not-allowed; }
.voice-btn.err { color: #d9604f; border-color: rgba(217, 96, 79, 0.55); }
/* 「说完了」让麦按钮：只在轮到自己时出现 */
.voice-yield {
  position: absolute; z-index: 19; right: calc(158px + var(--safe-r)); bottom: calc(82px + var(--safe-b));
  padding: 5px 12px; border-radius: 9px; font-size: 11px; font-family: inherit; cursor: pointer;
  color: #241902; font-weight: 700; letter-spacing: .5px;
  background: linear-gradient(180deg, #e8c25a, #b8871e);
  border: 1px solid rgba(255, 214, 120, .55);
  box-shadow: var(--shadow);
}
.voice-yield:hover:not(:disabled) { filter: brightness(1.08); }
.voice-yield:disabled { opacity: .55; cursor: default; }
.voice-hint {
  position: absolute; z-index: 20; right: calc(10px + var(--safe-r)); bottom: calc(156px + var(--safe-b));
  max-width: 220px; padding: 8px 11px; border-radius: 9px; font-size: 11px; line-height: 1.6;
  background: rgba(20, 16, 24, .96); border: 1px solid var(--hud-line); color: var(--ink-dim);
  box-shadow: var(--shadow);
}

/* 最近引路灯指示器（P0-2）：告诉你去哪才有事发生 */
.lamp-ping {
  position: absolute; z-index: 18; left: 50%; bottom: calc(112px + var(--safe-b)); transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 13px; border-radius: 20px;
  font-size: 11px; letter-spacing: .5px; color: #e6cd9a; white-space: nowrap;
  background: rgba(30, 23, 14, .78); border: 1px solid rgba(200, 160, 70, .32);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  pointer-events: none; opacity: .92;
}
.lamp-ping b { color: #ffdf9e; font-size: 12.5px; }
.lamp-ping i {
  width: 6px; height: 6px; border-radius: 50%; background: #ffcf6a;
  box-shadow: 0 0 10px 2px rgba(255, 200, 100, .6); animation: lampBlink 1.6s ease-in-out infinite;
}
@keyframes lampBlink { 0%, 100% { opacity: .45 } 50% { opacity: 1 } }

#game #err {
  position: absolute; z-index: 70; left: 50%; top: calc(92px + var(--safe-t)); transform: translateX(-50%);
  margin: 0; padding: 8px 16px; border-radius: 10px; font-size: 12px; max-width: 82%; text-align: center;
  background: rgba(58, 18, 14, .94); border: 1px solid rgba(180, 70, 52, .5); color: #f3c9bd;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .6); pointer-events: none;
}
#game #err:empty { display: none; }

/* 开局前的棋盘说明 */
.board-veil {
  position: absolute; inset: 0; z-index: 3; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; text-align: center; padding: 24px;
  pointer-events: none; background: radial-gradient(ellipse at 50% 45%, rgba(28, 20, 18, .3), rgba(6, 5, 8, .7) 72%);
}

/* ================================================================
   弹出层：规则 / 设置 / 结算
   ================================================================ */
.sheet {
  position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(4, 3, 6, .74); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden; transition: opacity .18s ease, visibility .18s;
}
.sheet.show { opacity: 1; visibility: visible; }
.sheet-box {
  width: min(680px, 100%); max-height: min(84vh, 760px); display: flex; flex-direction: column;
  background: linear-gradient(180deg, rgba(24, 20, 28, .98), rgba(12, 10, 15, .99));
  border: 1px solid var(--hud-line); border-radius: 16px; box-shadow: 0 24px 70px rgba(0, 0, 0, .8);
  transform: translateY(10px) scale(.99); transition: transform .2s cubic-bezier(.3, .9, .3, 1);
}
.sheet.show .sheet-box { transform: none; }
.sheet-box.narrow { width: min(460px, 100%); }
.sheet-head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  padding: 15px 18px 12px; border-bottom: 1px solid var(--hud-line-2);
}
.sheet-head b { font-size: 15px; letter-spacing: 4px; color: #ecdfc9; font-weight: 600; }
.sheet-x {
  width: 28px; height: 28px; padding: 0; margin: 0; border-radius: 8px; font-size: 12px; font-family: inherit;
  background: rgba(30, 26, 34, .9); border: 1px solid rgba(120, 104, 80, .24); color: var(--ink-dim); cursor: pointer;
}
.sheet-x:hover { color: #f0dcc0; border-color: var(--gold-2); }
.sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px 20px; }
.sheet-body::-webkit-scrollbar { width: 7px; }
.sheet-body::-webkit-scrollbar-thumb { background: #332c3c; border-radius: 4px; }
.sheet-body section { margin-bottom: 16px; }
.sheet-body h3 {
  margin: 0 0 6px; font-size: 12.5px; letter-spacing: 2px; color: #d9bd86; font-weight: 600;
}
.sheet-body p { margin: 0 0 7px; font-size: 12px; line-height: 1.8; color: #a99d8a; }
.sheet-body ul { margin: 0; padding-left: 18px; }
.sheet-body li { font-size: 12px; line-height: 1.85; color: #a99d8a; }
.sheet-body li b { color: #e0d2ba; font-weight: 600; }
.keys { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px 12px; padding-left: 0 !important; list-style: none; }
.keys li { display: flex; align-items: center; gap: 7px; font-size: 11.5px; }
/* 触屏设备上看键盘快捷键没有意义，换成手势说明 */
.touch-only { display: none; }
@media (hover: none) and (pointer: coarse) {
  .kb-only { display: none; }
  .touch-only { display: grid; }
}
kbd {
  display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 22px;
  padding: 0 6px; border-radius: 5px; font-family: inherit; font-size: 10.5px;
  background: rgba(40, 34, 46, .95); border: 1px solid rgba(130, 114, 90, .34);
  border-bottom-width: 2px; color: #cbbda6;
}
.sheet-foot { flex: 0 0 auto; padding: 10px 18px 16px; display: flex; justify-content: flex-end; gap: 8px; }

/* 设置项 */
.set-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--hud-line-2);
}
.set-row:last-of-type { border-bottom: 0; }
.set-row > label { font-size: 12.5px; color: #c2b7a5; letter-spacing: .5px; }
.switch {
  display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px 4px 4px; margin: 0;
  border-radius: 20px; background: rgba(20, 17, 24, .95); border: 1px solid rgba(120, 104, 80, .26);
  color: var(--ink-faint); font-size: 11px; font-family: inherit; cursor: pointer; min-width: 74px;
}
.switch i {
  width: 22px; height: 22px; border-radius: 50%; background: #4a424f; transition: all .16s; display: block;
}
.switch.on { color: #e4cfae; border-color: rgba(184, 134, 63, .5); }
.switch.on i { background: var(--gold); box-shadow: 0 0 12px rgba(201, 162, 39, .5); }
.vol-slider {
  -webkit-appearance: none; appearance: none;
  width: 120px; height: 4px; border-radius: 2px;
  background: rgba(120, 104, 80, .3); outline: none; cursor: pointer;
}
.vol-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--gold, #c9a227); border: 2px solid rgba(255, 235, 180, .5);
  box-shadow: 0 0 8px rgba(201, 162, 39, .4); cursor: pointer;
}
.vol-slider::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--gold, #c9a227); border: 2px solid rgba(255, 235, 180, .5);
  box-shadow: 0 0 8px rgba(201, 162, 39, .4); cursor: pointer;
}
.seg { display: inline-flex; gap: 3px; padding: 3px; border-radius: 10px; background: rgba(16, 14, 20, .95); border: 1px solid rgba(120, 104, 80, .22); }
.seg button {
  margin: 0; padding: 6px 12px; font-size: 11.5px; font-family: inherit; border-radius: 7px;
  background: none; border: 0; color: var(--ink-faint); cursor: pointer; transition: all .14s;
}
.seg button:hover { color: #e0d2ba; }
.seg button.on { background: rgba(58, 42, 24, .95); color: #f0d9ae; box-shadow: inset 0 1px 0 rgba(255, 230, 180, .1); }
.set-note { font-size: 10.5px; color: var(--ink-faint); line-height: 1.7; margin: 12px 0 0; }

/* 结算 */
.result .res-box {
  position: relative; width: min(560px, 100%); padding: 32px 28px 24px; text-align: center;
  background: linear-gradient(180deg, rgba(26, 20, 24, .99), rgba(11, 9, 13, .99));
  border: 1px solid rgba(184, 134, 63, .34); border-radius: 18px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, .85); overflow: hidden;
}
.res-glow {
  position: absolute; inset: -40% -10% auto; height: 60%; pointer-events: none;
  background: radial-gradient(ellipse at 50% 0%, rgba(184, 66, 47, .42), transparent 70%);
}
.res-kicker { position: relative; font-size: 11px; letter-spacing: 6px; color: var(--ink-faint); }
.res-title {
  position: relative; margin: 8px 0 4px; font-size: clamp(28px, 5vw, 40px); letter-spacing: 10px;
  color: #f0dcbb; text-shadow: 0 0 40px rgba(201, 162, 39, .4);
}
.res-title.lose { color: #d99a8a; text-shadow: 0 0 40px rgba(184, 66, 47, .5); }
.res-sub { position: relative; font-size: 12.5px; color: var(--ink-dim); line-height: 1.8; }
.res-grid {
  position: relative; display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 8px; margin: 20px 0 4px;
}
.res-cell {
  padding: 11px 6px; border-radius: 11px; background: rgba(20, 16, 22, .9);
  border: 1px solid rgba(120, 104, 80, .22);
}
.res-cell b { display: block; font-size: 19px; color: #ecd6ac; letter-spacing: 1px; }
.res-cell span { display: block; margin-top: 3px; font-size: 10px; color: var(--ink-faint); letter-spacing: 1px; }
.res-foot { position: relative; display: flex; gap: 9px; justify-content: center; margin-top: 20px; }
.res-foot button { margin: 0; padding: 11px 26px; font-size: 13px; letter-spacing: 2px; border-radius: 10px; font-family: inherit; }

/* ---------------- 窄屏（笔记本 / 小窗） ---------------- */
@media (max-width: 1180px) {
  :root { --dock-l: 238px; --dock-r: 162px; }
  .self-box { width: 218px; }
  .self-box.open { width: 300px; }
  .bag-row .item-card { width: 66px; }
}

@media (max-width: 900px) {
  .lobby-grid {
    grid-template-columns: minmax(0, 1fr); height: auto; min-height: 100dvh; padding: 10px; gap: 10px;
  }
  .lobby-main { overflow: visible; padding: 14px; }
  #heroCards { flex: 0 0 auto; overflow: visible; grid-template-columns: repeat(auto-fill, minmax(138px, 1fr)); padding-right: 0; }
  #heroCards .hport { height: 74px; }
  .lobby-side .joinbox-body { flex-direction: row; align-items: center; }
  .lobby-side .join-qr { width: 104px; height: 104px; margin: 0; flex: 0 0 104px; }
  .lobby-side .rooms { min-height: 130px; }
  .lobby-inputs { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .join-cell { grid-column: 1 / -1; }
  .join-cell .lbl { display: none; }
  .join-cell button { height: 44px; }
}

/* ================================================================
   紧凑档：窄屏手机 / 横屏手机 / 矮窗口
   ----------------------------------------------------------------
   三者共用一套规则（媒体查询用逗号并列）。只要屏幕小，HUD 就收敛成
   「左头像 · 中行动 · 右视角」三段式：左侧 62px 让给自己卡，右侧 96px
   让给视角/语音键，中间整条留给行动坞。
   行动坞必须 align-items:stretch —— 之前是 center，.actions 会收缩成
   内容宽度，投骰键在手机上只剩 120px 宽、字还被 letter-spacing 挤散。
   ================================================================ */
@media (max-width: 820px), (max-height: 560px) and (orientation: landscape) {
  :root { --dock-l: 62px; --dock-r: 96px; }

  .dock {
    left: calc(var(--dock-l) + var(--safe-l));
    right: calc(var(--dock-r) + var(--safe-r));
    bottom: calc(8px + var(--safe-b));
    align-items: stretch; gap: 6px; width: auto; max-width: none; transform: none;
  }
  .actions { width: 100%; gap: 6px; justify-content: stretch; align-items: stretch; }
  .actions button {
    flex: 1 1 auto; min-width: 0; max-width: none;
    padding: 12px 10px; font-size: 13px; letter-spacing: 1px;
  }
  .actions button.dice-btn {
    flex: 1 1 100%; max-width: 100%;
    padding: 14px 12px !important; font-size: 15px !important; letter-spacing: 5px;
  }
  .actions .mvinfo { flex: 1 1 100%; font-size: 11px; padding: 6px 10px; text-align: center; }
  .actions .mvinfo span { display: none; }
  /* 手机上别再摆那句长提示：一行字就把行动键挤到边上了，空背包看头像那里的 0/4 就够 */
  .bag-row { width: 100%; justify-content: center; }
  .bag-row .item-card { width: 58px; }
  .bag-row .bag-empty { display: none; }

  /* 左下：收起时只留一个头像方块 */
  .self-box {
    left: calc(8px + var(--safe-l)); bottom: calc(8px + var(--safe-b));
    width: 46px; height: 46px; padding: 4px; border-radius: 12px;
  }
  .self-box .sc-main, .self-box .sc-badges { display: none; }
  .self-box .sc-ava { flex: 0 0 36px; width: 36px; height: 38px; }
  .self-box::after { display: none; }
  /* 展开 → 底部抽屉，高度封顶，不挡住上面的棋盘 */
  .self-box.open {
    left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); width: auto;
    bottom: calc(8px + var(--safe-b)); max-height: 72vh; padding: 12px 14px; z-index: 80;
  }
  .self-box.open .sc-main, .self-box.open .sc-badges { display: flex; }
  .self-box.open .sc-ava { flex: 0 0 34px; width: 34px; height: 40px; }

  /* 右侧玩家栏 */
  .side {
    right: calc(6px + var(--safe-r)); top: calc(48px + var(--safe-t)); bottom: calc(112px + var(--safe-b));
  }
  .side-rail { flex: 0 0 44px; width: 44px; padding: 5px 4px; }
  .rail-head .hpc svg { width: 23px; height: 26px; }
  .rail-head .hpc .hpc-name { font-size: 7.5px; max-width: 34px; }
  .rail-btn { padding: 7px 0; font-size: 13px; }
  .side.open .side-panel {
    position: absolute; right: 50px; top: 0; bottom: 0; width: min(88vw, 330px); flex-basis: auto;
    margin-right: 0;
  }

  /* 小屏塞不下小地图：靠「最近引路灯」那行字导航。
     容器要一起收掉 —— 只藏 canvas 会留一个 39px 高的空壳「战 区」框。 */
  .minimap,
  .mini-frame { display: none !important; }
  .cam-btn { right: calc(8px + var(--safe-r)); bottom: calc(8px + var(--safe-b)); font-size: 10.5px; padding: 5px 9px; }
  .voice-btn { right: calc(8px + var(--safe-r)); bottom: calc(44px + var(--safe-b)); font-size: 10.5px; padding: 5px 9px; }
  .voice-yield { right: calc(8px + var(--safe-r)); bottom: calc(78px + var(--safe-b)); font-size: 10.5px; padding: 5px 9px; }
  .voice-hint { right: calc(8px + var(--safe-r)); top: calc(84px + var(--safe-t)); bottom: auto; max-width: 160px; }
  .fogstat { display: none; }
  .hud-move { top: calc(46px + var(--safe-t)); font-size: 11px; padding: 5px 11px; max-width: calc(100vw - 120px); }
  /* 事件卡片：手机上必须同时让开顶栏、右侧玩家竖栏（44px + 边距）和「剩余步数」条 */
  .fx-toasts {
    left: calc(8px + var(--safe-l)); right: calc(54px + var(--safe-r));
    width: auto; transform: none; top: calc(80px + var(--safe-t)); gap: 5px;
  }
  .toast { padding: 7px 10px; border-radius: 9px; }
  .toast .t-body b { font-size: 11.5px; }
  .toast .t-body i { font-size: 10.5px; }
  .toast .t-ico { width: 22px; height: 22px; font-size: 11px; }
  .lamp-ping { bottom: calc(112px + var(--safe-b)); font-size: 10px; padding: 4px 10px; max-width: calc(100vw - 24px); }

  /* 顶栏：强制单行，标签自己缩，不许换行去压下面的「移动」提示 */
  .top { gap: 5px; }
  #roomTag.hud-chip {
    display: block; line-height: 26px; overflow: hidden; text-overflow: ellipsis;
    max-width: 38vw; font-size: 11px; padding: 0 9px; height: 28px;
  }
  #phaseTag.hud-chip { display: none; }
  .turn-tag {
    height: 28px; font-size: 11px; padding: 0 9px; max-width: 40vw;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .hud-ico { width: 30px; height: 30px; font-size: 13px; }
  .top-btns { gap: 5px; }

  .sheet { padding: 10px; }
  .sheet-box { max-height: 90vh; }
  .sheet-body { padding: 12px 14px; }
  .res-box { padding: 26px 18px 20px; }
}

/* 横屏手机：高度只有 380~430，纵向一律再压一档 */
@media (max-height: 560px) and (orientation: landscape) {
  :root { --dock-l: 56px; --dock-r: 92px; }
  .self-box { width: 40px; height: 40px; padding: 3px; }
  .self-box .sc-ava { flex: 0 0 32px; width: 32px; height: 32px; }
  .side { top: calc(42px + var(--safe-t)); bottom: calc(70px + var(--safe-b)); }
  .lamp-ping { display: none; }
  .hud-move { display: none; }
  .dock { bottom: calc(6px + var(--safe-b)); gap: 4px; }
  .actions button { padding: 9px 10px; font-size: 12px; }
  .actions button.dice-btn { padding: 10px 12px !important; font-size: 14px !important; letter-spacing: 4px; }
  .cam-btn { bottom: calc(6px + var(--safe-b)); }
  .voice-btn { bottom: calc(38px + var(--safe-b)); }
  .voice-yield { bottom: calc(70px + var(--safe-b)); right: calc(8px + var(--safe-r)); }
  .self-box.open { max-height: 84vh; }
  .sheet-box { max-height: 94vh; }
}

/* ---------------- 大屏：整体放大一档 ---------------- */
@media (min-width: 1600px) {
  :root { --dock-l: 320px; --dock-r: 204px; }
  .hud-chip { height: 34px; font-size: 13px; padding: 0 14px; }
  .hud-ico { width: 36px; height: 36px; font-size: 15px; }
  .turn-tag { height: 34px; font-size: 13px; padding: 0 14px; }
  .self-box { width: 286px; padding: 12px 14px; }
  .self-box.open { width: 372px; }
  .actions button { padding: 12px 22px; font-size: 14px; }
  .bag-row .item-card { width: 84px; }
  .minimap { width: 164px !important; height: 164px !important; }
  .cam-btn { bottom: 180px; }
  .voice-btn { bottom: 224px; }
  .voice-hint { bottom: 262px; }
  .side { top: 64px; bottom: 196px; }
  .side-rail { flex: 0 0 58px; width: 58px; }
  .rail-head .hpc svg { width: 32px; height: 37px; }
  .side.open .side-panel { flex-basis: 350px; width: 350px; }
  .lamp-ping { font-size: 12.5px; padding: 6px 15px; bottom: 132px; }
}

/* ---------------- 受击响应窗口 ---------------- */
.defend {
  position: absolute; z-index: 90; left: 50%; bottom: calc(126px + var(--safe-b));
  transform: translateX(-50%); width: min(430px, calc(100vw - 24px));
  padding: 14px 16px 12px; border-radius: 14px;
  background: linear-gradient(180deg, rgba(58, 16, 13, .97), rgba(24, 8, 7, .98));
  border: 1px solid rgba(214, 98, 72, .58);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .72), 0 0 0 1px rgba(255, 120, 90, .1),
              inset 0 1px 0 rgba(255, 190, 160, .12);
  animation: dfIn .18s ease;
}
@keyframes dfIn { from { opacity: 0; transform: translate(-50%, 10px) } to { opacity: 1; transform: translate(-50%, 0) } }
.df-title { font-size: 14px; letter-spacing: 3px; color: #ffd6c4; font-weight: 600; }
.df-title.dim { color: #cba99b; font-size: 12.5px; letter-spacing: 1px; font-weight: 400; }
.df-sub { font-size: 11px; color: #c79c8c; margin-top: 4px; letter-spacing: .5px; }
.df-sub b { color: #ff9d7d; }
.df-bar { height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .1); margin: 9px 0 10px; overflow: hidden; }
.df-bar i {
  display: block; height: 100%; width: 100%;
  background: linear-gradient(90deg, #ff7a4d, #c02c14); transition: width .1s linear;
}
.df-opts { display: flex; gap: 8px; flex-wrap: wrap; }
.df-use {
  flex: 1 1 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 9px 12px; border-radius: 10px; margin: 0; font-family: inherit; text-align: left;
  background: rgba(122, 40, 26, .88); border: 1px solid rgba(226, 140, 110, .45);
  color: #ffe2d2; cursor: pointer; transition: all .14s;
}
.df-use:hover { background: rgba(154, 52, 34, .95); border-color: rgba(255, 170, 140, .7); }
.df-use b { font-size: 12.5px; letter-spacing: 1px; }
.df-use span { font-size: 10px; color: #d6a696; }
.df-pass {
  flex: 1 1 auto; padding: 9px 12px; border-radius: 10px; margin: 0; font-family: inherit; font-size: 12px;
  background: rgba(30, 22, 20, .9); border: 1px solid rgba(150, 118, 96, .3);
  color: #bfae9e; cursor: pointer;
}
.df-pass:hover { color: #ede0cf; border-color: rgba(190, 150, 120, .6); }
.df-none { font-size: 11px; color: #c08e7e; flex: 1 1 auto; align-self: center; }

@media (max-width: 820px) {
  .defend { bottom: calc(158px + var(--safe-b)); width: calc(100vw - 16px); padding: 12px 13px 10px; }
  .df-title { font-size: 13px; letter-spacing: 2px; }
}

/* ================================================================
   审判庭 —— 一间暖和的小屋（2.5D 独立场景）
   进场演出：开门 → 大家一个一个走进来 → 关门 → 围桌坐下。
   全是平面景片 + 透视层深 + 分层立体人形，不进 3D。
   ================================================================ */
.trial-scene {
  position: fixed; inset: 0; z-index: 86;
  display: flex; align-items: center; justify-content: center;
  padding: 14px; overflow: hidden;
  perspective: 1200px;
  animation: tsIn .26s ease;
}
.trial-scene[hidden] { display: none !important; }
@keyframes tsIn { from { opacity: 0 } to { opacity: 1 } }

/* ---- 暖屋背景图：AI 生成的小屋内景，自带圆桌/壁炉/吊灯 ---- */
.ts-bgwrap {
  position: absolute; inset: 0; overflow: hidden;
  pointer-events: none;
}
.ts-bgimg {
  position: absolute; inset: -3%; width: 106%; height: 106%;
  object-fit: cover; object-position: center 42%;
  transform: translate3d(calc(var(--px, 0) * -18px), calc(var(--py, 0) * -11px), 0) scale(1.06);
  will-change: transform;
  filter: brightness(.96) saturate(1.06);
}

/* 烛火浮尘 */
.ts-embers { position: absolute; inset: 0; overflow: hidden; }
.ts-embers::before,
.ts-embers::after {
  content: ''; position: absolute; left: 50%; bottom: -12px;
  width: 3px; height: 3px; border-radius: 50%;
  background: #ffbb6a; opacity: 0;
  box-shadow:
    -34vw 0 0 rgba(255, 168, 84, .5), -18vw -22vh 0 rgba(255, 190, 110, .42),
    -6vw -46vh 0 rgba(255, 160, 74, .38), 10vw -12vh 0 rgba(255, 198, 120, .46),
    22vw -58vh 0 rgba(255, 168, 84, .34), 33vw -30vh 0 rgba(255, 186, 104, .40),
    -40vw -64vh 0 rgba(255, 176, 92, .30), 41vw -70vh 0 rgba(255, 162, 80, .30);
  animation: tsEmber 13s linear infinite;
}
.ts-embers::after { animation-duration: 19s; animation-delay: -7s; filter: blur(.6px); }
@keyframes tsEmber {
  0% { transform: translate(-50%, 0) scale(1); opacity: 0; }
  12% { opacity: .9; }
  100% { transform: translate(-50%, -84vh) scale(.72); opacity: 0; }
}

/* ---- HUD：标题/按钮/投票条悬浮在暖屋图上方 ---- */
.ts-hud {
  position: absolute; inset: 0; z-index: 4;
  display: flex; flex-direction: column;
  justify-content: space-between;
  padding: 14px 18px 12px;
  pointer-events: none;
}
.ts-hud > * { pointer-events: auto; }
.ts-head, .ts-acts, .ts-foot {
  opacity: 0; transform: translateY(10px);
  transition: opacity .55s ease, transform .55s ease;
  pointer-events: none;
}
.trial-scene.ui-on .ts-head,
.trial-scene.ui-on .ts-acts,
.trial-scene.ui-on .ts-foot {
  opacity: 1; transform: none; pointer-events: auto;
}

.ts-head { display: flex; align-items: center; gap: 11px; padding: 0 4px; }
.ts-tag {
  flex: 0 0 auto; padding: 3px 12px; border-radius: 7px; font-size: 11px;
  letter-spacing: 6px; text-indent: 6px; color: #2a1704; font-weight: 800;
  background: linear-gradient(180deg, #f0c258, #c08f28);
  box-shadow: 0 3px 12px rgba(190, 140, 30, .45);
}
.ts-victim {
  flex: 1 1 auto; min-width: 0; font-size: 13.5px; color: #f7e8cd;
  letter-spacing: .6px; text-shadow: 0 2px 10px rgba(0, 0, 0, .5);
}
.ts-role {
  font-style: normal; margin-left: 8px; padding: 2px 7px; border-radius: 5px;
  font-size: 10.5px; color: #f0c191; background: rgba(150, 66, 40, .5);
  border: 1px solid rgba(210, 120, 84, .38);
}
.ts-rule { display: block; font-size: 10px; color: #a98c62; letter-spacing: .9px; margin-top: 3px; }
.ts-tally { flex: 0 0 116px; text-align: right; font-size: 10px; color: #a98c62; letter-spacing: .5px; }
.ts-tally b { display: block; color: #e8c486; font-size: 15px; font-variant-numeric: tabular-nums; }
.ts-tally i {
  display: block; height: 3px; border-radius: 2px; margin-top: 5px;
  background: linear-gradient(90deg, #e0b24a, #8a6418);
  transition: width .25s linear;
}

/* 桌心计时环：贴在暖屋图圆桌中心（约 50%, 60%） */
.ts-ring-wrap {
  position: absolute; left: 50%; top: 58%; width: 152px; height: 152px;
  transform: translate(-50%, -50%) translate3d(calc(var(--px, 0) * -22px), calc(var(--py, 0) * -14px), 0);
  z-index: 12;
}
.ts-ring { width: 100%; height: 100%; transform: rotate(-90deg); }
.ts-ring circle { fill: none; stroke-width: 5.5; stroke-linecap: round; }
.ts-ring .bg { stroke: rgba(255, 214, 140, .14); }
.ts-ring .fg {
  stroke: #e0a63c; stroke-dasharray: 326.7;
  filter: drop-shadow(0 0 8px rgba(224, 166, 60, .6));
  transition: stroke-dashoffset .12s linear, stroke .2s;
}
.ts-ring-wrap.me .ts-ring .fg {
  stroke: #63d68f; filter: drop-shadow(0 0 11px rgba(90, 214, 132, .7));
}
.ts-ring-wrap.over .ts-ring .fg { stroke: #8a7458; filter: none; }
.ts-ring-in {
  position: absolute; inset: 24px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center; gap: 1px;
}
.ts-who { font-size: 12.5px; color: #f2e2c0; letter-spacing: .7px; }
.ts-who.me { color: #8fe8a6; font-weight: 700; text-shadow: 0 0 14px rgba(90, 214, 132, .4); }
.ts-sec { font-size: 38px; line-height: 1.05; color: #fff0d2; font-variant-numeric: tabular-nums; font-weight: 600; }
.ts-slot { font-size: 9.5px; color: #b39468; letter-spacing: 1.4px; }

/* ---- 围桌而坐的人（高模渲的 2.5D 立绘） ---- */
.ts-seats {
  position: absolute; inset: 0; z-index: 20; pointer-events: none;
}
.ts-seat {
  position: absolute; width: 96px; cursor: pointer; user-select: none;
  pointer-events: auto;
  transition: left .95s cubic-bezier(.22, .61, .36, 1), top .95s cubic-bezier(.22, .61, .36, 1),
              transform .95s cubic-bezier(.22, .61, .36, 1), opacity .6s ease;
}
.ts-seat.enter { opacity: 0; }
.ts-seat .fig25 {
  display: block; width: 100%; height: auto;
  border-radius: 8px;
  filter: drop-shadow(0 12px 18px rgba(0, 0, 0, .55));
}
.ts-seat-glow {
  position: absolute; left: 50%; top: 62%; width: 150%; height: 96%;
  transform: translate(-50%, -50%); border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 190, 110, .3), transparent 68%);
  opacity: 0; transition: opacity .3s; pointer-events: none;
}
.ts-seat.now .ts-seat-glow { opacity: 1; }
.ts-seat.now .fig25 {
  filter: drop-shadow(0 10px 14px rgba(0, 0, 0, .5)) drop-shadow(0 0 16px rgba(255, 196, 110, .66));
}
.ts-seat.now.me .fig25 {
  filter: drop-shadow(0 10px 14px rgba(0, 0, 0, .5)) drop-shadow(0 0 18px rgba(110, 230, 150, .72));
}
.ts-seat.dead .fig25 { filter: grayscale(.92) brightness(.62); }
.ts-seat.dead .ts-name { opacity: .55; }
.ts-name {
  margin-top: 2px; text-align: center; font-size: 10.5px; color: #eeddb8;
  letter-spacing: .5px; text-shadow: 0 2px 8px rgba(0, 0, 0, .8); white-space: nowrap;
}
.ts-name b {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 4px; border-radius: 50%;
  font-size: 9px; background: rgba(255, 214, 130, .22); color: #f6d79a; vertical-align: 1px;
}
.ts-seat.now .ts-name b {
  background: linear-gradient(180deg, #f2ca62, #c08f28); color: #2a1704; font-weight: 800;
}
.ts-badge {
  position: absolute; left: 50%; top: -20px; transform: translateX(-50%);
  padding: 2px 8px; border-radius: 10px; font-size: 10px; font-weight: 700;
  color: #2a1704; background: linear-gradient(180deg, #f2ca62, #c8952e);
  box-shadow: 0 4px 12px rgba(200, 148, 40, .5); white-space: nowrap;
}
.ts-seat.now.me .ts-badge {
  background: linear-gradient(180deg, #8fe0a2, #42915f); color: #10240f;
}
.ts-dead {
  position: absolute; left: 50%; top: -16px; transform: translateX(-50%);
  font-size: 15px; opacity: .8; text-shadow: 0 2px 8px rgba(0, 0, 0, .8);
}
.ts-seat.voted::after {
  content: '已投'; position: absolute; right: -12px; top: 4px;
  padding: 1px 6px; border-radius: 8px; font-size: 9px;
  color: #2a1704; background: #e8c474;
}
/* 坐下：肩背微微沉一下 */
.trial-scene.seated .ts-seat .fig25 { animation: tsSit .5s ease both; }
@keyframes tsSit {
  0% { transform: translateY(-6px); }
  62% { transform: translateY(2px); }
  100% { transform: translateY(0); }
}

/* ---- 底部：发言 / 跳过 / 投票 ---- */
.ts-acts {
  flex: 0 0 auto; display: flex; gap: 10px; align-items: stretch;
  min-height: 58px; margin: 8px 2px 0;
}
.ts-speak, .ts-skip {
  margin: 0; padding: 14px 22px; border-radius: 12px; font-family: inherit;
  font-size: 15px; letter-spacing: 5px; text-indent: 5px; cursor: pointer;
  transition: filter .15s, transform .08s, opacity .15s;
}
.ts-speak {
  flex: 1 1 auto; color: #14220e; font-weight: 800;
  background: linear-gradient(180deg, #8fdca2, #3c8c5c);
  border: 1px solid rgba(150, 232, 176, .55);
  box-shadow: 0 12px 28px rgba(50, 150, 90, .32);
}
.ts-speak:hover:not(:disabled) { filter: brightness(1.08); }
.ts-speak:active:not(:disabled) { transform: translateY(1px); }
.ts-skip {
  flex: 0 0 132px; color: #e2cda6; background: rgba(46, 32, 18, .88);
  border: 1px solid rgba(190, 152, 88, .36);
}
.ts-skip:hover:not(:disabled) { color: #ffedd0; border-color: rgba(220, 178, 100, .62); }
.ts-speak:disabled, .ts-skip:disabled { opacity: .5; cursor: default; }
.ts-wait {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  padding: 12px 14px; border-radius: 12px; font-size: 12.5px; color: #c6b08a;
  letter-spacing: .6px; text-align: center; line-height: 1.7;
  background: rgba(255, 255, 255, .045); border: 1px solid rgba(255, 226, 170, .1);
}
.ts-foot {
  flex: 0 0 auto; display: flex; align-items: center; gap: 12px;
  margin: 8px 2px 2px;
}
.ts-note { flex: 1 1 auto; font-size: 11.5px; color: #c2ab84; letter-spacing: .5px; }
.ts-note.done b { color: #f6dfae; }
.ts-pass {
  flex: 0 0 auto; margin: 0; padding: 9px 18px; border-radius: 10px;
  font-family: inherit; font-size: 12px; letter-spacing: 2px; cursor: pointer;
  color: #c9b394; background: rgba(30, 24, 18, .9);
  border: 1px solid rgba(160, 138, 108, .3); transition: all .14s;
}
.ts-pass:hover:not(:disabled) { color: #f4e6c8; border-color: rgba(200, 168, 120, .6); }
.ts-pass:disabled { opacity: .45; cursor: default; }

/* 议事期间棋盘动作全部冻结，行动坞要看起来就是「不能按」 */
#game.trial-on .dock .actions button,
#game.trial-on .dock .bag-row .item-card {
  filter: grayscale(.85) brightness(.62); opacity: .5; pointer-events: none;
}

@media (max-width: 820px) {
  .ts-card { padding: 15px 13px 14px; border-radius: 15px; }
  .ts-stage { gap: 12px; margin: 14px 0 6px; }
  .ts-ring-wrap { flex-basis: 132px; width: 132px; height: 132px; }
  .ts-ring-in { inset: 15px; }
  .ts-sec { font-size: 28px; }
  .ts-who { font-size: 11px; }
  .ts-speak, .ts-skip { padding: 12px 10px; font-size: 13.5px; letter-spacing: 3px; text-indent: 3px; }
  .ts-tally { flex-basis: 84px; }
  .ts-order i { font-size: 10px; padding: 4px 9px 4px 6px; }
  .ts-list { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 6px; }
  .ts-vote, .ts-pass { padding: 12px 6px; font-size: 12px; }
}

/* ================================================================
   听觉层 + 崩塌
   ================================================================ */

/* ---------------- 听觉：屏幕边缘的方向光斑 ----------------
   只给方向，不给位置。玩家在迷雾里唯一「不看也有」的信息。
   位置由 JS 按屏幕方位角算好塞进 --hx/--hy，强度按 --hg-a / --hg-d 分级。 */
.hearing {
  position: fixed; inset: 0; z-index: 34; pointer-events: none;
  --hx: 50%; --hy: 50%; --hg-a: .4; --hg-d: 1.4s; --hg-w: 64px;
}
.hearing[hidden] { display: none; }
.hearing[data-level="1"] { --hg-a: .30; --hg-d: 1.75s; --hg-w: 54px; }
.hearing[data-level="2"] { --hg-a: .52; --hg-d: 1.25s; --hg-w: 68px; }
.hearing[data-level="3"] { --hg-a: .82; --hg-d: .92s;  --hg-w: 82px; }

.hg-blip {
  position: absolute; left: var(--hx); top: var(--hy);
  width: var(--hg-w); height: var(--hg-w);
  margin: calc(var(--hg-w) / -2) 0 0 calc(var(--hg-w) / -2);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(228, 84, 58, .85) 0%, rgba(200, 60, 40, .35) 42%, rgba(160, 40, 28, 0) 72%);
  filter: blur(1.5px);
  opacity: var(--hg-a);
  animation: hgPulse var(--hg-d) ease-out infinite;
}
/* 外圈那道波纹：像声波推过来，比单纯的光点更像「听」 */
.hg-blip::after {
  content: ''; position: absolute; inset: -14%;
  border-radius: 50%; border: 2px solid rgba(240, 110, 80, .55);
  animation: hgRing var(--hg-d) ease-out infinite;
}
@keyframes hgPulse {
  0%, 100% { transform: scale(.86); opacity: calc(var(--hg-a) * .55); }
  35%      { transform: scale(1.06); opacity: var(--hg-a); }
}
@keyframes hgRing {
  0%   { transform: scale(.7); opacity: .7; }
  70%  { transform: scale(1.9); opacity: 0; }
  100% { transform: scale(1.9); opacity: 0; }
}
/* 贴脸：两人在同一格，光斑没法指方向，改成整屏一圈红 */
.hearing.same .hg-blip { display: none; }
.hearing.same { box-shadow: inset 0 0 120px 26px rgba(190, 46, 30, .45); }
.hg-txt {
  position: absolute; left: var(--hx); top: var(--hy);
  transform: translate(-50%, calc(var(--hg-w) / 2 + 8px));
  font-size: 10.5px; letter-spacing: 1.5px; color: #e79b86;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .9); white-space: nowrap;
}
.hearing[data-level="1"] .hg-txt { opacity: .65; }

/* ---------------- 崩塌：地面上那圈裂缝 ----------------
   这里只做 UI 层（警告条 / 红边 / 倒计时）。
   格子本身的「变红 + 抖动 + 下沉」在 board3d 里做，因为它要逐帧跑。 */
.crack-hint {
  position: absolute; z-index: 33; left: 50%; transform: translateX(-50%);
  top: calc(84px + var(--safe-t));
  display: flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius: 10px; font-size: 11.5px; letter-spacing: .5px;
  color: #f3c9a8; white-space: nowrap; pointer-events: none;
  background: linear-gradient(180deg, rgba(70, 20, 12, .92), rgba(38, 12, 8, .92));
  border: 1px solid rgba(220, 96, 50, .45);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .6), 0 0 0 1px rgba(120, 30, 10, .3) inset;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.crack-hint[hidden] { display: none; }
.crack-hint b { color: #ffb27a; font-weight: 700; }
.crack-hint .ck-dot {
  width: 7px; height: 7px; border-radius: 50%; background: #ff7a3c;
  box-shadow: 0 0 10px 3px rgba(255, 100, 40, .8);
  animation: ckBlink 1s ease-in-out infinite;
}
@keyframes ckBlink { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }

/* 脚下正在裂：整屏红边呼吸，配合一次震屏 */
body.on-crack::after {
  content: ''; position: fixed; inset: 0; z-index: 60; pointer-events: none;
  box-shadow: inset 0 0 90px 30px rgba(200, 44, 20, .55);
  animation: crackDanger .9s ease-in-out infinite;
}
@keyframes crackDanger {
  0%, 100% { opacity: .35; }
  50% { opacity: 1; }
}

/* 崩塌发生的一瞬间：整屏闪一下暗红，然后退掉 */
body.collapse-flash::before {
  content: ''; position: fixed; inset: 0; z-index: 61; pointer-events: none;
  background: radial-gradient(ellipse at 50% 60%, rgba(180, 40, 16, .38), rgba(0, 0, 0, .1) 60%, transparent);
  animation: cFlash .8s ease-out forwards;
}
@keyframes cFlash {
  0% { opacity: 0; } 18% { opacity: 1; } 100% { opacity: 0; }
}

/* 被暴露的人：棋盘上套一圈醒目的红环（配合棋盘上的 token 光环） */
/* 玩家列表里的「暴露」徽章 */
.offtag.exposed {
  color: #ffb3a0; background: rgba(120, 26, 16, .8);
  border-color: rgba(230, 100, 70, .7);
  animation: ckBlink 1.1s ease-in-out infinite;
}

@media (max-width: 820px) {
  .crack-hint { top: calc(126px + var(--safe-t)); font-size: 10.5px; padding: 5px 11px; }
  .hg-txt { font-size: 9.5px; letter-spacing: 1px; }
}

/* ---------------- 审判庭 · 小屏 ---------------- */
@media (max-width: 820px) {
  .trial-scene { padding: 8px; }
  .ts-hud { padding: 10px 12px 8px; }
  .ts-head { gap: 7px; }
  .ts-victim { font-size: 11.5px; }
  .ts-rule { font-size: 9px; letter-spacing: .5px; }
  .ts-tally { flex-basis: 76px; }
  .ts-tally b { font-size: 13px; }
  .ts-ring-wrap { width: 118px; height: 118px; }
  .ts-ring-in { inset: 16px; }
  .ts-sec { font-size: 26px; }
  .ts-who { font-size: 10px; }
  .ts-seat { width: 68px; }
  .ts-name { font-size: 9px; }
  .ts-badge { top: -16px; font-size: 9px; padding: 1px 6px; }
  .ts-speak, .ts-skip { padding: 13px 10px; font-size: 13px; letter-spacing: 3px; text-indent: 3px; }
  .ts-skip { flex-basis: 96px; }
}

/* ============================================================================
   对局中：把 HUD 的毛玻璃全部降级成实心半透明
   ----------------------------------------------------------------------------
   这些面板背后是每秒重绘 60 次的 WebGL 画布。blur(14px) 意味着合成器每帧都要
   为**每一个**面板做一次全屏卷积 —— 十几个叠起来，GPU 的时间全花在重复模糊
   同一张画面上，主线程还要等合成结果排队，表现出来就是「画面卡、点了半天才动」。
   （实测：1280×800、DPR=1 时纯净场景能跑 185fps；一旦叠上这批面板，掉帧与输入
     延迟同时出现。面板越多的界面越卡，就是这个原因。）

   底色本来就是接近黑的，去掉模糊观感变化极小；换来的是跟手的输入。
   大厅不在 3D 画布上，所以只作用于 body.in-game。
   ============================================================================ */
body.in-game .hud-chip,
body.in-game .hud-ico,
body.in-game .turn-tag,
body.in-game .self-box,
body.in-game .actions button,
body.in-game .actions .mvinfo,
body.in-game .side-rail,
body.in-game .side-panel,
body.in-game .hud-move,
body.in-game .fogstat,
body.in-game .cam-btn,
body.in-game .voice-btn,
body.in-game .lamp-ping,
body.in-game .bag,
body.in-game .bag-row .bag-empty,
body.in-game .item-card,
body.in-game .tutor-overlay {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* 去掉模糊后要给回一点底气：原本靠 blur 压暗的地方补一层实底，
   文字才不会糊在 3D 画面上。只为「装字」的元素补，纯装饰的不动。 */
body.in-game .hud-chip,
body.in-game .turn-tag,
body.in-game .self-box,
body.in-game .fogstat,
body.in-game .hud-move,
body.in-game .actions .mvinfo {
  background-color: rgba(12, 10, 14, .90);
}

/* 按钮要能点得准：模糊没了之后靠一层轻微描边维持边界感 */
body.in-game .actions button,
body.in-game .cam-btn,
body.in-game .voice-btn {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07);
}


/* ============================================================
   大厅视觉升级（纯覆盖层，不动任何 JS 结构）
   原有样式全部保留在下面，这里只做"盖在上面"的调整：
   英雄卡是 client.js 动态拼的 innerHTML，改结构必崩，所以视觉
   必须靠选择器拿到，不能靠改 DOM。
   ============================================================ */

/* ---------- 标题：宋体 + 烫金渐变 + 血线收边 ---------- */
.menu-head {
  border-bottom: 0;            /* 原来的实线换成下面那条渐隐血线 */
  padding-bottom: 16px;
  position: relative;
}
.menu-head h1 {
  font-family: 'Songti SC', 'STSong', 'SimSun', 'Noto Serif SC', serif;
  font-weight: 400;
  font-size: clamp(34px, 5.8vh, 56px);
  letter-spacing: .26em;
  margin: 0 0 7px;
  /* 上亮下沉的金属渐变，比纯白字耐看，也更压得住暗背景 */
  background: linear-gradient(180deg, #f6ecdc 0%, #cfbea5 52%, #8b7660 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  text-shadow: none;
  filter: drop-shadow(0 2px 20px rgba(184, 66, 47, .20));
}
.menu-head .sub {
  font-family: 'Songti SC', 'STSong', 'SimSun', serif;
  font-size: 11.5px;
  letter-spacing: .40em;
  color: #7c7166;
}
/* 顶部到右端渐隐的红线，代替原来的整条实线 */
.menu-head::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg,
    rgba(168, 64, 44, .58) 0%,
    rgba(168, 64, 44, .16) 26%,
    rgba(148, 122, 88, .07) 58%,
    transparent 88%);
}

/* ---------- 输入区：收直角，聚焦时红边而不是发光 ---------- */
.lobby-inputs input {
  border-radius: 2px;
  background: rgba(7, 6, 10, .92);
  border-color: rgba(148, 122, 88, .20);
  color: #e8dfd2;
}
.lobby-inputs input:hover { border-color: rgba(148, 122, 88, .34); }
.lobby-inputs input:focus {
  border-color: rgba(168, 64, 44, .62);
  box-shadow: 0 0 0 3px rgba(168, 64, 44, .10);
  outline: none;
}
.lbl {
  font-size: 10px;
  letter-spacing: .24em;
  color: #7a6f65;
}

/* ---------- 主按钮：压暗底 + 顶部高光，别像一块塑料 ---------- */
button.primary {
  border-radius: 2px;
  letter-spacing: .30em;
  background: linear-gradient(180deg, #4a1a14 0%, #2b0e0b 58%, #1e0907 100%);
  border: 1px solid rgba(168, 64, 44, .62);
  color: #f2d2c2;
  box-shadow: inset 0 1px 0 rgba(255, 205, 175, .15), 0 6px 18px rgba(90, 20, 12, .38);
  transition: background .18s, box-shadow .18s, border-color .18s;
}
button.primary:hover:not(:disabled) {
  background: linear-gradient(180deg, #5e221a 0%, #381210 58%, #260a08 100%);
  border-color: rgba(190, 78, 54, .8);
  box-shadow: inset 0 1px 0 rgba(255, 210, 180, .22), 0 8px 26px rgba(120, 30, 16, .48);
}
button.primary:active:not(:disabled) {
  background: linear-gradient(180deg, #3d1410 0%, #240b09 58%, #180605 100%);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, .5);
}

/* ---------- 英雄卡：从"同质方块"改成有编号感的硬派卡 ---------- */
.hero-cards { gap: 9px; margin: 6px 0 14px; }

.hcard {
  border-radius: 2px;
  border: 1px solid rgba(148, 122, 88, .15);
  background: linear-gradient(180deg, #1b1722 0%, #110e18 62%, #0a0811 100%);
  padding: 9px 9px 10px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .028);
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* 原来那团径向暖光换成顶部一线光，卡面更干净 */
.hcard::before {
  background: radial-gradient(120% 58% at 50% 0%, rgba(196, 150, 96, .12), transparent 66%);
}
/* 悬停时从中间展开的一条血线 —— 和启动器菜单的逻辑一致 */
.hcard::after {
  content: '';
  position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(168, 64, 44, .85), transparent);
  opacity: 0; transform: scaleX(.28); transform-origin: center;
  transition: opacity .22s ease, transform .30s ease;
  pointer-events: none;
}
.hcard:hover {
  transform: translateY(-2px);
  border-color: rgba(148, 122, 88, .42);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05), 0 8px 20px rgba(0, 0, 0, .55);
}
.hcard:hover::after { opacity: .9; transform: scaleX(1); }

.hcard.picked {
  border-color: rgba(168, 64, 44, .72);
  background: linear-gradient(180deg, #1f1114 0%, #120b0e 62%, #0a0608 100%);
  /* 左侧 3px 血条用 inset 阴影做，省一个伪元素 */
  box-shadow: inset 3px 0 0 0 #a8402c,
              inset 0 0 0 1px rgba(168, 64, 44, .16),
              0 0 24px rgba(168, 64, 44, .15),
              0 10px 22px rgba(0, 0, 0, .50);
}
.hcard.picked::after { opacity: 1; transform: scaleX(1); }

/* 人物区：垫一层极淡的顶光，把立绘从背景里"托"起来 */
.hport { height: 108px; position: relative; }
.hport .fig {
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .8)) drop-shadow(0 0 16px rgba(196, 150, 96, .10));
}

.hname {
  font-family: 'Songti SC', 'STSong', 'SimSun', serif;
  font-size: 16px;
  font-weight: 400;
  letter-spacing: .18em;
  color: #e9dfd0;
  margin-top: 6px;
}

/* 技能：原来是 11px 一坨灰字挤三行。改成"名字独占一行 + 描述换行"+提对比 */
.hskill {
  font-size: 10.5px;
  line-height: 1.62;
  color: #948b93;
  margin-top: 5px;
  min-height: 54px;
}
.hskill b {
  display: block;              /* 纯 CSS 让它换行，不用改 JS 拼的字符串 */
  font-size: 11px;
  letter-spacing: .12em;
  color: #d3a065;
  margin-bottom: 3px;
}

.hpick {
  border-radius: 2px;
  font-size: 9.5px;
  letter-spacing: .10em;
  padding: 1px 5px;
  background: rgba(90, 31, 31, .88);
  border-color: rgba(168, 64, 44, .72);
  color: #f4c3b2;
}

/* ---------- 快速匹配条：抬成第二条主动作，但别抢主按钮 ---------- */
.match-btn {
  border-radius: 2px;
  background: linear-gradient(180deg, rgba(38, 28, 30, .92), rgba(16, 12, 15, .95));
  border: 1px solid rgba(148, 122, 88, .22);
  transition: border-color .18s, background .18s;
}
.match-btn:hover { border-color: rgba(168, 64, 44, .55); background: linear-gradient(180deg, rgba(52, 32, 32, .95), rgba(22, 14, 17, .96)); }

/* ---------- 右侧栏：两块钱板收成同一套边角 ---------- */
.lobby-side .joinbox,
.lobby-side .rooms {
  flex: 1 1 auto; min-height: 0;
  border-radius: 2px;
  border-color: rgba(148, 122, 88, .14);
  background: linear-gradient(180deg, rgba(18, 15, 21, .90), rgba(9, 8, 12, .94));
}
.lobby-side .joinbox-head span,
.lobby-side .rooms-head span {
  font-family: 'Songti SC', 'STSong', 'SimSun', serif;
  letter-spacing: .18em;
}

/* ---------- 底部入口：四个链接统一成小字距标签 ---------- */
.menu-link {
  border-radius: 2px;
  letter-spacing: .16em;
  font-size: 10.5px;
}


/* ============================================================
   第二轮：质感和光。
   第一轮只调了颜色和边角，实际观感几乎没变——把"能看出区别"的东西补上：
   金属流动的标题、人物脚下的地面光、卡片编号、按钮扫光、房间氛围光。
   全部是 CSS，不碰 DOM，出问题删掉这一块就回滚。
   ============================================================ */

/* 标题的金属流光：gradient 做宽到 240%，让高光能横着走一遍 */
.menu-head h1 {
  background: linear-gradient(100deg,
    #bda88d 0%, #ecdfc8 16%, #fffdf6 28%, #eddfc7 40%,
    #c9b49a 58%, #efe2cc 76%, #bda88d 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: titleSheen 11s ease-in-out infinite;
}
@keyframes titleSheen {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

/* 大厅背景的两团氛围光：左上血色余烬、右下冷调，把大片死黑撑开 */
#lobby .menu-bg::after {
  content: '';
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(58% 44% at 10% -4%, rgba(146, 42, 28, .17), transparent 62%),
    radial-gradient(52% 48% at 96% 104%, rgba(38, 68, 88, .13), transparent 64%);
}

/* 卡片编号：图鉴感的来源，纯 CSS counter，JS 那边一个字都不用改 */
.hero-cards { counter-reset: hc; }
.hcard { counter-increment: hc; }
.hcard .hport::before {
  content: counter(hc, decimal-leading-zero);
  position: absolute; top: 0; left: 1px;
  font-family: ui-monospace, 'SF Mono', Consolas, monospace;
  font-size: 9px; letter-spacing: .08em;
  color: rgba(196, 150, 96, .38);
  pointer-events: none;
}

/* 人物脚下的地面光：让立绘"站"在卡上，而不是浮在空气里 */
.hcard .hport::after {
  content: '';
  position: absolute; left: 50%; bottom: -3px;
  width: 74%; height: 13px; transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, rgba(196, 150, 96, .22), transparent 72%);
  filter: blur(3px); pointer-events: none;
}
.hcard.picked .hport::after {
  background: radial-gradient(50% 50% at 50% 50%, rgba(196, 72, 48, .30), transparent 72%);
}

/* 文字整体提亮一档：1440 宽下 10.5px 的灰字实测偏糊 */
.hskill { font-size: 11px; color: #b3a9b2; }
.hname  { color: #f0e7da; }

/* 选中卡：顶部再加一道内高光，让"被选中"在余光里也能看出来 */
.hcard.picked {
  background: linear-gradient(180deg, #241316 0%, #150d10 58%, #0b0709 100%);
}

/* 主按钮扫光：hover 时一道斜光从左边扫过去，成本几乎为零 */
button.primary { position: relative; overflow: hidden; }
button.primary::after {
  content: '';
  position: absolute; top: -10%; left: -70%; width: 42%; height: 120%;
  background: linear-gradient(100deg, transparent, rgba(255, 224, 205, .20), transparent);
  transform: skewX(-18deg);
  transition: left .62s cubic-bezier(.22, .61, .36, 1);
  pointer-events: none;
}
button.primary:hover:not(:disabled)::after { left: 130%; }

/* 房间列表空态：右上角那块大白板，给个虚线框收住，别让它散着 */
.lobby-side .room-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100%; min-height: 160px;
  border: 1px dashed rgba(148, 122, 88, .18);
  border-radius: 2px;
  padding: 18px 12px;
  text-align: center;
  line-height: 1.9;
}

/* 底部四个入口：加一条顶部分隔，和上面内容分层 */
.lobby-foot {
  border-top: 1px solid rgba(148, 122, 88, .10);
  padding-top: 10px;
}
.menu-link {
  color: #8d8177;
  transition: color .16s, border-color .16s, background .16s;
}
.menu-link:hover { color: #e5c9a8; border-color: rgba(168, 64, 44, .45); }


/* ============================================================
   第三轮：把启动器那套语言搬进游戏内大厅。
   前两轮改的是颜色和边角，观感变化太小——这一轮换的是"骨架"：
   整个面板铺一层英雄立绘、标题压上来、卡片改成玻璃层。
   ============================================================ */

/* 面板铺立绘：黑底 PNG 用 screen 混合直接吃掉，左缘用 mask 渐隐，
   让它从右边"渗"进来而不是贴上去。默认枯骨卫，够压住场子。 */
.lobby-main { position: relative; }
.lobby-main > * { position: relative; z-index: 1; }

/* 立绘放在标题右侧那块真正的空白里。
   之前铺满整块面板，结果被 5 列卡片全盖住，只剩一点影子——
   位置比强度重要。 */
.menu-head { position: relative; }
.menu-head::before {
  content: '';
  position: absolute; right: -4px; top: -38px;
  width: 240px; height: 168px;
  background: url('img/fig_kugu.webp') right top / contain no-repeat;
  mix-blend-mode: screen;
  opacity: .52;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 34%, #000 100%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 34%, #000 100%);
}

/* 标题再抬一级：更大、更亮、字距放开，让它成为整页的视觉锚点 */
.menu-head h1 {
  font-size: clamp(40px, 6.6vh, 64px);
  font-weight: 700;
  letter-spacing: .30em;
  margin-bottom: 10px;
  filter: drop-shadow(0 3px 26px rgba(200, 90, 55, .26));
}
.menu-head .sub {
  font-size: 12px;
  letter-spacing: .46em;
  color: #8b7f72;
}

/* 卡片玻璃化：半透明底 + 内描边，让面板立绘能透上来一点 */
.hcard {
  background:
    linear-gradient(180deg, rgba(28, 23, 33, .78) 0%, rgba(15, 12, 20, .86) 60%, rgba(9, 7, 13, .92) 100%);
  border-color: rgba(160, 132, 96, .17);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .045),
    0 2px 8px rgba(0, 0, 0, .34);
}
.hcard.picked {
  background:
    linear-gradient(180deg, rgba(48, 22, 24, .84) 0%, rgba(24, 12, 15, .9) 60%, rgba(10, 6, 9, .94) 100%);
}

/* 输入框和快速匹配条也抬成玻璃层，和卡片同一族 */
.lobby-inputs input {
  background: rgba(10, 8, 14, .72);
  border-color: rgba(160, 132, 96, .22);
}
.match-btn {
  background: linear-gradient(180deg, rgba(40, 29, 32, .72), rgba(17, 13, 16, .84));
  border-color: rgba(160, 132, 96, .22);
}

/* 选择区那行小字：原来是灰色小字，加一条前置竖线做段落标记 */
.lbl-row { position: relative; padding-left: 11px; }
.lbl-row::before {
  content: '';
  position: absolute; left: 0; top: 2px; bottom: 2px; width: 2px;
  background: linear-gradient(180deg, rgba(168, 64, 44, .85), rgba(168, 64, 44, .18));
}


/* ============================================================
   第四轮 · 重设计（覆盖上面三轮，视觉体系整套换掉）
   参考方向：2025-2026 主流的 Liquid Glass 材质 + Bento 分块 +
   大字重排版。三件事：
     1. 布局顺序改掉 —— 先选角色，再填房间；原来是让人先填表
     2. 面板做真玻璃（backdrop-filter + 内高光 + 外投影三层）
     3. 英雄卡从"灰方块"改成"角色卡"：立绘大、名字重、技能标签化
   仍然全程不碰 DOM 结构，只靠 CSS 重排。
   ============================================================ */

/* ---------- 1. 布局顺序：选角优先 ---------- */
.menu-card { display: flex; flex-direction: column; }
.lbl-row    { order: 1; }
#heroCards  { order: 2; flex: 0 1 auto; min-height: 0; overflow-y: auto; }
.lobby-inputs { order: 3; margin-top: 14px; }
.match-row  { order: 4; }
.lobby-foot { order: 5; }
#loginErr   { order: 6; }

/* ---------- 2. 玻璃面板 ---------- */
.lobby-main {
  border-radius: 22px;
  border: 1px solid rgba(255, 255, 255, .065);
  background:
    linear-gradient(168deg,
      rgba(36, 31, 42, .78) 0%,
      rgba(17, 14, 23, .88) 52%,
      rgba(8, 7, 12, .93) 100%);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, .62),
    inset 0 1px 0 rgba(255, 255, 255, .07),
    inset 0 -1px 0 rgba(0, 0, 0, .45);
}
/* 顶沿一道暖金细光，玻璃"有厚度"的关键 */
.lobby-main::after {
  content: '';
  position: absolute; left: 26px; right: 26px; top: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(212, 163, 115, .55), transparent);
  pointer-events: none;
}

/* ---------- 3. 标题：大字重 ---------- */
.menu-head h1 {
  font-size: clamp(42px, 7vh, 72px);
  font-weight: 800;
  letter-spacing: .20em;
  line-height: 1.04;
  filter: drop-shadow(0 4px 30px rgba(200, 90, 55, .3));
}
.menu-head .sub {
  font-family: system-ui, 'PingFang SC', sans-serif;
  font-size: 11.5px;
  letter-spacing: .42em;
  color: #8d8176;
  font-weight: 300;
}

/* ---------- 4. 英雄卡：角色卡 ---------- */
.hero-cards {
  grid-template-columns: repeat(auto-fill, minmax(156px, 1fr));
  gap: 12px; margin: 8px 0 4px;
}
.hcard {
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, .055);
  background: linear-gradient(180deg, rgba(46, 39, 53, .44) 0%, rgba(13, 11, 18, .64) 100%);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, .30),
    inset 0 1px 0 rgba(255, 255, 255, .05);
  padding: 12px 10px 11px;
  transition: transform .20s cubic-bezier(.22,.61,.36,1), border-color .2s, box-shadow .2s;
}
.hcard:hover {
  transform: translateY(-3px);
  border-color: rgba(255, 255, 255, .14);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .48), inset 0 1px 0 rgba(255, 255, 255, .08);
}
.hcard.picked {
  border-color: rgba(224, 74, 47, .55);
  background: linear-gradient(180deg, rgba(76, 28, 24, .56) 0%, rgba(22, 11, 14, .70) 100%);
  box-shadow:
    0 0 0 1px rgba(224, 74, 47, .26),
    0 0 34px rgba(224, 74, 47, .20),
    0 12px 32px rgba(0, 0, 0, .45),
    inset 0 1px 0 rgba(255, 182, 152, .16);
}
.hport { height: 118px; }
.hname {
  font-family: system-ui, 'PingFang SC', sans-serif;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .08em;
  color: #f6f0e7;
  margin-top: 8px;
}
.hskill {
  font-size: 10.5px;
  line-height: 1.62;
  color: #9c92a0;
  margin-top: 6px;
  min-height: 56px;
}
.hskill b {
  font-family: system-ui, 'PingFang SC', sans-serif;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .18em;
  color: #d4a373;
  margin-bottom: 4px;
}
.hpick {
  border-radius: 999px;
  font-size: 9px;
  letter-spacing: .12em;
  padding: 2px 7px;
  background: rgba(224, 74, 47, .92);
  border: 0;
  color: #fff;
  box-shadow: 0 3px 10px rgba(224, 74, 47, .45);
}

/* ---------- 5. 行动区：加大、加圆角 ---------- */
.lobby-inputs { grid-template-columns: minmax(0,1fr) minmax(0,1fr) 128px 168px; gap: 10px; }
.lobby-inputs input {
  height: 42px;
  border-radius: 11px;
  background: rgba(255, 255, 255, .035);
  border: 1px solid rgba(255, 255, 255, .075);
  color: #efe7dc;
  font-size: 13px;
  transition: border-color .18s, background .18s, box-shadow .18s;
}
.lobby-inputs input:hover { border-color: rgba(255, 255, 255, .13); background: rgba(255, 255, 255, .05); }
.lobby-inputs input:focus {
  border-color: rgba(224, 74, 47, .62);
  background: rgba(255, 255, 255, .06);
  box-shadow: 0 0 0 3px rgba(224, 74, 47, .12);
}
button.primary {
  height: 42px;
  border-radius: 11px;
  font-size: 14px;
  letter-spacing: .30em;
  background: linear-gradient(135deg, #c0392b 0%, #9a2c1e 52%, #7d231a 100%);
  border: 1px solid rgba(255, 128, 96, .32);
  color: #fff4ee;
  box-shadow:
    0 8px 26px rgba(190, 50, 30, .34),
    inset 0 1px 0 rgba(255, 190, 168, .30);
}
button.primary:hover:not(:disabled) {
  background: linear-gradient(135deg, #d2452f 0%, #ab3324 52%, #8b271c 100%);
  box-shadow: 0 10px 34px rgba(210, 60, 36, .46), inset 0 1px 0 rgba(255, 200, 180, .36);
}
.match-btn {
  border-radius: 12px;
  background: rgba(255, 255, 255, .042);
  border: 1px solid rgba(255, 255, 255, .075);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.match-btn:hover {
  background: rgba(255, 255, 255, .07);
  border-color: rgba(224, 74, 47, .42);
}

/* ---------- 6. 右侧栏同步玻璃化 ---------- */
.lobby-side .joinbox,
.lobby-side .rooms {
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, .055);
  background: linear-gradient(168deg, rgba(30, 25, 36, .72), rgba(10, 8, 14, .86));
  box-shadow: 0 18px 46px rgba(0, 0, 0, .42), inset 0 1px 0 rgba(255, 255, 255, .05);
}
.lobby-side .joinbox-head span,
.lobby-side .rooms-head span {
  font-family: system-ui, 'PingFang SC', sans-serif;
  font-weight: 600;
  letter-spacing: .1em;
  font-size: 12.5px;
}

/* ---------- 7. 底部入口：亚克力胶囊 ---------- */
.lobby-foot {
  border-top: 1px solid rgba(255, 255, 255, .05);
  padding-top: 12px;
  gap: 8px;
}
.menu-link {
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 10.5px;
  letter-spacing: .12em;
  color: #9a8f85;
  background: rgba(255, 255, 255, .035);
  border: 1px solid rgba(255, 255, 255, .06);
  transition: all .18s;
}
.menu-link:hover {
  color: #f0dcc6;
  background: rgba(224, 74, 47, .14);
  border-color: rgba(224, 74, 47, .40);
}

/* ---------- 8. 立绘放到面板"后面"，让玻璃透出来 ---------- */
/* 之前把立绘塞在标题旁边，结果只能在那一小块里，像贴纸。
   真正的做法是铺在整页背景层，面板是半透明玻璃，透过模糊才看得到——
   这才是 Liquid Glass 该有的层次：背景有东西，玻璃才有"玻璃感"。 */
.menu-head::before { display: none; }

#lobby .menu-bg::before {
  content: '';
  position: absolute; inset: 0;
  background: url('img/fig_kugu.webp') right bottom / auto 86% no-repeat;
  mix-blend-mode: screen;      /* 黑底直接吃掉，只剩人物 */
  opacity: .55;
  pointer-events: none;
}

/* 面板底色再透一档，否则背后什么都看不见，玻璃白做 */
.lobby-main {
  background:
    linear-gradient(168deg,
      rgba(30, 26, 36, .62) 0%,
      rgba(14, 12, 20, .74) 52%,
      rgba(7, 6, 11, .82) 100%);
}
.lobby-side .joinbox,
.lobby-side .rooms {
  background: linear-gradient(168deg, rgba(26, 22, 32, .60), rgba(9, 7, 13, .76));
}
