﻿/* =========================================================
   畅畅背单词 · 基础层 (base.css)
   ---------------------------------------------------------
   本文件只放「所有页面共用」的东西，分四类：
     1. 设计令牌 (:root 变量)        2. 基础重置与排版
     3. 公共组件 (导航/卡片/按钮/表单/弹窗/提示条)
     4. 工具类 (极少量)
   页面专属样式一律写到 vocab.css / test.css 里，不要往这里加。
   ========================================================= */

/* ---------------------------------------------------------
   1. 设计令牌
   --------------------------------------------------------- */
/* =========================================================
   字体：音标（IPA）专用
   =========================================================
   音标符号（ə ʃ ˈ ˌ ɪ ʊ ʒ θ ð）在普通西文字体里会粘连、看不清。
   Charis SIL 是专为音标设计的字体。

   字体文件已打包在本项目 fonts/ 目录里（约 1.4MB），
   ✅ 完全离线、拷到任何电脑效果一致，不依赖网络。

   ⚠️ 只加载 400 与 700 两个字重。
   音标文字必须用这两个字重之一 —— 写 600 之类会让浏览器
   合成加粗（把笔画涂抹加粗），小符号会糊在一起。
   --------------------------------------------------------- */

@font-face {
  font-family: 'Charis SIL';
  src: url('../fonts/CharisSIL-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Charis SIL';
  src: url('../fonts/CharisSIL-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- 护眼主题色系 --- */
  --bg-main: #f4f8f5;
  --bg-card: #ffffff;
  --text-primary: #2d3a31;
  --text-muted: #6e8275;

  /* --- 主题互动色 --- */
  --primary: #43a047;
  --primary-hover: #388e3c;
  --primary-light: #e8f5e9;

  --accent-blue: #42a5f5;
  --accent-blue-light: #e3f2fd;

  --accent-amber: #ffa726;
  --accent-amber-light: #fff3e0;

  --accent-red: #ef5350;
  --accent-red-light: #ffebee;

  /* --- 中性色（表单、状态、文字层次） --- */
  --neutral-50: #f8fafc;
  --neutral-100: #f1f5f9;
  --neutral-200: #e2e8f0;
  --neutral-300: #cbd5e1;
  --neutral-400: #94a3b8;
  --neutral-500: #64748b;
  --neutral-600: #475569;
  --neutral-700: #334155;
  --neutral-800: #0f172a;

  /* --- 边框与圆角 --- */
  --border-color: #d6e8d8;
  --radius-lg: 24px;
  --radius-md: 16px;
  --radius-sm: 12px;

  /* --- 阴影 --- */
  --shadow-soft: 0 8px 20px rgba(67, 160, 71, 0.06);
  --shadow-btn: 0 4px 0 #388e3c;
  --shadow-card-hover: 0 10px 24px rgba(67, 160, 71, 0.12);

  /* --- 音标字体栈 ---
     Charis SIL 已随项目打包（见上面的 @font-face），完全离线可用。
     后面的系统字体只是极端情况下的兜底。 */
  --font-ipa: "Charis SIL", "Gentium Plus", "Doulos SIL",
              "Lucida Sans Unicode", "Segoe UI", "DejaVu Sans", Arial, sans-serif;

  /* --- 遮罩 --- */
  --overlay-bg: rgba(45, 58, 49, 0.4);
  --overlay-blur: blur(2px);
}

/* ---------------------------------------------------------
   2. 基础重置与排版
   --------------------------------------------------------- */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "PingFang SC", "Microsoft YaHei", sans-serif;
}

body {
  background-color: var(--bg-main);
  color: var(--text-primary);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.92em;
  background: var(--neutral-100);
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--neutral-700);
}

/* ---------------------------------------------------------
   3. 公共组件
   --------------------------------------------------------- */

/* --- 3.1 顶部导航 --- */
.header {
  background-color: var(--bg-card);
  border-bottom: 2px solid var(--border-color);
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.02);
}

.header-container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 0 16px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  flex-shrink: 0;
}

.logo-icon {
  width: 42px;
  height: 42px;
  background: linear-gradient(135deg, #66bb6a, #43a047);
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 22px;
  font-weight: 900;
  box-shadow: 0 4px 10px rgba(67, 160, 71, 0.3);
}

.logo-text {
  font-size: 20px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.5px;
}

.nav-group {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.nav-item {
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  color: var(--text-muted);
  transition: all 0.2s ease;
  border: 1.5px solid transparent;
  cursor: pointer;
}

.nav-item:hover {
  background-color: var(--primary-light);
  color: var(--primary);
}

.nav-item.active {
  background-color: var(--primary-light);
  color: var(--primary);
  border-color: #a5d6a7;
}

.nav-item.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* --- 3.2 主内容区 --- */
.main-container {
  max-width: 900px;
  width: 100%;
  margin: 24px auto;
  padding: 0 16px;
  flex: 1;
}

.main-container.is-wide { max-width: 1000px; }

/* --- 3.3 卡片 --- */
.card {
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  border: 2px solid var(--border-color);
  box-shadow: var(--shadow-soft);
  padding: 24px;
  overflow: hidden;
}

.card + .card { margin-top: 24px; }

.card-section-title {
  font-size: 20px;
  font-weight: 800;
  margin-bottom: 4px;
}

.card-section-sub {
  font-size: 13px;
  color: var(--text-muted);
}

/* --- 3.4 按钮 --- */
.btn {
  --btn-bg: var(--primary);
  --btn-shadow: #2e7d32;
  --btn-color: #ffffff;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 22px;
  border-radius: 50px;
  font-size: 15px;
  font-weight: 800;
  border: none;
  cursor: pointer;
  transition: all 0.15s ease;
  text-decoration: none;
  user-select: none;
  white-space: nowrap;

  background-color: var(--btn-bg);
  color: var(--btn-color);
  box-shadow: 0 4px 0 var(--btn-shadow);
}

.btn:active:not(:disabled) {
  transform: translateY(3px);
  box-shadow: 0 1px 0 var(--btn-shadow);
}

.btn:disabled,
.btn.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
  filter: grayscale(60%);
}

.btn-primary   { --btn-bg: var(--primary);     --btn-shadow: #2e7d32; }
.btn-secondary { --btn-bg: var(--accent-blue); --btn-shadow: #1e88e5; }
.btn-danger    { --btn-bg: var(--accent-red);  --btn-shadow: #c62828; }
.btn-warning   { --btn-bg: var(--accent-amber);--btn-shadow: #e65100; }

.btn-sm { padding: 6px 16px; font-size: 13px; }
.btn-lg { padding: 14px 40px; font-size: 18px; }
.btn-block { width: 100%; }

.btn-group {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

/* 方形图标按钮 */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  width: 34px;
  height: 34px;
  padding: 0;
  font-size: 15px;
  cursor: pointer;
  border: 1px solid transparent;
  box-sizing: border-box;
  transition: all 0.15s ease;
  background: transparent;
}

.icon-btn.kill   { background: #f0fdf4; color: #16a34a; border-color: #bbf7d0; }
.icon-btn.kill:hover   { background: #dcfce7; border-color: #86efac; }

.icon-btn.edit   { background: #eff6ff; color: #2563eb; border-color: #bfdbfe; }
.icon-btn.edit:hover   { background: #dbeafe; border-color: #93c5fd; }

.icon-btn.delete { background: #fef2f2; color: #ef4444; border-color: #fecaca; }
.icon-btn.delete:hover { background: #fee2e2; border-color: #fca5a5; }

.icon-btn:disabled,
.icon-btn.is-disabled {
  opacity: 0.35;
  cursor: not-allowed;
  filter: grayscale(100%);
  pointer-events: none;
}

/* --- 3.5 表单 --- */
.inline-input,
.form-input,
.form-select,
.form-textarea {
  width: 100%;
  padding: 10px 14px;
  border: 2px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--text-primary);
  background: #fff;
  outline: none;
  box-sizing: border-box;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  font-family: inherit;
}

.form-textarea { resize: vertical; line-height: 1.6; }

.inline-input:focus,
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(67, 160, 71, 0.12);
}

.form-select { cursor: pointer; font-weight: 800; }

.form-label {
  display: block;
  font-size: 13px;
  font-weight: 800;
  margin-bottom: 6px;
}

.form-row { display: flex; flex-direction: column; gap: 6px; }

.field-hint-box {
  font-size: 12px;
  color: var(--neutral-500);
  margin-top: 6px;
  background: var(--neutral-50);
  border: 1px solid var(--neutral-200);
  padding: 10px 12px;
  border-radius: 8px;
  line-height: 1.6;
}

.field-hint-box ol,
.field-hint-box ul { margin: 0 0 0 18px; padding: 0; }
.field-hint-box li { margin: 2px 0; }

.custom-checkbox {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: var(--primary);
}

/* --- 3.6 弹窗 --- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay-bg);
  backdrop-filter: var(--overlay-blur);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

.modal-overlay.active {
  opacity: 1;
  pointer-events: auto;
}

.modal-card {
  background: #ffffff;
  border-radius: var(--radius-lg);
  border: 2px solid var(--border-color);
  width: 90%;
  max-width: 540px;
  max-height: 90vh;
  overflow-y: auto;
  padding: 24px;
  box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
}

.modal-card.is-wide { max-width: 640px; }

.modal-card::-webkit-scrollbar { width: 6px; }
.modal-card::-webkit-scrollbar-track { background: var(--neutral-100); border-radius: 4px; }
.modal-card::-webkit-scrollbar-thumb { background: var(--neutral-300); border-radius: 4px; }
.modal-card::-webkit-scrollbar-thumb:hover { background: var(--neutral-400); }

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  border-bottom: 2px solid var(--border-color);
  padding-bottom: 12px;
  margin-bottom: 18px;
}

.modal-title {
  font-size: 20px;
  font-weight: 800;
  margin: 0;
}

.modal-close-btn {
  background: none;
  border: none;
  font-size: 20px;
  cursor: pointer;
  color: var(--neutral-500);
  line-height: 1;
  padding: 4px;
  border-radius: 6px;
  transition: all 0.15s ease;
}

.modal-close-btn:hover {
  background: var(--neutral-100);
  color: var(--neutral-700);
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 2px solid var(--border-color);
  flex-wrap: wrap;
}

/* --- 3.7 徽标 / 标签 --- */
.card-badge {
  font-size: 11px;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: 6px;
  white-space: nowrap;
}

.badge-admin { background: #f3e5f5; color: #7b1fa2; }
.badge-batch { background: #fff3e0; color: #e65100; }
.badge-audio { background: #e0f2fe; color: #0369a1; }

/* --- 3.8 提示条 / 空状态 / 加载态 --- */
.empty-tip {
  color: var(--neutral-400);
  font-style: italic;
}

.error-tip {
  font-size: 12px;
  color: #dc2626;
  font-weight: 700;
  background: #fef2f2;
  border: 1px solid #fecaca;
  padding: 8px 12px;
  border-radius: 8px;
  line-height: 1.6;
}

.loading-tip {
  color: var(--text-muted);
  font-size: 13px;
  padding: 12px 0;
  text-align: center;
}

/* --- 3.9 数据格（首页统计用） --- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

.stat-box {
  background: #fafdfa;
  border: 2px solid var(--border-color);
  border-radius: var(--radius-md);
  padding: 20px;
}

.stat-box.is-red   { background: var(--accent-red-light);   border-color: #ffcdd2; }
.stat-box.is-green { background: var(--primary-light);      border-color: #c8e6c9; }
.stat-box.is-blue  { background: var(--accent-blue-light);  border-color: #bbdefb; }

.stat-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-muted);
}

.stat-box.is-red   .stat-label { color: var(--accent-red); }
.stat-box.is-green .stat-label { color: var(--primary); }
.stat-box.is-blue  .stat-label { color: var(--accent-blue); }

.stat-value {
  font-size: 32px;
  font-weight: 900;
  color: var(--text-primary);
  margin-top: 6px;
  line-height: 1.1;
}

.stat-box.is-red   .stat-value { color: var(--accent-red); }
.stat-box.is-green .stat-value { color: var(--primary); }
.stat-box.is-blue  .stat-value { color: var(--accent-blue); }

.stat-unit { font-size: 14px; font-weight: 700; margin-left: 4px; }

/* --- 3.9.0 今日任务卡片 ---------------------------------------- */
.task-card {
  text-align: center;
  padding: 34px 28px 38px;
}

.task-eyebrow {
  display: inline-block;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 3px;
  color: var(--primary);
  background: var(--primary-light);
  padding: 5px 16px 5px 19px;
  border-radius: 999px;
  margin-bottom: 18px;
}

.task-book {
  font-size: 34px;
  font-weight: 900;
  color: var(--text-primary);
  line-height: 1.25;
  margin: 0 0 22px;
  word-break: break-word;
}

/* 三个数字指标：待测 / 总量 / 待修正 */
.task-metrics {
  display: inline-flex;
  align-items: center;
  gap: 26px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  justify-content: center;
}

.task-metric {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 84px;
}

.task-metric-num {
  font-size: 32px;
  font-weight: 900;
  color: var(--primary);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.task-metric-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
}

.task-metric-divider {
  width: 1px;
  height: 34px;
  background: var(--border-color);
}

.task-hint {
  font-size: 14px;
  color: var(--text-muted);
  margin: 0 0 22px;
  min-height: 22px;
}

.btn-xl {
  font-size: 18px;
  padding: 15px 52px;
  border-radius: 999px;
}

/* --- 3.9.1 等级分布：标题在上，饼与图例并排等高 -------------------
   布局（按用户要求）：
     · 「等级分布」标题独占一行，在左上
     · 标题下方一行：左边饼图、右边图例
     · 饼与图例**等高**，图例纵向铺满这一行
   --------------------------------------------------------- */
.dist-block {
  margin-top: 26px;
  padding-top: 26px;
  border-top: 1px solid var(--border-color);
}

.dist-chart-head {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-muted);
  margin-bottom: 14px;
}

/* 一行两列：饼 + 图例，图例铺满这一行的高度 */
.dist-body {
  display: flex;
  /* ❌ 绝对不能用 align-items: stretch —— 那会把饼拉高到与图例同高，
     宽高比被破坏，圆就压成椭圆（真实踩过的坑）。
     图例自己用 flex 撑满高度即可。 */
  align-items: flex-start;
  gap: 30px;
  flex-wrap: wrap;
}

/* 饼容器：只负责定位与限宽；
   宽高比约束放在 SVG 自己身上，保证与 viewBox 完全一致。 */
.dist-pie-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 620px;
  margin: 0;
  /* ⚠️⚠️ 箱体比例**必须**等于 SVG 的 viewBox 比例（760:560）。
     下面那个绝对定位的白心是按"百分比"摆的：横向 % 按宽度算、
     纵向 % 按高度算 —— 只有箱体比例正确，两个方向才等价，
     白心才会落在环的正中间。 */
  aspect-ratio: 760 / 560;
}

/* ⚠️ 圆会不会变椭圆，只看这一条：**SVG 元素框的宽高比 = viewBox 宽高比**。
   写法上有个坑：用 `height: auto` 让浏览器自己算高度时，若祖先里有
   flex 拉伸（`align-items: stretch` / `align-self: stretch`），
   计算出的高度可能与 aspect-ratio 不符 → 圆被压扁。
   所以这里用「aspect-ratio + 视口单位 height」双保险：
   height 由视口算出，浏览器不必回头去猜。 */
.dist-pie-svg {
  display: block;
  width: 100%;
  height: 100%;
  /* ⚠️ `height: calc(min(100%, 620px) * 560 / 760)` 是**错的**：
     calc 里的 `100%` 在 height 上解析的是**父元素高度**，不是宽度 ——
     算出来的高度与箱体宽度无关，SVG 就被塞进一个比例不对的框里，
     内容按 meet 居中后**与上面按百分比定位的白心错位** → 看着"不圆"。
     现在高度交给父容器的 aspect-ratio，这里 100% 填满即可。 */
}

/* 扇区：白色描边分离相邻色块 */
.dist-pie-svg .slice {
  stroke: #ffffff;
  stroke-width: 2.5;
  transition: opacity 0.2s ease;
}

.dist-pie-svg .slice:hover {
  opacity: 0.82;
}

/* 引线（窄扇区 → 饼外标注） */
.dist-pie-svg .slice-leader {
  stroke: #c3cad2;
  stroke-width: 1.6;
  fill: none;
}

/* 扇区内部的百分比（只要百分比，不要词数） */
.dist-pie-svg .slice-pct {
  font-size: 21px;
  font-weight: 900;
  fill: #ffffff;
  paint-order: stroke;
  stroke: rgba(0, 0, 0, 0.13);
  stroke-width: 3px;
  font-variant-numeric: tabular-nums;
}

/* 饼外引线标注的百分比 */
.dist-pie-svg .slice-callout {
  font-size: 16px;
  font-weight: 900;
  fill: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* 中心白心：位置与尺寸**严格按 SVG 几何换算**，不能用 inset/50% 猜。
     SVG viewBox 760×560，圆心 (250, 280)，内半径 138
     · 直径占宽：2×138 / 760       = 36.316%
     · 圆心离左：(250 - 138) / 760 = 14.737%
     · 圆心离上：(280 - 138) / 760 = 18.684%
       —— 垂直偏移也除以 **760**：容器 `aspect-ratio:760/560` 保证
          高度 = 宽度×560/760，所以用宽度百分比表示正好等价。 */
.dist-pie-center {
  /* ⚠️⚠️ 白心位置**严格按 SVG 几何换算**，不能凭感觉：
     viewBox 760×560，圆心 (250,280)，内半径 138
       · 宽 = 2×138 / 760      = 36.316%（横向按宽度算 ✔）
       · 左 = (250-138) / 760  = 14.737%
       · 上 = (280-138) / **560** = 25.357%
     ❗ 之前 top 写的是 18.684%（= 142/760）—— **纵向却除了 760**，
        结果白心往上偏了 37 个单位，环看着就是不圆、白心也偏心。
     高度用 aspect-ratio: 1/1 自动跟宽度走：宽度 36.316% × (760/560) = 49.29%，
     正好等于 2×138/560，所以是正圆。 */
  position: absolute;
  left: 14.737%;
  top: 25.357%;
  width: 36.316%;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background: #ffffff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.dist-pie-center span {
  font-size: clamp(30px, 4.2vw, 52px);
  font-weight: 900;
  color: var(--text-primary);
  line-height: 1.02;
  font-variant-numeric: tabular-nums;
}

.dist-pie-center small {
  font-size: 13px;
  color: var(--text-muted);
  font-weight: 700;
}

/* 图例：与饼等高，条目拉开间距
   ⚠️ 必须限宽 + margin-left:auto：
      否则 flex 会把它拉到整行宽度，条目浅灰背景拖出一条很宽的空带。 */
.dist-legend-col {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 300px;              /* 限宽：否则浅灰背景拖出一条空带 */
  display: flex;
  align-self: stretch;           /* 拉伸到与饼同高（饼自己不被拉伸） */
  margin-left: auto;             /* 整块贴到这一行右侧 */
}

.dist-legend {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;   /* 条目纵向均匀铺开，撑满整行高度 */
  gap: 4px;
}

/* 单个图例项：色块 + 等级数字 + 文字 + 词数 */
.dist-legend .legend-item {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  padding: 0 10px;
  border-radius: 8px;
  background: var(--neutral-50);
  white-space: nowrap;
  min-width: 0;
  flex: 1 1 auto;                   /* 每项等高，一起撑满高度 */
}

.dist-legend .legend-dot {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* 等级数字（-3 … 6） */
.dist-legend .legend-level {
  font-size: 11px;
  font-weight: 900;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  min-width: 17px;
  text-align: center;
}

/* ⚠️ 不要用 flex-grow：那会把数字推到最右边、文字与数字之间空出一大片。
   让它按内容宽度紧挨着数字，数字自然跟在文字后面。 */
.dist-legend .legend-text {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 0 1 auto;
}

.dist-legend .legend-num {
  font-weight: 900;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* 计数为 0 的等级淡化 */
.dist-legend .legend-item.is-zero {
  opacity: 0.34;
}

@media (max-width: 820px) {
  .dist-body { gap: 20px; }
  .dist-pie-wrap { flex: 1 1 100%; }
  .dist-legend-col { flex: 1 1 100%; }
  .dist-legend { justify-content: flex-start; gap: 5px; }
  .dist-legend .legend-item { flex: 0 0 auto; min-height: 32px; }
  .task-book { font-size: 26px; }
  .dist-pie-svg .slice-pct { font-size: 17px; }
  .dist-pie-svg .slice-callout { font-size: 14px; }
}

/* --- 3.10 轻提示 Toast --- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 32px;
  transform: translate(-50%, 20px);
  background: var(--text-primary);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  padding: 12px 22px;
  border-radius: 50px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  opacity: 0;
  pointer-events: none;
  transition: all 0.25s ease;
  z-index: 2000;
  max-width: 88vw;
  text-align: center;
}

.toast.active {
  opacity: 1;
  transform: translate(-50%, 0);
}

.toast.is-error { background: #dc2626; }
.toast.is-ok    { background: var(--primary); }

/* --- 3.11 页脚 --- */
.footer {
  text-align: center;
  font-size: 12px;
  color: var(--text-muted);
  padding: 20px 16px;
}

/* ---------------------------------------------------------
   4. 工具类
   --------------------------------------------------------- */
.is-hidden { display: none !important; }

.clamp-2-lines {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
  word-break: break-word;
}

.cell-center {
  display: flex;
  align-items: center;
  min-height: 48px;
}

.divider {
  height: 2px;
  background: var(--border-color);
  border-radius: 2px;
  margin: 16px 0;
}

/* ---------------------------------------------------------
   5. 响应式
   --------------------------------------------------------- */
@media (max-width: 768px) {
  .header-container { height: auto; padding: 10px 16px; flex-wrap: wrap; }
  .nav-group { width: 100%; justify-content: flex-start; }
  .nav-item { padding: 6px 12px; font-size: 13px; }
  .main-container { margin: 16px auto; }
  .card { padding: 18px; border-radius: var(--radius-md); }
  .modal-card { padding: 18px; }
}
