@import url('../assets/fonts/kira.css');
@import url('../assets/fonts/misans.css');
/*! 本网站由月之森生态果蔬制作，反馈群：1098440238 */
/* ==========================================================================
   Sparklin'PARTY — 设计系统
   1. Tokens  2. Base  3. Controls  4. Shell  5. Page  6. Home
   7. Deck    8. Codex   9. Battle  10. Overlay/FX 11. Responsive
   ========================================================================== */

/* 1. Tokens ---------------------------------------------------------------- */
:root {
  --bg: #f4f1f6;
  --bg-deep: #ece6f1;
  --paper: #ffffff;
  --paper-soft: #fbf8fd;
  --ink: #241c2c;
  --ink-soft: #453a52;
  --muted: #7c7189;
  --line: #e6dfec;
  --line-strong: #d5c9df;
  --accent: #f2509a;
  --accent-deep: #d1307a;
  --accent-ink: #8d1d55;
  --accent-soft: #ffe4f0;
  --night: #191426;
  --night-2: #241d36;
  --night-line: #3d3354;
  --teal: #1f8a70;
  --gold: #b57a10;

  --radius-xs: 8px;
  --radius-sm: 12px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-pill: 999px;

  --shadow-sm: 0 2px 8px rgba(36, 28, 44, 0.06);
  --shadow-md: 0 12px 32px rgba(36, 28, 44, 0.1);
  --shadow-lg: 0 28px 70px rgba(36, 28, 44, 0.2);

  /* 全站字体：UI素材里的 KirakaraMaru v1.1（assets/fonts/kira.css 里声明）。
     MiSans 只作兜底（素材缺字时的后备），后面的系统字体再兜一层。 */
  --font: "KirakaraMaru", "MiSans", "YouYuan", "\5E7C\5706", "幼圆", "HarmonyOS Sans SC", "PingFang SC", "Microsoft YaHei UI", "Noto Sans CJK SC", "Segoe UI", system-ui, sans-serif;
  /* 等宽也统一到同一套字体：全站只有一种字体，数字不再切成另一种字形 */
  --mono: "KirakaraMaru", "Cascadia Code", Consolas, monospace;

  /* 全站唯一的卡牌尺寸（5:7）。所有卡牌（手牌 / 牌组 / 图鉴 / 准备页 / 详情）
     都是这一个尺寸，替换美术时只要按这个比例出图即可。 */
  --card-w: 150px;
  --card-h: 210px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* 2. Base ------------------------------------------------------------------ */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  /* 兜底色：任何瞬时重绘都不会露出纯白 */
  background-color: var(--bg-deep);
}

body {
  margin: 0;
  min-height: 100vh;
  /* 网站背景：素材图（已在生成时做柔化） */
  background-image: url('/assets/bg/site-bg.webp');
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
  background-attachment: fixed;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink);
  /* 上面已用 background-image 指定背景图；这里只叠一层半透明氛围色，不能再写 background 简写 */
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  position: relative;
}



h1, h2, h3, h4 {
  margin: 0;
  line-height: 1.25;
  letter-spacing: -0.2px;
}

p {
  margin: 0;
}

button {
  font: inherit;
  color: inherit;
}

a {
  color: var(--accent-ink);
}

code {
  font-family: var(--mono);
  font-size: 0.88em;
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--paper-soft);
  border: 1px solid var(--line);
}

kbd {
  font-family: var(--mono);
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.16);
  background: rgba(255, 255, 255, 0.22);
}

.muted {
  color: var(--muted);
}

.mono {
  font-family: var(--mono);
  font-size: 12px;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
}

.view-error {
  max-width: 560px;
  margin: 80px auto;
  padding: 28px;
  border-radius: var(--radius-md);
  background: var(--paper);
  border: 1px solid var(--line);
  text-align: center;
}

/* 3. Controls -------------------------------------------------------------- */
.btn {
  --btn-bg: var(--paper);
  --btn-ink: var(--ink);
  --btn-border: var(--line);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 42px;
  padding: 0 18px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--btn-border);
  background: var(--btn-bg);
  color: var(--btn-ink);
  font-weight: 650;
  font-size: 14px;
  cursor: pointer;
  transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease), background 0.15s, border-color 0.15s;
  white-space: nowrap;
}

.btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.btn:active:not(:disabled) {
  transform: translateY(0);
}

.btn:disabled {
  opacity: 0.48;
  cursor: not-allowed;
}

.btn-primary {
  --btn-bg: linear-gradient(135deg, #ff7ab2, var(--accent) 55%, var(--accent-deep));
  --btn-ink: #fff;
  --btn-border: transparent;
  box-shadow: 0 8px 20px rgba(242, 80, 154, 0.28);
}

.btn-primary:hover:not(:disabled) {
  box-shadow: 0 12px 26px rgba(242, 80, 154, 0.34);
}

.btn-ghost {
  --btn-bg: rgba(255, 255, 255, 0.9);
  --btn-border: var(--line-strong);
}

.btn-ghost:hover:not(:disabled) {
  background: #fff;
  border-color: var(--accent);
}

.btn-danger {
  --btn-bg: #ffe9ef;
  --btn-ink: #a41f47;
  --btn-border: #f6c0d2;
}

.btn-lg {
  min-height: 52px;
  padding: 0 26px;
  font-size: 15px;
}

.icon-btn {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  border: 1px solid var(--line-strong);
  background: #fff;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}

.icon-btn:hover {
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* ── 「胶囊白」素材：assets/ui/pill-white.png（1024×256，白底 / 细边 / 外发光）
   用 9 宫格 border-image 拉伸，左右圆头不跟着变宽，所以窄胶囊（房间号）和宽胶囊（战绩）都好看。
   素材右端的星点已去掉（小尺寸下只会糊成脏点）；要换素材就重跑 tools/make-pill-white.mjs。 ── */
.chip,
.net-status,
.room-chip {
  border: 4px solid transparent;
  border-image-source: url('../assets/ui/pill-white.png');
  border-image-slice: 48 130 48 130 fill;
  border-image-width: 4px 14px;
  border-image-repeat: stretch stretch;
  background: none;
  box-shadow: none;
}

/* 中性小胶囊统一走「胶囊白」，不再用半透明白
   （半透明白压在粉色顶栏 #fd3c73 上会透成粉的，看着像另一个组件） */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  color: var(--ink-soft);
  cursor: pointer;
}

.chip:hover {
  box-shadow: 0 0 0 2px rgba(242, 80, 154, 0.35);
}

.input {
  width: 100%;
  padding: 11px 13px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--paper-soft);
  color: var(--ink);
  font-size: 13px;
  line-height: 1.6;
  resize: vertical;
}

.input:focus {
  outline: 2px solid rgba(242, 80, 154, 0.35);
  outline-offset: 1px;
  background: #fff;
}

select.input, .setting-row select {
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: #fff;
  font-size: 13px;
  color: var(--ink);
}

.form-error {
  color: #b02a4c;
  font-size: 12.5px;
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.codex-sort-row,
.codex-rarity-row,
.codex-filter-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin: -4px 0 14px;
}

.codex-rarity-row,
.codex-filter-row {
  margin-bottom: 8px;
}

.codex-rarity-row > span,
.codex-filter-row > span,
.codex-sort-row > span {
  margin-right: 2px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.codex-sort-row > span {
  margin-right: 2px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.filter {
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: #fff;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
}

.filter.active {
  border-color: var(--band, var(--accent));
  background: var(--band-soft, var(--accent-soft));
  color: var(--band, var(--accent-ink));
  font-weight: 700;
}

/* 4. Shell ----------------------------------------------------------------- */
.shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 20px;
  height: 66px;
  padding: 0 clamp(14px, 3vw, 34px);
  border-bottom: 1px solid #ff9dbe;
  /* 顶栏＝纯色粉（与选中的粉色按钮同一色值，#FD3C73 取自 assets/ui/btn-pink-xxs.png 的填充），不做渐变 */
  background: #fd3c73;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 6px 18px rgba(242, 80, 154, 0.14);
}

/* 纯色粉顶栏上的文字：主标题 / 副标题 / 版本号都转白，不能用深色或 muted 紫（在粉底上会糊/发脏） */
.topbar .brand-text strong,
.topbar .brand-text small,
.topbar .version {
  color: #fff;
  text-shadow: 0 1px 2px rgba(140, 20, 60, 0.28);
}

.topbar .brand-text small,
.topbar .version {
  color: rgba(255, 255, 255, 0.88);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
}

.brand-mark {
  width: 38px;
  height: 38px;
  display: block;
  object-fit: cover;
  border-radius: 12px;
  background: linear-gradient(135deg, #ff8dbd, var(--accent) 55%, #a3266a);
  color: #fff;
  font-size: 18px;
  box-shadow: 0 8px 18px rgba(242, 80, 154, 0.32);
}

.brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.brand-text strong {
  font-size: 15px;
  letter-spacing: 1.4px;
}

.brand-text small {
  font-size: 10.5px;
  color: var(--muted);
  letter-spacing: 3px;
}

.nav {
  display: flex;
  gap: 2px;
  margin-left: 8px;
}

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  /* 导航项＝全站最新那套 UI 按钮素材（160×69、圆角≈5）：9 宫格 slice 6 / border 5px。
     默认白底深字，悬停 / 选中换粉底白字（与 .btn 完全同一套口径）。 */
  border: 5px solid transparent;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 5px;
  border-image-repeat: stretch;
  border-radius: 14px;
  background: none !important;
  box-shadow: none !important;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 630;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: filter 0.16s ease, color 0.16s ease;
}

.nav-icon {
  /* 固定成一个小方块再居中：★ / ⚙ 这类字形的实际宽度和基线各不相同，
     不锁死的话星号会比其它图标偏左偏下（2026-11-03 作者反馈「榜单的星星没对齐」） */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15em;
  height: 1.15em;
  line-height: 1;
  font-size: 13px;
  opacity: 0.75;
}

.nav-link:hover,
.nav-link:focus-visible,
.nav-link.active {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

.nav-link:hover .nav-icon,
.nav-link.active .nav-icon {
  opacity: 1;
}

.top-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 12px;
}

.version {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}

.view-host {
  flex: 1;
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 26px clamp(14px, 3vw, 34px) 60px;
}

.bgm-player {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 80;
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(980px, calc(100vw - 32px));
  min-height: 58px;
  padding: 9px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(12px);
}

.bgm-player[hidden],
.bgm-reopen[hidden],
.bgm-mini[hidden] {
  display: none;
}

.bgm-collapse {
  flex: 0 0 auto;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 11px;
  cursor: pointer;
}

/* 播放条封面：白底小方块 + 当前曲目所属乐队的团标（原来是 ♪ 音符）
   团标由 tools/make-band-emblems.mjs 生成，96×96 透明底，这里等比缩进 34×34 里 */
.bgm-cover {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 3px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #fff;
  box-shadow: 0 1px 2px rgba(36, 28, 44, 0.08);
  overflow: hidden;
}

.bgm-cover img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.bgm-meta {
  display: flex;
  flex: 0 1 190px;
  min-width: 110px;
  flex-direction: column;
  gap: 2px;
}

.bgm-meta strong,
.bgm-meta small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bgm-meta strong {
  color: var(--ink);
  font-size: 12px;
  line-height: 1.25;
}

.bgm-meta small {
  color: var(--muted);
  font-size: 9px;
}

.bgm-progress-wrap {
  display: flex;
  flex: 1 1 240px;
  min-width: 100px;
  align-items: center;
  gap: 8px;
}

.bgm-progress {
  --progress: 0%;
  flex: 1 1 auto;
  min-width: 50px;
  height: 4px;
  margin: 0;
  appearance: none;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--progress), var(--line-strong) var(--progress));
  cursor: pointer;
}

.bgm-progress::-webkit-slider-thumb {
  width: 10px;
  height: 10px;
  appearance: none;
  border-radius: 50%;
  background: var(--accent);
}

.bgm-progress::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
}

.bgm-time {
  flex: 0 0 auto;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 9px;
  white-space: nowrap;
}

.bgm-volume-icon {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font-size: 14px;
  cursor: pointer;
}

.bgm-volume {
  display: block;
  flex: 0 1 64px;
  min-width: 40px;
  height: 26px;
  margin: 0;
  accent-color: var(--accent);
}

.bgm-text-btn {
  flex: 0 0 auto;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper-soft);
  color: var(--ink);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}

.bgm-text-btn:hover,
.bgm-collapse:hover {
  border-color: var(--accent);
  color: var(--accent-ink);
}

.bgm-mode {
  flex: 0 1 142px;
  min-width: 96px;
  height: 32px;
  padding: 0 7px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper-soft);
  color: var(--ink-soft);
  font-size: 10px;
}

.bgm-close {
  flex: 0 0 auto;
  /* 叉要和旁边的「暂停 / 换一首 / 下拉」在同一条水平线上：
     它没有边框和背景，光靠 bar 的 align-items 居中，字本身会压在基线上偏低，
     所以这里自己做 flex 居中 + line-height:1（字形盒 = 控件盒） */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.bgm-close:hover {
  color: var(--accent-ink);
}

.bgm-mini {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 80;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: color-mix(in srgb, var(--paper) 72%, transparent);
  color: var(--muted);
  opacity: 0.5;
  font-size: 13px;
  cursor: pointer;
}

.bgm-mini:hover {
  opacity: 1;
  color: var(--accent-ink);
  border-color: var(--accent);
}

.bgm-reopen {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 80;
  padding: 9px 13px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--paper);
  color: var(--accent-ink);
  box-shadow: var(--shadow-md);
  font-weight: 800;
  cursor: pointer;
}

@media (max-width: 900px) {
  .bgm-player {
    left: 8px;
    right: 8px;
    bottom: 8px;
    width: auto;
    flex-wrap: wrap;
    gap: 7px;
  }
  .bgm-meta {
    flex: 1 1 150px;
  }
  .bgm-progress-wrap {
    order: 10;
    flex-basis: 100%;
  }
  .bgm-volume {
    display: none;
  }
  .bgm-mode-wrap {
    flex-basis: 130px;
  }
}


.footer {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  justify-content: center;
  padding: 22px 16px 30px;
  font-size: 11.5px;
  color: var(--muted);
  border-top: 1px solid rgba(36, 28, 44, 0.07);
}

/* 5. Page ------------------------------------------------------------------ */
.page {
  animation: page-in 0.32s var(--ease) both;
}

@keyframes page-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

.eyebrow {
  display: inline-block;
  font-size: 11px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--accent-ink);
  font-weight: 700;
}

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 26px;
}

.page-title {
  font-size: clamp(26px, 3.4vw, 34px);
  margin: 6px 0 8px;
}

.page-lead {
  color: var(--muted);
  font-size: 13.5px;
  max-width: 62ch;
}

.section {
  margin-top: 52px;
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}

.section-title {
  font-size: 21px;
}

.section-note {
  font-size: 12.5px;
  color: var(--muted);
}

/* 6. Home ------------------------------------------------------------------ */
.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: 36px;
  align-items: center;
  padding: clamp(26px, 4vw, 52px);
  border-radius: 32px;
  border: 1px solid rgba(255, 255, 255, 0.7);
  /* 简洁的纯白面板（原来是一层粉色径向 + 白粉linear 渐变） */
  background: #ffffff;
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.hero-title {
  font-size: clamp(38px, 5.6vw, 66px);
  line-height: 1.02;
  letter-spacing: -2px;
  /* 标题现在只有 logo 一张图，下边距收紧一点，别和按钮组拉太开 */
  margin: 14px 0 6px;
}

/* 标题 logo（assets/ui/title-logo.webp，由 tools/pack-title-logo.mjs 从「标题素材」裁出） */
.hero-logo {
  display: block;
  width: min(100%, 470px);
  height: auto;
  filter: drop-shadow(0 12px 26px rgba(255, 63, 126, 0.28));
}

.hero-title em {
  display: block;
  margin-top: -6px;
  font-style: normal;
  background: linear-gradient(120deg, #ff5fa2, #a13ad0);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-lead {
  max-width: 48ch;
  color: var(--ink-soft);
  font-size: 14.5px;
  line-height: 1.85;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

.hero-marks {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  margin: 38px 0 0;
  padding: 0;
  list-style: none;
}

.hero-marks li {
  display: flex;
  flex-direction: column;
}

.hero-marks b {
  font-size: 22px;
  letter-spacing: -0.5px;
}

.hero-marks span {
  font-size: 11.5px;
  color: var(--muted);
}

.hero-stage {
  position: relative;
  height: clamp(260px, 32vw, 380px);
  border-radius: 24px;
  /* 原图直出，不加任何蒙版 */
  background-image: url('/assets/ui/lobby-stage.webp');
  background-size: cover;
  background-position: center 62%;
  box-shadow: var(--shadow-lg), inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  overflow: hidden;
}

.hero-stage .hero-light,
.hero-stage .hero-floor { display: none; }

.hero-light {
  position: absolute;
  top: -10%;
  width: 180px;
  height: 130%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.42), transparent 72%);
  filter: blur(2px);
  transform-origin: 50% 0;
  animation: sweep 7s ease-in-out infinite alternate;
}

.hero-light-a {
  left: 8%;
  transform: rotate(16deg);
}

.hero-light-b {
  right: 2%;
  transform: rotate(-20deg);
  background: linear-gradient(180deg, rgba(255, 180, 216, 0.4), transparent 70%);
  animation-delay: -2.5s;
}

@keyframes sweep {
  50% {
    opacity: 0.55;
    transform: rotate(10deg) scaleX(1.15);
  }
}

.hero-deck {
  position: absolute;
  inset: auto 0 18% 0;
  display: flex;
  justify-content: center;
  gap: 0;
}

.hero-card {
  width: clamp(92px, 9vw, 122px);
  aspect-ratio: 0.72;
  margin: 0 -14px;
  border-radius: 14px;
  background: var(--band-gradient);
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: 0 18px 34px rgba(10, 6, 20, 0.45);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #fff;
  transform: rotate(calc((var(--i) - 1) * 9deg)) translateY(calc(var(--i) * -10px));
  transition: transform 0.5s var(--ease);
}

.hero-stage:hover .hero-card {
  transform: rotate(calc((var(--i) - 1) * 13deg)) translateY(calc(var(--i) * -14px - 8px));
}

.hero-card-glyph {
  font-size: 30px;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

.hero-card-logo {
  width: 46px;
  height: 46px;
  object-fit: contain;
  filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.35));
}

.hero-card-name {
  font-size: 10px;
  letter-spacing: 2px;
}

.hero-floor {
  position: absolute;
  inset: 68% -20% -30%;
  background:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.09) 0 1px, transparent 1px 18px),
    linear-gradient(180deg, rgba(255, 126, 178, 0.22), rgba(20, 14, 30, 0.9));
  transform: perspective(240px) rotateX(48deg);
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

.feature-card {
  padding: 22px;
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s var(--ease), box-shadow 0.2s;
}

.feature-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.feature-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 14px;
  border-radius: 12px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 18px;
}

.feature-card h3 {
  font-size: 15.5px;
  margin-bottom: 6px;
}

.feature-card p {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.8;
}

.band-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.band-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 20px;
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
  border-top: 3px solid var(--band);
  background: var(--paper);
  cursor: pointer;
  text-align: left;
  transition: transform 0.18s var(--ease), box-shadow 0.18s, background 0.18s;
}

.band-tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
}

.band-tile.active {
  background: var(--band-soft);
  border-color: var(--band);
}

.band-glyph {
  font-size: 26px;
  color: var(--band);
  line-height: 1.2;
}

.band-logo {
  width: 42px;
  height: 42px;
  object-fit: contain;
  filter: drop-shadow(0 3px 8px rgba(30, 20, 45, 0.18));
}

.band-tile strong {
  font-size: 15px;
  letter-spacing: 1px;
}

.band-tile small {
  font-size: 11px;
  color: var(--muted);
}

.band-motto {
  margin-top: 8px;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--ink-soft);
}

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  position: relative;
  padding: 20px 20px 20px 24px;
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
}

.steps li::before {
  counter-increment: step;
  content: counter(step);
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin-bottom: 10px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
}

.steps b {
  display: block;
  font-size: 14px;
}

.steps span {
  font-size: 12px;
  color: var(--muted);
}

/* 7. Deck ------------------------------------------------------------------ */
.deck-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.deck-count {
  font-family: var(--mono);
  font-size: 13px;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  background: #ffe9ef;
  color: #a41f47;
  border: 1px solid #f6c0d2;
}

.deck-count.ok {
  background: #e2f6ee;
  color: #146c53;
  border-color: #b7e6d5;
}

.deck-select-page {
  --card-w: 138px;
}

.deck-select-head-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.deck-select-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}

.deck-select-tile {
  position: relative;
  display: grid;
  grid-template-columns: 112px minmax(0, 1fr);
  gap: 14px;
  align-items: center;
  min-height: 142px;
  padding: 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  text-align: left;
  cursor: pointer;
  transition: transform 0.16s var(--ease), box-shadow 0.16s var(--ease), border-color 0.16s;
}

.deck-select-tile:hover {
  transform: translateY(-3px);
  border-color: var(--band, var(--accent));
  box-shadow: var(--shadow-md);
}

.deck-share-link {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 6;
  padding: 4px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper-soft);
  color: var(--accent-ink);
  font-size: 11px;
  font-weight: 800;
  cursor: pointer;
}

.deck-share-link:hover {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--ink-inverse, #170d1e);
}

.deck-share-entry {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--accent-ink);
}

.deck-select-art {
  position: relative;
  display: block;
  width: 112px;
  height: 116px;
}

.deck-select-art img {
  position: absolute;
  top: calc(4px + var(--i) * 5px);
  left: calc(14px + var(--i) * 18px);
  z-index: calc(1 + var(--i));
  width: 62px;
  height: 87px;
  object-fit: cover;
  border-radius: 7px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: 0 3px 8px rgba(15, 10, 25, 0.28);
  transform: rotate(calc((var(--i) - 1) * 5deg));
}

.deck-select-symbol {
  position: absolute;
  left: -5px;
  bottom: -4px;
  z-index: 5;
  display: block;
  width: 27px;
  height: 27px;
  padding: 3px;
  border-radius: 50%;
  object-fit: contain;
  background: var(--band-gradient);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

.deck-select-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 4px;
}

.deck-select-info strong {
  overflow: hidden;
  color: var(--ink);
  font-size: 15px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deck-select-info small {
  overflow: hidden;
  color: var(--muted);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deck-select-info em {
  color: var(--accent-ink);
  font-family: var(--mono);
  font-size: 10px;
  font-style: normal;
  font-weight: 700;
}

.deck-select-new {
  grid-template-columns: 72px minmax(0, 1fr);
  border-style: dashed;
  color: var(--muted);
}

.deck-select-plus {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background: var(--paper-soft);
  color: var(--accent-ink);
  font-size: 28px;
  font-weight: 300;
}

.deck-page {
  --card-w: 132px;
  --card-h: 185px;
}

@media (max-width: 720px) {
  .deck-select-grid { grid-template-columns: minmax(0, 1fr); }
  .deck-select-tile { grid-template-columns: 92px minmax(0, 1fr); }
  .deck-select-art { width: 92px; }
  .deck-select-art img { left: calc(12px + var(--i) * 14px); width: 56px; height: 78px; }
  .deck-select-back { width: 56px; height: 78px; }
  .deck-page { --card-w: 112px; --card-h: 157px; }
}

.deck-select-back {
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 4;
  width: 62px;
  height: 87px;
  border-radius: 9px;
  overflow: hidden;
  background: #1b1026;
  box-shadow: 0 5px 12px rgba(15, 10, 25, 0.35), inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

.deck-select-back-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.deck-confirm {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.deck-mode-badge {
  padding: 4px 9px;
  border: 1px solid rgba(88, 191, 155, 0.4);
  border-radius: var(--radius-pill);
  background: rgba(88, 191, 155, 0.12);
  color: var(--ok-ink, #23775e);
  font-size: 10px;
  font-weight: 800;
  white-space: nowrap;
}

.deck-mode-badge.limited {
  border-color: rgba(255, 170, 80, 0.45);
  background: rgba(255, 170, 80, 0.14);
  color: var(--caution-ink, #8a5314);
}

.deck-mode-note {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
}

.deck-mode-picker,
.card-back-grid {
  display: grid;
  gap: 8px;
}

.deck-band-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.deck-mode-picker {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.deck-mode-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--paper);
  text-align: left;
  cursor: pointer;
}

.deck-mode-card.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.deck-mode-card strong {
  font-size: 13px;
}

.deck-mode-card small {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}

.card-back-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.card-back-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 7px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  cursor: pointer;
}

.card-back-option.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.card-back-option small {
  color: var(--muted);
  font-size: 10px;
}

.card-back-preview {
  display: block;
  width: 38px;
  height: 54px;
  overflow: hidden;
  border-radius: 6px;
  background: #1b1026;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.32);
}

.card-back-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.deck-layout {
  display: grid;
  grid-template-columns: minmax(300px, 360px) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

.deck-panel,
.pool-panel {
  padding: 20px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
}

.pool-search {
  display: flex;
  flex: 1 1 auto;
  justify-content: flex-end;
  gap: 8px;
  min-width: 0;
}

.pool-search .input {
  min-width: 0;
  padding: 7px 9px;
  font-size: 11px;
}

.pool-search .input:first-child {
  max-width: 260px;
}

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}

.panel-head h2 {
  font-size: 15px;
}

.panel-note {
  font-size: 11.5px;
  color: var(--muted);
  font-family: var(--mono);
}

.deck-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 520px;
  overflow: auto;
  padding-right: 4px;
}

.deck-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  transition: background 0.15s, border-color 0.15s;
}

.deck-row:hover {
  background: var(--paper-soft);
  border-color: var(--line);
}

.deck-row-glyph {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: color-mix(in srgb, var(--band) 14%, #fff);
  color: var(--band);
  font-size: 15px;
}

/* 出战配置里每张牌前面直接放乐队 logo；通用队没有 logo，退回卡面符号 */
.deck-row-glyph img {
  display: block;
  width: 24px;
  height: 24px;
  object-fit: contain;
}

.deck-row-main {
  display: flex;
  flex-direction: column;
  line-height: 1.35;
  min-width: 0;
}

.deck-row-main strong {
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deck-row-main small {
  font-size: 10.5px;
  color: var(--muted);
}

.deck-row-count {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
}

.curve {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.curve-bars {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  align-items: end;
  height: 120px;
}

.curve-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  height: 100%;
}

.curve-bar {
  width: 100%;
  min-height: 3px;
  border-radius: 6px 6px 2px 2px;
  background: linear-gradient(180deg, #ff9cc4, var(--accent));
  transition: height 0.3s var(--ease);
}

.curve-col b {
  font-size: 11px;
  color: var(--ink-soft);
}

.curve-col small {
  font-size: 10px;
  color: var(--muted);
}

.pool-grid {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.pool-band-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding-left: 10px;
  border-left: 3px solid var(--band);
  font-size: 13px;
  margin-bottom: 10px;
}

.pool-band-title small {
  font-size: 11px;
  color: var(--muted);
}

.pool-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--card-w), 1fr));
  gap: 12px;
}

.pool-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 0;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  transition: transform 0.16s var(--ease);
}

.pool-item:hover {
  transform: translateY(-3px);
}

.pool-item.disabled {
  opacity: 0.42;
}

/* 卡面按钮 = 看描述；下面的小胶囊 = 加入牌组 */
.pool-card {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.pool-add {
  padding: 3px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  font-size: 11px;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.16s, color 0.16s, border-color 0.16s;
}

.pool-add:hover:not(:disabled) {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.pool-add:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* 卡池每张牌底下的「+ / −」一排：加一张和移除一张并排 */
.pool-btn-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.pool-remove {
  width: 26px;
  padding: 3px 0;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  font-size: 13px;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.16s, color 0.16s, border-color 0.16s;
}

.pool-remove:hover:not(:disabled) {
  background: rgba(214, 76, 96, 0.12);
  border-color: var(--danger, #d64c60);
  color: var(--danger, #d64c60);
}

.pool-remove:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.pool-copies {
  font-size: 10px;
  color: var(--muted);
}

.deck-share-text {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  max-height: 320px;
  overflow: auto;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--paper-soft);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
  user-select: text;
}

.deck-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--muted);
}

.deck-footer-actions {
  display: flex;
  gap: 10px;
}

/* Card component ----------------------------------------------------------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 13px;
  border: 1px solid rgba(36, 28, 44, 0.14);
  background: #fffdfb;
  box-shadow: 0 3px 10px rgba(36, 28, 44, 0.08);
  color: var(--ink);
  text-align: left;
  width: var(--card-w);
  height: var(--card-h);
  margin-inline: auto;
  flex: 0 0 auto;
}

.card-art {
  position: relative;
  height: 58px;
  background: var(--band-gradient);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.card-art::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(70% 100% at 50% 120%, rgba(255, 255, 255, 0.35), transparent 60%);
}

.card-glyph {
  position: relative;
  z-index: 1;
  font-size: 26px;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 3px 12px rgba(0, 0, 0, 0.3);
}

.card-cost {
  position: absolute;
  z-index: 2;
  top: 5px;
  left: 5px;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.94);
  color: var(--band-ink);
  font-size: 12px;
  font-weight: 800;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
}

.card-band {
  position: absolute;
  z-index: 2;
  right: 6px;
  bottom: 4px;
  font-size: 8px;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.82);
}

.card-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 7px 8px 6px;
  flex: 1;
}

.card-name {
  font-size: 12px;
  line-height: 1.3;
}

.card-type {
  font-size: 9px;
  letter-spacing: 0.4px;
  color: var(--muted);
}

.card-text {
  font-size: 10px;
  line-height: 1.5;
  color: #5d5369;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-keywords {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-top: auto;
}

.card-keywords span {
  font-size: 8.5px;
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--band-soft);
  color: var(--band-ink);
  font-weight: 700;
}

.card-stats {
  display: flex;
  justify-content: space-between;
  padding: 5px 8px;
  border-top: 1px solid rgba(36, 28, 44, 0.08);
  background: rgba(36, 28, 44, 0.03);
  font-size: 13px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.card-stats .atk {
  color: #b4520f;
}

.card-stats .hp {
  color: var(--teal);
}

.card-stats .hp small {
  font-size: 9px;
  opacity: 0.6;
}

.card-detail-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: -2px 0 8px;
}

.card-detail-tags span {
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--paper-soft);
  color: var(--accent-ink);
  font-size: 10px;
  font-weight: 700;
}

.card-stat-badge {
  position: absolute;
  bottom: 7px;
  z-index: 6;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  pointer-events: none;
}

.card-stat-badge.is-atk {
  left: 7px;
}

.card-stat-badge.is-hp {
  right: 7px;
}

.card-stat-badge img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 2px 4px rgba(12, 6, 24, 0.38));
}

.card-stat-badge b {
  position: relative;
  z-index: 1;
  color: #fff;
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 900;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(20, 10, 34, 0.8);
}

.card:has(.card-face) .card-stats:not(.is-skill) {
  display: none;
}

.card-detail-art .card-stat-badge {
  width: 60px;
  height: 60px;
}

.card-detail-art .card-stat-badge b {
  font-size: 25px;
}

.card-stats.is-skill {
  justify-content: center;
}

.skill-tag {
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--muted);
  text-transform: uppercase;
}

.card-mini .card-art {
  height: 46px;
}

.card-mini .card-glyph {
  font-size: 20px;
}

.card-mini .card-text {
  display: none;
}

.card-mini .card-name {
  font-size: 11px;
}

.card-mini .card-stats {
  padding: 3px 7px;
  font-size: 11px;
}

.card-hand {
  width: 100%;
}

.card-hand .card-art {
  height: 62px;
}

.card-small .card-art {
  height: 70px;
}

.card-detail {
  max-width: var(--card-w);
}

.card-detail .card-art {
  height: 120px;
}

.card-detail .card-glyph {
  font-size: 46px;
}

.card-detail .card-name {
  font-size: 16px;
}

.card-detail .card-text {
  font-size: 12px;
  -webkit-line-clamp: 6;
}

.card-detail .card-stats {
  font-size: 16px;
  padding: 8px 12px;
}

.card-glow {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(242, 80, 154, 0.35);
  pointer-events: none;
}

/* 8. Codex ----------------------------------------------------------------- */
.codex-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--card-w), 1fr));
  gap: 14px;
}

.codex-item {
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: transform 0.16s var(--ease);
}

.codex-item:hover {
  transform: translateY(-4px);
}

.keyword-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 12px;
  margin: 0;
}

.keyword-list div {
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--paper);
}

.section-notes[hidden] {
  display: none;
}

.keyword-list dt {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 13px;
  margin-bottom: 4px;
}

.keyword-list dt code {
  display: none;
}

.keyword-list dd {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

.detail-grid {
  display: grid;
  grid-template-columns: 290px minmax(0, 1fr);
  gap: 22px;
  align-items: start;
}

.detail-copy {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.detail-text {
  font-size: 14px;
  line-height: 1.85;
}

.detail-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 0;
}

.detail-stats div {
  padding: 8px 12px;
  border-radius: var(--radius-xs);
  background: var(--paper-soft);
  border: 1px solid var(--line);
}

.detail-stats dt {
  font-size: 10.5px;
  color: var(--muted);
}

.detail-stats dd {
  margin: 0;
  font-size: 13.5px;
  font-weight: 700;
}

/* 9. Battle ---------------------------------------------------------------- */
.battle-page {
  display: block;
}

.battle-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.9);
  box-shadow: var(--shadow-sm);
}

.round-badge {
  font-size: 10px;
  letter-spacing: 2.4px;
  color: var(--muted);
  font-weight: 700;
}

.round-badge b {
  font-size: 18px;
  color: var(--ink);
  letter-spacing: 0;
  margin-left: 4px;
}

.turn-badge {
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 700;
}

.turn-badge.is-you {
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.turn-badge.is-foe {
  background: rgba(36, 28, 44, 0.06);
  color: var(--ink-soft);
}

.ap-meter {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ap-label {
  font-size: 11px;
  color: var(--muted);
}

.pips {
  display: inline-flex;
  gap: 4px;
}

.pips i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(36, 28, 44, 0.12);
  transition: background 0.2s, transform 0.2s;
}

.pips i.on {
  background: linear-gradient(135deg, #ff8dbb, var(--accent));
  box-shadow: 0 0 0 2px rgba(242, 80, 154, 0.16);
}

.ap-meter b {
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

.battle-hint {
  flex: 1;
  min-width: 140px;
  font-size: 12.5px;
  color: var(--muted);
}

.battle-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: 16px;
  margin-top: 16px;
  align-items: start;
}

.arena {
  position: relative;
  padding: 18px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--night-line);
  /* 默认战斗背景（六本木高级公寓）；换背景由文件末尾那批 body[data-battle-bg=...] .arena 规则覆盖 */
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-roppongi.webp') center 54% / cover no-repeat;
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  overflow: hidden;
}

.side-row {
  display: grid;
  grid-template-columns: 184px minmax(0, 1fr);
  gap: 12px;
  align-items: stretch;
}

.you-side {
  grid-template-columns: minmax(0, 1fr) 184px;
}

.frontline {
  display: flex;
  justify-content: center;
  margin: 12px 0;
  border-top: 1px dashed rgba(255, 255, 255, 0.16);
}

.frontline span {
  transform: translateY(-50%);
  padding: 0 12px;
  background: var(--night);
  font-size: 8.5px;
  letter-spacing: 4px;
  color: rgba(255, 255, 255, 0.32);
}

.lane-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.lane-label {
  font-size: 9.5px;
  letter-spacing: 0.6px;
  color: rgba(255, 255, 255, 0.42);
}

.lane {
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: 9px;
  flex: 1;
  min-height: var(--lane-h, 168px);
}

/* 一条战线 6 格：只画已上场的单位，居中对齐向外铺开 */
.lane > .unit {
  flex: 0 1 var(--unit-w, 150px);
  min-width: 0;
  align-self: center;
}

/* 场地格与随从卡同排同尺寸：一起居中排列 */
.lane > .field-slot {
  flex: 0 1 132px;
  width: auto;
  min-width: 0;
  min-height: 132px;
  align-self: stretch;
}

.lane-empty {
  display: grid;
  place-items: center;
  flex: 1;
  border-radius: var(--radius-sm);
  border: 1px dashed rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.34);
  font-size: 12px;
  letter-spacing: 0.08em;
}

.stage {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 11px 12px;
  border-radius: var(--radius-md);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-top: 3px solid var(--band);
  background:
    radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--band) 26%, transparent), transparent 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.02));
  color: #fff;
  transition: box-shadow 0.2s, transform 0.2s;
}

.stage-head {
  display: flex;
  align-items: center;
  gap: 6px;
}

.stage-glyph {
  color: var(--band);
  font-size: 13px;
}

.stage-name {
  font-size: 11px;
  letter-spacing: 1.2px;
  font-weight: 700;
}

.stage-role {
  margin-left: auto;
  font-size: 9.5px;
  color: rgba(255, 255, 255, 0.5);
}

.stage-hype {
  display: flex;
  align-items: baseline;
  gap: 2px;
}

.stage-hype b {
  font-size: 30px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.stage-hype small {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}

.hype-bar {
  height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.14);
  overflow: hidden;
}

.hype-bar i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--band), #fff6);
  transition: width 0.45s var(--ease);
}

.stage-meta {
  display: flex;
  gap: 10px;
  font-size: 9.5px;
  color: rgba(255, 255, 255, 0.5);
}

.stage.critical .stage-hype b {
  color: #ffadc3;
  animation: beat 1.4s ease-in-out infinite;
}

@keyframes beat {
  50% {
    transform: scale(1.05);
  }
}

.stage.targetable {
  cursor: pointer;
  box-shadow: 0 0 0 2px #5ee0c4, 0 12px 30px rgba(94, 224, 196, 0.22);
}

.target-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 1px 6px;
  border-radius: 5px;
  background: #5ee0c4;
  color: #04231c;
  font-size: 9px;
  font-weight: 800;
}

.unit {
  position: relative;
  display: block;
  flex: 0 1 var(--unit-w, 150px);
  min-width: 0;
  overflow: visible;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  text-align: left;
  border-radius: 12px;
  transition: transform 0.16s var(--ease), filter 0.16s;
}

.unit-art {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1000 / 1050;
  overflow: hidden;
  border-radius: 12px;
  background: var(--band-gradient);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.24);
}

.unit.has-face .unit-art {
  background: transparent;
  box-shadow: none;
}

.unit-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* cover：卡图铺满卡面，关键词光效（.glow 的 inset:0）才会正好贴住立绘边缘；
     原来是 contain，图框比图大 → 光效看起来"没贴着人" */
  object-fit: cover;
  border-radius: inherit;
  pointer-events: none;
}

.unit-glyph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 28px;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.unit.has-face .unit-glyph {
  display: none;
}

.unit-exit-mark {
  position: absolute;
  left: 50%;
  bottom: 4px;
  z-index: 7;
  width: 27px;
  height: 27px;
  transform: translateX(-50%);
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(15, 5, 15, 0.55));
}

.unit-exit-mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.unit-name {
  position: absolute;
  left: 34px;
  right: 34px;
  bottom: 5px;
  z-index: 3;
  overflow: hidden;
  font-size: 10px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #fff;
  text-shadow: 0 1px 3px rgba(10, 6, 18, 0.9);
  pointer-events: none;
}

.unit-flags {
  position: absolute;
  top: calc(var(--unit-w, 150px) * 0.04);
  left: calc(var(--unit-w, 150px) * 0.04);
  right: calc(var(--unit-w, 150px) * 0.04);
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  min-height: 0;
  padding: 0;
  pointer-events: none;
}

.flag {
  font-size: 8.5px;
  padding: 0 3px;
  border-radius: 3px;
  background: rgba(36, 28, 44, 0.72);
  color: #fff;
}

.flag-charge { background: #ffe7cf; color: #96540c; }
.flag-improv { background: #fff3cd; color: #8a6209; }
.flag-spotlight { background: #e3ecff; color: #2c4c95; }
.flag-intimidate { background: #f0e6ff; color: #6437a6; }
.flag-debut { background: #e3f4ec; color: #1b6a52; }
.flag-exit { background: #ffe1ea; color: #a02149; }
.flag-frozen { background: #dcefff; color: #1f5f8c; font-variant-numeric: tabular-nums; }

.unit-atk,
.unit-hp {
  position: absolute;
  z-index: 4;
  display: grid;
  place-items: center;
  /* 徽章跟着单位缩放，但**必须夹在上下限之间**：单位很小时不再挤到卡面中间，很大时也不会糊成一坨 */
  width: clamp(16px, calc(var(--unit-w, 150px) * 0.26), 46px);
  height: clamp(16px, calc(var(--unit-w, 150px) * 0.26), 46px);
  bottom: 2px;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(10, 6, 18, 0.45));
}

.unit-atk {
  left: 2px;
  bottom: 2px;
  top: auto;
  right: auto;
  background: url("/assets/ui/stat-attack.png") center / 200% 200% no-repeat;
}

.unit-hp {
  right: 2px;
  left: auto;
  bottom: 2px;
  top: auto;
  transform: none;
  background: url("/assets/ui/stat-health.png") center / 200% 200% no-repeat;
}

.unit-atk b,
.unit-hp b {
  font-size: clamp(9px, calc(var(--unit-w, 150px) * 0.12), 20px);
  font-weight: 800;
  line-height: 1;
  color: #fffaf5;
  text-shadow: 0 1px 2px #1a1424;
}

.unit-atk b.buffed {
  color: #ffd166;
}

.unit[data-ready="1"] {
  cursor: pointer;
}

.unit[data-ready="1"] .unit-art {
  filter: drop-shadow(0 8px 12px rgba(0, 0, 0, 0.34));
}

.unit[data-ready="1"] .unit-name {
  color: #ffe6a3;
}

.unit[data-ready="1"]:hover {
  transform: translateY(-4px);
}

/* 压力：颜色变淡，仍保留可点击/可查看的目标轮廓 */
.unit[data-frozen="1"] {
  opacity: 0.55;
}

.unit[data-frozen="1"] .unit-art {
  filter: saturate(0.25) brightness(1.12);
}

.unit.selected {
  transform: translateY(-5px);
}

.unit.selected .unit-art {
  outline: 2px solid #ffd166;
  outline-offset: 2px;
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.36);
}

.unit.targetable {
  cursor: pointer;
}

.unit.targetable .unit-art {
  outline: 2px dashed #ff9ab9;
  outline-offset: 2px;
  animation: target-pulse 2.8s ease-in-out infinite;
}

@keyframes target-pulse {
  50% {
    outline-color: #ffd7e3;
  }
}

.unit-enter {
  animation: unit-pop 0.42s var(--ease) both;
}

/* 打出的随从/场地：光球还没落地前先藏着（落地那一刻去掉这个类，再叠 unit-enter 弹出） */
.unit.is-arriving {
  opacity: 0;
  transform: scale(0.72);
  pointer-events: none;
}

/* 结算等待：亮牌 + 光球播完之前战场还是旧画面，这层挡掉误触 */
.settle-blocker {
  position: fixed;
  inset: 0;
  z-index: 65;
  cursor: progress;
  background: transparent;
}

@keyframes unit-pop {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.9);
  }
}

.slot-empty {
  display: grid;
  place-items: center;
  min-height: 116px;
  border-radius: var(--radius-sm);
  border: 1px dashed rgba(255, 255, 255, 0.16);
}

.slot-empty i {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
}

.hand-zone {
  margin-top: 16px;
}

.hand-head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 7px;
  font-size: 10px;
  letter-spacing: 0.8px;
  color: rgba(255, 255, 255, 0.5);
}

.hand-strip {
  display: flex;
  gap: 9px;
  overflow-x: auto;
  padding: 2px 2px 8px;
  scrollbar-width: thin;
}

.hand-slot {
  flex: 0 0 auto;
  width: var(--card-w);
  padding: 0;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: transform 0.16s var(--ease);
}

.hand-slot.playable:hover {
  transform: translateY(-6px);
}

/* 手牌选中描边跟稀有度走，不再跟乐队走 */
.card[data-rarity="E"] { --rarity-edge: #aab3c2; --rarity-glow: rgba(170, 179, 194, 0.55); }
.card[data-rarity="D"] { --rarity-edge: #f7f9ff; --rarity-glow: rgba(225, 235, 255, 0.7); }
.card[data-rarity="R"] { --rarity-edge: #63b9ff; --rarity-glow: rgba(99, 185, 255, 0.62); }
.card[data-rarity="SR"] { --rarity-edge: #f0c45c; --rarity-glow: rgba(240, 196, 92, 0.62); }
.card[data-rarity="SSR"] { --rarity-edge: #ff8fd6; --rarity-glow: rgba(255, 143, 214, 0.65); }
.card[data-rarity="EX"] { --rarity-edge: #d9a7ff; --rarity-glow: rgba(217, 167, 255, 0.65); }

.hand-slot.selected .card {
  outline: 2px solid var(--rarity-edge, var(--accent));
  outline-offset: 1px;
  box-shadow: 0 0 0 1px var(--rarity-edge, var(--accent)), 0 0 18px var(--rarity-glow, rgba(255, 95, 162, 0.4));
}

.hand-slot.unplayable {
  opacity: 0.62;
  cursor: not-allowed;
}

.empty-hint {
  padding: 12px;
  font-size: 12px;
  color: var(--muted);
}

.michelle-hud {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 2px;
  padding: 7px 9px;
  border: 1px solid rgba(255, 143, 214, 0.28);
  border-radius: 9px;
  background: rgba(255, 143, 214, 0.08);
  color: var(--ink-soft);
  font-size: 11px;
}

.michelle-hud-title {
  color: var(--accent-ink);
  font-weight: 800;
}

.michelle-hud b {
  color: var(--accent-ink);
  font-family: var(--mono);
}

.michelle-detail-btn {
  padding: 3px 8px;
  border: 1px solid rgba(255, 143, 214, 0.35);
  border-radius: 999px;
  background: transparent;
  color: var(--accent-ink);
  font-size: 10px;
  font-weight: 800;
  white-space: nowrap;
  flex: 0 0 auto;
  cursor: pointer;
}

.michelle-detail-btn:hover {
  background: rgba(255, 143, 214, 0.16);
}

/* 战报面板顶部：本局记录（计数一行 + 详情按钮一行，按钮多了会自动换行，不再被挤成竖排） */
.log-hud-actions {
  display: flex;
  flex: 1 1 100%;
  flex-wrap: wrap;
  gap: 6px;
  margin-left: 0;
}

.log-hud-actions .michelle-detail-btn {
  margin-left: 0;
}

.michelle-detail-list h3 {
  margin: 10px 0 4px;
  color: var(--accent-ink);
  font-size: 13px;
}

.michelle-detail-list p {
  margin: 2px 0;
  color: var(--ink-soft);
  font-size: 12px;
}

/* 持久效果弹窗：一条 = 「标题 + 说明」两行（来源牌名已写进标题） */
.persistent-list .persistent-row {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 4px 0;
  padding: 6px 8px;
  border-radius: 10px;
  background: rgba(255, 143, 214, 0.1);
}
.persistent-list .persistent-row b {
  color: var(--accent-ink);
  font-size: 12px;
}
.persistent-list .persistent-row span {
  color: var(--ink-soft);
  font-size: 12px;
}
/* 「本回合」的临时加成：底色淡一点，和本局一直生效的区分开 */
.persistent-list .persistent-row.is-temporary {
  background: rgba(120, 150, 255, 0.12);
}
.persistent-list .persistent-row.is-temporary b {
  color: #4f5ed6;
}

/* 单位详情里的「本局获得」：这个单位因为哪张牌拿到了什么 */
.unit-gains {
  margin: 6px 0 2px;
  padding: 6px 8px;
  border-radius: 10px;
  background: rgba(255, 143, 214, 0.1);
}
.unit-gains-title {
  margin: 0 0 2px;
  color: var(--accent-ink);
  font-size: 12px;
  font-weight: 800;
}
.unit-gains ul {
  margin: 0;
  padding-left: 14px;
  color: var(--ink-soft);
  font-size: 12px;
}
.unit-gains li {
  margin: 1px 0;
}

.inspector {
  position: sticky;
  top: 86px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.92);
  box-shadow: var(--shadow-sm);
  max-height: calc(100vh - 120px);
  overflow: auto;
}

.inspector-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
}

.inspector-hint {
  font-size: 12px;
  color: var(--accent-ink);
  text-align: center;
}

.log-panel h3 {
  font-size: 13px;
  margin-bottom: 8px;
}

.log-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 320px;
  overflow-y: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}

.log-list .log-turn {
  position: sticky;
  top: 0;
  z-index: 1;
  margin-top: 4px;
  padding: 5px 4px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  color: var(--accent-ink);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.08em;
}

.log-list li {
  padding: 6px 0;
  border-bottom: 1px dashed var(--line);
  font-size: 11.5px;
  color: var(--ink-soft);
}

.log-list li:last-child {
  border-bottom: 0;
}

.log-danger {
  color: #a41f47;
}

.log-success {
  color: #146c53;
}

.inspector-foot {
  display: flex;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 10.5px;
  color: var(--muted);
}

/* Battle prep --------------------------------------------------------------- */
.prep-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 20px;
  align-items: start;
}

.prep-main,
.prep-side {
  padding: 22px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
}

.prep-title {
  font-size: 14px;
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.prep-side .prep-title {
  margin-top: 0;
}

.prep-main .prep-title:not(:first-child) {
  margin-top: 26px;
}

.foe-picker {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  /* 每一行等高：介绍文字长短不一也不会让选项卡片高低错落 */
  grid-auto-rows: 1fr;
  gap: 10px;
}

.foe-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  /* 统一高度（配合 grid-auto-rows: 1fr，短文案也不会比长文案矮一截） */
  min-height: 104px;
  text-align: center;
  padding: 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  border-top: 3px solid var(--band);
  background: var(--paper);
  cursor: pointer;
  transition: transform 0.16s var(--ease), box-shadow 0.16s;
}

.foe-option:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-sm);
}

.foe-option.active {
  background: var(--band-soft);
  border-color: var(--band);
}

.foe-glyph {
  width: 30px;
  height: 30px;
  object-fit: contain;
  color: var(--band);
}

.foe-option strong {
  font-size: 13px;
  letter-spacing: 1px;
}

.foe-option small {
  font-size: 10.5px;
  color: var(--muted);
}

.ai-deck-preview {
  margin-top: 14px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper-soft);
}

.ai-deck-preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 9px;
}

.ai-deck-preview-head b {
  color: var(--accent-ink);
  font-size: 12px;
  letter-spacing: 0.04em;
}

.foe-difficulty {
  color: var(--band, var(--accent)) !important;
  font-weight: 800;
  letter-spacing: 0.08em;
}

.ai-deck-modal {
  width: min(900px, calc(100vw - 28px));
}

.ai-deck-meta {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.6;
}

.ai-deck-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(56px, 1fr));
  gap: 6px;
  padding: 2px;
  overflow: visible;
}

.ai-deck-grid .card {
  width: 100%;
  min-width: 0;
}

.prep-deck {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.prep-deck .card {
  width: var(--card-w);
}

.online-deck-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 6px;
  margin: 8px 0 4px;
}

.prep-deck-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 7px;
  margin-bottom: 10px;
}

.prep-deck-choice {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  text-align: left;
  cursor: pointer;
}

.prep-deck-choice.active {
  border-color: var(--band, var(--accent));
  background: color-mix(in srgb, var(--band-soft, var(--accent-soft)) 55%, #fff);
  box-shadow: inset 0 0 0 1px var(--band, var(--accent));
}

.prep-deck-choice strong {
  overflow: hidden;
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.prep-deck-choice small {
  color: var(--muted);
  font-size: 10px;
}

.prep-more {
  font-size: 12px;
  color: var(--muted);
  padding: 4px 8px;
}

.prep-count {
  font-family: var(--mono);
  font-size: 11px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: #ffe9ef;
  color: #a41f47;
}

.prep-count.ok {
  background: #e2f6ee;
  color: #146c53;
}

.prep-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 24px;
}

.rule-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rule-list li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: 10px;
  border-bottom: 1px dashed var(--line);
}

.rule-list li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.rule-list b {
  font-size: 12.5px;
}

.rule-list span {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.7;
}

/* Settings ------------------------------------------------------------------ */
/* 三列各是一条竖向流（.settings-col）：存档贴在账号卡下面、关于贴在表现卡下面，
   不再被「对局历史」那一列的高度顶出大空隙（以前是 auto-fit 网格，行高按最高的那张算）。 */
.settings-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
  align-items: start;
}

.settings-col {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

@media (max-width: 1180px) {
  .settings-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 780px) {
  .settings-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.settings-card {
  padding: 22px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
}

.settings-card-wide {
  grid-column: 1 / -1;
}

.settings-card h2 {
  font-size: 15px;
  margin-bottom: 14px;
}

.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px dashed var(--line);
}

.setting-row:last-child {
  border-bottom: 0;
}

.setting-row b {
  font-size: 13px;
}

/* 左侧文字列必须自己占宽度：否则右侧滑杆一撑，文字会被压成一字一行（音效音量那行踩过） */
.setting-row > span:first-child {
  flex: 1 1 180px;
  min-width: 140px;
}

.setting-row small {
  display: block;
  font-size: 11px;
  color: var(--muted);
}

.setting-volume {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex: 0 1 auto;
  min-width: 0;
}

.setting-volume input[type="range"] {
  width: clamp(90px, 16vw, 190px);
  accent-color: var(--accent);
  cursor: pointer;
}

.setting-volume output {
  min-width: 3.6em;
  text-align: right;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent-ink);
}

.save-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 0 0 16px;
}

.save-facts div {
  padding: 10px 12px;
  border-radius: var(--radius-xs);
  background: var(--paper-soft);
  border: 1px solid var(--line);
}

.save-facts dt {
  font-size: 10.5px;
  color: var(--muted);
}

.save-facts dd {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
}

.settings-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.arch-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 14px 0;
  padding: 0;
  list-style: none;
}

.arch-list li {
  display: flex;
  gap: 12px;
  align-items: baseline;
  font-size: 12.5px;
}

.arch-list code {
  flex: 0 0 168px;
  font-size: 11px;
}

.arch-list span {
  color: var(--muted);
}

/* 10. Overlay / FX ---------------------------------------------------------- */
#toast {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: min(380px, calc(100vw - 36px));
  padding: 11px 15px;
  border-radius: var(--radius-sm);
  background: rgba(25, 20, 38, 0.94);
  color: #fff;
  font-size: 12.5px;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
  pointer-events: auto;
  cursor: pointer;
}

.toast.in {
  opacity: 1;
  transform: translateY(0);
}

.toast.out {
  opacity: 0;
  transform: translateY(6px);
}

.toast-icon {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 10px;
  background: rgba(255, 255, 255, 0.16);
}

.toast-success .toast-icon {
  background: #2fbe93;
}

.toast-danger .toast-icon {
  background: #ff5d84;
}

#modal.modal-host {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--ink);
  width: min(720px, calc(100vw - 28px));
  max-height: calc(100vh - 32px);
  /* <dialog> 自己就是定位元素：margin:auto 即视口居中，别覆盖 position/inset（会挡住点击） */
  margin: auto;
  overflow: visible;
}
/* 小屏笔记本：弹窗整体限高，正文单独滚动，底部按钮始终可见 */
#modal.modal-host .modal-card {
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 32px);
}
#modal.modal-host .modal-head {
  flex: 0 0 auto;
}
#modal.modal-host .modal-body {
  flex: 1 1 auto;
  overflow-x: hidden;
  overflow-y: auto;
  min-height: 0;
}
#modal.modal-host .modal-actions {
  flex: 0 0 auto;
  padding-top: 4px;
  background: var(--paper);
}
@media (max-height: 760px) {
  #modal.modal-host {
    max-height: calc(100vh - 16px);
  }
  #modal.modal-host .modal-card {
    max-height: calc(100vh - 16px);
    padding: 16px 18px;
  }
  .modal-body {
    margin: 10px 0 12px;
    line-height: 1.6;
  }
}

#modal.modal-host::backdrop {
  background: rgba(18, 12, 28, 0.56);
  backdrop-filter: blur(6px);
}

.modal-card {
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: var(--shadow-lg);
  padding: 24px 26px;
  animation: modal-in 0.26s var(--ease) both;
}

@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.98);
  }
}

.modal-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 12px;
}

.modal-title {
  font-size: 21px;
  margin-top: 4px;
}

.modal-close {
  margin-left: auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--paper-soft);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.modal-body {
  margin: 16px 0 20px;
  font-size: 14px;
  line-height: 1.85;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.modal-card-detail {
  width: min(820px, calc(100vw - 28px));
}

.modal-card-detail#modal {
  width: min(820px, calc(100vw - 28px));
}

.result-modal {
  width: min(520px, calc(100vw - 28px));
}

#modal.result-modal {
  width: min(520px, calc(100vw - 28px));
}

/* 天梯结算：±分数 + 当前段位（结算面板顶部那块） */
.ladder-delta {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 2px 0 12px;
  flex-wrap: wrap;
}

.ladder-delta-value {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--muted);
}

.ladder-delta-value.is-up { color: var(--accent-ink); }
.ladder-delta-value.is-down { color: #b4536f; }
.ladder-delta small { font-size: 12px; color: var(--muted); }

.result-line {
  font-size: 14px;
  color: var(--ink-soft);
}

.result-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin: 16px 0;
}

.result-stats div {
  padding: 10px 12px;
  border-radius: var(--radius-xs);
  background: var(--paper-soft);
  border: 1px solid var(--line);
}

.result-stats dt {
  font-size: 10.5px;
  color: var(--muted);
}

.result-stats dd {
  margin: 0;
  font-size: 16px;
  font-weight: 800;
}

/* FX layer */
#fx-layer {
  position: fixed;
  inset: 0;
  z-index: 800;
  pointer-events: none;
  overflow: hidden;
}

.fx-number {
  position: absolute;
  transform: translate(-50%, -50%);
  font-size: 32px;
  font-weight: 900;
  color: #ff6d93;
  text-shadow: 0 2px 0 #2b1024, 0 4px 14px rgba(0, 0, 0, 0.4);
  animation: fx-rise 0.95s var(--ease) forwards;
  white-space: nowrap;
}

.fx-number.fx-large {
  font-size: 46px;
}

.fx-heal {
  color: #5fe3b5;
}

.fx-buff {
  color: #ffd479;
}

.fx-freeze {
  color: #9ad9ff;
  font-size: 16px;
}

@keyframes fx-rise {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.7);
  }
  30% {
    opacity: 1;
    transform: translate(calc(-50% + var(--drift) * 0.3), -70%) scale(1.1);
  }
  to {
    opacity: 0;
    transform: translate(calc(-50% + var(--drift)), -150%) scale(1);
  }
}

.fx-beam {
  position: absolute;
  height: 3px;
  border-radius: 3px;
  transform-origin: 0 50%;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.1), #ffd9a0 30%, #ff6d93);
  animation: fx-beam 0.42s ease-out forwards;
}

@keyframes fx-beam {
  from {
    opacity: 0;
    transform: scaleX(0.05) rotate(var(--rot, 0deg));
  }
  40% {
    opacity: 1;
  }
  to {
    opacity: 0;
    transform: scaleX(1) rotate(var(--rot, 0deg));
  }
}

.fx-ring {
  position: absolute;
  width: 26px;
  height: 26px;
  border: 3px solid rgba(255, 109, 147, 0.85);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  animation: fx-ring 0.5s ease-out forwards;
}

@keyframes fx-ring {
  from {
    opacity: 0.95;
    width: 12px;
    height: 12px;
  }
  to {
    opacity: 0;
    width: 110px;
    height: 110px;
    border-width: 1px;
  }
}

.fx-spark {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #ffd166;
  animation: fx-spark 0.6s ease-out forwards;
}

@keyframes fx-spark {
  to {
    opacity: 0;
    transform: rotate(var(--angle)) translateX(var(--distance)) scale(0.4);
  }
}

.fx-flash-screen {
  position: fixed;
  inset: 0;
  background: #fff;
  opacity: 0.55;
  animation: fx-flash 0.45s ease-out forwards;
}

@keyframes fx-flash {
  to {
    opacity: 0;
  }
}

.fx-flash-blue {
  background: #b9d6ff;
}

.fx-shake {
  animation: fx-shake 0.36s;
}

@keyframes fx-shake {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(-4px, 2px); }
  40% { transform: translate(4px, -2px); }
  60% { transform: translate(-3px, -2px); }
  80% { transform: translate(3px, 2px); }
}

/* 11. Responsive ------------------------------------------------------------ */
@media (max-width: 1080px) {
  .hero {
    grid-template-columns: 1fr;
  }

  .hero-stage {
    order: -1;
    height: 230px;
  }

  .deck-layout,
  .prep-grid {
    grid-template-columns: 1fr;
  }

  .battle-body {
    grid-template-columns: 1fr;
  }

  .inspector {
    position: static;
    max-height: none;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 16px;
  }

  .inspector-detail {
    flex: 1 1 280px;
    align-items: flex-start;
  }

  .log-panel {
    flex: 1 1 260px;
  }

  .band-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 820px) {
  .topbar {
    flex-wrap: wrap;
    height: auto;
    padding: 10px 14px;
    gap: 8px;
  }

  .nav {
    order: 3;
    width: 100%;
    overflow-x: auto;
    margin: 0;
  }

  .nav-link {
    padding: 3px 10px;
    font-size: 12.5px;
  }

  .view-host {
    padding-top: 16px;
  }

  .side-row {
    grid-template-columns: 1fr;
  }

  .you-side {
    grid-template-columns: 1fr;
  }

  .you-side .lane-wrap {
    order: -1;
  }

  .arena {
    padding: 12px;
  }

  .battle-bar .battle-hint {
    flex-basis: 100%;
    order: 5;
  }

  .end-turn {
    margin-left: auto;
    min-width: 132px;
  }

  .lane {
    gap: 6px;
  }

  .unit {
    min-height: 104px;
  }

  .lane-empty {
    min-height: 104px;
  }

  .unit-art {
    height: 46px;
  }

  .hand-slot {
    width: 118px;
  }

  .detail-grid {
    grid-template-columns: 1fr;
  }

  .card-detail {
    max-width: 100%;
  }

  .hero-marks {
    gap: 18px;
  }

  .arch-list code {
    flex-basis: 130px;
  }
}

@media (max-width: 560px) {
  body {
    font-size: 14px;
  }

  .hero {
    border-radius: 22px;
    padding: 20px;
  }

  .hero-title {
    letter-spacing: -1px;
  }

  .hero-actions .btn {
    flex: 1;
  }

  .section {
    margin-top: 34px;
  }

  .band-grid,
  .codex-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .pool-cards {
    grid-template-columns: repeat(3, 1fr);
  }

  .battle-bar {
    padding: 10px 12px;
    gap: 8px;
  }

  .battle-bar .round-badge,
  .battle-bar .ap-meter {
    font-size: 11px;
  }

  .end-turn {
    width: 100%;
    margin-left: 0;
  }

  .hand-slot {
    width: 104px;
  }

  .unit {
    min-height: 96px;
  }

  .unit-name {
    font-size: 9.5px;
  }

  .unit-stats {
    font-size: 12px;
  }

  .modal-card {
    padding: 18px;
  }

  .save-facts,
  .result-stats,
  .detail-stats {
    grid-template-columns: 1fr;
  }

  .deck-actions {
    width: 100%;
  }

  .deck-actions .btn {
    flex: 1;
  }
}

/* 12. Motion preferences ----------------------------------------------------- */
body[data-motion="reduced"] *,
body[data-motion="reduced"] *::before,
body[data-motion="reduced"] *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
}

@media (prefers-reduced-motion: reduce) {
  body[data-motion="auto"] *,
  body[data-motion="auto"] *::before {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 13. Online ---------------------------------------------------------------- */
.small {
  font-size: 11.5px;
}

.net-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 12px;
  border-radius: var(--radius-pill);
  /* 胶囊白素材（9 宫格见 styles.css 开头的 .chip/.net-status/.room-chip 共用规则） */
  font-size: 11.5px;
  color: var(--muted);
}

.net-status i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #b9aec6;
}

.net-open i {
  background: #2fbe93;
  box-shadow: 0 0 0 3px rgba(47, 190, 147, 0.18);
}

.net-connecting i {
  background: #e2a83c;
  animation: beat 1.2s ease-in-out infinite;
}

.net-closed i,
.net-error i {
  background: #e4577c;
}

.online-grid {
  display: grid;
  /* 固定两列：开房 | 加入房间 / 房间大厅 | 小游戏分数榜 —— 让「房间大厅」确实落在「加入房间」下面 */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  align-items: start;
}

.online-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 22px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
}

.online-panel h2 {
  font-size: 15px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 12px;
  font-weight: 650;
  color: var(--ink-soft);
}

.code-input {
  font-family: var(--mono);
  font-size: 20px;
  letter-spacing: 8px;
  text-transform: uppercase;
  max-width: 220px;
  padding: 10px 14px;
}

.band-picker {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.band-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--paper-soft);
  font-size: 12px;
  font-weight: 650;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.band-option span {
  color: var(--band);
  font-size: 15px;
  line-height: 1;
}

.band-choice-logo {
  width: 24px;
  height: 24px;
  object-fit: contain;
}

.band-option:hover {
  border-color: var(--band);
}

.band-option.active {
  background: var(--band-soft);
  border-color: var(--band);
  color: var(--band-ink);
}

.deck-line {
  margin: 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: #fff3f6;
  border: 1px solid #f6d4de;
  color: #a4304f;
  font-size: 12px;
}

.deck-line.ok {
  background: #eef9f4;
  border-color: #c7e8da;
  color: #1a6b53;
}

/* .online-help（「你和朋友连着同一个房间服务器…」那行说明）已在 2026-11-02 连同说明一起移除 */

.room-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.room-code {
  font-family: var(--mono);
  font-size: clamp(34px, 6vw, 52px);
  letter-spacing: 14px;
  line-height: 1.1;
  color: var(--accent-ink);
}

.seat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  max-width: 720px;
}

.seat-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px 20px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  border-top: 3px solid var(--band);
  background: var(--paper);
  box-shadow: var(--shadow-sm);
}

.seat-card.mine {
  background: linear-gradient(160deg, var(--band-soft), #fff 60%);
}

.seat-card.empty {
  border-style: dashed;
  border-top-style: solid;
  background: var(--paper-soft);
  color: var(--muted);
}

.seat-card header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.seat-label {
  font-size: 10.5px;
  letter-spacing: 2px;
  color: var(--muted);
}

.seat-state {
  font-size: 11px;
  font-weight: 700;
  color: var(--band);
}

.seat-card strong {
  font-size: 18px;
  letter-spacing: 0.4px;
}

.seat-card small {
  font-size: 11.5px;
  color: var(--muted);
}

.seat-dot {
  margin-top: 10px;
  font-size: 10.5px;
  color: var(--muted);
}

.seat-dot::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 6px;
  border-radius: 50%;
  background: #b9aec6;
}

.seat-dot.on::before {
  background: #2fbe93;
}

.seat-dot.off::before {
  background: #e4577c;
}

.room-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.room-chip {
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  /* 胶囊白素材（9 宫格共用规则在文件开头） */
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}

@media (max-width: 700px) {
  .seat-grid {
    grid-template-columns: 1fr;
  }

  .room-code {
    letter-spacing: 8px;
  }

  .band-picker {
    grid-template-columns: 1fr 1fr;
  }

  .room-actions {
    width: 100%;
  }

  .room-actions .btn {
    flex: 1;
  }
}

/* 14. Online invite box ------------------------------------------------------ */
.invite-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  max-width: 720px;
  margin-top: 18px;
  padding: 16px 20px;
  border-radius: var(--radius-md);
  border: 1px dashed var(--line-strong);
  background: var(--paper-soft);
}

.invite-label {
  display: block;
  font-size: 10.5px;
  letter-spacing: 1.6px;
  color: var(--muted);
  margin-bottom: 8px;
}

.invite-line {
  margin: 0 0 4px;
  font-size: 13px;
  color: var(--ink-soft);
}

.invite-line code {
  font-size: 13px;
  background: #fff;
}

.invite-code {
  font-weight: 800;
  letter-spacing: 4px;
  color: var(--accent-ink);
  background: var(--accent-soft);
  border-color: #f6c8dc;
}

/* 卡牌详情弹窗（ui/card-detail.js）--------------------------------------- */
.card-detail-body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

.card-detail-art {
  position: relative;
}

.card-detail-art .card {
  box-shadow: var(--shadow-md);
}

/* ── 稀有度角标（图鉴 / 牌组编辑 / 对战准备看卡组）──
   素材：D:\BARDS\稀有度素材图标\{E,D,R,SR,SSR,EX}.png —— 原图是 2894×4093 的大画布，
   字形只占右下角一小块（缩到 20px 根本看不见），所以先用 tools/trim-rarity-icons.mjs 裁掉留白，
   输出到 assets/ui/rarity 目录（E/D/R 竖排、SR/SSR/EX 横排，宽高比 0.6~1.6 不等）。
   角标按「高度」定尺寸、宽度自适应；描边用 drop-shadow 加深，避免卡图偏亮时看不清。 */
.card-rarity-icon {
  position: absolute;
  right: 5px;
  bottom: 5px;
  z-index: 6;
  height: 26px;
  width: auto;
  max-width: 46%;
  object-fit: contain;
  pointer-events: none;
  filter: drop-shadow(0 0 2px rgba(28, 16, 40, 0.9)) drop-shadow(0 1px 3px rgba(28, 16, 40, 0.65));
}

.card-unit .card-rarity-icon {
  bottom: 22%;
}

.card-mini .card-rarity-icon {
  height: 22px;
  right: 3px;
}

.card-small .card-rarity-icon {
  height: 25px;
}

.card-detail .card-rarity-icon {
  height: 40px;
  right: 8px;
}

/* 详情页卡图右上角的「放大」按钮（右上角空着，也不会跟右下角的稀有度角标 / 生命徽章抢位置）。
   z-index 要高于卡面里的费用/攻防徽章（那里是 4/5）。 */
/* 卡图右上角的「放大」按钮：只留图标（⤢），文字已去掉，所以做成小圆钮 */
.card-detail-zoom {
  position: absolute;
  right: 10px;
  top: 10px;
  z-index: 20;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(20, 16, 28, 0.72);
  color: #f5eefc;
  cursor: pointer;
  backdrop-filter: blur(2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  transition: background 0.16s, border-color 0.16s, transform 0.12s;
}

.card-detail-zoom:hover {
  background: rgba(20, 16, 28, 0.82);
  border-color: rgba(255, 255, 255, 0.6);
  transform: scale(1.06);
}

.card-detail-zoom span {
  font-size: 15px;
  line-height: 1;
}

/* 放大的卡图浮层 */
.card-zoom-layer {
  position: fixed;
  inset: 0;
  /* 放大卡图要压在所有东西之上（特效层 800 / toast 900）；挂在 <dialog> 里时也要压住详情内容 */
  z-index: 2000;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(12, 9, 18, 0.86);
  backdrop-filter: blur(3px);
  cursor: zoom-out;
  animation: card-zoom-in 0.14s ease-out;
}

.card-zoom-figure {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 8px;
  max-width: 94vw;
  max-height: 94vh;
}

.card-zoom-img {
  display: block;
  width: auto;
  height: auto;
  max-width: min(94vw, 620px);
  max-height: 88vh;
  border-radius: 14px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
  image-rendering: auto;
}

.card-zoom-caption {
  font-size: 12px;
  color: rgba(240, 232, 250, 0.72);
  text-align: center;
}

@keyframes card-zoom-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.card-detail-meta {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
}

.card-detail-text {
  margin: 0 0 12px;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--ink-soft);
}

/* 卡牌描述里的特效标签：选择 / 过载_8 / 招募_1 / 安可_2 / 破坏 / 消失 / 压力 */
.effect-key {
  font-weight: 800;
}

/* 卡牌特效统一深蓝；登场 / 退场 / 压力只加粗，套用默认颜色 */
.effect-blue {
  color: #173a8f;
}

/* 词条说明：小半号、换颜色，跟在卡牌描述下面 */
.card-keyword-notes {
  display: grid;
  gap: 3px;
  margin: -4px 0 12px;
  padding: 7px 9px;
  border-left: 2px solid var(--accent);
  background: var(--paper-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.card-keyword-notes p {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--muted);
}

.card-keyword-notes b {
  margin-right: 5px;
  font-weight: 800;
  color: var(--accent-ink);
}

.card-keyword-notes b.note-effect {
  color: #173a8f;
}

.card-keyword-notes span {
  color: var(--muted);
}

.card-tags-editor {
  display: grid;
  gap: 5px;
  margin: 0 0 12px;
  padding: 8px 9px;
  border-left: 2px solid var(--accent);
  border-radius: 0 8px 8px 0;
  background: var(--paper-soft);
}

.card-tags-input-row {
  display: flex;
  gap: 7px;
}

.card-tags-input-row .input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 8px;
  font-size: 11px;
}

.card-tags-input-row .btn {
  flex: 0 0 auto;
  padding: 5px 8px;
  font-size: 10px;
}

.card-tags-editor small {
  color: var(--muted);
  font-size: 10px;
}

.card-detail-keys {
  margin: 0;
  display: grid;
  gap: 6px;
}

.card-detail-keys > div {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 8px;
  font-size: 12px;
  padding-bottom: 6px;
  border-bottom: 1px dashed var(--line);
}

.card-detail-keys dt {
  font-weight: 700;
  color: var(--accent-ink);
}

/* 图鉴详情：有专属语音的卡给一排播放按钮（清单异步到，空的就整行不占位） */
.card-voice-bar {
  display: none;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}
.card-voice-bar:not(:empty) { display: flex; }
.card-voice-buttons { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.card-voice-bar .field-label { font-size: 12px; color: var(--ink-soft); }

.derivative-showcase {
  margin-top: 14px;
  padding: 10px 11px 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: linear-gradient(150deg, rgba(255, 246, 250, 0.95), rgba(246, 236, 255, 0.9));
}

.derivative-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.derivative-head b {
  color: var(--accent-ink);
  font-size: 13px;
  letter-spacing: 0.08em;
}

.derivative-head span {
  color: var(--muted);
  font-size: 10.5px;
}

.derivative-stage {
  position: relative;
  min-height: 132px;
}

.derivative-slide {
  display: none;
  grid-template-columns: 76px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  animation: derivative-in 0.32s ease both;
}

.derivative-slide.is-active {
  display: grid;
}

.derivative-slide img {
  width: 76px;
  aspect-ratio: 5 / 7;
  object-fit: cover;
  border-radius: 6px;
  box-shadow: 0 3px 9px rgba(20, 12, 35, 0.2);
}

.derivative-copy {
  min-width: 0;
}

.derivative-copy strong {
  display: block;
  overflow: hidden;
  color: var(--ink);
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.derivative-copy small {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 10.5px;
}

.derivative-copy p {
  margin: 6px 0 0;
  color: var(--ink-soft);
  font-size: 11.5px;
  line-height: 1.5;
}

.derivative-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 7px;
}

.derivative-arrow {
  width: 26px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}

.derivative-arrow:hover {
  border-color: var(--accent);
  color: var(--accent-ink);
  background: var(--accent-soft);
}

.derivative-dots {
  display: flex;
  justify-content: center;
  gap: 5px;
}

.derivative-dots button {
  width: 5px;
  height: 5px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(36, 28, 44, 0.22);
  cursor: pointer;
  transition: width 0.2s, background 0.2s;
}

.derivative-dots button.is-active {
  width: 16px;
  border-radius: 99px;
  background: var(--accent);
}

@keyframes derivative-in {
  from { opacity: 0; transform: translateX(7px); }
  to { opacity: 1; transform: translateX(0); }
}

@media (max-width: 640px) {
  .derivative-slide { grid-template-columns: 62px minmax(0, 1fr); }
  .derivative-slide img { width: 62px; }
  .derivative-stage { min-height: 148px; }
}

.card-detail-keys dd {
  margin: 0;
  color: var(--muted);
}

@media (max-width: 720px) {
  .card-detail-body {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: left;
  }
}

/* 换牌层 */
.mulligan-layer {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 16px;
  overflow-y: auto;
  background: rgba(20, 14, 28, 0.72);
  backdrop-filter: blur(3px);
}

.mulligan-panel {
  display: grid;
  justify-items: center;
  /* 内容按自然高度排列：不要让 grid 把某一行拉高，把底部那张详情框挤到看不见 */
  align-content: start;
  gap: 10px;
  padding: 22px 26px;
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: var(--shadow-lg);
  max-width: min(1120px, calc(100vw - 32px));
  /* 2026-11-07：换牌框**定高**（不再随详情文字长短伸缩，作者反馈“有时候扩张很大”）。
     细节：顶部三行（标题/说明/卡）/ 中间详情 / 底部按钮 都用固定轨，详情区自己滚。 */
  width: min(1120px, calc(100vw - 32px));
  height: min(660px, calc(100dvh - 32px));
  max-height: calc(100dvh - 32px);
  grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
  overflow: hidden;
}

.mulligan-title {
  margin: 0;
  font-size: 24px;
  letter-spacing: 0.2em;
  color: var(--accent-ink);
}

.mulligan-note,
.mulligan-wait {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

.mulligan-cards {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

.mulligan-card {
  --unit-w: 74px;
  /* 换牌卡与手牌同尺寸 */
  width: var(--card-w);
  position: relative;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: transform 0.16s var(--ease), filter 0.16s;
}

.mulligan-card:hover {
  transform: translateY(-6px);
}

.mulligan-card.picked {
  filter: saturate(0.4);
  transform: translateY(-4px);
}

.mulligan-card.picked .card {
  outline: 3px solid var(--rarity-edge, var(--accent));
  outline-offset: -1px;
  box-shadow: 0 0 18px var(--rarity-glow, rgba(255, 95, 162, 0.4));
}

.mulligan-mark {
  position: absolute;
  inset: auto 0 34px;
  text-align: center;
  font-size: 13px;
  font-weight: 800;
  color: var(--accent-ink);
  pointer-events: none;
}

/* 换牌界面的卡牌详情：作者要求**不要叶片框**，直接透明铺在面板上（叶片 9 宫格会吃掉底部几像素） */
/* 天梯段位：挪到血量右边，形状仍是胶囊（外观全部来自 .rank-badge，这里只管位置） */
.stage-rank {
  margin-left: 8px;
  vertical-align: middle;
  /* 对战页的段位是「主体 + 居中星位」的成品图，比文字胶囊高一点：别把热度那行撑歪 */
  height: 34px;
  display: inline-flex;
  align-items: center;
}

.stage-rank .rank-badge { --rank-badge-w: 34px; }

/* ── 在线页：三个入口（房间对战 / 天梯对战 / 排行榜） ── */
.online-hub {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  grid-auto-rows: 1fr;
  gap: 14px;
}

.online-hub-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 132px;
  padding: 18px 20px;
  /* 用 UI素材 的按钮图（白 / 粉 9 宫格），和全站其它按钮同一套皮肤 */
  border: 0 solid transparent;
  border-width: 0;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 6px;
  border-image-repeat: stretch;
  background: none;
  cursor: pointer;
  text-align: center;
  transition: transform 0.16s var(--ease), filter 0.16s;
}

.online-hub-card:hover {
  transform: translateY(-3px);
  filter: brightness(1.03);
}

.online-hub-card strong { font-size: 17px; letter-spacing: 0.08em; }
.online-hub-card small { font-size: 11.5px; color: var(--muted); line-height: 1.5; }

/* 天梯入口用粉按钮（房间对战 / 排行榜是白按钮）—— 素材取 assets/ui/btn-pink-xxs.png */
.online-hub-card.is-pink {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  background: none;
  color: #fff;
}

.online-hub-card.is-pink strong {
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

.online-back {
  margin-bottom: 10px;
}

/* 天梯排队：按钮右边那一串「正在匹配… / 预计 N 秒 / 计时」 */
.ladder-actions {
  align-items: center;
  flex-wrap: wrap;
}

.ladder-queue-state {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
}

.ladder-queue-state small {
  font-size: 11.5px;
  color: var(--muted);
  opacity: 0.85;
}

.ladder-queue-state b {
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--accent-ink);
}

/* 大厅「日志公告栏」（替代原来的乐队特色板块） */
.devlog-list {
  display: grid;
  gap: 10px;
}

.devlog-item {
  /* 叶片 UI（assets/ui/leaf-panel.png 九宫格）：细长条用小一点的边框宽度 */
  border: 20px solid transparent;
  border-image: url('../assets/ui/leaf-panel.png') 160 fill / 20px stretch;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* 标题就是一个按钮：点一下展开 / 收起正文 */
.devlog-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  width: 100%;
  padding: 0 2px;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
}

.devlog-head:hover { background: var(--paper-soft); }

.devlog-head strong { flex: 1 1 auto; font-size: 14px; letter-spacing: 0.02em; }
.devlog-head small { font-size: 11.5px; color: var(--muted); white-space: nowrap; }

.devlog-caret {
  font-size: 12px;
  color: var(--muted);
  transition: transform 0.16s var(--ease);
}

.devlog-item.is-open .devlog-caret { transform: rotate(180deg); }

/* 展开时给整条一点柔光，替代原来的粉色边框（叶片皮肤下改不了 border-color） */
.devlog-item.is-open { filter: drop-shadow(0 4px 14px rgba(242, 80, 154, 0.18)); }

/* 置顶公告：标题前一个 📌 图钉 */
.devlog-pin { margin-right: 4px; }

.devlog-body {
  padding: 6px 2px 0;
}

.devlog-item p {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--ink-soft);
}

.devlog-empty {
  margin: 0;
  font-size: 12.5px;
  color: var(--muted);
}

/* 设置页：账号 ID 那一行 */
.account-id-line { margin-top: 6px; }
.account-id-line b { letter-spacing: 0.12em; color: var(--accent-ink); }

/* 天梯面板 */
.ladder-myrank {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 10px;
  flex-wrap: wrap;
}

/* 2026-11-06：徽章图标 + 「职业 3 级 · 当前 6400 分」一行显示 */
.ladder-myrank .rank-badge { --rank-badge-w: 40px; align-self: center; }
.ladder-myrank b { font-size: 18px; letter-spacing: 0.04em; }
.ladder-myrank small { font-size: 11.5px; color: var(--muted); }

/* 设置页存档卡里的「天梯段位」：44px 图标 + 单行文字，不要折行 */
.setting-rank-line,
.save-facts dd[data-field="ladder-rank"] {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  white-space: nowrap;
}

.rank-inline-name { font-weight: 700; white-space: nowrap; }

/* 排行榜：左边三个竖排选项，右边列表 */
.ranking-grid {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

.ranking-tabs {
  display: grid;
  gap: 8px;
}

/* 排行榜左侧三个选项：和入口按钮同一套 UI素材（白底 / 选中粉底） */
.ranking-tab {
  padding: 14px 16px;
  border: 0 solid transparent;
  border-width: 6px;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 6px;
  border-image-repeat: stretch;
  background: none;
  text-align: left;
  cursor: pointer;
  font-size: 14px;
  font-weight: 650;
  color: var(--ink);
}

.ranking-tab:hover {
  filter: brightness(1.03);
}

.ranking-tab.active {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

.ranking-list {
  display: grid;
  gap: 6px;
}

.ranking-row {
  display: grid;
  /* 2026-11-06：段位图标挪到名字前面（原来单独占一列在最右）→ 现在只剩 名次 / 名字 / 分数 三列 */
  grid-template-columns: 46px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  font-size: 12.5px;
}

.ranking-row.is-me { border-color: var(--accent); background: var(--accent-soft); }

/* 前三名：金 / 银 / 铜（底色 + 左侧名次颜色），名次与分数加粗更醒目 */
.ranking-row.is-top1,
.ranking-row.is-top2,
.ranking-row.is-top3 {
  font-weight: 700;
}

.ranking-row.is-top1 {
  border-color: #e8b53d;
  background: linear-gradient(90deg, rgba(255, 216, 120, 0.55), rgba(255, 245, 214, 0.9));
}

.ranking-row.is-top2 {
  border-color: #b9c2cf;
  background: linear-gradient(90deg, rgba(216, 224, 234, 0.7), rgba(246, 248, 251, 0.95));
}

.ranking-row.is-top3 {
  border-color: #cd8f57;
  background: linear-gradient(90deg, rgba(236, 190, 150, 0.6), rgba(252, 241, 231, 0.95));
}

.ranking-row.is-top1 .ranking-place { color: #a97200; }
.ranking-row.is-top2 .ranking-place { color: #6c7789; }
.ranking-row.is-top3 .ranking-place { color: #955c26; }
.ranking-place { color: var(--muted); font-variant-numeric: tabular-nums; }
/* 名字前面带段位徽章（2026-11-06 作者要求），行内 28px、垂直居中 */
.ranking-name {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
}
.ranking-name .rank-badge { --rank-badge-w: 28px; flex: 0 0 auto; }
.ranking-name .rank-badge-art { filter: drop-shadow(0 1px 2px rgba(70, 24, 52, 0.22)); }
.ranking-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.ranking-score { font-variant-numeric: tabular-nums; font-weight: 700; }

.ranking-empty { color: var(--muted); font-size: 12px; }

@media (max-width: 820px) {
  .ranking-grid { grid-template-columns: 1fr; }
  .ranking-tabs { grid-auto-flow: column; grid-auto-columns: 1fr; }
}

.mulligan-detail {
  width: min(760px, 100%);
  padding: 0 4px;
  border: 0;
  border-radius: 0;
  background: transparent;
  text-align: left;
  /* 牌效文字很长时（多关键词 + 注释）在框内滚动，不会把底部挤出可见区 */
  max-height: 34vh;
  overflow-y: auto;
  /* 2026-11-07：定高行的最后一块 —— 换牌框整体定高后，这一格吃掉剩余高度并内部滚动 */
  min-height: 0;
  align-self: stretch;
  max-height: none;
}

.mulligan-detail-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.mulligan-detail-head b {
  font-size: 14px;
}

.mulligan-detail-head span {
  font-size: 11px;
  color: var(--muted);
}

.mulligan-detail-keywords {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}

.mulligan-detail-keywords span {
  font-size: 10px;
  padding: 1px 7px;
  border-radius: 99px;
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.mulligan-detail p {
  margin: 5px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.mulligan-confirm {
  min-width: 220px;
}

/* 多目标选择：点选若干目标后确认（抬到手中牌之上，否则按钮会被手牌挡住） */
.target-select-bar {
  position: fixed;
  left: 50%;
  bottom: 96px;
  z-index: 130;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  box-shadow: var(--shadow-md);
}

.target-select-count {
  font-size: 12px;
  color: var(--ink-soft);
}

.target-select-count b {
  color: var(--accent-ink);
  font-size: 14px;
}

.unit.chosen {
  outline: 3px solid #ffd166;
  outline-offset: -2px;
  box-shadow: 0 0 0 3px rgba(255, 209, 102, 0.35), 0 0 22px rgba(255, 209, 102, 0.55);
}

/* 选择机制：打出带 choices 的牌后弹出 */
.choice-layer {
  position: fixed;
  inset: 0;
  z-index: 62;
  display: grid;
  place-items: center;
  /* 不压暗、不模糊：选项期间玩家还要能看清场上的卡牌与详情 */
  background: none;
  backdrop-filter: none;
  pointer-events: none;
}

.choice-panel {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 10px;
  width: min(460px, calc(100vw - 32px));
  padding: 22px 24px;
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: var(--shadow-lg);
  /* 只有面板吃点击，周围让指针回到战场 */
  pointer-events: auto;
}

.choice-eyebrow {
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--muted);
}

.choice-title {
  margin: 0;
  font-size: 20px;
  color: var(--accent-ink);
}

.choice-options {
  display: grid;
  gap: 8px;
  width: 100%;
  /* 选项可能很多（例如“选择手牌返回牌堆”会列出整只手牌）：限高并滚动 */
  max-height: 62vh;
  overflow-y: auto;
}

.choice-option {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper-soft);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.14s var(--ease), border-color 0.14s, background 0.14s;
}

.choice-option:hover {
  transform: translateY(-1px);
  border-color: var(--accent);
  background: var(--accent-soft);
}

.choice-option b {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 12px;
}

.choice-wait {
  position: fixed;
  top: 14px;
  left: 50%;
  z-index: 61;
  transform: translateX(-50%);
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 12px;
  box-shadow: var(--shadow-sm);
}

.turn-timer {
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  font-size: 13px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--paper-soft);
  border: 1px solid var(--line);
  color: var(--ink-soft);
}

.turn-timer.urgent {
  background: #ffe9ef;
  border-color: #ff9ab9;
  color: #b3225a;
}

/* 罚时回合（上回合没出牌被超时 → 本回合只有 20 秒）：红底白字，一眼能看见 */
.turn-timer.penalized {
  background: #d61f4a;
  border-color: #8f0f2c;
  color: #fff;
  box-shadow: 0 0 0 2px rgba(214, 31, 74, 0.35);
}

/* ── 回合只剩 20 秒：**战场区（.arena）的边框**闪红光（online.js 每秒 toggle body.turn-urgent） ── */
@keyframes turn-urgent-pulse {
  0%, 100% {
    border-color: rgba(255, 60, 90, 0.65);
    box-shadow:
      inset 0 0 0 3px rgba(255, 48, 82, 0.55),
      inset 0 0 34px rgba(255, 48, 82, 0.28),
      0 0 0 1px rgba(255, 48, 82, 0.45),
      0 0 18px rgba(255, 48, 82, 0.30);
  }
  50% {
    border-color: rgba(255, 92, 122, 1);
    box-shadow:
      inset 0 0 0 7px rgba(255, 48, 82, 0.95),
      inset 0 0 70px rgba(255, 48, 82, 0.6),
      0 0 0 2px rgba(255, 48, 82, 0.9),
      0 0 34px rgba(255, 48, 82, 0.7);
  }
}
body.turn-urgent .battle-body .arena {
  animation: turn-urgent-pulse 680ms ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  body.turn-urgent .battle-body .arena {
    animation: none;
    border-color: rgba(255, 92, 122, 1);
    box-shadow: inset 0 0 0 5px rgba(255, 48, 82, 0.9), inset 0 0 48px rgba(255, 48, 82, 0.45);
  }
}

/* ── 多牌组：切换条 ── */
.deck-rarity-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: -2px 0 14px;
}

.deck-rarity {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 58px;
  padding: 5px 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10px;
  color: var(--muted);
}

.deck-rarity b {
  font-weight: 900;
  letter-spacing: 0.04em;
}

.deck-rarity em {
  color: var(--ink);
  font-style: normal;
  font-weight: 800;
}

.deck-rarity.rarity-ssr {
  border-color: rgba(211, 151, 28, 0.5);
  background: #fff7dc;
}

.deck-rarity.rarity-ssr b {
  color: #9b6500;
}

.deck-rarity.rarity-sr {
  border-color: rgba(130, 82, 190, 0.4);
  background: #f5edff;
}

.deck-rarity.rarity-sr b {
  color: #6a3aa0;
}

.deck-rarity.rarity-r {
  border-color: rgba(48, 111, 190, 0.35);
  background: #edf5ff;
}

.deck-rarity.rarity-r b {
  color: #285e9b;
}

.deck-tabs {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 0 2px;
}

.deck-tabs-list {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  flex: 1 1 auto;
}

.deck-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.15s ease;
}

.deck-chip:hover {
  border-color: var(--brand);
  color: var(--ink);
}

.deck-chip.is-active {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  border-color: transparent;
  color: #fff;
  box-shadow: 0 6px 16px rgba(255, 143, 190, 0.32);
}

.deck-chip-count {
  font-size: 11px;
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

.deck-tabs-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.deck-name-input {
  width: 140px;
  padding: 8px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
}

.deck-name-input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(255, 143, 190, 0.18);
}

.toast-action {
  margin-left: 10px;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
}

.toast-action:hover {
  background: rgba(255, 255, 255, 0.22);
}

/* ── 场地牌 / 反制牌 ── */
.field-strip {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 2px 4px;
  font-size: 12px;
}

.field-label {
  color: var(--muted);
  font-weight: 700;
}

.field-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  border: 1px dashed var(--line);
  background: var(--paper-soft);
  color: var(--ink-soft);
  font-weight: 700;
}

.field-chip b {
  color: var(--accent-ink);
  font-weight: 800;
}

.field-chip.is-empty {
  opacity: 0.55;
  border-style: dotted;
}

.counter-chip {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  background: linear-gradient(135deg, #5b4a86, #3a2f5c);
  color: #fff;
  font-weight: 800;
  letter-spacing: 0.04em;
}


/* ── 场地卡：和随从同排同尺寸，可多张，显示剩余回合 ── */
.lane > .field-card {
  flex: 0 1 150px;
  min-width: 0;
  min-height: 150px;
  align-self: center;
}

/* 有场图时按场图的比例摆（成品 440×270 / 520×325），框正好贴满格子；
   取 1.62 的宽高比 + 稍微放大一点，让自带边框连同底部队标完整露出来 */
.lane > .field-card.has-face {
  flex: 0 1 244px;
  min-width: 0;
  min-height: 0;
  aspect-ratio: 440 / 271;
  align-self: center;
}

.field-card {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  padding: 6px 4px;
  overflow: hidden;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background-color: #1a1526;
  background-image:
    linear-gradient(180deg, rgba(10, 6, 18, 0.5), rgba(10, 6, 18, 0.82)),
    var(--field-art, none);
  background-position: center;
  background-size: cover;
  text-align: center;
  color: #fff;
}

/* 场地卡：有「场地卡图」就整张铺图，文字层让位（只剩剩几回合的小标签飘在右下） */
.field-card.has-face {
  padding: 0;
  border: 0;
  /* 图里自带圆角边框：这里不能再裁一刀，否则边框四个角会被切掉（作者反馈「边框没包住图」） */
  border-radius: 0;
  overflow: visible;
  background-image: none;
  background-color: transparent;
  align-content: end;
}

.field-card-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* contain：整张（含自带边框与底部队标）完整放进格子，不裁边；
     cover 会把 520×325 这种略高的素材上下切掉 ~2%，边框就被削平了 */
  object-fit: contain;
  object-position: center;
  pointer-events: none;
}

.field-card.has-face .field-card-tag,
.field-card.has-face .field-card-name,
.field-card.has-face .field-card-body {
  display: none;
}

.field-card.has-face .field-card-remain {
  position: absolute;
  right: 4px;
  bottom: 4px;
  z-index: 1;
  background: rgba(10, 6, 18, 0.62);
}

.field-card-tag {
  font-size: 10px;
  letter-spacing: 0.18em;
  color: #ffd166;
  font-weight: 800;
  text-shadow: 0 1px 3px rgba(10, 6, 18, 0.9);
}

.field-card-name {
  font-size: 11px;
  font-weight: 800;
  color: #fff;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 3px rgba(10, 6, 18, 0.9);
}

.field-card-body {
  font-size: 11px;
  line-height: 1.3;
  color: rgba(255, 255, 255, 0.82);
  white-space: pre-line;
  text-shadow: 0 1px 3px rgba(10, 6, 18, 0.9);
}

.field-card-remain {
  margin-top: 2px;
  font-size: 10px;
  font-weight: 800;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.86);
}

/* ── 牌组拖拽 ── */
.deck-row.is-dragging,
.pool-item.is-dragging {
  opacity: 0.45;
}

[data-drop].is-drop-target {
  outline: 2px dashed var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius-lg);
  background: rgba(255, 143, 190, 0.06);
}

.pool-item[draggable="true"],
.deck-row[draggable="true"] {
  cursor: grab;
}

.pool-item[draggable="true"]:active,
.deck-row[draggable="true"]:active {
  cursor: grabbing;
}

/* ── 对策栏 ── */
.counter-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 2px 6px;
  font-size: 12px;
}

.counter-bar-tag {
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--accent-ink);
  font-size: 11px;
}

.counter-bar-chip {
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  background: linear-gradient(135deg, #5b4a86, #3a2f5c);
  color: #fff;
  font-weight: 700;
  font-size: 11px;
}

.counter-bar-empty {
  color: var(--muted);
  font-size: 11px;
}

.counter-bar-foe {
  opacity: 0.85;
}

.counter-bar-chip.is-button {
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.12s var(--ease), border-color 0.12s;
}

.counter-bar-chip.is-button:hover {
  transform: translateY(-1px);
  border-color: var(--accent);
}

/* 12 乐队：筛选条自动换行，避免超出屏幕 */
.band-pick-row {
  flex-wrap: wrap;
  gap: 6px;
}

.band-pick {
  font-size: 12px;
  padding: 5px 10px;
}

.filter-row {
  flex-wrap: wrap;
  gap: 4px;
}

.filter {
  font-size: 11px;
  padding: 4px 9px;
}

/* ── 乐队徽记（素材包）── */
.card-emblem {
  position: absolute;
  left: 8%;
  right: 8%;
  top: 26%;
  height: 46%;
  object-fit: contain;
  opacity: 0.92;
  pointer-events: none;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35));
}

.card-art {
  position: relative;
}

.card:has(.card-emblem) .card-glyph {
  opacity: 0.25;
}

/* ── 关键词光效（sprite sheet 横向 n 帧，贴图与帧位由 glow.js 写进 style）──
   每帧一层、background-position 写死，只让透明度平滑呼吸（错开 animation-delay）。
   以前是单层 + 动画 background-position 跳帧：spritesheet 相邻帧亮度差很大（清晰的盾 ↔ 虚化光晕），
   硬切就成了"闪一下"；重绘（innerHTML 整块替换）还会让动画从头跳。改成 crossfade 后是连续的光。
   注意别再套 filter: drop-shadow / will-change —— 一叠加层的阴影跟着帧变，更容易看出闪。 */
.glow {
  position: absolute;
  inset: 0;
  display: block;
  background-repeat: no-repeat;
  pointer-events: none;
  /* 兜底：万一动画没跑（极端设置），光效也还是看得见，不会整层消失 */
  opacity: 0.55;
  animation-name: glow-pulse;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

@keyframes glow-pulse {
  0% { opacity: 0.08; }
  50% { opacity: 1; }
  100% { opacity: 0.08; }
}

/* 瞩目（=守护）用 V4 光效素材：APNG 自己循环，不需要 glow-pulse 的亮度呼吸。
   画布 750×788，盾形内容实测包围盒 x129..616（488 宽）、y101..683（583 高），四周留白约 17% / 13%。
   按内容框「宽度」等比铺（750/488 ≈ 153.7%，高度用 auto）：
   只给一个百分比、另一个 auto，缩放就会保持等比，不会被拉扁/拉宽；
   两个都写死（153.7% 135.2%）会横向/纵向各自缩放，盾牌就被拉宽了。 */
.glow.glow-apng {
  animation: none;
  opacity: 1;
  inset: 0;
  background-repeat: no-repeat;
  /* 108%：盾形内容宽度约卡面的 70%（比之前 135% 收一圈）；153.7% = 卡面宽 */
  background-size: 108% auto;
  background-position: 50% 50%;
}

.unit-tile, .hand-card, .card-art {
  position: relative;
}

/* ── 卡图（素材生成，找不到时自动回退到 CSS 卡面）── */
.card-art .card-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  pointer-events: none;
}

/* ── 稀有度外框光：与 Godot RarityGlow 同一套贴图 ── */
.rarity-glow {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  background-position: center;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  pointer-events: none;
}

.card-art > .rarity-glow {
  z-index: 1;
}

.card:not(:has(.card-face)) .rarity-glow {
  display: none;
}

/* 有卡图时：卡图铺满整张卡，费用/攻防/稀有度光全部叠在卡图上 */
/* 有卡图时：卡壳底色 / 边框 / 乐队渐变底全部透明 ——
   卡图四角是圆的、带透明边，留着底色就会从圆角处露出「色块」；
   卡图本身已经自带卡框与底纹，不需要再垫一层。 */
.card:has(.card-face) {
  background: transparent;
  border-color: transparent;
}

.card:has(.card-face) .card-art {
  position: absolute;
  inset: 0;
  height: 100%;
  min-height: 0;
  border-radius: inherit;
  background: transparent;
}

.card:has(.card-face) .card-art .card-face {
  object-fit: cover;
}

/* 卡图本身自带光效，去掉旧卡面顶部的白色径向叠层，避免整张卡发灰 */
.card:has(.card-face) .card-art::after {
  display: none;
}

.card:has(.card-face) .card-stats {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 4;
  border-top: 0;
  padding: 14px 9px 5px;
  background: linear-gradient(180deg, transparent, rgba(10, 6, 18, 0.78) 42%);
  color: #fff;
  text-shadow: 0 1px 2px rgba(10, 6, 18, 0.8);
}

.card:has(.card-face) .card-stats .atk {
  color: #ffd166;
}

.card:has(.card-face) .card-stats .hp {
  color: #8ef0d0;
}

.card:has(.card-face) .card-cost,
.card:has(.card-face) .card-band {
  z-index: 5;
}

.rarity-portrait-e { background-image: url("/assets/ui/rarity-portrait-e.png"); }
/* D / R 外框光效互换：D 用白色 R 光，R 用蓝色 D 光 */
.rarity-portrait-d { background-image: url("/assets/ui/rarity-portrait-r.png"); }
.rarity-portrait-r { background-image: url("/assets/ui/rarity-portrait-d.png"); }
.rarity-portrait-sr { background-image: url("/assets/ui/rarity-portrait-sr.png"); }
.rarity-portrait-ssr { background-image: url("/assets/ui/rarity-portrait-ssr.png"); }
.rarity-portrait-ex { background-image: url("/assets/ui/rarity-portrait-ssr.png"); }

.rarity-board-e { background-image: url("/assets/ui/rarity-board-e.png"); }
/* D / R 外框光效互换（场上单位）：D 用白色 R 光，R 用蓝色 D 光 */
.rarity-board-d { background-image: url("/assets/ui/rarity-board-r.png"); }
.rarity-board-r { background-image: url("/assets/ui/rarity-board-d.png"); }
.rarity-board-sr { background-image: url("/assets/ui/rarity-board-sr.png"); }
.rarity-board-ssr { background-image: url("/assets/ui/rarity-board-ssr.png"); }
.rarity-board-ex { background-image: url("/assets/ui/rarity-board-ssr.png"); }

/* 图片 404 时统一隐藏，让卡面/单位回退到 CSS 占位 */
img.is-missing {
  display: none !important;
}

.card:has(.card-face) .card-glyph,
.card:has(.card-face) .card-emblem {
  display: none;
}

/* 卡图铺满整张卡，隐藏手绘文字层 */
.card:has(.card-face) .card-body,
.card:has(.card-face) .card-glyph,
.card:has(.card-face) .card-emblem,
.card:has(.card-face) .card-band {
  display: none;
}

/* 卡图不再内嵌费用：费用徽章由 UI 叠在卡图左上角（与 Godot StatLayer 同一素材） */
.card:has(.card-face) .card-cost {
  top: 13px;
  left: 0;
  width: 32px;
  height: 32px;
  border-radius: 0;
  /* 徽章只占贴图画布一半，用 200% 让星形填满盒子的可见区域 */
  background: url("/assets/ui/stat-cost.png") center / 200% 200% no-repeat;
  box-shadow: none;
  color: #302b49;
  font-size: 13px;
}

/* 过载可用：左上角费用改为过载后的数值，金色 */
.card-cost.is-overload,
.card:has(.card-face) .card-cost.is-overload {
  color: #ffd166;
  text-shadow: 0 0 7px rgba(255, 209, 102, 0.75), 0 1px 2px rgba(40, 24, 0, 0.9);
}

.card-cost.is-reduced {
  color: #0e8a5f;
  background: #d9f8e9;
  box-shadow: 0 0 0 1px rgba(20, 140, 95, 0.35), 0 2px 6px rgba(0, 0, 0, 0.18);
}

/* 卡图版：减费数字改为绿色（保留星形徽章背景） */
.card:has(.card-face) .card-cost.is-reduced {
  color: #63e0b4;
  text-shadow: 0 0 7px rgba(99, 224, 180, 0.75), 0 1px 2px rgba(0, 40, 20, 0.9);
  background: url("/assets/ui/stat-cost.png") center / 200% 200% no-repeat;
  box-shadow: none;
}

/* 加费：费用数字改为红色 */
.card-cost.is-increased {
  color: #c6283a;
  background: #ffe1e5;
  box-shadow: 0 0 0 1px rgba(198, 40, 58, 0.35), 0 2px 6px rgba(0, 0, 0, 0.18);
}

.card:has(.card-face) .card-cost.is-increased {
  color: #ff5c6c;
  text-shadow: 0 0 7px rgba(255, 92, 108, 0.75), 0 1px 2px rgba(40, 0, 0, 0.9);
  background: url("/assets/ui/stat-cost.png") center / 200% 200% no-repeat;
  box-shadow: none;
}

.card-cost.is-reduced small,
.card-cost.is-increased small {
  position: absolute;
  right: -5px;
  bottom: -4px;
  font-size: 9px;
  font-weight: 900;
  line-height: 1;
}

.card-cost.is-reduced small {
  color: #0e8a5f;
}

.card:has(.card-face) .card-cost.is-reduced small {
  color: #63e0b4;
}

.card-cost.is-increased small {
  color: #c6283a;
}

.card:has(.card-face) .card-cost.is-increased small {
  color: #ff5c6c;
}

.card-art .card-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── 打出卡牌展示 ─────────────────────────────────────────────── */
.card-reveal-layer {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  pointer-events: none;
  background: transparent;
  opacity: 0;
  transition: opacity 0.24s ease;
}

.card-reveal-layer.is-visible {
  opacity: 1;
}

.card-reveal-layer {
  /* 亮牌定位：整体在容器左侧约 1/3 处、并上移 200px（居中受 padding 影响，位移是 padding 的一半） */
  padding-right: clamp(0px, 36vw, 640px);
  padding-bottom: 100px;   /* 居中后仅上移 50px（相对上一版下移 150px） */
}

.card-reveal-ui {
  display: grid;
  justify-items: center;
  gap: 10px;
  margin-left: 0;
  opacity: 0;
  transform: translateY(24px) scale(0.55) rotate(-2deg);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.2, 0.85, 0.3, 1.15);
}

.card-reveal-layer.is-visible .card-reveal-ui {
  opacity: 1;
  transform: translateY(0) scale(1) rotate(0deg);
}

.card-reveal-side {
  padding: 4px 12px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 999px;
  background: rgba(12, 8, 22, 0.78);
  color: #ffd9ea;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}

.card-reveal-layer.is-foe .card-reveal-side {
  color: #b9ddff;
  border-color: rgba(140, 200, 255, 0.45);
}

.card-reveal-frame {
  position: relative;
  /* 和卡面同一比例（600×840 = 5:7），宽高完全贴合，不会露出外框 */
  width: min(240px, 32vw);
  aspect-ratio: 5 / 7;
  border-radius: 14px;
  isolation: isolate;
  overflow: visible;
  background: none;
  /* 完全不加投影：卡面四边是透明的，任何阴影都会变成一圈黑边 */
  filter: none;
  box-shadow: none;
}

.card-reveal-glow {
  position: absolute;
  inset: -16%;
  z-index: -1;
  border-radius: 24px;
  background: radial-gradient(ellipse, rgba(255, 143, 214, 0.4), transparent 68%);
  filter: blur(12px);
  animation: card-reveal-pulse 1.4s ease-in-out infinite;
}

.card-reveal-frame.is-missing .card-reveal-fallback {
  background: linear-gradient(145deg, #39224f, #151020);
}

.card-reveal-layer.is-foe .card-reveal-glow {
  background: radial-gradient(ellipse, rgba(112, 194, 255, 0.42), transparent 68%);
}

.card-reveal-art {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  border-radius: 14px;
  object-fit: cover;
  /* 只留卡面本身的边框，不再额外描白边/粉色光圈 */
  box-shadow: none;
}

.card-reveal-layer.is-foe .card-reveal-art {
  box-shadow: 0 0 0 1px rgba(180, 220, 255, 0.45), 0 0 24px rgba(112, 194, 255, 0.35);
}

/* ── 爆牌：亮牌但整体灰掉（手牌满、抽到的那张被弃置） ───────────── */
.card-reveal-layer.is-burned .card-reveal-art {
  filter: grayscale(1) brightness(0.82) contrast(0.92);
  box-shadow: 0 0 0 1px rgba(190, 190, 190, 0.5), 0 0 22px rgba(150, 150, 150, 0.35);
}

.card-reveal-layer.is-burned .card-reveal-fallback {
  filter: grayscale(1) brightness(0.75);
}

.card-reveal-layer.is-burned .card-reveal-glow {
  background: radial-gradient(ellipse, rgba(170, 170, 170, 0.35), transparent 68%);
  animation: none;
}

.card-reveal-layer.is-burned .card-reveal-side {
  border-color: rgba(200, 200, 200, 0.45);
  color: #d8d8d8;
  background: rgba(18, 18, 20, 0.82);
}

.card-reveal-layer.is-burned .card-reveal-name {
  color: #cfcfcf;
}

.card-reveal-layer.is-burned .card-reveal-frame {
  filter: grayscale(1);
}

.card-reveal-fallback {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: grid;
  place-items: center;
  padding: 18px;
  border-radius: 14px;
  /* 卡图自带透明留白，默认不铺底色，否则会透出一圈黑框 */
  background: none;
  color: #fff;
  font-size: 17px;
  font-weight: 800;
  text-align: center;
}

.card-reveal-name {
  max-width: min(320px, 70vw);
  overflow: hidden;
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
}

.card-reveal-overload {
  margin-top: -4px;
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(255, 196, 70, 0.16);
  color: #ffd166;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
}

@keyframes card-reveal-pulse {
  50% { opacity: 0.62; transform: scale(1.06); }
}

@media (max-width: 640px) {
  .card-reveal-ui { margin-left: -7vw; }
  .card-reveal-frame { width: min(190px, 42vw); }
  .card-reveal-side { font-size: 10px; }
  .card-reveal-name { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .card-reveal-layer,
  .card-reveal-ui { transition-duration: 0.08s; }
  .card-reveal-glow { animation: none; }
}

/* ── 对战表情 ─────────────────────────────────────────── */
.emote-btn.is-empty {
  opacity: 0.45;
}

.emote-panel {
  position: fixed;
  top: 64px;
  right: 16px;
  z-index: 90;
  padding: 10px;
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  background: rgba(14, 10, 22, 0.94);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}

.emote-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--muted, #a99bbd);
}

.emote-grid {
  display: grid;
  grid-template-columns: repeat(4, 84px);
  gap: 8px;
}

.emote-chip {
  display: grid;
  gap: 2px;
  justify-items: center;
  padding: 4px;
  border-radius: 10px;
  border: 1px solid transparent;
  background: rgba(255, 255, 255, 0.04);
  cursor: pointer;
  transition: transform 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}

.emote-chip:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  background: rgba(242, 80, 154, 0.14);
}

.emote-chip img {
  width: 72px;
  height: 72px;
  object-fit: contain;
  pointer-events: none;
}

.emote-chip small {
  font-size: 10.5px;
  color: rgba(255, 255, 255, 0.82);
  pointer-events: none;
}

.emote-bubble {
  opacity: 0;
  transform: translateY(8px) scale(0.92);
  transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.2, 0.85, 0.3, 1.2);
  filter: drop-shadow(0 10px 22px rgba(0, 0, 0, 0.5));
}

.emote-bubble.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}

.emote-bubble img {
  width: 100%;
  display: block;
}

.emote-bubble span {
  display: block;
  margin-top: 2px;
  text-align: center;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.75);
}

/* 观战者发的表情：贴页面最左边，缩一号，带一句「谁发的」 */
.emote-bubble.is-spectator {
  filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.45));
  opacity: 0;
  transform: translateX(-14px) scale(0.9);
}

.emote-bubble.is-spectator.is-visible {
  opacity: 1;
  transform: translateX(0) scale(0.9);
}

.emote-bubble .emote-from {
  display: block;
  margin-top: 1px;
  text-align: center;
  font-size: 11px;
  font-style: normal;
  font-weight: 700;
  color: #ffd7e6;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── 对战动效：指向光带 / 悬停放大 / 突进 / 受击 ─────────────────── */

/* 悬停：可行动的我方单位、可指向的敌方单位都轻微放大 */
.unit {
  transition: transform 0.16s ease, filter 0.16s ease;
}
.unit.side-you[data-ready="1"]:hover,
.unit.targetable:hover {
  transform: translateY(-3px) scale(1.06);
  z-index: 6;
}

/* 指向弧形光带（SVG） */
.fx-curve {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 45;
}
.fx-curve path {
  fill: none;
  stroke-linecap: round;
}
.fx-curve .fx-curve-glow {
  stroke: rgba(88, 206, 255, 0.55);
  stroke-width: 11;
  filter: blur(5px);
}
.fx-curve .fx-curve-line {
  stroke: #b9f1ff;
  stroke-width: 3;
  filter: drop-shadow(0 0 6px #4fd0ff);
}
/* 指向线改成实线：不再虚线流动 */
.fx-curve-aim .fx-curve-line {
  stroke-dasharray: none;
  stroke-width: 3.5;
  filter: drop-shadow(0 0 7px rgba(79, 208, 255, 0.9));
}
@keyframes fx-curve-flow {
  to { stroke-dashoffset: -52; }
}
.fx-curve-attack .fx-curve-line {
  animation: fx-curve-burst 0.42s ease-out forwards;
}
@keyframes fx-curve-burst {
  0% { stroke-dasharray: 0 2000; opacity: 1; }
  100% { stroke-dasharray: 2000 0; opacity: 0.15; }
}

/* 瞄准落点环 */
.fx-ring-aim {
  width: 46px;
  height: 46px;
  border: 2px solid rgba(120, 226, 255, 0.9);
  box-shadow: 0 0 14px rgba(79, 208, 255, 0.75), inset 0 0 10px rgba(79, 208, 255, 0.35);
  animation: fx-ring-aim 1.1s ease-in-out infinite;
}
@keyframes fx-ring-aim {
  0%, 100% { transform: translate(-50%, -50%) scale(0.92); opacity: 0.75; }
  50% { transform: translate(-50%, -50%) scale(1.06); opacity: 1; }
}

/* 受击：红闪 + 左右晃 */
.fx-hit {
  animation: fx-hit 0.46s ease-out;
}
@keyframes fx-hit {
  0% { filter: none; transform: translateX(0); }
  10% { filter: brightness(1.9) saturate(3.2) sepia(0.9) hue-rotate(-28deg) drop-shadow(0 0 22px rgba(255, 20, 70, 1)); transform: translateX(-7px); }
  30% { filter: brightness(1.85) saturate(3) sepia(0.85) hue-rotate(-28deg) drop-shadow(0 0 18px rgba(255, 40, 80, 0.9)); transform: translateX(7px); }
  50% { filter: brightness(1.6) saturate(2.2) sepia(0.6) hue-rotate(-20deg); transform: translateX(-6px); }
  70% { filter: brightness(1.3) saturate(1.5); transform: translateX(4px); }
  100% { filter: none; transform: translateX(0); }
}

/* 突进 */
.fx-lunge {
  animation: fx-lunge 0.4s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes fx-lunge {
  0% { transform: translate(0, 0) scale(1); }
  45% { transform: translate(var(--lunge-x, 0px), var(--lunge-y, 0px)) scale(1.05); }
  100% { transform: translate(0, 0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .fx-hit, .fx-lunge, .fx-curve, .fx-ring-aim { animation: none !important; }
}

/* 被技能 / buff 影响：白闪一下 */
.fx-white {
  animation: fx-white 0.36s ease-out;
}
@keyframes fx-white {
  0% { filter: brightness(1) saturate(1); }
  18% { filter: brightness(3.2) saturate(0.15) contrast(1.15) drop-shadow(0 0 18px rgba(255, 255, 255, 0.95)); }
  55% { filter: brightness(2.1) saturate(0.5) drop-shadow(0 0 10px rgba(255, 255, 255, 0.6)); }
  100% { filter: brightness(1) saturate(1); }
}

@media (prefers-reduced-motion: reduce) {
  .fx-white { animation: none !important; }
}


/* 图鉴：关键词搜索框 */
.codex-search-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
  font-size: 12px;
  color: var(--muted, #9fb0c8);
}
.codex-search-row .filter-input {
  flex: 1 1 auto;
  max-width: 360px;
  padding: 7px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: inherit;
  font-size: 13px;
  outline: none;
}
.codex-search-row .filter-input:focus {
  border-color: var(--accent, #ff6d93);
  background: rgba(255, 255, 255, 0.1);
}



/* 退场替身：旧位置克隆卡面，淡出 + 缩小 */
.fx-ghost {
  position: fixed;
  z-index: 70;
  pointer-events: none;
  opacity: 1;
  transform: scale(1);
  transform-origin: center;
  transition: opacity 0.34s ease, transform 0.34s ease;
}
.fx-ghost > * {
  width: 100% !important;
  height: 100% !important;
  margin: 0 !important;
}
.fx-ghost.is-transparent {
  opacity: 0;
  transition: none;
}

/* ── 本回合战报弹窗（网页端） ───────────────────────────
   2026-11-05 作者要求（电脑端联机）：从「贴左边缘」改到**贴右边缘** ——
   左边是领队立绘 / 手牌，弹窗压在上面挡操作；右边留白最多，看着也顺手。
   手机竖屏不用这个形态（改走 `.round-feed.feed-ticker` 顶端滚动条，那条自己写了 left/right）。 */
.round-feed {
  position: fixed;
  left: auto;
  right: 10px;
  /* 2026-11-05 作者要求：在 46% 的基础上再下移 100px */
  top: calc(46% + 100px);
  width: 330px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 58;
  pointer-events: none;
}
.round-feed-entry {
  padding: 7px 10px;
  border-radius: 10px;
  background: rgba(18, 14, 28, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  animation: round-feed-in 0.24s ease-out;
}
.round-feed-entry b {
  display: block;
  font-size: 12px;
  color: #ffb3cf;
  margin-bottom: 2px;
}
.round-feed-entry.is-foe b {
  color: #b9ddff;
}
.round-feed-entry span {
  display: block;
  font-size: 11px;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.78);
}
@keyframes round-feed-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 对手选牌时的卡背 */
.choice-layer.is-foe {
  align-content: start;
  padding-top: 12vh;
}
.foe-choose-backs {
  display: flex;
  gap: 16px;
  justify-content: center;
  margin-bottom: 14px;
}
.foe-choose-back {
  width: 108px;
  height: 152px;
  border-radius: 12px;
  overflow: hidden;
  animation: foe-back-in 0.28s ease-out backwards;
  animation-delay: calc(var(--i, 0) * 70ms);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
}
.foe-choose-back img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
@keyframes foe-back-in {
  from { opacity: 0; transform: translateY(-14px) scale(0.92); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.choice-wait {
  color: rgba(255, 255, 255, 0.85);
  font-size: 13px;
  text-align: center;
}

/* 对手选完牌：卡背飞回手牌 */
.foe-fly-back {
  position: fixed;
  width: 108px;
  height: 152px;
  border-radius: 12px;
  overflow: hidden;
  z-index: 72;
  pointer-events: none;
  transition: transform 0.42s cubic-bezier(0.3, 0.7, 0.2, 1), opacity 0.3s ease 0.2s;
}
.foe-fly-back img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* 战场尺寸随窗口缩放：--board-scale 由 JS（fitBoardScale）写到 :root，默认 1。
   战场高度、单位宽、领队头像、右侧信息栏都乘这个系数，小屏自动缩、大屏自动放大。 */
:root {
  --board-scale: 1;
}

/* ── 对战页：整体加宽，10 张手牌一排放得下 ─────────────── */
.battle-page {
  --lane-h: calc(168px * var(--board-scale));
  --unit-w: calc(150px * var(--board-scale));
  --leader-avatar: calc(120px * var(--board-scale));
  /* 2026-11-07（作者：左右还有空隙，别加卡片、非必要别用滚动条）：右侧详情栏加宽一档，
     卡面文字少折几行，多数情况不需要滚动；手牌那边把让出来的宽度算进去。 */
  --inspector-w: clamp(260px, calc(340px * var(--board-scale)), 430px);
  --card-max-w: clamp(92px, calc(150px * var(--board-scale)), 190px);
  /* 手牌卡宽按视口自适应：10 张 + 间距 + 右侧信息栏（信息栏加宽后这里同步从 420 提到 560） */
  --card-w: clamp(calc(72px * var(--board-scale)), calc((100vw - 560px) / 10), calc(150px * var(--board-scale)));
  --card-h: calc(var(--card-w) * 1.4);
  max-width: min(1920px, 99vw);
  margin-inline: auto;
  position: relative;
  /* 自成层叠上下文：背景层用 z-index:-1 压在本页内容下面，但仍盖住 body 背景 */
  isolation: isolate;
}

/* 对战页不再铺专属整屏背景：与大厅共用 body 的站点背景；战斗图只留在战场面板内部 */
.battle-page .battle-scene {
  display: none;
}

/* 压暗 + 上下渐隐，保证面板上的字仍然清楚 */
.battle-page .battle-scene::after {
  content: none;
}

/* 信息栏收窄一点，把宽度让给战场 */
.battle-page .battle-body {
  grid-template-columns: minmax(0, 1fr) var(--inspector-w, 264px);
  gap: 12px;
  /* 2026-11-07：整页高度不许被右侧详情的内容长短带着变 —— 以前 align-items:start 时，
     详情里换一张文字长的牌 → 整页变高 → fitBoardScale 缩小 --board-scale → 整块战斗界面“变小一下”，
     悬停走开又变回来（作者反馈的「战斗界面莫名其妙变大变小」）。现在两列等高、详情自己内部滚动。 */
  align-items: stretch;
}

.battle-page .battle-body > .inspector {
  /* 高度由 JS `syncInspectorHeight()` 钉成「战场那一列的高度」（CSS 拿不到兄弟列的高度） */
  min-height: 0;
  max-height: calc(100dvh - 120px);
  /* 只保留这**一条**滚动条，而且只有内容真的放不下时才出现（内部小块不再各自滚） */
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: thin;
}

/* 详情内容：默认**不**单独滚动（2026-11-07 作者：非必要不要滚动条）——
   右栏加宽后长描述也能整段排下来；真的超长时才由外层 .inspector 出唯一一条滚动条。 */
.battle-page .battle-body > .inspector .inspector-detail,
.battle-page .battle-body > .inspector .unit-gains,
.battle-page .battle-body > .inspector .battle-log {
  min-height: 0;
  overflow: visible;
}

/* 右栏里的正文允许在窄屏上折行，别把字挤成竖条 */
.battle-page .battle-body > .inspector p,
.battle-page .battle-body > .inspector li {
  overflow-wrap: anywhere;
}

/* 手牌一行：满了自动缩，少了自动长，最多 10 张永不溢出 */
.battle-page .hand-strip {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  overflow: hidden;
  justify-content: center;
  align-items: flex-start;
}

.battle-page .hand-slot {
  flex: 1 1 0;
  min-width: 0;
  max-width: var(--card-max-w, var(--card-w));
  aspect-ratio: 5 / 7;
  display: block;
}

.battle-page .hand-slot .card {
  width: 100%;
  height: 100%;
}

.battle-page .hand-zone {
  margin-top: 12px;
}

.round-feed-entry.is-effect b {
  color: #ffd479;
}

/* ── 领队头像：无边框、无底色，直接铺满 120px ─────────── */
.stage-avatar {
  display: inline-grid;
  place-items: center;
  width: var(--leader-avatar, 120px);
  height: var(--leader-avatar, 120px);
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: none;
  box-shadow: none;
  flex: 0 0 auto;
}
.stage-avatar img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* 牌组确认里的头像选择 */
.avatar-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.avatar-option {
  display: grid;
  justify-items: center;
  gap: 3px;
  padding: 4px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.04);
  color: inherit;
  cursor: pointer;
  transition: border-color 0.16s ease, transform 0.16s ease;
}
.avatar-option img {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}
.avatar-option small {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.7);
}
.avatar-option:hover {
  transform: translateY(-2px);
}
.avatar-option.active {
  border-color: var(--accent, #ff6d93);
  box-shadow: 0 0 0 2px rgba(255, 109, 147, 0.35);
}

/* 领队名下面另起一行放乐队名 */
.stage-title {
  display: grid;
  gap: 1px;
  line-height: 1.15;
}
.stage-title .stage-name {
  display: block;
}
.stage-title .stage-role {
  display: block;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.62);
}

/* ── 选中光圈：指向可指向的单位/领队时套在它外面 ─────────── */
.target-ring {
  position: absolute;
  /* 12 帧 sprite 是正方形帧：容器也必须正方，否则背景会被拉伸（单位变宽/变高时尤其明显） */
  left: 50%;
  top: 50%;
  width: 132%;
  aspect-ratio: 1 / 1;
  height: auto;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 8;
  display: block;
}
.target-ring {
  contain: paint;
}

/* 把重绘范围限制在卡片内部：悬停/光圈动画不再触发整页重绘 */
.unit,
.stage {
  contain: layout style;
}
.unit .glow,
.field-cell .glow {
  /* 不要 contain: paint / will-change：前者会把光效裁掉，后者叠 filter 后更容易看出闪 */
  mix-blend-mode: normal;
}
.target-ring i {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-size: 1200% 100%;   /* 12 帧横向 sprite sheet */
  will-change: background-position;
  pointer-events: none;
}
.target-ring .ring-outer {
  background-image: url('/assets/ui/ring-outer.webp');
  animation: ring-play 2.6s steps(11) infinite;
}
.target-ring .ring-inner {
  inset: 8%;
  background-image: url('/assets/ui/ring-inner.webp');
  animation: ring-play 2s steps(11) infinite reverse;
}
@keyframes ring-play {
  from { background-position: 0% 0; }
  to { background-position: 100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .target-ring .ring-outer,
  .target-ring .ring-inner { animation: none; }
}

/* 领队的光圈套在头像那一小块上（2026-11-07：以前这里是 `inset: -16px -20px`，后面又被
   `inset: -10px` 覆盖 —— 而基类用的是 `left/top: 50% + translate(-50%,-50%) + width: 132%`，
   加了 inset 之后 left/top 被挪到 -10px、width 还是 132% → 光圈整个偏到左上（作者截图里那个错位）。
   现在统一保持「居中 + 略大于头像」，把残留的 inset 清掉。 */
.target-ring.is-leader {
  inset: auto;
  left: 50%;
  top: 50%;
  right: auto;
  bottom: auto;
  width: 116%;
  aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
}
.target-ring.is-leader i {
  background-size: 1200% 100%;
}

/* 首页主视觉：三张卡错落展示在夜景舞台上 */
.hero-deck {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  perspective: 900px;
}
.hero-face {
  width: clamp(130px, 14vw, 200px);
  border-radius: 14px;
  display: block;
  transform: rotate(-7deg) translateY(10px);
  box-shadow: 0 22px 48px rgba(4, 8, 22, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.12);
  transition: transform 0.24s var(--ease);
  animation: hero-face-float 6s ease-in-out infinite;
}
.hero-face.is-mid {
  transform: rotate(0deg) translateY(-10px);
  z-index: 2;
  animation-delay: 0.6s;
}
.hero-face.is-last {
  transform: rotate(7deg) translateY(10px);
  animation-delay: 1.2s;
}
.hero-face.is-tail {
  transform: rotate(13deg) translateY(20px);
  animation-delay: 1.8s;
  width: clamp(104px, 11vw, 168px);
}
.hero-face.is-fading {
  opacity: 0;
  transition: opacity 0.22s var(--ease);
}
.hero-face:hover {
  transform: translateY(-16px) rotate(0deg) scale(1.04);
  z-index: 3;
  animation-play-state: paused;
}
@keyframes hero-face-float {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.06); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-face { animation: none; }
}

/* 领队头像作为光圈锚点 */
.stage-avatar { position: relative; }
/* 领队光圈统一由上面那条「居中 + 116%」的规则负责，这里不再覆盖 inset（旧的 -10px 会把光圈挤到左上角） */

/* ── 联机大厅横幅已在 2026-11-02 移除（那块「列车必将驶向下一站」的夜舞台大图）── */


/* 卡面未解码完成时也显示卡底色，不会闪白 */
.card-face,
.unit-face {
  background: transparent;
}

/* 战场重绘时不重放整页淡入，否则每次操作都会闪一下 */
.battle-page,
.online-page {
  animation: none;
}

/* ── 顶栏常驻（2026-11-05 作者要求）────────────────────────────
   这里原本是「对战页顶栏自动收起、鼠标靠近顶部再滑下」（`body.topbar-collapsible .topbar
   { transform: translateY(-100%) }` + 顶部热区提示条）。作者连续反馈菜单条会消失，
   而这套收起机制的兜底只有「鼠标靠近顶部 18px」，触屏（平板/手机）根本叫不回来。
   → 整块删掉：顶栏任何页面、任何设备都常驻。 */
.topbar {
  transition: transform 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}

/* 联机对战：对手手牌 / 行动点信息条 */
.foe-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px;
  border-radius: 999px;
  background: rgba(18, 28, 48, 0.9);
  border: 1px solid rgba(126, 206, 255, 0.8);
  color: #eaf7ff;
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 3px 12px rgba(8, 18, 38, 0.35);
}
.foe-status b {
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* 2026-11-06：行动点显示成 x/y，y = 当前行动点槽 —— 分母用小号半透明字跟在后面 */
.foe-status small,
.stage-ap small {
  font-size: 10.5px;
  font-weight: 700;
  opacity: 0.72;
  margin-left: 1px;
}

.stage-ap { font-variant-numeric: tabular-nums; }

/* 对局中查看卡组 */
.deck-viewer {
  display: grid;
  gap: 14px;
  max-height: 60vh;
  overflow: auto;
}
.deck-viewer-group h4 {
  margin: 0 0 6px;
  font-size: 13px;
  color: var(--ink-soft);
}
.deck-viewer-group ul {
  margin: 0;
  padding-left: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 3px 10px;
  font-size: 12px;
}

/* 准备页：牌组标题行 + 查看完整卡组 */
.prep-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 18px 0 10px;
}
.prep-title-row .prep-title {
  margin: 0;
}

/* 模态框：全屏切换 */
.modal-head {
  position: relative;
}
.modal-head-tools {
  position: absolute;
  top: 12px;
  right: 14px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.modal-expand,
.modal-close {
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font-size: 18px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 8px;
  cursor: pointer;
}
.modal-expand:hover,
.modal-close:hover {
  background: rgba(120, 100, 160, 0.14);
  color: var(--ink);
}
/* 卡组类弹窗：比默认更宽一点 */
#modal.modal-host.ai-deck-modal {
  width: min(1000px, calc(100vw - 28px));
}

/* 全屏：窗口本身也放大，仍然靠 <dialog> 的 margin:auto 居中 */
.modal-host.modal-full {
  width: min(1640px, calc(100vw - 24px));
  max-height: calc(100vh - 24px);
  margin: auto;
}
.modal-host.modal-full .modal-card {
  width: 100%;
  height: 86vh;
  max-height: calc(100vh - 40px);
  display: flex;
  flex-direction: column;
}
.modal-host.modal-full .modal-body {
  flex: 1 1 auto;
  overflow: auto;
}

/* 选择弹窗：选项悬停时的卡牌简介 */
.choice-hover-card {
  /* 绝对定位：出现/消失都不会改变弹窗高度，避免整块面板上下跳动 */
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 8px);
  margin-top: 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  max-height: 140px;
  overflow: auto;
}
.choice-hover-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 4px;
}
.choice-hover-head b {
  font-size: 14px;
}
.choice-hover-head span {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.6);
}
.choice-hover-text {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.82);
  white-space: pre-wrap;
}

/* 小卡（mini）：攻击/生命徽章按卡宽缩放，避免叠在一起 */
.card.card-mini > .card-stat-badge,
.ai-deck-grid .card > .card-stat-badge,
.prep-deck .card > .card-stat-badge {
  width: 44%;
  height: auto;
  aspect-ratio: 1 / 1;
  bottom: 4%;
}
.card.card-mini > .card-stat-badge.is-atk,
.ai-deck-grid .card > .card-stat-badge.is-atk,
.prep-deck .card > .card-stat-badge.is-atk {
  left: 3%;
}
.card.card-mini > .card-stat-badge.is-hp,
.ai-deck-grid .card > .card-stat-badge.is-hp,
.prep-deck .card > .card-stat-badge.is-hp {
  right: 3%;
}
.card.card-mini > .card-stat-badge b,
.ai-deck-grid .card > .card-stat-badge b,
.prep-deck .card > .card-stat-badge b {
  font-size: clamp(7px, 2.6vw, 13px);
}


/* 攻击/生命徽章锚定到整张卡：左下 / 右下 */
.card > .card-stat-badge {
  bottom: 5px;
  z-index: 8;
}
.card > .card-stat-badge.is-atk {
  left: 5px;
  right: auto;
}
.card > .card-stat-badge.is-hp {
  right: 5px;
  left: auto;
}

/* 领队屏障层数 */
.stage-barrier {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 2px 0 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  color: #dff1ff;
  background: rgba(84, 160, 255, 0.22);
  border: 1px solid rgba(126, 190, 255, 0.55);
}


/* 卡牌详情：机制词条解释（屏障等） */
.card-mechanic-notes {
  margin: 10px 0 0;
  padding: 10px 12px;
  list-style: none;
  border-radius: 10px;
  background: rgba(84, 160, 255, 0.10);
  border: 1px solid rgba(126, 190, 255, 0.35);
  font-size: 12px;
  line-height: 1.6;
}
.card-mechanic-notes b {
  color: #6aa9ff;
}


/* 战斗动画层（光矢 / 破坏碎屑） */
.battle-fx-layer {
  position: fixed;
  inset: 0;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  overflow: hidden;
  z-index: 40;
}
.fx-bolt {
  position: absolute;
  width: 0;
  height: 0;
  animation: fx-bolt-fly var(--dur, 320ms) cubic-bezier(0.2, 0.7, 0.35, 1) forwards;
}
.fx-bolt img {
  position: absolute;
  width: 220px;
  height: auto;
  left: -110px;
  top: -44px;
  filter: drop-shadow(0 0 12px rgba(140, 210, 255, 0.85));
  transform-origin: center;
}
@keyframes fx-bolt-fly {
  from { transform: translate(0, 0) scale(0.7); opacity: 0; }
  20%  { opacity: 1; }
  to   { transform: translate(var(--dx, 0px), var(--dy, 0px)) scale(1.05); opacity: 0.9; }
}
.fx-burst {
  position: absolute;
  width: 260px;
  height: auto;
  margin-left: -130px;
  margin-top: -130px;
  opacity: 0;
  animation: fx-burst-pop 420ms ease-out forwards;
}
@keyframes fx-burst-pop {
  0%   { opacity: 0; transform: scale(0.35); }
  35%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.25); }
}
.fx-destroy {
  position: absolute;
  width: 420px;
  height: auto;
  margin-left: -210px;
  margin-top: -210px;
  animation: fx-destroy-fade var(--dur, 1200ms) ease-out forwards;
  filter: drop-shadow(0 6px 18px rgba(255, 190, 230, 0.5));
}
@keyframes fx-destroy-fade {
  0%   { opacity: 0; transform: scale(0.55) rotate(-6deg); }
  15%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.15) rotate(6deg); }
}


/* 光球命中（技能 / 效果伤害） */
.fx-orb-hit {
  position: absolute;
  width: 240px;
  height: auto;
  margin-left: -120px;
  margin-top: -120px;
  animation: fx-orb-hit 600ms ease-out forwards;
  filter: drop-shadow(0 0 16px rgba(150, 200, 255, 0.9));
}
@keyframes fx-orb-hit {
  0%   { opacity: 0; transform: scale(0.4); }
  25%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.3); }
}

/* 光球飞行（技能伤害，从己方领队射向目标） */
.fx-orb {
  position: absolute;
  width: 0;
  height: 0;
  animation: fx-orb-fly 300ms cubic-bezier(0.2, 0.7, 0.35, 1) forwards;
}
.fx-orb img {
  position: absolute;
  width: 140px;
  height: auto;
  left: -70px;
  top: -70px;
  filter: drop-shadow(0 0 16px rgba(150, 200, 255, 0.9));
}
@keyframes fx-orb-fly {
  from { transform: translate(0, 0) scale(0.5); opacity: 0; }
  25%  { opacity: 1; }
  to   { transform: translate(var(--dx, 0px), var(--dy, 0px)) scale(1); opacity: 1; }
}


/* 光球序列帧（40 帧 2s：逐渐放大 → 命中爆散 → 音符飞散 → 消退） */
.fx-orb-seq {
  position: absolute;
  width: 320px;
  height: 320px;
  margin-left: -160px;
  margin-top: -160px;
  background-image: url('/assets/fx/orb-blue-sheet.webp');
  background-repeat: no-repeat;
  background-size: 12800px 256px;
  animation: fx-orb-seq 2s steps(40) forwards;
  filter: drop-shadow(0 0 18px rgba(150, 200, 255, 0.85));
}
@keyframes fx-orb-seq {
  from { background-position: 0 0; }
  to   { background-position: -12800px 0; }
}

/* 碎屑序列帧（24 帧 0.7s） */
.fx-shards-seq {
  position: absolute;
  width: 260px;
  height: 260px;
  margin-left: -130px;
  margin-top: -130px;
  background-image: url('/assets/fx/shards-sheet.webp');
  background-repeat: no-repeat;
  background-size: 6144px 256px;
  animation: fx-shards-seq 700ms steps(24) forwards;
}
@keyframes fx-shards-seq {
  from { background-position: 0 0; }
  to   { background-position: -6144px 0; }
}

/* 兜底：动画层里的空图不显示边框 */
.battle-fx-layer img:not([src]),
.battle-fx-layer img[src=""] {
  display: none !important;
}
.fx-shards-seq,
.fx-orb-hit,
.fx-orb-seq {
  border: 0 !important;
  outline: 0 !important;
}


/* 重返战场后的「结算 / 离开」常驻按钮 */
.result-reopen {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}


/* 背景上的文字可读性：整体压暗背景后，裸在背景上的文字提亮 + 轻微描边阴影 */
/* 直接落在背景上的标题/说明文字：提亮 + 轻微描边，保证可读 */
body[data-view="home"] .page.home .section-title {
  color: #f8f4ff;
  text-shadow: 0 1px 5px rgba(8, 6, 16, 0.65);
}

/* 背景上的步骤说明与页脚文字提亮 */
body[data-view="home"] .page.home .steps .muted,
body[data-view="home"] .page.home .steps p,
body[data-view="home"] .page.home .steps .step-title,
body[data-view="home"] .page.home .footer,
body[data-view="home"] .page.home .footer *,
body[data-view="home"] .page.home > p {
  color: #f2ecfb;
  text-shadow: 0 1px 4px rgba(8, 6, 16, 0.55);
}

/* 「上手三件事」三张小卡与乐队卡的底色偏白，文字保持深色 */
body[data-view="home"] .page.home .band-tile,
body[data-view="home"] .page.home .band-tile *,
body[data-view="home"] .page.home .steps li,
body[data-view="home"] .page.home .steps li * {
  color: inherit;
  text-shadow: none;
}


/* 所有页面：抬头文字、筛选行标签、页脚都直接落在背景上 → 提亮保证可读 */
.page-head .eyebrow {
  color: #ffd7ea;
  text-shadow: 0 1px 4px rgba(8, 6, 16, 0.6);
}

.page-head .page-title {
  color: #fbf7ff;
  text-shadow: 0 2px 8px rgba(8, 6, 16, 0.7);
}

.page-head .page-lead {
  color: #ece5f8;
  text-shadow: 0 1px 5px rgba(8, 6, 16, 0.6);
}

.codex-rarity-row > span,
.codex-filter-row > span,
.codex-sort-row > span,
.filter-label {
  color: #e9e2f6 !important;
  text-shadow: 0 1px 4px rgba(8, 6, 16, 0.55);
}

.footer {
  color: #f0eaf9;
  text-shadow: 0 1px 5px rgba(8, 6, 16, 0.65);
}

.footer * {
  color: #f0eaf9;
}


/* 图鉴搜索框：背景上要看清输入区与占位符 */
.codex-search-row > span {
  color: #e9e2f6 !important;
  text-shadow: 0 1px 4px rgba(8, 6, 16, 0.55);
}

.filter-input {
  background: rgba(255, 255, 255, 0.92);
  border-color: rgba(255, 255, 255, 0.65);
  color: #241c2c;
}

.filter-input::placeholder {
  color: #6d6279;
}

/* 鑷村懡涓€鍑伙細缁撶畻闈㈡澘寮瑰嚭鍓嶅厛鍛婅瘔鐜╁銆岃嚜宸辨槸鎬庝箞娌＄殑銆?*/
/* 「落幕」横幅：底板 UI素材\横幅UI.png（assets/ui/banner.png，由 tools/trim-banner-ui.mjs
   裁到缎带的可视包围盒 1190×118 —— 原图四周有不对称留白，不裁的话字会偏）。
   宽定死、高度按素材比例（aspect-ratio），缎带两端的折角才不会拉变形；
   阴影用 filter:drop-shadow（跟透明通道走），不能用 box-shadow（那会画成矩形黑影）。 */
.death-banner {
  position: fixed;
  left: 50%;
  top: 38%;
  transform: translate(-50%, -50%) scale(0.92);
  z-index: 300;
  width: min(560px, 76vw);
  aspect-ratio: 1190 / 118;
  display: flex;
  align-items: center;
  justify-content: center;
  /* letter-spacing 会在最后一个字后面多留一格，往左补一格才是真居中 */
  padding-left: 6px;
  box-sizing: border-box;
  pointer-events: none;
  background: url('/assets/ui/banner.png') center / 100% 100% no-repeat;
  filter: drop-shadow(0 16px 26px rgba(40, 0, 14, 0.42));
  opacity: 0;
  transition: opacity 180ms ease, transform 220ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
.death-banner.show {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  animation: death-shake 420ms ease-in-out 120ms 2;
}
.death-banner-text {
  font-size: clamp(20px, 4.6vw, 30px);
  font-weight: 900;
  letter-spacing: 6px;
  color: #fff;
  text-shadow: 0 2px 12px rgba(120, 8, 40, 0.6);
}
@keyframes death-shake {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  25% { transform: translate(calc(-50% - 5px), -50%) scale(1.01); }
  75% { transform: translate(calc(-50% + 5px), -50%) scale(1.01); }
}


/* ── 牌堆（左侧竖排：上面对手、下面自己）+ 对手手牌背 + 抽牌/洗牌飞牌动画 ── */
.deck-rail {
  position: fixed;
  left: 12px;
  top: 96px;
  bottom: 104px;
  width: 92px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  z-index: 57;
  pointer-events: none;
}

.deck-pile {
  position: relative;
  width: clamp(70px, 5.4vw, 92px);
  aspect-ratio: 5 / 7;
  filter: drop-shadow(0 12px 22px rgba(0, 0, 0, 0.45));
}

.deck-pile img {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 9px;
  z-index: 2;
}

/* 叠牌厚度：卡背下面露两层边 */
.deck-pile-stack,
.deck-pile-stack::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 9px;
  background: linear-gradient(160deg, #2a2340, #171325);
  border: 1px solid rgba(255, 255, 255, 0.16);
  z-index: 1;
}

.deck-pile-stack {
  transform: translate(-5px, 4px);
}

.deck-pile-stack::after {
  transform: translate(-10px, 8px);
  opacity: 0.7;
}

.deck-pile-count {
  position: absolute;
  right: -8px;
  bottom: -9px;
  z-index: 3;
  min-width: 26px;
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(12, 10, 22, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.24);
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  text-align: center;
}

/* 牌堆摆正（不再斜着），只靠叠牌厚度做出「一摞」的感觉 */
.deck-pile.is-foe,
.deck-pile.is-you {
  transform: none;
}

/* 对手手牌：卡背一行，张数=对手手牌数 */
.foe-hand-row {
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: 34px;
  margin: 0 0 4px;
}

.foe-hand-back {
  display: block;
  width: 22px;
  height: 31px;
  border-radius: 4px;
  object-fit: cover;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.42);
  border: 1px solid rgba(255, 255, 255, 0.16);
}

.foe-hand-count {
  margin-left: 6px;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.52);
}

/* 飞牌幽灵：抽牌 / 洗回牌堆都用它 */
.fly-card-back {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 96;
  border-radius: 9px;
  object-fit: cover;
  pointer-events: none;
  box-shadow: 0 16px 30px rgba(0, 0, 0, 0.5);
  will-change: transform, opacity;
}

@media (max-width: 1180px) {
  .deck-rail { display: none; }
}

/* 洗牌时牌堆自己抖一下：配合飞回去的卡背，看得出「在洗」 */
.deck-pile.is-shuffling img {
  animation: deck-pile-shuffle 0.58s ease-in-out 2;
}

@keyframes deck-pile-shuffle {
  0% { transform: translateX(0) rotate(0deg); }
  25% { transform: translateX(-3px) rotate(-3deg); }
  50% { transform: translateX(2px) rotate(2.5deg); }
  75% { transform: translateX(-2px) rotate(-2deg); }
  100% { transform: translateX(0) rotate(0deg); }
}

/* ── GENERATED: 战斗背景（由 tools/import-battle-backgrounds.mjs 生成，勿手改）── */
/* ── GENERATED: 战斗背景（由 tools/import-battle-backgrounds.mjs 生成，勿手改）── */
/* ── GENERATED: 战斗背景（由 tools/import-battle-backgrounds.mjs 生成，勿手改）── */
/* ── GENERATED: 战斗背景（由 tools/import-battle-backgrounds.mjs 生成，勿手改）── */
/* BEGIN GENERATED: battle backgrounds */
body[data-battle-bg="roppongi"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-roppongi.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="wood"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/battle-hall-wood.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="live-stage"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-live-stage.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="haunted-stage"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-haunted-stage.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="cafe-stage"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-cafe-stage.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="sunset-classroom"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-sunset-classroom.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="station-plaza"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-station-plaza.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="shopping-street"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-shopping-street.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="star-sea"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-star-sea.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="night-rooftop"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-night-rooftop.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="day-gym"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-day-gym.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="tennis-court"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-tennis-court.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="concert-hall-night"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-concert-hall-night.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="night-gym"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-night-gym.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="shopping-street-rain"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-shopping-street-rain.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="waterfront-night"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-waterfront-night.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="chuchu-studio"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-chuchu-studio.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="ring-rehearsal"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-ring-rehearsal.webp') center 54% / cover no-repeat;
}
body[data-battle-bg="where-dreams-begin"] .arena {
  background:
    linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.44)),
    radial-gradient(560px 260px at 50% -10%, rgba(242, 80, 154, 0.12), transparent 65%),
    radial-gradient(420px 220px at 90% 110%, rgba(112, 92, 220, 0.14), transparent 70%),
    url('/assets/bg/bg-where-dreams-begin.webp') center 54% / cover no-repeat;
}
/* END GENERATED: battle backgrounds */

/* ── 对局中收起顶栏（2026-11-05 作者要求恢复）────────────────────
   `battle-hud-hidden` 由 `board.js` 的 `syncBattleChrome()` 按「有对局且未结算」挂上，
   摘掉它的出口有三个（缺一个就会变成「菜单条再也回不来」的老 bug）：
     · `syncBattleChrome()`：`state.over` / 没有 match → remove
     · `stopBattleAnimations()`：结算、视图卸载 → remove
     · `resetBattleLayout()`：`exitBattleMode()` 与 `router.render()`（每页一次）→ remove
   另外 `body.topbar-collapsible`（鼠标悬停唤起那套）已经整块删掉了，别再往回加。 */
body.battle-hud-hidden .topbar {
  transform: translateY(calc(-100% - 10px));
  opacity: 0;
  pointer-events: none;
}

/* 对局页把顶栏让出来的高度吃掉一点，战场别贴着窗口顶边 */
body.battle-hud-hidden .view-host {
  padding-top: 0;
}

/* 矮屏（笔记本 720p 之类）：把战场以外的竖向装饰压薄，尽量一屏放得下 */
@media (max-height: 820px) {
  .battle-bar {
    padding: 6px 14px;
    gap: 6px 12px;
  }
  .battle-page .hand-zone {
    margin-top: 6px;
  }
  .hand-head {
    margin-bottom: 4px;
  }
  .battle-page .hand-strip {
    padding-bottom: 2px;
  }
  .lane-label {
    font-size: 9px;
  }
  .frontline {
    margin: 8px 0;
  }
}

/* 高屏：战场纵向铺满视口，别在下面留一大片空白（矮屏不受影响） */
@media (min-height: 860px) {
  .battle-page .battle-body {
    align-items: stretch;
  }
  .battle-page .arena {
    display: flex;
    flex-direction: column;
    min-height: calc(100vh - 150px);
  }
  .battle-page .side-row {
    flex: 1 1 auto;
  }
  .battle-page .lane {
    flex: 1 1 auto;
  }
}

/* ── 对局历史列表（设置页）── */
.history-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.history-row {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 10px;
  background: var(--paper-soft);
  border: 1px solid var(--line);
}

.history-result {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  background: rgba(36, 28, 44, 0.35);
}

.history-row.is-win .history-result {
  background: linear-gradient(135deg, #ff9ec4, var(--accent));
}

.history-row.is-loss .history-result {
  background: linear-gradient(135deg, #9aa3b5, #6b7488);
}

.history-row.is-draw .history-result {
  background: linear-gradient(135deg, #b9a2ff, #7f6bd6);
}

.history-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.3;
}

.history-main b {
  font-size: 12.5px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.history-main small {
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.history-when {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.history-empty {
  margin: 10px 0 0;
}

/* ── 对局历史：整行可点 + 行内「导出」+ 战报弹窗 ── */
.history-item {
  display: flex;
  align-items: stretch;
  gap: 6px;
}

.history-item .history-row {
  flex: 1 1 auto;
  min-width: 0;
}

/* 行内导出按钮：跟整行同高，别把行撑高 */
.history-export {
  flex: 0 0 auto;
  align-self: center;
  font-size: 11px;
  padding: 2px 6px;
}

.history-row {
  width: 100%;
  text-align: left;
  cursor: pointer;
  transition: transform 0.14s var(--ease), border-color 0.14s, background 0.14s;
}

.history-row:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  background: #fff;
}

.history-when {
  color: var(--accent-ink);
}

.history-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.history-log {
  max-height: 320px;
  overflow: auto;
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--paper-soft);
  border: 1px solid var(--line);
}

.history-log-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 12px;
  line-height: 1.45;
}

.history-log-list .log-turn {
  margin-top: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--muted);
}

.history-log-list .log-line {
  color: var(--ink-soft);
}

.history-log-list .log-line.is-danger {
  color: #d1436f;
}

.history-log-list .log-line.is-success {
  color: #2f9e77;
}

/* ── 手牌/牌组里的单位：攻防被强化显示绿色，被削弱显示红色 ── */
.card-stats .atk.stat-up,
.card-stats .hp.stat-up,
.card-stats .atk .stat-up,
.card-stats .hp .stat-up,
.card-stat-badge b.stat-up {
  color: #2fbf8f;
}

.card-stats .atk.stat-down,
.card-stats .hp.stat-down,
.card-stats .atk .stat-down,
.card-stats .hp .stat-down,
.card-stat-badge b.stat-down {
  color: #e0526c;
}

.card-stat-badge.is-atk b.stat-up,
.card-stat-badge.is-hp b.stat-up {
  color: #2fbf8f;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
}

.card-stat-badge.is-atk b.stat-down,
.card-stat-badge.is-hp b.stat-down {
  color: #e0526c;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
}


/* ── 房间大厅列表 ── */
.room-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

.room-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name code" "meta code";
  gap: 2px 10px;
  padding: 8px 10px;
  border-radius: 10px;
  text-align: left;
  background: var(--paper-soft);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: transform 0.14s var(--ease), border-color 0.14s, background 0.14s;
}

.room-row:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  background: #fff;
}

.room-row strong { grid-area: name; font-size: 12.5px; color: var(--ink); }
.room-row small { grid-area: meta; font-size: 11px; color: var(--muted); }
.room-code {
  grid-area: code;
  align-self: center;
  font-family: ui-monospace, monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--accent-ink);
}
.room-row.is-full { opacity: 0.72; }

/* ── 观战工具条 ── */
.spectate-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 8px;
  padding: 8px 12px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.92);
}

.spectate-tag {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--accent-ink);
}

/* ── 回合提示：中央大字（和「落幕」同款缎带底板，素材 assets/ui/banner.png） ── */
.turn-banner {
  position: fixed;
  left: 50%;
  top: 38%;
  transform: translate(-50%, -50%) scale(0.92);
  width: min(560px, 76vw);
  aspect-ratio: 1190 / 118;
  display: flex;
  align-items: center;
  justify-content: center;
  /* letter-spacing 会在最后一个字后面多留一格，往左补一格才是真居中 */
  padding-left: 4px;
  box-sizing: border-box;
  font-size: clamp(20px, 4.8vw, 31px);
  font-weight: 900;
  letter-spacing: 4px;
  color: #fff;
  text-shadow: 0 2px 10px rgba(120, 8, 40, 0.55);
  background: url('/assets/ui/banner.png') center / 100% 100% no-repeat;
  /* 透明底图：阴影必须跟 alpha 走，box-shadow 会画成矩形黑影 */
  filter: drop-shadow(0 14px 22px rgba(40, 0, 14, 0.34));
  opacity: 0;
  pointer-events: none;
  z-index: 900;
  transition: opacity 0.26s ease, transform 0.26s cubic-bezier(0.2, 0.9, 0.2, 1);
}

.turn-banner.in {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* 大厅排版：左列「我来开房」通栏到底；右列依次是 加入房间 → 房间大厅 → 小游戏分数榜 */
.online-grid.is-lobby-grid {
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
  align-items: start;
}

.online-grid.is-lobby-grid > .online-panel:nth-child(1) {
  grid-column: 1;
  grid-row: 1 / span 3;
}

.online-grid.is-lobby-grid > .online-panel:nth-child(2) {
  grid-column: 2;
  grid-row: 1;
}

.online-grid.is-lobby-grid > .online-panel:nth-child(3) {
  grid-column: 2;
  grid-row: 2;
}

.online-grid.is-lobby-grid > .online-panel:nth-child(4) {
  grid-column: 2;
  grid-row: 3;
}

@media (max-width: 900px) {
  .online-grid.is-lobby-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .online-grid.is-lobby-grid > .online-panel:nth-child(n) {
    grid-column: 1;
    grid-row: auto;
  }
}

/* ── 等匹配时的贪吃蛇 + 2048 ── */
.mini-games {
  /* 榜单放两边、两款游戏在中间：左榜 | 贪吃蛇 | 2048 | 右榜 */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto minmax(0, 1fr);
  gap: 10px;
  align-items: stretch;
  margin: 8px 0 4px;
}

@media (max-width: 720px) {
  .mini-games {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .mini-board-side {
    order: 3;
  }
}

.mini-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 240px;
  min-width: 0;
  max-width: 260px;
}

.mini-board {
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--paper-soft);
  padding: 8px 10px;
  font-size: 11px;
  color: var(--muted);
  align-self: stretch;
  min-width: 0;
}

/* 两侧的榜：把空白吃掉，表格贴满整列 */
.mini-board-side {
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow: auto;
  max-height: 300px;
}

.mini-board-head {
  font-weight: 800;
  color: var(--accent-ink);
  margin-bottom: 4px;
}

.mini-board-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 1px 0;
  color: var(--ink-soft);
}

.mini-board-row b {
  width: 14px;
  color: var(--muted);
  font-weight: 700;
}

.mini-board-row span {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mini-board-row em {
  font-style: normal;
  font-weight: 800;
  color: var(--accent-ink);
}

.mini-board-row.is-mine span,
.mini-board-row.is-mine em {
  color: var(--accent);
}

.mini-board-empty {
  margin: 0;
  opacity: 0.8;
}

.snake-slot {
  margin: 0;
  display: flex;
  justify-content: center;
  flex: 1 1 240px;
  min-width: 0;
}

.snake-wrap,
.g2048-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
  width: 100%;
  max-width: 260px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--paper-soft);
}

.snake-head,
.g2048-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 10.5px;
  color: var(--muted);
}

.snake-score,
.g2048-score {
  font-weight: 800;
  color: var(--accent-ink);
}

.snake-grid {
  display: grid;
  grid-template-columns: repeat(15, 1fr);
  gap: 1px;
  padding: 3px;
  border-radius: 8px;
  background: rgba(36, 28, 44, 0.06);
  aspect-ratio: 1;
  outline: none;
  max-height: 200px;
}

.snake-grid i {
  border-radius: 2px;
  background: rgba(36, 28, 44, 0.05);
}

.snake-grid i.is-body { background: #ffa8c8; }
.snake-grid i.is-head { background: var(--accent); }
.snake-grid i.is-food { background: #6fd6a8; }

.snake-ops {
  display: flex;
  gap: 4px;
  justify-content: center;
}

.snake-ops .btn {
  padding: 2px 8px;
  min-width: 0;
  font-size: 12px;
  line-height: 1.3;
}

.snake-tip {
  margin: 0;
  text-align: center;
  font-size: 10px;
  opacity: 0.75;
}

/* ── 2048（和贪吃蛇并排的小游戏）── */
.g2048-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  padding: 4px;
  border-radius: 8px;
  background: rgba(36, 28, 44, 0.08);
  aspect-ratio: 1;
  outline: none;
  max-height: 200px;
}

.g2048-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 800;
  line-height: 1;
  color: var(--accent-ink);
  background: rgba(36, 28, 44, 0.05);
}

.g2048-tile.is-v2 { background: #fdf1f6; }
.g2048-tile.is-v4 { background: #fbe3ee; }
.g2048-tile.is-v8 { background: #ffc9de; }
.g2048-tile.is-v16 { background: #ffb1cd; }
.g2048-tile.is-v32 { background: #ff97bd; color: #fff; }
.g2048-tile.is-v64 { background: #ff7aab; color: #fff; }
.g2048-tile.is-v128 { background: #f45c9a; color: #fff; font-size: 12px; }
.g2048-tile.is-v256 { background: #e2478c; color: #fff; font-size: 12px; }
.g2048-tile.is-v512 { background: #c93b85; color: #fff; font-size: 12px; }
.g2048-tile.is-v1024 { background: #a8327c; color: #fff; font-size: 11px; }
.g2048-tile.is-v2048 { background: #86286d; color: #fff; font-size: 11px; }
.g2048-tile.is-vbig { background: #5f1c50; color: #fff; font-size: 11px; }

.g2048-ops {
  display: flex;
  gap: 4px;
  justify-content: center;
  flex-wrap: wrap;
}

.g2048-ops .btn {
  padding: 2px 8px;
  min-width: 0;
  font-size: 12px;
  line-height: 1.3;
}

.g2048-tip {
  margin: 0;
  text-align: center;
  font-size: 10px;
  opacity: 0.75;
}

/* ── 新手教程 ── */
.tutorial {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.tut-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}

.tut-hype {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 10px 14px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--paper);
}

.tut-hype-side {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
}

.tut-hype-side b {
  font-size: 20px;
  color: var(--accent-ink);
}

.tut-hype button { margin-left: auto; }

.tut-board {
  display: grid;
  gap: 10px;
}

/* 教程舞台：正式对局那套 boardHTML 直接铺进来 */
.tut-board-stage {
  border-radius: 18px;
  overflow: hidden;
}

.tut-dialog-note {
  margin: 0;
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--paper-soft);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--muted);
}

.tut-lane {
  padding: 10px 12px;
  border-radius: 14px;
  border: 1px dashed var(--line);
  background: var(--paper-soft);
}

.tut-lane.is-highlight,
.tut-hand.is-highlight {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(242, 80, 154, 0.18);
}

.tut-lane-title {
  margin: 0 0 8px;
  font-size: 11px;
  color: var(--muted);
}

.tut-units,
.tut-hand-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 64px;
  align-items: center;
}

.tut-unit,
.tut-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #fff;
  font-size: 12px;
  cursor: pointer;
  text-align: left;
}

.tut-unit b,
.tut-card b {
  color: var(--accent-ink);
  font-size: 14px;
}

.tut-unit span,
.tut-card span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 150px;
}

.tut-unit em {
  font-style: normal;
  font-weight: 800;
  color: #d2402f;
}

.tut-unit i,
.tut-card i {
  grid-column: 1 / -1;
  font-style: normal;
  font-size: 10px;
  color: var(--muted);
}

.tut-unit.is-ready { border-color: var(--accent); }
.tut-unit.is-dead { opacity: 0.4; }
.tut-card.is-selected { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(242, 80, 154, 0.2); }

.tut-hand {
  padding: 10px 12px;
  border-radius: 14px;
  border: 1px dashed var(--line);
  background: var(--paper-soft);
}

/* 右下角对话框 */
.tut-dialog {
  position: fixed;
  right: 18px;
  bottom: 18px;
  width: min(470px, calc(100vw - 36px));
  z-index: 260;
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: 12px;
  /* 叶片框：和 BGM 播放器 / 对战顶部条同一套九宫格素材（slice 160 + fill） */
  border: 34px solid transparent;
  border-image: url('../assets/ui/leaf-panel.png') 160 fill / 34px stretch;
  border-radius: 0;
  padding: 2px 6px 2px 0;
  background: none !important;
  box-shadow: 0 18px 42px rgba(36, 28, 44, 0.24);
}

/* 向导（香澄）立绘：浮在对话框左侧，脚底与对话框底边对齐（比原来再大一号） */
.tut-guide {
  flex: 0 0 auto;
  width: 172px;
  height: 262px;
  margin: -14px 0 -10px -18px;
  pointer-events: none;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.tut-guide-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  object-position: bottom center;
  filter: drop-shadow(0 6px 10px rgba(36, 28, 44, 0.22));
  transition: opacity 160ms ease;
}

.tut-dialog-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

@media (max-width: 640px) {
  .tut-guide { width: 120px; height: 184px; margin-left: -12px; }
}

.tut-dialog-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--accent-ink);
}

.tut-dialog-close {
  border: 0;
  background: transparent;
  font-size: 16px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}

.tut-dialog-body {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--ink-soft);
}

.tut-dialog-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.tut-dialog-goal {
  font-size: 11px;
  color: var(--muted);
}

/* ── 全站公告：顶部跑马灯 ── */
.announce-bar {
  position: relative;
  overflow: hidden;
  height: 30px;
  margin: 0 0 6px;
  border-radius: 10px;
  background: linear-gradient(90deg, rgba(242, 80, 154, 0.16), rgba(126, 96, 220, 0.16));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line));
}

/* 跑马灯：整条轨道一直往左滚，位移正好「一半宽度」→ 首尾接得上，无缝循环 */
.announce-track {
  display: inline-flex;
  align-items: center;
  height: 100%;
  white-space: nowrap;
  will-change: transform;
  animation-name: announce-scroll;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 18s;
}

.announce-piece {
  padding-right: 64px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent-ink);
}

@keyframes announce-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(var(--announce-shift, -50%)); }
}

/* 设置页「关于」卡片 */
.about-title {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}

.about-text {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--ink-soft);
}

/* ── 新手教程：高亮（要明显，不能只是细描边）── */
.tut-pulse {
  animation: tut-pulse 1.1s ease-in-out infinite;
}

@keyframes tut-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(242, 80, 154, 0.35); }
  50% { box-shadow: 0 0 0 7px rgba(242, 80, 154, 0.16); }
}

/* ── 帧数多的光效（威压 V4 极光）：单层 + steps 逐帧，让光真的在流动 ── */
.glow.glow-strip {
  animation-name: glow-strip;
  /* ⚠️ 间隔数必须是「帧数-1」：background-position 的百分比是相对 (图宽-盒宽) 算的，
     12 帧时用 steps(12) 会让每帧偏移只有 0.917 帧宽 → 看到的就是特效在左右滑。 */
  animation-timing-function: steps(var(--glow-steps, 11), end);
  animation-iteration-count: infinite;
  /* steps 动画不能靠 opacity 平衡亮度：这里用正常的叠加上限，保留半透明柔光 */
  opacity: 1;
  background-position: 0 0;
}

@keyframes glow-strip {
  from { background-position: 0 0; }
  to { background-position: 100% 0; }
}


/* ── 按钮底图：来自 UI素材（按钮_白色 / 按钮_粉色，已裁掉透明外边，662×283，圆角≈32）
   用 border-image 9 宫格：四角与边框按原像素保留，只有中间被拉伸 → 不会变形、也不会切掉圆角。
   之前所有「生成的按钮」与毛玻璃/渐变一律停用。 ── */
.btn,
.foe-option,
.prep-deck-choice,
.choice-option,
.mini-actions button,
.tut-dialog-foot .btn {
  border: 0 solid transparent;
  border-width: 5px;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;   /* xxs 图 160×69、圆角≈5：切片 6，最细一档 */
  border-image-width: 5px;
  border-image-repeat: stretch;
  /* 圆角交给底图自己表达；这些残留的底色/投影会在 border-radius:0 时画成直角矩形，
     正好在圆角两侧露出「小方边」，所以这里强制清空 */
  border-radius: 14px;
  background: transparent !important;
  background-color: transparent !important;
  background-image: none !important;
  box-shadow: none !important;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  color: var(--ink);
}

/* 粉色按钮（主操作） */
.btn-primary,
.btn-primary:link,
.btn-danger,
.foe-option.active,
.prep-deck-choice.active {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

/* 悬停 / 按下：只调亮度，不再叠渐变、底色或投影 */
.btn:hover:not(:disabled),
.foe-option:hover,
.prep-deck-choice:hover {
  filter: brightness(1.04);
}

.btn:active:not(:disabled),
.foe-option:active,
.prep-deck-choice:active {
  filter: brightness(0.96);
}

.btn:disabled,
.btn.is-disabled {
  filter: grayscale(0.35) brightness(0.98);
  opacity: 0.72;
}

/* 任何 hover / focus 状态都不要再补底色或投影（否则圆角外侧又会出现直角边） */
.btn:hover,
.btn:focus,
.btn:focus-visible,
.btn:active,
.foe-option:hover,
.foe-option:focus,
.prep-deck-choice:hover,
.prep-deck-choice:focus,
.choice-option:hover,
.choice-option:focus {
  background: transparent !important;
  background-color: transparent !important;
  box-shadow: none !important;
}

/* 输入框/下拉这类不是按钮的控件保持原样；这里只清掉按钮上的毛玻璃残留 */
.btn::before,
.btn::after {
  display: none;
}

/* ── 全站字体统一：中文黑体偏厚重（贴近 UI 素材里的字体观感） ── */
html {
  font-family: var(--font);
  font-synthesis-weight: auto;   /* 幼圆只有 Regular，粗体靠合成 */
}

body,
button,
input,
select,
textarea,
.btn,
.foe-option,
.prep-deck-choice,
.choice-option {
  font-family: var(--font);
  font-weight: 630;   /* 幼圆只有 Regular：字重拉高让合成粗体更明显 */
  letter-spacing: 0.01em;
}

/* 标题与按钮文字再厚一档，和样例图里的粗黑体对齐 */
.hero-title,
.modal-title,
h1,
h2,
h3,
.btn,
.foe-option,
.prep-deck-choice,
.choice-option,
.brand-name,
.tut-dialog-head strong,
[data-tut-title] {
  font-weight: 630;
}

/* 小字（说明/元信息）也加粗一档，保证在浅色底上够显眼 */
.muted,
.small,
.eyebrow,
.hero-marks span,
.tut-dialog-body {
  font-weight: 630;
}

/* hover：白色按钮换成粉色底图（文字转白） */
.btn:hover:not(:disabled),
.btn:focus-visible,
.foe-option:hover,
.prep-deck-choice:hover,
.choice-option:hover,
.mini-actions button:hover {
  border-image-source: url('../assets/ui/btn-pink-xxs.png') !important;
  color: #fff !important;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

/* 文字可读性：细体在浅色底上发灰，给正文加极轻的对比修饰 */
body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.hero-title,
.modal-title,
h1, h2, h3 {
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);
}

.btn,
.foe-option,
.prep-deck-choice,
.choice-option {
  letter-spacing: 0.02em;
}

/* ── 文字描边（包边）：彩色底上的介绍文字用白描边提亮，别让深字糊在粉色上 ── */
.band-motto,
.band-tile strong,
.band-tile small,
.deck-select-tile .deck-select-info small,
.deck-select-tile .deck-select-info em,
.opponent-tagline,
.band-card-desc,
[data-band-desc] {
  text-shadow:
    -1px 0 0 rgba(255, 255, 255, 0.92),
    1px 0 0 rgba(255, 255, 255, 0.92),
    0 -1px 0 rgba(255, 255, 255, 0.92),
    0 1px 0 rgba(255, 255, 255, 0.92),
    0 0 6px rgba(255, 255, 255, 0.55);
}

/* ── 分享按钮：换成 UI素材底图（和白按钮一致，hover 变粉） ── */
.deck-share-link {
  padding: 5px 12px;
  border: 6px solid transparent;
  border-radius: 8px;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;   /* xxs 图 160×69、圆角≈5：切片 6，最细一档 */
  border-image-width: 5px;
  border-image-repeat: stretch;
  background: none;
  box-shadow: none;
  color: var(--ink);
  font-size: 11px;
  font-weight: 630;
  line-height: 1;
}

.deck-share-link:hover,
.deck-share-link:focus-visible {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  background: none;
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

/* ── 图鉴 / 牌组筛选 chip 与图鉴搜索框：换成全站最新那套 UI 素材按钮 ──────────
   素材：assets/ui/btn-{white,pink}-xxs.png（160×69，圆角≈5）→ 9 宫格 slice 6 / border 5px。
   白底深字，悬停 / 选中＝粉底白字，和 .btn / 导航项完全同一口径。
   写在这里（文件末尾）是为了盖掉前面几处旧的 pill / 半透明底色（含 .codex-search-row 的覆盖）。 */
.filter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 3px 11px;
  border: 5px solid transparent;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 5px;
  border-image-repeat: stretch;
  border-radius: 14px;
  background: none !important;
  box-shadow: none !important;
  color: var(--ink);
  font-size: 12px;
  font-weight: 630;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: color 0.16s ease;
}

.filter:hover,
.filter:focus-visible,
.filter.active {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  background: none !important;
  color: #fff;
  font-weight: 630;   /* 选中态别加粗，否则宽度会跳 */
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

/* 图鉴搜索框：同一套白底图，输入区本身不要底色 */
.codex-search-row .filter-input {
  flex: 1 1 auto;
  max-width: 380px;
  padding: 2px 10px;
  border: 5px solid transparent;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 5px;
  border-image-repeat: stretch;
  border-radius: 14px;
  background: none !important;
  box-shadow: none !important;
  color: var(--ink);
  font-size: 13px;
  font-weight: 630;
}

.codex-search-row .filter-input::placeholder {
  color: #7c7189;
}

.codex-search-row .filter-input:focus {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  background: none !important;
  color: #fff;
}

.codex-search-row .filter-input:focus::placeholder {
  color: rgba(255, 255, 255, 0.82);
}

/* ── BGM 播放器里的选项（收起配乐 / 暂停 / 换一首 / 播放模式 / 展开按钮）──
   同样换成 assets/ui/btn-{white,pink}-xxs.png 9 宫格：白底深字，悬停·聚焦·打开＝粉底白字。
   播放模式是 <select>：外面套一层 .bgm-mode-wrap 画底图，select 自己透明（保留系统下拉箭头）。 */
.bgm-collapse,
.bgm-text-btn,
.bgm-reopen {
  padding: 5px 11px;
  border: 5px solid transparent;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 5px;
  border-image-repeat: stretch;
  border-radius: 14px;
  background: none !important;
  box-shadow: none !important;
  color: var(--ink);
  font-size: 11px;
  font-weight: 630;
  letter-spacing: 0.01em;
  cursor: pointer;
}

.bgm-collapse:hover,
.bgm-collapse:focus-visible,
.bgm-text-btn:hover,
.bgm-text-btn:focus-visible,
.bgm-reopen:hover,
.bgm-reopen:focus-visible {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
  background: none !important;
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

.bgm-mode-wrap {
  display: inline-flex;
  flex: 0 1 152px;
  min-width: 104px;
  align-items: center;
  padding: 0 6px;
  border: 5px solid transparent;
  border-image-source: url('../assets/ui/btn-white-xxs.png');
  border-image-slice: 6 fill;
  border-image-width: 5px;
  border-image-repeat: stretch;
  border-radius: 14px;
  background: none;
  box-shadow: none;
}

.bgm-mode-wrap:hover,
.bgm-mode-wrap:focus-within {
  border-image-source: url('../assets/ui/btn-pink-xxs.png');
}

.bgm-mode-wrap:hover .bgm-mode,
.bgm-mode-wrap:focus-within .bgm-mode {
  color: #fff;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

.bgm-mode {
  flex: 1 1 auto;
  min-width: 0;
  height: 26px;
  padding: 0 2px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-size: 10px;
  font-weight: 630;
  cursor: pointer;
}

.bgm-mode:focus {
  outline: none;
}

/* 下拉展开的选项列表：系统弹层是白底，而 select 自己是粉色按钮上的白字，
   不单独指定就会「白字白底」看不见 —— 这里把选项固定成白底深字 */
.bgm-mode option {
  background: #fff;
  color: #2b2233;
  font-weight: 600;
}

.bgm-mode option:checked,
.bgm-mode option:hover {
  background: #ffd9e6;
  color: #b3225a;
}

/* ── 选中（粉底）/ 悬停时，选项里的标题、难度、简介都要转白 ─────────────
   这些卡片（对局准备的对手卡、牌组选择卡）选中后底图换成粉色 UI 按钮，
   如果里面的小字还留着深色/muted 色，在粉底上会糊成一片。 */
.foe-option.active strong,
.foe-option:hover strong,
.prep-deck-choice.active strong,
.prep-deck-choice:hover strong,
.foe-option.active small,
.foe-option:hover small,
.prep-deck-choice.active small,
.prep-deck-choice:hover small,
.foe-option.active .foe-difficulty,
.foe-option:hover .foe-difficulty,
.foe-option.active .foe-tagline,
.foe-option:hover .foe-tagline {
  color: #fff !important;
  text-shadow: 0 1px 2px rgba(120, 20, 60, 0.35);
}

/* 「进阶 / 简单」这类难度标记原本是乐队色（带 !important），选中后同样转白 */
.foe-option.active .foe-difficulty,
.foe-option:hover .foe-difficulty {
  color: #fff !important;
  opacity: 0.95;
}

/* ── 叶片 UI 面板：把所有「圆角白片」换成 UI素材/叶片UI.png ─────────────────
   素材 1024×1024：浅紫双描边 + 右下角星屑。9 宫格 slice 240（≈23%）、边框 42px，
   四角与星屑都在 240 的角块里 → **不裁切、不拉伸**，只有中间平坦区被拉伸。
   原来的白底/阴影/圆角一律关掉，内边距收小，改由 42px 边框充当留白（圆角看着更大）。 */
.hero,
.settings-card,
.deck-select-tile,
.online-panel,
.prep-main,
.prep-side,
.modal-card,
.band-tile,
.ai-deck-preview,
.history-detail,
.inspector,
.mulligan-panel,
.choice-panel,
.seat-card,
.invite-box,
.mini-board {
  border: 42px solid transparent;
  /* 9 宫格关键：slice 必须 ≥ 素材圆角半径（约 36px），并且和 border-width 一起决定绘制比例。
     这里 slice 40 + fill：
       · 四角按 42/40 等比缩放 → 圆角形状不变（不是拉伸）；
       · 描边带 1:1 落在边缘上，不会在卡片内部再出现一圈白框；
       · 内部由 fill 提供（素材内部是均匀白），不会有填充与描边的接缝。 */
  border-image: url('../assets/ui/leaf-panel.png') 160 fill / 42px stretch;
  border-radius: 0;
  background: none !important;
  box-shadow: none !important;
}

/* 边框吃掉的留白从 padding 里扣回来，视觉厚度与原来接近 */
.hero { padding: clamp(2px, 1vw, 8px); }
.settings-card,
.online-panel,
.prep-main,
.prep-side,
.modal-card,
.inspector { padding: 8px 10px; }
.deck-select-tile {
  padding: 8px;
  /* 牌组卡比较小：42px 边框会挤掉卡背、还会在中间再套一圈白框，收到 16px 只当细边框用 */
  border-width: 16px;
  border-image-width: 16px;
}

/* 房间里的座位卡 / 邀请框 / 小游戏榜：中等尺寸用 24px */
.seat-card,
.invite-box,
.mini-board {
  border-width: 24px;
  border-image-width: 24px;
}
.band-tile {
  padding: 4px 8px;
  /* 乐队卡小：42px 边框 + 40px 圆角会把四角切成斜边，收到 20px */
  border-width: 20px;
  border-image-width: 20px;
}
.ai-deck-preview,
.history-detail,
.seat-card,
.invite-box,
.mini-board { padding: 6px 8px; }

/* 换牌 / 做出选择这两个弹窗比整页小一点，边框收到 32px 免得内容太挤 */
.mulligan-panel,
.choice-panel {
  border-width: 32px;
  border-image-width: 32px;
  padding: 4px 6px;
}

/* 细长条（BGM 播放器 / 对局顶部那条）用窄一点的叶片边框，否则一条 60px 高的 bar 装不下 */
.bgm-player,
.battle-bar {
  border: 16px solid transparent;
  border-image: url('../assets/ui/leaf-panel.png') 160 fill / 16px stretch;
  border-radius: 0;
  background: none !important;
  box-shadow: none !important;
}

/* 对战里的卡片**不套叶片**（卡面本身就是框，套叶片会把卡挤小、双层边框很脏），也不加投影 */
.card {
  border: 1px solid rgba(36, 28, 44, 0.14);
  border-image: none;
  border-radius: 13px;
  background: #fffdfb;
  box-shadow: none;
}

/* 大厅 / 在线 的展示区（lobby-stage.webp 那张大图）：圆角向叶片面板看齐，投影去掉
   （.lobby-stage 已在 2026-11-02 移除，只剩首页 .hero-stage） */
.hero-stage {
  border-radius: 16px;
  box-shadow: none;
}

/* 弹窗底部按钮区原来铺了一条白底 → 换个弹窗时就露出一大条白边，改成透明 */
.modal-card .modal-actions,
#modal.modal-host .modal-actions {
  background: transparent !important;
}

/* 叶片面板上不要再叠 hover 描边 / 投影：会和叶片自己的双描边打架，看起来像多了两条线 */
.deck-select-tile:hover,
.band-tile:hover {
  border-color: transparent;
  box-shadow: none;
}

/* 「新建牌组」原来用虚线 1px 边框，压在叶片框上就是两条多余的横线 —— 回实线（叶片自己就是框） */
.deck-select-new {
  border-style: solid;
}

/* 新建牌组要和已有牌组一样高：让网格每一行等高，最后那格自然被撑满 */
.deck-select-grid {
  grid-auto-rows: 1fr;
}

/* 叶片边框占了不少宽度：给音量那行收紧一点，避免「100%」被挤出卡片 */
.setting-row > span:first-child { flex: 1 1 120px; min-width: 110px; }
.setting-volume input[type="range"] { width: clamp(80px, 13vw, 170px); }
.setting-volume output { min-width: 3.2em; }

/* 选择效果那类选项行保持原来的药丸底：以前它也被叶片规则接管，
   悬停时会和粉色按钮 9 宫格打架（四个角冒出粉块、字变白看不见）。 */
.choice-option {
  border: 1px solid var(--line) !important;
  border-image: none !important;
  border-radius: var(--radius-sm) !important;
  background: var(--paper-soft) !important;
  color: var(--ink) !important;
}

.choice-option:hover {
  border-color: var(--accent) !important;
  background: var(--accent-soft) !important;
  color: var(--ink) !important;
}

/* 天梯段位徽章（2026-11-06 第二版）：直接用作者提供的「段位主体 + 居中星位」成品图，不带文字。
   素材 → `assets/ranks/level-<tier>-L<nn>.webp`（160×190），由 `tools/import-rank-badges.ps1` 合成。
   尺寸走 `--rank-badge-w`：默认 64px（座位卡 / 设置页），`.is-compact` 44px（对战页 / 排行榜行）。 */
.rank-badge {
  --rank-badge-w: 64px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  line-height: 0;
}

.rank-badge.is-compact { --rank-badge-w: 44px; }
/* 顶栏战绩条用：22px，别把整条撑高 */
.rank-badge.is-mini { --rank-badge-w: 22px; }

/* 战绩条里的徽章再收一点、去掉投影，避免把 chip 顶高 */
.chip-record .rank-badge { --rank-badge-w: 22px; }
.chip-record .rank-badge-art { filter: none; }

.rank-badge-art {
  display: block;
  width: var(--rank-badge-w);
  height: auto;
  filter: drop-shadow(0 2px 5px rgba(70, 24, 52, 0.28));
}

/* 排行榜里的段位文字仍保留六档配色（图标旁边那一列文字用） */
.rank-text { font-weight: 700; }

.rank-text.rank-novice { color: #5b6472; }
.rank-text.rank-pro { color: #127a56; }
.rank-text.rank-elite { color: #14588f; }
.rank-text.rank-master { color: #8c1f1f; }
.rank-text.rank-grandmaster { color: #4b2a72; }
.rank-text.rank-legend { color: #8a5a00; }

/* ── 天梯规则弹窗（2026-11-04）：段位说明 + 升级分数柱状图 ────────── */
.page-head-tools { display: flex; align-items: center; gap: 10px; }

.ladder-rules { display: grid; gap: 16px; }

.ladder-rule-chart {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper-soft);
  padding: 12px 14px 10px;
}

.rule-chart-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.rule-chart-head b { font-size: 13px; }
.rule-chart-head small { font-size: 11.5px; color: var(--muted); }

/* 绘图区：左侧留出刻度文字的位置 */
.rule-plot {
  position: relative;
  height: 230px;
  margin: 18px 0 4px 46px;
}

.rule-grids { position: absolute; inset: 0; pointer-events: none; }

.rule-grid {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  border-top: 1px dashed rgba(90, 80, 110, 0.18);
}

.rule-grid span {
  position: absolute;
  left: -46px;
  top: -7px;
  width: 40px;
  text-align: right;
  font-size: 10px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* 每级一根柱子 */
.rule-bars {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(51, 1fr);
  align-items: end;
  gap: 2px;
}

.rule-col {
  position: relative;
  height: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.rule-fill {
  display: block;
  width: 100%;
  min-height: 3px;
  border-radius: 3px 3px 1px 1px;
  background: #e6e3ee;
}

.rule-col-novice .rule-fill { background: linear-gradient(180deg, #c9ccd4, #dfe2e8); }
.rule-col-pro .rule-fill { background: linear-gradient(180deg, #4fbf95, #a4e3c8); }
.rule-col-elite .rule-fill { background: linear-gradient(180deg, #4b93cf, #a9d2f2); }
.rule-col-master .rule-fill { background: linear-gradient(180deg, #c0504f, #e6b7b7); }
.rule-col-grandmaster .rule-fill { background: linear-gradient(180deg, #7a56a8, #c8b4e3); }
.rule-col-legend .rule-fill { background: linear-gradient(180deg, #d9a326, #f0d79a); }

/* 锚点柱：描边 + 星标 */
.rule-col.is-anchor .rule-fill { box-shadow: 0 0 0 1.5px var(--accent) inset; }

.rule-star {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: 9px;
  line-height: 1;
  color: var(--accent-ink);
}

/* 底部大段名：6 等分对齐柱子分组 */
.rule-groups {
  display: grid;
  grid-template-columns: repeat(51, 1fr);
  gap: 2px;
  margin-left: 46px;
  margin-top: 10px;
  text-align: center;
}

/* 传说只占最后 1 列，标题用 nowrap 让它自然溢出居中，不挤成一列窄条 */
.rule-group { overflow: visible; white-space: nowrap; }

/* 2026-11-06：六档段位标签上方放作者提供的徽章主体图（与排行榜/座位卡同一套素材） */
.rule-group-badge {
  display: block;
  width: 40px;
  height: auto;
  margin: 0 auto 2px;
  filter: drop-shadow(0 2px 4px rgba(70, 24, 52, 0.22));
}

.rule-group b { display: block; font-size: 12px; }
.rule-group small { font-size: 10px; color: var(--muted); }

.rule-group-novice b { color: #5b6472; }
.rule-group-pro b { color: #127a56; }
.rule-group-elite b { color: #14588f; }
.rule-group-master b { color: #8c1f1f; }
.rule-group-grandmaster b { color: #4b2a72; }
.rule-group-legend b { color: #8a5a00; }

.ladder-rule-text h3 { margin: 12px 0 4px; font-size: 13px; }
.ladder-rule-text h3:first-child { margin-top: 0; }
.ladder-rule-text ul { margin: 0; padding-left: 18px; }
.ladder-rule-text li { font-size: 12.5px; line-height: 1.7; color: var(--ink-soft); }

.modal-ladder-rules .modal-card { max-width: min(920px, 94vw); }

/* ── 手机端布局（2026-11-04）─────────────────────────────────────
   1) 竖屏右侧白边：内容是「比视口宽」的（顶栏 7 个导航 + 战绩条），
      横向溢出后固定背景图盖不到右侧 → 露白。这里锁死横向溢出。
   2) 顶栏在窄屏不再硬撑：导航可横向滑动、战绩条可缩可换行。
   3) 对战沉浸模式（body.battle-immersive）：收掉页脚、压缩内边距，把高度让给战场。 */
html,
body {
  max-width: 100%;
  /* 老浏览器兜底；新浏览器下一行会覆盖成 clip ——
     hidden 会让 body 变成滚动容器，把顶栏的 position: sticky 顶失效，
     16:9 笔记本往下滚一点就看不到主菜单条（2026-11-05 玩家反馈） */
  overflow-x: hidden;
  overflow-x: clip;
}

/* 只在需要的地方放开宽度：.shell 铺满、元素允许收缩；
   注意**不能**给 .view-host 写 max-width:100%，那会把桌面端的 1280 内容宽度顶掉（2026-11-04 作者反馈「变宽了」） */
.shell {
  max-width: 100%;
}

.view-host,
.topbar {
  min-width: 0;
}

@media (max-width: 820px) {
  .topbar {
    height: auto;
    min-height: 56px;
    padding: 6px 10px;
    gap: 8px 10px;
    flex-wrap: wrap;
    align-items: center;
  }

  .brand { min-width: 0; }
  .brand-text small { display: none; }          /* 小屏省掉「星之鼓动」 */
  .brand-text strong { font-size: 14px; white-space: nowrap; }

  /* 导航：一排横向可滑，不撑破视口 */
  .nav {
    order: 3;
    width: 100%;
    margin-left: 0;
    display: flex;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }

  .nav::-webkit-scrollbar { display: none; }

  .nav-link {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 12.5px;
  }

  .top-right {
    margin-left: auto;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* 战绩条：可以换行、不撑宽 */
  .chip-record {
    white-space: normal;
    word-break: break-word;
    max-width: 62vw;
    line-height: 1.35;
    text-align: right;
  }

  .version { display: none; }

  /* 页面主体留白收紧，别把内容挤出视口 */
  .view-host { padding-left: 10px; padding-right: 10px; }
  .page { max-width: 100%; }
}

/* 对战沉浸：页脚不要、内边距更小，横屏时尽量一屏放下 */
body.battle-immersive .footer { display: none; }
body.battle-immersive .view-host { padding: 0; }
body.battle-immersive .topbar { min-height: 0; }

@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .battle-page { padding: 4px; }
}

/* ── 手机紧凑对战（2026-11-04 第五版）：**靠 body.battle-compact 类**，不再靠媒体查询 ──
   之前只写 `@media (orientation: landscape) and (max-height: 560px)`，部分手机浏览器/WebView 匹配不到，
   于是「详情栏没变宽、单位没变大、光效没贴图」全都没生效。
   现在由 JS（`applyCompactBattleLayout()`）判断横屏 + 视口高度并挂类，同时把
   `--unit-w / --lane-h / --card-w / --card-h` 直接写成对战页的内联变量（优先级最高）。 */

body.battle-compact .battle-page {
  /* 单位/手牌尺寸用 vh 自适应：34vh 在 390px 高的手机横屏 ≈ 132px，比原来 88px 大一倍多 */
  --unit-w: clamp(78px, 19.5vh, 108px);
  --lane-h: calc(var(--unit-w) * 1.42);
  --card-w: clamp(38px, 7.4vh, 64px);
  --card-h: calc(var(--card-w) * 1.4);
  padding: 0 4px 4px;
  max-width: 100vw;
}

/* 手机横屏：配乐面板收起（顶栏不再隐藏 —— 2026-11-05 作者要求菜单条常驻） */
body.battle-compact .bgm-player { display: none; }
body.battle-compact .view-host { padding-top: 0; }

/* 战线：压低上下内边距，两条战线各让 50px 出来 */
body.battle-compact .lane-wrap { padding: 0; }
body.battle-compact .lane {
  /* 战线高度 = 单位卡高度 + 一点余量，否则单位上下被裁 */
  min-height: calc(var(--unit-w) * 1.42);
  height: auto;
  padding: 0;
  gap: 2px;
  overflow: visible;
}
body.battle-compact .lane-wrap { min-height: 0; padding: 0; gap: 0; row-gap: 0; }
body.battle-compact .lane { margin: 0; }
body.battle-compact .arena { padding-bottom: 0; }
body.battle-compact .battle-body { margin-top: 0; }
body.battle-compact .frontline { margin-block: 0; }
/* 对策栏在横屏里压成一行小字（内容还在，只是不占高度） */
body.battle-compact .counter-bar {
  font-size: 9px;
  line-height: 1.2;
  padding: 0 4px;
  min-height: 0;
  margin: 0;
}
body.battle-compact .lane-slot,
body.battle-compact .lane-cell { padding-block: 0; }
body.battle-compact .frontline { margin: 0; height: 10px; }
body.battle-compact .hand-zone { padding-top: 0; }

/* 顶栏压薄成一行（可横滑，「结束回合」固定可见） */
body.battle-compact .battle-bar {
  flex-wrap: nowrap;
  overflow-x: auto;
  /* 叶片描边（border-image）在紧凑模式下从 16px 收到 6px，横屏才放得下一屏 */
  border-width: 6px;
  padding: 0 4px;
  gap: 2px 6px;
  font-size: 10.5px;
  line-height: 1.2;
  scrollbar-width: none;
}

body.battle-compact .battle-bar { max-height: 40px; overflow-y: hidden; }
body.battle-compact .battle-bar .btn {
  padding: 2px 7px;
  font-size: 11px;
  line-height: 1.25;
}

body.battle-compact .battle-bar::-webkit-scrollbar { display: none; }
body.battle-compact .battle-bar > * { flex: 0 0 auto; }
body.battle-compact .battle-bar .end-turn { padding: 2px 8px; font-size: 11.5px; }
body.battle-compact .battle-bar kbd { display: none; }

/* 主体：战场 + 宽详情/战报栏 */
body.battle-compact .battle-body {
  margin-top: 2px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 6px;
  align-items: start;
}

body.battle-compact .inspector {
  /* 详情/战报栏：定高 + 内部滚动；字略缩小、面板加高 → 一屏里能看到更多行 */
  height: 52vh;
  min-height: 190px;
  max-height: 52vh;
  overflow-y: auto;
  align-self: start;
  font-size: 10.5px;
  line-height: 1.42;
  padding: 8px;
}

body.battle-compact .inspector h3,
body.battle-compact .inspector h4 { font-size: 12px; }
body.battle-compact .inspector .round-feed-entry { font-size: 10px; }
body.battle-compact .inspector-foot { font-size: 10.5px; }

/* 战场：左侧 92px 留给两枚领队（贴在战线旁边） */
body.battle-compact .arena {
  position: relative;
  /* 战场本身也用 flex 排：两条战线分剩下的高度，手牌固定占底部，谁都不会被裁掉 */
  display: flex;
  flex-direction: column;
  height: calc(100dvh - 50px);
  padding: 2px 4px 0 92px;
  overflow: hidden;
}

body.battle-compact .lane-wrap { flex: 1 1 0; }
/* ⚠️ 竖屏旧规则给过 .you-side .lane-wrap { order: -1 }，在 display:contents 之后它会把
   我方战线顶到最上面（单位看起来"跑到对面场地"）。这里清零，顺序永远是对手在上、我方在下 */
body.battle-compact .you-side .lane-wrap,
body.battle-compact .foe-side .lane-wrap { order: 0; }
body.battle-compact .frontline { flex: 0 0 10px; }
body.battle-compact .hand-zone { flex: 0 0 96px; }

body.battle-compact .side-row { display: contents; }

body.battle-compact .side-row .stage {
  position: absolute;
  left: 2px;
  width: 84px;
  margin: 0;
}

body.battle-compact .foe-side .stage { top: 0; }
body.battle-compact .you-side .stage { bottom: 76px; }

body.battle-compact .stage .stage-head { gap: 3px; }
body.battle-compact .stage .stage-avatar { display: none; }
body.battle-compact .stage .stage-name { font-size: 10.5px; }
body.battle-compact .stage .stage-role { display: none; }
body.battle-compact .stage .stage-hype b { font-size: 18px; }
body.battle-compact .stage .stage-hype small { font-size: 9.5px; }
/* 舞台面板只留名字+热度+段位：内容少了才不会被压成两块叠一起 */
body.battle-compact .stage .stage-meta { display: none; }
body.battle-compact .stage .hype-bar { margin-top: 2px; }
body.battle-compact .stage .stage-rank { font-size: 9px; margin-left: 3px; }
body.battle-compact .stage .hype-bar { height: 4px; }

body.battle-compact .lane-wrap { width: 100%; }
/* 对手手牌背在横屏里不铺开（会卡在场地中间），只留「手牌 N」小字 */
body.battle-compact .foe-hand-row { height: 12px; overflow: hidden; gap: 1px; }
body.battle-compact .foe-hand-back { display: none; }
body.battle-compact .foe-hand-count { font-size: 9px; }
body.battle-compact .lane { min-height: calc(var(--unit-w) * 1.42); }
body.battle-compact .frontline { margin: 0; }
body.battle-compact .frontline span { font-size: 8.5px; padding: 0 7px; }

body.battle-compact .hand-zone { margin-top: 0; }
body.battle-compact .hand-head { font-size: 9.5px; margin-bottom: 1px; }
body.battle-compact .hand-strip { gap: 3px; }
/* 手牌按「一张多宽」硬压：以前是 flex 平分容器宽，10 张时每张 83px，竖向就撑出来 110px。
   同时别裁掉卡面下半截（.hand-strip 默认 overflow: hidden） */
body.battle-compact .hand-slot { max-width: clamp(34px, 6.8vh, 62px); }
/* 老规则 `.battle-page .hand-strip { overflow: hidden }` 会裁掉卡面下半截，这里必须压过它 */
body.battle-compact .hand-strip {
  overflow: visible !important;
  align-items: flex-start;
  height: auto;
}

/* 竖屏手机：战场贴顶、单列（详情折到下面） */
@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .battle-page { margin: 0; padding: 4px 2px 8px; }
  body.battle-immersive .battle-body { grid-template-columns: minmax(0, 1fr); }
  body.battle-immersive .battle-page .inspector { order: 2; }
}

/* ── 手机端布局（2026-11-04）─────────────────────────────────────
   1) 竖屏右侧白边：内容是「比视口宽」的（顶栏 7 个导航 + 战绩条），
      横向溢出后固定背景图盖不到右侧 → 露白。这里锁死横向溢出。
   2) 顶栏在窄屏不再硬撑：导航可横向滑动、战绩条可缩可换行。
   3) 对战沉浸模式（body.battle-immersive）：收掉页脚、压缩内边距，把高度让给战场。 */
html,
body {
  max-width: 100%;
  /* 老浏览器兜底；新浏览器下一行会覆盖成 clip ——
     hidden 会让 body 变成滚动容器，把顶栏的 position: sticky 顶失效，
     16:9 笔记本往下滚一点就看不到主菜单条（2026-11-05 玩家反馈） */
  overflow-x: hidden;
  overflow-x: clip;
}

/* 只在需要的地方放开宽度：.shell 铺满、元素允许收缩；
   注意**不能**给 .view-host 写 max-width:100%，那会把桌面端的 1280 内容宽度顶掉（2026-11-04 作者反馈「变宽了」） */
.shell {
  max-width: 100%;
}

.view-host,
.topbar {
  min-width: 0;
}

@media (max-width: 820px) {
  .topbar {
    height: auto;
    min-height: 56px;
    padding: 6px 10px;
    gap: 8px 10px;
    flex-wrap: wrap;
    align-items: center;
  }

  .brand { min-width: 0; }
  .brand-text small { display: none; }          /* 小屏省掉「星之鼓动」 */
  .brand-text strong { font-size: 14px; white-space: nowrap; }

  /* 导航：一排横向可滑，不撑破视口 */
  .nav {
    order: 3;
    width: 100%;
    margin-left: 0;
    display: flex;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }

  .nav::-webkit-scrollbar { display: none; }

  .nav-link {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 12.5px;
  }

  .top-right {
    margin-left: auto;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* 战绩条：可以换行、不撑宽 */
  .chip-record {
    white-space: normal;
    word-break: break-word;
    max-width: 62vw;
    line-height: 1.35;
    text-align: right;
  }

  .version { display: none; }

  /* 页面主体留白收紧，别把内容挤出视口 */
  .view-host { padding-left: 10px; padding-right: 10px; }
  .page { max-width: 100%; }
}

/* 对战沉浸：页脚不要、内边距更小，横屏时尽量一屏放下 */
body.battle-immersive .footer { display: none; }
body.battle-immersive .view-host { padding: 0; }
body.battle-immersive .topbar { min-height: 0; }

@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .battle-page { padding: 4px; }
}



/* ── 手机端布局（2026-11-04）─────────────────────────────────────
   1) 竖屏右侧白边：内容是「比视口宽」的（顶栏 7 个导航 + 战绩条），
      横向溢出后固定背景图盖不到右侧 → 露白。这里锁死横向溢出。
   2) 顶栏在窄屏不再硬撑：导航可横向滑动、战绩条可缩可换行。
   3) 对战沉浸模式（body.battle-immersive）：收掉页脚、压缩内边距，把高度让给战场。 */
html,
body {
  max-width: 100%;
  /* 老浏览器兜底；新浏览器下一行会覆盖成 clip ——
     hidden 会让 body 变成滚动容器，把顶栏的 position: sticky 顶失效，
     16:9 笔记本往下滚一点就看不到主菜单条（2026-11-05 玩家反馈） */
  overflow-x: hidden;
  overflow-x: clip;
}

/* 只在需要的地方放开宽度：.shell 铺满、元素允许收缩；
   注意**不能**给 .view-host 写 max-width:100%，那会把桌面端的 1280 内容宽度顶掉（2026-11-04 作者反馈「变宽了」） */
.shell {
  max-width: 100%;
}

.view-host,
.topbar {
  min-width: 0;
}

@media (max-width: 820px) {
  .topbar {
    height: auto;
    min-height: 56px;
    padding: 6px 10px;
    gap: 8px 10px;
    flex-wrap: wrap;
    align-items: center;
  }

  .brand { min-width: 0; }
  .brand-text small { display: none; }          /* 小屏省掉「星之鼓动」 */
  .brand-text strong { font-size: 14px; white-space: nowrap; }

  /* 导航：一排横向可滑，不撑破视口 */
  .nav {
    order: 3;
    width: 100%;
    margin-left: 0;
    display: flex;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }

  .nav::-webkit-scrollbar { display: none; }

  .nav-link {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 12.5px;
  }

  .top-right {
    margin-left: auto;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* 战绩条：可以换行、不撑宽 */
  .chip-record {
    white-space: normal;
    word-break: break-word;
    max-width: 62vw;
    line-height: 1.35;
    text-align: right;
  }

  .version { display: none; }

  /* 页面主体留白收紧，别把内容挤出视口 */
  .view-host { padding-left: 10px; padding-right: 10px; }
  .page { max-width: 100%; }
}

/* 对战沉浸：页脚不要、内边距更小，横屏时尽量一屏放下 */
body.battle-immersive .footer { display: none; }
body.battle-immersive .view-host { padding: 0; }
body.battle-immersive .topbar { min-height: 0; }

@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .battle-page { padding: 4px; }
}



/* ── 手机端布局（2026-11-04）─────────────────────────────────────
   1) 竖屏右侧白边：内容是「比视口宽」的（顶栏 7 个导航 + 战绩条），
      横向溢出后固定背景图盖不到右侧 → 露白。这里锁死横向溢出。
   2) 顶栏在窄屏不再硬撑：导航可横向滑动、战绩条可缩可换行。
   3) 对战沉浸模式（body.battle-immersive）：收掉页脚、压缩内边距，把高度让给战场。 */
html,
body {
  max-width: 100%;
  /* 老浏览器兜底；新浏览器下一行会覆盖成 clip ——
     hidden 会让 body 变成滚动容器，把顶栏的 position: sticky 顶失效，
     16:9 笔记本往下滚一点就看不到主菜单条（2026-11-05 玩家反馈） */
  overflow-x: hidden;
  overflow-x: clip;
}

/* 只在需要的地方放开宽度：.shell 铺满、元素允许收缩；
   注意**不能**给 .view-host 写 max-width:100%，那会把桌面端的 1280 内容宽度顶掉（2026-11-04 作者反馈「变宽了」） */
.shell {
  max-width: 100%;
}

.view-host,
.topbar {
  min-width: 0;
}

@media (max-width: 820px) {
  .topbar {
    height: auto;
    min-height: 56px;
    padding: 6px 10px;
    gap: 8px 10px;
    flex-wrap: wrap;
    align-items: center;
  }

  .brand { min-width: 0; }
  .brand-text small { display: none; }          /* 小屏省掉「星之鼓动」 */
  .brand-text strong { font-size: 14px; white-space: nowrap; }

  /* 导航：一排横向可滑，不撑破视口 */
  .nav {
    order: 3;
    width: 100%;
    margin-left: 0;
    display: flex;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }

  .nav::-webkit-scrollbar { display: none; }

  .nav-link {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 12.5px;
  }

  .top-right {
    margin-left: auto;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* 战绩条：可以换行、不撑宽 */
  .chip-record {
    white-space: normal;
    word-break: break-word;
    max-width: 62vw;
    line-height: 1.35;
    text-align: right;
  }

  .version { display: none; }

  /* 页面主体留白收紧，别把内容挤出视口 */
  .view-host { padding-left: 10px; padding-right: 10px; }
  .page { max-width: 100%; }
}

/* 对战沉浸：页脚不要、内边距更小，横屏时尽量一屏放下 */
body.battle-immersive .footer { display: none; }
body.battle-immersive .view-host { padding: 0; }
body.battle-immersive .topbar { min-height: 0; }

@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .battle-page { padding: 4px; }
}

/* ── 手机端布局（2026-11-04）─────────────────────────────────────
   1) 竖屏右侧白边：内容是「比视口宽」的（顶栏 7 个导航 + 战绩条），
      横向溢出后固定背景图盖不到右侧 → 露白。这里锁死横向溢出。
   2) 顶栏在窄屏不再硬撑：导航可横向滑动、战绩条可缩可换行。
   3) 对战沉浸模式（body.battle-immersive）：收掉页脚、压缩内边距，把高度让给战场。 */
html,
body {
  max-width: 100%;
  /* 老浏览器兜底；新浏览器下一行会覆盖成 clip ——
     hidden 会让 body 变成滚动容器，把顶栏的 position: sticky 顶失效，
     16:9 笔记本往下滚一点就看不到主菜单条（2026-11-05 玩家反馈） */
  overflow-x: hidden;
  overflow-x: clip;
}

/* 只在需要的地方放开宽度：.shell 铺满、元素允许收缩；
   注意**不能**给 .view-host 写 max-width:100%，那会把桌面端的 1280 内容宽度顶掉（2026-11-04 作者反馈「变宽了」） */
.shell {
  max-width: 100%;
}

.view-host,
.topbar {
  min-width: 0;
}

@media (max-width: 820px) {
  .topbar {
    height: auto;
    min-height: 56px;
    padding: 6px 10px;
    gap: 8px 10px;
    flex-wrap: wrap;
    align-items: center;
  }

  .brand { min-width: 0; }
  .brand-text small { display: none; }          /* 小屏省掉「星之鼓动」 */
  .brand-text strong { font-size: 14px; white-space: nowrap; }

  /* 导航：一排横向可滑，不撑破视口 */
  .nav {
    order: 3;
    width: 100%;
    margin-left: 0;
    display: flex;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }

  .nav::-webkit-scrollbar { display: none; }

  .nav-link {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 12.5px;
  }

  .top-right {
    margin-left: auto;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* 战绩条：可以换行、不撑宽 */
  .chip-record {
    white-space: normal;
    word-break: break-word;
    max-width: 62vw;
    line-height: 1.35;
    text-align: right;
  }

  .version { display: none; }

  /* 页面主体留白收紧，别把内容挤出视口 */
  .view-host { padding-left: 10px; padding-right: 10px; }
  .page { max-width: 100%; }
}

/* 对战沉浸：页脚不要、内边距更小，横屏时尽量一屏放下 */
body.battle-immersive .footer { display: none; }
body.battle-immersive .view-host { padding: 0; }
body.battle-immersive .topbar { min-height: 0; }

@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .battle-page { padding: 4px; }
}



/* 手机竖屏对战：战场从最顶部开始（和电脑端一致），顶栏已经隐藏 */
@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .view-host {
    padding: 0 6px 8px;
  }

  body.battle-immersive .battle-page {
    margin: 0;
    padding: 4px 2px 8px;
  }

  body.battle-immersive .battle-page .battle-bar {
    margin-top: 0;
    padding: 5px 8px;
    gap: 4px 8px;
    font-size: 11.5px;
  }

  body.battle-immersive .battle-page .battle-body {
    margin-top: 6px;
    grid-template-columns: minmax(0, 1fr);
  }

  /* 竖屏把右侧信息栏折到战场下面，宽度让给战场 */
  body.battle-immersive .battle-page .inspector {
    order: 2;
  }
}

/* 手机横屏卡面数字：花费左上 / 攻击左下 / 生命右下（作者 2026-11-04 指定），
   尺寸跟着卡宽走，小卡上也不会盖住立绘 */
body.battle-compact .card-cost {
  top: 2px;
  left: 2px;
  width: clamp(14px, calc(var(--card-w) * 0.30), 26px);
  height: clamp(14px, calc(var(--card-w) * 0.30), 26px);
  font-size: clamp(9px, calc(var(--card-w) * 0.20), 15px);
  border-radius: 5px;
}

body.battle-compact .hand-slot .unit-atk { left: 1px; bottom: 1px; top: auto; right: auto; }
body.battle-compact .hand-slot .unit-hp { right: 1px; bottom: 1px; top: auto; left: auto; }

/* ── 战报滚动播报条（2026-11-04 作者要求）──────────────────────────────
   **只在手机竖屏**用：战报从「悬浮在战场上的列表」改成顶端一条横向滚动 ticker
   · 固定贴顶、单行 26px，不再挡住战场
   · 整条内容匀速左移、循环（--feed-speed 由 JS 按条目数给 10~30s）
   · 电脑网页（非竖屏）不套这个类，仍是基础 `.round-feed` 的**左边浮动战报窗** */
.round-feed.feed-ticker {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* ★ 基础规则 `.round-feed` 写死了 width: 330px —— 有宽度时 left/right 失效，
     条子只铺到 330px，右边空出 ~100px 接不到屏幕边缘（2026-11-04 作者反馈）。 */
  width: auto;
  max-width: none;
  z-index: 60;
  display: block;
  height: 26px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 0;
  background: linear-gradient(90deg, rgba(16, 12, 28, 0.94), rgba(30, 22, 46, 0.88));
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
  pointer-events: auto;
}

.feed-ticker .feed-ticker-track {
  display: inline-flex;
  align-items: center;
  height: 26px;
  white-space: nowrap;
  animation: feed-ticker-scroll var(--feed-speed, 18s) linear infinite;
  will-change: transform;
}

.feed-ticker .round-feed-entry {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 26px;
  margin: 0;
  padding: 0 16px 0 0;
  border: 0;
  background: none;
  color: #fff;
  font-size: 12px;
  line-height: 26px;
  white-space: nowrap;
  animation: none;
}

.feed-ticker .round-feed-entry b { color: #ffd479; font-weight: 700; }
.feed-ticker .round-feed-entry.is-foe b { color: #ff9ab9; }

@keyframes feed-ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .feed-ticker .feed-ticker-track { animation: none; }
}

/* ── 顶栏那颗「战报 / 详情」按钮（2026-11-04 作者要求）──────────────────
   点一下让右边栏（竖屏是底部详情栏）在「卡牌详情」和「战报」之间切换。
   标签不写死：body.detail-log 开着时显示「详情」（意思是点回去看卡），否则显示「战报」。 */
.inspector-mode-btn .mode-to-detail { display: none; }
body.detail-log .inspector-mode-btn .mode-to-log { display: none; }
body.detail-log .inspector-mode-btn .mode-to-detail { display: inline; }

/* 竖屏对战：BGM 面板收起、详情字号缩小，一屏给战场 */
@media (max-width: 820px) and (orientation: portrait) {
  body.battle-immersive .bgm-player {
    display: none;
  }

  body.battle-immersive .inspector {
    font-size: 11px;
    line-height: 1.45;
    padding: 8px;
  }

  body.battle-immersive .inspector h3,
  body.battle-immersive .inspector h4 { font-size: 12.5px; }

  body.battle-immersive .inspector .round-feed-entry { font-size: 11px; }

  /* 竖屏手牌：把卡宽告诉徽章（--unit-w），三个数字钉在左上/左下/右下 */
  body.battle-immersive .hand-slot {
    --unit-w: 76px;
  }

  body.battle-immersive .hand-slot .card-cost {
    top: 1px;
    left: 1px;
    width: 18px;
    height: 18px;
    font-size: 11px;
  }

  body.battle-immersive .hand-slot .unit-atk {
    left: 1px;
    bottom: 1px;
    top: auto;
    right: auto;
  }

  body.battle-immersive .hand-slot .unit-hp {
    right: 1px;
    bottom: 1px;
    top: auto;
    left: auto;
    transform: none;
  }
}

/* ── 手牌 / 换牌小卡的数字徽章（2026-11-04 作者口径）────────────────────
   花费左上、攻击左下、生命右下；尺寸按**卡宽百分比**（32%）算，
   以前写死 46px，小卡上两个徽章会互相叠住 → 看起来"错位"。 */
.battle-page .hand-slot .card-stat-badge,
.mulligan-card .card-stat-badge,
.mulligan-grid .card .card-stat-badge {
  width: 32%;
  height: auto;
  aspect-ratio: 1 / 1;
  bottom: 2px;
}

.battle-page .hand-slot .card-stat-badge.is-atk,
.mulligan-card .card-stat-badge.is-atk,
.mulligan-grid .card .card-stat-badge.is-atk {
  left: 2px;
  bottom: 2px;
}

.battle-page .hand-slot .card-stat-badge.is-hp,
.mulligan-card .card-stat-badge.is-hp,
.mulligan-grid .card .card-stat-badge.is-hp {
  right: 2px;
  bottom: 2px;
}

.battle-page .hand-slot .card-stat-badge b,
.mulligan-card .card-stat-badge b,
.mulligan-grid .card .card-stat-badge b {
  font-size: clamp(9px, 2.9vw, 19px);
}

.battle-page .hand-slot .card-cost,
.mulligan-card .card-cost,
.mulligan-grid .card .card-cost {
  top: 2px;
  left: 2px;
  width: 24%;
  height: auto;
  aspect-ratio: 1 / 1;
  font-size: clamp(9px, 2.9vw, 16px);
  border-radius: 6px;
}

/* ══ 2026-11-04 第四轮（作者手机竖屏反馈）──────────────────────────────
   ① 换牌界面：卡牌放大 + 花费/攻击/生命三个数字归位
   ② 竖屏对战：底部固定「卡牌详情」栏（以前详情折在战场下方，屏幕里看不到） */

/* ① 换牌卡 -----------------------------------------------------------------
   症状：换牌那几张卡只有 21.6px 宽（`.mulligan-card` 宽吃 `--card-w`，而竖屏的
   `--board-scale` 被压到 0.3），上面的数字还全错位：
   · 花费吃的是 `.card:has(.card-face) .card-cost` 写死的 32×32 星形徽章
     （比整张卡还大，top:13px / left:0 → 掉到卡片下沿外面）
   · 攻/防按卡宽 32% 算，21.6px 的卡上只有 6px，两个数字糊成一团
   现在：卡片宽度自己算（竖屏 4 张一排放得下，桌面最多 104px），
   三个数字按卡宽比例钉在 花费=左上 / 攻击=左下 / 生命=右下。 */
.mulligan-panel {
  --card-w: clamp(72px, calc((100vw - 140px) / 4), 104px);
  /* 卡高必须跟着一起重算：`.battle-page` 上的 `--card-h` 是按它的 21.6px 算好再继承下来的，
     只改 `--card-w` 会得到「73 宽 × 30 高」的横条（卡图被拦腰截断） */
  --card-h: calc(var(--card-w) * 1.4);
}

.mulligan-card {
  width: var(--card-w);
  --unit-w: var(--card-w);
}

/* 花费：左上角星形徽章，尺寸跟卡宽走（选择器权重 0,3,0 + 位置在后 → 盖过写死的 32px） */
.mulligan-card .card .card-cost {
  top: 2px;
  left: 2px;
  width: calc(var(--card-w) * 0.26);
  height: calc(var(--card-w) * 0.26);
  font-size: calc(var(--card-w) * 0.15);
  border-radius: 0;
  background: url("/assets/ui/stat-cost.png") center / 200% 200% no-repeat;
  box-shadow: none;
}

/* 攻击左下 / 生命右下 */
.mulligan-card .card .card-stat-badge {
  width: 30%;
  height: auto;
  aspect-ratio: 1 / 1;
  bottom: 3px;
}

.mulligan-card .card .card-stat-badge.is-atk {
  left: 3px;
  right: auto;
}

.mulligan-card .card .card-stat-badge.is-hp {
  right: 3px;
  left: auto;
}

.mulligan-card .card .card-stat-badge b {
  font-size: calc(var(--card-w) * 0.17);
}

.mulligan-mark {
  bottom: calc(var(--card-w) * 0.30);
  font-size: calc(var(--card-w) * 0.13);
}

/* ② 竖屏底部详情栏 --------------------------------------------------------
   竖屏是单列布局，`.inspector` 被折到战场**下面**（430×932 实测 y≈1092，视口只有 932），
   所以点卡牌 / 划过卡牌虽然更新了详情，屏幕上根本看不到 = 作者说的「详情没了」。
   现在竖屏把它钉在屏幕底部（固定高 + 内部滚动），战场区留出同高下边距，
   手牌不会被永久盖住。
   用的是 JS 挂的 `body.battle-portrait`（不靠 orientation 媒体查询 —— 作者机上
   orientation 匹配不稳，横屏那次就是这么翻的，见 HANDOVER §3.119）。 */
body.battle-portrait .battle-page {
  /* 顶端战报条 26px + 悬浮回合操作栏 46px，战场从它们下面开始 */
  padding-top: 76px;
  padding-bottom: calc(min(38vh, 320px) + 16px);
}

body.battle-portrait .battle-page .inspector {
  /* 详情卡自己定尺寸：`.card` 宽吃 `--card-w`，竖屏只有 21.6px 时卡图会缩成邮票大小。
     别开太大：卡片高度 = 宽 × 1.4，底板只有 38vh，开大会把文字挤到滚动条下面。 */
  --card-w: min(112px, 26vw);
  --card-h: calc(var(--card-w) * 1.4);
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: auto;
  /* 高度跟着内容走（超了才滚）：详情短的时候不会白占一大块 */
  height: auto;
  max-height: min(38vh, 320px);
  margin: 0;
  padding: 10px 12px 16px;
  /* 全局叶片皮肤（.inspector 属于叶片 9 宫格那组）带 `background: none !important`，
     所以这里必须用 !important 才盖得住 —— 否则底部这条详情栏是**全透明**的，字压在战场上没法看 */
  border: 0 !important;
  border-top: 1px solid rgba(255, 255, 255, 0.6) !important;
  border-radius: 16px 16px 0 0;
  background: rgba(255, 255, 255, 0.98) !important;
  box-shadow: 0 -10px 28px rgba(24, 12, 36, 0.32) !important;
  overflow-y: auto;
  z-index: 58;
  transition: max-height 0.22s var(--ease, ease);
  /* ≤1080px 的那条响应式规则把 .inspector 改成了「横排 + 可换行」（给桌面窄窗口用的），
     底部详情栏要竖排：否则卡图、说明、收起按钮会挤成一排 */
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 8px;
}

body.battle-portrait .battle-page .inspector .inspector-detail {
  flex: 0 0 auto;
  align-items: center;
}

body.battle-portrait .battle-page .inspector .log-panel {
  flex: 0 0 auto;
}

/* 详情栏的「收起 / 展开」按钮（只在竖屏出现；标签由 body.battle-portrait.detail-collapsed 切换，重绘也不会错） */
.inspector-toggle {
  display: none;
}

body.battle-portrait .battle-page .inspector-toggle {
  display: block;
  /* sticky 而不是 absolute：详情栏自己是滚动容器，absolute 会跟着内容滚出去 */
  position: sticky;
  top: 0;
  align-self: flex-end;
  margin: -4px 0 0 auto;
  z-index: 2;
  padding: 2px 9px;
  border: 1px solid rgba(36, 28, 44, 0.16);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.96);
  color: var(--accent-ink, #8a2b4a);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
  box-shadow: 0 2px 8px rgba(24, 12, 36, 0.16);
  cursor: pointer;
}

.inspector-toggle-open { display: none; }
body.battle-portrait.detail-collapsed .inspector-toggle-open { display: inline; }
body.battle-portrait.detail-collapsed .inspector-toggle-close { display: none; }

/* 收起状态：缩到屏幕底下，**只留文字**（卡图 / 关键词解释 / 牌库脚注 / 战报列表都收起来） */
body.battle-portrait.detail-collapsed .battle-page .inspector {
  max-height: 96px;
}

/* 收起后只有两三行字，不会再滚 → 按钮改成绝对定位坐到右上角，文字让出位置，省一行高度 */
body.battle-portrait.detail-collapsed .battle-page .inspector-toggle {
  position: absolute;
  top: 6px;
  right: 8px;
  margin: 0;
}

body.battle-portrait.detail-collapsed .battle-page .inspector .inspector-detail {
  padding-right: 54px;
}

body.battle-portrait.detail-collapsed .battle-page .inspector-detail .card,
body.battle-portrait.detail-collapsed .battle-page .inspector .card-keyword-notes,
body.battle-portrait.detail-collapsed .battle-page .inspector .card-mechanic-notes,
body.battle-portrait.detail-collapsed .battle-page .inspector .unit-gains,
body.battle-portrait.detail-collapsed .battle-page .inspector .michelle-hud,
body.battle-portrait.detail-collapsed .battle-page .inspector .log-list,
body.battle-portrait.detail-collapsed .battle-page .inspector .inspector-foot {
  display: none;
}

body.battle-portrait.detail-collapsed .battle-page .inspector .inspector-hint,
body.battle-portrait.detail-collapsed .battle-page .inspector .inspector-detail h3,
body.battle-portrait.detail-collapsed .battle-page .inspector .muted,
body.battle-portrait.detail-collapsed .battle-page .inspector .log-panel h3 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
}

/* 收起后底栏只占 96px，页面下边距跟着收，免得战场下面空一大块 */
body.battle-portrait.detail-collapsed .battle-page {
  padding-bottom: 112px;
}

body.battle-portrait.detail-collapsed #toast {
  bottom: 110px;
}

/* ── 手机竖屏：顶部回合操作栏也做成悬浮栏（和底部详情栏同一套皮肤）+ 紧凑单行 ── */
body.battle-portrait .battle-page .battle-bar {
  position: fixed;
  top: 26px;               /* 顶在战报滚动条下面 */
  left: 0;
  right: 0;
  z-index: 59;
  margin: 0;
  height: 46px;
  padding: 4px 8px;
  /* 叶片皮肤（background / box-shadow 都是 !important）要显式盖掉，换成和详情栏一样的白底 */
  border: 0 !important;
  border-top: 0 !important;
  border-radius: 0 0 16px 16px;
  background: rgba(255, 255, 255, 0.97) !important;
  box-shadow: 0 8px 22px rgba(24, 12, 36, 0.26) !important;
  flex-wrap: nowrap;
  align-items: center;
  /* 3px：又多了一颗「战报 / 详情」按钮，400px 宽的竖屏靠这一像素把整行塞下 */
  gap: 3px;
  font-size: 10.5px;
  line-height: 1.2;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

body.battle-portrait .battle-page .battle-bar::-webkit-scrollbar { display: none; }
body.battle-portrait .battle-page .battle-bar > * { flex: 0 0 auto; }
/* 「点击手牌出牌，点击单位发起攻击」这句最占地方，竖屏收掉（详情栏里本来也有提示）。
   「重开」也收掉：一局打完在结算面板还能重开，对局中间用不到，省下来的宽度刚好让其余按钮排成一行。
   联机的「房间 XXXX」同样收掉（大厅和邀请框都显示着，对局里只是装饰）。 */
body.battle-portrait .battle-page .battle-bar .battle-hint { display: none; }
body.battle-portrait .battle-page .battle-bar .restart-btn { display: none; }
body.battle-portrait .battle-page .battle-bar .room-chip { display: none; }
/* 对手那条也收掉（战场上方本来就写着「手牌 N」），把宽度留给表情 / 退出 */
body.battle-portrait .battle-page .battle-bar .foe-status { display: none; }
/* 联机竖屏只剩 400px：表情只留字（次数在表情面板里还写着）+「退出」收掉
   —— 退出＝本局作废、功能上被「投降」覆盖，收掉以后 ROUND/回合/行动点/倒计时/表情/投降/结束回合
   在 400px 上才排得下（2026-11-04 实测 455 → 394）。 */
body.battle-portrait .battle-page .battle-bar .emote-left { display: none; }
body.battle-portrait .battle-page .battle-bar .quit-room-btn { display: none; }
/* 又多了「战报 / 详情」那颗按钮：竖屏把行动点读数收掉（领队下面那行本来就写着「行动点 N」），
   腾出的 46px 刚好让 ROUND/回合/倒计时/表情/战报/投降/结束回合 在 400px 上排成一行。 */
body.battle-portrait .battle-page .battle-bar .ap-meter { display: none; }
/* 「战报 / 详情」按钮竖屏再紧一点（左右内边距 6px），省出来的像素留给别的按钮 */
body.battle-portrait .battle-page .battle-bar .inspector-mode-btn { padding: 3px 6px; }
body.battle-portrait .battle-page .battle-bar kbd { display: none; }
body.battle-portrait .battle-page .battle-bar .btn { padding: 3px 7px; font-size: 10.5px; line-height: 1.25; }
/* 结束回合最重要：横滑时钉在右边常驻，其余按钮在它下面滑过去。
   （手机窄屏的老规则 `.end-turn { width: 100% }` 要显式改回 auto，否则它会铺满整条栏把别的按钮盖住） */
body.battle-portrait .battle-page .battle-bar .end-turn {
  position: sticky;
  right: 0;
  width: auto;
  min-width: 0;
  margin-left: 2px;
  padding: 4px 8px;
  font-size: 11.5px;
  /* 左侧留一段白边，滑动时别的按钮不会从它下面露半个字 */
  border-left: 8px solid rgba(255, 255, 255, 0.97);
  box-shadow: -8px 0 12px rgba(24, 12, 36, 0.14);
}
body.battle-portrait .battle-page .battle-bar .round-badge { font-size: 9px; letter-spacing: 1px; }
body.battle-portrait .battle-page .battle-bar .round-badge b { font-size: 13px; margin-left: 2px; }
body.battle-portrait .battle-page .battle-bar .turn-badge { padding: 3px 7px; font-size: 10.5px; }
body.battle-portrait .battle-page .battle-bar .ap-meter { gap: 3px; }
body.battle-portrait .battle-page .battle-bar .ap-label { display: none; }
body.battle-portrait .battle-page .battle-bar .pips { gap: 2px; }
body.battle-portrait .battle-page .battle-bar .pips i { width: 6px; height: 6px; }
body.battle-portrait .battle-page .battle-bar .ap-meter b { font-size: 12px; }
body.battle-portrait .battle-page .battle-bar .ap-slot-total { font-size: 9.5px; }
body.battle-portrait .battle-page .battle-bar .turn-timer { padding: 2px 6px; font-size: 10.5px; }

/* 表情面板挂在顶栏下方：竖屏顶栏变成悬浮条以后跟着下移 */
body.battle-portrait .emote-panel {
  top: 80px;
}

/* 卡牌 / 单位上的「划过看详情」：手指横向划过卡牌时，浏览器默认会把它当成滚动手势
   抢走（发 pointercancel → 页面收不到 pointermove，实测一次拖动只有 1 条 pointermove，
   详情永远停在第 1 张）。这里只放行纵向滚动，横向拖动留给详情。 */
.hand-slot,
.unit,
.field-card,
.choice-option {
  touch-action: pan-y;
}

/* 竖屏底部多了详情栏，toast（「对手回合开始」这类提示）别压在栏上 */
body.battle-portrait #toast {
  bottom: calc(min(38vh, 320px) + 14px);
}




/* ── 2026-11-07 对战页「乱晃」收口 ────────────────────────────────
   1) 滚动条出现/消失会让 `100vw` 变 ~15px：页宽（max-width: 97vw）、手牌宽、居中位置全都跟着跳。
      常驻预留滚动条槽位后宽度稳定；不支持 scrollbar-gutter 的浏览器忽略，行为与以前一致。
   2) 平板橡皮筋滚动会把整页拖着上下晃，对战沉浸模式里关掉。 */
@supports (scrollbar-gutter: stable) {
  html {
    scrollbar-gutter: stable;
  }
}

body.battle-immersive,
body.battle-compact {
  overscroll-behavior: none;
}
