:root {
  --bg: #f5f7fa;
  --panel: #ffffff;
  --panel-2: #f0f4f8;
  --line: #e3e8ef;
  --text: #1f2937;
  --text-2: #5b6675;
  --text-3: #8a94a6;
  --primary: #1c3a5e;
  --primary-2: #2f6fa8;

  --accent: #e8813a;
  --ok: #2f9e6f;
  --warn: #d99a2b;
  --danger: #c85a52;
  --radius: 14px;
  --shadow: 0 6px 24px rgba(24, 46, 74, .08);
  /* 平板专注面板 sticky 时要空出的顶部距离（= 吸顶顶栏高度 + 间距）。
     这里是兜底值，kid.js 启动时按顶栏实测高度覆盖 —— 硬编码一个数字
     迟早会在某个字号/换行/缩放下露馅。 */
  --kid-focus-top: 92px;

  /* 孩子端任务状态色（2026-09-27）。选色原则：
     **未完成 = 彩色、完成 = 灰**——两档饱和度的差别要大，孩子不用读字就能分。
     之前的做法只是把做完的卡片 opacity 降到 .72，等于把字也一起弄糊了，
     孩子读出来的不是「做完了」而是「看不清」。 */
  --k-todo: #1d6fe0;
  --k-todo-bg: #e8f0fd;
  --k-todo-line: #c3d9f8;
  --k-doing: #0f9d58;
  --k-paused: #64748b;
  --k-review: #e8813a;
  --k-done: #9aa1ac;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.6 -apple-system, "Segoe UI", "Microsoft YaHei", "PingFang SC", sans-serif;
}

/* ── 顶栏 ── */
.topbar {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 16px 28px; background: var(--panel); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.brand { display: flex; align-items: center; gap: 12px; }
.logo {
  width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;
  background: linear-gradient(135deg, var(--primary), var(--primary-2));
  color: #fff; font-weight: 700; font-size: 20px;
}
.topbar h1 { margin: 0; font-size: 17px; font-weight: 700; }
.topbar h1 em { font-style: normal; color: var(--text-3); font-weight: 400; font-size: 13px; }
.sub { margin: 2px 0 0; color: var(--text-3); font-size: 12px; }
.topbar-actions { display: flex; align-items: center; gap: 8px; }

.badge { padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge-on { background: rgba(47,158,111,.12); color: var(--ok); }
.badge-off { background: var(--panel-2); color: var(--text-3); }

/* ── 布局 ── */
/* 家长端 / 孩子端已拆成独立页面，内容按阅读宽度单栏居中，不再左右分屏。
   孩子端主场景是平板，所以它的容器更宽。 */
.single { padding: 22px 28px 60px; max-width: 760px; margin: 0 auto; }
.page-kid .single { max-width: 920px; }
@media (max-width: 980px) { .single { padding: 16px 14px 48px; } }

/* ── 卡片 ── */
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; margin-bottom: 14px; }
.card-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.card-title h3 { margin: 0; font-size: 14px; font-weight: 600; }
.hint { font-size: 12px; color: var(--text-3); }
.meta { font-size: 12px; color: var(--text-3); margin-top: 8px; min-height: 16px; }

/* ── 表单 ── */
.field { display: block; margin-bottom: 10px; }
.field span { display: block; font-size: 12px; color: var(--text-2); margin-bottom: 4px; }
input, select, textarea {
  width: 100%; padding: 9px 11px; border: 1px solid var(--line); border-radius: 10px;
  background: #fff; color: var(--text); font: inherit; outline: none;
}
textarea { resize: vertical; line-height: 1.7; }
input:focus, select:focus, textarea:focus { border-color: var(--primary-2); box-shadow: 0 0 0 3px rgba(47,111,168,.12); }
.row { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.row select { flex: 1 1 120px; width: auto; }

/* ── 按钮 ── */
.btn {
  padding: 9px 16px; border-radius: 10px; border: 1px solid transparent; cursor: pointer;
  font: inherit; font-weight: 600; transition: .15s;
}
.btn-primary { background: linear-gradient(135deg, var(--primary), var(--primary-2)); color: #fff; }
.btn-primary:hover { filter: brightness(1.08); }
.btn-ghost { background: var(--panel-2); color: var(--text-2); border-color: var(--line); }
.btn-ghost:hover { background: #e6ecf4; }
.btn-sm { padding: 5px 11px; font-size: 12px; border-radius: 8px; }
.btn-ok { background: rgba(47,158,111,.12); color: var(--ok); }
.btn-ok:hover { background: rgba(47,158,111,.2); }
.btn-warn { background: rgba(217,154,43,.14); color: #a9761a; }
.btn-danger { background: rgba(200,90,82,.12); color: var(--danger); }
.btn-block { width: 100%; margin-top: 4px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* ── 任务卡 ── */
.task-list { display: flex; flex-direction: column; gap: 8px; }
.task {
  border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px;
  display: flex; gap: 10px; align-items: center; background: #fff;
}
.task-main { flex: 1; min-width: 0; }
.task-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.task-content { font-weight: 600; }
.task-sub { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.subject { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 6px; background: var(--panel-2); color: var(--primary); }
.subject-语文 { background: #fdeeea; color: #c0563f; }
.subject-数学 { background: #e9f0fb; color: #35618f; }
.subject-英语 { background: #eaf6ef; color: #2f7d59; }
.subject-科学 { background: #e6f6f4; color: #26756e; }
.subject-道法 { background: #fdeff5; color: #a3486e; }
.subject-物理 { background: #eaf0fb; color: #3a5b9a; }
.subject-化学 { background: #f1eefb; color: #5b4b9a; }
.subject-生物 { background: #ebf6e8; color: #3d7a34; }
.subject-历史 { background: #fbf3e4; color: #8a6420; }
.subject-地理 { background: #e8f5ef; color: #2c7a5e; }
.subject-政治 { background: #fdeff5; color: #a3486e; }
.subject-体育 { background: #eef7e6; color: #4a7a2a; }
.subject-音乐 { background: #fbeff7; color: #8f3f78; }
.subject-美术 { background: #fdf0e6; color: #a5622a; }
.subject-信息技术 { background: #e9f1f7; color: #34637f; }
.subject-其他 { background: #f1f1f4; color: #6b7280; }
.subject-未分类 { background: #f1f1f4; color: #6b7280; }
.subject-常规 { background: rgba(47,111,168,.12); color: var(--primary-2); }
.subject-劳动 { background: #fdf2e6; color: #a5622a; }
.subject-习惯 { background: #eef4fb; color: #3a5b9a; }
.task-actions { display: flex; gap: 6px; flex-shrink: 0; }
.conf-low { color: var(--warn); font-size: 11px; font-weight: 600; }

.status { font-size: 11px; padding: 2px 8px; border-radius: 999px; font-weight: 600; }
.status-pending { background: var(--panel-2); color: var(--text-2); }
.status-doing { background: rgba(47,111,168,.12); color: var(--primary-2); }
.status-paused { background: rgba(217,154,43,.15); color: #a9761a; }
.status-done { background: rgba(47,158,111,.12); color: var(--ok); }
.status-approved { background: rgba(47,158,111,.2); color: #1f7a53; }

.timer { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 15px; color: var(--primary-2); min-width: 62px; text-align: right; }

/* 识别预览行 */
.pv-row { display: flex; gap: 6px; align-items: center; }
.pv-row select { flex: 0 0 88px; padding: 6px 8px; }
.pv-row input { flex: 1; padding: 6px 9px; }
.pv-row input.min { flex: 0 0 78px; }

/* ── 统计 ── */
.stats { display: flex; flex-direction: column; gap: 8px; }
.stat-row { display: flex; align-items: center; gap: 10px; }
.stat-name { flex: 0 0 56px; font-size: 12px; color: var(--text-2); }
.stat-bar { flex: 1; height: 8px; background: var(--panel-2); border-radius: 999px; overflow: hidden; }
.stat-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--primary-2), #6fa8d8); }
.stat-val { flex: 0 0 62px; text-align: right; font-size: 12px; color: var(--text-3); }

/* ── 孩子端 ── */
.kid-hero { padding: 14px 16px; border-radius: var(--radius); margin-bottom: 14px;
  background: linear-gradient(135deg, #1c3a5e, #2f6fa8); color: #fff; }
.kid-name { font-size: 18px; font-weight: 700; }
.kid-meta { font-size: 12px; opacity: .85; margin-top: 4px; }
.points-list { display: flex; flex-direction: column; gap: 6px; font-size: 14px; }
.point-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 8px 10px; background: var(--panel-2); border-radius: 8px; line-height: 1.45; }
.point-row b { color: var(--ok); font-size: 14.5px; }

/* ── 提示 ── */
.warn { background: #fff8e8; border: 1px solid #f2e0b6; color: #8a6420; padding: 8px 10px; border-radius: 10px; font-size: 12px; margin: 8px 0; }
.empty { color: var(--text-3); font-size: 13px; padding: 14px; text-align: center; background: var(--panel-2); border-radius: 10px; }
.hidden { display: none !important; }
/* ⚠️ hidden **属性** 也要显式兜住。UA 默认的 `[hidden]{display:none}` 会被任何一条
   后写的 display 压过去（`.kid-only-undone[hidden]` 已经为这个坑单独补过一次）。
   入口页的「识别引擎状态」卡与顶栏徽标靠 hidden 属性默认隐藏（只给总管理员看），
   这里再加一道，免得以后给 .card / .badge 加 display 时悄悄把它重新露出来。 */
.home-card[hidden], .badge[hidden] { display: none !important; }
/* 入口页引擎卡标题右侧的「管理后台 →」：跟随卡片一起显隐（卡片藏了它就藏了） */
.engine-admin-link { margin-left: auto; text-decoration: none; }

.toast {
  position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 20px);
  background: #1f2937; color: #fff; padding: 10px 18px; border-radius: 10px;
  font-size: 13px; opacity: 0; pointer-events: none; transition: .25s; z-index: 99;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ══════════════════════════════════════════════════════════════════
   识别引擎相关样式（大模型优先 / 待确认 / 备注与评价 / 配置面板）
   ══════════════════════════════════════════════════════════════════ */
.badge-warn { background: rgba(217,154,43,.14); color: #a8761c; }

/* 任务类型：常规习惯与学科作业视觉上区分开，避免家长误当成作业 */
.subject-routine { background: rgba(47,111,168,.12); color: var(--primary-2); }
.pv-type {
  flex: 0 0 auto; padding: 4px 8px; border-radius: 7px; font-size: 12px; font-weight: 600;
  background: var(--panel-2); color: var(--text-2); white-space: nowrap;
}
.pv-type.pv-routine { background: rgba(47,111,168,.12); color: var(--primary-2); }

/* 「需要孩子提交作业」勾选框：默认不勾，勾了孩子端才出现交作业入口 */
.need-submit {
  display: inline-flex; align-items: center; gap: 6px; margin: 6px 0 2px;
  font-size: 12.5px; color: var(--text-2); cursor: pointer; user-select: none;
}
.need-submit input { width: 15px; height: 15px; accent-color: var(--primary, #2f6fa8); cursor: pointer; }
.need-submit-batch { flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; }
.need-submit-batch .meta { flex: 1 1 100%; }

/* 备注（注意：左手压书…）与星级评价：识别出来的细节必须让孩子看到 */
.task-detail { margin: 6px 0 2px; }
.note-list {
  margin: 4px 0 0; padding-left: 18px; color: var(--text-2); font-size: 12.5px; line-height: 1.7;
}
.note-list li::marker { color: var(--text-3); }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.chip {
  display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px;
  background: rgba(217,154,43,.13); color: #a8761c; font-weight: 600;
}

/* 双通道一致性提示 */
.conf-ok { color: var(--ok); }
.conf-low { color: #a8761c; font-weight: 600; }

/* ── 作答与批改结果（家长端复核 / 孩子端提交状态）────────────────────────
   批改是有后果的判断，所以视觉上要「像建议」而不是「像判决」：
   顶部徽标带「批改建议」字样、逐题判定用色区分、底部固定提示需家长确认。 */
.grade-box {
  margin-top: 8px; padding: 10px 12px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
}
.grade-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.grade-badge {
  font-size: 12px; font-weight: 600; padding: 2px 9px; border-radius: 999px;
  background: #e8f2ec; color: var(--ok);
}
.grade-badge-ok { background: #e8f2ec; color: var(--ok); }
.grade-badge-warn { background: #fdf3e3; color: #a8761c; }
.grade-items { list-style: none; margin: 8px 0 0; padding: 0; }
.grade-item {
  display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline;
  padding: 5px 0; border-top: 1px dashed var(--line); font-size: 12.5px; line-height: 1.55;
}
.grade-item:first-child { border-top: none; }
.grade-no { color: var(--text-3); min-width: 16px; }
.grade-verdict { font-weight: 600; min-width: 56px; }
.v-correct .grade-verdict { color: var(--ok); }
.v-wrong .grade-verdict { color: var(--danger); }
.v-partial .grade-verdict { color: #a8761c; }
.v-unclear .grade-verdict { color: var(--text-3); }
.grade-score { color: var(--text-2); font-variant-numeric: tabular-nums; }
.grade-comment { flex: 1 1 100%; color: var(--text-2); }
.grade-comment-all { margin-top: 8px; font-size: 12.5px; color: var(--text-2); }
.grade-tip { margin-top: 6px; font-size: 12px; color: var(--text-3); }

/* 上传按钮 */
.row-upload { align-items: center; gap: 10px; margin-top: 8px; }
.btn-upload { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.meta-inline { color: var(--text-3); font-size: 12px; }

/* 学生端分组 —— 2026-09-24 起按**科目**分（语文 / 数学 / 英语 …，家长原话
   「按照参考图中的语文、数学等类型进行归类」）。加了左侧短竖条与条数徽章：
   纯靠加粗小字分不出「这是分组标题」还是「随便一行灰字」。 */
.kid-group { margin-bottom: 12px; }
.kid-group:last-child { margin-bottom: 0; }
.kid-group-title {
  position: relative; display: flex; align-items: center; gap: 6px; padding-left: 9px;
  font-size: 12.5px; font-weight: 800; color: var(--text-2); letter-spacing: .3px;
  margin: 2px 0 7px;
}
.kid-group-title::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 13px; border-radius: 2px; background: var(--primary-2);
}
/* 分组右侧的计数：孩子关心的是「还剩几项没做」，不是「我做到哪了」。
   还有剩 → 橙色（要动手）；全做完 → 绿色（可以歇了）。 */
.kid-group-left {
  margin-left: auto; font-size: 11.5px; font-weight: 800;
  color: var(--k-review); font-variant-numeric: tabular-nums;
}
.kid-group-left.done { color: #2f7d4f; }

/* 引擎状态 / 大模型配置面板 */
.engine-box {
  margin-top: 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-2); padding: 0 12px;
}
.engine-box > summary {
  cursor: pointer; padding: 9px 0; font-size: 12.5px; color: var(--text-2); font-weight: 600;
  list-style: none;
}
.engine-box > summary::-webkit-details-marker { display: none; }
.engine-box > summary::before { content: '⚙ '; }
.engine-body { padding: 0 0 12px; }
.engine-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.engine-form { display: grid; gap: 7px; }
.engine-form input {
  width: 100%; padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); color: var(--text); font-size: 12.5px; font-family: inherit;
}
.engine-form input:focus { outline: 2px solid rgba(47,111,168,.25); border-color: var(--primary-2); }
.engine-form button { justify-self: start; }
.engine-foot { margin: 9px 0 0; font-size: 11.5px; color: var(--text-3); line-height: 1.6; }

/* ── 孩子端入口（家长端「孩子端绑定与账号」卡内，2026-09-29）──────────────
   整条链路里最难的一步是「那台平板上到底输什么」。所以这块要给足视觉重量：
   网址用等宽字体（看得出是一个要照抄的地址，不是一句说明），二维码单独一列。 */
.kid-entry {
  margin-top: 14px; padding: 14px 16px 12px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--panel-2);
}
.kid-entry-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.kid-entry-body { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.kid-entry-ways { flex: 1 1 320px; display: flex; flex-direction: column; gap: 12px; }
.kid-way { display: flex; flex-direction: column; gap: 5px; }
.kid-way-tag {
  align-self: flex-start; font-size: 11px; font-weight: 600;
  color: var(--primary-2); background: rgba(47,111,168,.1);
  padding: 1px 8px; border-radius: 999px;
}
.kid-url { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kid-url code {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 13.5px; font-weight: 600; color: var(--text);
  background: var(--panel); border: 1px solid var(--line);
  padding: 3px 9px; border-radius: 7px;
}
.kid-entry-qr { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.kid-entry-qr img {
  width: 150px; height: 150px; background: #fff;
  border: 1px solid var(--line); border-radius: 10px; padding: 5px;
}
/* 窄屏：二维码挪到最下面一行并居中，别把网址挤成两行 */
@media (max-width: 640px) {
  .kid-entry-body { justify-content: center; }
  .kid-entry-qr { order: 2; }
}

/* ══════════════════════════════════════════════════════════════════
   入口页（index.html）—— 双端分端后的选择页
   ══════════════════════════════════════════════════════════════════ */
.home-wrap { padding: 26px 28px 60px; max-width: 1040px; margin: 0 auto; }
@media (max-width: 980px) { .home-wrap { padding: 16px 14px 48px; } }

.entry-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 18px; }
@media (max-width: 820px) { .entry-grid { grid-template-columns: 1fr; } }

.entry-card {
  display: block; text-decoration: none; color: inherit;
  background: var(--panel); border: 1px solid var(--line); border-radius: 18px;
  box-shadow: var(--shadow); padding: 22px; transition: .18s;
}
.entry-card:hover { transform: translateY(-2px); border-color: var(--primary-2); box-shadow: 0 12px 32px rgba(24,46,74,.13); }
.entry-icon {
  display: grid; place-items: center; width: 52px; height: 52px; border-radius: 14px;
  font-size: 26px; margin-bottom: 12px;
}
.entry-icon-parent { background: linear-gradient(135deg, #eef4fb, #dbe8f6); }
.entry-icon-kid { background: linear-gradient(135deg, #eaf7f0, #d6efe1); }
.entry-card h2 { margin: 0 0 4px; font-size: 19px; }
.entry-desc { margin: 0 0 12px; color: var(--text-3); font-size: 13px; }
.entry-list { margin: 0 0 16px; padding-left: 18px; color: var(--text-2); font-size: 13px; line-height: 1.9; }
.entry-list li::marker { color: var(--text-3); }
.entry-go { font-weight: 700; font-size: 13.5px; color: var(--primary-2); }
.home-card { padding: 16px 18px; }

/* 入口页「第一次使用」步骤：自绘序号圆点，避免 ol 默认样式的缩进与 marker 颜色不齐 */
.home-steps { margin: 0; padding-left: 0; list-style: none; counter-reset: hs; color: var(--text-2); font-size: 13px; line-height: 1.85; }
.home-steps li { position: relative; padding-left: 26px; margin-bottom: 8px; }
.home-steps li:last-child { margin-bottom: 0; }
.home-steps li::before {
  counter-increment: hs; content: counter(hs);
  position: absolute; left: 0; top: 3px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--panel-2); color: var(--text-3);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
.home-steps b { color: var(--text); }

/* ⚠️ 以下两个类曾被入口页的「识别引擎状态」卡使用；那张卡 2026-09-29 已从公开页移除。
   类本身留着无害（别的宽表可能复用），但**别再把平台信息搬回公开页**——见 docs/12 §五。 */
.stat-name-wide { flex: 0 0 84px; }
.stat-val-wide { flex: 1; text-align: left; color: var(--text-2); font-size: 12.5px; overflow-wrap: anywhere; }

/* ══════════════════════════════════════════════════════════════════
   家长端补充：关键指标 / 孩子实时进度（计时状态回传，规划 2.6）
   ══════════════════════════════════════════════════════════════════ */
.kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 14px; }
@media (max-width: 640px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }
.kpi {
  background: var(--panel-2); border-radius: 12px; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 2px;
}
.kpi b { font-size: 20px; color: var(--primary); font-variant-numeric: tabular-nums; }
.kpi span { font-size: 12px; color: var(--text-3); }

/* ── 快捷加减分 chips（2026-10-08 美化）──────────────────────────────────
   原先直接复用 .btn-sm 一串空格拼接：无间距、分值和名称挤在一行文字里，
   加分扣分红绿混排。改成独立面板 + 「分值徽章 + 名称」药丸 chip，
   分值先入眼、名称跟后，加/减按边框色分列。 */
.qa-box {
  margin-top: 10px; padding: 10px 12px;
  background: var(--panel-2); border-radius: 12px;
}
.qa-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.qa-title { font-size: 12px; font-weight: 700; color: var(--text-2); letter-spacing: .5px; }
.qa-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.qa-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 13px 6px 7px; border-radius: 999px;
  border: 1px solid transparent; cursor: pointer; font: inherit;
  font-size: 13px; line-height: 1.5; transition: .15s; background: #fff;
}
.qa-chip b {
  font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums;
  padding: 1px 8px; border-radius: 999px;
}
.qa-chip.plus { border-color: rgba(47,158,111,.35); }
.qa-chip.plus b { background: rgba(47,158,111,.14); color: var(--ok); }
.qa-chip.plus:hover { border-color: var(--ok); background: rgba(47,158,111,.07); }
.qa-chip.minus { border-color: rgba(200,90,82,.35); }
.qa-chip.minus b { background: rgba(200,90,82,.14); color: var(--danger); }
.qa-chip.minus:hover { border-color: var(--danger); background: rgba(200,90,82,.07); }
.qa-chip.qa-empty {
  border: 1px dashed var(--line); background: transparent;
  color: var(--text-3); padding: 6px 13px;
}
.qa-edit-btn { padding: 2px 10px; font-size: 12px; }
/* 编辑态：行内表单（名称 + 分值 + 删行），从内联样式收编成类 */
.qa-edit-row { display: flex; gap: 6px; margin-top: 6px; }
.qa-edit-row input {
  flex: 1; min-width: 0; padding: 6px 10px; font: inherit;
  border: 1px solid var(--line); border-radius: 8px; background: #fff;
}
.qa-edit-row input[type="number"] { flex: 0 0 78px; }
.qa-edit-foot { margin-top: 8px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.live-box { display: flex; flex-direction: column; gap: 8px; }
.live-row {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  border-radius: 12px; border: 1px solid var(--line); background: #fff;
}
.live-row.live-doing { border-color: rgba(47,111,168,.35); background: rgba(47,111,168,.05); }
.live-row.live-paused { border-color: rgba(217,154,43,.35); background: rgba(217,154,43,.06); }
.live-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.live-content { font-weight: 600; }
.live-timer { font-size: 18px; min-width: 74px; }

/* ══════════════════════════════════════════════════════════════════
   孩子端（kid.html）—— 纯净模式：大字、大按钮、少步骤
   尺寸按平板触控设计（按钮 ≥ 48px 高），一屏内能完成「开始 → 完成」
   ══════════════════════════════════════════════════════════════════ */
.page-kid { background: linear-gradient(180deg, #f2f8ff, var(--bg) 320px); }
.kid-pts-top {
  font-weight: 700; color: var(--primary); background: rgba(47,111,168,.1);
  padding: 5px 12px; border-radius: 999px; font-size: 13px; font-variant-numeric: tabular-nums;
}
.kid-wrap { padding-top: 20px; }
.kid-foot { text-align: center; color: var(--text-3); font-size: 12px; margin: 18px 0 0; }

.page-kid .kid-hero { padding: 14px 16px; border-radius: 14px; margin-bottom: 14px; box-shadow: var(--shadow); }
.page-kid .kid-name { font-size: 19px; }
.page-kid .kid-meta { font-size: 13px; margin-top: 4px; }
.kid-progress { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
.kid-progress-bar { flex: 1; height: 8px; border-radius: 999px; background: rgba(255,255,255,.28); overflow: hidden; }
.kid-progress-bar i { display: block; height: 100%; border-radius: 999px; background: #ffd479; transition: width .35s ease; }
.kid-progress-text { font-size: 13px; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ── 任务卡片（2026-09-24 平板改版：卡片只管「看清 + 点选」）──────────────
   开始/暂停/完成按钮已移到专注面板，卡片上不再有操作排 —— 高度几乎减半，
   一眼能扫完今天有哪些事。紧凑靠三处：内边距、行距、以及去掉那个按钮排。 */
.kid-card {
  display: flex; align-items: flex-start; gap: 10px;
  border: 1.5px solid var(--line); border-left-width: 5px; border-left-color: var(--k-todo);
  border-radius: 12px; padding: 9px 11px; margin-bottom: 7px; background: #fff;
}
/* 正文列：科目 + 任务名 + 元信息 + （偶尔）交作业按钮 */
.kid-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
/* ⚠️ 每条状态规则里 border-color（四边）必须写在 border-left-color 之前 ——
   简写会把左边覆盖掉，色条就没了。 */
.kid-card-doing { border-color: #b7e3cb; border-left-color: var(--k-doing); background: #f1faf5; }
.kid-card-paused { border-left-color: var(--k-paused); }
.kid-card-review { border-color: #f6d3b4; border-left-color: var(--k-review); background: #fff8f2; }
.kid-card-finished { border-color: #e6e8ec; border-left-color: var(--k-done); background: #f5f6f7; }
.kid-card-finished .kid-content { text-decoration: line-through; text-decoration-thickness: 1.5px; color: var(--text-3); }
.kid-card-finished .subject { filter: grayscale(.85); opacity: .75; }
.kid-card-finished .pts-badge { background: #e9ebee; color: var(--text-3); }
.kid-card-finished .kid-done-tip { color: #2f7d4f; font-weight: 700; }

/* 状态胶囊：钉在卡片最右侧的**固定一列**。孩子扫的不是正文，是这一列 ——
   这也是它必须放在 flex 末尾、而不是混进 .kid-card-meta 那行灰字里的原因。 */
.kid-state {
  flex: none; align-self: flex-start; margin-top: 1px;
  display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
  padding: 3px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 800;
  background: var(--k-todo-bg); color: var(--k-todo); border: 1px solid var(--k-todo-line);
}
.kid-state-ico { width: 12px; height: 12px; flex: none; }
/* 「在跑」和「等家长」用实心底：这两个状态需要孩子立刻注意到 */
.kid-state-doing { background: var(--k-doing); color: #fff; border-color: var(--k-doing); }
.kid-state-paused { background: #eef1f5; color: #495468; border-color: #d9dee7; }
.kid-state-review { background: var(--k-review); color: #fff; border-color: var(--k-review); }
.kid-state-finished { background: #e9f6ee; color: #2f7d4f; border-color: #c3e6d3; }
/* 「这一条正在跑」用呼吸圈提示。幅度刻意小 —— 大了会把视线从正文上拽走 */
@keyframes kid-state-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(15,157,88,.45); }
  70% { box-shadow: 0 0 0 6px rgba(15,157,88,0); }
}
.kid-card-doing .kid-state { animation: kid-state-pulse 1.8s ease-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .kid-card-doing .kid-state { animation: none; }
}
/* 可点选：整张卡都是热区（点哪儿都行），指针与悬停要像按钮 */
.kid-card-pick { cursor: pointer; transition: border-color .15s, background .15s, box-shadow .15s; }
.kid-card-pick:hover { border-color: var(--primary-2); background: #fbfdff; }
/* 选中态必须写在 .kid-card-doing 之后：两者优先级相同，后出现的那条生效 */
.kid-card-sel { border-color: var(--primary); background: #f4f9ff; box-shadow: 0 0 0 3px rgba(37,99,235,.16); }
/* ⚠️ 状态色条必须**活过选中高亮**：`.kid-card-sel` 的 `border-color` 会把左边那条
   一起刷成主色（真浏览器实测成 rgb(28,58,94)），孩子点一下就把状态线索弄丢了。
   用**双类名**（优先级 0,2,0 > 0,1,0）而不是靠书写顺序 —— 顺序迟早被人挪乱。 */
.kid-card.kid-card-todo { border-left-color: var(--k-todo); }
.kid-card.kid-card-doing { border-left-color: var(--k-doing); }
.kid-card.kid-card-paused { border-left-color: var(--k-paused); }
.kid-card.kid-card-review { border-left-color: var(--k-review); }
.kid-card.kid-card-finished { border-left-color: var(--k-done); }
.kid-card-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.kid-card-head .subject { font-size: 11.5px; padding: 2px 8px; border-radius: 7px; }
.kid-content { font-size: 14.5px; font-weight: 700; line-height: 1.4; }
.kid-card-meta { font-size: 12px; color: var(--text-3); }
/* 任务卡分值徽标：让孩子一眼看到「做完能得几分」 */
.pts-badge {
  display: inline-block; margin-left: 5px; padding: 1px 7px; border-radius: 8px;
  background: rgba(217,154,43,.14); color: #a9761a; font-weight: 700; font-size: 11.5px;
}
/* 「📋 有要求」：要求本身在专注面板里用小字展示，卡片上只留一个记号，
   让孩子知道「这一条点开右边还有细节可看」 */
.kid-req-mark {
  display: inline-block; margin-left: 5px; padding: 1px 7px; border-radius: 8px;
  background: rgba(47,111,168,.1); color: var(--primary-2); font-weight: 700; font-size: 11.5px;
}
/* 「已完成 N 项」折叠行：做完的卡片收进它下面。
   2026-09-27 家长反馈「完成的和没完成的视觉上不明显，得一个个点开看」——
   光靠颜色只解决一半（做完的还占着同样大的位置），折起来才算真解决。 */
.kid-done-fold {
  display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
  margin-top: 2px; padding: 8px 11px;
  border: 1px dashed #d5dae2; border-radius: 10px; background: #f7f8fa;
  font: inherit; font-size: 12.5px; font-weight: 800; color: #6b7280;
  cursor: pointer; transition: background .15s, border-color .15s;
}
.kid-done-fold:hover { background: #f1f3f7; border-color: #b9c2cf; }
.kid-done-fold .kid-state-ico { color: #2f7d4f; width: 13px; height: 13px; }
/* 还欠着作业没交：折叠行也得喊出来，否则卡片一折孩子就忘了拍照片 */
.kid-fold-warn { color: var(--k-review); }
.kid-fold-caret { margin-left: auto; font-size: 11px; line-height: 1; transition: transform .18s; }
.kid-done-fold[aria-expanded="true"] .kid-fold-caret { transform: rotate(180deg); }
.kid-done-list { margin-top: 6px; }
.kid-done-list[hidden] { display: none; }

/* 「只看没做完」开关（看板标题右侧）。
   做成胶囊而不是裸复选框：孩子用手指点，17px 的方框太难命中；
   打开时整条变蓝，一眼知道「列表现在是被过滤过的」——否则他会以为
   「我做完的那些不见了」。 */
.kid-only-undone {
  display: inline-flex; align-items: center; gap: 7px; margin-left: auto; align-self: center;
  padding: 5px 13px 5px 8px; border-radius: 999px;
  border: 1.5px solid var(--line); background: #fff;
  font-size: 13px; font-weight: 700; color: var(--text-2);
  cursor: pointer; user-select: none; -webkit-user-select: none;
  transition: background .15s, border-color .15s, color .15s;
}
.kid-only-undone:hover { border-color: var(--k-todo-line); }
.kid-only-undone input { width: 18px; height: 18px; margin: 0; accent-color: var(--k-todo); cursor: pointer; }
.kid-only-undone:has(input:checked) { background: var(--k-todo-bg); border-color: var(--k-todo-line); color: var(--k-todo); }
/* ⚠️ 必须显式写 [hidden]：上面的 display:inline-flex 会把 UA 默认的
   `[hidden]{display:none}` 压过去，标签藏不起来 */
.kid-only-undone[hidden] { display: none; }
.page-kid .chip { font-size: 12px; padding: 3px 10px; }
.kid-card-action { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 2px; }

.kid-btn {
  min-height: 40px; padding: 8px 18px; border-radius: 10px; border: 2px solid transparent;
  font: inherit; font-size: 14.5px; font-weight: 700; cursor: pointer; transition: .15s;
}
.kid-btn:hover { filter: brightness(1.05); }
.kid-btn:disabled { opacity: .5; cursor: not-allowed; }
.kid-btn:active { transform: scale(.97); }
.kid-btn-primary { background: linear-gradient(135deg, var(--primary), var(--primary-2)); color: #fff; }
.kid-btn-ok { background: rgba(47,158,111,.14); color: var(--ok); border-color: rgba(47,158,111,.3); }
.kid-btn-warn { background: rgba(217,154,43,.16); color: #a9761a; border-color: rgba(217,154,43,.32); }

/* ── 专注面板（孩子端 2026-09-24）───────────────────────────────────────
   平板横屏：右栏的大圆环倒计时（家长给的参考图那套）。手机：一进页面顶部那一块。
   DOM 里它排在任务看板**之前** —— 手机端 DOM 顺序就是显示顺序，专注面板必须在
   上面；平板端靠 grid 把它挪到第 2 列（见下方 768px 媒体查询）。
   圆环用 SVG 的 stroke-dashoffset 驱动，比 conic-gradient 在旧 WebView 上稳。 */
.kid-focus {
  margin-bottom: 14px; padding: 14px 16px 12px;
  border: 1.5px solid var(--line); border-radius: 16px; background: #fff;
  box-shadow: var(--shadow);
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.kf-top { display: flex; align-items: center; gap: 10px; width: 100%; }
.kf-seg {
  display: inline-flex; padding: 2px; border-radius: 10px;
  background: var(--panel-2); border: 1px solid var(--line);
}
.kf-seg-btn {
  border: 0; background: transparent; color: var(--text-3); font: inherit;
  font-size: 12.5px; font-weight: 700; padding: 5px 12px; border-radius: 8px; cursor: pointer;
}
.kf-seg-btn.on { background: #fff; color: var(--primary); box-shadow: 0 1px 3px rgba(20,40,70,.12); }
.kf-hint { margin-left: auto; font-size: 12px; color: var(--text-3); }

.kf-task {
  font-size: 16px; font-weight: 700; line-height: 1.4; text-align: center;
  color: var(--text); padding: 0 4px;
}

/* 任务要求（家长下发的备注 + 星级标准）—— 位置在任务名与圆环之间（家长建议）。
   小字、左对齐：要求常常是两三条短句，居中会读成一片糊。 */
.kf-req { width: 100%; max-width: 430px; }
.kf-req-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.kf-req-list li {
  position: relative; padding-left: 14px; text-align: left;
  font-size: 12.5px; line-height: 1.6; color: var(--text-2);
}
.kf-req-list li::before {
  content: ''; position: absolute; left: 4px; top: .62em;
  width: 4px; height: 4px; border-radius: 999px; background: var(--primary-2); opacity: .55;
}

/* 圆环与中间的大字重叠：grid 同一格里叠加，比 absolute + 负 margin 稳 */
.kf-ring-wrap { display: grid; place-items: center; }
.kf-ring, .kf-clock { grid-area: 1 / 1; }
.kf-ring { width: 148px; height: 148px; display: block; }
.kf-ring-bg { fill: none; stroke: #edf0f6; stroke-width: 11; }
.kf-ring-fg {
  fill: none; stroke: var(--primary-2); stroke-width: 11; stroke-linecap: round;
  transition: stroke-dashoffset .45s linear, stroke .25s;
}
.kf-ring-fg.over { stroke: #d99a2b; }   /* 超过预计时间：环走满并转琥珀色 */
.kf-clock {
  font-size: 32px; font-weight: 800; color: var(--text);
  font-variant-numeric: tabular-nums; letter-spacing: -.5px; text-align: center;
}
.kf-sub { font-size: 12.5px; color: var(--text-3); text-align: center; }
.kf-actions { display: flex; gap: 10px; width: 100%; }
.kf-actions:empty { display: none; }    /* 今天的任务都做完时，不留两条空行 */
.kf-actions .kid-btn { flex: 1; min-height: 48px; font-size: 16px; }

.kf-points {
  width: 100%; margin-top: 4px; padding: 10px 0 0; border: 0; border-top: 1px solid var(--line);
  background: transparent; font: inherit; font-size: 13px; font-weight: 700;
  color: var(--text-2); cursor: pointer;
  display: flex; align-items: center; justify-content: space-between;
}
.kf-arrow { color: var(--text-3); font-size: 17px; line-height: 1; }

/* 手机上专注面板在页面最顶，已经承担了「先做哪项 + 开始」这件事；
   提醒条再给一个同样的「▶ 开始做」就是两个按钮干同一件事（而且相隔不到一屏），
   去掉下面那个。平板端不冲突（两边隔得远），保留。 */
@media (max-width: 767px) {
  .kid-brief #kidBriefStart { display: none; }
}

/* ── 今日提醒条（孩子端 2026-09-24）─────────────────────────────────────
   打开页面就用一句话说清「今天几项、先做哪项」。全部做完后整条转成绿色，
   孩子不用再去数下面的卡片。 */
.kid-brief {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px; margin-bottom: 14px; border-radius: 14px;
  background: #fff8e8; border: 1.5px solid #f2e0b6;
}
.kid-brief-done { background: rgba(47, 158, 111, .1); border-color: rgba(47, 158, 111, .28); }
.kid-brief-text { flex: 1; min-width: 210px; display: flex; flex-direction: column; gap: 4px; }
.kid-brief-text b { font-size: 16.5px; color: #8a6420; }
.kid-brief-done .kid-brief-text b { color: var(--ok); }
.kid-brief-text .meta-inline { font-size: 13px; color: var(--text-2); }
.kid-brief-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ── 休息提醒条（连续专注到点后出现）─────────────────────────────────── */
.kid-rest {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px; margin-bottom: 14px; border-radius: 14px;
  background: linear-gradient(135deg, #e8f4ff, #f5faff);
  border: 1.5px solid #bcdcf5;
}
.kid-rest-icon { font-size: 26px; }
.kid-rest-text { flex: 1; min-width: 190px; display: flex; flex-direction: column; gap: 3px; }
.kid-rest-text b { font-size: 16.5px; color: var(--primary); }
.kid-rest-text .meta-inline { font-size: 13px; color: var(--text-2); }
.kid-rest-clock {
  font-size: 24px; font-weight: 800; color: var(--primary-2);
  font-variant-numeric: tabular-nums; min-width: 74px; text-align: center;
}

.kid-timer {
  font-size: 20px; font-weight: 800; color: var(--primary-2);
  font-variant-numeric: tabular-nums; min-width: 78px;
}
.kid-timer-paused { color: #a9761a; }
.kid-done-tip { font-size: 14.5px; font-weight: 600; color: var(--text-3); }
.bind-lead { margin: 0 0 12px; font-size: 13.5px; color: var(--text-2); }

/* ══════════════════════════════════════════════════════════════════
   移动端适配
   家长端主场景是**手机**（家长在群里看到消息后随手粘贴），
   孩子端主场景是**平板**。早期只在桌面上看过，顶栏按钮和识别预览行
   在 375px 宽度下会横向溢出 —— 下面是针对这两个真实场景的适配。
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 720px) {
  .topbar { padding: 12px 14px; gap: 10px; flex-wrap: wrap; }
  .topbar-actions { flex-wrap: wrap; gap: 6px; width: 100%; }
  .brand { min-width: 0; }
  .topbar h1 { font-size: 15.5px; }
  .topbar h1 em { display: none; }          /* 小屏省掉「· 家长端」后缀，标题不换行 */
  .logo { width: 34px; height: 34px; font-size: 17px; border-radius: 9px; }
  .single { padding: 14px 12px 44px; }
  .card { padding: 12px; border-radius: 12px; }
  /* 识别预览行在手机上必须换行，否则「科目 + 内容 + 时长」会挤出屏幕 */
  .pv-row { flex-wrap: wrap; }
  .pv-row select { flex: 1 1 96px; }
  .pv-row input { flex: 1 1 100%; }
  .pv-row input.min { flex: 1 1 96px; }
  .task { align-items: flex-start; }
  .task-actions { flex-direction: column; }
  .kpi b { font-size: 18px; }
  .row { gap: 6px; }
  .row .btn { flex: 1 1 auto; }
  .row select { flex: 1 1 100%; }
  .entry-grid { grid-template-columns: 1fr; }
}

/* 手机竖屏：孩子端也可能被家长临时用手机查看，字号略放大但不夸张 */
@media (max-width: 480px) {
  .kid-content { font-size: 16px; }
  .kid-timer { font-size: 20px; min-width: 78px; }
  .kid-btn { min-height: 44px; padding: 9px 20px; font-size: 15px; }
  .page-kid .kid-name { font-size: 19px; }
  .kid-card { padding: 12px; }
}

/* 识别结果预览：给每条加序号，家长核对时能对上「原文第几条」 */
.pv-idx {
  flex: 0 0 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: var(--panel-2); color: var(--text-2); font-size: 11.5px; font-weight: 700;
}
/* 通知区：与「作业」视觉上区分开，家长一眼知道这条不会发给孩子 */
.warn b { display: block; margin-bottom: 4px; }
.notice-list { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
.notice-list > div { line-height: 1.6; }

/* ══════════════════════════════════════════════════════════════════
   登录（手机号 + 验证码）与 ⑥ 会员额度
   ══════════════════════════════════════════════════════════════════ */
.row-code { align-items: stretch; }
.row-code input { flex: 1 1 auto; }
.row-code .btn { flex: 0 0 auto; white-space: nowrap; }
#loginFoot a { color: var(--primary-2); text-decoration: none; font-weight: 600; }
#loginFoot a:hover { text-decoration: underline; }

.member-box { display: flex; flex-direction: column; gap: 12px; }
.member-status { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.plan-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 560px) { .plan-grid { grid-template-columns: 1fr; } }
.plan-card {
  border: 1px solid var(--line); border-radius: 12px; padding: 12px;
  display: flex; flex-direction: column; gap: 6px; background: var(--panel-2);
}
.plan-name { font-size: 13px; font-weight: 700; }
.plan-price { font-size: 20px; font-weight: 800; color: var(--primary); font-variant-numeric: tabular-nums; }
.plan-unit { font-size: 12px; font-weight: 500; color: var(--text-3); }
.plan-hint { font-size: 11.5px; color: var(--text-3); min-height: 16px; }
.plan-card .btn { margin-top: auto; }


/* ── 常态化任务（家长端 ⑦）────────────────────────────────────────────── */
.routine-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.routine-row { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border: 1px solid var(--line, #e5e8ef); border-radius: 10px; background: #fff; }
.routine-row.off { opacity: .55; }
.routine-main { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.routine-main b { font-size: 13.5px; }
.wd-row { display: flex; gap: 4px; flex-wrap: wrap; }
.wd-chip { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; padding: 3px 6px; border: 1px solid #e5e8ef; border-radius: 8px; cursor: pointer; user-select: none; }
.wd-chip input { width: auto; margin: 0; }

/* ── 积分商城 / 奖励卡（家长端 ⑧ + 孩子端共用）────────────────────────── */
.reward-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(185px, 1fr)); gap: 8px; margin-top: 8px; }
.reward-card { display: flex; flex-direction: column; gap: 5px; padding: 10px; border: 1px solid #e5e8ef; border-radius: 12px; background: #fff; }
.reward-card.off { opacity: .55; }
.reward-emoji { font-size: 30px; line-height: 1; }
.reward-img { width: 100%; height: 76px; object-fit: cover; border-radius: 8px; background: #f3f5f9; }
.reward-info { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.reward-info b { font-size: 13.5px; }
/* 「可选」小标：贴在标题后面，明确告诉家长这一步不做也没关系（邀请家人最容易
   被误读成「必须做」—— 第一屏出现过一次就会让人以为不邀请就用不了） */
.tag-optional {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  font-size: 11px; font-weight: 500; color: #6b7688;
  background: #f0f2f7; border-radius: 999px; vertical-align: middle;
}
/* 行内编辑器：占满整行再放四个输入框（挤在 185px 的格子里没法用）。
   网格子项默认只占一格，所以要显式跨列。 */
.reward-card.editing { grid-column: 1 / -1; border-color: #bfd3ff; background: #f8fbff; }
.reward-card.editing input {
  width: 100%; padding: 6px 8px; font-size: 13px; border: 1px solid #dfe4ee;
  border-radius: 8px; background: #fff; box-sizing: border-box;
}
/* 「这个链接不是图片地址」的提示 —— 用暖色但别和「错误」抢眼 */
.warn-inline { color: #b26a00; }
.reward-ops { display: flex; gap: 6px; flex-wrap: wrap; }
.redemption-row { align-items: center; }

/* ── 孩子端：多孩分区 / 顶栏积分 / 兑换胶囊 ─────────────────────────────── */
.kid-sec { border: 1px solid #e5e8ef; border-radius: 14px; padding: 12px; margin-bottom: 12px; background: #fff; }
.kid-sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.kid-sec-name { font-size: 17px; font-weight: 800; color: var(--primary, #2563eb); }
.kid-sec-pts { font-size: 14px; font-weight: 800; color: #b45309; font-variant-numeric: tabular-nums; }
.kid-sec-progress { font-size: 12px; color: var(--text-3, #8a8f9c); margin-left: auto; }
.kid-sec-bar { height: 8px; border-radius: 4px; background: #edf0f6; overflow: hidden; margin-bottom: 10px; }
.kid-sec-bar i { display: block; height: 100%; background: var(--primary, #2563eb); border-radius: 4px; transition: width .3s; }
.kid-pts-top { font-size: 15px; font-weight: 800; color: #b45309; background: #fdf3e0; border: 1px solid #f3ddb0; border-radius: 999px; padding: 4px 12px; white-space: nowrap; }
.pts-chip { font-size: 13px; font-weight: 800; color: #b45309; background: #fdf3e0; border: 1px solid #f3ddb0; border-radius: 999px; padding: 3px 10px; margin-left: 6px; }
.kid-chip { border: 1.5px solid #d7dce6; background: #fff; color: var(--text-2, #444); border-radius: 999px; padding: 5px 14px; font-size: 13.5px; font-weight: 700; cursor: pointer; }
.kid-chip.on { border-color: var(--primary, #2563eb); color: var(--primary, #2563eb); background: rgba(37,99,235,.06); }
.kid-btn-ghost { border: 1.5px dashed #d7dce6; background: #f7f8fb; color: var(--text-3, #8a8f9c); }

/* ── 「交作业」抽屉（孩子端提交作答 → 家长批改）────────────────────────
   从底部升起而不是跳页：孩子端一屏一事，跳页会丢掉正在做的任务进度。 */
.sheet-mask {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(24, 46, 74, .38);
  display: none; align-items: flex-end; justify-content: center;
}
.sheet-mask.on { display: flex; }
.sheet {
  width: 100%; max-width: 560px;
  background: var(--panel); border-radius: 18px 18px 0 0;
  padding: 20px 20px 26px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 10px;
}
.sheet h3 { margin: 0; font-size: 17px; }
.sheet textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  font: inherit; resize: vertical; background: var(--panel-2); color: var(--text);
}
.sheet-actions { display: flex; gap: 10px; }
.sheet-actions .kid-btn { flex: 1; }

/* 积分 / 奖励抽屉（点专注面板底部那条打开）—— 内容比「交作业」抽屉长得多，
   所以标题行钉住、中间自己滚，别把整个页面撑成一屏滚不完 */
.sheet-tall { max-width: 680px; max-height: 86vh; padding: 18px 20px 22px; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sheet-head h3 { margin: 0; font-size: 17px; }
.sheet-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 18px;
}
.sheet-sec { display: flex; flex-direction: column; gap: 6px; }

/* ── Pad 横屏适配（≥768px：双栏仪表台）────────────────────────────────── */
@media (min-width: 768px) {
  .page-kid main.single { max-width: 1180px; }
  .kid-wrap {
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    align-items: start;
    gap: 16px;
  }
  /* 卡片都包在 #kidBody 里：让它在宽屏「透明化」，栏容器与专注面板直接成为 grid 项
     （必须 :not(.hidden)——ID 选择器优先级高，否则会盖过 .hidden 的 display:none） */
  .kid-wrap > #kidBody:not(.hidden) { display: contents; }
  .kid-wrap > #bindCard:not(.hidden) { grid-column: 1 / -1; }
  /* 左栏任务清单、右栏专注面板。
     两块都显式写 grid-row:1 —— 专注面板在 DOM 里排在前面（手机端需要它靠前），
     只指定 grid-column 的话自动放置会把它排到第二行去。 */
  .kid-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
  .kid-col > .card { margin-bottom: 0; }   /* 间距交给 gap，避免与 margin 叠加 */
  .kid-col-l { grid-column: 1; grid-row: 1; }
  /* sticky：左栏任务一多就很长（实测 7 张卡 = 1450px+），不吸附的话孩子往下一滚
     右栏就是一大片空白，圆环和「暂停 / 任务完成」也跟着走没了。
     align-self: start 是必须的 —— 否则 grid item 会被拉伸到整行高，sticky 无处可动。
     top 用变量而不是 16px：页面顶栏也是吸顶的（.topbar 有 position:sticky），
     写 16px 的话面板滚上去会被顶栏压住一截。 */
  .kid-focus {
    grid-column: 2; grid-row: 1; align-self: start;
    position: sticky; top: var(--kid-focus-top);
    margin-bottom: 0; padding: 18px 20px 14px;
  }
  .page-kid .kid-hero { margin: 0; }
  .page-kid .kid-foot { grid-column: 1 / -1; }
  /* 平板触控：按钮略大但不夸张。卡片保持紧凑 —— 左栏要尽量一屏看完今天的量 */
  .kid-card { padding: 10px 13px; gap: 12px; }
  .kid-content { font-size: 15px; }
  .kid-card-meta { font-size: 12.5px; }
  /* 孩子坐在半米外看：状态胶囊是这一屏最该看清的东西，放大一档 */
  .kid-state { font-size: 13px; padding: 4px 10px; }
  .kid-state-ico { width: 13px; height: 13px; }
  .kid-done-fold { font-size: 13px; }
  .kid-group-left { font-size: 12.5px; }
  .kid-btn { min-height: 42px; font-size: 15px; }
  .kid-sec-name { font-size: 16px; }
  /* 孩子坐在半米外看，要求小字要比手机上大一档才读得清 */
  .kf-req { max-width: 100%; }
  .kf-req-list li { font-size: 13.5px; }

  /* 右栏唯一的主角是圆环：放大到不用凑近也能看清（孩子坐在半米外） */
  .kf-ring { width: 236px; height: 236px; }
  .kf-clock { font-size: 48px; }
  .kf-task { font-size: 19px; }
  .kf-sub { font-size: 13px; }
  .kf-actions .kid-btn { min-height: 54px; font-size: 17px; }
}

/* ── ⑨ 完成日历（家长端）────────────────────────────────────────────── */
.cal-head { display: flex; align-items: center; gap: 10px; margin: 10px 0 6px; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-wd { text-align: center; font-size: 11.5px; color: var(--text-3); padding: 2px 0; }
.cal-cell {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 5px 2px; border: 1px solid transparent; border-radius: 8px; background: var(--panel-2);
  cursor: pointer; font: inherit;
}
.cal-cell:hover { border-color: var(--primary-2); }
.cal-blank { background: transparent; cursor: default; }
.cal-blank:hover { border-color: transparent; }
.cal-day { font-size: 13px; font-weight: 700; line-height: 1.2; }
.cal-ratio { font-size: 10.5px; font-weight: 700; color: var(--text-2); font-variant-numeric: tabular-nums; }
.cal-full { background: rgba(47,158,111,.16); }
.cal-part { background: rgba(217,154,43,.18); }
.cal-miss { background: rgba(217,69,69,.13); }
.cal-today .cal-day { color: var(--primary); }
.cal-sel { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(37,99,235,.15); }
.cal-detail { margin-top: 10px; border-top: 1px dashed var(--line); padding-top: 8px; }
.cal-detail-title { font-size: 13px; font-weight: 800; margin-bottom: 6px; }
.cal-task { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 9px; margin-bottom: 5px; background: #fff; }
.cal-task-content { flex: 1; font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ext-pending { border: 1px solid #f3ddb0; background: #fdf6e8; border-radius: 10px; padding: 8px 10px; margin-bottom: 8px; }
.ext-pending-title { font-size: 13px; font-weight: 800; color: #8a6420; margin-bottom: 6px; }
/* 家长端主视图顶部的「待处理」提示条（延期申请等）。配色沿用上面 .ext-pending，
   让家长一眼认出「跟日历里那条申请是同一件事」。 */
.home-alert {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 14px; padding: 12px 14px;
  border: 1px solid #f3ddb0; border-left: 4px solid var(--warn); background: #fdf6e8;
  border-radius: 12px;
}
.home-alert-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.home-alert-main b { font-size: 14px; color: #8a6420; }
.home-alert-sub { font-size: 12px; color: #8a6420; opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 新家长「开始使用」清单：三步，全做完整卡消失 */
.start-guide {
  margin-bottom: 14px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--panel);
}
.start-guide-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.start-step { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.start-step + .start-step { border-top: 1px dashed var(--line-soft); }
.start-tick { flex: none; width: 18px; text-align: center; font-weight: 800; color: var(--text-3, #93a1b5); }
.start-step.done .start-tick { color: #2ea36d; }
.start-step-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.start-step.done .start-step-body b { color: var(--text-3, #93a1b5); text-decoration: line-through; }

/* 孩子端延期标记 */
/* 逾期卡：虚线边框表示「这不是今天的」，但**左边色条要保持实线**，
   否则状态色这一列在逾期卡上就断了 */
.kid-card-overdue { border-style: dashed; border-left-style: solid; background: #fffdf7; }
.ext-date { color: #a9761a; font-weight: 700; }
.ext-badge { font-size: 13px; font-weight: 700; color: #8a6420; background: #fdf3e0; border: 1px solid #f3ddb0; border-radius: 8px; padding: 4px 10px; }

/* 总管理员页 */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; margin: 12px 0; }
.stat-card { background: var(--panel-2, #f4f7fb); border: 1px solid var(--line, #e5eaf2); border-radius: 12px; padding: 12px 10px; text-align: center; }
.stat-num { font-size: 24px; font-weight: 800; color: var(--text-1, #1c2b41); }
.stat-label { font-size: 12px; color: var(--text-2, #5b6b82); margin-top: 2px; }
.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.data-table th { text-align: left; font-size: 12px; color: var(--text-2, #5b6b82); font-weight: 600; padding: 8px 10px; border-bottom: 1px solid var(--line, #e5eaf2); white-space: nowrap; }
.data-table td { padding: 9px 10px; border-bottom: 1px solid var(--line-soft, #eef2f8); vertical-align: top; }
.data-table tr:last-child td { border-bottom: none; }
/* 管理后台家庭列表：无家长的孤儿家庭标记 + 单元格次要说明（如家庭原名） */
.cell-sub { margin-top: 2px; font-size: 11px; color: var(--text-2, #5b6b82); }

/* ── 家长端二级导航（低频功能入口）────────────────────────── */
.subnav {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 12px; margin-bottom: 14px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
}
.subnav-btn {
  appearance: none; cursor: pointer;
  padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel-2);
  color: var(--text-2); font-size: 13px; line-height: 1.4;
  transition: background .15s, color .15s, border-color .15s;
}
.subnav-btn:hover { border-color: var(--primary-2); color: var(--text); }
.subnav-btn.active {
  background: var(--primary); border-color: var(--primary);
  color: #fff; font-weight: 600;
}
@media (max-width: 640px) {
  .subnav { gap: 6px; padding: 8px; }
  .subnav-btn { padding: 6px 10px; font-size: 12px; }
}

/* ── 站点页脚（备案号）────────────────────────────────────────────────────
   工信部要求网站在页面底部标注备案号并链接到 https://beian.miit.gov.cn ——
   这是**法定义务**，四个页面统一挂同一段。<footer class="site-foot"> 的文案
   与 web/scripts 下的静态守卫一致，改这里要一起改（见 check-web.js）。

   ⚠️ 必须放在 </main> **之外**（body 的直接子元素）：
   孩子端 .kid-wrap 在平板下是 grid（左任务/右专注两栏），页脚塞进去会被自动
   放置当成第三列 —— 0 报错 0 警告，只有真浏览器看得见。
   宽度与内边距按页面类型对齐主容器，否则页脚会比正文宽出一截很难看。 */
.site-foot {
  max-width: 760px; margin: 0 auto; padding: 0 28px 34px;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 2px 8px; text-align: center;
  color: var(--text-3); font-size: 12px; line-height: 1.7;
}
.page-kid .site-foot { max-width: 920px; }
.page-home .site-foot { max-width: 1040px; }
@media (max-width: 980px) { .site-foot { padding: 0 14px 26px; } }
.site-foot a { color: var(--text-2); text-decoration: none; }
.site-foot a:hover { color: var(--primary); text-decoration: underline; }
.site-foot a:focus-visible { outline: 2px solid var(--primary-2); outline-offset: 2px; border-radius: 4px; }
.site-foot-sep { color: var(--line); }

/* ══════════════════════════════════════════════════════════════════
   总管理员后台 · 「家庭为中心」的管理台（2026-09-29 重做）
   目标：一个家庭 = 一个可展开的管理单元，账号挂在家庭里面。
   旧版是两张平表（家庭 / 账号），建孩子账号要先抄家庭ID、孩子ID 再去另一张表粘。
   ══════════════════════════════════════════════════════════════════ */
.admin-wide { max-width: 1080px; }   /* 家庭卡要横着放三列，760px 放不下 */

.fam-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.fam-tools input,
.fam-tools select {
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel); color: var(--text); font-size: 13px; font-family: inherit;
}
.fam-tools input { flex: 1 1 200px; min-width: 160px; }
/* 排序下拉必须给死宽度：`select` 在 flex 行里换行到独占一行时会撑满整行，
   渲染出一个横贯卡片的下拉框，看着像布局坏了。 */
.fam-tools select { flex: 0 0 auto; width: 140px; }
.fam-tools input:focus, .fam-tools select:focus { outline: 2px solid rgba(47,111,168,.2); border-color: var(--primary-2); }
.fam-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.fam-chip {
  border: 1px solid var(--line); background: var(--panel); color: var(--text-2);
  border-radius: 999px; padding: 4px 12px; font-size: 12px; cursor: pointer; font-family: inherit;
}
.fam-chip:hover { border-color: var(--primary-2); color: var(--primary-2); }
.fam-chip.on { background: var(--primary-2); border-color: var(--primary-2); color: #fff; }

/* 空壳提示条：只在真有可回收的残壳时出现 */
.clean-banner {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: #fdf6e9; border: 1px solid #f0dcb4; border-radius: 12px;
  padding: 9px 12px; margin-bottom: 10px;
}
.clean-banner-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 260px; }
.clean-banner-main b { font-size: 13px; color: #8a6420; }

/* 账号命中（搜账号时给直接入口）*/
.acct-hits { background: var(--panel-2); border: 1px solid var(--line); border-radius: 12px; padding: 8px 12px; margin-bottom: 10px; }
.acct-hits-title { font-size: 12px; font-weight: 600; color: var(--text-2); margin-bottom: 4px; }

/* 家庭卡 */
.fam-list { display: flex; flex-direction: column; gap: 8px; }
.fam-card {
  border: 1px solid var(--line); border-radius: 12px; background: var(--panel);
  overflow: hidden; transition: border-color .15s;
}
.fam-card.is-orphan { border-color: #f0dcb4; }
.fam-card.is-shell { background: #fefbf5; }
.fam-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; cursor: pointer;
}
.fam-head:hover { background: var(--panel-2); }
.fam-caret { color: var(--text-3); font-size: 11px; width: 10px; }
.fam-name { font-size: 13.5px; }
.fam-sub {
  font-size: 12px; color: var(--text-2); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fam-meta { margin-left: auto; font-size: 12px; color: var(--text-3); white-space: nowrap; }
.fam-state { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; background: rgba(47,158,111,.12); color: var(--ok); white-space: nowrap; }
.fam-state.orphan, .fam-state.shell { background: rgba(217,154,43,.14); color: #8a6420; }
/* 状态只说一次：名字旁不再挂「无家长 / 空壳」小标签，视觉区分交给卡片本身的
   `.is-orphan`（琥珀描边）/ `.is-shell`（暖底）两个类（见上面的 .fam-card 规则）。 */

/* 展开区：家长 / 孩子 / 数据 三列 */
.fam-body { border-top: 1px dashed var(--line); padding: 12px; }
.fam-cols { display: grid; grid-template-columns: 1fr 1fr .9fr; gap: 16px; }
.fam-col-title { font-size: 12px; font-weight: 600; color: var(--text-2); margin-bottom: 6px; }
.acct-row { display: flex; align-items: center; gap: 8px; padding: 5px 0; }
.acct-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.acct-main b { font-size: 12.5px; }
.acct-ops { margin-left: auto; display: flex; gap: 6px; flex-shrink: 0; }
.kv { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; padding: 3px 0; }
.kv span { color: var(--text-2); }
.kv b { font-weight: 600; }

/* 家庭内建号：表单长在卡片里，家庭ID / 孩子ID 由上下文带过去 */
.inline-form { margin-top: 10px; padding: 10px 12px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px; }
.inline-title { font-size: 12.5px; font-weight: 600; margin-bottom: 8px; }
.inline-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
.inline-fields input, .inline-fields select {
  padding: 7px 9px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); color: var(--text); font-size: 12.5px; font-family: inherit;
}
.inline-ops { display: flex; gap: 8px; margin-top: 8px; }

.fam-ops { display: flex; align-items: center; gap: 10px; margin-top: 12px; padding-top: 9px; border-top: 1px solid var(--line); }
.fam-danger { margin-left: auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.fam-empty { padding: 22px; text-align: center; font-size: 13px; color: var(--text-3); }
.danger-box > summary { color: var(--danger); }
.danger-box > summary::before { content: '⚠ '; }

@media (max-width: 860px) {
  .fam-cols { grid-template-columns: 1fr; gap: 12px; }
  .fam-meta { margin-left: 0; width: 100%; }
}

/* ── 隐私政策确认弹窗（首启 / 政策版本变更时出现）───────────────────────────
   审核依据：华为应用市场《审核指南》第 7.5 项 —— 首次启动须明确提示用户阅读隐私政策。
   位置放在文件末尾而非随某组件写：它是独立于任何页面的全局遮罩层。
   为什么不写进各页面的 <style>：三页共用且要跨版本保持逐字一致，单独一段便于校对。 */
.pv-mask {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(17, 27, 44, .55);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.pv-box {
  background: #fff; border-radius: 14px; padding: 26px 28px;
  max-width: 460px; width: 100%;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .22);
}
.pv-box h2 { margin: 0 0 12px; font-size: 17px; color: var(--primary); }
.pv-lead { margin: 0 0 10px; font-size: 13.5px; line-height: 1.75; color: var(--text-2); }
.pv-warn {
  margin: 10px 0 0; padding: 9px 12px;
  background: #fdeeee; border-radius: 8px;
  font-size: 12.5px; line-height: 1.7; color: var(--danger);
}
.pv-links { list-style: none; margin: 14px 0 16px; padding: 0; }
.pv-links li { margin: 6px 0; }
.pv-links a { color: var(--primary-2); font-size: 13.5px; text-decoration: underline; }
.pv-check {
  display: flex; gap: 9px; align-items: flex-start;
  margin: 4px 0 16px; padding: 11px 13px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  font-size: 12.5px; line-height: 1.7; color: var(--text-2);
}
.pv-check input { margin: 3px 0 0; flex: 0 0 auto; width: 15px; height: 15px; }
.pv-btn {
  display: block; width: 100%; margin-top: 8px;
  padding: 11px 14px; border-radius: 10px;
  font-size: 14px; font-family: inherit; cursor: pointer;
}
.pv-primary { background: var(--primary); color: #fff; border: 1px solid var(--primary); }
.pv-ghost { background: transparent; color: var(--text-2); border: 1px solid var(--line); }
.pv-primary:disabled { opacity: .45; cursor: not-allowed; }
.pv-ghost:disabled { opacity: .45; cursor: not-allowed; }

/* 举报与投诉入口（未成年人保护要求，见 children-privacy.html §六） */
.report-card .report-channels { list-style: none; margin: 10px 0 0; padding: 0; }
.report-card .report-channels li { margin: 6px 0; font-size: 12.5px; color: var(--text-2); line-height: 1.7; }
.report-card .report-channels a { color: var(--primary-2); text-decoration: underline; }

/* 登录卡内的隐私政策提示（华为审核第 7.5 项要求「注册登录界面」也要明示） */
/* 登录页隐私同意复选框（2026-10-23 华为驳回整改）。
   驳回要求「提供空白复选框且由用户自愿、明确勾选」——
   原来的「登录即表示…」是默示同意，已删除。
   🔴 复选框必须 width:auto + flex:none：全局 `input { width:100% }` 会把它撑满整行。 */
.login-consent {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 0 14px; padding: 10px 12px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  font-size: 12px; line-height: 1.8; color: var(--text-2);
  cursor: pointer;
}
.login-consent input[type="checkbox"] {
  flex: none; margin: 4px 0 0;
  width: 16px; height: 16px; accent-color: var(--primary-2);
  cursor: pointer;
}
.login-consent span { flex: 1 1 auto; min-width: 0; }
.login-consent a { color: var(--primary-2); text-decoration: underline; }
.login-consent b { color: var(--text); }
/* 复选框未勾选时，按钮呈禁用观感（真实 disabled 由 JS 控制） */
.btn-block:disabled { opacity: .5; cursor: not-allowed; }

/* ═══════════════════════════════════════════════════════════════════
   数学出题器 · 控制面板 + 试卷预览 + 打印
   ═══════════════════════════════════════════════════════════════════ */

.qz-wrap { display: grid; grid-template-columns: 360px 1fr; gap: 16px; align-items: start; }
@media (max-width: 900px) { .qz-wrap { grid-template-columns: 1fr; } }

.qz-label { font-size: 13px; color: var(--text-2); flex: none; }
.qz-grades { display: flex; gap: 6px; flex-wrap: wrap; }
.qz-grade {
  min-width: 38px; height: 32px; padding: 0 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--panel); color: var(--text);
  font-size: 14px; cursor: pointer;
}
.qz-grade.on { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600; }
.qz-check { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; color: var(--text-2); white-space: nowrap; }
/* 同 .qz-sec：全局 input{width:100%} 会把勾选框撑满并挤掉旁边的文字 */
.qz-check > input[type="checkbox"] {
  width: auto; flex: none; padding: 0; margin: 0; border: none; background: none;
}

.qz-sections { display: flex; flex-direction: column; gap: 6px; }
.qz-sec {
  display: flex; align-items: center; gap: 8px; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
  font-size: 13px; cursor: pointer;
}
/* 🔴 必须显式复位 checkbox 的宽度：项目全局有 `input, select, textarea { width:100% }`，
   会把勾选框撑成和面板同宽，把板块名挤成 0 宽竖排成一列（截图里非常明显）。
   .qz-sec 里的 input 只可能是 checkbox/radio，统一复位成内容大小。 */
.qz-sec > input[type="checkbox"],
.qz-sec > input[type="radio"] {
  width: auto; flex: none; padding: 0; margin: 0;
  border: none; background: none; border-radius: 0;
}
.qz-sec.off { opacity: .5; }
/* 🔴 min-width:0 不能省：flex 子项默认 min-width:auto，会被「不换行的最长词」撑开，
   这里的表现是板块名被挤成 13px 宽、逐字竖排（截图里非常明显）。
   加了它才会正常占满剩余空间并正常折行。 */
.qz-sec-name { flex: 1; min-width: 0; line-height: 1.5; word-break: break-word; }
.qz-sec-n { color: var(--text-2); font-size: 12px; flex: none; white-space: nowrap; }
.qz-num {
  width: 56px; flex: none; padding: 3px 6px;
  border: 1px solid var(--line); border-radius: 6px; font-size: 12px; text-align: center;
}

.qz-tip { margin: 10px 0 0; font-size: 12px; color: var(--text-2); line-height: 1.7; }
.qz-stat { margin-top: 8px; font-size: 12.5px; color: var(--text-2); }
.qz-stat b { color: var(--primary); font-size: 14px; }

/* ── 试卷本体（屏幕上也要能看清，所以用真实 mm 尺寸 + 阴影）────────────── */
.qz-sheet {
  width: 210mm; max-width: 100%; margin: 0 auto; padding: 12mm;
  background: #fff; color: #111; box-shadow: 0 2px 14px rgba(0, 0, 0, .12);
  font-family: "PingFang SC", "Microsoft YaHei", "Heiti SC", sans-serif;
  box-sizing: border-box;
}
.qz-title { margin: 0; text-align: center; font-size: 20pt; font-weight: 700; letter-spacing: 1px; }
.qz-sub { margin-top: 4mm; text-align: center; font-size: 12pt; color: #333; }
.qz-name { margin-top: 3mm; text-align: center; font-size: 12pt; }
.qz-hr { margin: 2mm 0 3mm; border-top: 1px solid #444; }

.qz-sec-block { margin-bottom: 4mm; break-inside: auto; }
.qz-sec-head {
  margin: 0 0 1.5mm; font-size: 13pt; font-weight: 700; color: #111;
  break-after: avoid; page-break-after: avoid;
}
.qz-row { display: flex; break-inside: avoid; page-break-inside: avoid; }
.qz-cell {
  flex: 1 1 0; min-width: 0; display: flex; align-items: center;
  padding-right: 3mm; box-sizing: border-box;
}
/* 格内再套一层行内盒：分数要和同行的 ×、= 按**基线**对齐，
   而 vertical-align 只对行内元素生效 —— 直接放在 flex 格子里会被忽略。
   nowrap 保证一行就是一题，绝不折行（折行会顶破固定行高、压到下一题）。 */
.qz-line { display: inline-block; white-space: nowrap; }

/* 各版式字号：与 quiz-core.js 的 LAYOUTS 一一对应，改一处必须改另一处 */
.qz-sec-block[data-layout="mind"] .qz-cell { font-size: 13.5pt; }
.qz-sec-block[data-layout="mid"]  .qz-cell { font-size: 13pt; }
.qz-sec-block[data-layout="row2"] .qz-cell { font-size: 13pt; }
.qz-sec-block[data-layout="wide"] .qz-cell { font-size: 13pt; }
.qz-sec-block[data-layout="tall"] .qz-cell { font-size: 13pt; }

/* 🔴 分数的课本式上下结构：分子在上、分数线居中、分母在下。
   比例 0.85 是调出来的，不是拍的：
     · 0.74（原来，= Python 版 FRAC_RATIO）时分数里的数字只有正文的七成半，
       而分数题里几乎每个数字都在分数里 → 整道题看着比旁边的整数题小一号，
       像「排版出错了」。这是用户实际反馈的问题。
     · 0.85 让分数数字与正文基本齐平，同时靠 line-height:.95 + 细分数线保持
       分数的**总高度 ≈ 1.6em**（和 0.74 时差不多），不会顶破行高。
   行内盒（.qz-line）+ vertical-align:middle 让分数线落在数学轴线（≈基线 + x高/2），
   与同行的 × ÷ = 自然对齐。 */
.fr {
  display: inline-block; vertical-align: middle; text-align: center;
  line-height: .95; margin: 0 .1em;
}
.fr-n, .fr-d { display: block; font-size: .85em; padding: 0 .1em; }
.fr-n { border-bottom: 1px solid currentColor; padding-bottom: .02em; }
.fr-d { padding-top: .02em; }

/* ── 答案页 ─────────────────────────────────────────────────────────────── */
.qz-answer { page-break-before: always; break-before: page; padding-top: 2mm; }
.qz-ans-title { margin: 0 0 2mm; text-align: center; font-size: 16pt; font-weight: 700; }
.qz-ans-sub { text-align: center; font-size: 10.5pt; color: #333; margin-bottom: 3mm; }
.qz-ans-block { margin-bottom: 3mm; break-inside: avoid; }
.qz-ans-head { margin: 0 0 1.5mm; font-size: 11.5pt; font-weight: 700; }
.qz-ans-items { display: flex; flex-wrap: wrap; gap: 1mm 6mm; font-size: 11pt; }
.qz-ans-item { white-space: nowrap; }

/* ── 打印：只出试卷本体，控制面板与提示全部不打印 ─────────────────────────── */
@media print {
  body { background: #fff !important; }
  .subnav, .qz-wrap > .card, .qz-tip, .qz-stat, #toast, .report-card { display: none !important; }
  .qz-wrap { display: block; }
  .qz-sheet {
    width: auto; max-width: none; margin: 0; padding: 0;
    box-shadow: none; background: #fff;
  }
  .qz-cell, .qz-sec-head, .qz-ans-item { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
@page { size: A4 portrait; margin: 12mm; }

/* ── 常态化任务：日频 / 周期 双模式 ─────────────────────────────────────── */
.rt-modes { display: flex; gap: 24px; flex-wrap: wrap; }
.rt-mode { display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; color: var(--text); cursor: pointer; white-space: nowrap; }
/* 🔴 必须显式复位：全局 `input, select, textarea { width:100% }` 会把单选按钮撑满整行，
   两个选项之间就会空出一大片、文字还被挤成两行（截图里很明显）。 */
.rt-mode > input[type="radio"],
.rt-mode > input[type="checkbox"] {
  width: auto; flex: none; padding: 0; margin: 0; border: none; background: none;
}
.rt-inline { font-size: 13.5px; color: var(--text); display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.rt-inline input { text-align: center; }
.rt-check { display: inline-flex; align-items: center; gap: 5px; font-size: 13.5px; color: var(--text); white-space: nowrap; }
/* 全局 `input, select, textarea { width:100% }` 会把勾选框撑满，必须显式复位 */
.rt-check > input[type="checkbox"] {
  width: auto; flex: none; padding: 0; margin: 0; border: none; background: none;
}

/* ── 积分流水（2026-10-14）───────────────────────────────────────────────
   🔴 配色遵循中国股市惯例：加分=红、扣分=绿，与项目内其他积分展示保持一致。 */
.pts-pos { color: #d93a3a; font-weight: 600; }
.pts-neg { color: #1a9e5c; font-weight: 600; }

.ledger-head, .ledger-row {
  display: grid; grid-template-columns: 88px 1fr 62px 64px 44px;
  gap: 8px; align-items: center; padding: 8px 2px;
}
.ledger-head {
  font-size: 12px; color: var(--text-2); border-bottom: 1px solid var(--line);
  padding-bottom: 6px; margin-bottom: 2px;
}
.ledger-row { border-bottom: 1px solid var(--line); font-size: 13px; }
.ledger-row:last-child { border-bottom: none; }
.ledger-head .ta-r, .ledger-delta { text-align: right; }
.ledger-time { color: var(--text-2); font-size: 12px; }
.ledger-reason { line-height: 1.5; word-break: break-word; }
.ledger-child { color: var(--text-2); font-size: 12px; }
.ledger-delta { font-size: 14px; }
@media (max-width: 560px) {
  .ledger-head, .ledger-row { grid-template-columns: 74px 1fr 0 56px 34px; }
  .ledger-child, .ledger-head span:nth-child(3) { display: none; }
}
.ledger-op { text-align: right; }
.pt-undo {
  border: none; background: none; padding: 2px 4px; cursor: pointer;
  font-size: 12px; color: var(--text-2); border-radius: 6px;
}
.pt-undo:hover { color: var(--danger, #d5443c); background: rgba(213, 68, 60, 0.08); }

/* ── 快捷加减分 · 加分/扣分 切换（2026-10-14）─────────────────────────────
   手机浏览器的数字键盘没有负号键，正负只能靠这个按钮切。配色沿用项目惯例：加分红、扣分绿。 */
.qa-sign {
  flex: none; min-width: 52px; padding: 6px 8px; border-radius: 8px;
  font-size: 12.5px; cursor: pointer; font-family: inherit;
}
.qa-sign.plus { color: #cf1322; background: #fff1f0; border: 1px solid #ffccc7; }
.qa-sign.minus { color: #237804; background: #f0fff4; border: 1px solid #b7eb8f; }

/* ── 识别预览里的「周期 / 交期」标记（2026-10-14）──────────────────────────
   周期任务=蓝色（会重复出现）；一次性交期=橙色（只管这一次）。
   两个颜色刻意不同：家长确认时要一眼分清「每周五」和「这周五」。 */
.pv-sched {
  flex: none; font-size: 12px; padding: 2px 7px; border-radius: 6px;
  background: #eef3ff; color: #3358d4; border: 1px solid #cfdcff; white-space: nowrap;
}
.pv-sched-due { background: #fff7e6; color: #ad6800; border-color: #ffd591; }

/* 未来交期任务的日期徽标（2026-10-14）
   家长端保留「今天及以后」都可见（要提前知道周五有作文），
   但必须标出交期，否则会混在今天的任务里分不清。孩子端不显示这类任务。 */
.due-badge {
  flex: none; font-size: 11.5px; padding: 1px 6px; border-radius: 6px;
  background: #fff7e6; color: #ad6800; border: 1px solid #ffd591; white-space: nowrap;
}

/* ── 「过几天要交」的交期标记（2026-10-14）────────────────────────────────
   这类任务从建出来就一直显示、可以提前做（家长反馈：藏到交期那天才出现，
   孩子就没法提前完成）。所以必须让它一眼看出「不是今天非交不可」——
   橙色系、比逾期那条更亮，加粗让它在一行元信息里先被看到。 */
.kid-due-tag {
  font-size: 12px; font-weight: 800; color: #b0621a;
  background: #fff4e5; border: 1px solid #ffd8a8; border-radius: 7px;
  padding: 1px 7px;
}

/* 「不同意」之后提示用户去点「同意」的引导态（2026-10-15 华为驳回整改）。
   审核要求拒绝选项真实可用，所以拒绝后必须留有可返回同意的路径，
   而不能像之前那样把按钮永久禁用。 */
.pv-nudge {
  box-shadow: 0 0 0 3px rgba(220, 38, 38, .35);
  animation: pv-pulse 1.4s ease-in-out infinite;
}
@keyframes pv-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(220, 38, 38, .35); }
  50%      { box-shadow: 0 0 0 6px rgba(220, 38, 38, .18); }
}
@media (prefers-reduced-motion: reduce) {
  .pv-nudge { animation: none; }
}
