/* ==========================================================================
   page.css — 站点骨架样式
   --------------------------------------------------------------------------
   分工：卡面与稀有度在 cards.css，这里只管布局、顶栏、按钮、面板、对话框。

   ⚠️ 页面 CSP 是 style-src 'self'（没有 unsafe-inline）：
     · 不要写 <style> 块，也不要用 style="..." 属性
     · JS 里 setAttribute('style', ...) 会被静默丢掉，动态值请用 CSSOM
   ========================================================================== */

/* --------------------------------------------------------------------------
   变量：配色与尺寸集中在这里，一处改全局
   -------------------------------------------------------------------------- */

:root {
  --bg: #f5f4fa;
  --bg-2: #eceaf5;
  --panel: #ffffff;
  --panel-2: #f7f6fc;
  --text: #1f1b2e;
  --text-2: #3d3550;
  --muted: #6b6780;
  --border: #e4e1ef;
  --border-2: #d5d1e6;

  --accent: #7b5cff;
  --accent-weak: #efeaff;
  --accent-strong: #5b3fd6;

  --ok: #2f9e6b;
  --warn: #e8a33d;
  --danger: #e5484d;
  --danger-strong: #b02a2f;
  --danger-weak: #fdecec;
  --gold: #f0c04a;

  --radius: 16px;
  --radius-sm: 12px;
  --shadow: 0 2px 10px rgba(30, 20, 60, 0.06);
  --shadow-lift: 0 8px 24px -8px rgba(30, 20, 60, 0.22);

  /* 卡牌比例。默认 2:3（用户指定的规格），运行时会被 settings.cardRatio 覆盖。
     为什么需要覆盖：实际资源里 84/93 张是 832x1216（偏 2:3 约 2.6%，肉眼几乎看不出），
     按主力图的真实比例显示能让绝大多数卡完全贴合、不留白边；
     硬按 2:3 则每一张都会留一点边。改这里只影响「没配 cardRatio」时的默认值。 */
  --card-ratio: 2 / 3;

  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --bar-h: 56px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14121d;
    --bg-2: #1b1826;
    --panel: #1e1b2a;
    --panel-2: #241f33;
    --text: #f0eef7;
    --text-2: #ded9ee;
    --muted: #9d98b3;
    --border: #322c47;
    --border-2: #423a5c;
    --accent: #9b83ff;
    --accent-weak: #2a2340;
    --accent-strong: #b6a4ff;
    --danger-weak: #3a2124;
    --shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
    --shadow-lift: 0 8px 24px -8px rgba(0, 0, 0, 0.6);
  }
}

/* --------------------------------------------------------------------------
   基础
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   hidden 属性必须真的能藏住东西
   --------------------------------------------------------------------------
   为什么需要一条 `!important` 的规则：`hidden` 属性靠的是 UA 样式表里的
   `[hidden] { display: none }`，而**作者样式表里任何一条 display 都能盖掉它**
   —— 不看优先级，UA 样式表整个来源就更弱。本页的大图正好踩中：
   `.card-dialog-img` 与 `.card-dialog-video` 都写了 `display: block`，
   于是 `el.hidden = true` 一点作用都没有，静态图与动态卡面就同时显出来了
   （用户 2026-09-19 截图里那一摞）。
   把 hidden 提成不可覆盖的规则，以后每加一个带 display 的类都不用重新踩一次。
   -------------------------------------------------------------------------- */

[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--text);
  font: 15px/1.6 system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* 顶栏：桌面固定，窄屏换行 */
.bar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--panel) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--border);
}

.bar-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 1rem;
  min-height: var(--bar-h);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  text-decoration: none;
  color: var(--text);
  font-weight: 700;
  padding: 0.35rem 0;
  flex: 0 0 auto;
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font-size: 0.9rem;
}

.brand-text {
  font-size: 1rem;
}

.nav {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  flex: 1 1 auto;
  flex-wrap: wrap;
}

.nav-link {
  padding: 0.4rem 0.7rem;
  border-radius: 999px;
  text-decoration: none;
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 600;
  white-space: nowrap;
}

.nav-link:hover {
  color: var(--text);
  background: var(--panel-2);
}

.nav-on {
  color: var(--accent-strong);
  background: var(--accent-weak);
}

.bar-right {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
}

.cur-chip,
.warn-chip {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  white-space: nowrap;
}

.cur-chip {
  background: var(--accent-weak);
  color: var(--accent-strong);
}

.warn-chip {
  background: #fff2d6;
  color: #7a5200;
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --------------------------------------------------------------------------
   碎片
   -------------------------------------------------------------------------- */

.shard-chip {
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  border: 1px solid var(--border-2);
  background: var(--panel-2);
  color: var(--text-2);
  cursor: pointer;
  white-space: nowrap;
}

.shard-chip:hover {
  border-color: var(--accent);
  color: var(--accent-strong);
}

.shard-group {
  padding: 0.7rem 0.85rem;
}

.shard-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
}

.shard-count {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
  min-width: 6rem;
}

.shard-num {
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.shard-unit {
  font-size: 0.78rem;
  color: var(--muted);
}

.shard-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  flex: 1 1 auto;
  justify-content: flex-end;
}

.shard-hint {
  font-size: 0.76rem;
  color: var(--muted);
}

.shard-hint-off {
  color: var(--warn);
}

/* 重复卡的角标与结果摘要 */
.badge-dup {
  position: absolute;
  top: 8px;
  right: -2px;
  z-index: 6;
  font-size: 0.62rem;
  font-weight: 700;
  padding: 0.12rem 0.4rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent-strong);
  border: 1px solid var(--accent);
  white-space: nowrap;
  pointer-events: none;
}

.badge-dup.small,
.badge-new.small {
  position: static;
  font-size: 0.6rem;
}

/* 重复的卡不用灰掉，只做一点边框提示；灰掉会让人以为「没拿到」 */
.result-dup .card {
  border-color: var(--accent);
}

/* --------------------------------------------------------------------------
   特殊工艺（闪卡）的角标与切换胶囊
   --------------------------------------------------------------------------
   位置与光效在 cards.css，这里只放「文字标签」这一层。三种工艺各自一个颜色，
   和卡名颜色对应（银灰 / 金 / 红）。 */
.badge-foil {
  position: absolute;
  left: -2px;
  top: 8px;
  z-index: 7;
  font-size: 0.62rem;
  font-weight: 700;
  padding: 0.12rem 0.4rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  background: rgba(10, 6, 20, 0.72);
  white-space: nowrap;
  pointer-events: none;
}

.badge-foil-flat {
  color: #c9ced6;
}

.badge-foil-full {
  color: #ffd257;
}

.badge-foil-shatter {
  color: #ff4d4d;
}

/* 抽卡记录里的工艺标签：inline（不是浮在卡片上），用同三套颜色 */
.badge-foil-hist {
  font-size: 0.62rem;
  font-weight: 700;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  white-space: nowrap;
}

/* 抽到闪卡的结果格子：给边框一点颜色呼应，但不抢卡面本身的效果 */
.result-foil .card {
  border-color: currentColor;
}

/* 工艺筛选条（图鉴工具栏下面一行） */
.foil-filter {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin: 0 0 0.9rem;
}

/* 稀有度筛选条：与工艺筛选条同款，只是多一行 —— 两行之间留小一点的间距，
   让它们读起来像「一块筛选区」，而不是两块各自独立的东西 */
.rarity-filter {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin: 0 0 0.45rem;
}

/* 选中时用档位自己的颜色（与卡面角标一致）：SR 蓝 / SSR 紫 / UR 金 / SP 红 / HR 强调色 */
.rarity-chip-SR.is-on { border-color: #5b8def; background: rgba(91, 141, 239, 0.16); color: #5b8def; }
.rarity-chip-SSR.is-on { border-color: #c46bd8; background: rgba(196, 107, 216, 0.16); color: #c46bd8; }
.rarity-chip-UR.is-on { border-color: #e8a33d; background: rgba(232, 163, 61, 0.18); color: #b8860b; }
.rarity-chip-\?\?\?.is-on { border-color: #e5484d; background: rgba(229, 72, 77, 0.16); color: #c62828; }
.rarity-chip-HR.is-on { border-color: var(--accent); background: var(--accent-weak); color: var(--accent-strong); }

.foil-filter-key {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
}

/* 工艺胶囊：筛选条与大图里的切换按钮共用 */
.foil-chip {
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.22rem 0.6rem;
  border: 1px solid var(--border-2);
  border-radius: 999px;
  background: var(--panel);
  color: var(--text-2);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.foil-chip:hover {
  border-color: var(--accent);
}

.foil-chip.is-on {
  border-color: var(--accent);
  background: var(--accent-weak);
  color: var(--accent-strong);
}

/* 各自的颜色（和卡名一致）：未选中时也认得出是哪一种工艺 */
.foil-chip-flat.is-on {
  border-color: #c9ced6;
  background: rgba(201, 206, 214, 0.16);
  color: #c9ced6;
}

.foil-chip-full.is-on {
  border-color: #ffd257;
  background: rgba(255, 210, 87, 0.16);
  color: #b8860b;
}

.foil-chip-shatter.is-on {
  border-color: #ff4d4d;
  background: rgba(255, 77, 77, 0.16);
  color: #c62828;
}

.foil-chip-count {
  font-size: 0.7rem;
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

/* 一种工艺都没拥有时的说明（大图里） */
.card-dialog-foil-hint {
  font-size: 0.76rem;
  color: var(--muted);
  max-width: 24rem;
}

/* 抽卡页上那行特殊工艺说明（概率 + 门槛） */
.foil-rate-line {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
  color: var(--muted);
  font-size: 0.8rem;
}

.foil-rate-key {
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  font-weight: 600;
}

.foil-rate-note {
  opacity: 0.85;
}

.result-summary,
.hist-summary {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  margin-top: 0.7rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border-2);
  font-size: 0.83rem;
  color: var(--text-2);
}

.hist-summary {
  margin-top: 0;
  padding: 0.5rem 0.75rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.result-link {
  color: var(--accent-strong);
  font-weight: 600;
  text-decoration: none;
  margin-left: auto;
}

.result-link:hover {
  text-decoration: underline;
}

/* 系列分组 */
.series-chip {
  display: inline-block;
  font-size: 0.82rem;
  font-weight: 700;
  padding: 0.12rem 0.6rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent-strong);
  border: 1px solid var(--accent);
}

.group-note {
  font-size: 0.72rem;
  color: var(--muted);
}

@media (prefers-color-scheme: dark) {
  .warn-chip {
    background: #3d2f10;
    color: #f0c04a;
  }
}

/* --------------------------------------------------------------------------
   主区域
   -------------------------------------------------------------------------- */

.view {
  flex: 1 1 auto;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 1.25rem 1rem 2.5rem;
}

/* 首页封面：作为整页背景铺一层，上面压半透明遮罩保证可读性 */
.view.has-cover {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  position: relative;
}

.view.has-cover::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 72%, transparent), color-mix(in srgb, var(--bg) 94%, transparent));
  z-index: 0;
  pointer-events: none;
}

.view.has-cover > * {
  position: relative;
  z-index: 1;
}

.sec {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.sec-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.sec-title {
  margin: 0;
  font-size: 1.3rem;
  letter-spacing: -0.01em;
}

.sec-desc {
  margin: 0.2rem 0 0;
  color: var(--muted);
  font-size: 0.88rem;
}

.sec-extra {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  flex-wrap: wrap;
}

.pill {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.22rem 0.65rem;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   按钮
   -------------------------------------------------------------------------- */

.btn {
  font: inherit;
  font-weight: 600;
  font-size: 0.86rem;
  padding: 0.42rem 0.9rem;
  border-radius: 10px;
  border: 1px solid var(--border-2);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.08s ease;
  white-space: nowrap;
}

.btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent-strong);
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.btn.primary:hover:not(:disabled) {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: #fff;
}

.btn.ghost {
  background: transparent;
  border-color: transparent;
  color: var(--muted);
}

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

.btn.danger {
  color: var(--danger);
}

.btn.danger:hover:not(:disabled) {
  border-color: var(--danger);
  color: var(--danger);
}

.btn.small {
  font-size: 0.78rem;
  padding: 0.28rem 0.6rem;
}

.btn.big {
  font-size: 1rem;
  padding: 0.7rem 1.6rem;
  border-radius: 12px;
}

/* --------------------------------------------------------------------------
   抽卡页
   -------------------------------------------------------------------------- */

.rate-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 0.5rem;
}

.rate-cell {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.6rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
}

.rate-num {
  font-size: 1.05rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.rate-sub {
  font-size: 0.72rem;
  color: var(--muted);
}

.rate-off {
  opacity: 0.5;
}

/* （这里原本还有一条 .draw-actions 的「面板」样式：抽卡键还单独占一块卡片时用的。
   按钮挪到主视觉下面之后它已经没人用了，留着只会把面板背景 / 边框 / 内边距
   悄悄加到新的一行上 —— 两条同名规则叠在一起，改样式时很难看出是哪条生效。） */

.draw-have {
  color: var(--muted);
  font-size: 0.85rem;
  margin-left: auto;
}

.result-box {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.85rem;
  box-shadow: var(--shadow);
}

.result-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.7rem;
  font-weight: 600;
}

.result-time {
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 400;
}

.result-head .btn {
  margin-left: auto;
}

/* --------------------------------------------------------------------------
   卡片网格：自适应列数，不写死
   -------------------------------------------------------------------------- */

.grid {
  display: grid;
  gap: 0.7rem;
}

.grid.cards {
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
}

.grid.cards .card-lg {
  min-width: 0;
}

@media (min-width: 720px) {
  .grid.cards {
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  }
}

/* --------------------------------------------------------------------------
   分组（卡池一览 / 图鉴）
   -------------------------------------------------------------------------- */

.group {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.85rem;
  box-shadow: var(--shadow);
}

.group-warn {
  border-color: var(--warn);
}

.group-head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
}

.group-meta {
  color: var(--muted);
  font-size: 0.82rem;
}

.pool-tabs {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}

.tab {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
}

.tab-on {
  background: var(--accent-weak);
  border-color: var(--accent);
  color: var(--accent-strong);
}

/* --------------------------------------------------------------------------
   进度条
   -------------------------------------------------------------------------- */

.progress {
  height: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent), var(--gold));
  border-radius: 999px;
  transition: width 0.3s ease;
}

/* --------------------------------------------------------------------------
   动态卡面（HR）
   --------------------------------------------------------------------------
   视频只在大图里播（网格里挂两百多个 <video> 必然卡死），网格与结果区只标一个
   「动」字。自动播放的三个前提（muted / loop / playsinline）写在 page.html 上。
   与静态卡面是**切换**关系（谁显示由 page.js 的 showVideo 一条判据决定），
   所以两者的盒子尺寸必须一致，这里用与 .card-dialog-img 相同的两个上限。 */

.card-dialog-video {
  /* 尺寸必须和 .card-dialog-img **一模一样**：两者是切换关系，切换时盒子不该跳。
     ⚠️ 不要写成 width/height: 100% —— 静态图藏起来之后，检视容器
     （`.card-dialog-card`，inline-block）就只剩视频这一个在流内的孩子，
     而 `height: 100%` 在由内容撑高的父元素上是循环引用，结果高度塌成 0。
     这里跟静态图一样用「固有比例 + 两个上限」，视频自己的分辨率就是比例来源
     （没就绪时浏览器拿 poster 的比例，也就是静态卡面的比例）。 */
  display: block;
  width: auto;
  max-width: min(80vw, 21rem);
  max-height: 56vh;
  border: 1px solid var(--border);
  border-radius: 10px;
  object-fit: contain;
  background: #000;
}

/* 网格/结果区里的「这张有动态卡面」角标 */
.badge-hr {
  position: absolute;
  top: 8px;
  left: -2px;
  z-index: 7;
  padding: 0.05rem 0.34rem;
  border-radius: 999px;
  background: rgba(123, 92, 255, 0.92);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   红碎补偿（抽到已有的红碎 -> 返券 + 下次十连必出同档未拥有的红碎）
   -------------------------------------------------------------------------- */

/* 顶栏那个「欠着几张」的提示：用红碎的颜色，和 SP 保底那个 pill 区分开 */
.pill-comp {
  border-color: #b02a2f;
  background: rgba(229, 72, 77, 0.12);
  color: #b02a2f;
  font-weight: 600;
}

/* 结果格子上标出「这一张是补偿补的」 */
.badge-comp {
  position: absolute;
  top: 8px;
  left: -2px;
  z-index: 7;
  padding: 0.12rem 0.4rem;
  border-radius: 999px;
  background: rgba(229, 72, 77, 0.94);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
}

.result-comp .card {
  border-color: #b02a2f;
}

/* --------------------------------------------------------------------------
   特殊工艺的收集进度（图鉴顶部，三行：平闪 / 全闪 / 红碎）
   -------------------------------------------------------------------------- */
.foil-progress {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.foil-progress-head {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.foil-progress-title {
  font-weight: 700;
  font-size: 0.86rem;
}

.foil-progress-note {
  color: var(--muted);
  font-size: 0.76rem;
  line-height: 1.6;
}

/* 一行 = 工艺名 / 张数 / 百分比 / 进度条，四列对齐（窄屏时进度条落下一行） */
.foil-progress-row {
  display: grid;
  grid-template-columns: 3.2rem 6.5rem 3.4rem 1fr;
  align-items: center;
  gap: 0.5rem;
}

.foil-progress-key {
  font-size: 0.8rem;
  font-weight: 700;
}

/* 与卡名、工艺胶囊同一套颜色，扫一眼就知道是哪一门 */
.foil-key-flat {
  color: #c9ced6;
}

.foil-key-full {
  color: #b8860b;
}

.foil-key-shatter {
  color: #e5484d;
}

.foil-progress-num {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--text-2);
}

.foil-progress-pct {
  font-size: 0.78rem;
  color: var(--muted);
  text-align: right;
}

.foil-progress-bar {
  height: 6px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}

.foil-progress-fill {
  height: 100%;
  width: 0;
  border-radius: 999px;
  transition: width 0.3s ease;
}

.foil-fill-flat {
  background: linear-gradient(90deg, #9aa3b0, #c9ced6);
}

.foil-fill-full {
  background: linear-gradient(90deg, #c99a2e, #ffd257);
}

.foil-fill-shatter {
  background: linear-gradient(90deg, #b02a2f, #ff6b6f);
}

.foil-progress-hint {
  color: var(--ok);
  font-size: 0.78rem;
  font-weight: 600;
}

@media (max-width: 560px) {
  .foil-progress-row {
    grid-template-columns: 3.2rem 6.5rem 3.4rem;
  }

  .foil-progress-bar {
    grid-column: 1 / -1;
  }
}

/* --------------------------------------------------------------------------
   抽卡记录
   -------------------------------------------------------------------------- */

.hist {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}

.hist-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.75rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.86rem;
}

.hist-row:last-child {
  border-bottom: 0;
}

.hist-row:nth-child(even) {
  background: var(--panel-2);
}

.hist-idx {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 0.78rem;
  min-width: 4.5rem;
}

.hist-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hist-time {
  color: var(--muted);
  font-size: 0.76rem;
  white-space: nowrap;
}

/* 记录指向的卡已不在名册里 —— 明确标出来，不静默变成空 */
.hist-missing {
  background: var(--danger-weak) !important;
  color: var(--danger-strong);
}

/* --------------------------------------------------------------------------
   面板与提示
   -------------------------------------------------------------------------- */

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.9rem;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.panel-title {
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.panel-hint {
  margin: 0;
  color: var(--muted);
  font-size: 0.83rem;
  line-height: 1.6;
}

.panel-warn {
  border-color: var(--warn);
  background: color-mix(in srgb, var(--warn) 8%, var(--panel));
}

.panel-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
}

.panel-out {
  white-space: pre-wrap;
  font-family: var(--mono);
  font-size: 0.76rem;
  line-height: 1.55;
  color: var(--text-2);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.7rem;
  max-height: 15rem;
  overflow: auto;
  word-break: break-word;
}

.panel-out:empty {
  display: none;
}

.panel-out-err {
  border-color: var(--danger);
  color: var(--danger-strong);
  background: var(--danger-weak);
}

.issue-list {
  margin: 0;
  padding-left: 1.2rem;
  font-size: 0.85rem;
  line-height: 1.7;
}

/* 空状态 */
.empty {
  background: var(--panel);
  border: 1px dashed var(--border-2);
  border-radius: var(--radius);
  padding: 1.6rem 1.2rem;
  text-align: center;
}

.empty-title {
  font-weight: 700;
  margin-bottom: 0.4rem;
}

.empty-lines {
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.7;
}

.empty .panel-actions {
  justify-content: center;
  margin-top: 0.8rem;
}

/* --------------------------------------------------------------------------
   表单
   -------------------------------------------------------------------------- */

.field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

/* 后台里一组同类的字段：两列起排，窄屏自动落回一列 */
.panel-sub {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.6rem;
}

/* 一组复选框（例如「哪些档位弹表情包」） */
.checks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
}

.check {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  cursor: pointer;
}

.check input[type='checkbox'] {
  width: auto;
  margin: 0;
}

.field-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
}

input[type='text'],
input[type='password'],
input[type='number'],
textarea,
select {
  font: inherit;
  font-size: 0.88rem;
  padding: 0.42rem 0.6rem;
  border: 1px solid var(--border-2);
  border-radius: 9px;
  background: var(--panel);
  color: var(--text);
  width: 100%;
  min-width: 0;
}

input:focus,
textarea:focus,
select:focus {
  outline: 2px solid var(--accent-weak);
  border-color: var(--accent);
}

textarea {
  resize: vertical;
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.5;
}

.weight-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.5rem;
}

.alert {
  background: var(--danger-weak);
  border: 1px solid var(--danger);
  color: var(--danger-strong);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.7rem;
  font-size: 0.83rem;
  white-space: pre-wrap;
}

/* --------------------------------------------------------------------------
   后台的卡牌表
   -------------------------------------------------------------------------- */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.84rem;
}

.table th {
  text-align: left;
  font-size: 0.75rem;
  color: var(--muted);
  font-weight: 600;
  padding: 0.45rem 0.55rem;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.table td {
  padding: 0.4rem 0.55rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.table tr:last-child td {
  border-bottom: 0;
}

.table input,
.table select {
  padding: 0.28rem 0.45rem;
  font-size: 0.82rem;
}

.cell-img {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cell-actions {
  display: flex;
  gap: 0.25rem;
  flex-wrap: wrap;
}

.cell-warn {
  color: var(--danger);
  font-size: 0.72rem;
}

.row-hidden {
  opacity: 0.55;
}

/* --------------------------------------------------------------------------
   对话框
   -------------------------------------------------------------------------- */

.dialog {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0;
  background: var(--panel);
  color: var(--text);
  max-width: 30rem;
  width: calc(100% - 2rem);
  box-shadow: 0 20px 60px -20px rgba(20, 12, 40, 0.4);
}

.dialog.wide {
  max-width: 60rem;
}

.dialog::backdrop {
  background: rgba(20, 12, 40, 0.42);
  backdrop-filter: blur(2px);
}

/*
 * 拖动检视时**临时关掉整屏的背景模糊**。
 *
 * 模层的 backdrop-filter 是整块视口大小的一层，弹层里任何重绘都会让它重新模糊
 * 一遍整个页面（背后还是密密麻麻的图鉴卡片）。卡片每帧都在倾斜，于是每帧都重算 ——
 * 这是「按住拖一下整页卡住」里最贵的那一步。
 * 拖动只持续几秒，而模糊在弹层遮罩下面本来就看不太出来，所以直接让路。
 *
 * 用 `:has()` 选中「弹层里有正在拖的卡」这个状态；不支持 `:has()` 的浏览器
 * 会整条丢掉这条规则，也就是退回原来的行为（只是可能有点卡），不会变丑。
 */
.card-dialog:has(.is-inspecting)::backdrop {
  backdrop-filter: none;
}

/* 顶栏的毛玻璃同理：它在弹层遮罩下面，本来就被压暗了，
   但浏览器仍要维护一整条全宽的背景模糊 —— 弹层开着时它是纯浪费。 */
body:has(dialog[open]) .bar {
  backdrop-filter: none;
}

.dialog-form {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1.1rem;
  margin: 0;
}

.dialog-title {
  margin: 0;
  font-size: 1.05rem;
}

.dialog-hint {
  margin: 0;
  color: var(--muted);
  font-size: 0.84rem;
  line-height: 1.6;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.2rem;
}

.editor-body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  max-height: 62vh;
  overflow-y: auto;
}

/* --------------------------------------------------------------------------
   Toast 与页脚
   -------------------------------------------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  z-index: 80;
  max-width: min(90vw, 34rem);
  padding: 0.6rem 1rem;
  border-radius: 999px;
  background: var(--text);
  color: var(--bg);
  font-size: 0.86rem;
  font-weight: 600;
  box-shadow: var(--shadow-lift);
  text-align: center;
}

.toast-ok {
  background: var(--ok);
  color: #fff;
}

.toast-error {
  background: var(--danger);
  color: #fff;
  border-radius: var(--radius-sm);
}

.foot {
  border-top: 1px solid var(--border);
  background: var(--panel);
}

.foot-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0.85rem 1rem;
  display: flex;
  gap: 0.75rem;
  justify-content: space-between;
  flex-wrap: wrap;
  color: var(--muted);
  font-size: 0.78rem;
}

.foot-meta {
  font-variant-numeric: tabular-nums;
}

/* 页脚右侧：图片缓存入口 + 元信息 */
.foot-right {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* 缓存对话的状态行：数字要对齐，长句子要能换行 */
.cache-stat {
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--text);
  font-size: 0.86rem;
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
}

/* 缓存对话的按钮略大一点：这是个「要等一会儿」的动作 */
#cache-dialog .dialog-actions {
  flex-wrap: wrap;
}

#cache-dialog .dialog-actions .btn {
  flex: 1 1 auto;
  min-width: 7rem;
}

/* --------------------------------------------------------------------------
   顶栏的「加载图片」一键按钮
   --------------------------------------------------------------------------
   它是一颗**会变长的按钮**：文案从「加载图片」变成「加载中 42/158」。
   数字要等宽，否则每张图跳一下、整条顶栏跟着抖。 */
.cache-load {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 全部图都在本地了：做成低调的「已完成」态，别再抢注意力 */
.cache-load.is-done {
  color: var(--accent-strong);
  border-color: var(--accent);
  background: var(--accent-weak);
}

.cache-load:disabled {
  cursor: default;
}

/* SP 保底生效中的提示：和普通计数 pill 区分开，一眼能认出「现在有保底」 */
.pill-pity {
  background: var(--accent-weak);
  color: var(--accent-strong);
  border-color: var(--accent);
  font-weight: 700;
}

/* --------------------------------------------------------------------------
   图鉴：搜索栏 + 可收起的系列组 + 点开看大图
   -------------------------------------------------------------------------- */

.coll-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0.2rem 0 0.9rem;
}

.coll-search-box {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 16rem;
  min-width: 12rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.1rem 0.75rem;
}

.coll-search-icon {
  color: var(--muted);
  font-size: 0.95rem;
}

.coll-search {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  padding: 0.4rem 0;
  outline: none;
  /* 搜索框自带的清除按钮在深色底上很难看，交给浏览器的默认行为就好 */
  appearance: none;
}

.coll-search-box:focus-within {
  border-color: var(--accent);
}

.coll-found {
  color: var(--muted);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}

.coll-expand {
  font-size: 0.8rem;
  padding: 0.25rem 0.6rem;
}

/* 动态 / 静态卡面开关（图鉴工具栏） */
.coll-dynamic {
  font-size: 0.8rem;
  padding: 0.25rem 0.6rem;
}

.coll-dynamic.on {
  border-color: var(--accent);
  color: var(--accent);
}

/* 一张都没解锁时按钮是禁用状态 —— 要能一眼看出「现在不能用」，而不是点了没反应 */
.coll-dynamic[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.coll-dynamic-note {
  color: var(--muted);
  font-size: 0.78rem;
  margin: -0.5rem 0 0.8rem;
}

/* --------------------------------------------------------------------------
   HR（动态卡面）：碎片区块 + 大图里的 HR 标识
   -------------------------------------------------------------------------- */

.hr-panel .panel-hint + .panel-hint {
  margin-top: -0.4rem;
}

.hr-rows {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-top: 0.6rem;
}

.hr-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

/* 已解锁的那几行压低对比度：它们已经不需要读者做任何事 */
.hr-row-done {
  opacity: 0.62;
}

.hr-row-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.88rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hr-row-state {
  color: var(--muted);
  font-size: 0.78rem;
}

/* 大图标题旁的 HR 标识：这是「这张卡有动态形态」的唯一凭据（格子上只有一个「动」字） */
.hr-chip {
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* --------------------------------------------------------------------------
   每日签到
   --------------------------------------------------------------------------
   四张候选卡平铺（1 张初始 + 最多 3 次重抽），每张下面写明「种类 + 点数」，
   再各自带一个「领这一张」。选中的那张会高亮 —— 领完还要能一眼看出领的是哪张。
   -------------------------------------------------------------------------- */

.checkin-actions {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin: 0.2rem 0 1rem;
}

.checkin-roll {
  font-weight: 700;
}

.checkin-note {
  color: var(--muted);
  font-size: 0.82rem;
}

.checkin-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.7rem;
  margin-bottom: 1rem;
}

.checkin-card {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

/* 选中/已领的那张：边框换成强调色，并把其余候选压暗（选择已经做完了） */
.checkin-card-picked {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.checkin-card-meta {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  font-size: 0.82rem;
}

.checkin-card-name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.checkin-card-kind {
  color: var(--muted);
  font-size: 0.76rem;
}

.checkin-card-points {
  color: var(--gold);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.checkin-picked {
  text-align: center;
  color: var(--accent);
  font-size: 0.78rem;
  font-weight: 700;
}

.checkin-take {
  font-size: 0.8rem;
  padding: 0.25rem 0.6rem;
}

/* 系列组的标题本身就是按钮：可点、可聚焦、可键盘操作 */
.group-toggle {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 0;
  padding: 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
}

.group-toggle:hover .series-chip {
  border-color: var(--accent);
  color: var(--accent-strong);
}

.group-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 8px;
}

.group-caret {
  display: inline-block;
  width: 0.9rem;
  color: var(--muted);
  font-size: 0.78rem;
}

/* 收起：只藏卡面网格，标题与「x / y」计数仍然看得见 ——
   全藏起来的话这一组就像「不存在」，没人会想到去点它。 */
.group.is-collapsed .grid.cards {
  display: none;
}

/* --------------------------------------------------------------------------
   组容器：收起时是**卡片网格**，展开时占满整行
   --------------------------------------------------------------------------
   用户 2026-09-19：「即使收起也依旧会占一整行的空间，把布局改为类似抽卡结果
   一样的卡片布局」。所以收起的组渲染成一张与抽卡结果同款的卡（封面 2:3 + 名字 +
   进度），一行放好几张；展开的组 `grid-column: 1 / -1` 铺满，里面的卡片网格不变。
   -------------------------------------------------------------------------- */
.coll-groups {
  display: grid;
  gap: 0.7rem;
  grid-template-columns: repeat(auto-fill, minmax(8.4rem, 1fr));
  align-items: start;
}

/* 展开的组铺满整行（它的卡片网格需要整个宽度） */
.coll-groups > .group {
  grid-column: 1 / -1;
}

/* 收起的组 = 一个格子 */
.coll-groups > .group.is-collapsed {
  grid-column: auto;
}

/* 收起的那一格：标题变成一张卡片 */
.coll-groups > .group.is-collapsed {
  padding: 0;
  background: transparent;
  box-shadow: none;
}

.coll-groups > .group.is-collapsed > .group-head {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  width: 100%;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel);
  overflow: hidden;
  transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}

.coll-groups > .group.is-collapsed > .group-head:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: var(--shadow-lift);
}

/* 收起的封面 = 卡面（2:3，铺满整格宽），不再是小缩略图 */
.coll-groups > .group.is-collapsed .group-cover {
  width: 100%;
  aspect-ratio: 2 / 3;
  border: 0;
  border-radius: 0;
}

/* 展开按钮的提示：卡片右上角一个小圆标（在封面上要压得住底色） */
.coll-groups > .group.is-collapsed .group-caret {
  position: absolute;
  top: 0.3rem;
  right: 0.35rem;
  z-index: 2;
  width: auto;
  min-width: 1.2rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: rgba(20, 20, 26, 0.55);
  color: #fff;
  text-align: center;
}

/* 文字改成竖排（名字一行、进度一行） */
.coll-groups > .group.is-collapsed .group-text {
  display: block;
  padding: 0.45rem 0.55rem 0.55rem;
  line-height: 1.35;
}

.coll-groups > .group.is-collapsed .group-meta {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.78rem;
}

/* 卡池说明太长，卡片里不显示（悬停 title 里还有） */
.coll-groups > .group.is-collapsed .group-note {
  display: none;
}

.coll-groups > .group.is-collapsed .pool-name {
  font-size: 0.95rem;
}

/* --------------------------------------------------------------------------
   图鉴的两级分组：一级 = 卡池，二级 = 系列
   --------------------------------------------------------------------------
   各级都有封面，**点封面就是展开/收起**（整个标题都是按钮，封面在按钮里面）。
   一级的封面用卡池封面，二级的用该系列里最高稀有度的第一张卡。 */
.group-pool {
  display: grid;
  gap: 0.7rem;
}

/* 一级收起时整块二级都收起来（平铺的一级组里直接是 .grid.cards，由上面那条管）。
   ⚠️ 二级的容器现在是 `.coll-groups`（卡片网格）—— 这条曾经写的是 `.group-body`，
   容器改名之后它**静默失效**：卡池收起了，里面的系列还全都在。
   改这类容器名时，记得搜一遍有没有按旧名字写的规则（测试里也有一条闸门盯着它）。 */
.group-pool.is-collapsed > .coll-groups {
  display: none;
}

/* 二级比一级淡一档，层次靠底色而不是边框粗细来区分 */
.group-series {
  background: var(--panel-2);
  box-shadow: none;
  padding: 0.7rem;
}

.group-cover {
  flex: 0 0 auto;
  display: block;
  overflow: hidden;
  border-radius: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
}

.pool-cover {
  width: 3.1rem;
  aspect-ratio: 2 / 3;
}

.series-cover {
  width: 1.9rem;
  aspect-ratio: 2 / 3;
}

.group-cover-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 没有封面图时画一个字，别留空洞（留下空洞会被当成「图加载失败」） */
.group-cover-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-weight: 700;
}

.pool-name {
  font-weight: 700;
  font-size: 1.02rem;
}

/* 名字 / 计数 / 说明 三件套：整体换行，不要各自散开 */
.group-text {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* 点开看大图：覆盖整格的按钮，命中区域大才不会点空。
   视觉上透明，只有悬停/聚焦时才提示「看大图」。 */
.coll-open {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 7;
  border: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: zoom-in;
  border-radius: inherit;
}

.coll-open:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.coll-open-hint {
  position: absolute;
  left: 50%;
  bottom: 8px;
  transform: translateX(-50%);
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  background: rgba(20, 12, 40, 0.66);
  color: #fff;
  opacity: 0;
  transition: opacity 0.14s ease;
  pointer-events: none;
  white-space: nowrap;
}

.coll-cell:hover .coll-open-hint,
.coll-open:focus-visible .coll-open-hint {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   大图 / 合成弹层
   -------------------------------------------------------------------------- */

.card-dialog {
  max-width: 34rem;
}

.card-dialog .dialog-form {
  align-items: center;
  text-align: center;
}

.card-dialog-chips {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.card-dialog-figure {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  /* 倾斜时不要被裁掉边角 */
  padding: 0.5rem 0;
}

/* 检视容器：拖动它换角度。位置变量由 page.js 用 CSSOM 写（CSP 禁内联 style）
   ⚠️ 闪卡那套变量（--pointer-* / --background-* / --foil-1..6 / --foil-glitter）
   定义在 cards.css 的共享块里（`.card, .card-dialog-card`）—— **不要在这里再抄一份**：
   抄一份就意味着改配色时要改两个地方，而不改的那一份会静默地继续用旧色。 */
.card-dialog-card {
  position: relative;
  display: inline-block;
  line-height: 0;
  border-radius: 10px;
  /* 光效层是矩形的伪元素，要裁到圆角里，否则四个角会露出直角的闪光 */
  overflow: hidden;
}

/* 检视时提亮（拖动 = 在换角度，光要更明显才看得出「闪」） */
.card-dialog-card.is-inspecting {
  --foil-opacity: 1;
}

.card-dialog-img {
  display: block;
  width: auto;
  max-width: min(80vw, 21rem);
  max-height: 56vh;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-2);
  object-fit: contain;
}

/* 工艺切换：一排小胶囊（普通 / 平闪 / 全闪 / 红碎） */
.card-dialog-foils {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  flex-wrap: wrap;
}

.card-dialog-foils:empty {
  display: none;
}

/* 检视提示：只有能拖的卡才显示 */
.card-dialog-inspect {
  color: var(--muted);
  font-size: 0.76rem;
}

/* 没有卡面图 ≠ 大图读不到。前者是「还没配」，后者会在图鉴格子里报错。 */
.card-dialog-nofile {
  width: min(80vw, 21rem);
  padding: 3rem 1rem;
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 0.85rem;
}

.card-dialog-owner {
  color: var(--ok);
  font-size: 0.84rem;
  font-weight: 600;
}

.card-dialog-owner-missing {
  color: var(--muted);
  font-weight: 400;
}

.card-dialog-synth {
  width: 100%;
}

.card-dialog-hint {
  min-height: 1.2em;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   抽卡页舞台：侧面选池 + 主视觉轮播 + 右下角抽卡键
   -------------------------------------------------------------------------- */

.draw-stage {
  display: flex;
  gap: 0.8rem;
  align-items: stretch;
  margin: 0 0 0.8rem;
}

/* 侧面：竖排的卡池方块（封面半透明 + 卡池名） */
.draw-pools {
  flex: 0 0 auto;
  width: 5.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.pool-tile {
  position: relative;
  flex: 0 0 auto;
  aspect-ratio: 2 / 3;
  padding: 0;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--panel-2);
  cursor: pointer;
  /* 未选中 = 半透明；选中 = 不透明 + 高亮圈。
     用透明度而不是灰度：几张封面并排时仍然认得出画的是什么 */
  opacity: 0.5;
  transition: opacity 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}

.pool-tile:hover {
  opacity: 0.8;
}

.pool-tile.is-on {
  opacity: 1;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-weak);
}

.pool-tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.pool-tile-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pool-tile-noimg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.7rem;
}

/* 名字压在下缘：加一层由透明到深色的遮罩，白字在任何卡面上都读得清 */
.pool-tile-veil {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 52%;
  background: linear-gradient(180deg, rgba(10, 6, 20, 0) 0%, rgba(10, 6, 20, 0.88) 100%);
  pointer-events: none;
}

.pool-tile-name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0.3rem 0.3rem 0.35rem;
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  pointer-events: none;
}

/* 主视觉：16:9（用户给的横幅就是 1360x768 = 16:9） */
.draw-banner {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--panel-2);
}

.banner-box {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.banner-track {
  display: flex;
  height: 100%;
  /* 时长与 page.js 的 BANNER_SLIDE_MS 对应 */
  transition: transform 0.62s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}

/* 一张幻灯片 = 模糊底 + 完整卡面两层。
   横幅原图不一定是 16:9（「我与我的群友」那张是 3:2），cover 会裁掉上下约 18%
   的画面，所以卡面改用 contain 完整显示，缺出来的两条用同图模糊放大补满。 */
.banner-slide {
  position: relative;
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.banner-blur,
.banner-img {
  display: block;
  width: 100%;
  height: 100%;
}

/* 模糊底：铺满整框（cover），略微放大以免 blur 边缘露出一圈浅色 */
.banner-blur {
  position: absolute;
  inset: 0;
  object-fit: cover;
  object-position: center;
  filter: blur(26px) saturate(1.2);
  transform: scale(1.18);
}

/* 卡面：完整显示，绝不裁切。正好 16:9 的图会铺满整框，模糊层看不见。 */
.banner-img {
  position: relative;
  object-fit: contain;
  object-position: center;
}

/* 轮播圆点：默认半透明，当前那张实心。也是「手动切换」的入口 */
.banner-dots {
  position: absolute;
  left: 50%;
  bottom: 0.6rem;
  transform: translateX(-50%);
  display: flex;
  gap: 0.35rem;
  z-index: 3;
}

.banner-dot {
  width: 0.5rem;
  height: 0.5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
}

.banner-dot.is-on {
  background: #fff;
  transform: scale(1.25);
}

/* 有图但个别横幅解析不出来时说清楚，别让人怀疑「我放了三张怎么只轮播两张」 */
.banner-warn {
  position: absolute;
  left: 0.7rem;
  top: 0.7rem;
  z-index: 3;
  max-width: 70%;
  padding: 0.25rem 0.55rem;
  border-radius: 8px;
  background: rgba(120, 40, 30, 0.82);
  color: #fff;
  font-size: 0.74rem;
  line-height: 1.5;
}

/* 没配主视觉：说清「可以放图」，而不是留一块空白让人以为加载失败 */
.banner-empty {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 1rem;
  text-align: center;
}

.banner-empty-title {
  font-size: 1.1rem;
  font-weight: 700;
}

.banner-empty-hint {
  max-width: 26rem;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.6;
}

/* 主视觉那一列：轮播 + 它**下面**的抽卡键行 */
.draw-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

/* 列里按自己的 16:9 定高，不要被拉伸 */
.draw-main > .draw-banner {
  flex: 0 0 auto;
}

/* 抽卡键：主视觉**外面**的一行，右对齐；21:9 的比例保持不变。
   （以前是 absolute 压在主视觉右下角 —— 会挡到画面。） */
.draw-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
}

/* 模式切换 + 抽卡键：切模式那一排在上，按钮在下，整体右对齐 */
.draw-actions {
  flex-direction: column;
  align-items: flex-end;
}

.draw-action-btns {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* 普通 / 追梦池 的分段开关 */
.dream-switch {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.2rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel);
}

.mode-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.05rem;
  padding: 0.28rem 0.85rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  line-height: 1.15;
}

.mode-btn-label {
  font-size: 0.86rem;
  font-weight: 700;
}

.mode-btn-sub {
  font-size: 0.68rem;
  opacity: 0.85;
}

.mode-btn:hover {
  color: var(--text);
}

.mode-btn.is-on {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--text);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent);
}

/* 追梦池的说明行（涨到多少了 / 要花券） */
.dream-note {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.35rem;
  color: var(--muted);
  font-size: 0.8rem;
}

.dream-note-key {
  padding: 0.1rem 0.45rem;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--border));
  border-radius: 999px;
  color: var(--text);
  font-weight: 600;
}

.dream-note-cost {
  color: var(--warn, #e8a33d);
}

.dream-warn {
  margin-top: 0.4rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid color-mix(in srgb, var(--warn, #e8a33d) 50%, var(--border));
  border-radius: 8px;
  background: color-mix(in srgb, var(--warn, #e8a33d) 12%, transparent);
  color: var(--text);
  font-size: 0.8rem;
  max-width: 30rem;
}

/* 点数徽标（普通抽卡的次数）与券徽标并排，在碎片徽标右边 */
.points-chip {
  padding: 0.1rem 0.5rem;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 抽卡记录里的「普通池 / 追梦池」标签 */
.badge-mode {
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  font-size: 0.68rem;
  white-space: nowrap;
}

.badge-mode-normal {
  background: color-mix(in srgb, var(--muted) 22%, transparent);
  color: var(--muted);
}

.badge-mode-dream {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--text);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 50%, transparent);
}

.hist-dream {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

.hist-sum-mode {
  font-variant-numeric: tabular-nums;
}

/* 碎片 → 抽卡券 */

.ticket-rows {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.3rem 0 0.5rem;
}

.ticket-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel);
}

.ticket-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  min-width: 0;
}

.ticket-have,
.ticket-gain {
  font-variant-numeric: tabular-nums;
}

.ticket-gain {
  font-weight: 700;
  color: var(--ok);
}

.ticket-arrow {
  color: var(--muted);
}

.ticket-hint {
  color: var(--muted);
  font-size: 0.78rem;
}

.ticket-hint-off {
  color: color-mix(in srgb, var(--muted) 75%, transparent);
}

.ticket-actions {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}

/* 后台：追梦池设置折叠块 */
.dream-admin {
  margin-top: 0.6rem;
  padding: 0.5rem 0.65rem;
  border: 1px dashed var(--border);
  border-radius: 10px;
}

.dream-admin > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.86rem;
}

/* 后台：概率自检输出 */
.audit-out {
  max-height: 30rem;
  overflow: auto;
  font-size: 0.8rem;
}

.audit-head {
  margin-bottom: 0.4rem;
  color: var(--muted);
}

.audit-block {
  margin-bottom: 0.9rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
}

.audit-title {
  font-weight: 600;
  margin-bottom: 0.3rem;
}

.audit-sub {
  margin: 0.4rem 0 0.2rem;
  color: var(--muted);
}

.audit-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr 1fr;
  gap: 0.2rem 0.5rem;
  padding: 0.1rem 0;
  font-variant-numeric: tabular-nums;
}

.audit-h {
  color: var(--muted);
  font-weight: 600;
}

.audit-cell {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.audit-bad {
  color: #ff6b6b;
  font-weight: 700;
}

.audit-gated {
  color: var(--muted);
}

.audit-verdict {
  margin-top: 0.4rem;
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  font-weight: 700;
}

.audit-ok {
  background: color-mix(in srgb, var(--ok) 18%, transparent);
  color: var(--ok);
}

.audit-fail {
  background: color-mix(in srgb, #ff6b6b 18%, transparent);
  color: #ff6b6b;
}

.draw-btn {
  aspect-ratio: 21 / 9;
  width: 9.6rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.05rem;
  padding: 0;
  border-radius: 12px;
  font-weight: 700;
  box-shadow: 0 6px 18px -8px rgba(10, 6, 20, 0.7);
}

.draw-btn-label {
  font-size: 1rem;
  line-height: 1.2;
}

.draw-btn-cost {
  font-size: 0.7rem;
  font-weight: 600;
  opacity: 0.85;
}

.draw-btn.draw-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.draw-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* 现有券数压在主视觉左下角（小小的胶囊，不是按钮 —— 按钮已经挪到主视觉外面了） */
.banner-have {
  position: absolute;
  left: 0.8rem;
  bottom: 0.9rem;
  z-index: 3;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: rgba(10, 6, 20, 0.55);
  color: #fff;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

.draw-extra {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin: 0.2rem 0 0;
}

@media (max-width: 720px) {
  /* 窄屏：卡池改横排放到主视觉上方，否则侧面那一列会把主视觉挤没 */
  .draw-stage {
    flex-direction: column-reverse;
  }

  .draw-pools {
    flex-direction: row;
    width: 100%;
    overflow-x: auto;
    padding-bottom: 0.2rem;
  }

  .pool-tile {
    width: 4.2rem;
  }

  .draw-btn {
    width: 6.4rem;
  }

  .draw-btn-label {
    font-size: 0.86rem;
  }
}

/* --------------------------------------------------------------------------
   抽卡页的「抽卡范围」
   （卡池切换已改成侧面的封面方块，见上面「抽卡页舞台」）
   -------------------------------------------------------------------------- */

.pool-scope {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0 0 0.9rem;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  background: var(--panel);
  font-size: 0.85rem;
}

.pool-scope-key {
  color: var(--muted);
  font-size: 0.78rem;
}

.pool-scope-name {
  font-weight: 700;
}

.pool-scope-count {
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent-strong);
  font-size: 0.78rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.pool-scope-series {
  color: var(--muted);
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   卡池头：封面卡 + 系列清单 + 可抽张数
   -------------------------------------------------------------------------- */

.pool-hero {
  display: flex;
  gap: 0.9rem;
  align-items: stretch;
  margin: 0 0 1rem;
  padding: 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
}

.pool-cover {
  flex: 0 0 auto;
  width: 6.5rem;
}

/* 封面用 2:3 的卡面比例（--card-ratio 由页面按数据设置），和卡牌一致 */
.pool-cover-img {
  display: block;
  width: 100%;
  aspect-ratio: var(--card-ratio, 832 / 1216);
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--panel-2);
}

/* 没封面 / 封面卡不在名册里时都要说清楚，不能留一块空白 */
.pool-cover-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  width: 100%;
  aspect-ratio: var(--card-ratio, 832 / 1216);
  padding: 0.4rem;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 0.72rem;
  line-height: 1.4;
}

.pool-hero-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  justify-content: center;
}

.pool-hero-name {
  font-size: 1.05rem;
  font-weight: 700;
}

.pool-hero-desc {
  color: var(--muted);
  font-size: 0.82rem;
}

.pool-hero-line {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.84rem;
}

.pool-hero-key {
  flex: 0 0 auto;
  min-width: 2.4rem;
  color: var(--muted);
  font-size: 0.78rem;
}

.pool-hero-series {
  color: var(--text);
  line-height: 1.6;
}

@media (max-width: 560px) {
  .pool-cover {
    width: 5rem;
  }
}

/* --------------------------------------------------------------------------
   「关注安叶喵」板块

   参考 dsh-magical-girl-catalog 的「关注安叶！」：一条链接一张卡片。
   卡片在**没有链接**时仍然要长得像卡片（不能塌成一行文字）——
   番茄小说那条就是「只有扫码图、没有可点地址」，它才是这个页面的主角。
   -------------------------------------------------------------------------- */

.link-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 0.9rem;
}

.link-cell {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.link-card {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow);
  color: inherit;
  text-decoration: none;
}

.link-card.is-clickable {
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}

.link-card.is-clickable:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
  border-color: var(--accent);
}

.link-card.is-clickable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 不可点的卡片：左侧一道竖线，明确「这是信息，不是按钮」 */
.link-card.is-static {
  border-left: 3px solid var(--border-2);
}

.link-icon {
  width: 2.4rem;
  height: 2.4rem;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  border-radius: var(--radius-sm);
  background: var(--accent-weak);
}

.link-icon-img {
  width: 2.4rem;
  height: 2.4rem;
  flex: 0 0 auto;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}

.link-main {
  flex: 1 1 12rem;
  min-width: 0;
}

.link-title {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-wrap: wrap;
  font-weight: 700;
}

.link-badge {
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent-strong);
  font-size: 0.72rem;
  font-weight: 600;
}

.link-url {
  margin-top: 0.15rem;
  color: var(--muted);
  font-size: 0.76rem;
  font-family: var(--mono);
  word-break: break-all;
}

.link-desc {
  margin-top: 0.35rem;
  color: var(--muted);
  font-size: 0.84rem;
  line-height: 1.6;
}

/* 配图（扫码图）：整张卡的正下方一行，宽度撑满 —— 二维码太小就扫不出来 */
.link-qr {
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--border);
}

/*
 * 配图（番茄小说的分享海报，1219x1999 竖版）。
 * 宽度给足（二维码要扫得出来），高度封顶 —— 竖版海报按原比例铺满会把整张卡片
 * 拉到 400+ px 高，一屏只看得到一张卡。`object-fit: contain` 是必须的：
 * 只写 max-height 会把图**压扁**（宽度还是 100%），看着像图坏了。
 */
.link-qr-img {
  width: 100%;
  max-width: 15rem;
  max-height: 22rem;
  height: auto;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: #fff;
}

.link-qr-hint {
  color: var(--muted);
  font-size: 0.78rem;
}

/* 链接不合法 / 什么都没有：写成一行可见的说明，不要静默 */
.link-warn {
  padding: 0.35rem 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--danger-weak);
  color: var(--danger-strong);
  font-size: 0.78rem;
  word-break: break-all;
}

/* --------------------------------------------------------------------------
   后台的链接行（「关注安叶喵」那一块）
   -------------------------------------------------------------------------- */

/* 每条链接一张卡：不加边框的话，两行输入框看起来像同一组字段 */
.link-admin-rows {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.link-admin {
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

/* --------------------------------------------------------------------------
   公告弹窗（缺纪念卡 -> 引导重置）
   -------------------------------------------------------------------------- */
.notice-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.notice-item {
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--accent-weak);
  color: var(--accent-strong);
  font-size: 0.8rem;
  font-weight: 600;
}

.notice-warn {
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius-sm);
  background: var(--danger-weak);
  color: var(--danger-strong);
  font-size: 0.82rem;
  line-height: 1.65;
}

/* --------------------------------------------------------------------------
   窄屏
   -------------------------------------------------------------------------- */

@media (max-width: 560px) {
  .bar-inner {
    padding: 0.4rem 0.7rem;
    gap: 0.5rem;
  }

  .nav {
    order: 3;
    width: 100%;
    overflow-x: auto;
    flex-wrap: nowrap;
    padding-bottom: 0.3rem;
  }

  .view {
    padding: 1rem 0.7rem 2rem;
  }

  .grid.cards {
    grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
    gap: 0.55rem;
  }

  .draw-have {
    margin-left: 0;
    width: 100%;
  }
}
