/* ==========================================================================
   oracv · Notion Design System
   ─ 页面底 #f7f7f5 暖灰 / 纯白卡片浮层 / 1px 极细边 + 极轻柔微阴影
   ─ 卡片圆角 12px，按钮 6px，内容列 900px
   ========================================================================== */

/* ══════════════════════════════════════════════════════════════════════
   1. 设计变量
   ══════════════════════════════════════════════════════════════════════ */
:root {
  /* ── 背景 ── */
  --bg:            #ffffff;   /* 卡片白 */
  --bg-page:       #f7f7f5;   /* 页面最底层：Notion 极浅暖灰 */
  --bg-subtle:     #f7f7f5;   /* Notion 二级底/侧栏 */
  --bg-callout:    #f1f1ef;   /* Notion callout 灰 */
  --bg-hover:      rgba(55, 53, 47, 0.055);
  --bg-selected:   rgba(55, 53, 47, 0.08);

  /* ── 文字 ── */
  --text:          #37352f;   /* 主文字 */
  --text-2:        #787774;   /* 次要文字 */
  /* #54：#9b9a97 → #8a8986，对比度约 2.8:1 → 3.4:1（接近 WCAG AA）。
     只调一档、不调成纯黑 —— 再深就不是 Notion 那种「退后半步」的克制灰了。 */
  --text-3:        #8a8986;   /* 三级文字 */
  --ink:           #191918;   /* 标题/正文强调 */

  /* ── 边框：极细，近乎不可见 ── */
  --border:        rgba(0, 0, 0, 0.05);
  --border-2:      rgba(55, 53, 47, 0.16);

  /* ── 阴影：极轻柔，让白卡片浮在暖灰底上 ── */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.03), 0 1px 3px rgba(0, 0, 0, 0.04);
  --shadow-lift: 0 2px 6px rgba(0, 0, 0, 0.06);
  --shadow-pop:  0 8px 24px rgba(0, 0, 0, 0.12);

  /* ── 圆角 ── */
  --r-xs: 3px;
  --r-sm: 6px;     /* 按钮 / 输入框 */
  --r-md: 8px;     /* 区块 / Banner */
  --r-card: 12px;  /* 卡片 */

  /* ── 熟练度语义色（Notion 官方标签色） ── */
  --c-mastered: #448361;
  /* #94 · 色彩心理学互换：**蓝 = 已掌握**（沉稳、完成感），**绿 = 今日到期**（"该做了"的提示）。
     ⚠️ 刻意**不改** `--c-mastered` 的值本身 —— 学习时间的柱状图、连接状态点、
        「已认识」判定卡还在用它，全局改会把时间图表也一起染蓝。
        所以另开一个 `--c-due` 承载"原来那抹绿"，熟练度那一层单独指向 `--c-blue`。 */
  --c-due:      #448361;
  /* #95 · 学习时长图表（柱状图 / 日历热力图最深档）专用蓝。
     绿色已语义化为「今日到期」，图表属于数据可视化，统一改蓝。 */
  --c-chart:    #337ea9;
  --c-good:     #cb912f;
  --c-needwork: #d9730d;
  --c-weak:     #c4554d;
  --c-untrained:#91918e;
  --c-blue:     #2383e2;
  --c-purple:   #9065b0;

  /* ── 主色：Notion 官网清爽蓝 ── */
  --accent:       #2383e2;
  --accent-hover: #1a73c7;

  /* ── 温和点缀色：Notion Callout 官方色板 ────────────────────────────
     #88：绿/红/蓝/紫**提高饱和度**（原来 #edf7ee 太接近白，整页灰扑扑没层次）。
     ⚠️ 影响范围已核对：题卡底色 / mini-stat / tsummary / plan-stat / 评估判定卡
        —— 全是同一类"温和淡色块"，一起变鲜明反而更统一。 */
  --tint-green-bg:  #dbeddb;   --tint-green-fg:  #1c3829;   --tint-green-hover:  #d0e6d0;
  --tint-yellow-bg: #fbf3db;   --tint-yellow-fg: #402c1b;   --tint-yellow-hover: #f6ecc9;
  --tint-orange-bg: #faebdd;   --tint-orange-fg: #49290d;   --tint-orange-hover: #f5e2cf;
  --tint-red-bg:    #ffe2dd;   --tint-red-fg:    #5d1715;   --tint-red-hover:    #fcd9d2;
  --tint-blue-bg:   #d3e5ef;   --tint-blue-fg:   #183347;   --tint-blue-hover: #c6dcee;
  --tint-purple-bg: #e8deee;   --tint-purple-fg: #412454;

  /* ── #88 · 题卡质感：极细边 + 极淡影 ──────────────────────────────
     Notion 的高级感来自「1px 极细边 + 一层几乎看不见的投影」，
     而不是"浮起来"。重阴影 = 廉价感，这里刻意压到最低。 */
  --qcard-border:        rgba(15, 15, 15, 0.07);
  --qcard-shadow:        0 1px 2px rgba(15, 15, 15, 0.04);
  --qcard-shadow-hover:  0 2px 8px rgba(15, 15, 15, 0.06);

  --ease: cubic-bezier(0.2, 0, 0.4, 1);
}

/* ══════════════════════════════════════════════════════════════════════
   2. 基础
   ══════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--bg-page);
  color: var(--text);
  font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica,
               "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif,
               "Apple Color Emoji", "Segoe UI Emoji";
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection { background: rgba(35, 131, 226, 0.18); }

/* 细腻滚动条 */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(55, 53, 47, 0.18);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: rgba(55, 53, 47, 0.3); background-clip: content-box; }

button {
  font-family: inherit;
  font-size: 14px;
  color: inherit;
  border: 0;
  background: none;
  cursor: pointer;
  transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease),
              color 0.12s var(--ease), opacity 0.12s var(--ease);
}
button:active:not(:disabled) { opacity: 0.7; }
button:disabled { opacity: 0.4; cursor: not-allowed; }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
  background: rgba(135, 131, 120, 0.15);
  color: #eb5757;
  padding: 0.2em 0.4em;
  border-radius: var(--r-xs);
}

kbd {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  padding: 1px 5px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  border: 1px solid var(--border);
  color: var(--text-2);
}
.kbd-dark {
  background: rgba(255, 255, 255, 0.22);
  border-color: transparent;
  color: #fff;
}

hr { border: 0; border-top: 1px solid var(--border); }

/* ══════════════════════════════════════════════════════════════════════
   3. 顶部导航 —— 白底 / 底部一根极细灰线 / 极简悬浮菜单
   ══════════════════════════════════════════════════════════════════════ */
.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #fff;
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}
.topbar-inner {
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 48px;
  height: 72px;
  display: flex;
  align-items: center;
  gap: 40px;
}

/* Logo */
.logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  flex-shrink: 0;
  padding: 4px 6px;
  margin-left: -6px;
  border-radius: var(--r-sm);
  transition: background-color 0.12s var(--ease);
}
.logo:hover { background: var(--bg-hover); }
/* #101 · LOGO 换成一枚手写 SVG（说话气泡 + 蓝对勾）
   ⚠️ 原来是「黑圆角方块 + 白方孔」用 CSS 伪元素画的，尺寸被锁死在 22px；
      现在改成真 SVG（viewBox 32），尺寸想多大就多大，且与页面插画同一套画法。 */
.logo-mark {
  width: 30px;                                   /* 22 → 30（用户反馈"LOGO 有点小"） */
  height: 30px;
  display: block;
  flex: 0 0 auto;
  overflow: visible;
}
.logo-text {
  font-size: 20px;                               /* 18 → 20，与 30px 图形等比例 */
  font-weight: 700;
  letter-spacing: -0.035em;
  color: var(--ink);
}

/* 导航项 */
.nav {
  display: flex;
  align-items: center;
  gap: 2px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.nav::-webkit-scrollbar { display: none; }
.nav-item {
  height: 32px;
  padding: 0 11px;
  border-radius: var(--r-sm);
  font-size: 15px;
  font-weight: 400;
  color: var(--text-2);          /* 未选中：深灰字 */
  white-space: nowrap;
  transition: background-color 0.12s var(--ease), color 0.12s var(--ease);
}
.nav-item:hover { background: var(--bg-hover); color: var(--text); }
.nav-item.active {
  background: var(--bg-selected); /* 选中：极浅灰底 */
  color: var(--text);             /* 选中：黑字 */
  font-weight: 500;
}

.topbar-aside { margin-left: auto; flex-shrink: 0; }
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  border-radius: var(--r-sm);
  font-size: 14px;
  color: var(--text-2);
  cursor: pointer;
  user-select: none;
  transition: background-color 0.12s var(--ease), color 0.12s var(--ease);
}
.toggle:hover { background: var(--bg-hover); color: var(--text); }
.toggle input[type="checkbox"] { width: 15px; height: 15px; accent-color: #37352f; cursor: pointer; }

/* ══════════════════════════════════════════════════════════════════════
   4. 主体骨架 —— 大留白 / 固定内容宽度
   ══════════════════════════════════════════════════════════════════════ */
/* #92：顶部留白 72 → 32。以前 `.shell` 的 72px 加上 page-hero 的 76px = **148px** 空白，
   标题离导航栏太远，"空袭感"很强。
   #97：再收到 16。插画放大到 ≈230px 高之后，它是靠底对齐把标题"顶"在下面的，
   于是标题上方必然留出一大块空白 —— 这里再往下压 16px，配合 page-hero 从 48 收到 18，
   标题整体上移约 46px。 */
.shell { padding: 16px 0 140px; }
.shell-inner { max-width: 1320px; margin: 0 auto; padding: 0 48px; }

.page { display: none; }
.page.active { display: block; animation: fadeUp 0.24s var(--ease); }
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* 双栏：正文 900px + 侧栏 280px，居中排布，内容充分展开 */
.layout {
  display: grid;
  grid-template-columns: minmax(0, 900px) 280px;
  gap: 64px;
  justify-content: center;
  align-items: start;
}
.layout-main { min-width: 0; }
.layout-side { position: sticky; top: 112px; display: flex; flex-direction: column; gap: 32px; }

/* 单栏页（学习模式） */
.column { max-width: 900px; margin: 0 auto; }

/* 连接状态：白卡片
   #89 · 上线清理：这条「✅ 已连接本地服务器 · 所有数据自动读写文件」看着像测试工具，
   UI 上不再显示。⚠️ **逻辑全部保留**（updateConnBar 仍在跑），断网改由右上角 toast 提示。
   ⚠️ 必须 !important —— 否则这里的 `display:flex` 会盖掉 HTML 上的 hidden 属性。 */
.conn-bar {
  display: none !important;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  margin-bottom: 40px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  font-size: 14px;
  color: var(--text-2);
}
.conn-bar.ok { color: var(--text); }
.conn-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--c-needwork); flex-shrink: 0; }
.conn-bar.ok .conn-dot { background: var(--c-mastered); }

/* ══════════════════════════════════════════════════════════════════════
   5. 排版
   ══════════════════════════════════════════════════════════════════════ */
.doc-head { margin-bottom: 40px; }
.doc-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; flex-wrap: wrap; }

/* ⚠️ #91：`.doc-title` 已从这条共用规则里**摘出** —— 题库设置页改用了 page-hero 结构。
   以前它自己是 40px / 17px，其它页面是 32px / 13.5px，这就是"字号不统一"的真正根因。
   现在全站只剩两档：首页 XL 56px、内页 LG 40px。 */
.page-title,
/* ⚠️ #89：`.overview-title` 已从这条共用规则里**摘出** ——
   5 个页面的标题改用 `.page-hero-title`（**32px**，见 00-core.js 的 pageHeroHtml）。
   学习模式的全屏开始屏 / 结束屏**保留 40px**：那是居中 hero 屏，性质不同，不该一起缩小。 */
.settings-header h2,
.learn-start-screen h2,
.learn-done-screen h2 {
  font-size: 40px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink);
}
/* 兜底：万一还有老调用没换成 page-hero，至少是 32px 而不是继承 body 的 16px */
.overview-title {
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink);
}
/* #91：与 `.page-hero-sub` 对齐（17px → 15px），万一还有老调用也不会跳字号 */
.doc-sub { margin-top: 12px; font-size: 15px; line-height: 1.6; color: var(--text-2); }
/* 兜底：万一还有地方用 .doc-title，至少保持 LG 档的 40px */
.doc-title { font-size: 40px; font-weight: 700; line-height: 1.12; letter-spacing: -0.025em; color: var(--ink); }

.block-title,
.section-title,
.manual-set-title,
.learn-footer-info b {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.section-title { margin-bottom: 8px; }
.section-title.muted { color: var(--text-3); margin: 32px 0 8px; }
.section-title.mt-lg { margin-top: 28px; }

.footnote { margin-top: 20px; font-size: 13px; line-height: 1.7; color: var(--text-3); }

.muted { color: var(--text-2); }
.muted-2 { color: var(--text-3); }
.muted-italic { color: var(--text-3); font-style: italic; font-size: 14px; }
.hint { font-size: 13px; font-weight: 400; color: var(--text-3); }
.lead { color: var(--text-2); max-width: 520px; margin: 0 auto; }

/* ══════════════════════════════════════════════════════════════════════
   6. 基础组件
   ══════════════════════════════════════════════════════════════════════ */

/* ── 按钮 ── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);      /* 极小圆角 */
  background: #fff;
  color: var(--text);              /* 黑字 */
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
}
.btn:hover:not(:disabled) { background: var(--bg-callout); }   /* 悬停浅灰 */
.btn .key { font-size: 12px; font-weight: 500; color: var(--text-3); }

/* 主按钮：Notion 官网清爽蓝 */
.btn-primary,
.btn-success {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-primary:hover:not(:disabled),
.btn-success:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn-danger { background: #fff; border-color: var(--border-2); color: var(--text); }
.btn-danger:hover:not(:disabled) { background: var(--bg-callout); }

.btn-danger-solid { background: var(--c-weak); border-color: var(--c-weak); color: #fff; }
.btn-danger-solid:hover:not(:disabled) { background: #ad4640; border-color: #ad4640; }

.btn-row { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.btn-row.mt-lg { margin-top: 32px; }
.btn-wide { min-width: 180px; }

/* 「会 / 不会」：白底灰框黑字，彻底删掉大红大绿 */
.btn-group { display: flex; gap: 12px; flex-wrap: wrap; }
.btn-group .btn { flex: 1 0 auto; min-width: 140px; }
.btn-group .btn-success,
.btn-group .btn-danger {
  background: #fff;
  border-color: var(--border-2);
  color: var(--text);
}
.btn-group .btn-success:hover:not(:disabled),
.btn-group .btn-danger:hover:not(:disabled) { background: var(--bg-callout); }

/* ── 输入框 ── */
.input,
select,
input[type="text"], input[type="date"], input[type="time"], input[type="number"] {
  height: 36px;
  padding: 0 12px;
  font-family: inherit;
  font-size: 14px;
  color: var(--text);
  background: #fff;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  outline: none;
  transition: border-color 0.12s var(--ease), background-color 0.12s var(--ease);
}
select { padding-right: 28px; cursor: pointer; }
.input:hover, select:hover,
input[type="text"]:hover, input[type="date"]:hover, input[type="time"]:hover { background: var(--bg-subtle); }
.input:focus, select:focus,
input[type="text"]:focus, input[type="date"]:focus, input[type="time"]:focus,
input[type="number"]:focus { border-color: var(--c-blue); background: #fff; }

.textarea {
  width: 100%;
  min-height: 220px;
  padding: 14px 16px;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.7;
  color: var(--text);
  background: #fff;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  outline: none;
  resize: vertical;
}
.textarea:focus { border-color: var(--c-blue); }

input[type="range"] { width: 120px; accent-color: var(--text); cursor: pointer; }
input[type="checkbox"], input[type="radio"] { width: 15px; height: 15px; accent-color: #37352f; cursor: pointer; }

.search-input { width: 260px; }

/* ── 卡片：白底 + 极细灰边 + 零阴影 ── */
.card,
.question-card,
.learn-card,
.side-block,
.practice-setup,
.group-panel,
.voice-panel,
.tsummary-card,
.ws-card,
.plan-stat,
.goal-plan-result,
.cal-wrap,
.ts-detail {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
}
.side-block { padding: 20px 22px; }

/* ── 色点（熟练度唯一的彩色来源） ── */
.dot, .dot-color {
  width: 8px; height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
  background: var(--c-untrained);
}
/* #94 · 已掌握 = 蓝（原来是绿，和「今日到期」互换） */
.dot-mastered { background: var(--c-blue); }
.dot-good     { background: var(--c-good); }
.dot-needwork { background: var(--c-needwork); }
.dot-weak     { background: var(--c-weak); }
.dot-untrained{ background: var(--c-untrained); }
.dot.ok   { background: var(--c-mastered); }
.dot.warn { background: var(--c-good); }
.dot.fail { background: var(--c-weak); }

/* ── 熟练度标签（Notion 官方标签配色） ── */
.proficiency-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  padding: 1px 7px;
  border-radius: var(--r-xs);
  white-space: nowrap;
  vertical-align: middle;
}
.prof-untrained { background: #e3e2e0; color: #32302c; }
.prof-weak      { background: #ffe2dd; color: #5d1715; }
.prof-needwork  { background: #fadec9; color: #49290d; }
.prof-good      { background: #fdecc8; color: #402c1b; }
.prof-mastered  { background: #d3e5ef; color: #183347; }   /* #94：绿 → 蓝，与「今日到期」互换 */
.badge-sm { font-size: 11px; padding: 0 5px; }

/* ── 星级 ── */
.star-rating { display: inline-flex; align-items: center; gap: 1px; vertical-align: middle; }
.star-rating .star {
  color: #dcdbd9;
  cursor: pointer;
  font-size: 18px;      /* #63：15 → 18（★ 太小）；gap 保持 1px 不变 */
  line-height: 1;
  user-select: none;
  transition: color 0.12s var(--ease);
}
.star-rating .star:hover { color: #f5cd6b; }
.star-rating .star.active { color: #dfab01; }
.star-rating.readonly .star { cursor: default; }
.star-rating.readonly .star:hover { color: #dcdbd9; }
.star-rating.readonly .star.active:hover { color: #dfab01; }
.star-rating.small .star { font-size: 15px; }   /* #63：13 → 15（保持比普通星星小一档） */

/* ── 筛选 chip ── */
.filter-chip,
.practice-chip,
.weekday-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease), color 0.12s var(--ease);
}
.filter-chip:hover,
.practice-chip:hover,
.weekday-chip:hover { background: var(--bg-subtle); color: var(--text); }
.filter-chip.active,
.practice-chip.active,
.weekday-chip.active {
  background: var(--bg-selected);
  border-color: var(--border-2);
  color: var(--text);
  font-weight: 600;
}
.count-badge {
  font-size: 11px;
  font-weight: 600;
  padding: 0 6px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.filter-chip.active .count-badge,
.practice-chip.active .count-badge { background: rgba(55, 53, 47, 0.1); color: var(--text-2); }

/* ── 空状态 ── */
.empty-hint {
  padding: 32px 8px;
  text-align: center;
  font-size: 14px;
  color: var(--text-3);
}
.empty-overview, .ws-empty, .archive-empty { text-align: center; padding: 96px 16px; color: var(--text-3); font-size: 15px; }
.empty-overview .big, .archive-empty .emoji-xl { font-size: 40px; margin-bottom: 16px; }
.empty-sub { font-size: 13px; margin-top: 10px; color: var(--text-3); }
.empty-msg { color: var(--text-3); margin-top: 10px; font-size: 14px; }
.empty-note { color: var(--text-3); font-style: italic; text-align: center; padding: 32px; font-size: 14px; }
.emoji-xl { font-size: 40px; }
.emoji-lg { font-size: 32px; margin-bottom: 8px; }

/* ══════════════════════════════════════════════════════════════════════
   7. 答题区（强化训练 / 学习模式）
   ══════════════════════════════════════════════════════════════════════ */
.question-card, .learn-card {
  position: relative;
  padding: 40px 44px;
  animation: fadeUp 0.24s var(--ease);
}
.question-card.pad-lg { padding: 32px 36px; }

.status-badge {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  margin-bottom: 24px;
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
}
.mode-badge {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  margin-left: 8px;
  border-radius: var(--r-xs);
  font-size: 11px;
  font-weight: 600;
}
.mode-badge.review { background: #dbeddb; color: #1c3829; }
.mode-badge.random { background: #d3e5ef; color: #183347; }

/* 题目：Notion 文档式 —— 无边框无背景、字号大、加粗、纯黑、居左 */
.question-text,
.learn-question {
  font-size: 27px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-align: left;
  margin-bottom: 28px;
  word-break: break-word;
  animation: fadeUp 0.28s var(--ease);
}
.question-text.card-title { font-size: 20px; font-weight: 400; color: var(--text-2); }

/* 答案：Notion 浅色块 + 6px 圆角 + 大内边距 + 行高 1.6 */
.answer-text,
.learn-answer {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 20px 24px;
  margin-bottom: 28px;
  background: var(--tint-blue-bg);   /* 浅蓝 Banner */
  border-left: 3px solid var(--accent);
  border-radius: var(--r-md);
  font-size: 16px;
  line-height: 1.6;
  color: var(--text);
  word-break: break-word;
  white-space: pre-wrap;
}
.answer-text .label,
.answer-label {
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-3);
  padding-top: 3px;
}
.answer-text .content { flex: 1; }

/* 答案默认隐藏，.show 才展开（功能生命线） */
.learn-answer { display: none; }
.learn-answer.show { display: block; animation: fadeUp 0.28s var(--ease); }
.answer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.answer-header .answer-label { padding-top: 0; }

/* 角标按钮 */
.end-round-btn {
  position: absolute;
  top: 20px; right: 20px;
  height: 28px;
  padding: 0 11px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
}
.end-round-btn:hover { background: var(--bg-subtle); color: var(--text); }

.speak-btn, .speak-answer-btn, .speak-q {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 28px; height: 28px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  color: var(--text-2);
}
.speak-btn:hover, .speak-answer-btn:hover, .speak-q:hover { background: var(--bg-subtle); color: var(--text); }
.speak-btn.speaking, .speak-answer-btn.speaking { background: var(--tint-blue-bg); border-color: rgba(35, 131, 226, 0.3); color: var(--tint-blue-fg); }
/* 合成/缓冲中：按钮内变成转圈，同时禁用防连点 */
.speak-btn.loading, .speak-answer-btn.loading {
  position: relative;
  background: var(--tint-blue-bg);
  border-color: rgba(35, 131, 226, 0.3);
  color: var(--tint-blue-fg);
  cursor: progress;
}
.speak-btn.loading > *, .speak-answer-btn.loading > * { visibility: hidden; }
.speak-btn.loading::after, .speak-answer-btn.loading::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border: 2px solid rgba(35, 131, 226, 0.25);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: speakSpin 0.65s linear infinite;
}
@keyframes speakSpin { to { transform: rotate(360deg); } }
.speak-btn { position: absolute; top: 20px; right: 20px; }
.speak-btn.offset { right: 116px; }
.speak-q { width: 30px; height: 30px; }

/* 显示答案按钮 */
.learn-show-btn {
  width: 100%;
  height: 44px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
}
.learn-show-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

/* 四档评估 */
.learn-assess { display: none; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.learn-assess.show { display: grid; }
.assess-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 14px 8px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}
.assess-btn:hover { background: var(--bg-callout); }
.assess-btn .emoji { font-size: 20px; line-height: 1.2; }
.assess-btn .key { font-size: 11px; font-weight: 500; color: var(--text-3); }
.assess-again:hover { border-color: var(--c-weak); }
.assess-hard:hover  { border-color: var(--c-needwork); }
.assess-good:hover  { border-color: var(--c-good); }
.assess-easy:hover  { border-color: var(--c-mastered); }

/* 本轮结束 */
.end-message {
  padding: 48px 40px;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  background: #fff;
  box-shadow: var(--shadow-card);
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.end-sub { display: block; margin-top: 10px; font-size: 15px; font-weight: 400; color: var(--text-2); }
.summary-stats { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin: 24px 0; }
.stat-pill {
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-2);
}
.stat-pill.known   { background: #dbeddb; color: #1c3829; border-color: transparent; }
.stat-pill.unknown { background: #ffe2dd; color: #5d1715; border-color: transparent; }
.stat-pill.pending { background: var(--bg-subtle); color: var(--text-2); }

/* 学习模式进度与统计 */
.learn-progress-bar { height: 6px; background: var(--bg-callout); border-radius: 3px; overflow: hidden; margin-bottom: 32px; }
.learn-progress-fill { height: 100%; background: var(--accent); border-radius: 3px; transition: width 0.4s var(--ease); }
.learn-top-stats { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 32px; font-size: 13px; }
.learn-top-stats .stat-box {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  color: var(--text-2);
}
.learn-top-stats .stat-box .num { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }

.learn-card-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 24px;
  padding-right: 56px;
  font-size: 13px;
  color: var(--text-2);
}
.learn-card-meta .no {
  padding: 1px 7px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
}
.learn-footer-info {
  margin-top: 20px;
  padding: 14px 18px;
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-2);
  text-align: center;
}
.learn-keys-hint {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 14px;
  font-size: 12px;
  color: var(--text-3);
}
.learn-actions-bar { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 20px; }
.learn-actions-bar button {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
}
.learn-actions-bar button:hover { background: var(--bg-subtle); color: var(--text); }

/* 学习模式起止页 */
.learn-start-screen, .learn-done-screen { padding: 48px 0; text-align: center; }
.learn-start-screen .big-icon, .learn-done-screen .big-icon { font-size: 44px; margin-bottom: 20px; }
/* #93 · 学习模式起止页：emoji 📖 → 手写原生插画（摊开的书 + 灯泡），居中展示。
   .empty-art 用在强化训练「题库为空」的空状态（靶心，尺寸更小）。 */
.start-art { display: block; width: 132px; height: auto; margin: 0 auto 20px; }
.empty-art { display: block; width: 96px; height: auto; margin: 0 auto 12px; }
.learn-start-screen h2, .learn-done-screen h2 { margin-bottom: 16px; }
.learn-start-screen p {
  max-width: 560px;
  margin: 0 auto 32px;
  font-size: 15px;
  line-height: 1.7;
  color: var(--text-2);
  text-align: left;
}
.start-btn {
  height: 40px;
  padding: 0 28px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
}
.start-btn:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
.start-btn.ghost { background: #fff; color: var(--text); border-color: var(--border-2); }
.start-btn.ghost:hover { background: var(--bg-subtle); }
.done-note { max-width: 520px; margin: 0 auto 32px; font-size: 15px; line-height: 1.7; color: var(--text-2); }
.learn-done-screen .stats { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin: 32px 0; }
.learn-done-screen .stats .stat-card {
  min-width: 112px;
  padding: 16px 22px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
}
.learn-done-screen .stats .stat-card .num {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.learn-done-screen .stats .stat-card .lbl { margin-top: 2px; font-size: 12px; color: var(--text-3); font-weight: 500; }
.c-again { color: var(--c-weak); }
.c-hard  { color: var(--c-needwork); }
.c-good  { color: var(--c-mastered); }
.c-easy  { color: var(--c-purple); }

/* 训练筛选页 */
.practice-setup { padding: 24px 28px; }
/* #93 · 同一个「画中画」问题：.practice-setup 也自带白底 + 灰边，而它本来就在
   .question-card.pad-lg 里面 —— 框里套框。去掉内层，只留外框（padding 也还给外框）。
   ⚠️ 两个类 > 一个类，所以能盖住上面这行和移动端 `.practice-setup{padding:16px}`。 */
.question-card > .practice-setup {
  background: transparent;
  border: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}
.practice-section { margin-bottom: 24px; }
.practice-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-2);
}
.practice-section-title .hint { font-weight: 400; color: var(--text-3); }
.practice-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.practice-chip .chip-count {
  font-size: 11px;
  font-weight: 600;
  padding: 0 6px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.practice-chip.active .chip-count { background: rgba(55, 53, 47, 0.1); color: var(--text-2); }
.practice-chip.prof-untrained-chip.active,
.practice-chip.prof-weak-chip.active,
.practice-chip.prof-needwork-chip.active,
.practice-chip.prof-good-chip.active,
.practice-chip.prof-mastered-chip.active {
  background: var(--bg-selected);
  border-color: var(--border-2);
  color: var(--text);
}
.practice-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 24px;
  padding: 16px 20px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
}
.practice-summary .info { font-size: 14px; color: var(--text-2); }
.practice-summary .info b { font-size: 18px; color: var(--ink); font-variant-numeric: tabular-nums; }
.practice-summary .actions { display: flex; gap: 10px; flex-wrap: wrap; }
.practice-start-btn {
  height: 40px;
  padding: 0 24px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
}
.practice-start-btn:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
.practice-start-btn.review-btn { background: #fff; color: var(--text); border-color: var(--border-2); }
.practice-start-btn.review-btn:hover:not(:disabled) { background: var(--bg-subtle); }
.setup-head { text-align: center; margin-bottom: 32px; }
.setup-title { font-size: 28px; font-weight: 700; letter-spacing: -0.015em; color: var(--ink); }
.setup-sub { margin-top: 8px; font-size: 15px; color: var(--text-2); }
.info-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 20px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  font-size: 13px;
  color: var(--text-2);
}

/* ══════════════════════════════════════════════════════════════════════
   8. 侧边栏 —— 白底 + 极细灰边，熟练度只用小圆点区分
   ══════════════════════════════════════════════════════════════════════ */
.side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.side-title, .stats-title {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-3);
}
.side-meta, #progressText {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.stats-title { margin-bottom: 12px; }

.stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.stat-cell {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
  font-size: 13px;
  color: var(--text-2);
  transition: background-color 0.12s var(--ease);
}
.stat-cell:hover { background: var(--bg-subtle); }
.stat-cell:nth-child(5) { grid-column: 1 / -1; }
.stat-cell .num {
  margin-left: auto;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* 统计数字跟随对应熟练度着色，不再是死板纯黑 */
.stat-cell .dot-mastered ~ .num { color: var(--c-blue); }
.stat-cell .dot-good     ~ .num { color: var(--c-good); }
.stat-cell .dot-needwork ~ .num { color: var(--c-needwork); }
.stat-cell .dot-weak     ~ .num { color: var(--c-weak); }
.stat-cell .dot-untrained ~ .num { color: var(--c-untrained); }

.answered-list { display: flex; flex-direction: column; gap: 6px; }
.answered-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--r-md);
  border-left: 2px solid var(--c-untrained);
  background: var(--bg-subtle);
  font-size: 13px;
  line-height: 1.6;
  word-break: break-word;
  animation: slideIn 0.22s var(--ease);
}
@keyframes slideIn {
  from { opacity: 0; transform: translateX(-4px); }
  to   { opacity: 1; transform: none; }
}
.answered-item.known   { border-left-color: var(--c-mastered); }
.answered-item.unknown { border-left-color: var(--c-weak); }
.answered-item .mark { font-weight: 700; color: var(--text-3); flex-shrink: 0; }
.answered-item.known .mark { color: var(--c-mastered); }
.answered-item.unknown .mark { color: var(--c-weak); }

/* ══════════════════════════════════════════════════════════════════════
   9. 题卡总览
   ══════════════════════════════════════════════════════════════════════ */
/* ⚠️ 这个类**不是题卡总览专属**：75-time / 74-words / 76-goal / 40-archive 四个页面共用，
   #88 那次差点被我当成"仅总览用的旧样式"删掉 —— 保留。 */
.overview-header {
  display: flex;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}

/* ══════════════════════════════════════════════════════════════════════
   #89 · 全局页面头部（大厂 Dashboard 式）
   ──────────────────────────────────────────────────────────────────────
   5 个页面共用一套（HTML 由 00-core.js 的 `pageHeroHtml()` 生成）：
       大标题 32px/700  →  一行灰色数据副标题  →  一条 1px 极细分割线
   ⚠️ 顶部留白：**留一点是刻意的**（标题贴死导航栏正是"后台管理系统"的观感来源），
      但右侧插画放大到 ≈230px 高之后，`align-items:flex-end` 会把它自己顶上去，
      标题上方就空出一大块 —— 所以 #97 把 padding-top 从 **48 收到 18**。
   ⚠️ 副标题里的 emoji 全部去掉，只留「·」分隔的纯文字 + 等宽数字。
   ══════════════════════════════════════════════════════════════════════ */
.page-hero {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding: 18px 0 22px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--border);
}
.page-hero-main { min-width: 0; }

/* LG 档（默认）：所有**内页** 40px */
.page-hero-title {
  font-size: 40px;
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.025em;
  color: var(--ink);
}
.page-hero-sub {
  margin-top: 12px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-2);
  max-width: 620px;                     /* 副标题不横跨整页，读起来稳 */
  font-variant-numeric: tabular-nums;   /* 数字等宽：数值跳动时不会左右抖 */
}
.page-hero-sub b { font-weight: 600; color: var(--text); }
.page-hero-aside { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ══════════════════════════════════════════════════════════════════════
   #91 · XL 档 —— 只给「题卡总览」：巨物排版，全站唯一的视觉锚点
   ──────────────────────────────────────────────────────────────────────
   参考 Notion 官网的巨型标题，但**不做居中** —— 这是 Dashboard 不是营销页，
   下面筛选条是左对齐的，居中会让整页重心错乱；左对齐 + 右侧插画才有平衡。
   ══════════════════════════════════════════════════════════════════════ */
.page-hero.is-hero-xl {
  padding: 76px 0 40px;      /* 上下留白接近翻倍（48→76 / 28→40） */
  margin-bottom: 46px;       /* 筛选条整体往下推（32→46） */
}
.page-hero.is-hero-xl .page-hero-title {
  /* ⚠️ 用 clamp 而不是固定 56px：1440px → 56px / 1024px → 53px / 768px → 40px / 375px → 34px。
     一行搞定全部断点，中间尺寸不会断层，手机端也不会贴边（实测 6 字标题在 375px 屏刚好）。 */
  font-size: clamp(34px, 5.2vw, 56px);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.04;         /* 大字号必须收紧行高，否则标题会松散 */
}
.page-hero.is-hero-xl .page-hero-sub {
  margin-top: 20px;          /* 标题 → 副标题 的间距拉大（12 → 20） */
  font-size: 18px;
  max-width: 660px;
}
.page-hero.is-hero-xl .page-hero-art { width: 400px; }

/* #91 · Header 右侧插画：原生 SVG（不用图片 —— 任意缩放不糊、体积极小、可换色）
   #93 · 第一次放大：190px 宽（≈121px 高）→ 260px（≈165px）
   #96 · 再放大一档：clamp(240px, 25vw, 360px)
         —— 1440px 屏 360px 宽 / ≈229px 高，1080px 屏 270px / ≈172px，
            比 #93 那版再大约 38%，才压得住 56px 的巨物标题。
   ⚠️ 仍用 clamp 而不是写死：中间尺寸平滑过渡，不会在 900px 断点处「啪」地跳一下
      （≤900px 直接隐藏插画，优先保文字）。 */
.page-hero-art {
  flex: 0 0 auto;
  width: clamp(240px, 25vw, 360px);
  height: auto;
  display: block;
  opacity: 0.95;
}

/* #93 · 紧凑档（size:'sm'）—— 只给「卡片内部的头部」（强化训练筛选页）：
   它整块是嵌在 .question-card.pad-lg 里的，直接用 40px 默认档会撑破卡片、压过内容，
   所以单独收一档：标题 32px/700、副标题 14px、插画 150px（≈95px 高）。 */
.page-hero.is-hero-sm { padding: 4px 0 22px; margin-bottom: 26px; }
.page-hero.is-hero-sm .page-hero-title { font-size: 32px; font-weight: 700; letter-spacing: -0.02em; }
.page-hero.is-hero-sm .page-hero-sub { margin-top: 10px; font-size: 14px; }
.page-hero.is-hero-sm .page-hero-art { width: 150px; }

@media (max-width: 900px) {
  .page-hero.is-hero-xl { padding: 48px 0 28px; margin-bottom: 28px; }
  .page-hero.is-hero-xl .page-hero-sub { font-size: 16px; margin-top: 14px; }
  .page-hero.is-hero-sm .page-hero-title { font-size: 28px; }
  .page-hero-art { display: none; }   /* 窄屏优先保文字 */
}
@media (max-width: 600px) {
  /* #97：窄屏没有插画"顶高"，所以只留一点点上边距（20/16） */
  .page-hero { padding: 20px 0 16px; margin-bottom: 22px; }
  .page-hero-title { font-size: 30px; }
  .page-hero-sub { font-size: 14px; }
}

/* #88 · 题卡总览顶部：特大粗黑标题 + 细灰副标题 + 一条极细分割线（Notion 画廊页的做法）。
   ⚠️ 刻意**不做深色 banner** —— 顶部一条深色横条正是"后台管理系统"的典型特征。
   40px 粗标题沿用全站统一规则（.overview-title），只负责把 emoji 去掉、补一行数据副标题。 */
.overview-hero {
  margin-bottom: 20px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.overview-sub {
  margin-top: 10px;
  font-size: 13px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.overview-counts { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; font-size: 13px; }
.mini-stat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: #fff;
  box-shadow: var(--shadow-card);
  color: var(--text-2);
  font-weight: 500;
}
.mini-stat b { margin-left: 0.3rem; color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
/* 顶部统计条的数字同样跟随熟练度着色 */
.mini-stat .dot-mastered ~ b { color: var(--c-blue); }
.mini-stat .dot-good     ~ b { color: var(--c-good); }
.mini-stat .dot-needwork ~ b { color: var(--c-needwork); }
.mini-stat .dot-weak     ~ b { color: var(--c-weak); }
.mini-stat .dot-untrained ~ b { color: var(--c-untrained); }
.mini-stat.accent { background: var(--tint-green-bg); color: var(--tint-green-fg); }
.mini-stat.accent b { color: var(--tint-green-fg); }

/* 今日学习时长：右上角的一枚安静的次要信息，不带框不带底 */
.overview-today {
  margin-left: auto;
  font-size: 13px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── 题卡总览筛选区：保留大卡片包裹感，控件做轻 ─────────────────
   设计原则（Linear / Notion / Apple）：
   · 外层是白卡片：圆角 + 细边 + 微阴影，负责「整体感」
   · 内部控件全部去边框：层次只靠字重和颜色
   · 未选中 = 干净浅灰字（ghost），hover 浮出一层极淡灰
   · 选中 = 统一的极柔和浅蓝底 + 加粗深色字，不再用语义色抢占注意力
   · 计数是极弱化的次级文字，只是「顺手看见」，不是视觉主角     */
.filter-bar {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 20px 24px 22px;
  margin-bottom: 30px;
}
.filter-group { display: flex; align-items: baseline; gap: 28px; }
.filter-group + .filter-group { margin-top: 18px; }   /* 三行之间留出呼吸感 */
.filter-group-label {
  flex: 0 0 46px;
  font-size: 13px;      /* #62：12 → 13（"熟练度/分组/重点" 三个标签太小） */
  color: var(--text-3);
  /* #54：去掉 opacity:0.72 —— 它把标签压到几乎看不见，
     现在 --text-3 本身已经够浅，不需要再叠一层透明度。 */
  letter-spacing: 0.08em;
}
.filter-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.fchip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 30px;
  padding: 0 14px;
  border: none;
  border-radius: 999px;      /* 圆润胶囊 */
  background: transparent;
  font-family: inherit;
  font-size: 14px;           /* #62：13 → 14（胶囊按钮文字） */
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: background-color 0.14s var(--ease), color 0.14s var(--ease), transform 0.08s var(--ease);
}
.fchip:hover { background: rgba(0, 0, 0, 0.045); color: var(--text); }   /* 极淡的悬浮底色 */
.fchip:active { transform: scale(0.97); }
.fchip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 选中：极柔和的浅蓝底 + 加粗深色文字，克制、不抢戏 */
.fchip.active {
  background: var(--tint-blue-bg);
  color: var(--text);
  font-weight: 650;
}

/* 计数：极其弱化的次级文字，tabular-nums 保证跳动时不抖宽 */
.fchip-count {
  font-size: 12px;      /* #62：11 → 12（按钮里的计数） */
  font-weight: 500;
  color: var(--text-3);
  opacity: 0.8;
  font-variant-numeric: tabular-nums;
}
.fchip:hover .fchip-count { color: var(--text-2); opacity: 1; }
.fchip.active .fchip-count { color: var(--text); opacity: 0.55; }

/* 语义色圆点：替代原来的 emoji，静默地传达分类（唯一保留的彩色） */
.fchip-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
/* #94 · 「今日到期」拿原来的绿、「已掌握」拿蓝（两者互换，见 :root 注释） */
.fdot-due       { background: var(--c-due); }
.fdot-untrained { background: var(--c-untrained); }
.fdot-weak      { background: var(--c-weak); }
.fdot-needwork  { background: var(--c-needwork); }
.fdot-good      { background: var(--c-good); }
.fdot-mastered  { background: var(--c-blue); }

/* 星级：★ 用主题金色，比文本灰更有质感 */
.fchip-star { color: #dfab01; font-size: 13px; letter-spacing: 1px; }   /* #63：12 → 13（筛选栏「重点」那排 ★ 也是重点星星，一并大一号） */

/* ═══════════════════════════════════════════════════════════════════════════
   #88 · 题卡总览（画册级重构）
   ───────────────────────────────────────────────────────────────────────────
   ⚠️ 以前"底部乱飘"的根因：模板里分组标签排在 footer **后面** —— "有分组"的卡片
      底部比"没分组"的多出一块（约 24px），同一行的熟练度/历史永远差一截。
   现在改成 4 段**固定高度**的骨架：
       ① .qcard-head   固定 22px   题号（弱化）／星级（弱化）
       ② .qcard-title  固定 2 行   16px/600 粗黑 —— 题目是主角
       ③ .qcard-spacer flex:1      吸收所有剩余高度
       ④ .qcard-foot   固定 44px   两行：熟练度+历史 ／ 题型+分组（**没有也占位**）
   底部区高度写死 + margin-top:auto 双保险 → 所有卡片底部落在同一水平线。
   ═══════════════════════════════════════════════════════════════════════════ */
.cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }

.qcard {
  --c: var(--c-untrained);
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 158px;
  padding: 20px 20px 16px;
  border: 1px solid var(--qcard-bd, var(--qcard-border));
  border-radius: var(--r-card);
  background: var(--qcard-bg, #fff);
  box-shadow: var(--qcard-shadow);
  cursor: pointer;
  transition: background-color 0.16s var(--ease), border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
  animation: fadeUp 0.22s var(--ease);
}
/* 悬停：底色微深 + 极淡的抬升。⚠️ 不做位移、不做放大 —— 那是廉价感的来源 */
.qcard:hover {
  background: var(--qcard-bg-hover);
  border-color: var(--qcard-bd-hover);
  box-shadow: var(--qcard-shadow-hover);
}

/* 熟练度温和底色：Notion Callout 色板（#88 提高饱和度，告别一片灰扑扑） */
.qcard.prof-untrained-border {
  --c: var(--c-untrained);
  --qcard-bg: #fff;
  --qcard-bg-hover: #fafaf8;
  --qcard-bd: var(--qcard-border);
  --qcard-bd-hover: rgba(15, 15, 15, 0.14);
}
.qcard.prof-weak-border {
  --c: var(--c-weak);
  --qcard-bg: var(--tint-red-bg);
  --qcard-bg-hover: var(--tint-red-hover);
  --qcard-bd: rgba(93, 23, 21, 0.10);
  --qcard-bd-hover: rgba(93, 23, 21, 0.20);
}
.qcard.prof-needwork-border {
  --c: var(--c-needwork);
  --qcard-bg: var(--tint-orange-bg);
  --qcard-bg-hover: var(--tint-orange-hover);
  --qcard-bd: rgba(73, 41, 13, 0.10);
  --qcard-bd-hover: rgba(73, 41, 13, 0.20);
}
.qcard.prof-good-border {
  --c: var(--c-good);
  --qcard-bg: var(--tint-yellow-bg);
  --qcard-bg-hover: var(--tint-yellow-hover);
  --qcard-bd: rgba(64, 44, 27, 0.10);
  --qcard-bd-hover: rgba(64, 44, 27, 0.20);
}
/* #94 · 已掌握：绿底 → 蓝底（和「今日到期」的绿互换，见 :root 注释） */
.qcard.prof-mastered-border {
  --c: var(--c-blue);
  --qcard-bg: var(--tint-blue-bg);
  --qcard-bg-hover: var(--tint-blue-hover);
  --qcard-bd: rgba(24, 51, 71, 0.10);
  --qcard-bd-hover: rgba(24, 51, 71, 0.20);
}

/* ① 头部：固定 22px —— 题号弱化成灰字（**去掉边框**，那个边框让它像个小按钮） */
.qcard-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 22px; }
.qcard-no {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--text-3);
}
.qcard-stars { font-size: 12px; letter-spacing: 0.06em; opacity: 0.85; white-space: nowrap; }
.qcard-stars:empty { display: none; }
.qcard-stars .star { color: rgba(55, 53, 47, 0.22); }
.qcard-stars .star.active { color: #dfab01; }

/* ② 题目：固定 2 行（16 × 1.45 × 2 ≈ 46px）—— 行数不再影响下方任何元素 */
.qcard-title {
  min-height: 46px;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -0.005em;
  color: var(--ink);
  word-break: break-word;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* ③ 弹性空白：吃掉所有剩余高度，把底部区顶到卡片最下缘 */
.qcard-spacer { flex: 1 1 auto; min-height: 4px; }

/* ④ 底部：固定两行（20 + 4 + 20 = 44px）。margin-top:auto 是第二道保险 */
.qcard-foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: 12px;
  /* 半透明白线在「未练习」的白底卡上会完全消失，所以用极淡的暖黑 —— 在白底和彩色底上都看得见且柔和 */
  border-top: 1px solid rgba(55, 53, 47, 0.07);
}
.qcard-foot-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 20px; }
.qcard-prof { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; color: var(--text-2); }
.qcard-prof::before {
  content: '';
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--c);
  display: inline-block;
  flex: 0 0 auto;
}
.qcard-history {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: var(--text-3);
}
/* 第 2 行：题型（类目）+ 分组。**没有内容也占位** —— 这是底部对齐的关键 */
.qcard-meta { display: flex; align-items: center; gap: 8px; min-height: 20px; overflow: hidden; }
.qcard-type {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  color: var(--text-3);
  white-space: nowrap;
}
/* 类目色点：饱和度压低，只是"分类提示"，不抢题目的注意力 */
.qcard-type.qt-behavioral { --qt-c: #8b7cc8; }
.qcard-type.qt-opinion    { --qt-c: #4f83b8; }
.qcard-type.qt-factual    { --qt-c: #5d9370; }
.qcard-type.qt-none       { --qt-c: rgba(55, 53, 47, 0.28); }
.qcard-type::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 1px;
  background: var(--qt-c, var(--text-3));
  flex: 0 0 auto;
}
.qcard-group-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  padding: 1px 7px;
  border-radius: var(--r-xs);
  background: rgba(255, 255, 255, 0.66);   /* 半透明白，能融入任何熟练度底色 */
  font-size: 11px;
  font-weight: 500;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ══════════════════════════════════════════════════════════════════════
   10. 题库设置
   ══════════════════════════════════════════════════════════════════════ */
.block { margin-bottom: 32px; }
.block-head { margin-bottom: 16px; }
.group-panel, .voice-panel { padding: 20px 24px; }
.group-panel-header { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.group-panel-header .title { font-size: 12px; font-weight: 600; letter-spacing: 0.02em; color: var(--text-3); }
.group-list { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.group-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 4px 3px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  font-size: 13px;
  color: var(--text);
}
.group-chip .chip-name { cursor: pointer; }
.group-chip .chip-name:hover { color: var(--text-2); text-decoration: underline; }
.group-chip .chip-count {
  padding: 0 6px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-3);
}
.chip-del {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px; height: 20px;
  border-radius: var(--r-xs);
  font-size: 14px;
  color: var(--text-3);
}
.chip-del:hover { background: #ffe2dd; color: #5d1715; }
.add-group-btn {
  height: 28px;
  padding: 0 11px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
}
.add-group-btn:hover { background: var(--bg-subtle); color: var(--text); }
.group-empty-hint { font-size: 14px; color: var(--text-3); }

.voice-panel { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
/* #89 / #92 · 朗读卡：纵向堆叠
   ⚠️ 必须用 `#backendPage .voice-panel.voice-panel-stack`（ID + 双类）来写：
      下面 `#backendPage .voice-panel` 是 **ID 选择器**，优先级高于单类 `.voice-panel-stack`，
      之前就是被它盖掉了 —— 所以朗读卡实际上一直是 row + wrap，纵向规则根本没生效。 */
.voice-panel-stack { flex-direction: column; align-items: stretch; gap: 14px; }
.voice-panel-stack > .field { flex-direction: column; align-items: flex-start; gap: 6px; }
.voice-panel-stack > .field > select { width: 100%; }
#backendPage .voice-panel.voice-panel-stack { flex-direction: column; align-items: stretch; gap: 14px; }
/* ⚠️ **真正把朗读卡拉高的元凶**：`#backendPage .voice-panel .voice-actions { flex: 1 1 220px }`
   —— 在纵向布局里 `flex-basis: 220px` 指的是**高度基准 220px**，
   于是 `.voice-actions` 被强行撑成 220px 高，整张卡被拉到 560px、底部一大片白。 */
#backendPage .voice-panel.voice-panel-stack .voice-actions {
  flex: 0 0 auto;
  min-height: 0;
  width: 100%;
}
#backendPage .voice-panel.voice-panel-stack > .field { flex: 0 0 auto; }

/* ══════════════════════════════════════════════════════════════════════
   #94 · 朗读卡：「左标签 / 右操作」两列（并去掉「操作」这个标签）
   ──────────────────────────────────────────────────────────────────────
   左列：模型、音色、音色提示   ·   右列：试听、刷新音色列表、自动朗读
   用 grid 排成 **三行两列**，右列三件东西因此与左列三行落在同一水平线
   （用户要的"相互对齐"），而不是两个各自溢出的 flex 块。
   ⚠️ `align-items:end` 而不是 center：让按钮**底边**与左边下拉框底边齐平；
      center 会把按钮飘在「小标题 + 下拉框」的中间，看着像没对齐。
   ⚠️ 优先级：ID + 双类 > `#backendPage .voice-panel`（ID + 单类），
      所以不会被 row/wrap 或 ≤980px 的 column 规则反盖。
   ══════════════════════════════════════════════════════════════════════ */
#backendPage .voice-panel.voice-2col {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  align-items: end;
  column-gap: 24px;
  row-gap: 14px;
}
#backendPage .voice-panel.voice-2col > .field { flex: 0 0 auto; min-width: 0; max-width: none; }
#backendPage .voice-panel.voice-2col > .btn,
#backendPage .voice-panel.voice-2col > .toggle { justify-self: start; }
/* 按钮高度锁 32px = 左侧 select 的高度（去掉 .voice-row 包装后不再继承那条规则） */
#backendPage .voice-panel.voice-2col > .btn { height: 32px; padding: 0 12px; font-size: 13px; white-space: nowrap; }
#backendPage .voice-panel.voice-2col > .voice-toggle { margin-left: 0; }
#backendPage .voice-panel.voice-2col > .voice-hint { margin-top: 0; }
/* 窄屏（≤600px）：「刷新音色列表」这类长按钮在窄列里会挤成两行，退回单列堆叠 */
@media (max-width: 600px) {
  #backendPage .voice-panel.voice-2col { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
}
/* 提示文字紧跟在「音色」下拉框正下方 —— 以前挂在操作列下面，导致卡片底部空出一块 */
.voice-hint-inline { margin-top: 2px; font-size: 11.5px; line-height: 1.5; }
/* 自动朗读开关：从顶部导航栏搬到这里（id 不变，JS 绑定无需改动） */
.voice-toggle { flex: 0 0 auto; margin-left: auto; }
.voice-actions { flex-direction: column; align-items: flex-start; gap: 8px; }
.voice-row { display: flex; align-items: center; gap: 10px; }
.voice-hint { font-size: 12px; color: var(--text-3); }
.voice-hint.ok { color: var(--c-mastered); }
.voice-hint.warn { color: var(--c-weak); }

/* 全局「生成语音中」徽标（自动朗读时没有按钮可以反馈状态） */
.tts-badge {
  position: fixed;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border: 1px solid rgba(35, 131, 226, 0.28);
  border-radius: 999px;
  background: var(--tint-blue-bg);
  color: var(--tint-blue-fg);
  box-shadow: var(--shadow-lift);
  font-size: 13px;
  font-weight: 500;
  pointer-events: none;
}
.tts-badge.hide { display: none; }
.tts-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 2px solid rgba(35, 131, 226, 0.25);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: speakSpin 0.65s linear infinite;
}
.field { display: inline-flex; align-items: center; gap: 10px; font-size: 13px; color: var(--text-2); }
.field-label { font-size: 13px; font-weight: 500; color: var(--text-2); }
.voice-panel select { max-width: 320px; }
.field input[type="range"] { width: 110px; }
.range-val {
  min-width: 34px;
  text-align: right;
  font-size: 12px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.check { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-2); cursor: pointer; }
.voice-panel optgroup { font-weight: 600; color: var(--text); }

.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 24px; }
/* #89 · 上线清理：「✅ 已连接服务器 / 保存失败」这行小字是开发者痕迹，UI 上隐藏。
   ⚠️ 逻辑保留（updateFileStatus 仍在跑，断网时它会弹 toast）。
   ⚠️ 必须 !important —— 否则 `display:inline-flex` 会盖掉 HTML 上的 hidden 属性。 */
.file-status {
  display: none !important;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  font-size: 13px;
  color: var(--text-2);
}
.tip-line { margin-bottom: 16px; font-size: 13px; color: var(--text-3); }

.question-list { display: flex; flex-direction: column; gap: 8px; max-height: 660px; overflow-y: auto; padding-right: 4px; }
/* ══════════════════════════════════════════════════════════════════════
   #98 · 题目列表：每一行 = 固定列的「表格行」
   ──────────────────────────────────────────────────────────────────────
   之前为什么会乱（三个根因一起发作）：
     ① 文本块 min-height:38 + 2 行截断 → 只有 1 行文字的行 60px、2 行的 82px，行高参差
     ② 右侧控件宽度**跟着内容变**（分组下拉 / 熟练度徽章 / 其它问法按钮 全都不同宽）
     ③ flex-wrap + 前两列按 3:2.5 吸收剩余空间 → 控件随文字长短左右漂移
   修法：**行高锁死 + 右侧全部定宽 + 题目/答案各 flex:1 平分**，
        于是每一列的 x 坐标在全表都一模一样 —— Notion 数据库那种观感。
   ══════════════════════════════════════════════════════════════════════ */
.question-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;          /* ⚠️ 关键：绝不允许折行，一折列就对不齐 */
  padding: 12px 16px;
  min-height: 62px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
  box-shadow: var(--shadow-card);
  transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease);
}
.question-row:hover { background: var(--bg-subtle); border-color: var(--border-2); }
.question-row > .index {
  flex: 0 0 32px;
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-3);
  white-space: nowrap;
}
/* #98 · 单行 + 省略号（原来 2 行截断正是行高不一致的元凶）。
   超长内容照样看得到：title 悬浮提示 + 点一下开编辑弹窗，交互一点没变。 */
.clickable-input {
  height: 38px;
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  font-size: 14px;
  line-height: 20px;
  color: var(--text);
  cursor: pointer;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.clickable-input:hover { background: #fff; border-color: var(--border-2); }
.clickable-input.empty { color: var(--text-3); }
/* 题目 / 答案各占一半剩余宽度 —— 两者之间是同一条竖中线，全表一致 */
.question-row > .q-input,
.question-row > .a-input { flex: 1 1 0; min-width: 0; }

/* ── #98 · 定宽列 ────────────────────────────────────────────────────
   全部写成 `.question-row > .xxx`（两个类 > 一个类）：
   `.group-select-row` / `.proficiency-badge` / `.variant-row-btn` 在别处也在用，
   绝不能改它们的全局宽度，只能在这一行里定宽。 */
.question-row > .group-select-row {
  flex: 0 0 84px;
  max-width: none;
  height: 32px;
}
.question-row > .star-cell { flex: 0 0 62px; overflow: hidden; }
.question-row > .proficiency-badge {
  flex: 0 0 150px;
  display: block;               /* inline-flex 撑不住省略号，必须换掉 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.question-row > .variant-row-btn {
  flex: 0 0 108px;
  min-width: 0;
  height: 30px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.question-row > .qt-select { flex: 0 0 88px; min-width: 0; height: 30px; }
/* 两个图标按钮收成一组（行模板里已包一层 .row-icons），否则会各自按内容占宽 */
.question-row > .row-icons { flex: 0 0 56px; display: flex; justify-content: flex-end; gap: 4px; }
.question-row > .row-icons .btn-icon { flex: 0 0 26px; width: 26px; height: 26px; }

/* ── #98 · 响应式：先分档收窄，实在放不下才堆叠 ────────────────────── */
@media (max-width: 1280px) {
  .question-row > .group-select-row { flex: 0 0 76px; }
  .question-row > .star-cell        { flex: 0 0 58px; }
  .question-row > .proficiency-badge{ flex: 0 0 128px; }
  .question-row > .variant-row-btn  { flex: 0 0 92px; }
  .question-row > .qt-select        { flex: 0 0 80px; }
}
/* ≤1024：题目/答案会被压到 100px 出头没法读 —— 改成堆叠
   （题号+题目一行 / 答案一行 / 控件一行）。对齐没了但可读性优先。 */
@media (max-width: 1024px) {
  .question-row { flex-wrap: wrap; row-gap: 8px; min-height: 0; }
  .question-row > .q-input { flex: 1 1 calc(100% - 40px); }
  .question-row > .a-input { flex: 1 1 100%; }
  .question-row > .group-select-row,
  .question-row > .star-cell,
  .question-row > .proficiency-badge,
  .question-row > .variant-row-btn,
  .question-row > .qt-select,
  .question-row > .row-icons { flex: 0 0 auto; }
  .question-row > .proficiency-badge { flex: 0 0 auto; }
}
.group-select-inline, .group-select-row {
  max-width: 170px;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  outline: none;
}
.star-cell { display: inline-flex; align-items: center; padding: 0 2px; }
.save-btn {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  flex-shrink: 0;
}
.save-btn:hover { background: var(--bg-subtle); }
.save-btn.saved { background: #dbeddb; color: #1c3829; border-color: transparent; }
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  border-radius: var(--r-sm);
  font-size: 15px;
  color: var(--text-3);
  flex-shrink: 0;
}
.btn-icon:hover { background: var(--bg-hover); color: var(--text); }
.btn-icon.delete:hover { background: #ffe2dd; color: #5d1715; }
.add-btn {
  height: 36px;
  padding: 0 18px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
}
.add-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.settings-header { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; margin-bottom: 40px; }

/* ══════════════════════════════════════════════════════════════════════
   11. 单词统计
   ══════════════════════════════════════════════════════════════════════ */
.word-stats-summary { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; margin-bottom: 32px; }
.ws-card { padding: 20px 24px; }
.ws-card .ws-num { font-size: 30px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); font-variant-numeric: tabular-nums; }
.ws-card .ws-lbl { margin-top: 2px; font-size: 12px; font-weight: 500; color: var(--text-3); }
.ws-controls {
  display: flex;
  align-items: center;
  /* #99：间距 20 → 12 —— 下拉框统一加最小宽度后，20px 的间距会在 1080px 屏把最后一个
     下拉挤到第二行，收窄间距刚好保住「一整排」 */
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 24px;
  padding: 18px 24px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
}
/* 标签 + 控件是一个整体：要么同行并排，要么整块掉到下一行，绝不允许上下错位 */
.ws-controls label { display: inline-flex; flex-wrap: nowrap; align-items: center; gap: 10px; font-size: 13px; font-weight: 500; color: var(--text-2); white-space: nowrap; flex: 0 0 auto; }
/* 单词统计筛选行：所有控件统一 36px 高、垂直居中；空间不够整块折行 */
.ws-controls label select, .ws-controls label input[type="text"] { height: 36px; }
/* #99 · 四个下拉框统一最小宽度。
   之前每个 <select> 按自己最长的那条 option 定宽 —— 来源 65 / 分组 102 / 最低频率 68 /
   排序 70，一排看过去参差不齐。给 min-width（不是固定宽度）：短选项的会统一撑到 88px，
   分组名特别长时仍然可以自己变宽，不会把名字截掉。 */
.ws-controls label select { min-width: 88px; }

/* ══ #100 · 筛选栏改成「标签在上、控件在下」的等宽网格 ════════════════════
   为什么改：之前六个控件挤在一条 flex 行里，每个下拉框按自己最长的那条 option 定宽
   （来源 65 / 分组 102 / 最低频率 68 / 排序 70），右侧还空出一大块 —— 在 2560px 宽的屏上
   整行显得又散又乱；而且「统一最小宽度」这种 20px 级的微调，缩放后肉眼几乎看不出来。
   现在：6 列网格 = 搜索 260 + 4 个下拉各 1fr + 按钮 auto，
   标签统一变成压在控件上方的小字 → 四个下拉框**严格等宽**、整行铺满、右侧不再留白。
   ⚠️ 只在 ≥900px 生效；≤768px 另有「标签在上、两列」的移动版规则。 */
@media (min-width: 900px) {
  .ws-controls {
    display: grid;
    grid-template-columns: 260px repeat(4, minmax(0, 1fr)) auto;
    align-items: end;
    gap: 14px 16px;
  }
  .ws-controls label {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--text-3);
  }
  /* 搜索框那个 label 只有一个小放大镜，堆成上下会很奇怪 → 保持横排，靠底对齐 */
  .ws-controls label:first-child {
    flex-direction: row;
    align-items: center;
    gap: 8px;
    color: var(--text-2);
  }
  .ws-controls label select,
  .ws-controls label input[type="text"],
  .ws-controls label:first-child input[type="text"] { width: 100%; min-width: 0; }
  .ws-controls label select { min-width: 0; }   /* 网格已保证等宽，不再靠 88px 撑 */
  .ws-refresh { align-self: end; }
}
/* #104 · 补上「769–899px」这一档
   ────────────────────────────────────────────────────────────
   以前只有两档：≥900px 是 6 列网格、≤768px 是手机版两列网格，
   **中间这 130px 宽的区间两边都够不着**，只能掉回最原始的 flex 行 ——
   六个控件按各自内容宽挤成一排，和上下两个区间都长得不一样
   （窗口拉到 800px 时，筛选栏会突然变成第三种排法）。
   现在补一档 3 列网格：搜索框整行、4 个下拉按 3+1 落位、按钮整行，
   观感与两侧连贯，不再有"中间断层"。 */
@media (min-width: 769px) and (max-width: 899px) {
  .ws-controls {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: end;
    gap: 12px 14px;
  }
  .ws-controls label {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 500;
    color: var(--text-3);
    white-space: nowrap;
    min-width: 0;
  }
  .ws-controls label:first-child {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    color: var(--text-2);
  }
  .ws-controls label select,
  .ws-controls label input[type="text"] { width: 100%; min-width: 0; }
  .ws-refresh { grid-column: 1 / -1; }
}
.ws-controls label:first-child input[type="text"] { width: 220px; min-width: 140px; flex-shrink: 1; }
.ws-refresh {
  height: 36px;
  padding: 0 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
}
.ws-refresh:hover { background: var(--bg-callout); }
.ws-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.ws-toolbar .ws-count { font-size: 13px; color: var(--text-2); }
.ws-table-wrap { max-height: 640px; overflow-y: auto; border: 1px solid var(--border); border-radius: var(--r-md); background: #fff; }
/* ══ #99 · 表格右上角那道「白缺口」════════════════════════════════════
   内滚动条会占掉 ~15px 宽，而吸顶表头的灰底只铺到滚动条**左边**，
   于是右上圆角处露出一块白、圆角也被方角顶破；顺带最后一列的 chip 贴着滚动条。
   修法：① 滚动条改细（10px）+ 无边框的胶囊 thumb ② 给滚动条预留稳定空间
        ③ 表头首/末格补圆角，灰底与圆角严丝合缝。 */
.ws-table-wrap { scrollbar-width: thin; scrollbar-gutter: stable; }
.ws-table-wrap::-webkit-scrollbar { width: 10px; }
.ws-table-wrap::-webkit-scrollbar-track { background: transparent; }
.ws-table-wrap::-webkit-scrollbar-thumb {
  background: rgba(55, 53, 47, 0.16);
  background-clip: padding-box;   /* 配透明边框 → 6px 的细胶囊，不撑满整条轨道 */
  border: 2px solid transparent;
  border-radius: 999px;
}
.ws-table-wrap::-webkit-scrollbar-thumb:hover { background: rgba(55, 53, 47, 0.3); background-clip: padding-box; }
.ws-table thead th:first-child { border-top-left-radius: var(--r-md); }
.ws-table thead th:last-child  { border-top-right-radius: var(--r-md); }
/* 最后一列留出一点内边距，chip 不再贴着滚动条 */
.ws-table th:last-child, .ws-table td:last-child { padding-right: 14px; }
.ws-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.ws-table thead { position: sticky; top: 0; background: var(--bg-subtle); z-index: 2; }
.ws-table th {
  padding: 10px 20px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-3);
}
.ws-table td { padding: 10px 20px; border-bottom: 1px solid var(--border); vertical-align: top; }
.ws-table tr { transition: background-color 0.12s var(--ease); }
.ws-table tr:hover { background: var(--bg-subtle); }
.ws-word { font-weight: 500; cursor: pointer; }
.ws-word:hover { color: var(--c-blue); text-decoration: underline; }
.ws-freq { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 600; }
.ws-variants, .ws-locs { font-size: 12px; color: var(--text-3); }
.td-muted { font-size: 12px; color: var(--text-3); white-space: nowrap; }
.ws-loc-chip {
  display: inline-block;
  margin: 2px;
  padding: 0 7px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  cursor: pointer;
}
.ws-loc-chip:hover { background: #e3e2e0; color: var(--text); }
.more-count { font-size: 12px; color: var(--text-3); }

/* ══════════════════════════════════════════════════════════════════════
   12. 学习时间
   ══════════════════════════════════════════════════════════════════════ */
.tsummary-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; margin-bottom: 32px; }
/* 四张数据卡：四个不同颜色的浅色块，数据看板一眼看过去很丰富 */
.tsummary-card { padding: 22px 26px; }
.tsummary-card .ts-label { display: flex; align-items: center; font-size: 12px; font-weight: 500; letter-spacing: 0.02em; color: var(--text-3); }
.tsummary-card .ts-label::before {
  content: '';
  width: 7px; height: 7px;
  margin-right: 8px;
  border-radius: 2px;
  background: var(--c-mastered);
}
.tsummary-card.blue   .ts-label::before { background: var(--c-blue); }
.tsummary-card.purple .ts-label::before { background: var(--c-purple); }
.tsummary-card.orange .ts-label::before { background: var(--c-needwork); }
.tsummary-card .ts-value { margin-top: 6px; font-size: 30px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); font-variant-numeric: tabular-nums; }
.tsummary-card .ts-sub { margin-top: 2px; font-size: 12px; color: var(--text-3); }

.tsummary-card        { background: var(--tint-green-bg);  border-color: rgba(68, 131, 97, 0.14); }
.tsummary-card.blue   { background: var(--tint-blue-bg);   border-color: rgba(35, 131, 226, 0.14); }
.tsummary-card.purple { background: var(--tint-purple-bg); border-color: rgba(144, 101, 176, 0.14); }
.tsummary-card.orange { background: var(--tint-yellow-bg); border-color: rgba(203, 145, 47, 0.16); }
.tsummary-card        .ts-value { color: var(--tint-green-fg); }
.tsummary-card.blue   .ts-value { color: var(--tint-blue-fg); }
.tsummary-card.purple .ts-value { color: var(--tint-purple-fg); }
.tsummary-card.orange .ts-value { color: var(--tint-yellow-fg); }
.tsummary-card        .ts-label, .tsummary-card        .ts-sub { color: var(--tint-green-fg);  opacity: 0.75; }
.tsummary-card.blue   .ts-label, .tsummary-card.blue   .ts-sub { color: var(--tint-blue-fg);   opacity: 0.75; }
.tsummary-card.purple .ts-label, .tsummary-card.purple .ts-sub { color: var(--tint-purple-fg); opacity: 0.75; }
.tsummary-card.orange .ts-label, .tsummary-card.orange .ts-sub { color: var(--tint-yellow-fg); opacity: 0.75; }

.cal-wrap { padding: 24px 28px; margin-bottom: 32px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }
.cal-title { font-size: 16px; font-weight: 600; color: var(--text); }
.cal-nav { display: flex; gap: 6px; }
.cal-nav button {
  height: 30px;
  min-width: 32px;
  padding: 0 10px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  color: var(--text-2);
}
.cal-nav button:hover { background: var(--bg-subtle); color: var(--text); }
.today-btn { font-size: 13px; }

.chart { display: flex; align-items: flex-end; gap: 14px; height: 180px; padding: 16px 0; }
.chart-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.chart-value { margin-bottom: 6px; font-size: 12px; font-weight: 600; color: var(--text-3); }
/* #95 · 柱状图跟热力图统一走蓝色系（数据可视化用蓝，绿色留给「今日到期」语义） */
.chart-bar { width: 100%; max-width: 60px; background: var(--c-chart); border-radius: var(--r-sm) var(--r-sm) 0 0; transition: height 0.3s var(--ease); }
.chart-day { margin-top: 8px; font-size: 13px; font-weight: 600; color: var(--text-2); }
.chart-date { font-size: 12px; color: var(--text-3); }

.cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-bottom: 8px; }
.cal-weekdays div { padding: 4px 0; text-align: center; font-size: 12px; font-weight: 500; color: var(--text-3); }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; }
.cal-cell {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 8px;
  min-height: 80px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
  cursor: pointer;
  transition: border-color 0.12s var(--ease), background-color 0.12s var(--ease);
}
.cal-cell:hover { border-color: var(--border-2); }
.cal-cell.other-month { opacity: 0.4; cursor: default; }
.cal-cell.today { border-color: var(--text); }
.cal-date { font-size: 12px; font-weight: 600; color: var(--text-2); }
.cal-cell.today .cal-date { color: var(--ink); }
.cal-time { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; font-weight: 600; color: var(--text); }
.cal-time.small { font-size: 12px; font-weight: 400; color: var(--text-3); }
/* 热力图：#94 之后**全站只在"熟练度"层用色彩语义**，学习时长属于"数据可视化"，
   绿色已被「今日到期」占用 → 整条色阶改蓝色系（极浅蓝 → 沉稳蓝 #337ea9）。
   ⚠️ 深的尽头用 #337ea9（Notion 的 blue-text 级饱和）而不是主色 #2383e2：
      后者太跳，一整片日历格会刺眼；这个饱和度和原来那抹 #448361 视觉重量一致。 */
.heat-0 { background: #fff; }
.heat-1 { background: #eaf3f8; border-color: #d9e9f2; }
.heat-2 { background: #cfe3ef; border-color: #bbd7e7; }
.heat-3 { background: #a6cbe0; border-color: #93bfd8; }
.heat-4 { background: #6fa9c9; border-color: #5b9abd; }
.heat-5 { background: var(--c-chart); border-color: #2a7099; }
.heat-5 .cal-time, .heat-5 .cal-date { color: #fff; }

.ts-detail { padding: 24px 28px; }
.ts-detail-title { margin-bottom: 16px; font-size: 16px; font-weight: 600; color: var(--text); }
.ts-session-list { display: flex; flex-direction: column; gap: 8px; max-height: 420px; overflow-y: auto; }
.ts-session-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px;
  border-left: 2px solid var(--c-untrained);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  font-size: 14px;
}
.ts-session-item.learn    { border-left-color: var(--c-purple); }
.ts-session-item.practice { border-left-color: var(--c-blue); }
.ts-icon { font-size: 16px; }
.ts-info { flex: 1; }
.ts-name { font-weight: 500; color: var(--text); }
.ts-time { margin-top: 2px; font-size: 12px; color: var(--text-3); }
.ts-duration { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 600; font-size: 14px; }
.total-row {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  text-align: right;
  font-weight: 600;
  color: var(--ink);
}

/* ══════════════════════════════════════════════════════════════════════
   13. 学习计划
   ══════════════════════════════════════════════════════════════════════ */
.goal-setup { padding: 26px 30px; margin-bottom: 32px; background: #fff; border: 1px solid var(--border); border-radius: var(--r-card); box-shadow: var(--shadow-card); }
.goal-form-row { display: flex; gap: 24px; flex-wrap: wrap; margin-bottom: 20px; }
.goal-form-row label { display: inline-flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 500; color: var(--text-2); }
.field-label { display: block; margin-bottom: 10px; }
.weekday-picker { display: flex; gap: 6px; flex-wrap: wrap; }
.time-block-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
  font-size: 13px;
  color: var(--text-2);
}
.block-start, .block-end { max-width: 130px; }
.del-block-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  color: var(--text-3);
}
.del-block-btn:hover { background: #ffe2dd; color: #5d1715; }
.add-block-btn {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
.add-block-btn:hover { background: var(--bg-subtle); }
.scope-list { display: flex; flex-direction: column; gap: 8px; font-size: 14px; color: var(--text); }
.scope-list label { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.goal-generate-btn {
  height: 40px;
  padding: 0 28px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
}
.goal-generate-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

.goal-plan-result { padding: 28px 32px; animation: fadeUp 0.24s var(--ease); }
.plan-header { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); margin-bottom: 8px; }
.plan-badge {
  display: inline-flex;
  align-items: center;
  height: 20px;
  margin-left: 10px;
  padding: 0 8px;
  border-radius: var(--r-xs);
  font-size: 11px;
  font-weight: 600;
  vertical-align: middle;
}
.plan-badge.ok   { background: #dbeddb; color: #1c3829; }
.plan-badge.warn { background: #fadec9; color: #49290d; }
.plan-badge.fail { background: #ffe2dd; color: #5d1715; }
.plan-sub { font-size: 13px; color: var(--text-3); }
.plan-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin: 24px 0; }
/* 数据看板：四种温和底色循环，让统计活起来 */
.plan-stat { padding: 14px 18px; background: var(--bg-subtle); border: 1px solid transparent; box-shadow: none; border-radius: var(--r-md); }
.plan-stat .num { font-size: 24px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); font-variant-numeric: tabular-nums; }
.plan-stat .lbl { margin-top: 2px; font-size: 12px; font-weight: 500; color: var(--text-3); }

.plan-stat:nth-child(4n+1) { background: var(--tint-blue-bg); }
.plan-stat:nth-child(4n+2) { background: var(--tint-purple-bg); }
.plan-stat:nth-child(4n+3) { background: var(--tint-yellow-bg); }
.plan-stat:nth-child(4n+4) { background: var(--tint-green-bg); }
.plan-stat:nth-child(4n+1) .num { color: var(--tint-blue-fg); }
.plan-stat:nth-child(4n+2) .num { color: var(--tint-purple-fg); }
.plan-stat:nth-child(4n+3) .num { color: var(--tint-yellow-fg); }
.plan-stat:nth-child(4n+4) .num { color: var(--tint-green-fg); }
.plan-stat:nth-child(4n+1) .lbl { color: var(--tint-blue-fg); opacity: 0.7; }
.plan-stat:nth-child(4n+2) .lbl { color: var(--tint-purple-fg); opacity: 0.7; }
.plan-stat:nth-child(4n+3) .lbl { color: var(--tint-yellow-fg); opacity: 0.7; }
.plan-stat:nth-child(4n+4) .lbl { color: var(--tint-green-fg); opacity: 0.7; }
.plan-alert {
  margin-bottom: 20px;
  padding: 16px 20px;
  border-radius: var(--r-md);
  font-size: 14px;
  line-height: 1.6;
}
.plan-alert.fail { background: #ffe2dd; color: #5d1715; }
.plan-alert.warn { background: #fadec9; color: #49290d; }
.plan-alert.ok   { background: #dbeddb; color: #1c3829; }

.daily-plan-list { display: flex; flex-direction: column; gap: 8px; max-height: 520px; overflow-y: auto; margin-top: 14px; }
.daily-plan-item {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 14px 18px;
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  font-size: 14px;
}
.daily-plan-item.rest { color: var(--text-3); }
.dp-date { min-width: 130px; font-weight: 500; color: var(--text); }
.dp-time { min-width: 130px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; color: var(--text-2); }
.dp-tasks { flex: 1; font-size: 13px; color: var(--text-2); }
.dp-duration { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 600; }
.dp-blocks { display: flex; gap: 5px; flex-wrap: wrap; width: 100%; margin-top: 10px; }
.pomodoro-visual {
  margin: 24px 0;
  padding: 18px 22px;
  border-radius: var(--r-md);
  background: #fdecc8;
  color: #402c1b;
}
.pv-title { margin-bottom: 12px; font-size: 13px; font-weight: 600; }
.pv-blocks { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pomodoro-block { padding: 2px 9px; border-radius: var(--r-xs); font-size: 12px; font-weight: 600; }
.pomodoro-block.study { background: var(--text); color: #fff; }
.pomodoro-block.break, .pomodoro-block.long-break { background: rgba(255, 255, 255, 0.7); color: #402c1b; }
.pv-arrow { font-size: 12px; color: #402c1b; }
.pv-loop { font-size: 12px; color: var(--text-3); }
.pv-tip { margin-top: 10px; font-size: 12px; color: #402c1b; }

/* ══════════════════════════════════════════════════════════════════════
   14. 存档
   ══════════════════════════════════════════════════════════════════════ */
/* ── 多问法（Variants） ── */
.variant-count {
  margin-left: auto;
  padding: 1px 8px;
  border-radius: var(--r-xs);
  background: var(--tint-purple-bg);
  color: var(--tint-purple-fg);
  font-size: 11px;
  font-weight: 600;
}
.variant-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.variant-row { display: flex; align-items: flex-start; gap: 10px; }
.variant-idx {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  margin-top: 6px;
  border-radius: var(--r-xs);
  background: var(--tint-blue-bg);
  color: var(--tint-blue-fg);
  font-size: 11px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.variant-input {
  flex: 1 1 260px;
  /* 一行最多有 4 个按钮，给输入框留够下限宽度，避免被挤成一条缝 */
  min-width: 220px;
  max-width: none;
  /* #91：原来 rows=2 让「其它问法」输入框约 60px 高，一行文字却占两行，很松散。
     改成 rows=1（见 60-variants.js）+ 这里锁 44px，输入长了可以自己拖高。 */
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--tint-blue-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  line-height: 1.55;
  resize: vertical;
  outline: none;
  transition: border-color 0.12s var(--ease), background-color 0.12s var(--ease);
}
.variant-input:focus { border-color: rgba(35, 131, 226, 0.5); background: #fff; }
.variant-input::placeholder { color: var(--text-3); }
.variant-del {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  margin-top: 4px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease);
}
.variant-del:hover { background: var(--tint-red-bg); border-color: rgba(196, 85, 77, 0.3); }

/* 行内「朗读」「设为主问法」：行里有多个按钮时整体会换行，不再挤压输入框 */
.variant-speak {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text-2);
  font-size: 13px;
  cursor: pointer;
  transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease), color 0.12s var(--ease);
}
.variant-speak:hover { background: var(--tint-blue-bg); border-color: rgba(35, 131, 226, 0.3); color: var(--tint-blue-fg); }
.variant-promote {
  white-space: nowrap;
  font-size: 12px;
  color: var(--text-2);
}
.variant-promote:hover { background: var(--tint-blue-bg); border-color: rgba(35, 131, 226, 0.3); color: var(--tint-blue-fg); }

/* 「↩ 撤销」：只在刚生成过、内容还是 AI 原样时出现，用完即消失 */
.variant-undo {
  white-space: nowrap;
  font-size: 12px;
  color: var(--text-2);
  border-color: rgba(35, 131, 226, 0.35);
  background: var(--tint-blue-bg);
}
.variant-undo:hover { background: var(--tint-blue-bg); border-color: rgba(35, 131, 226, 0.6); color: var(--tint-blue-fg); }
/* 已保存的行不显示 AI 生成按钮：想重新生成必须先删掉这一行 */
.variant-row[data-draft="0"] .variant-ai { display: none; }
/* JS 用 hidden 控制显隐时，避免被上面的 flex / inline-flex 样式覆盖 */
.variant-ai[hidden], .variant-speak[hidden], .variant-promote[hidden], .variant-undo[hidden] { display: none !important; }
.variant-row { flex-wrap: wrap; }
/* AI 生成按钮：Notion AI 那种淡紫磐感 */
.variant-ai {
  position: relative;
  flex-shrink: 0;
  height: 28px;
  margin-top: 4px;
  padding: 0 11px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid rgba(144, 101, 176, 0.28);
  border-radius: var(--r-sm);
  background: var(--tint-purple-bg);
  color: var(--tint-purple-fg);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.14s var(--ease), border-color 0.14s var(--ease), box-shadow 0.14s var(--ease), transform 0.14s var(--ease);
}
.variant-ai:hover {
  background: #efe7f4;
  border-color: rgba(144, 101, 176, 0.5);
  box-shadow: 0 1px 2px rgba(144, 101, 176, 0.12);
  transform: translateY(-1px);
}
.variant-ai:active { transform: none; }
/* 「🔄 换一个」态略微加深，和「✨ 生成」区分开 */
.variant-ai[data-ai-state="regen"] {
  background: #f0e9f5;
  border-color: rgba(144, 101, 176, 0.42);
}
.variant-ai[data-ai-state="regen"]:hover { background: #e9e0f1; }
/* 加载中：置灰 + 转圈，防连点 */
.variant-ai.loading,
.variant-ai:disabled {
  background: var(--bg-subtle);
  border-color: var(--border);
  color: var(--text-3);
  cursor: default;
  box-shadow: none;
  transform: none;
}
.ai-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 2px solid rgba(55, 53, 47, 0.15);
  border-top-color: var(--c-purple);
  border-radius: 50%;
  animation: aiSpin 0.65s linear infinite;
}
@keyframes aiSpin { to { transform: rotate(360deg); } }
.variant-add-btn { width: 100%; height: 34px; font-size: 13px; font-weight: 500; }
.variant-add-btn:hover { background: var(--bg-callout); }
.variant-empty {
  padding: 14px 16px;
  border: 1px dashed var(--border-2);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  font-size: 13px;
  color: var(--text-3);
}
.variant-tip { margin-top: 8px; font-size: 11px; line-height: 1.6; color: var(--text-3); }
.variant-modal-body { max-height: 54vh; overflow-y: auto; }
.variant-row-btn {
  height: 28px;
  padding: 0 10px;
  flex-shrink: 0;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease), color 0.12s var(--ease);
}
.variant-row-btn:hover { background: var(--bg-callout); color: var(--text); }
.variant-row-btn.has-variants {
  background: var(--tint-purple-bg);
  border-color: rgba(144, 101, 176, 0.3);
  color: var(--tint-purple-fg);
}
.variant-row-btn.has-variants:hover { background: #efe7f4; }
.modal-foot .foot-note { margin-right: auto; font-size: 12px; color: var(--text-3); }

.archive-list { display: flex; flex-direction: column; gap: 10px; }
.archive-item {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px 20px;
  border: 1px solid var(--border);
  border-left: 2px solid var(--c-untrained);
  border-radius: var(--r-md);
  background: #fff;
  box-shadow: var(--shadow-card);
}
.archive-item.practice  { border-left-color: var(--c-blue); }
.archive-item.learn     { border-left-color: var(--c-purple); }
.archive-item.completed { border-left-color: var(--c-mastered); opacity: 0.6; }
.archive-item.abandoned { border-left-color: var(--c-untrained); opacity: 0.6; }
.ar-icon { font-size: 20px; flex-shrink: 0; }
.ar-info { flex: 1; min-width: 200px; }
.ar-title { font-size: 15px; font-weight: 500; color: var(--text); }
.ar-meta { margin-top: 2px; font-size: 12px; color: var(--text-3); }
.tag-done { color: var(--c-mastered); font-weight: 600; }
.tag-muted { color: var(--text-3); }
.ar-progress { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; font-weight: 600; color: var(--text-2); }
.ar-actions { display: flex; gap: 6px; flex-shrink: 0; }
.archive-btn {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
.archive-btn:hover { background: var(--bg-subtle); }
.archive-btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.archive-btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.archive-btn.danger { color: #5d1715; }
.archive-btn.danger:hover { background: #ffe2dd; }

/* ══════════════════════════════════════════════════════════════════════
   15. 题卡详情弹窗
   ══════════════════════════════════════════════════════════════════════ */
.detail-header { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 24px; }
.detail-no {
  padding: 1px 8px;
  border-radius: var(--r-xs);
  background: var(--bg-callout);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
}
.detail-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  margin-left: auto;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  color: var(--text-2);
}
.detail-close:hover { background: var(--bg-subtle); color: var(--text); }
.detail-section { margin-bottom: 28px; }
.detail-section-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-3);
}
.detail-question { font-size: 18px; font-weight: 600; line-height: 1.6; color: var(--ink); word-break: break-word; }
.detail-answer {
  padding: 18px 22px;
  border-radius: var(--r-md);
  border-left: 3px solid var(--accent);
  background: var(--tint-blue-bg);
  font-size: 15px;
  line-height: 1.6;
  word-break: break-word;
  white-space: pre-wrap;
}
.detail-note { margin-top: 14px; font-size: 13px; line-height: 1.6; color: var(--text-2); }
.detail-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
.detail-stat { padding: 12px 14px; border-radius: var(--r-md); background: var(--bg-subtle); }
.stat-num { display: block; font-size: 22px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.stat-lbl { margin-top: 2px; font-size: 11px; font-weight: 500; color: var(--text-3); }
.meta-edit-row {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 14px 18px;
  border-radius: var(--r-md);
  background: var(--bg-subtle);
}
.meta-label { font-size: 13px; font-weight: 500; color: var(--text-3); }
.manual-set-btns { display: flex; gap: 6px; flex-wrap: wrap; }
.manual-set-btn {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
}
.manual-set-btn:hover { background: var(--bg-subtle); color: var(--text); }
.manual-set-btn.ms-untrained:hover { border-color: var(--c-untrained); }
.manual-set-btn.ms-weak:hover      { background: #ffe2dd; color: #5d1715; border-color: transparent; }
.manual-set-btn.ms-needwork:hover  { background: #fadec9; color: #49290d; border-color: transparent; }
.manual-set-btn.ms-good:hover      { background: #fdecc8; color: #402c1b; border-color: transparent; }
.manual-set-btn.ms-mastered:hover  { background: #d3e5ef; color: #183347; border-color: transparent; }   /* #94：绿 → 蓝 */
.detail-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.detail-action-btn {
  height: 36px;
  padding: 0 18px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}
.detail-action-btn:hover { background: var(--bg-subtle); }
.detail-action-btn.primary,
.detail-action-btn.success { background: var(--accent); border-color: var(--accent); color: #fff; }
.detail-action-btn.primary:hover,
.detail-action-btn.success:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.detail-action-btn.danger { color: #5d1715; }
.detail-action-btn.danger:hover { background: #ffe2dd; }
.detail-action-btn.ghost { color: var(--text-2); }

/* ══════════════════════════════════════════════════════════════════════
   16. 弹窗
   ══════════════════════════════════════════════════════════════════════ */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: rgba(15, 15, 15, 0.35);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.modal-overlay.hide { display: none; }

.modal {
  width: 100%;
  max-width: 460px;
  padding: 28px 32px;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  background: #fff;
  box-shadow: var(--shadow-pop);
  animation: modalIn 0.22s var(--ease);
}
.modal-md { max-width: 560px; }
.modal-lg { max-width: 720px; max-height: 86vh; overflow-y: auto; }
@keyframes modalIn {
  from { opacity: 0; transform: translateY(8px) scale(0.99); }
  to   { opacity: 1; transform: none; }
}
.modal-head { margin-bottom: 20px; }
.modal-title { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); }
.modal-sub { margin-top: 10px; font-size: 14px; line-height: 1.7; color: var(--text-2); }
.modal-body { margin-bottom: 24px; }
.modal-body .input { width: 100%; }
.modal-foot { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }

/* app.js 动态生成的旧弹窗结构（保留兼容） */
.modal-box, .prompt-modal-box, .edit-modal-box, .qcard-detail-modal {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  animation: modalIn 0.22s var(--ease);
}
.modal-box { padding: 28px 32px; max-width: 460px; width: 100%; }
.modal-box h3, .prompt-modal-box h3, .edit-modal-box h3 { font-size: 18px; font-weight: 600; color: var(--ink); margin-bottom: 12px; }
.modal-box p { margin-bottom: 28px; font-size: 14px; line-height: 1.7; color: var(--text-2); }
.modal-btns, .prompt-actions, .edit-actions { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; margin-top: 20px; }
.modal-box .btn-cancel, .modal-box .btn-red,
.prompt-modal-box .btn-cancel, .prompt-modal-box .btn-save,
.edit-modal-box .btn-cancel, .edit-modal-box .btn-save {
  height: 36px;
  padding: 0 18px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}
.modal-box .btn-cancel:hover,
.prompt-modal-box .btn-cancel:hover,
.edit-modal-box .btn-cancel:hover { background: var(--bg-subtle); }
.modal-box .btn-red { background: #5d1715; border-color: #5d1715; color: #fff; }
.modal-box .btn-red:hover { background: #4b120f; }
.prompt-modal-box .btn-save,
.edit-modal-box .btn-save { background: var(--text); border-color: var(--text); color: #fff; }
.prompt-modal-box .btn-save:hover,
.edit-modal-box .btn-save:hover { background: #2f2d28; }
.prompt-modal-box { padding: 28px 32px; max-width: 460px; width: 100%; }
.prompt-modal-box input {
  width: 100%;
  height: 38px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  font-family: inherit;
  font-size: 14px;
  outline: none;
}
.prompt-modal-box input:focus { border-color: var(--c-blue); }
.edit-modal-box { padding: 28px 32px; max-width: 720px; width: 100%; }
.edit-modal-box .edit-sub { margin-bottom: 16px; font-size: 12px; color: var(--text-3); }
.edit-modal-box textarea {
  width: 100%;
  min-height: 220px;
  padding: 14px 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  font-family: inherit;
  font-size: 15px;
  line-height: 1.7;
  color: var(--text);
  resize: vertical;
  outline: none;
}
.edit-modal-box textarea:focus { border-color: var(--c-blue); }
.qcard-detail-modal { padding: 28px 32px; max-width: 720px; width: 100%; max-height: 86vh; overflow-y: auto; }

/* ══════════════════════════════════════════════════════════════════════
   17. 悬浮元素
   ══════════════════════════════════════════════════════════════════════ */
.toast {
  position: fixed;
  left: 50%;
  bottom: 40px;
  z-index: 400;
  padding: 10px 20px;
  border-radius: var(--r-sm);
  background: var(--text);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  /* #55：max-width 与换行提到基础规则上（原来只在移动端媒体查询里）——
     电脑上长提示（如「❌ 生成失败：……」）也能自动折行，两端不出屏。 */
  max-width: calc(100vw - 32px);
  white-space: normal;
  text-align: center;
  opacity: 0;
  transform: translate(-50%, 8px);
  pointer-events: none;
  box-shadow: var(--shadow-lift);
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

.study-timer-badge {
  position: fixed;
  top: 88px;
  right: 32px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: #fff;
  box-shadow: var(--shadow-card);
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease);
}
.study-timer-badge.show { opacity: 1; transform: none; }
.pulse-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--c-mastered);
  animation: pulse 1.8s infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.time-num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════════════
   18. 工具类
   ══════════════════════════════════════════════════════════════════════ */
.center { text-align: center; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 1rem; }
.mb-lg { margin-bottom: 1.2rem; }
.mt-lg { margin-top: 1.5rem; }
.mt-0 { margin-top: 0; }
.ml-1 { margin-left: 1rem; }
.ml-xs { margin-left: 0.2rem; }
.push-right { margin-left: auto; }
.p-0 { padding: 0; }

/* ══════════════════════════════════════════════════════════════════════
   19. 响应式
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1080px) {
  .layout { grid-template-columns: 1fr; gap: 40px; }
  .layout-side { position: static; flex-direction: row; flex-wrap: wrap; }
  .layout-side .side-block { flex: 1 1 280px; }
}
@media (max-width: 860px) {
  .topbar-inner { height: auto; padding: 12px 20px; gap: 16px; flex-wrap: wrap; }
  .nav { order: 3; flex: 1 0 100%; }
  .topbar-aside { margin-left: auto; }
  .shell { padding: 48px 0 120px; }
  .shell-inner { padding: 0 20px; }
  .question-card, .learn-card { padding: 28px 24px; }
  .question-text, .learn-question { font-size: 23px; }
  .doc-title, .page-title, .overview-title,
  .settings-header h2, .learn-start-screen h2, .learn-done-screen h2 { font-size: 32px; }
  .learn-assess { grid-template-columns: repeat(2, 1fr); }
  .study-timer-badge { top: auto; bottom: 20px; right: 20px; }
}

/* ══════════════════════════════════════════════════════════════════════
   阶段 6 · 题库设置页视觉重构（电脑端）
   目标：把「分组」「朗读」从贴边的一行元素，升级成两张留白克制的卡片；
        朗读区用两列网格对齐，按钮等宽，提示文字与控件左对齐。
   全部用 #backendPage 限定，不影响其它 7 个页面。
   ══════════════════════════════════════════════════════════════════════ */

/* ── 两张卡片 ── */
#backendPage .block {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  /* #91：并排卡片收紧内边距（20/24 → 16/20），更紧凑精致 */
  padding: 16px 20px 20px;
  margin-bottom: 18px;
}
#backendPage .block-head { margin-bottom: 14px; }

/* ── 强化训练侧栏：未抽题时隐藏「本题录音历史」卡片 ── */
.side-block.hide { display: none; }

/* ── #86 · 两列：题型（左 50%）+ 朗读（右 50%），分组整行 ──────────────
   顺序即网格顺序（DOM 顺序：题型 → 朗读 → 分组），≤980px 折成单列。
   ⚠️ 坑 20 三件套（上次并排就是栽在这三点上）：
     ① `minmax(0, 1fr)` —— grid 子项默认的 `min-width:auto` 会被内容撑破，
        必须显式给 0，否则下拉框会把整列顶宽；
     ② 下拉框 / 按钮 / 小标签 **nowrap** —— 绝不允许「一个字一行」；
     ③ 提示文字**允许换行**（它是长句，nowrap 反而会溢出卡片）。 */
#backendPage .settings-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px;
  /* #92 · **等高恢复成 stretch**：
     之前 490px 的假高不是 stretch 造成的，而是 `flex:1` + `align-content:center`
     把内容撑开又居中（已在 #91 删掉）。现在内容都是自然高度（~230px），
     stretch 只负责"取两者中较高者"，正好满足"两张卡绝对等高对齐"。 */
  align-items: stretch;
  margin-bottom: 18px;
}
/* #93 · 去掉「画中画」：settings-grid 里的 .block 已经是唯一的外框，
   内层 .voice-panel / .group-panel 不再自带「白底 + 1px 灰边 + 阴影 + 圆角」——
   否则就是框里再套一个框，控件浮在大卡片之上，视觉层次乱。
   ⚠️ 必须写 ID + class：共用规则 `.voice-panel{...}`（styles.css 顶部卡片组）是
      **单类**选择器，优先级更低，只有 `#backendPage .xxx` 才盖得住；
      `.group-panel,.voice-panel{padding:20px 24px}` 同理。
   只拆「盒子外观」，不动布局（display/flex/gap 都保留）。 */
#backendPage .settings-grid .voice-panel,
#backendPage .settings-grid .group-panel {
  background: transparent;
  border: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}
#backendPage .settings-grid .block {
  margin-bottom: 0;
  min-width: 0;
  /* ⚠️ 用 **min-height 代替 stretch**：内容少的卡补到 232px、内容多的自己长出来。
     两卡内容自然高度都在 200~240px，所以底边基本齐（差 0~10px，肉眼看不出），
     但**绝不会**再出现被拉到 490px 的大片留白。 */
  min-height: 232px;
}
/* 分组卡占整行，**不受**上面的 232px 约束（它内容很少，撑到 232 反而空） */
#backendPage .settings-grid > .block-full { grid-column: 1 / -1; min-height: 0; }
#backendPage .settings-grid .voice-panel > .field { min-width: 0; }
#backendPage .settings-grid .voice-panel select,
#backendPage .settings-grid .voice-panel .btn,
#backendPage .settings-grid .voice-panel .field-label { white-space: nowrap; }
#backendPage .settings-grid .voice-hint { min-width: 0; }
@media (max-width: 980px) {
  #backendPage .settings-grid { grid-template-columns: minmax(0, 1fr); }
}
#backendPage .block-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* ── 分组：柔和底色 + 胶囊圆角 + 拉开间距 ── */
#backendPage .group-list { gap: 10px; }
#backendPage .group-chip {
  padding: 5px 7px 5px 13px;
  border-radius: 999px;
  background: var(--bg-subtle);
  border-color: var(--border);
  gap: 8px;
  transition: background-color 0.14s var(--ease), border-color 0.14s var(--ease);
}
#backendPage .group-chip:hover { background: var(--bg-callout); border-color: var(--border-2); }
#backendPage .group-chip .chip-count {
  padding: 0 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: #fff;
  font-variant-numeric: tabular-nums;
}
#backendPage .group-empty-hint { font-size: 13px; color: var(--text-3); }
#backendPage .add-group-btn {
  height: 30px;
  padding: 0 14px;
  border: 1px dashed var(--border-2);
  border-radius: 999px;
  background: transparent;
  font-size: 13px;
  color: var(--text-2);
  transition: background-color 0.14s var(--ease), color 0.14s var(--ease);
}
#backendPage .add-group-btn:hover { background: var(--bg-subtle); color: var(--text); }

/* ── 朗读：弹性行排布，空间不足时整块优雅折行，绝不竖排 ──
   每个字段有最小宽度（150px），放不下就整块换到下一行 */
#backendPage .voice-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 14px 18px;
}
#backendPage .voice-panel .field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  flex: 1 1 150px;
  min-width: 150px;
  max-width: 250px;
}
#backendPage .voice-panel .field-label {
  display: block;
  margin: 0;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-3);
}
#backendPage .voice-panel select {
  width: 100%;
  max-width: none;
  height: 32px;
  padding: 0 26px 0 10px;
  font-size: 13px;
}
/* 操作区：按钮一行平铺，提示文字占满整行自然换行（永远不竖排） */
#backendPage .voice-panel .voice-actions {
  flex: 1 1 220px;
  min-width: 200px;
  max-width: none;
}
#backendPage .voice-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
#backendPage .voice-row .btn { height: 32px; min-width: 0; padding: 0 12px; font-size: 13px; white-space: nowrap; }
#backendPage .voice-hint {
  display: block;
  min-width: 0;
  margin-top: 6px;
  padding-left: 0;
  font-size: 12px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}
/* 窄屏：朗读区每个字段独占一行，上下堆叠 */
@media (max-width: 980px) {
  #backendPage .voice-panel { flex-direction: column; align-items: stretch; }
  #backendPage .voice-panel .field,
  #backendPage .voice-panel .voice-actions { flex: 1 1 auto; min-width: 0; max-width: none; }
}

/* ── 工具栏：搜索框可伸展，状态靠右 ── */
#backendPage .toolbar { gap: 10px; margin-bottom: 18px; }
#backendPage .toolbar .search-input { flex: 1 1 240px; min-width: 0; }

/* ══════════════════════════════════════════════════════════════════════
   阶段 5 · 移动端适配（≤ 768px）
   原则：只改「布局与触控尺寸」，不动任何电脑端的视觉与业务逻辑。
   所有规则都写在这个媒体查询里，电脑端（> 768px）一行都不受影响。
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

  /* ── 0. 全局：禁止横向滚动 ──
     题干 / 答案里常有很长的英文，最容易把整页顶出横向滚动条 */
  html, body { overflow-x: hidden; }
  body { -webkit-text-size-adjust: 100%; }

  /* ── 1. 导航栏：从顶部平铺改为「底部固定 + 横向滚动」，拇指可达 ── */
  .topbar-inner { height: 56px; padding: 0 16px; gap: 12px; flex-wrap: nowrap; }
  .topbar-aside { margin-left: auto; }
  .nav {
    order: 0;
    flex: none;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 120;
    display: flex;
    gap: 6px;
    padding: 8px 12px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    background: #fff;
    border-top: 1px solid var(--border);
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.04);
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav-item {
    flex: 0 0 auto;
    height: 44px;          /* 触控区域 ≥ 44px */
    padding: 0 14px;
    font-size: 14px;
    white-space: nowrap;
  }
  /* 给底部导航留出占位高度 */
  .shell { padding: 20px 0 calc(92px + env(safe-area-inset-bottom, 0px)); }
  .shell-inner { padding: 0 16px; }
  .study-timer-badge { top: auto; bottom: calc(88px + env(safe-area-inset-bottom, 0px)); right: 12px; }
  /* #55：max-width / white-space / text-align 已提到基础 .toast 上，这里只留移动端专属的 bottom */
  .toast {
    bottom: calc(100px + env(safe-area-inset-bottom, 0px));
  }

  /* ── 2. 题卡总览：强制单列，文字不溢出 ── */
  .cards-grid { grid-template-columns: 1fr; gap: 12px; }
  .qcard { min-height: 0; padding: 16px; gap: 10px; }
  /* #88：旧类名（.qcard-header-row / .qcard-text / .qcard-footer）已随四段式骨架废弃，
     这里同步换成新类名，手机端才不会漏掉响应式规则 */
  .qcard-head { gap: 8px; }
  .qcard-title { min-height: 40px; font-size: 15px; line-height: 1.55; overflow-wrap: anywhere; }
  .qcard-foot-row { flex-wrap: wrap; gap: 8px; }
  .qcard-history { font-size: 12px; overflow-wrap: anywhere; }
  .proficiency-badge { white-space: nowrap; }
  .filter-bar { padding: 14px 16px 16px; margin-bottom: 20px; }
  .overview-header { gap: 12px; margin-bottom: 16px; }
  .overview-counts { flex-wrap: wrap; gap: 8px; }
  .stats-grid { grid-template-columns: 1fr; }
  .side-block { padding: 14px 16px; }
  .layout { gap: 20px; }
  .layout-side { flex-direction: column; }
  .layout-side .side-block { flex: 1 1 auto; }
  .answered-item { font-size: 13px; padding: 10px; }

  /* ── 3. 答题区：按钮触控区 ≥ 44px，题目 / 答案不横向滚动 ── */
  .question-card, .learn-card { padding: 20px 16px; }
  .question-text, .learn-question {
    font-size: 19px;
    line-height: 1.45;
    margin-bottom: 18px;
    overflow-wrap: anywhere;
    word-break: break-word;
  }
  .answer-text, .learn-answer { padding: 14px 16px; gap: 10px; margin-bottom: 18px; }
  .answer-text .content, .learn-answer .content { overflow-wrap: anywhere; word-break: break-word; }
  .answer-text .label, .answer-label { padding-top: 0; }
  .info-row { padding: 10px 12px; gap: 8px; font-size: 12px; }
  .btn { height: 44px; padding: 0 14px; font-size: 15px; }
  .btn-group { gap: 10px; }
  .btn-group .btn { flex: 1 1 0; min-width: 0; }
  .learn-assess { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .assess-btn { min-height: 52px; padding: 10px 6px; }
  .end-round-btn, .speak-btn { min-height: 44px; }
  /* 去掉移动端点击的 300ms 延迟与双击缩放误触 */
  .btn, .nav-item, .assess-btn, .ws-word, .ws-loc-chip, .star, .chip { touch-action: manipulation; }
  .practice-setup { padding: 16px; }
  .group-panel, .voice-panel { padding: 16px; }

  /* ── 4. 弹窗：限高 90vh，内部可滚动，四周留白 ── */
  .modal-overlay { padding: 16px; }
  .modal {
    max-width: 100%;
    max-height: 90vh;
    padding: 18px;
    display: flex;
    flex-direction: column;
  }
  .modal-head { flex: 0 0 auto; margin-bottom: 14px; }
  .modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    margin-bottom: 16px;
  }
  .modal-foot { flex: 0 0 auto; }
  .modal-foot .btn { flex: 1 1 auto; height: 44px; }
  /* app.js 动态生成的旧弹窗结构：整体可滚 */
  .modal-box, .prompt-modal-box, .edit-modal-box, .qcard-detail-modal {
    max-width: 100%;
    max-height: 90vh;
    padding: 18px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* ── 5. 单词统计表格：横向滚动 + 隐藏次要列 ── */
  .ws-controls { gap: 12px; padding: 14px 16px; }
  .ws-controls label { gap: 6px; font-size: 12px; }
  .ws-table-wrap { max-height: 68vh; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .ws-table { min-width: 100%; font-size: 13px; }
  .ws-table th, .ws-table td { padding: 8px 12px; }
  .ws-table th:nth-child(3), .ws-table td:nth-child(3) { display: none; }  /* 隐藏「来源分布」 */
  .ws-locs { max-width: 160px; overflow: hidden; }
  .ws-variants { overflow-wrap: anywhere; }

  /* ── 6. 学习时长 / 学习计划 / 存档 ── */
  .tsummary-grid, .time-summary { grid-template-columns: repeat(2, 1fr); }
  .plan-stat { padding: 12px; }
  .archive-item { flex-wrap: wrap; gap: 10px; }
  .settings-row { flex-wrap: wrap; }
  .doc-title, .page-title, .overview-title,
  .settings-header h2, .learn-start-screen h2, .learn-done-screen h2 { font-size: 26px; }

  /* ══════════════════════════════════════════════════════════════════
     阶段 6 · 移动端全页面精修
     ══════════════════════════════════════════════════════════════════ */

  /* ── 7. 学习时长：日历 / 柱状图紧凑化（格子不再被切一半）──
     7 列必须写成 minmax(0, 1fr)：默认的 1fr 隐含 min-width:auto，
     内容稍长就会把整页撑出横向滚动条，这是日历溢出的真正原因。 */
  .cal-wrap, .ts-detail { padding: 16px 14px; margin-bottom: 20px; }
  .cal-head { margin-bottom: 14px; }
  .cal-title { font-size: 15px; }
  .cal-nav button { height: 34px; min-width: 34px; }
  .chart { gap: 6px; height: 150px; padding: 12px 0; }
  .chart-value { margin-bottom: 4px; font-size: 10px; }
  .chart-bar { max-width: 34px; }
  .chart-day { margin-top: 6px; font-size: 11px; }
  .chart-date { font-size: 10px; }

  .cal-weekdays,
  .cal-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
  .cal-weekdays { margin-bottom: 6px; }
  .cal-weekdays div { padding: 2px 0; font-size: 11px; }
  .cal-cell {
    min-height: 54px;
    padding: 5px 3px;
    gap: 3px;
    align-items: center;
    text-align: center;
    border-radius: var(--r-sm);
    overflow: hidden;
  }
  .cal-date { font-size: 11px; }
  /* 时长允许折行（"1h 30m" → 两行），宁可矮胖也绝不被裁切 */
  .cal-time { font-size: 10px; line-height: 1.2; white-space: normal; overflow-wrap: anywhere; }
  .cal-time.small { font-size: 10px; }
  .ts-session-list { max-height: 60vh; }
  .ts-session-item { gap: 10px; padding: 10px 12px; }
  .ts-info { min-width: 0; }
  .ts-name, .ts-time { overflow-wrap: anywhere; }

  /* ── 8. 题库设置：行内元素纵向堆叠，不再挤成一条横带 ── */
  #backendPage .doc-head { margin-bottom: 20px; }
  #backendPage .doc-head-row { gap: 12px; }
  #backendPage .doc-head-row .btn { width: 100%; height: 44px; }
  #backendPage .block { padding: 16px 16px 18px; margin-bottom: 14px; }
  #backendPage .settings-grid { gap: 14px; }
  #backendPage .voice-row .btn { flex: 1 1 auto; min-width: 0; height: 40px; }
  #backendPage .toolbar { gap: 8px; margin-bottom: 14px; }
  #backendPage .toolbar .btn { flex: 1 1 auto; min-width: 0; height: 44px; padding: 0 10px; font-size: 13px; }
  #backendPage .toolbar .search-input { flex: 1 1 100%; width: 100%; }
  #backendPage .file-status { flex: 1 1 100%; margin-left: 0; }

  /* 题目列表：手机上取消内部滚动框，跟着页面一起滚，
     否则 max-height:660px 的独立滚动区会和页面滚动「打架」 */
  .question-list { max-height: none; overflow: visible; padding-right: 0; gap: 10px; }
  .question-row { padding: 12px; gap: 10px; row-gap: 8px; min-height: 0; flex-wrap: wrap; }
  /* ⚠️ #98 之后必须写 `.question-row > .x`（两个类）：上面的定宽规则也是两个类，
     只写 `.q-input` 会被它盖掉 → 手机上就再也堆不起来、列被压成一条细缝。 */
  .question-row > .index { flex: 0 0 auto; min-width: 0; }
  .question-row > .q-input, .question-row > .a-input { flex: 1 1 100%; min-width: 0; }
  .question-row > .group-select-row { flex: 1 1 140px; height: 38px; }
  .question-row > .star-cell,
  .question-row > .proficiency-badge,
  .question-row > .variant-row-btn,
  .question-row > .qt-select,
  .question-row > .row-icons { flex: 0 0 auto; }
  .question-row .variant-row-btn { height: 38px; }
  .question-row > .row-icons .btn-icon { flex: 0 0 38px; width: 38px; height: 38px; }
  .group-select-inline, .group-select-row { max-width: none; height: 38px; flex: 1 1 140px; }
  .save-btn { height: 38px; }
  .btn-icon { width: 38px; height: 38px; }

  /* ── 9. 单词统计：整页重排（移动端最臃肿的一页）──
     桌面是 4 列表格；手机上 1019 行 × 20 个题号块，每行要占 150px 高，
     挤得又高又窄。这里把 <table> 整体「卡片化」：
       第 1 行：单词 + 频率胶囊      第 2 行：题/答 占比（小字）
       第 3 行：题号横滑条（一行到底，不再堆 10 行）
     表格本身不再横向滚动，页面也就永远不会被撑宽。 */
  /* 统计卡：5 张大卡占了三屏之一，改成一条可横滑的数据带（约省 230px 高度） */
  .word-stats-summary {
    display: flex;
    gap: 8px;
    margin: 0 -16px 16px;
    padding: 0 16px 4px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .word-stats-summary::-webkit-scrollbar { display: none; }
  .ws-card { flex: 0 0 132px; padding: 10px 12px; }
  .ws-card .ws-num { font-size: 19px; white-space: nowrap; }
  .ws-card .ws-lbl { font-size: 11px; line-height: 1.35; }

  /* 筛选控件：两列「标签在上 / 控件在下」，标签不会再被挤成「分 / 组：」 */
  .ws-controls {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    padding: 14px;
  }
  .ws-controls label {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    min-width: 0;
    font-size: 11px;
    font-weight: 500;
    color: var(--text-3);
    white-space: nowrap;
  }
  .ws-controls label:first-child {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    gap: 8px;
  }
  .ws-controls input[type="text"], .ws-controls select { width: 100%; min-width: 0; height: 34px; font-size: 13px; }
  .ws-refresh { grid-column: 1 / -1; width: 100%; height: 40px; }
  .ws-toolbar { gap: 6px; margin-bottom: 10px; }
  .ws-toolbar .hint { font-size: 11px; line-height: 1.5; }

  /* 卡片列表：不要内层滚动框，跟着页面一起滚 */
  .ws-table-wrap { max-height: none; overflow: visible; border: 0; border-radius: 0; background: transparent; }
  .ws-table { display: block; width: 100%; min-width: 0; font-size: 14px; }
  .ws-table thead { display: none; }          /* 卡片布局下「频率/出现题目」表头没意义 */
  .ws-table tbody { display: block; }
  .ws-table tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: 3px 10px;
    margin-bottom: 8px;
    padding: 11px 13px;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: #fff;
  }
  .ws-table tr:hover { background: #fff; }
  .ws-table td { display: block; padding: 0; border: 0; min-width: 0; }
  .ws-table td:nth-child(1) { grid-column: 1; grid-row: 1; }
  .ws-table td:nth-child(2) { grid-column: 2; grid-row: 1; justify-self: end; }
  /* 之前被隐藏的「来源分布」重新露出来，压缩成一行小字元信息 */
  .ws-table td:nth-child(3) {
    display: block;
    grid-column: 1 / -1;
    grid-row: 2;
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-3);
  }
  .ws-table td:nth-child(4) { grid-column: 1 / -1; grid-row: 3; }

  .ws-word { font-size: 17px; font-weight: 600; line-height: 1.3; }
  .ws-variants { display: block; margin-top: 1px; font-size: 12px; line-height: 1.45; overflow-wrap: anywhere; }
  /* 必须带 .ws-table 前缀：上面 `.ws-table td { padding:0; min-width:0 }` 的
     权重比单个 `.ws-freq` 高，否则频率胶囊会被压成一条细线 */
  .ws-table td.ws-freq {
    min-width: 44px;
    padding: 0 10px;
    border-radius: 999px;
    background: var(--bg-subtle);
    font-size: 13px;
    line-height: 24px;
    text-align: center;
    color: var(--text);
  }
  /* 题号：单行横滑，一屏放得下 6–7 个，用完向右滑 */
  .ws-table td.ws-locs {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    margin-top: 3px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* 右缘淡出：一眼就知道这排题号还能往右滑 */
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent 100%);
  }
  .ws-locs::-webkit-scrollbar { display: none; }
  /* 单行横滑时把 chip 做成 26px 高的胶囊，比桌面更粗一档才好点 */
  .ws-locs .ws-loc-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    height: 26px;
    margin: 0;
    padding: 0 8px;
    border-radius: var(--r-sm);
  }
  .more-count { flex: 0 0 auto; }

  /* ── 10. 学习计划 / 存档：表单与列表折行 ── */
  .goal-setup { padding: 16px; margin-bottom: 20px; }
  .goal-form-row { gap: 12px; margin-bottom: 16px; }
  .goal-form-row label { width: 100%; justify-content: space-between; }
  .time-block-row { padding: 12px; }
  .plan-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .daily-plan-item { gap: 8px; padding: 12px 14px; }
  .dp-date, .dp-time { flex: 1 1 100%; min-width: 0; }
  .pomodoro-visual { padding: 14px 16px; }
  .ar-actions { flex-wrap: wrap; }
  .archive-btn { min-height: 36px; }

  /* ── 11. 底部导航不遮挡：悬浮元素上移 + 每页尾部留出安全距离 ── */
  .tts-badge {
    bottom: calc(96px + env(safe-area-inset-bottom, 0px));
    max-width: calc(100vw - 32px);
    white-space: normal;
    text-align: center;
  }
  .modal-overlay { padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
  .page { padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px)); }
}

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

/* ══════════════════════════════════════════════════════════════════════
   阶段 0 · 安全网 UI：启动屏 / 致命错误条 / 单块渲染失败卡
   全部沿用现有设计变量，保持 Notion 极简风格
   ══════════════════════════════════════════════════════════════════════ */

/* ── 启动屏 ── */
.boot-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  min-height: 42vh;
  color: var(--text-3);
  font-size: 14px;
}
.boot-screen.hide { display: none; }
.boot-spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--border-2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: bootSpin 0.7s linear infinite;
}
@keyframes bootSpin { to { transform: rotate(360deg); } }
.boot-text { letter-spacing: 0.2px; }
.boot-screen.timeout .boot-spinner { animation: none; border-top-color: var(--border-2); }
.boot-screen.timeout .boot-text { color: var(--tint-red-fg); }
.boot-screen code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg-callout);
  padding: 1px 5px;
  border-radius: var(--r-xs);
  font-size: 12px;
}

/* ── 致命错误条（init 挂了才出现） ── */
.fatal-banner {
  position: sticky;
  top: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 20px;
  background: var(--tint-red-bg);
  color: var(--tint-red-fg);
  border-bottom: 1px solid var(--c-weak);
  font-size: 13px;
}
.fatal-text { flex: 1 1 240px; font-weight: 500; }
.fatal-btn {
  height: 26px;
  padding: 0 10px;
  font-size: 12px;
  font-weight: 500;
  color: var(--tint-red-fg);
  background: transparent;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background-color 0.12s var(--ease);
}
.fatal-btn:hover { background: rgba(0, 0, 0, 0.05); }
.fatal-btn.primary { background: var(--c-weak); color: #fff; border-color: var(--c-weak); }
.fatal-btn.primary:hover { background: #b04a42; }

/* ── 快捷键帮助面板 ── */
.ks-group { margin-bottom: 14px; }
.ks-title { font-size: 12px; font-weight: 600; color: var(--text-2); margin-bottom: 6px; }
.ks-row { display: flex; flex-wrap: wrap; gap: 8px 16px; font-size: 13px; color: var(--text); }

/* ── 答题判定反馈动效（阶段 3）── */
.question-card.judge-known,
.question-card.judge-unknown { transition: border-color 0.18s var(--ease), background-color 0.18s var(--ease); }
.question-card.judge-known { border-color: var(--c-mastered); background: var(--tint-green-bg); }
.question-card.judge-unknown { border-color: var(--c-weak); background: var(--tint-red-bg); }
.question-card.q-swap-in { animation: qSwapIn 0.22s var(--ease); }
@keyframes qSwapIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.answered-item.fresh { animation: slideIn 0.24s var(--ease); }
.btn.just-picked { transform: scale(0.96); opacity: 0.75; }

/* ── 骨架屏：切到还没渲染过的页面时先占位，避免空白闪一下 ── */
.sk-wrap { display: flex; flex-direction: column; gap: 10px; padding: 4px 0 8px; }
.sk-line, .sk-card {
  position: relative;
  overflow: hidden;
  background: var(--bg-callout);
  border-radius: var(--r-sm);
}
.sk-line { height: 14px; }
.sk-line.w-40 { width: 40%; }
.sk-line.w-60 { width: 60%; }
.sk-line.w-80 { width: 80%; }
.sk-card { height: 76px; }
.sk-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
  margin-top: 16px;
}
.sk-line::after, .sk-card::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.65), transparent);
  animation: skShimmer 1.1s var(--ease) infinite;
}
@keyframes skShimmer { to { transform: translateX(100%); } }

/* ── 单块渲染失败卡（某个页面渲染抛错时不拖垮整站） ── */
.render-error {
  padding: 20px;
  margin: 8px 0;
  background: var(--tint-orange-bg);
  color: var(--tint-orange-fg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: 13px;
}
.re-title { font-weight: 600; margin-bottom: 6px; }
.re-msg {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  opacity: 0.85;
  word-break: break-all;
}
.re-actions { margin-top: 12px; display: flex; gap: 8px; }
.re-actions button {
  height: 28px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 500;
  color: var(--tint-orange-fg);
  background: transparent;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background-color 0.12s var(--ease);
}
.re-actions button:hover { background: rgba(0, 0, 0, 0.05); }

/* ═══════════════════════════════════════════════════════════════════════════
   阶段 7 · AI 录音作答与评估
   ① 录音按钮  ② 录音弹窗（录音中 / 进度 / 不可用 / 文字模式）
   ③ 录音历史列表  ④ 成绩单弹窗（手风琴）
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── ① 录音按钮 ── */
.record-row,
.learn-record-row {
  display: flex;
  justify-content: center;
  margin: 14px 0 10px;
}
.btn-record {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 18px;
  border: 1px solid var(--border-2);
  border-radius: 999px;
  background: var(--bg-subtle);
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.16s var(--ease), border-color 0.16s var(--ease);
  touch-action: manipulation;
}
.btn-record:hover { background: var(--bg-callout); border-color: var(--border-2); }
.btn-record:active { background: var(--bg-hover); }

/* ── ② 录音弹窗 ── */
.rec-live { padding: 6px 0 2px; text-align: center; }
.rec-dot-wrap { height: 22px; display: flex; align-items: center; justify-content: center; }
.rec-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: #ef4444;
  box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.45);
  animation: recPulse 1.3s ease-out infinite;
}
@keyframes recPulse {
  0%   { box-shadow: 0 0 0 0 rgba(239,68,68,.45); transform: scale(1); }
  60%  { box-shadow: 0 0 0 14px rgba(239,68,68,0); transform: scale(1.12); }
  100% { box-shadow: 0 0 0 0 rgba(239,68,68,0); transform: scale(1); }
}
.rec-timer {
  margin-top: 6px;
  font-size: 42px;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.rec-tip { margin-top: 4px; font-size: 13px; color: var(--text-3); }
.rec-cap {
  height: 4px;
  margin: 14px auto 0;
  max-width: 320px;
  border-radius: 999px;
  background: var(--bg-subtle);
  overflow: hidden;
}
.rec-cap-bar {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, #22c55e, #f59e0b 70%, #ef4444);
  transition: width 0.2s linear;
}
.rec-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 18px;
}
.rec-actions .btn { min-width: 132px; }
.rec-note {
  margin-top: 12px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--text-3);
  text-align: center;
}
.link-btn {
  border: 0;
  background: none;
  padding: 0;
  font-size: 12px;
  color: var(--tint-orange-fg);
  cursor: pointer;
  text-decoration: underline;
}

/* 进度态 */
.rec-progress { padding: 4px 0 2px; text-align: center; }
.rec-stage-icon { font-size: 40px; line-height: 1.1; }
.rec-stage-title { margin-top: 8px; font-size: 16px; font-weight: 600; color: var(--ink); }
.rec-stage-sub { margin-top: 6px; font-size: 13px; line-height: 1.7; color: var(--text-2); }
.rec-steps { margin: 16px 0 4px; text-align: left; }
.rec-step {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-size: 13px;
  color: var(--text-3);
}
.rec-step.active { background: var(--bg-subtle); color: var(--text); font-weight: 500; }
.rec-step.done { color: var(--text-2); }
.rec-step-dot { display: flex; align-items: center; justify-content: center; }
.rec-step-dot i {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--c-mastered);
  animation: recBlink 1s ease-in-out infinite;
}
@keyframes recBlink { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }
.rec-step-sub { font-size: 11px; color: var(--text-3); }
.rec-bar {
  height: 6px;
  margin-top: 12px;
  border-radius: 999px;
  background: var(--bg-subtle);
  overflow: hidden;
}
.rec-bar-in {
  height: 100%;
  border-radius: 999px;
  background: var(--c-mastered);
  transition: width 0.4s var(--ease);
}

/* 不可用态：把「为什么 + 怎么办」讲清楚 */
.rec-blocked { text-align: center; padding: 4px 0; }
.rec-blocked-icon { font-size: 34px; }
.rec-blocked-title { margin-top: 8px; font-size: 16px; font-weight: 600; color: var(--ink); }
.rec-blocked-reason { margin-top: 8px; font-size: 13px; line-height: 1.75; color: var(--text-2); }
.rec-blocked-how {
  margin-top: 10px;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  background: var(--bg-callout);
  font-size: 13px;
  line-height: 1.75;
  color: var(--text-2);
  text-align: left;
}
/* ⚠️ #81 根因：`.field` 默认是 **inline-flex**（宽度 = 内容宽度，shrink-to-fit），
   里面的 textarea 写 `width:100%` 也只是「占满这个塌缩后的容器」→ 看起来像一条窄缝。
   必须显式改成 flex + width:100%，textarea 才真的撑满弹窗。 */
.rec-text-mode .field { display: flex; flex-direction: column; align-items: stretch; gap: 8px; width: 100%; }
.rec-text-mode .field-label { font-size: 12px; color: var(--text-3); }
/* #82：初始 6 行（150px）就够，**由 JS 按内容自动长高**，别一上来就傻大黑粗。
   ⚠️ height 必须是 auto，否则 JS 设的 height 会被这里盖掉。 */
.rec-text-mode textarea {
  display: block;
  width: 100%;
  height: auto;
  min-height: 150px;      /* ≈6 行（15px × 1.7 行高 ≈ 25.5px/行） */
  max-height: 60vh;
  resize: vertical;
  overflow-y: auto;
}
/* 文字作答时把弹窗放宽（原本 560px 写长文偏窄） */
.modal.is-wide { max-width: 720px; }

/* #82 · 题型卡片里「手动区只是兜底」的说明（放小、放淡，别抢主状态的注意力） */
.qt-manual-note {
  font-size: 12px;
  line-height: 1.7;
  color: var(--text-3);
  margin: 2px 0 12px;
}

/* #85 · 顶部题型卡的两个批量按钮：能并排就并排，放不下就各占一行（绝不横向挤压） */
.qt-batch-row .btn { flex: 1 1 auto; justify-content: center; }

/* ═══════════════════════════════════════════════════════════════════════════
   #86 · 题型：全站小标签 + 列表行下拉框 + 重判状态
   全部沿用「克制灰 + 极淡底 + 细边」，拒绝大红大绿（用户审美红线）。
   ═══════════════════════════════════════════════════════════════════════════ */
.qt-badge {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 6px;
  font-size: 11.5px;
  line-height: 1;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--text-3);
  white-space: nowrap;
  vertical-align: middle;
}
.qt-badge.qt-behavioral { border-color: #ded9ef; background: #f5f3fb; color: #5c5474; }
.qt-badge.qt-opinion    { border-color: #d8e3f0; background: #f2f6fb; color: #50647a; }
.qt-badge.qt-factual    { border-color: #d8e7de; background: #f2f8f4; color: #4f6b59; }
.qt-badge.qt-none       { background: transparent; color: var(--text-3); opacity: 0.9; }
/* 强化训练的 status-badge 里嵌了一个 badge，别把那一行撑高 */
.status-badge .qt-badge { margin: 0 4px; }

/* 题库列表每一行的题型下拉：选完立刻保存，宽度固定不抢空间 */
.qt-select {
  flex: 0 0 auto;
  min-width: 92px;
  height: 30px;
  padding: 0 8px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--text);
  background: #fff;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  white-space: nowrap;
  cursor: pointer;
}
.qt-select:hover { background: var(--bg-subtle); }
.qt-select.qt-saved { border-color: #9ec9ab; background: #f2f8f4; }

/* 重判进行中：提示加深加粗（用户反馈"不知道到底跑没跑"） */
.voice-hint.qt-running { color: var(--text); font-weight: 600; }
/* 按钮置灰：disabled 属性 + 类双保险（有些浏览器对 button:disabled 的默认样式不一致） */
.btn.is-disabled, .btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* ── ③ 录音历史列表 ── */
.rec-list { display: flex; flex-direction: column; gap: 8px; }
.rec-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: #fff;
}
.rec-item-main { flex: 1 1 auto; min-width: 0; }
.rec-item-line1 { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.rec-score { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.rec-time { font-size: 12px; color: var(--text-2); }
.rec-dur { font-size: 12px; color: var(--text-3); }
.rec-item-line2 { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.rec-audio-tag {
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-3);
  background: var(--bg-subtle);
}
.rec-audio-tag.ok { color: #15803d; background: #f0fdf4; border-color: #bbf7d0; }
.rec-audio-tag.gone { color: #b45309; background: #fffbeb; border-color: #fde68a; }
.rec-audio-tag.err { color: #b91c1c; background: #fef2f2; border-color: #fecaca; }
.rec-audio-tag.wait { color: var(--tint-orange-fg); }
.rec-view-btn {
  flex-shrink: 0;
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  touch-action: manipulation;
}
.rec-view-btn:hover { background: var(--bg-hover); }
.rec-empty {
  padding: 16px 14px;
  border: 1px dashed var(--border-2);
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  text-align: left;
}
.rec-empty-title { font-size: 13px; font-weight: 500; line-height: 1.6; color: var(--text-2); }
.rec-empty-sub { margin-top: 6px; font-size: 12px; line-height: 1.9; color: var(--text-3); }
/* 强化训练右侧栏更窄：行高再放松一点，别挤成一坨 */
.side-block .rec-empty { padding: 14px 12px; }
.side-block .rec-empty-title { font-size: 12.5px; }
.side-block .rec-empty-sub { line-height: 1.95; }
.side-block .rec-item { flex-wrap: wrap; padding: 10px; gap: 8px; }
.side-block .rec-view-btn { flex: 1 1 100%; height: 30px; }
.learn-record-block { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.learn-record-head { font-size: 13px; font-weight: 600; color: var(--text-2); margin-bottom: 10px; }

/* 分数配色（环形进度与分数文字共用） */
.sc-great { --ring: #16a34a; color: #16a34a; }
.sc-good  { --ring: #2563eb; color: #2563eb; }
.sc-ok    { --ring: #d97706; color: #d97706; }
.sc-bad   { --ring: #dc2626; color: #dc2626; }
.sc-none  { --ring: var(--border-2); color: var(--text-3); }

/* ── ④ 成绩单弹窗 ── */
#reportModal { padding: 24px; }
#reportBox {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 720px;
  max-height: 86vh;
  padding: 0;
  overflow: hidden;
}
/* 只有正文滚动，头部和底部按钮钉住 —— 手风琴再长也不会把整页顶出去 */
#reportBody {
  flex: 1 1 auto;
  min-height: 0;
  margin-bottom: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable;
}
.report-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 22px 24px 18px;
  border-bottom: 1px solid var(--border);
  background: #fff;
}
.report-head-text { flex: 1 1 auto; min-width: 0; }
.report-ring {
  position: relative;
  flex: 0 0 auto;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: conic-gradient(var(--ring, var(--border-2)) calc(var(--p, 0) * 1%), var(--bg-subtle) 0);
}
.report-ring::before {
  content: '';
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  background: #fff;
}
.report-ring-num {
  position: relative;
  font-size: 26px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.report-level { font-size: 15px; font-weight: 600; color: var(--ink); }
.report-summary { margin-top: 4px; font-size: 13px; line-height: 1.7; color: var(--text-2); }
.report-meta { margin-top: 6px; font-size: 12px; color: var(--text-3); }
.rp-empty { padding: 28px 24px; text-align: center; font-size: 14px; color: var(--text-3); }

/* 手风琴 */
.report-acc { padding: 0; }
.acc-item { border-bottom: 1px solid var(--border); }
.acc-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 48px;
  padding: 0 24px;
  border: 0;
  background: none;
  font-size: 14px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.14s var(--ease);
}
.acc-head:hover { background: var(--bg-hover); }
.acc-icon { font-size: 15px; }
.acc-title { font-weight: 500; }
.acc-badge {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--bg-subtle);
  font-size: 11px;
  color: var(--text-3);
}
.acc-caret { margin-left: auto; color: var(--text-3); transition: transform 0.26s var(--ease); }
.acc-item.open .acc-caret { transform: rotate(180deg); }
/* 0fr → 1fr 的网格动画：不用 JS 测高度，也不会出现高度跳变 */
.acc-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.28s var(--ease); }
.acc-item.open .acc-body { grid-template-rows: 1fr; }
.acc-inner { overflow: hidden; padding: 0 24px; }
.acc-item.open .acc-inner { padding: 2px 24px 18px; }

/* 成绩单各区块 */
.rp-dim { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.rp-dim-label { width: 48px; font-size: 13px; color: var(--text-2); flex-shrink: 0; }
.rp-dim-track {
  flex: 1 1 auto;
  height: 8px;
  border-radius: 999px;
  background: var(--bg-subtle);
  overflow: hidden;
}
.rp-dim-track i { display: block; height: 100%; border-radius: 999px; background: var(--c-mastered); transition: width 0.4s var(--ease); }
.rp-dim-val { width: 32px; text-align: right; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.rp-fluency { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.rp-chip {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--bg-subtle);
  font-size: 12px;
  color: var(--text-2);
}
.rp-chip.good { background: #f0fdf4; color: #15803d; }
.rp-chip.bad { background: #fffbeb; color: #b45309; }
.rp-chip.flag { background: #fef2f2; color: #b91c1c; }
.rp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 12px; }
.rp-note { margin-top: 6px; font-size: 12px; line-height: 1.7; color: var(--text-3); }

/* ── #69 · 成绩单 v3：七项 rubric / 头部补充 / 置信度 ── */
.rp-head-weak { margin-top: 6px; font-size: 12.5px; color: var(--text-2); }
.rp-head-weak b { font-weight: 600; font-variant-numeric: tabular-nums; }
.rp-cap-note {
  margin-top: 5px; font-size: 12px; line-height: 1.65; color: #b45309;
  background: #fffbeb; border: 1px solid #fde68a; border-radius: 6px; padding: 4px 8px; display: inline-block;
}
.rp-confidence { margin-top: 5px; font-size: 12px; color: var(--text-3); }
.rp-confidence.is-low { color: #b91c1c; }
.rp-version-note { margin-top: 5px; font-size: 12px; color: var(--text-3); font-style: italic; }

.rp-rubric { margin-top: 4px; }
.rp-item { padding: 9px 0; border-bottom: 1px solid var(--border); }
.rp-item:last-child { border-bottom: 0; }
.rp-item.is-off { opacity: 0.55; }
.rp-item-head { display: flex; align-items: center; gap: 8px; }
.rp-item-name { flex: 0 0 74px; font-size: 13px; color: var(--text-2); }
.rp-item-tag {
  flex: 0 0 auto; font-size: 11px; padding: 1px 6px; border-radius: 999px;
  background: var(--bg-subtle); color: var(--text-3);
}
.rp-item-evidence {
  margin-top: 4px; font-size: 12px; line-height: 1.7; color: var(--text-3);
  font-style: italic; padding-left: 10px; border-left: 2px solid var(--border);
}
.rp-item-evidence.is-bad { color: #b91c1c; font-style: normal; }
.rp-praise {
  margin: 10px 0;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, #fffbeb, #fef3c7);
  border: 1px solid #fde68a;
  font-size: 14px;
  line-height: 1.8;
  color: #92400e;
}
.rp-iv-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.rp-iv-label { font-size: 13px; font-weight: 600; color: var(--text-2); }
.rp-iv-val { font-size: 13px; color: var(--text-2); }
.rp-dots { display: inline-flex; gap: 4px; }
.rp-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--border-2); }
.rp-dots i.on { background: #f59e0b; }
.rp-stars { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
.rp-star { font-size: 13px; color: var(--text-3); }
.rp-star.on { color: #15803d; }
.rp-signal { margin-top: 14px; }
.rp-signal-track {
  position: relative;
  height: 6px;
  border-radius: 999px;
  background: linear-gradient(90deg, #fca5a5, #fde68a 50%, #86efac);
}
.rp-signal-track i {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  margin-left: -7px;
  border-radius: 50%;
  background: #fff;
  border: 3px solid var(--ink);
  transform: translateY(-50%);
  transition: left 0.4s var(--ease);
}
.rp-signal-ends { display: flex; justify-content: space-between; margin-top: 6px; font-size: 11px; color: var(--text-3); }
.rp-follow { margin: 6px 0 0; padding-left: 18px; }
.rp-follow li { font-size: 13px; line-height: 1.8; color: var(--text-2); }
.rp-monologue {
  padding: 14px 16px;
  border-left: 3px solid var(--border-2);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--bg-callout);
  font-size: 14px;
  line-height: 1.9;
  color: var(--text);
  white-space: pre-wrap;
}
.rp-sent {
  padding: 12px 14px;
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: #fff;
}
.rp-sent-row { display: flex; gap: 8px; font-size: 13px; line-height: 1.8; }
.rp-sent-row + .rp-sent-row { margin-top: 6px; }
.rp-sent-tag { flex: 0 0 58px; font-size: 11px; color: var(--text-3); padding-top: 2px; }
.rp-sent-row.orig { color: var(--text-2); text-decoration: line-through; text-decoration-color: #fca5a5; }
.rp-sent-row.fix { color: #15803d; }
.rp-sent-row.cmt { color: var(--text-3); }
.rp-raw {
  padding: 12px 14px;
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  font-size: 13px;
  line-height: 1.9;
  color: var(--text-2);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.report-foot {
  padding: 14px 24px 20px;
  border-top: 1px solid var(--border);
}
.rp-audio { width: 100%; height: 36px; }
.rp-audio-gone { font-size: 12px; color: var(--text-3); }
.report-foot-btns { display: flex; gap: 10px; justify-content: flex-end; margin-top: 12px; flex-wrap: wrap; }

/* 调试入口（题库设置页）：独立卡片，说明 / 输入框 / 按钮各占一行 */
#recordDebugBlock .rec-debug-card {
  padding: 16px 18px 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  background: #fff;
  box-shadow: var(--shadow-card);
}
.rec-debug-desc { font-size: 13px; line-height: 1.8; color: var(--text-3); }
.rec-debug-sample-btn {
  margin-left: 6px;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 13px;
  color: var(--tint-orange-fg);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.rec-debug-sample-btn:hover { color: var(--text); }
.rec-debug-input {
  display: block;
  width: 100%;
  min-height: 116px;
  max-height: 240px;
  margin-top: 12px;
  padding: 12px 14px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.8;
  color: var(--text);
  background: var(--bg-subtle);
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  outline: none;
  resize: vertical;
}
.rec-debug-input:focus { background: #fff; border-color: var(--c-blue); }
.rec-debug-input::placeholder { color: var(--text-3); }
.rec-debug-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.rec-debug-foot .btn { height: 34px; padding: 0 16px; }
.rec-debug-foot .voice-hint { font-size: 12px; color: var(--text-3); }
.block-foot-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px; }

/* ── 手机端：成绩单必须靠折叠保清爽 ── */
@media (max-width: 768px) {
  .record-row, .learn-record-row { margin: 12px 0 8px; }
  .btn-record { width: 100%; justify-content: center; height: 46px; font-size: 15px; }
  .rec-actions { gap: 8px; }
  .rec-actions .btn { flex: 1 1 140px; height: 46px; min-width: 0; }
  .rec-timer { font-size: 36px; }
  .rec-item { flex-wrap: wrap; }
  .rec-view-btn { width: 100%; height: 38px; }
  .rec-empty { text-align: left; }

  #reportBox { max-height: 92vh; }
  .report-head { gap: 14px; padding: 16px; }
  .report-ring { width: 68px; height: 68px; }
  .report-ring-num { font-size: 22px; }
  .acc-head { height: 52px; padding: 0 16px; }
  .acc-inner, .acc-item.open .acc-inner { padding-left: 16px; padding-right: 16px; }
  .report-foot { padding: 12px 16px 18px; }
  .rp-sent-tag { flex-basis: 48px; }
  .rp-monologue { font-size: 13px; line-height: 1.85; }
  .detail-action-btn.record { width: 100%; justify-content: center; min-height: 46px; }
}

/* ══════════════════════════════════════════════════════════════════════
   P0-2 · 登录 / 注册 全屏层（Notion 极简克制：细灰边、零阴影、左对齐）
   ──────────────────────────────────────────────────────────────────────
   z-index 400 —— 必须高于所有弹窗（.modal-overlay 是 300），
   否则未登录时，之前渲染出来的弹窗会浮在登录框上面。
   ══════════════════════════════════════════════════════════════════════ */
.auth-gate {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
  background: var(--bg-page);
  overflow-y: auto;
}
.auth-gate.hide { display: none; }

/* ── #113 · 未登录防闪烁（FOUC）──
   HTML 出厂自带 <body class="pre-auth">：页面首绘前（styles.css 在 <head> 里
   是渲染阻塞的，规则必然先于第一帧生效）把导航栏与页面骨架整体藏住，
   登录态确认前用户看到的是干净的白底而不是「导航栏闪一下再被登录框盖住」。
   移除时机由 js/22-auth.js 的 ensureAuth() 负责（每条出口都调 authBootRelease），
   index.html 里另有 5 秒内联兜底。用 visibility 而不是 display：保留布局盒子，
   登录成功后移除类即可显示，不触发整页重排。 */
body.pre-auth .topbar,
body.pre-auth .shell { visibility: hidden; }

.auth-card {
  width: 100%;
  max-width: 380px;
  padding: 36px 34px 30px;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  background: #fff;
  box-shadow: var(--shadow-card);
}

.auth-brand { display: flex; align-items: center; gap: 8px; margin-bottom: 26px; }
.auth-mark { width: 24px; height: 24px; display: block; }
.auth-brand-text {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* 登录 / 注册 切换：一条底线，不用胶囊、不用背景块 */
.auth-tabs { display: flex; gap: 18px; margin-bottom: 20px; }
.auth-tab {
  padding: 0 0 7px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-3);
}
.auth-tab:hover { color: var(--text); }
.auth-tab.active { border-bottom-color: var(--ink); color: var(--ink); }

.auth-title {
  margin-bottom: 8px;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.auth-sub {
  margin-bottom: 24px;
  font-size: 13px;
  line-height: 1.75;
  color: var(--text-2);
}

.auth-form { display: block; }
.auth-label {
  display: block;
  margin-bottom: 7px;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-3);
}
.auth-input {
  display: block;
  width: 100%;
  height: 34px;
  margin-bottom: 16px;
  padding: 0 11px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 14px;
  color: var(--text);
  font-family: inherit;
}
.auth-input::placeholder { color: var(--text-3); }
.auth-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(35, 131, 226, 0.12);
}
.auth-row { display: block; }

.auth-msg {
  min-height: 17px;
  margin-bottom: 10px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--c-weak);
}

.auth-submit {
  width: 100%;
  height: 36px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
}
.auth-submit:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
.auth-submit:disabled { opacity: 0.45; cursor: not-allowed; }

.auth-skip {
  display: block;
  width: 100%;
  margin-top: 14px;
  padding: 0;
  border: 0;
  background: none;
  font-size: 12px;
  font-family: inherit;
  color: var(--text-3);
  text-align: center;
}
.auth-skip:hover { color: var(--text-2); }
.auth-skip.hide { display: none; }

/* ── 右上角用户条 ── */
.topbar-user {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex-shrink: 0;
}
.topbar-user.hide { display: none; }
.auth-chip-user { font-size: 13px; font-weight: 500; color: var(--ink); }
.auth-chip-tag { font-size: 11.5px; color: var(--text-3); }
.auth-chip-btn {
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: #fff;
  font-size: 12px;
  font-family: inherit;
  color: var(--text-2);
}
.auth-chip-btn:hover { background: var(--bg-callout); }

@media (max-width: 640px) {
  .auth-card { padding: 28px 22px 24px; }
  .topbar-user { gap: 6px; }
  .auth-chip-tag { display: none; }
}