/* ============================================================
 * Worlds 2026 赛程全流程模拟器 · 样式
 * 暗色电竞风；桌面双栏 / 移动单栏
 * ============================================================ */

:root {
  --bg:        #0b0d12;
  --bg-soft:   #11141d;
  --card:      #161a25;
  --card-2:    #1c2130;
  --line:      #262c3d;
  --line-soft: #1e2331;
  --text:      #e9edf7;
  --text-2:    #aab3c8;
  --muted:     #7d879e;
  --gold:      #d9b45b;
  --gold-dim:  #8a7135;
  --red:       #e64553;
  --green:     #4ec97f;
  --blue:      #5b9dff;
  --radius:    14px;
  --radius-sm: 9px;
  --dock-h:    68px;
  --shadow:    0 10px 30px rgba(0, 0, 0, .45);
  --font: "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "SF Mono", "JetBrains Mono", ui-monospace, Consolas, monospace;
}

* { box-sizing: border-box; }

/* hidden 属性必须能压过下方的 display:flex（.modal / .drawer 都设了 flex） */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  background-image:
    radial-gradient(900px 480px at 12% -8%, rgba(217, 180, 91, .10), transparent 62%),
    radial-gradient(760px 420px at 92% 4%, rgba(91, 157, 255, .08), transparent 60%);
  background-attachment: fixed;
}

button { font-family: inherit; }

/* ---------------- 布局骨架 ---------------- */
.app {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 16px calc(var(--dock-h) + 26px);
}

/* ---------------- 顶栏 ---------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 0 12px;
  background: linear-gradient(180deg, var(--bg) 62%, rgba(11, 13, 18, .82));
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-soft);
}

.brand { display: flex; align-items: center; gap: 11px; min-width: 0; }

.brand-mark {
  width: 38px; height: 38px;
  flex: 0 0 38px;
  border-radius: 10px;
  display: grid; place-items: center;
  font-weight: 800; font-size: 19px;
  color: #1a1405;
  background: transparent;
  overflow: hidden;
}

/* 左上角品牌位 = 官方 Worlds 图标（纯白填充，深底上直接呈现） */
.brand-mark img {
  width: 88%; height: 88%;
  display: block;
  object-fit: contain;
  filter: drop-shadow(0 2px 7px rgba(0, 0, 0, .55));
}

.brand-text h1 {
  margin: 0;
  font-size: 16px;
  letter-spacing: .14em;
  font-weight: 800;
}
.brand-text p {
  margin: 2px 0 0;
  font-size: 11.5px;
  color: var(--muted);
  letter-spacing: .04em;
}

.topmeta { display: flex; align-items: center; gap: 12px; }

.stage-chip {
  font-size: 12px;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: 999px;
  color: var(--gold);
  background: rgba(217, 180, 91, .12);
  border: 1px solid rgba(217, 180, 91, .32);
  white-space: nowrap;
}

.progress-mini { text-align: right; }
.progress-mini span {
  font-size: 11px;
  color: var(--muted);
  font-family: var(--mono);
}
.progress-bar {
  width: 82px; height: 4px;
  margin-top: 4px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
}
.progress-bar i {
  display: block; height: 100%;
  width: 0;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--gold-dim), var(--gold));
  transition: width .35s ease;
}

/* ---------------- 背景音乐开关 ----------------
   内敛处理：关时只留一圈暗边，开时点亮金色，播放时外面一圈极轻的呼吸环。
   音源缺失时按钮会被 js/bgm.js 隐藏，不会留下死控件。 */
.bgm-btn {
  position: relative;
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--muted);
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, background .18s ease;
}
.bgm-btn:hover { color: var(--text); border-color: #3a4256; }
.bgm-btn:focus-visible { outline: 2px solid rgba(217, 180, 91, .5); outline-offset: 2px; }
.bgm-btn .bgm-icon { font-size: 13px; line-height: 1; display: block; }

.bgm-btn.on {
  color: var(--gold);
  border-color: rgba(217, 180, 91, .42);
  background: rgba(217, 180, 91, .10);
}
.bgm-btn.playing .bgm-icon { animation: bgmBreath 2.4s ease-in-out infinite; }
.bgm-btn.playing::after {
  content: '';
  position: absolute; inset: -4px;
  border-radius: 50%;
  border: 1px solid rgba(217, 180, 91, .35);
  animation: bgmRing 2.1s ease-out infinite;
  pointer-events: none;
}

/* 关闭态：加一道斜杠。
   只靠变暗是不够的 —— 玩家第一眼要能看出「这是关着的」，
   而不是「它好像是灰的、但可能还在响」。 */
.bgm-btn:not(.on) .bgm-icon { opacity: .55; }
.bgm-btn:not(.on)::before {
  content: '';
  position: absolute; left: 50%; top: 50%;
  width: 17px; height: 1.5px;
  margin: -0.75px 0 0 -8.5px;
  border-radius: 1px;
  background: currentColor;
  transform: rotate(-45deg);
  pointer-events: none;
}

@keyframes bgmBreath { 0%, 100% { opacity: .72; } 50% { opacity: 1; } }
@keyframes bgmRing {
  0%   { transform: scale(.82); opacity: .5; }
  72%  { transform: scale(1.14); opacity: 0; }
  100% { transform: scale(1.14); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .bgm-btn.playing .bgm-icon { animation: none; }
  .bgm-btn.playing::after { animation: none; opacity: 0; }
}

/* ---------------- 主体网格 ---------------- */
.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 322px;
  gap: 18px;
  align-items: start;
  padding-top: 18px;
}

.stream { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.panel  { display: flex; flex-direction: column; gap: 14px; position: sticky; top: 78px; }

/* ---------------- 空态 ---------------- */
.empty {
  padding: 40px 26px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--card), var(--bg-soft));
  text-align: center;
}
.empty-trophy { font-size: 42px; line-height: 1; }
.empty h2 { margin: 14px 0 8px; font-size: 21px; }
.empty p { margin: 0 auto; max-width: 560px; color: var(--text-2); font-size: 14px; line-height: 1.75; }
.empty-list {
  list-style: none;
  margin: 18px auto 22px;
  padding: 0;
  max-width: 460px;
  text-align: left;
  display: grid;
  gap: 8px;
}
.empty-list li {
  position: relative;
  padding-left: 20px;
  font-size: 13px;
  color: var(--text-2);
}
.empty-list li::before {
  content: "";
  position: absolute; left: 4px; top: 7px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--gold);
}

/* ---------------- 轮次卡片 ---------------- */
.round {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--card);
  overflow: hidden;
  animation: rise .34s ease both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.round-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 16px;
  background: linear-gradient(180deg, var(--card-2), var(--card));
  border-bottom: 1px solid var(--line-soft);
}
.round-title { font-size: 14.5px; font-weight: 700; margin: 0; }
.round-sub { margin: 3px 0 0; font-size: 11.5px; color: var(--muted); font-family: var(--mono); }
.round-badge {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 4px 9px;
  border-radius: 6px;
  color: var(--muted);
  border: 1px solid var(--line);
  background: var(--bg-soft);
  white-space: nowrap;
}
.round-badge.done { color: var(--green); border-color: rgba(78, 201, 127, .34); background: rgba(78, 201, 127, .08); }

/* 对阵列表 */
.matches { padding: 6px 8px; display: flex; flex-direction: column; gap: 2px; }

/* 瑞士轮的战绩组标题（1-0 组 / 0-1 组 …）。
   2026-09-22 玩家反馈「瑞士轮混在一起看不出来是 1-0 组还是 0-1 组」——
   引擎早就把组名挂在每一场上了，是渲染层一直没显示。
   样式刻意做得低调：左边一个小标签 + 右侧一条通栏细线，
   只负责「把这一组圈出来」，不跟比分和爆冷标签抢注意力。 */
.sw-group {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 9px 6px 3px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--muted);
  font-family: var(--mono);
  cursor: default;
  user-select: none;
}
.sw-group::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line-soft);
}
/* 首组贴着轮次标题，不必再顶一格 */
.sw-group:first-child { margin-top: 2px; }

.mt {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  padding: 9px 8px;
  border-radius: var(--radius-sm);
  transition: background .2s ease;
}
.mt + .mt { border-top: 1px solid var(--line-soft); }
.mt:hover { background: rgba(255, 255, 255, .025); }

.mt-side { display: flex; align-items: center; gap: 8px; min-width: 0; }
.mt-side.right { justify-content: flex-end; }

.mt-name {
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mt-side.w .mt-name { color: var(--text); font-weight: 700; }
.mt-side.l .mt-name { color: var(--muted); font-weight: 500; }

.mt-score-wrap { display: flex; align-items: center; gap: 5px; white-space: nowrap; }

.mt.hidden { opacity: 0; visibility: hidden; }

.dot {
  width: 8px; height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
  background: var(--muted);
}

.mt-score {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 3px 10px;
  border-radius: 7px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  color: var(--text-2);
  white-space: nowrap;
}
.mt-score.final { border-color: rgba(217, 180, 91, .3); color: var(--gold); }

/* 逐局播放中（淘汰赛）：比分栏留白。
   比分要等这一场最后一小局揭完才给，所以这里只留一个虚线占位 ——
   min-width 是为了不让「揭晓那一刻」把整行元素挤得左右横移。 */
.mt-score.pending {
  color: var(--muted);
  border-style: dashed;
  min-width: 42px;
  text-align: center;
}

.mt-tag {
  display: inline-block;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 700;
  padding: 1.5px 6px;
  border-radius: 5px;
  vertical-align: 1px;
  letter-spacing: .03em;
  white-space: nowrap;
}
.tag-upset { color: #ffd166; background: rgba(255, 209, 102, .13); border: 1px solid rgba(255, 209, 102, .3); }
.tag-big   { color: #ff7a8a; background: rgba(230, 69, 83, .15); border: 1px solid rgba(230, 69, 83, .36); }
.tag-bo    { color: var(--muted); background: var(--bg-soft); border: 1px solid var(--line); }

/* ---------------- 真实赛果（「已发生」）----------------
   2026-09-22 起引擎可以照抄现实赛果（见 js/data.js 的 REAL_RESULTS）。
   配色刻意另起一个**紫色相**：
     · 金（--gold）被主题强调色占着，德杯下还会整条换成蓝；
     · 绿是晋级 / 出线，红是爆冷 ——
   「这一场来自现实」是一条**来源标注**，必须一眼与「结果的性质」区分开，
   否则玩家会把现实比分读成引擎推演的结果。 */
:root {
  --real:      #a78bfa;
  --real-soft: rgba(167, 139, 250, .12);
  --real-line: rgba(167, 139, 250, .34);
}
.real-chip,
.real-tag { color: var(--real); background: var(--real-soft); border: 1px solid var(--real-line); }
.mt-tag.real-tag { margin-left: 6px; }
.bk-tag.real-tag { margin-left: 4px; }

/* 轮次标题换色：整轮里只要有一场来自现实，这个标题就换色（Q2） */
.round.real .round-title { color: var(--real); }
.round.real .round-head { border-bottom-color: var(--real-line); }
/* 那一场本身也留一道竖线 —— 一页里混着推演与真实时，靠它一眼扫出是哪几场 */
.mt.real { box-shadow: inset 3px 0 0 var(--real-line); }

.round-flags { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.real-chip {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  padding: 4px 9px; border-radius: 6px; white-space: nowrap;
}
.res-realnote { font-size: 11.5px; color: var(--real); font-family: var(--mono); }

/* 抽屉：真实赛果下拉（沿用 save-input 的底子，只补 select 需要的那点） */
.real-sel {
  width: 100%; font-size: 12px; padding: 6px 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg-soft); color: var(--text);
  font-family: var(--font); outline: none;
}
.real-sel:focus { border-color: var(--gold-dim); }

/* ---------------- 「不服」按钮 + 质疑面板 ----------------
   定位是发泄按钮，所以刻意做得低调：默认半透明，hover 才亮起来，
   不跟比分/爆冷标签抢注意力。 */
.mt-protest {
  margin-left: 6px;
  color: var(--muted);
  background: transparent;
  border: 1px dashed var(--line);
  cursor: pointer;
  opacity: .5;
  font-family: inherit;
  transition: opacity .15s ease, color .15s ease, border-color .15s ease;
}
.mt-protest:hover { opacity: 1; color: var(--text); border-color: #4a5266; }
.mt-protest.on {
  opacity: 1;
  color: var(--gold);
  border-style: solid;
  border-color: rgba(217, 180, 91, .4);
  background: rgba(217, 180, 91, .1);
}

.protest {
  margin: 0 12px 10px;
  padding: 10px 12px 9px;
  border-left: 3px solid rgba(217, 180, 91, .45);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: rgba(217, 180, 91, .05);
  animation: ptIn .18s ease-out;
}
@keyframes ptIn { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .protest { animation: none; } }

.protest .pt-head { margin-bottom: 6px; }
.protest .pt-who {
  font-size: 12px;
  font-weight: 700;
  color: var(--gold);
  font-family: var(--mono);
  letter-spacing: .02em;
}
.protest p { margin: 0 0 4px; font-size: 12px; line-height: 1.62; }
.protest .pt-verdict { font-size: 13px; font-weight: 700; color: var(--text); }
.protest .pt-fact { color: var(--text-2); font-family: var(--mono); font-size: 11.5px; }
.protest .pt-why { color: var(--muted); }
.protest .pt-note { color: var(--muted); font-size: 11px; font-style: italic; }
.protest .pt-foot { margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--line-soft); }

/* 事件条 */
.events { padding: 0 16px 4px; display: flex; flex-direction: column; gap: 6px; }
.ev {
  font-size: 12px;
  padding: 7px 11px;
  border-radius: 8px;
  border-left: 3px solid var(--line);
  background: var(--bg-soft);
  color: var(--text-2);
}
.ev.upset    { border-left-color: #ff7a8a; color: #ffc9d0; }
.ev.advance  { border-left-color: var(--green); color: #b6efcd; }
.ev.eliminate{ border-left-color: var(--red);   color: #ffc1c7; }
.ev.slot     { border-left-color: var(--gold);  color: #f0dcac; }

/* 彩蛋：蝴蝶飞不过沧海。
   刻意不像报错、也不像「爆冷」那种告警色 —— 用暖金 + 斜体，
   读起来像一句旁白。它排在揭示序列最后一位，读完成绩才出现。 */
.ev.egg {
  border-left-color: rgba(217, 180, 91, .75);
  background: linear-gradient(100deg, rgba(217, 180, 91, .13), rgba(217, 180, 91, .02));
  color: #f1dfb6;
  font-style: italic;
  letter-spacing: .2px;
}
.ev.egg::before { content: '✦ '; opacity: .55; font-style: normal; }
.ev.egg.hidden { opacity: 0; visibility: hidden; }
.ev.egg.reveal { animation: eggIn .46s ease both; }

/* 事件 / 教练席 / 吐槽一律进揭示序列（2026-09-21 第十一轮）。
   原先只有 .ev.egg 带 hidden，其余 .ev（爆冷、让二追三、晋级、出局）以及
   .quip / .coach 是一进页面就可见的 —— 而「大爆冷：XX 掀翻 YY（3-1）」
   这种文案把最终比分写在句子里，等于在这轮还没播完时就先把结果说了。
   注释写法与 .mt / .games 保持一致：hidden 藏起来，reveal 是入场动画。 */
.ev.hidden, .coach.hidden, .quip.hidden { opacity: 0; visibility: hidden; }
.ev.reveal, .coach.reveal, .quip.reveal { animation: mtIn .3s ease both; }
@keyframes eggIn {
  0%   { opacity: 0; transform: translateY(6px); }
  60%  { opacity: 1; transform: translateY(0); }
  100% { opacity: 1; transform: none; }
}
.toast.egg {
  border-color: rgba(217, 180, 91, .42);
  background: linear-gradient(100deg, rgba(40, 33, 20, .97), rgba(28, 33, 48, .97));
  color: #f3e4bb;
  font-style: italic;
  text-align: center;
  line-height: 1.6;
  /* 一轮可能命中多条彩蛋，它们用 \n 拼在一条提示里 */
  white-space: pre-line;
}

/* 吐槽条 */
.quip {
  margin: 2px 16px 14px;
  padding: 10px 12px;
  border-radius: 9px;
  font-size: 12.5px;
  line-height: 1.6;
  color: #f3e4bb;
  background: linear-gradient(100deg, rgba(217, 180, 91, .12), rgba(217, 180, 91, .02));
  border: 1px dashed rgba(217, 180, 91, .3);
}
.quip::before { content: "「"; opacity: .5; margin-right: 1px; }
.quip::after  { content: "」"; opacity: .5; margin-left: 1px; }

/* ---------------- 侧栏卡片 ---------------- */
.pcard {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--card);
  padding: 14px;
}
.pcard h3 {
  margin: 0 0 11px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--muted);
  text-transform: uppercase;
}

.slot-grid { display: flex; flex-direction: column; gap: 9px; }
.slot-row { display: flex; align-items: center; gap: 8px; }
.slot-region {
  flex: 0 0 46px;
  font-size: 10.5px;
  font-weight: 700;
  font-family: var(--mono);
  padding: 2px 0;
  text-align: center;
  border-radius: 5px;
}
.slot-teams { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.chip {
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 6px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  color: var(--text-2);
  white-space: nowrap;
}
.chip.tbd { color: var(--muted); border-style: dashed; }
.chip.playin { color: #ffd9a0; border-color: rgba(255, 200, 120, .3); background: rgba(255, 200, 120, .07); }
.chip.seed { font-family: var(--mono); font-size: 10px; padding: 3px 5px; opacity: .85; }

/* 瑞士轮战绩表 */
.swiss-table { display: flex; flex-direction: column; gap: 3px; max-height: 340px; overflow: auto; }
.st-row {
  display: grid;
  grid-template-columns: 1fr auto 38px 38px;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  border-radius: 7px;
  font-size: 12px;
  background: var(--bg-soft);
}
.st-row.out { opacity: .42; }
.st-row.adv { background: rgba(78, 201, 127, .08); }
.st-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-rec { font-family: var(--mono); text-align: right; font-size: 11.5px; color: var(--text-2); }
.st-rec.l { color: var(--muted); }

/* 最终结果 */
.res-champ {
  text-align: center;
  padding: 14px 10px 16px;
  border-radius: 11px;
  background: linear-gradient(180deg, rgba(217, 180, 91, .14), transparent);
  border: 1px solid rgba(217, 180, 91, .26);
  margin-bottom: 10px;
}
.res-champ .lbl { font-size: 10.5px; letter-spacing: .18em; color: var(--gold); font-weight: 700; }
.res-champ .nm  { font-size: 20px; font-weight: 800; margin-top: 6px; }
.res-champ .sc  { font-family: var(--mono); font-size: 12.5px; color: var(--text-2); margin-top: 5px; }

.res-list { display: flex; flex-direction: column; gap: 4px; }
.res-item {
  display: flex; justify-content: space-between; gap: 8px;
  font-size: 12px; padding: 5px 8px;
  border-radius: 7px; background: var(--bg-soft);
}
.res-item .p { color: var(--muted); font-family: var(--mono); font-size: 11px; }

/* 结局页的两个出口：「重放这一局」与「重新模拟」。
   并排等宽 + 各带一行副标 —— 只写两个名字玩家分不出哪个是「再看一遍这一局」，
   而这两件事的区别恰恰是这个功能唯一的难点（前者复用这一局的输入，后者换新种子）。 */
.res-actions { display: flex; gap: 8px; margin-top: 11px; }
.res-actions .btn {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  line-height: 1.25; padding: 9px 8px;
}
.res-actions .btn small { font-size: 10.5px; font-weight: 500; opacity: .78; }
.res-actions .btn:disabled small { opacity: 1; color: var(--muted); }

/* ---------------- 底部控制栏 ---------------- */
.dock {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  padding: 9px 16px calc(9px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(180deg, rgba(11, 13, 18, .72), rgba(9, 11, 15, .97));
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--line-soft);
}
.dock-inner {
  max-width: 1240px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 9px;
}
.dock-spacer { flex: 1; }

.btn {
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 9px 15px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: transform .12s ease, filter .18s ease, background .18s ease;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .38; cursor: not-allowed; transform: none; }

.btn-primary {
  color: #1a1405;
  background: linear-gradient(150deg, #f0d189, var(--gold) 55%, #b08f38);
  box-shadow: 0 4px 16px rgba(217, 180, 91, .24);
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.07); }

.btn-warn {
  color: #201203;
  background: linear-gradient(150deg, #ffd08a, #ffab42);
  box-shadow: 0 4px 16px rgba(255, 171, 66, .22);
}

.btn-ghost {
  color: var(--text-2);
  background: var(--card);
  border-color: var(--line);
}
.btn-ghost:hover:not(:disabled) { background: var(--card-2); color: var(--text); }

.btn-lg { padding: 12px 30px; font-size: 14.5px; }

/* ---------------- 抽屉 ---------------- */
.drawer-mask {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0, 0, 0, .58);
  backdrop-filter: blur(2px);
  animation: fade .2s ease both;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 61;
  width: min(430px, 92vw);
  display: flex;
  flex-direction: column;
  background: var(--bg-soft);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow);
  animation: slideIn .26s cubic-bezier(.22, .8, .3, 1) both;
}
@keyframes slideIn { from { transform: translateX(100%); } to { transform: none; } }

.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 15px 18px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.drawer-head h2 { margin: 0; font-size: 15px; }

.icon-btn {
  width: 32px; height: 32px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-2);
  font-size: 14px;
  cursor: pointer;
  line-height: 1;
}
.icon-btn:hover { color: var(--text); background: var(--card-2); }

.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px calc(30px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: 22px;
  -webkit-overflow-scrolling: touch;
}

.field { display: flex; flex-direction: column; gap: 9px; }
.field-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.field-label { font-size: 12.5px; font-weight: 700; color: var(--text-2); letter-spacing: .05em; }
.field-val { font-family: var(--mono); font-size: 13px; color: var(--gold); font-weight: 700; }
.field-hint { margin: 0; font-size: 11.5px; color: var(--muted); line-height: 1.6; }

/* 音量行（背景音乐）：滑杆吃掉剩余宽度，读数定宽右对齐。
   min-width:0 是必须的 —— flex 子项默认 min-width:auto，range 的固有宽度会
   把读数顶出容器（窄屏抽屉里尤其明显）。 */
.bgm-vol-row { display: flex; align-items: center; gap: 10px; }
.bgm-vol-row input[type="range"] { flex: 1; min-width: 0; }
.bgm-vol-row .field-val { flex: none; min-width: 42px; text-align: right; }

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 5px;
  border-radius: 4px;
  background: var(--line);
  outline: none;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 19px; height: 19px;
  border-radius: 50%;
  background: linear-gradient(150deg, #f0d189, var(--gold));
  border: 2px solid #1a1405;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(217, 180, 91, .4);
}
input[type="range"]::-moz-range-thumb {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--gold);
  border: 2px solid #1a1405;
  cursor: pointer;
}

.preset-row { display: flex; flex-wrap: wrap; gap: 7px; }
.preset {
  font-size: 12px;
  padding: 7px 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
  text-align: left;
  line-height: 1.35;
}
.preset:hover { border-color: var(--gold-dim); color: var(--text); }
.preset.on {
  border-color: rgba(217, 180, 91, .55);
  background: rgba(217, 180, 91, .12);
  color: var(--gold);
}
.preset small { display: block; font-size: 10.5px; color: var(--muted); margin-top: 2px; }
.preset.on small { color: rgba(217, 180, 91, .75); }

.mini-btn {
  font-size: 11.5px;
  padding: 4px 10px;
  border-radius: 7px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
}
.mini-btn:hover { color: var(--gold); border-color: var(--gold-dim); }
.mini-btn.primary {
  color: #201203; border-color: var(--gold-dim); font-weight: 700;
  background: linear-gradient(150deg, #f0d189, var(--gold));
}
.mini-btn.primary:hover { filter: brightness(1.07); color: #201203; }
.mini-btn.danger:hover { color: var(--red); border-color: rgba(230, 69, 83, .45); }
.mini-btn:disabled { opacity: .4; cursor: not-allowed; }
.mini-btn:disabled:hover { color: var(--text-2); border-color: var(--line); }
/* 抽屉里的背景音乐开关：开启时点亮，与顶栏那颗 ♪ 状态一致 */
.mini-btn.active { color: var(--gold); border-color: var(--gold-dim); }
.mini-btn.active:hover { color: var(--gold); }

/* 同一行放两个 mini 按钮（未定席位：按实力补满 / 完全推演） */
.mini-row { display: flex; gap: 6px; align-items: center; flex: 0 0 auto; }
.mini-row .mini-btn { white-space: nowrap; }

/* -------- 参数存档 -------- */
.store-badge {
  font-size: 10px; font-family: var(--mono); padding: 2px 7px; border-radius: 999px;
  border: 1px solid rgba(78, 201, 127, .34); color: var(--green);
  background: rgba(78, 201, 127, .1); white-space: nowrap;
}
.store-badge.off { border-color: var(--line); color: var(--muted); background: transparent; }

.save-row { display: flex; gap: 7px; align-items: stretch; }
.save-row > .mini-btn { flex: 1; }
.save-input {
  flex: 1; min-width: 0; font-size: 12px; padding: 6px 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg-soft); color: var(--text);
  font-family: var(--font); outline: none;
}
.save-input::placeholder { color: var(--muted); }
.save-input:focus { border-color: var(--gold-dim); }

.slot-list { display: flex; flex-direction: column; gap: 6px; }
.slot-empty { font-size: 11.5px; color: var(--muted); padding: 6px 0; }
.slot-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 9px; border-radius: 8px;
  border: 1px solid var(--line-soft); background: var(--bg-soft);
}
.slot-item .sn {
  font-size: 12px; font-weight: 600; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.slot-item .sd {
  font-size: 10px; color: var(--muted); font-family: var(--mono);
  margin-left: auto; flex: 0 0 auto;
}

.code-box { display: flex; flex-direction: column; gap: 7px; }
.code-area {
  width: 100%; min-height: 62px; resize: vertical;
  font-family: var(--mono); font-size: 10.5px; line-height: 1.5;
  padding: 8px 10px; border-radius: 8px; word-break: break-all;
  border: 1px solid var(--line); background: var(--bg-soft); color: var(--text-2);
  outline: none;
}
.code-area:focus { border-color: var(--gold-dim); }
.code-area[readonly] { color: var(--gold); }

/* 席位手选 */
.slot-pick { display: flex; flex-direction: column; gap: 12px; }
.sp-group { display: flex; flex-direction: column; gap: 7px; }
.sp-title { font-size: 11.5px; color: var(--muted); }
.sp-row { display: flex; flex-wrap: wrap; gap: 6px; }
.sp-item {
  font-size: 11.5px;
  padding: 5px 10px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
}
.sp-item:hover { border-color: var(--gold-dim); }
.sp-item.on { border-color: rgba(217, 180, 91, .55); background: rgba(217, 180, 91, .13); color: var(--gold); font-weight: 600; }

/* 实力值列表 */
.strength-list { display: flex; flex-direction: column; gap: 13px; }
.sl-group { display: flex; flex-direction: column; gap: 5px; }
.sl-group-title {
  font-size: 10.5px;
  font-family: var(--mono);
  font-weight: 700;
  letter-spacing: .1em;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--line-soft);
}
.sl-row {
  display: grid;
  grid-template-columns: 78px 1fr 34px;
  align-items: center;
  gap: 9px;
}
.sl-name { font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sl-val { font-family: var(--mono); font-size: 11.5px; text-align: right; color: var(--text-2); }
.sl-row input[type="range"] { height: 4px; }
.sl-row input[type="range"]::-webkit-slider-thumb { width: 14px; height: 14px; }

/* ---------------- 弹层 ---------------- */
.modal {
  position: fixed; inset: 0; z-index: 70;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(3px);
  animation: fade .2s ease both;
}
.modal-box {
  width: min(460px, 100%);
  max-height: 92vh;
  display: flex; flex-direction: column;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--bg-soft);
  box-shadow: var(--shadow);
  animation: pop .24s cubic-bezier(.2, .9, .3, 1.1) both;
}
@keyframes pop { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: none; } }

.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
}
.modal-head h2 { margin: 0; font-size: 14.5px; }

.modal-body { flex: 1; overflow-y: auto; padding: 14px 16px; }
.share-preview { display: flex; justify-content: center; }
.share-preview img {
  max-width: 100%;
  /* 结果图又高又窄（750×~1500），不压高度的话它会把下面的分享文案
     顶到滚动区之外 —— 而文案和「复制文案」正是这个弹层的主要动作之一。
     压到 44vh 后，图 + 文案 + 底部按钮在桌面与手机上一屏都放得下。 */
  max-height: 44vh;
  width: auto;
  border-radius: 10px;
  border: 1px solid var(--line);
  display: block;
}
.share-tip {
  margin: 11px 0 0;
  text-align: center;
  font-size: 11.5px;
  color: var(--muted);
}

/* 分享文案：结果图解决「好看」，这段解决「说得清」 */
.share-cap {
  margin-top: 14px;
  padding: 11px 13px 12px;
  border: 1px solid var(--line-soft);
  border-radius: 11px;
  background: var(--bg);
}
.cap-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 8px;
}
.cap-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em;
  color: var(--gold-dim);
}
.cap-text {
  margin: 0;
  font-size: 12.5px; line-height: 1.75;
  color: var(--text-2);
  white-space: pre-wrap;      /* 引擎给的换行必须保留 */
  word-break: break-word;
  user-select: text;          /* 自动复制失败时还能手动选 */
}
.cap-text:empty::before {
  content: '（本局还没结束，暂无文案）';
  color: var(--muted);
}

/* 二维码（toy.getQrCode）：扫码换设备继续玩。
   拿不到整块 hidden（见 js/share.js 的 lock：绝不画空框）。 */
.share-qr {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap;                 /* 极窄屏下让二维码与文字各占一行，不横向溢出 */
  margin-top: 14px;
  padding: 11px 13px 12px;
  border: 1px solid var(--line-soft);
  border-radius: 11px;
  background: var(--bg);
}
.share-qr-img {
  /* 96 + 6×2 = 108（border-box）⇒ 码本体 96px。
     白底板是**可扫性**的保障：深色底上二维码扫不出来。 */
  width: 108px; height: 108px; flex: none;
  padding: 6px;
  background: #fff;
  border-radius: 8px;
}
.share-qr-side { min-width: 0; flex: 1; }
.share-qr-cap {
  margin: 0 0 6px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em;
  color: var(--gold-dim);
}
.share-qr-url {
  margin: 0 0 8px;
  font-size: 11.5px; line-height: 1.5;
  color: var(--muted);
  word-break: break-all;           /* 长链接必须能断行 */
  user-select: text;               /* 自动复制失败时还能手动选 */
}

.modal-foot {
  display: flex; gap: 8px; justify-content: flex-end;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line);
}

/* ---------------- 轮次揭示动画 ---------------- */
.mt.reveal { animation: mtIn .3s ease both; }
@keyframes mtIn {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: none; }
}
.round.pending .matches .mt { opacity: 0; }

/* ============================================================
 * 舞台列：视图切换 / 轮次分页 / 种子池 / 树状图 / 逐局明细
 * ============================================================ */

.stage-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

/* -------- 视图切换 -------- */
/* ---------------- 重放态横幅 ----------------
   重放与「重新模拟」必须一眼分得开：横幅在整个重放期间**不撤**，
   把「眼下这一遍是重放出来的」写在玩家一直看得见的地方。
   配色沿用蓝色（不是金色）—— 金色是「正式模拟」的主色，重放是回看，
   用另一个色系才不会与主按钮抢注意力。 */
.replay-bar {
  display: flex; align-items: center; gap: 9px;
  margin: 0 0 11px;
  padding: 9px 12px;
  border-radius: 11px;
  background: linear-gradient(90deg, rgba(91, 157, 255, .14), rgba(91, 157, 255, .03));
  border: 1px solid rgba(91, 157, 255, .3);
  font-size: 12px;
}
.replay-bar .rb-tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .1em;
  padding: 4px 9px; border-radius: 6px;
  color: #cfe1ff; background: rgba(91, 157, 255, .18);
  border: 1px solid rgba(91, 157, 255, .42);
  white-space: nowrap;
}
.replay-bar .rb-tag::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--blue); flex: 0 0 auto;
}
/* 播放中才闪；踩到结局页就定住 —— 闪着的点暗示「还在放」，停在结局时不该再闪 */
.replay-bar.live .rb-tag::before { animation: rbPulse 1.5s ease-in-out infinite; }
@keyframes rbPulse { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }
.replay-bar .rb-seed {
  font-family: var(--mono); font-size: 11.5px; color: var(--blue);
  white-space: nowrap;
}
.replay-bar .rb-note { color: var(--text-2); min-width: 0; }
.replay-bar .rb-exit {
  margin-left: auto; flex: 0 0 auto;
  background: none; border: 0; cursor: pointer;
  color: var(--blue); font-size: 12px; font-weight: 600;
  padding: 4px 2px; font-family: inherit;
}
.replay-bar .rb-exit:hover { text-decoration: underline; }
/* 窄屏：一行塞不下「标签 + 种子 + 副标 + 出口」，副标换到第二行 */
@media (max-width: 560px) {
  .replay-bar { flex-wrap: wrap; row-gap: 5px; }
  .replay-bar .rb-note { order: 9; width: 100%; }
}

.viewtabs {
  display: flex; gap: 4px; padding: 4px;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  border-radius: 11px; width: fit-content;
}
.vtab {
  appearance: none; border: 1px solid transparent; background: transparent;
  color: var(--muted); font-size: 12.5px; font-weight: 700;
  padding: 6px 18px; border-radius: 8px; cursor: pointer; letter-spacing: .05em;
}
.vtab:hover { color: var(--text-2); }
.vtab.on {
  color: #16130a;
  background: linear-gradient(180deg, #eccd86, var(--gold));
  border-color: var(--gold-dim);
}

/* -------- 轮次导航（每轮一页） -------- */
.pager {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 7px; background: var(--card);
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
}
.pg-btn {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 7px;
  border: 1px solid var(--line); background: var(--card-2); color: var(--text-2);
  font-size: 16px; line-height: 1; cursor: pointer; display: grid; place-items: center;
  padding: 0;
}
.pg-btn:hover:not(:disabled) { color: var(--gold); border-color: var(--gold-dim); }
.pg-btn:disabled { opacity: .28; cursor: not-allowed; }
.pg-list {
  display: flex; gap: 4px; overflow-x: auto; flex: 1; min-width: 0;
  scrollbar-width: none; -ms-overflow-style: none; padding: 1px;
}
.pg-list::-webkit-scrollbar { display: none; }
.pg-item {
  flex: 0 0 auto; border: 1px solid var(--line); background: transparent;
  color: var(--muted); font-size: 11px; padding: 4px 10px; border-radius: 999px;
  cursor: pointer; white-space: nowrap;
}
.pg-item:hover { color: var(--text-2); background: var(--card-2); }
.pg-item.on {
  color: var(--gold); border-color: rgba(217, 180, 91, .5);
  background: rgba(217, 180, 91, .13); font-weight: 700;
}

/* -------- 种子池徽标 -------- */
.pool {
  display: inline-block; font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  font-style: normal; line-height: 1; padding: 2px 4px; border-radius: 4px;
  border: 1px solid currentColor; opacity: .95;
}
.pool.p1 { color: #e8c876; }
.pool.p2 { color: #8fb4f0; }
.pool.p3 { color: #c79ae6; }
.pool.p4 { color: #74cf9c; }
.pool.px { color: var(--muted); border-style: dashed; }
.chip .pool { margin-left: 3px; }

.h3-sub {
  font-weight: 500; font-size: 10px; color: var(--muted);
  letter-spacing: 0; margin-left: 5px;
}
.pool-legend {
  display: flex; flex-wrap: wrap; gap: 5px 11px; margin-top: 10px; padding-top: 9px;
  border-top: 1px solid var(--line-soft); font-size: 10.5px; color: var(--muted);
}
.pool-legend span { display: inline-flex; align-items: center; gap: 4px; }

/* -------- 逐局明细 -------- */
.games {
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center;
  padding: 8px 12px 9px; border-top: 1px solid var(--line-soft);
  background: rgba(255, 255, 255, .016);
}
.games .gl {
  font-size: 10px; letter-spacing: .1em; color: var(--muted);
  font-weight: 700; margin-right: 3px;
}
.games .game {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--line); background: var(--bg-soft);
  border-radius: 7px; padding: 3px 7px 3px 4px; font-size: 11px; color: var(--text-2);
}
.games .game.clinch { border-color: rgba(217, 180, 91, .5); background: rgba(217, 180, 91, .1); color: var(--gold); }
/* 逐局播放：一小局是一格一格里冒出来的，所以动画挂在格子上而不是整条上。 */
.games .game.enter { animation: mtIn .3s ease both; }
.games .game .gn { font-family: var(--mono); font-size: 9.5px; color: var(--muted); }
.games .game.clinch .gn { color: rgba(217, 180, 91, .8); }
.games .game .logo { width: 15px; height: 15px; }
.games.hidden { opacity: 0; visibility: hidden; }
.games.reveal { animation: mtIn .3s ease both; }

/* ============================================================
 * 批量模拟实验室（F02）
 *
 * 它是一个**旁路视图**（用 .viewtabs 的第三个页签进入），所以在这里自成一段，
 * 不往底栏加按钮 —— 底栏的按钮预算在窄屏是硬约束（3 工具 + 3 操作 = 最小 416px）。
 *
 * 配色只用变量（--gold / --card / --line-soft …）：德杯模式下 --gold 会被换成官方蓝，
 * 于是这一整段自动跟着换色相。唯一的例外是选中态按钮 —— 它在金底上写深字，
 * 换到蓝底就成了毛病，所以在文件末尾的德杯段里单独覆盖（与 .vtab.on 同一处）。
 * ============================================================ */
.lab { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

.lab-intro {
  background: var(--card); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 15px 16px;
}
.lab-intro h2 { margin: 0 0 8px; font-size: 15px; font-weight: 700; letter-spacing: .02em; }
.lab-intro p { margin: 0 0 7px; font-size: 12.5px; line-height: 1.72; color: var(--text-2); }
.lab-intro p:last-child { margin-bottom: 0; }
.lab-intro b { color: var(--text); }
/* 措辞纪律（需求 §5.1）用一条左侧金线挑出来 —— 它是这一页最要紧的一句话 */
.lab-caveat { border-left: 2px solid var(--gold-dim); padding-left: 10px; }

.lab-ctrl { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.lab-sizes {
  display: inline-flex; gap: 4px; padding: 4px;
  background: var(--bg-soft); border: 1px solid var(--line-soft); border-radius: 11px;
}
.lab-size {
  appearance: none; border: 1px solid transparent; background: transparent;
  color: var(--muted); font-size: 12.5px; font-weight: 700; padding: 6px 14px;
  border-radius: 8px; cursor: pointer; letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
}
.lab-size:hover { color: var(--text-2); }
.lab-size.on {
  color: #16130a;
  background: linear-gradient(180deg, #eccd86, var(--gold));
  border-color: var(--gold-dim);
}
.lab-mini {
  appearance: none; cursor: pointer; font-size: 11.5px; font-weight: 700;
  padding: 7px 11px; border-radius: 9px; font-family: var(--mono);
  color: var(--muted); background: var(--card-2); border: 1px solid var(--line);
}
.lab-mini:hover { color: var(--gold); border-color: var(--gold-dim); }
.lab-go { padding: 8px 20px; }

/* 队伍成绩表排序（需求 §5.5：支持按不同指标排序）—— 与档位按钮同一套视觉语言，
   但更轻：它是「看的方式」，不是「跑什么」，不该抢档位按钮的视觉权重。 */
.lab-sorts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 0 0 9px; }
.lab-sorts-lb { font-size: 11.5px; color: var(--muted); letter-spacing: .06em; }
.lab-sort {
  appearance: none; border: 1px solid var(--line); background: var(--card-2);
  color: var(--muted); font-size: 11.5px; font-weight: 700; padding: 5px 11px;
  border-radius: 8px; cursor: pointer; letter-spacing: .04em;
}
.lab-sort:hover { color: var(--text-2); border-color: var(--gold-dim); }
.lab-sort.on {
  color: #16130a;
  background: linear-gradient(180deg, #eccd86, var(--gold));
  border-color: var(--gold-dim);
}
.lab-stop { padding: 8px 16px; }

.lab-prog { display: flex; align-items: center; gap: 10px; }
.lab-progtrack {
  flex: 1; height: 6px; border-radius: 4px; overflow: hidden;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
}
.lab-progtrack > i {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--gold-dim), var(--gold));
  transition: width .12s linear;
}
.lab-progtext {
  font-size: 11px; color: var(--muted); font-family: var(--mono);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.lab-out { display: flex; flex-direction: column; gap: 10px; }
.lab-hint, .lab-note { font-size: 12px; line-height: 1.7; color: var(--muted); }
.lab-meta {
  font-family: var(--mono); font-size: 11px; line-height: 1.7; color: var(--text-2);
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); padding: 9px 11px;
}
.lab-warn {
  font-size: 12px; line-height: 1.7; color: #ffd08a;
  background: rgba(255, 171, 66, .08); border: 1px solid rgba(255, 171, 66, .28);
  border-radius: var(--radius-sm); padding: 9px 11px;
}
.lab-cap { margin: 8px 0 0; font-size: 13.5px; font-weight: 700; }
.lab-cap2 { margin: 0 0 8px; font-size: 12.5px; font-weight: 700; color: var(--text-2); }

.lab-list { display: flex; flex-direction: column; gap: 3px; }
.lab-row {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: minmax(78px, 1fr) 48px 58px minmax(60px, 1.25fr);
  background: var(--card); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); padding: 7px 10px;
}
.lab-team { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 700; }
.lab-team .logo { width: 17px; height: 17px; padding: 1.5px; border-radius: 4px; }
.lab-num {
  text-align: right; font-size: 11.5px; color: var(--muted);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.lab-pct {
  text-align: right; font-size: 12.5px; font-weight: 700; color: var(--gold);
  font-variant-numeric: tabular-nums;
}
/* 条形**按榜首归一**（榜首占满），所以它的宽度只能横向比、不能当刻度读；
   要读数值看左边的百分比。这一点写在报告下方的注释里。 */
.lab-track {
  display: block; height: 6px; border-radius: 4px; overflow: hidden;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
}
.lab-track > i {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--gold-dim), var(--gold));
}

.lab-table { display: flex; flex-direction: column; gap: 2px; }
.lab-th, .lab-tr {
  display: grid; align-items: center; gap: 8px; padding: 6px 10px;
  grid-template-columns: minmax(78px, 1fr) repeat(4, 60px);
}
.lab-th {
  font-size: 10.5px; letter-spacing: .08em; color: var(--muted);
  font-weight: 700; text-transform: uppercase;
}
.lab-tr {
  background: var(--card); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
}
.lab-tr > span {
  text-align: right; font-size: 11.5px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.lab-tr > span.lab-team { text-align: left; }
.lab-tr > span.lab-hi { color: var(--gold); font-weight: 700; }
.lab-rt .lab-th, .lab-rt .lab-tr { grid-template-columns: minmax(78px, 1fr) 58px 86px; }

.lab-two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
.lab-block {
  background: var(--card); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 12px 13px;
}
.lab-sub { font-size: 11px; color: var(--muted); margin: 8px 0 6px; letter-spacing: .04em; }
.lab-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.lab-chip {
  font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 6px;
  background: var(--card-2); border: 1px solid var(--line); color: var(--text-2);
}
.lab-chip > i {
  font-style: normal; color: var(--muted); font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* 窄屏：表格四列收窄 + 两张块改成上下排。**不横向溢出**是底线
   （最小总宽 74+40+52+60+GAP 21 = 247px，360px 视口仍有余量）。 */
@media (max-width: 560px) {
  .lab-row { grid-template-columns: 74px 40px 52px 1fr; gap: 7px; padding: 6px 8px; }
  .lab-team { font-size: 11.5px; gap: 5px; }
  .lab-team .logo { width: 15px; height: 15px; }
  .lab-th, .lab-tr { grid-template-columns: minmax(66px, 1fr) repeat(4, 46px); gap: 5px; padding: 5px 7px; }
  .lab-rt .lab-th, .lab-rt .lab-tr { grid-template-columns: minmax(66px, 1fr) 44px 68px; }
  .lab-tr > span { font-size: 11px; }
  .lab-two { grid-template-columns: 1fr; }
  .lab-intro { padding: 13px 13px; }
  .lab-size { padding: 6px 10px; font-size: 11.5px; }
  .lab-mini { font-size: 10.5px; padding: 6px 9px; }
  .lab-sort { font-size: 11px; padding: 5px 9px; }
  .lab-go { padding: 8px 14px; }
}

/* -------- 树状图 -------- */
.bracket { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.bk-block {
  background: var(--card); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 13px;
}
.bk-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 12px;
}
.bk-head h3 { margin: 0; font-size: 13.5px; font-weight: 700; }
.bk-head .bk-sub { font-size: 10.5px; color: var(--muted); font-family: var(--mono); }
.bk-scroll { overflow-x: auto; padding-bottom: 4px; }

/* 树状图用网格定位：每列的比赛按跨行数与父级中心对齐。
   例（淘汰赛，4 行）：QF1..QF4 各占 1 行；SF1 跨 1–2 行、SF2 跨 3–4 行；GF 跨 1–4 行。
   于是 SF1 的垂直中心正好落在 QF1 与 QF3 的中点，GF 落在两个半决赛的中点。 */
/* 行高必须「等高」，否则跨行卡片的中心会漂移、连线对不上：
   --rowh 由 renderBracket 在实测卡片自然高度后回写（见 fitRowH）。 */
.bk-grid {
  display: grid;
  gap: 12px 24px;
  grid-template-columns: repeat(var(--cols, 3), minmax(136px, 1fr));
  grid-template-rows: auto repeat(var(--rows, 4), minmax(var(--rowh, 84px), auto));
  align-items: stretch;
}
.bk-hcol {
  grid-row: 1;
  align-self: end;
  font-size: 10px; letter-spacing: .13em; color: var(--muted);
  font-weight: 700; text-transform: uppercase; padding-bottom: 2px;
}
/* 连线几何：列间距 24px，横向连线取「半间距」12px 锚定在列间中线，
   父级跨行卡片的竖向汇流杆也立在同一条中线上，于是子级出线正好接上杆的两端。 */
.bk-cell { position: relative; display: flex; align-items: center; }
/* 右侧横向出线（末列不画）：卡片右缘 → 列间中线 */
.bk-cell:not([data-last])::after {
  content: ''; position: absolute; top: 50%; right: -12px;
  width: 12px; height: 1px; background: var(--line);
}
/* 跨行卡片的竖向汇流杆：等高行下，子级中心落在行带的确定百分比处
   （span2 → 23.4%/76.6%，span4 → 24.2%/75.8%，由 行高84 / 行距12 推得） */
.bk-cell[data-span="2"]::before {
  content: ''; position: absolute; left: -12px; top: 23.4%; bottom: 23.4%;
  width: 1px; background: var(--line);
}
.bk-cell[data-span="4"]::before {
  content: ''; position: absolute; left: -12px; top: 24.2%; bottom: 24.2%;
  width: 1px; background: var(--line);
}
/* 跨行卡片自身的入线：列间中线 → 卡片左缘 */
.bk-cell[data-span] > .bk-match::after {
  content: ''; position: absolute; left: -12px; top: 50%;
  width: 12px; height: 1px; background: var(--line);
}
/* 单线入线（子级不在上一列时，如入围赛 M3/M6）：只画一条横线指示流向。
   声明在 [data-span] 之后 → 同时带 data-in 时以入线为准。 */
.bk-cell[data-in]::before {
  content: ''; position: absolute; left: -12px; top: 50%;
  width: 12px; height: 1px; background: var(--line);
}
.bk-cell[data-in] > .bk-match::after { content: none; }
.bk-match {
  position: relative; width: 100%;
  display: flex; flex-direction: column;
  background: var(--card-2); border: 1px solid var(--line);
  border-radius: 9px; overflow: visible;
}
.bk-match > *:first-child { border-top-left-radius: 8px; border-top-right-radius: 8px; }
.bk-match > *:last-child { border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; }
.bk-mhead {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 5px 8px 2px; font-size: 9.5px; color: var(--muted); font-family: var(--mono);
}
.bk-team {
  display: flex; align-items: center; gap: 6px; padding: 4px 8px;
  font-size: 12px; min-width: 0;
}
.bk-team.w { color: var(--text); font-weight: 700; background: rgba(217, 180, 91, .07); }
.bk-team.l { color: var(--muted); }
.bk-team .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-team .sc { margin-left: auto; font-family: var(--mono); font-size: 11.5px; flex: 0 0 auto; }
.bk-team .logo { width: 16px; height: 16px; flex: 0 0 16px; }
.bk-team.ph { color: var(--muted); font-style: italic; font-size: 11px; }
.bk-note { padding: 0 8px 6px; font-size: 9.5px; color: var(--muted); font-family: var(--mono); }
.bk-tag {
  font-size: 9px; padding: 1px 4px; border-radius: 3px;
  border: 1px solid rgba(217, 180, 91, .34); color: var(--gold);
}
.bk-empty { padding: 22px 12px; text-align: center; color: var(--muted); font-size: 12.5px; }
.bk-legend {
  display: flex; flex-wrap: wrap; gap: 5px 14px; margin-top: 11px;
  padding-top: 9px; border-top: 1px solid var(--line-soft);
  font-size: 10.5px; color: var(--muted);
}

/* ---------------- 响应式 ---------------- */
@media (max-width: 940px) {
  .layout { grid-template-columns: 1fr; }
  .panel { position: static; }
  .stage-col { order: 1; }
  .panel { order: 2; }
}

@media (max-width: 560px) {
  :root { --dock-h: 62px; }
  .app { padding: 0 12px calc(var(--dock-h) + 22px); }

  /* 窄屏收起品牌文字，只留赛事图标。
     原因：顶栏是 flex-wrap 容器，而模式切换在 ≤720px 被 order:3 + width:100%
     钉成**整行的第二行**，第一行就只剩 brand 与 topmeta 相加。这两块都不可压缩
     （h1 带 .14em letter-spacing、.stage-chip 是 white-space:nowrap），放不下时
     topmeta 整体掉到第二行 ⇒ 顶栏从两行变三行（实测 111px → 154px），
     进度条与音乐开关就此离开 logo 那一行 —— 玩家报的就是这个。
     2026-09-22 实测（tools/_topbar-probe.cjs，8 视口 × 5 状态）：
       · S16  模式：390px 起正常，320 / 360 换行
       · 德杯 模式：**414px 就换行**（标题 DEMACIA CUP 2026 更长 + chip 最长到
         「0-2 积分赛」），要到 480px 才正常
     收起文字后第一行 = logo 34 + gap 14 + topmeta（最长 188）= 236px，
     320px 视口仍有 60px 余量，全区间不再换行。
     信息不丢：第二行的模式切换 tab 写着赛事全名（S16 全球总决赛 / 德杯国际邀请赛），
     且 .brand-mark 的 alt 由 syncModeChrome() 跟着模式更新，读屏也拿得到。 */
  .brand-text { display: none; }
  .brand-mark { width: 34px; height: 34px; flex-basis: 34px; font-size: 17px; }
  .progress-bar { width: 60px; }
  .topmeta { gap: 8px; }
  .bgm-btn { width: 28px; height: 28px; }

  .dock { padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px)); }
  /* flex-wrap 是**兜底**：队列里按钮再多、文案再长，也只换行、不越出视口右边界。
     .dock 是 position:fixed，越界的按钮会被切在屏幕外而且滚不到 ——
     2026-09-21 实测 390px 下「下一场 ›」右边界到 428（六个按钮最小总宽 416px，
     加内边距要 440px 视口才放得下）。 */
  .dock-inner { gap: 7px; flex-wrap: wrap; }
  .btn { padding: 8px 12px; font-size: 12.5px; }
  .btn-ghost { padding: 8px 10px; font-size: 12px; }
  #btnNext, #btnSkip { flex: 1; }
  /* 播放期间收起三个工具按钮：此时玩家能做的只有「下一局 / 播完本场 / 跳过本轮」，
     重置 / 换种子 / 参数 既用不上、又正是把主按钮挤出屏幕的主因。
     收起后三个操作按钮平分整行，手指也好按。class 由 ui.js 的 updateDock 挂。 */
  .dock-inner.playing .btn-ghost,
  .dock-inner.playing .dock-spacer { display: none; }
  .dock-inner.playing #btnRun,
  .dock-inner.playing #btnSkip,
  .dock-inner.playing #btnNext { flex: 1 1 auto; }

  .round-head { padding: 11px 13px; }
  .round-title { font-size: 13.5px; }
  .matches { padding: 4px 5px; }
  .mt { padding: 8px 6px; gap: 6px; }
  .mt-name { font-size: 12.5px; }
  .mt-score { font-size: 12px; padding: 3px 8px; }
  .quip, .events { margin-left: 12px; margin-right: 12px; }
  .events { padding-left: 0; padding-right: 0; }

  .empty { padding: 30px 18px; }
  .empty h2 { font-size: 18px; }

  /* 新组件移动端收敛 */
  .viewtabs { width: 100%; }
  .vtab { flex: 1; padding: 6px 10px; }
  .pg-item { font-size: 10.5px; padding: 4px 8px; }
  .pager { gap: 5px; padding: 5px; }
  .bk-block { padding: 11px; }
  .bk-grid { gap: 10px 16px; }
  .bk-grid { grid-template-columns: repeat(var(--cols, 3), minmax(112px, 1fr)); }
  .bk-cell:not([data-last])::after { right: -8px; width: 8px; }
  .bk-cell[data-span]::before { left: -8px; }
  .bk-cell[data-span] > .bk-match::after { left: -8px; width: 8px; }
  .bk-cell[data-in]::before { left: -8px; width: 8px; }
  .bk-team { font-size: 11px; padding: 3px 7px; }
  .games { padding: 7px 10px 8px; }
  .games .game { font-size: 10.5px; }
}

@media (max-width: 380px) {
  .mt-name { font-size: 11.5px; }
  .sl-row { grid-template-columns: 66px 1fr 30px; }
}

/* ---------------- 队伍 Logo ---------------- */
.logo {
  flex: 0 0 auto;
  display: block;
  object-fit: contain;
  background: #eef2f9;
  border-radius: 5px;
}
/* 亮色 logo 换深底盘，保证对比度（配色表见 js/logo-tone.js） */
.logo.plate-dark {
  background: #171c29;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .10);
}
.mt-side .logo { width: 22px; height: 22px; padding: 2px; }
.st-row .logo  { width: 16px; height: 16px; padding: 1.5px; border-radius: 4px; }
.chip .logo    { width: 14px; height: 14px; padding: 1px; border-radius: 3px; margin-right: 4px; vertical-align: -3px; }
.sl-name .logo { width: 16px; height: 16px; padding: 1.5px; border-radius: 4px; }
.res-item .logo { width: 15px; height: 15px; padding: 1.5px; border-radius: 4px; vertical-align: -3px; margin-right: 5px; }
.res-champ .logo { width: 34px; height: 34px; padding: 3px; border-radius: 9px; margin: 0 auto 8px; }

.mt-side .logo.lose { opacity: .62; filter: saturate(.55); }
.st-name { display: flex; align-items: center; gap: 5px; min-width: 0; }
.sl-name { display: flex; align-items: center; gap: 6px; }
.res-item > span { display: inline-flex; align-items: center; gap: 1px; min-width: 0; }

/* ---------------- Toast ---------------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--dock-h) + 22px + env(safe-area-inset-bottom, 0px));
  z-index: 90;
  transform: translate(-50%, 14px);
  max-width: 84vw;
  padding: 10px 18px;
  border-radius: 10px;
  font-size: 12.5px;
  color: var(--text);
  background: rgba(28, 33, 48, .97);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }

/* 滚动定位留出顶栏空间 */
.round { scroll-margin-top: 78px; }
.pcard { scroll-margin-top: 78px; }

/* -------- 缺图兜底：字母徽标 --------
   有 logo 文件时完全不会出现；文件缺失时顶替 <img> 的位置
   （2026-09-21 之前德杯 9 支队就是靠它撑住的，现已补齐正式队标），
   尺寸与 .logo 一致，所以排版不会因为缺图而错位。 */
.logo-fallback {
  display: inline-grid;
  place-items: center;
  width: 16px; height: 16px;
  border-radius: 4px;
  font-style: normal;
  font-size: 8px;
  font-weight: 800;
  letter-spacing: -0.2px;
  line-height: 1;
  color: var(--text-2);
  background: rgba(255, 255, 255, .07);
  border: 1px solid var(--line);
  vertical-align: -3px;
  margin-right: 4px;
  text-transform: uppercase;
}
.logo-fallback.lose { opacity: .45; }
.games .logo-fallback, .coach-strip .logo-fallback { width: 15px; height: 15px; font-size: 7.5px; }
.st-name .logo-fallback { width: 16px; height: 16px; }
.bk-team .logo-fallback { width: 18px; height: 18px; font-size: 8.5px; }
.res-item .logo-fallback { width: 15px; height: 15px; }

/* ============================================================
 * 赛事模式（S16 / 德杯）
 * 两套强调色：S16 用金色（世界赛视觉），德杯用**官方蓝金**。
 * 只覆盖 --gold 系列变量，不逐个改选择器 —— 主题是一个全局状态，
 * 分散写死颜色会在下次调整时漏掉一半。
 *
 * 德杯蓝的来历（2026-09-21 第四次改色，前三版：青绿）：
 *   官方视觉的主蓝实测为 #1826A0（从素材图上取标题笔画 = #1927a2）。
 *   但它在暗底 #0b0d12 上对比度只有 1.7，当文字色完全读不了 ——
 *   所以**保留色相 232°、只提亮**：hsl(232, 74%, 63%) = #6475e8，对比度 4.8 ✓。
 *   这是暗色主题下的标准做法：品牌色不能直接搬，要按底色调亮度。
 *   官方金 #f0cc9f 作次强调（背景第二层光晕用它），蓝主金辅才是那套视觉的关系。
 * ============================================================ */
:root {
  --accent:      #d9b45b;
  --accent-dim:  #8a7135;
  --accent-soft: rgba(217, 180, 91, .10);
  --accent-line: rgba(217, 180, 91, .34);
  --accent-text: #f0dcac;
}
html[data-mode="demacia"] {
  --gold:        #6475e8;
  --gold-dim:    #3d49b0;
  --accent:      #6475e8;
  --accent-dim:  #3d49b0;
  --accent-soft: rgba(100, 117, 232, .10);
  --accent-line: rgba(100, 117, 232, .34);
  --accent-text: #c6cef8;
}
/* 背景光晕也跟着换，否则顶栏还是金色的。
   第二层刻意用官方金（低透明度）—— 蓝金两色同时在场，才是德杯那套视觉。 */
html[data-mode="demacia"] body {
  background-image:
    radial-gradient(900px 480px at 12% -8%, rgba(100, 117, 232, .13), transparent 62%),
    radial-gradient(760px 420px at 92% 4%, rgba(240, 204, 159, .07), transparent 60%);
}

/* -------- 德杯下的按钮：一律单一色相，不许蓝黄混（2026-09-21 第十一轮） --------
 * 病根：几处按钮的渐变配方写的是「硬编码浅金 + var(--gold)」。
 *   S16 下 --gold 本身就是金，整条同色相，看不出问题；
 *   德杯下 --gold 被换成官方蓝 #6475e8，同一行配方立刻变成
 *   浅金(#f0d189) → 蓝 → 暗金(#b08f38)，一个按钮上两种色相。
 *
 * 修法：德杯下把这几处切成**单一色相的蓝**（亮蓝 → 深蓝），字改白；
 *   直接引用 --gold / --gold-dim，不再写死色值 —— 以后调德杯蓝，
 *   按钮自动跟随（这才是本文件一贯的做法：主题是全局状态，别分散写死）。
 *   覆盖范围是「有底色渐变的物件」这四处：主按钮、小按钮、选中态 tab、
 *   参数抽屉的滑杆圆钮。
 *
 * 文字为什么要改白：原来的深字 #1a1405 是按金底配的，
 *   搬到蓝底上对比度只剩 4.2，且观感发脏。
 *
 * .btn-warn（播完本场 / 跳过本轮）刻意**不覆盖**：它是 #ffd08a → #ffab42
 *   的纯黄橙，本来就不含蓝。蓝主 + 金辅正是德杯官方那套视觉的主次关系，
 *   辅助按钮留给金，主次才分得开。
 * ------------------------------------------------------------------------ */
html[data-mode="demacia"] .btn-primary,
html[data-mode="demacia"] .mini-btn.primary,
html[data-mode="demacia"] .vtab.on {
  color: #f4f7ff;
  background: linear-gradient(150deg, var(--gold), var(--gold-dim));
  box-shadow: 0 4px 16px rgba(61, 73, 176, .34);
}
html[data-mode="demacia"] .mini-btn.primary:hover { color: #f4f7ff; }
/* 选中态 tab 的边框原本取 --gold-dim，跟新背景的暗端撞成一片 → 改取亮蓝描边 */
html[data-mode="demacia"] .vtab.on { border-color: var(--accent-line); }
/* 实验室的档位按钮是同一类东西（选中态 = 实心 + 深字），所以同一处覆盖。 */
html[data-mode="demacia"] .lab-size.on,
html[data-mode="demacia"] .lab-sort.on {
  color: #f4f7ff;
  background: linear-gradient(150deg, var(--gold), var(--gold-dim));
  border-color: var(--accent-line);
  box-shadow: 0 4px 16px rgba(61, 73, 176, .34);
}
html[data-mode="demacia"] input[type="range"]::-webkit-slider-thumb {
  background: var(--gold);
  box-shadow: 0 2px 8px rgba(61, 73, 176, .45);
}

/* -------- 模式切换（顶栏） -------- */
.mode-switch {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px;
  border-radius: 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  flex: 0 0 auto;
}
.ms-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
  transition: color .16s ease, background .16s ease;
}
.ms-btn:hover { color: var(--text-2); background: rgba(255, 255, 255, .04); }
/* 重放期间模式切换也上锁（换赛事 = 换一套状态机，重放的那一局就不存在了） */
.ms-btn:disabled { opacity: .45; cursor: not-allowed; }
.ms-btn:disabled:hover { color: var(--muted); background: transparent; }
.ms-btn.on:disabled { opacity: .6; }
.ms-btn.on:disabled:hover { color: #10130c; background: var(--accent); }
.ms-btn.on {
  color: #10130c;
  background: var(--accent);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
}
html[data-mode="demacia"] .ms-btn.on { color: #060a1e; }

/* 窄屏：模式切换换行到第二行，别把顶栏挤爆 */
@media (max-width: 720px) {
  .topbar { flex-wrap: wrap; }
  .brand { flex: 1 1 auto; }
  .mode-switch { order: 3; width: 100%; justify-content: center; }
  .ms-btn { flex: 1 1 0; text-align: center; }
}

/* -------- 教练席（德杯线下专属） -------- */
.coach {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-top: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-left-width: 3px;
  font-size: 12.5px;
  line-height: 1.7;
}
.coach-tag {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .12em;
  color: var(--accent);
  border: 1px solid var(--accent-line);
  border-radius: 5px;
  padding: 1px 6px;
  margin-top: 2px;
}
.coach-txt { color: var(--accent-text); }

/* -------- 教练沟通卡用量条 -------- */
.coach-strip {
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center;
  padding: 7px 12px 9px; border-top: 1px dashed var(--line-soft);
  /* 德杯专属区块（教练卡是德杯线下独有），底色取德杯蓝的极低透明度。
     不用 var(--accent-soft)：那个是 .10，做背景太抢眼。 */
  background: rgba(100, 117, 232, .035);
}
.coach-strip .gl {
  font-size: 10px; letter-spacing: .1em; color: var(--muted);
  font-weight: 700; margin-right: 3px;
}
.coach-strip .cc {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--line); background: var(--bg-soft);
  border-radius: 7px; padding: 3px 7px 3px 5px;
}
.coach-strip .cc.max { border-color: var(--accent-line); background: var(--accent-soft); }
/* 逐格入场（同 .games .game.enter）：教练卡的格数 = 局数，
   预先塞进去等于提前告诉玩家这场打了几局。 */
.coach-strip .cc.enter { animation: mtIn .3s ease both; }
.coach-strip .cc .gn { font-family: var(--mono); font-size: 9.5px; color: var(--muted); }
/* 格内两行 = **双方各自**的用量（上行主队 / 下行客队）。
   德杯是两位教练各有各的 3 张、不是双方共用 3 张，所以一格必须画两行。
   gn 与 cn 原本就各占一列、只有 pip 区从一行变两行 ⇒ **不增加宽度**，只抬高格子。 */
.coach-strip .cc .cr { display: inline-flex; flex-direction: column; gap: 2px; }
.coach-strip .cc .cd { display: inline-flex; align-items: center; gap: 4px; }
.coach-strip .cc .pip {
  width: 7px; height: 11px; border-radius: 2px;
  background: rgba(255, 255, 255, .10);
  display: inline-block;
}
.coach-strip .cc .pip.on { background: var(--accent); }
html[data-mode="demacia"] .coach-strip .cc .pip.on { background: #4a58d8; }
/* 客队取德杯官方金，与主队的官方蓝成对 ——
   这是**两个主体之间**的区分；「不许蓝黄混」管的是同一个控件内部，不是这里。 */
html[data-mode="demacia"] .coach-strip .cc .cd.b .pip.on { background: #f0cc9f; }
.coach-strip .cc .cn { font-family: var(--mono); font-size: 9.5px; color: var(--text-2); }
/* 队伍列：两枚队标上下排，与格内两行 pip 一一对应。
   少了它，「上行是哪支队」根本无从判断 —— 那正是玩家报上来的问题。 */
.coach-strip .cflags {
  display: inline-flex; flex-direction: column; gap: 3px; margin-right: 2px;
}
.coach-strip .cflag { display: inline-flex; align-items: center; height: 11px; }
.coach-strip .cflag .logo { width: 13px; height: 13px; border-radius: 3px; }
.coach-strip.hidden { opacity: 0; visibility: hidden; }
.coach-strip.reveal { animation: mtIn .3s ease both; }
@media (max-width: 560px) {
  /* 窄屏优先级：尾标签是规则说明、不参与读数，先让位；
     再收一点 pip 与内边距 —— 5 局 × 双方两行也能挤进 390px。 */
  .coach-strip .gl:last-child { display: none; }
  .coach-strip .cc { padding: 3px 5px 3px 4px; gap: 4px; }
  .coach-strip .cc .pip { width: 6px; height: 10px; }
  .coach-strip .cflag .logo { width: 12px; height: 12px; }
}

/* -------- 侧栏：战绩表的小分差 / 递补标记 -------- */
.st-diff {
  font-family: var(--mono); font-size: 10.5px; color: var(--muted);
  text-align: right; min-width: 26px;
}
.st-via {
  font-style: normal; font-size: 9.5px; font-weight: 700;
  color: var(--accent); border: 1px solid var(--accent-line);
  border-radius: 4px; padding: 0 3px; margin-left: 3px;
}

/* -------- 席位卡的补充说明行 -------- */
.slot-note {
  margin-top: 4px; padding-top: 8px;
  border-top: 1px dashed var(--line-soft);
  font-size: 10.5px; line-height: 1.65; color: var(--muted);
}

/* -------- 参数抽屉：只读说明块（德杯名额） -------- */
.sp-note {
  font-size: 11.5px; line-height: 1.75; color: var(--text-2);
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent-line);
  border-radius: var(--radius-sm); padding: 9px 11px;
}
.sp-note b { color: var(--accent-text); }

/* -------- 侧栏「本阶段最相关」的那张卡 --------
   arrangePanel() 把最相关的卡用 order:-1 提到最上面，这里给它一条强调边，
   否则「卡换了位置」在视觉上完全不可见，玩家只会觉得界面在跳。 */
.pcard-first { border-color: var(--accent-line); }
.pcard-first h3::after {
  content: "";
  display: inline-block; width: 6px; height: 6px; margin-left: 7px;
  border-radius: 50%; background: var(--accent); vertical-align: 2px;
}

/* ---------------- 抽签直播间（F01） ----------------
   与结果图弹层共用 .modal 机制，但内容是两栏的现场演出，所以盒子更宽
   （桌面 720px；620px 以下收成单栏）。
   强调色一律走 --accent 系列 —— 它会随模式切换（S16 金 / 德杯蓝金），
   硬写金色会让德杯的抽签间看起来是另一个赛事的界面。 */
body.draw-open { overflow: hidden; }

.draw-modal { z-index: 80; }
.draw-box { width: min(720px, 100%); }
.draw-body { padding: 16px 18px 18px; }

.draw-cap {
  margin: 0 0 9px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em;
  color: var(--accent-dim, var(--gold-dim));
}
.draw-sub { margin: 0 0 13px; font-size: 12.5px; line-height: 1.7; color: var(--text-2); }
.draw-sub b { color: var(--accent-text, var(--gold)); }

.draw-rules {
  margin-bottom: 15px; padding: 10px 12px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--bg);
}
.draw-rulelist { margin: 0; padding-left: 17px; }
.draw-rulelist li { font-size: 12.5px; line-height: 1.95; color: var(--text-2); }
.draw-note {
  margin: 8px 0 0; padding-top: 8px;
  border-top: 1px dashed var(--line-soft);
  font-size: 11.5px; line-height: 1.75; color: var(--muted);
}

/* -------- 准备页：参与队伍 -------- */
.draw-field { display: flex; flex-direction: column; gap: 9px; }
.draw-prepcell {
  display: flex; flex-direction: column; gap: 7px;
  padding: 9px 11px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--bg);
}
.dpc-label { font-size: 11.5px; font-weight: 700; color: var(--text-2); }
.dpc-ids { display: flex; flex-wrap: wrap; gap: 6px; }

/* -------- 队伍 chip -------- */
.dchip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px 3px 5px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--card); font-size: 11.5px; line-height: 1.3;
  white-space: nowrap;
  transition: border-color .18s, background .18s, box-shadow .18s, transform .18s;
}
.dchip .logo,
.dchip .logo-fallback {
  width: 18px; height: 18px; padding: 1.5px; border-radius: 4px;
  margin: 0; vertical-align: baseline;
}
.dchip b { font-weight: 600; }
.dchip-reg { width: 4px; height: 12px; border-radius: 2px; flex: 0 0 auto; }
.dchip.sm { padding: 2px 7px 2px 4px; font-size: 11px; }
.dchip.sm .logo, .dchip.sm .logo-fallback { width: 15px; height: 15px; }

/* 焦点：本拍抽出的那支。每拍重渲染一次 ⇒ 动画只在这一个元素上重播，
   视觉上就是「刚抽出来的那支弹了一下」。 */
.dchip.focus {
  border-color: var(--accent, var(--gold));
  background: var(--accent-soft, rgba(217, 180, 91, .10));
  box-shadow: 0 0 0 2px var(--accent-line, rgba(217, 180, 91, .34));
  animation: chipIn .34s cubic-bezier(.2, .9, .3, 1.1) both;
}
/* 合法对手：虚线金边 —— 与「已抽中」的实心绿区分开。
   只在合法对手 ≥ 2 时出现（非泄露闸，见 js/draw.js 的 showCandidates）。 */
.dchip.legal {
  border-style: dashed;
  border-color: var(--accent-dim, var(--gold-dim));
  background: var(--accent-soft, rgba(217, 180, 91, .10));
}
/* 刚刚落位的一对（子拍 0 时「已抽定」区最后一行）。
   池子的相位改正后，这一签的「揭晓」不发生在池子里 —— 池子只是取消高亮，
   所以绿框要落在结果行上，否则那一拍在屏幕上没有任何变化。 */
.dchip.picked {
  border-color: var(--green);
  background: rgba(78, 201, 127, .14);
  box-shadow: 0 0 0 2px rgba(78, 201, 127, .20);
  animation: chipIn .34s cubic-bezier(.2, .9, .3, 1.1) both;
}
@keyframes chipIn {
  from { opacity: .35; transform: scale(.9); }
  to { opacity: 1; transform: none; }
}

/* -------- 演出页 -------- */
.draw-stage { display: flex; flex-direction: column; gap: 13px; }
.draw-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.draw-round { font-size: 13.5px; font-weight: 700; }
.draw-progress { font-size: 11.5px; color: var(--muted); }
.draw-progress b { color: var(--accent-text, var(--gold)); font-size: 13.5px; }

.draw-main { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.draw-col { min-width: 0; }
.draw-poolhead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 9px;
}
.dph-label { font-size: 11.5px; font-weight: 700; color: var(--accent-text, var(--text-2)); }
.dph-flag { font-size: 10.5px; color: var(--muted); text-align: right; }
/* 落位模型的阶段徽标（「抽 A 池」/「抽 B 池」）。margin-right:auto 让它紧贴
   左侧标签、同时把右侧的档位说明推到行尾 —— 池头仍是 flex + space-between。 */
.dph-stage {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
  color: var(--accent-text, var(--gold));
  margin-left: 6px; margin-right: auto;
}
.dph-warn { color: var(--red); }
.draw-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.draw-tip {
  margin: 11px 0 0; font-size: 11.5px; line-height: 1.75; color: var(--text-2);
}
.draw-tip b { color: var(--accent-text, var(--gold)); }
.draw-empty { margin: 0; font-size: 11.5px; color: var(--muted); }

.draw-done { display: flex; flex-direction: column; gap: 6px; }
.dpair {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 8px;
  padding: 7px 9px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--bg);
  animation: chipIn .3s ease both;
}
.dpair.live { border-color: var(--accent-dim, var(--gold-dim)); background: var(--accent-soft, rgba(217, 180, 91, .10)); }
.dpair-side { display: flex; justify-content: flex-end; min-width: 0; overflow: hidden; }
.dpair-side:last-child { justify-content: flex-start; }
.dpair-vs { font-size: 9.5px; font-weight: 800; letter-spacing: .1em; color: var(--muted); }
.dpair-wait { font-style: normal; font-size: 11px; color: var(--muted); }

.draw-foot { flex-wrap: wrap; }

@media (max-width: 620px) {
  .draw-main { grid-template-columns: 1fr; }
  .draw-body { padding: 13px 13px 15px; }
  .draw-foot { justify-content: stretch; }
  .draw-foot .btn { flex: 1 1 auto; }
}

/* ============================================================
 * F03 追队模式（需求 §6）
 *  · 赛程页主队高亮（§6.2）
 *  · 侧栏主队赛程面板（§6.3）
 * 颜色一律走 --gold / --accent-* —— 德杯下那几个变量会被换成官方蓝，
 * 这样两套配色自动跟随（本文件一贯做法：主题是全局状态，不分散写死）。
 * ============================================================ */

/* 主队那一场的淡底。⚠️ 左侧竖条**只加在非 real 行**上：
   真实赛果行（.mt.real）已经占用了同一条 inset box-shadow，
   两条写在一起时后者胜，会把「已发生」的标记整条抹掉。 */
.mt.hero { background: rgba(217, 180, 91, .055); }
html[data-mode="demacia"] .mt.hero { background: rgba(100, 117, 232, .11); }
.mt.hero:not(.real) { box-shadow: inset 3px 0 0 var(--gold-dim); }
.mt.hero .mt-name { color: var(--text); }

.follow-hint { margin: 0 0 8px; font-size: 11.5px; line-height: 1.7; color: var(--muted); }
.follow-sel, .story-sel {
  width: 100%; padding: 7px 9px;
  font-family: inherit; font-size: 12.5px;
  color: var(--text); background: var(--card-2);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  outline: none;
}
.follow-sel:focus, .story-sel:focus { border-color: var(--gold-dim); }

.follow-hero { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
.fh-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: none; }
.fh-dot.alive, .fh-dot.pending { background: var(--gold); }
.fh-dot.champion, .fh-dot.runnerup { background: var(--gold); box-shadow: 0 0 0 3px var(--accent-soft, rgba(217, 180, 91, .10)); }
.fh-dot.out { background: var(--red); }
.fh-name { font-size: 13px; font-weight: 700; }
.fh-st {
  margin-left: auto; flex: none;
  font-size: 10.5px; padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--text-2);
}
.fh-st.champion, .fh-st.runnerup { color: var(--accent-text, var(--gold)); border-color: var(--accent-line, rgba(217, 180, 91, .34)); }
.fh-st.out { color: var(--red); border-color: rgba(230, 69, 83, .4); }

.follow-rec {
  display: flex; flex-wrap: wrap; gap: 4px 12px;
  font-size: 11.5px; color: var(--text-2);
  padding: 7px 9px; margin-bottom: 8px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--bg);
}
.follow-rec b { color: var(--text); }

/* 「下一场」：只在引擎真的配对出来了才由 ui.js 渲染这一块（需求 §6.3 末句）。
   它左侧那条竖线就是「这一条是已确定的对阵」的视觉记号。 */
.follow-next {
  font-size: 11.5px; color: var(--text-2);
  margin-bottom: 8px; padding-left: 8px;
  border-left: 2px solid var(--gold-dim);
}
.follow-next b { color: var(--text); }
.follow-next.muted { border-left-color: var(--line); color: var(--muted); }
.fn-sub { color: var(--muted); }

/* 赛程列表用 flex 而不是 grid：行内「战绩组标题」之类的元素是可选的，
   定列数的 grid 遇到元素个数变化会整体错位。 */
.follow-list { display: flex; flex-direction: column; gap: 3px; margin-bottom: 9px; }
.follow-row {
  display: flex; align-items: center; gap: 7px;
  font-size: 11.5px; padding: 5px 8px;
  border-radius: 6px; background: var(--bg);
  border-left: 2px solid var(--line);
}
/* 胜负沿用全局口径（亮 = 赢、暗 = 输），不引入红绿 —— 与 .mt-side.w/.l 同源 */
.follow-row.w { border-left-color: var(--gold); }
.fr-stage { flex: 0 1 auto; max-width: 40%; font-size: 10.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fr-opp { flex: 1 1 auto; min-width: 0; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fr-sc { flex: none; font-family: var(--mono); color: var(--text); }
.fr-res { flex: none; font-weight: 700; color: var(--muted); }
.follow-row.w .fr-res { color: var(--accent-text, var(--gold)); }

.follow-act { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.follow-act .mini-btn { flex: 1 1 auto; }
.follow-opt { display: flex; align-items: flex-start; gap: 6px; font-size: 11px; line-height: 1.5; color: var(--muted); }
.follow-opt input { margin: 2px 0 0; flex: none; }

/* ============================================================
 * F04 世界赛故事档案 —— 第四个视图（需求 §11.1「世界赛档案」）
 * ============================================================ */
.story { display: flex; flex-direction: column; gap: 13px; min-width: 0; }
.story-head h2 { margin: 0 0 5px; font-size: 15px; font-weight: 700; letter-spacing: .02em; }
.story-sub { margin: 0; font-size: 12.5px; color: var(--text-2); }
.story-sub b { color: var(--accent-text, var(--gold)); }
.story-warn {
  margin: 8px 0 0; padding: 7px 10px;
  font-size: 11.5px; color: var(--text-2);
  border-left: 2px solid var(--accent-dim, var(--gold-dim));
  background: var(--accent-soft, rgba(217, 180, 91, .10));
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.story-block {
  padding: 12px 13px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card);
}
.story-block h3 {
  margin: 0 0 9px; font-size: 13px; font-weight: 700;
  letter-spacing: .02em;
  color: var(--accent-text, var(--gold));
}
.story-note { margin: 0 0 7px; font-size: 11.5px; line-height: 1.72; color: var(--text-2); }
.story-note:last-child { margin-bottom: 0; }
.story-note b { color: var(--text); }
.story-note.dim { color: var(--muted); font-size: 11px; }

.story-games { display: flex; flex-direction: column; gap: 3px; }
.story-g {
  display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; padding: 6px 9px;
  background: var(--bg); border-radius: 6px;
  border-left: 2px solid var(--line);
}
.story-g.w { border-left-color: var(--gold); }
.story-g.champ { border-left-color: var(--gold); background: var(--accent-soft, rgba(217, 180, 91, .10)); }
.sg-r { flex: 0 1 auto; max-width: 34%; font-size: 10.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sg-o { flex: 1 1 auto; min-width: 0; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sg-s { flex: none; font-family: var(--mono); color: var(--text); }
.sg-b { flex: none; font-size: 10px; color: var(--muted); }
.sg-t {
  flex: none; font-size: 10px; padding: 1px 6px; border-radius: 999px;
  color: var(--accent-text, var(--gold));
  border: 1px solid var(--accent-line, rgba(217, 180, 91, .34));
}
.sg-t.real { color: var(--text-2); border-color: var(--line); }

.story-list { display: flex; flex-direction: column; gap: 6px; }
.story-li { display: flex; gap: 9px; font-size: 11.5px; line-height: 1.6; }
.sl-name { flex: none; width: 62px; text-align: right; font-weight: 700; color: var(--accent-text, var(--gold)); }
.sl-txt { min-width: 0; color: var(--text-2); }

.story-line { margin: 0; padding-left: 20px; }
.story-line li { font-size: 11.5px; line-height: 1.75; color: var(--text-2); }
.story-line li + li { margin-top: 4px; }

.prof-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 10px 0 7px; font-size: 13px; font-weight: 700; }
.prof-region { font-size: 10.5px; font-weight: 400; color: var(--muted); padding: 1px 7px; border: 1px solid var(--line); border-radius: 999px; }
.prof-finish {
  margin-left: auto; font-size: 10.5px; font-weight: 400;
  padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--text-2);
}
.prof-finish.champion, .prof-finish.runnerup { color: var(--accent-text, var(--gold)); border-color: var(--accent-line, rgba(217, 180, 91, .34)); }
.prof-stages { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 9px; }
.prof-st { font-size: 11px; color: var(--muted); padding: 3px 8px; border-radius: 6px; border: 1px solid var(--line-soft); background: var(--bg); }
.prof-st b { color: var(--text); }

.story-share { display: flex; flex-wrap: wrap; gap: 7px; }
.story-share .mini-btn { flex: 1 1 auto; }

/* 窄屏：档案是单栏长页。
   让位的顺序是「先舍 BO 形式、再舍轮次名」—— 这两样都不含赛果，
   而对手与比分在任何宽度下都必须留着。 */
@media (max-width: 560px) {
  .story-block { padding: 11px 11px; }
  .sg-b { display: none; }
  .sg-r { max-width: 40%; }
  .fr-stage { max-width: 34%; }
  .sl-name { width: 52px; }
}


@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
