/* 词阅 WordLens —— 样式层（浅色 / 深色双主题，与画布设计稿 token 一致） */

:root {
  --brand: #6C5CE7;
  --brand-2: #8B7CFF;
  --brand-soft: #EFEDFE;
  --brand-deep: #F1EFFE;
  --bg: #F7F8FC;
  --card: #FFFFFF;
  --card-2: #F7F8FC;
  --text: #1A1A2E;
  --text-1: #12121F;   /* 正文/标题专用：比 --text 再深一档 */
  --text-2: #6B6B8A;
  --text-3: #9A9AB5;
  --line: #F0F1F7;
  --border: #EAECF3;
  --green: #0E9F6E;
  --green-bg: #E7F8F1;
  --red: #F43F5E;
  --red-bg: #FEECEF;
  --amber: #C97E05;
  --amber-bg: #FFF4E3;
  --shadow-1: 0 1px 2px rgba(15, 17, 51, .04), 0 6px 16px -6px rgba(15, 17, 51, .07);
  --shadow-2: 0 2px 6px rgba(15, 17, 51, .05), 0 14px 30px -10px rgba(15, 17, 51, .12);
  --shadow-3: 0 10px 26px -8px rgba(108, 92, 231, .45), inset 0 1px 0 rgba(255, 255, 255, .16);
  --r-lg: 20px;
  --r-md: 16px;
  --r-sm: 12px;
  --font-num: "Inter Tight", "SF Pro Display", system-ui, sans-serif;
  --font-en: "DM Sans", system-ui, -apple-system, sans-serif;
  --font-read: Georgia, "Times New Roman", "Source Serif Pro", "Songti SC", serif;
  --font-cn: "Noto Sans SC", -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
}

[data-theme="dark"] {
  --brand: #8B7CFF;
  --brand-soft: #2E2A5C;
  --brand-deep: #232142;
  --bg: #12121C;
  --card: #1E1E2C;
  --card-2: #2A2A3A;
  --text: #F2F2F7;
  --text-1: #F7F7FC;
  --text-2: #A8A8C2;
  --text-3: #8A8AA5;
  --line: #2A2A3A;
  --border: #2E2E40;
  --green: #34D399;
  --green-bg: #173A2C;
  --red: #FB7185;
  --red-bg: #3A1D28;
  --amber: #FBBF24;
  --amber-bg: #3A2E15;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .35), 0 6px 16px -6px rgba(0, 0, 0, .45);
  --shadow-2: 0 2px 6px rgba(0, 0, 0, .4), 0 14px 30px -10px rgba(0, 0, 0, .55);
  --shadow-3: 0 10px 26px -8px rgba(139, 124, 255, .5), inset 0 1px 0 rgba(255, 255, 255, .1);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  background: #ECEDF5;
  font-family: var(--font-cn);
  color: var(--text);
}
[data-theme="dark"] body {
  background: #08080F;
}

body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px 16px;
}

/* ---------- 手机壳 ---------- */
.phone {
  position: relative;
  width: 390px;
  height: 844px;
  background: var(--bg);
  border-radius: 44px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 42px 90px -26px rgba(20, 22, 60, .45), 0 0 0 10px #171724, 0 0 0 11px #34344A;
  transition: background .25s ease;
}

.screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ---------- 状态栏 ---------- */
.statusbar {
  height: 52px;
  padding: 0 26px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: none;
  font-family: var(--font-num);
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
}
.statusbar .icons { display: flex; align-items: center; gap: 6px; }
.statusbar .icons svg { display: block; }

/* ---------- 滚动内容 ---------- */
.view {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 20px 8px;
  display: flex;
  flex-direction: column;
  gap: 18px;   /* 模块间距 14→18：模块之间要留白明显、模块内部靠近（卡片内部 gap 仍是 10–14） */
  scrollbar-width: none;
}
.view::-webkit-scrollbar { display: none; }

/* ---------- 通用块 ---------- */
.row { display: flex; align-items: center; }
.row.between { justify-content: space-between; }
.col { display: flex; flex-direction: column; }
.grow { flex: 1; min-width: 0; }

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 18px;
  box-shadow: var(--shadow-1);
}

/* 上次读到：发现页顶部的续读直达卡片 */
.resume-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  width: 100%; text-align: left; cursor: pointer;
  font-family: inherit;
  background: var(--card);
  border: 1px solid var(--brand);
  border-radius: var(--r-lg);
  padding: 13px 16px;
  box-shadow: var(--shadow-1);
  transition: transform .12s;
}
.resume-card:active { transform: scale(.98); }
.resume-card .rc-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 600; color: var(--brand);
}
.resume-card .rc-title {
  font-family: var(--font-en); font-weight: 700; font-size: 15px; line-height: 21px; color: var(--text-1);
}
.resume-card .rc-zh { font-size: 12px; color: var(--text-2); line-height: 18px; }
.resume-card .rc-meta { display: flex; align-items: center; gap: 8px; width: 100%; margin-top: 2px; }
.resume-card .rc-bar {
  flex: 1; height: 5px; border-radius: 3px; background: var(--brand-soft); overflow: hidden;
}
.resume-card .rc-bar span { display: block; height: 100%; border-radius: 3px; background: var(--brand); }
.resume-card .rc-pct { font-size: 11px; color: var(--text-2); white-space: nowrap; }
.resume-card .rc-go {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 12px; font-weight: 600; color: var(--brand); white-space: nowrap;
}

/* ---------- 阅读记录 ---------- */
.history-entry { width: 100%; text-align: left; cursor: pointer; align-items: center; }
.history-entry > svg { color: var(--text-3); flex: none; }
.history-view { gap: 12px; }
.history-filters { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.history-filters .muted-2 { margin-left: auto; }
.history-filter {
  border: 1px solid var(--border); background: var(--card); color: var(--text-2);
  border-radius: 999px; padding: 6px 11px; font-family: var(--font-cn); font-size: 11.5px; cursor: pointer;
}
.history-filter.on { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.history-row {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px;
  background: var(--card); box-shadow: var(--shadow-1); font-family: inherit;
}
.history-row:active { transform: scale(.995); }
.history-row.archived { cursor: default; opacity: .72; }
.history-row.archived:active { transform: none; }
.history-row .thumb { width: 64px; height: 64px; border-radius: 10px; flex: none; position: relative; overflow: hidden; background-size: cover; background-position: center; }
.history-row .thumb img { width: 100%; height: 100%; display: block; object-fit: cover; }
.history-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 4px; }
.history-title { font-family: var(--font-en); font-size: 13px; line-height: 18px; font-weight: 600; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.history-zh { color: var(--text-2); font-size: 11px; line-height: 15px; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.history-meta, .history-status { color: var(--text-3); font-size: 10.5px; }
.history-progress { height: 4px; border-radius: 3px; background: var(--brand-soft); overflow: hidden; margin-top: 2px; }
.history-progress span { display: block; height: 100%; border-radius: inherit; background: var(--brand); }
.history-status { display: flex; justify-content: space-between; align-items: center; }
.history-status b { color: var(--brand); font-weight: 600; }
.history-empty { text-align: center; color: var(--text-2); font-size: 13px; padding: 28px 18px; }

/* ---------- 记词本 ---------- */
.notebook-view { gap: 12px; }
.nb-list { display: flex; flex-direction: column; gap: 8px; }
.nb-row {
  display: flex; align-items: flex-start; gap: 10px;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: 12px;
  background: var(--card); box-shadow: var(--shadow-1);
}
.nb-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; cursor: pointer; }
.nb-main:active { opacity: .7; }
.nb-word-row { display: flex; align-items: baseline; gap: 8px; }
.nb-word { font-family: var(--font-en); font-size: 15px; font-weight: 600; color: var(--text-1); }
.nb-phonetic { font-family: var(--font-en); font-size: 12px; color: var(--text-3); }
/* 查词卡音标（v75 从内联 11px 收进类里）：次要信息以 12px 为下限 */
.phonetic { font-family: var(--font-en); font-size: 12px; color: var(--text-3); }
.nb-def { font-size: 12px; color: var(--text-2); line-height: 16px; }
.nb-from { margin-top: 4px; }
.nb-source {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--text-3); background: var(--bg);
  border: 1px solid var(--border); border-radius: 6px; padding: 3px 8px;
  cursor: pointer; font-family: var(--font-cn);
}
.nb-source:hover { color: var(--brand); border-color: var(--brand); }
.nb-del {
  flex: none; width: 28px; height: 28px; border-radius: 14px;
  border: 1px solid var(--border); background: var(--card);
  color: var(--text-3); cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.nb-del:hover { color: var(--red); border-color: var(--red); background: var(--red-bg); }
.nb-empty { text-align: center; color: var(--text-2); font-size: 13px; padding: 28px 18px; }

/* ---------- 四级字号（2026-09-22 v75 规范）----------
 * 页面标题 .h1 / 模块标题 .h2+.h3（同一档）/ 说明文字 .muted / 次要信息 .muted-2。
 * .muted 12→14、.muted-2 11→12：原先两者都挤在 11–12px，说明与脚注分不开，
 * 390px 手机上辅助文字小到难读（用户实测反馈）。任何新文案别再写内联 font-size:11px/11.5px。 */
.h1 { font-size: 22px; font-weight: 700; letter-spacing: -.3px; color: var(--text-1); }
.h2 { font-size: 16px; font-weight: 600; }
.h3 { font-size: 15px; font-weight: 600; }
.muted { color: var(--text-2); font-size: 14px; line-height: 1.55; }
.muted-2 { color: var(--text-3); font-size: 12px; line-height: 1.6; }
.link { color: var(--brand); font-size: 12px; font-weight: 500; cursor: pointer; }
.link:hover { opacity: .75; }
.link.danger { color: var(--red); }

/* ---------- 数据备份 ---------- */

/* 选择器带上 .sheet-btns 前缀，否则会被上面 `.sheet-btns button { border: 0 }` 盖掉 */
.sheet-btns .ghost-btn {
  height: 48px; border: 1px solid var(--border); border-radius: 14px;
  background: transparent; color: var(--text-2);
  font-family: var(--font-cn); font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.sheet-btns .danger-btn {
  height: 48px; border: 0; border-radius: 14px;
  background: var(--red); color: #fff;
  font-family: var(--font-cn); font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.sheet-btns .danger-btn:active, .sheet-btns .ghost-btn:active { transform: translateY(1px); }

.chip {
  display: inline-flex;
  align-items: center;
  flex: none;
  white-space: nowrap;
  padding: 6px 10px;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2px;
}
.chip.green { background: var(--green-bg); color: var(--green); }
.chip.amber { background: var(--amber-bg); color: var(--amber); }

.icon-btn {
  width: 36px; height: 36px;
  border-radius: 18px;
  background: var(--card);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex: none;
  box-shadow: var(--shadow-1);
  transition: opacity .15s ease, transform .12s ease, background .18s ease;
}
.icon-btn:hover { opacity: .8; }
.icon-btn:active { transform: scale(.92); }
.icon-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.icon-btn.solid { background: var(--brand); border-color: transparent; }
.icon-btn.active { background: var(--brand-soft); border-color: transparent; color: var(--brand); }
.icon-btn svg { display: block; }

/* ---------- 进度环 ---------- */
.ring-wrap { position: relative; width: 78px; height: 78px; flex: none; }
.ring-wrap svg { display: block; transform: rotate(-90deg); }
.ring-txt {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-num); font-weight: 700; font-size: 19px;
  color: var(--text-1);
}

/* ---------- 数据格 ---------- */
.stat-grid { display: flex; gap: 10px; }

/* 「阅读概况」的两组口径（累计 / 近 7 天）：标签在左、数字组在右，
 * 让「这行数字是什么口径」不用读标签猜。320px 窄屏标签换到上方，数字组才有满宽。 */
.ov-group { display: flex; align-items: center; gap: 14px; }
.ov-label { flex: none; width: 48px; font-size: 12px; color: var(--text-3); }
.ov-group .stat-grid { flex: 1; min-width: 0; }
@media (max-width: 359px) {
  .ov-group { flex-direction: column; align-items: stretch; gap: 8px; }
  .ov-label { width: auto; }
}
.stat {
  flex: 1;
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 12px 8px;
  text-align: center;
}
.stat .n { font-family: var(--font-num); font-weight: 700; font-size: 18px; line-height: 1.1; }
.stat .l { font-size: 12px; color: var(--text-2); margin-top: 3px; }
.stat.bad { background: var(--red-bg); }
.stat.bad .n { color: var(--red); }
.stat.bad .l { color: var(--red); opacity: .8; }
.stat.good .n { color: var(--green); }

/* ---------- 主按钮 ---------- */
.btn-primary {
  width: 100%;
  height: 54px;
  border: 0;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--brand-2) 0%, var(--brand) 100%);
  color: #fff;
  font-family: var(--font-cn);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .5px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  cursor: pointer;
  box-shadow: var(--shadow-3);
  transition: filter .18s ease, transform .12s ease, box-shadow .18s ease;
}
.btn-primary:hover { filter: brightness(1.07); box-shadow: 0 14px 30px -8px rgba(108, 92, 231, .55), inset 0 1px 0 rgba(255, 255, 255, .16); }
.btn-primary:active { transform: translateY(1px) scale(.99); }

/* ---------- 文章卡 ---------- */
.article {
  display: flex; gap: 12px; align-items: center;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px;
  box-shadow: var(--shadow-1);
  cursor: pointer;
  transition: box-shadow .2s ease, transform .2s ease;
}
.article:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }
.article:active { transform: translateY(0) scale(.995); }
.article:focus-visible, .discover-feat:focus-visible,
.cat:focus-visible, .sort-opt:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* 从阅读页返回时，刚才那篇闪一下 —— 长列表里一眼找回位置 */
.article.flash, .discover-feat.flash { animation: flashBack 1.25s ease; }
@keyframes flashBack {
  0%   { box-shadow: 0 0 0 0 rgba(108, 92, 231, .55); }
  30%  { box-shadow: 0 0 0 4px rgba(108, 92, 231, .28); }
  100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0); }
}
.article .thumb {
  width: 76px; height: 76px; border-radius: 12px; flex: none;
  position: relative; overflow: hidden;
  background-size: cover; background-position: center;
}
/* 懒加载封面：<img> 撑满方框，没加载完先用浅灰占位，避免白块闪一下 */
.article .thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  background: var(--card-2);
}
.article .thumb.has-img::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(20, 20, 43, .07);
}
.article .t {
  font-family: var(--font-en);
  font-size: 13px;
  line-height: 18px;
  font-weight: 500;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* 中文标题：英文下的辅助小字。和英文标题贴成一组，行高压到最小，最多两行 */
.article .t-zh {
  font-family: var(--font-cn);
  font-size: 11.5px;
  line-height: 16px;
  color: var(--text-2);
  margin-top: -2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.article .tag { font-size: 11px; font-weight: 500; color: var(--brand); }
.article .meta { font-size: 11px; color: var(--text-3); }

/* 人物专题保留摄影主体；完整图片在阅读页按原比例呈现。 */
.article.people-card { flex-direction: column; align-items: stretch; padding: 0; overflow: hidden; gap: 0; }
.article.people-card .thumb { width: 100%; height: 240px; min-width: 0; border-radius: 0; }
.article.people-card .thumb img { width: 100%; height: 100%; object-fit: cover; object-position: center 25%; }
.article.people-card > .col { padding: 16px; }
.people-name { font-size: 20px; font-weight: 650; color: var(--text-1); }
.people-reading-note { padding: 14px; border: 1px solid var(--border); border-radius: 12px; color: var(--text-2); font-size: 12px; line-height: 1.8; }
.people-reading-note p { margin: 6px 0 10px; }
/* 存储写入告警（2026-09-22）：只在 localStorage 写不进去时渲染（见 app.js 的 save()）。
 * 用警示色边框而不是纯红底 —— 它是「提醒去导出备份」，不是错误弹窗。 */
.storage-warn { display: flex; gap: 8px; align-items: flex-start; margin-top: 10px; padding: 10px 12px;
  border: 1px solid var(--warn, #b8860b); border-radius: 10px; color: var(--text-1); font-size: 12px; line-height: 1.7; }
.storage-warn svg { flex: none; margin-top: 2px; color: var(--warn, #b8860b); }
.people-reading-note a { display: block; padding: 10px; background: var(--brand); color: white; border-radius: 8px; text-align: center; text-decoration: none; }
.read-cover.has-img.people-cover { height: auto; background: transparent; }
.people-cover > img { width: 100%; height: auto; display: block; }
.photo-credit { font-size: 10px; line-height: 1.6; color: var(--text-3); }

/* 已读标记：读完打过的卡在列表里一眼能认出，避免重读。徽标随标题内联，不单独占行。 */
.article .read-dot {
  display: inline-block;
  font-family: var(--font-cn);
  font-size: 10px; font-weight: 600; line-height: 1;
  color: var(--green);
  background: var(--green-bg);
  border-radius: 6px;
  padding: 3px 5px;
  margin-left: 6px;
  vertical-align: 2px;
  white-space: nowrap;
}
/* 已读的卡片整体降一档，视觉上退到「看过的」那一层 */
.article.read .t { color: var(--text-2); }
.article.read .thumb img { opacity: .72; }
.article.read .thumb.has-img::after { box-shadow: inset 0 0 0 1px rgba(20, 20, 43, .05); }

.example-box {
  background: var(--card-2);
  border-radius: var(--r-sm);
  padding: 12px;
  display: flex; flex-direction: column; gap: 6px;
}
.example-box .en { font-family: var(--font-en); font-size: 13px; line-height: 20px; }
.example-box .cn { font-size: 12px; line-height: 19px; color: var(--text-2); }

/* 例句/搭配里的目标词：和阅读页生词共用一套语言（brand 色 + 加粗），
   全站只有一种「被标出来的词」。mark 的浏览器默认荧光底色要清掉，
   这里表达的是「就是这个词」，不是荧光笔；也不做 hover —— 它不可点。 */
.example-box .w-hl {
  background: none;
  color: var(--brand);
  font-weight: 600;
}

/* 例句按需加载的占位：沿用同一套 .example-box 外壳，加载完成时高度不跳 */
.example-box.loading { flex-direction: row; align-items: center; gap: 10px; }
.ex-hint { font-size: 12px; color: var(--text-2); }
.mini-btn {
  margin-left: auto;
  padding: 5px 12px;
  border: 0;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand);
  font-family: var(--font-cn);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

/* ---------- 操作按钮 ---------- */
.answer-btn {
  flex: 1;
  height: 52px;
  border: 0;
  border-radius: var(--r-md);
  font-family: var(--font-cn);
  font-size: 14px;
  font-weight: 600;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer;
  transition: filter .15s ease, transform .12s ease, box-shadow .15s ease;
}
.answer-btn:hover { filter: brightness(.97); }
.answer-btn:active { transform: translateY(1px) scale(.98); }
.answer-btn.no { background: var(--red-bg); color: var(--red); box-shadow: inset 0 0 0 1px rgba(244, 63, 94, .16); }
.answer-btn.fuzzy { background: var(--amber-bg); color: var(--amber); box-shadow: inset 0 0 0 1px rgba(201, 126, 5, .16); }
.answer-btn.yes { background: var(--green-bg); color: var(--green); box-shadow: inset 0 0 0 1px rgba(14, 159, 110, .18); }

/* ---------- 阅读正文 ----------
 * 正文字号/行高/左右留白统一由 .read-scroll 上的 CSS 变量控制（见「阅读：排版基础」段），
 * 旧的一套 .para/.en 尺寸（15/17/19px）已随逐句分行一起删掉，避免两套数字打架。 */

/* 正文里所有能点开的词共用 .word 基类：它**只**表示「可点」，视觉上与正文完全一致
 * —— 一篇文章 97% 的 token 都可点，给它们任何颜色或下划线都会把正文变成链接页。
 * 只在悬停 / 按压时给一点反馈，让手指知道碰到了词。
 *
 * 这里原本还有 `padding: 0 1px`，2026-09-20 删除。实测（.bak/pad-ab.cjs，390×844，
 * 同一行相邻两词成对归零前后）：**词缝差 0.000px** —— 两个词盒各向外撑 1px，正好把
 * 它吃掉的空格补回来，留给「点空白弹译文」的死区恒为 4.688px。结论：这 1px 没有
 * 换来任何点击容错，只把词与词撑开 2px（整行后一个词的 bLeft 前移 2.000px/词）。
 * 视觉间距与可点热区是两件事，不该由一个数同时决定 —— 要扩大热区得靠事件层的
 * 命中规则（见计划 §3），不是靠 padding 把盒子撑大。 */
.word {
  cursor: pointer;
  border-radius: 4px;
  transition: background .15s;
  -webkit-tap-highlight-color: transparent;
}
.word:hover, .word:active { background: var(--brand-soft); }

/* 高亮态（当前档位的目标词）：紫色字 + 加粗。
 * cursor / padding / hover 一律由 .word 提供，这里只写「染色」这一件事 ——
 * 同一个效果在两条规则里各写一遍，改一处漏一处是迟早的事。 */
.kw { color: var(--brand); font-weight: 600; }
.kw.on { background: var(--brand); color: #fff; }

/* 刚点开词卡的那个词（app.js 的 markTappedWord 加 .tapped）。
 * 轻卡的遮罩改成不模糊之后正文仍然清晰可读 —— 那就必须能一眼看出
 * 「卡片上这条释义对应正文里哪一个词」，否则长句里十几个词根本无从对应。
 * 只加底色：padding / border-radius / 字重 / 字号一律沿用 .word 基类不动，
 * 因为任何改变行盒的反馈都会自己引起换行（.para-tts 那次 27px 隐形占位就是这类坑）。
 * 选择器写足 4 个类是为了压过 .screen.rt-paper .kw / .screen.rt-night .kw 的 3 个类 ——
 * 护眼档和夜间档的 .kw 自带底色，不压过就恰好在那两个主题里看不到定位标识。 */
.read-body .para .word.tapped { background: rgba(108, 92, 231, .18); }

.toolbar {
  display: flex;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 18px;
  height: 56px;
  box-shadow: var(--shadow-1);
  flex: none;
  overflow: hidden;
}
.toolbar button {
  flex: 1;
  border: 0; background: transparent;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-family: var(--font-cn); font-size: 10px; font-weight: 500;
  color: var(--text-2); cursor: pointer;
}
.toolbar button:hover { background: var(--card-2); }

/* ---------- 阅读：扇贝风格增强 ---------- */
.read-progress {
  position: sticky; top: 0; left: 0; right: 0;
  height: 3px; background: transparent; z-index: 5;
}
.read-progress::before {
  content: ""; display: block;
  height: 3px; background: var(--brand-soft);
}
.read-progress .bar {
  position: absolute; left: 0; top: 0; height: 3px;
  background: var(--brand);
  transition: width .25s;
  width: 0%;
}

.read-top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 20px 6px;
}
.read-top .center {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; gap: 2px;
  font-family: var(--font-cn); font-size: 12px; color: var(--text-2);
}
.read-top .center .src { font-size: 10px; color: var(--text-3); }
.read-top-title {
  display: block; max-width: min(62vw, 520px); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text-1); font-size: 12px; font-weight: 600;
}
.read-top-spacer { width: 40px; height: 40px; flex: none; }

.read-top, .read-progress { flex: none; }

/* 阅读页滚动容器：复用 .view 的 overflow-y:auto，底部留出 FAB 空间。
 *
 * 左右留白只在这里定义一次（--rd-pad），正文/标题/读完卡都从它取。
 * 为什么：原来是 .read-scroll 的 20px 和 .read-body 的 24px 叠加，
 * 手机上一行正文两侧各让掉 40px（390px 屏只剩约 310px 宽），换行密、读着累。
 * 两层各写一半 padding，谁改都不会想到另一层还在加 —— 现在只有一个数。
 *
 * .view.read-scroll 的选择器要压过媒体查询里的 .view{padding}，
 * 否则平板上会用回 .view 的横向 16px，又变回两层叠加。 */
.view.read-scroll { padding: 12px 0 110px; }
.read-scroll {
  /* 手机档 22px；≥760px 放宽到 30px（见下面紧跟的媒体查询）。
   * 「只在这里定义一次」这句从写下那天起就是假的 —— editorial.css 又声明了一遍
   * （基础层 30px、≤759px 媒体查询又写回 22px），加载在后所以它赢。2026-09-20 把
   * 那两行删掉、把两个档位的值一并收回这里，计算值一个像素没变。 */
  --rd-pad: 22px;
  /* 字号三档：英文 19/21/24px，行高按 1.7 倍取整；中文同比跟进，
     不再固定 13.5px —— 英文调到最大而中文不动，双语对照会一轻一重。 */
  --rd-en: 19px; --rd-en-lh: 32px;
  --rd-cn: 14px; --rd-cn-lh: 22px;
  gap: 18px;
}
.read-scroll.fs-1 { --rd-en: 21px; --rd-en-lh: 36px; --rd-cn: 15.5px; --rd-cn-lh: 24px; }
.read-scroll.fs-2 { --rd-en: 24px; --rd-en-lh: 41px; --rd-cn: 17px; --rd-cn-lh: 27px; }
/* 宽一点的屏（平板 / 桌面预览窗口）左右留白放宽到 30px：行宽越大越需要两侧留白兜住，
 * 不然一行 700+px 的长行会超出舒适阅读行长。阈值 760px 沿用 editorial 层原来的分界，
 * 只是把归属收回本文件（见 .read-scroll 里的说明）。 */
@media (min-width: 760px) {
  .read-scroll { --rd-pad: 30px; }
}

.read-hero {
  padding: 8px var(--rd-pad) 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.read-hero .pills { display: flex; gap: 8px; }
.read-hero .pills > * { flex: none; white-space: nowrap; }
.read-hero h1.title {
  font-family: var(--font-en);
  font-size: 24px; font-weight: 700; line-height: 32px;
  letter-spacing: -.5px;
  color: var(--text-1);
}
/* 中文标题：阅读页的辅助行，比英文标题轻一档，和它贴成一组（hero 的 gap 是 12px） */
.read-hero .title-zh {
  font-family: var(--font-cn);
  font-size: 14px; font-weight: 400; line-height: 21px;
  color: var(--text-2);
  margin-top: -6px;
}
.read-hero .byline {
  display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap;
  font-size: 12px; color: var(--text-3);
}
.read-hero .byline .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--text-3); }
/* 译文署名（PG 三篇起：translationCredit 数据层留痕，页面在 byline 下方展示）
 * 11→12px（v75 次要信息下限统一） */
.read-hero .translation-credit {
  font-size: 12px; line-height: 1.6; color: var(--text-3);
  padding-bottom: 14px; margin-top: 6px;
}

.read-cover {
  height: 140px; border-radius: 16px;
  position: relative; overflow: hidden;
  background-size: cover; background-position: center;
  box-shadow: var(--shadow-2);
}
.read-cover.has-img { height: 140px; }
.read-cover.has-img::after {
  content: "";
  background: linear-gradient(180deg, rgba(0,0,0,.06) 0%, transparent 34%, rgba(0,0,0,.18) 66%, rgba(0,0,0,.62) 100%);
}
/* 有真图时，刊头字加一层暗底保证可读 */
.read-cover.has-img .mark { text-shadow: 0 2px 12px rgba(0,0,0,.7); }
.read-cover .play {
  position: absolute; right: 14px; bottom: 14px;
  width: 40px; height: 40px; border-radius: 20px;
  background: rgba(255,255,255,.92);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0,0,0,.18);
  z-index: 3;
}
.read-cover::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 60%, rgba(0,0,0,.20) 100%);
  pointer-events: none;
}
.read-cover .mark {
  position: absolute; left: 16px; bottom: 14px;
  font-family: var(--font-read); font-style: italic;
  font-size: 16px; font-weight: 700; letter-spacing: .3px;
  color: rgba(255,255,255,.95);
  text-shadow: 0 1px 8px rgba(0,0,0,.35);
  z-index: 2;
}
/* 「轻触英文看译文」提示条 */
.peek-hint {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px;
  background: var(--brand-soft); color: var(--brand);
  border-radius: 10px; padding: 7px 12px;
  align-self: flex-start; font-weight: 500;
}
/* 读完数据卡（生词数 / 查询 / 阅读时长） */
.read-finish .stat-chips {
  display: flex; gap: 6px; flex-wrap: wrap; justify-content: center;
}
.read-finish .st-chip {
  display: inline-flex; align-items: center; gap: 4px;
  white-space: nowrap;
  font-size: 11px; color: var(--text-2);
  background: rgba(255,255,255,.78); border: 1px solid var(--brand-soft);
  padding: 4px 10px; border-radius: 999px;
}
.read-finish .st-chip b {
  color: var(--brand); font-family: var(--font-num); font-weight: 700; font-size: 12px;
}
.read-finish .st-chip i { font-style: normal; color: var(--text-2); }
/* 顶部进度浮标（相对手机壳定位，桌面预览时不会跑到壳外） */
/* 进度文字：并入阅读顶栏（原先悬浮在正文上会盖住文字行） */
.read-hud {
  font-family: var(--font-cn); font-size: 10.5px; color: var(--text-2);
  white-space: nowrap; pointer-events: none;
}

/* 正文排版：一段话连续排下去
 *
 * 旧结构是「每个句子一个 flex 块」，于是一段话被拆成竖排的句子清单：
 * 英文再长也只在句末换行，句间还有 10px 空隙 + 2px 间距，读起来一顿一顿。
 * 现在 .para 是段落级的文本流，句子是内联 span，句与句之间只有空格 ——
 * 换行由行宽自然决定（「一段文字能自然连读，句间没有不必要的视觉停顿」）。
 *
 * 逐句译文 .cn 是句子的**相邻兄弟**节点（2026-09-19 从 .sentence 内部拆出来）：
 * 块级元素，插在该句下方、必然打断文本流 —— 这正是双语对照要的效果。
 * 非「逐句对照」档它 display:none，段落仍然是连续的一段。
 */
.read-body {
  padding: 0 var(--rd-pad);
}
/* 竖向内边距为什么是 0（而不是原来那个 16px / 8px）：正文块与页眉、读完卡之间的
 * 距离由 .read-scroll 的 gap（28px）统一给，这里再垫一层就是两份来源叠加 ——
 * 历史上真正生效的也一直是 0：editorial.css 有一行 `.read-body{padding:0 var(--rd-pad)}`
 * 加载在后、同特异性，把这里的 16px/8px 盖掉了不知多久。2026-09-20 把那行删掉、
 * 把生效值（0）写回这里，计算值一个像素没变（.bak/pad-probe.cjs 实测 390 与 1000 两档
 * bodyPadding 均为 `0px 22px` / `0px 30px`）—— **归一只改来源，不改观感**。
 * ⚠️ 同一批删掉的还有 styles.css 自己 `@media (min-width:900px)` 里的
 * `.read-body{padding-left/right:42px}`：它同样被 editorial 层盖住，从未生效过。
 * 那句「宽屏正文限制阅读行长」的意图现在由 .read-body 的 max-width 承担。 */
/* 段落间距 24px（2026-09-20 起）。这是**全站唯一的取值来源** ——
 * 在此之前它是 18px，但 editorial.css 里一行遗留的 `.read-body .para{margin-bottom:30px}`
 * 因为加载顺序在后把它盖掉了，于是注释写 18、浏览器算 30，谁也不知道自己在读哪个数。
 * 现在 18 → 24 是有意改的（长文过散、多滚），30 那行遗留覆盖已删除。
 * ⚠️ 历史上 30px 是被否过的：第一版样张把**句距和段距一起**拉到 (20, 30)，
 * 用户观感是「隔得空太大了」—— 但那次崩的是两个量同时变大。
 * 这里只动段距、句距仍是 10px，24 对 10 的层次依然清楚。
 * 真机试读若仍觉散，直接回退这一个数字即可（单一来源之后回退不再有副作用）。 */
.read-body .para {
  font-family: var(--font-read);
  font-size: var(--rd-en); line-height: var(--rd-en-lh);
  /* letter-spacing: normal（2026-09-20，原为 .1px）。Georgia 这类衬线的排字关系
     是字体自己设计好的，额外加 0.1px 等于把每行的字距均匀拉开一点点 —— 在 19px
     字号下不过 0.5%，肉眼几乎看不出，但它会和「逐词包裹」叠加：每个词各自成为一个
     内联盒之后，0.1px 是加在每个盒的右侧，词多的行被累积推长。先回到字体本值，
     要看「疏 / 密」就直接调字号与行高，别用字距微调。 */
  letter-spacing: normal;
  color: var(--text-1);
  margin: 0 0 24px;
}
.read-body .para:last-child { margin-bottom: 0; }
/* ---------- 小标题段（.para-head，2026-09-21 随 AI 栏目整期合并引入） ----------
 * 源站的 h2/h3 在整期长文里回到了正文，数据侧打了 `head: 2|3|4`（见 tools/offbook.mjs
 * 头部「粒度」、「节标题当段落」那段）。这里只解决一件事：**让它看起来像标题**。
 *
 * 为什么不能只靠 hN 标签自带的样式：把 h2 塞进正文，浏览器默认字号是 1.5em（fs-0 下
 * 19→28px）、外边距 0.83em 上下都有 —— 那是给「文档大纲」用的，不是给「长文里的小节」
 * 用的。28px 的标题会跟 19px 正文拉开两级，一眼看去像换了一篇文章。
 * 所以字号几乎与正文齐平（+1px），靠**加粗 + 上方 40px 空**做层次。
 *
 * 为什么上方 40 / 下方 12 而不是对称：标题属于**它下面**那段内容，所以下边距要小于
 * 段距 24px（12px 让标题与首段贴住，读起来是一个整体）；上方 40px 才是「上一节结束了」
 * 的信号。对称的 24/24 会让标题看起来跟前一段更亲。
 *
 * 为什么字号写成 calc(… + 1px) 而不是写死 20px：--rd-en 是字号档位变量
 * （fs-0 19px / fs-1 21px / fs-2 24px），写死就变成「用户调大字号，标题反而不跟着长」。
 * 行高反向收 3px 同理，跟着档位一起动。
 *
 * ⚠️ 风险已核：`audit.js` 里唯一的 <h2> 断言在发现页（.editorial-copy），与阅读页无关；
 * 用 `.para.para-head` 而非 `.para-head` 是为了稳过 `.read-body .para` 那条基础声明
 * （同特异性靠文件顺序太脆，挪一行就失效）。
 * 段距的唯一来源仍是上面 `.read-body .para` 的 margin —— 这里只覆盖标题段自己那一份。 */
.read-body .para.para-head {
  font-weight: 700;
  font-size: calc(var(--rd-en) + 1px);
  line-height: calc(var(--rd-en-lh) - 3px);
  margin: 40px 0 12px;
}
/* h3 是**节级**，比 h2 章级低一档：字号回到正文大小，只靠加粗 + 32px 上间距分层次。
 * 为什么要分档：一期长文实测 43 个 h2 + 169 个 h3（`on-cognitive-decoupling` 是 9+22），
 * 两档同号时读者分不出「换章」和「换节」—— 而前者才是长滚里真正需要定位的点。
 * 40 / 32 的差也是刻意的：章级要明显大于节级，节级又要明显大于段距 24px。 */
.read-body h3.para.para-head {
  font-size: var(--rd-en);
  margin-top: 32px;
}
/* 正文第一段若就是标题（AI 栏目整期文的第一节标题），上方 40px 会在封面与标题间
 * 多出一块空白，看起来像内容缺失。 */
.read-body .para.para-head:first-child { margin-top: 0; }
/* 句子边界：句末留 3px 水平空隙。
 * inline 元素的水平 padding 只在元素首尾出现（跨行时 padding-right 落在最后一行
 * 末尾），不像 margin 那样在每行行首重复缩进。段落感保留 —— 换行仍由行宽决定，
 * 句间 3px 远小于 24px 的段距，不会被读成「一句一张卡片」；但扫读时能看出句子
 * 在哪里结束。这是「句子是交互与翻译的最小单位」在排版上的落点。 */
.read-body .para .sentence { display: inline; padding-right: 3px; }
/* ---------- 「一句一行」（.para-flow，2026-09-19 起全站生效） ----------
 * 中文对照档每句后面跟一个块级译文，句子自然一行一句；纯英文档句子是 inline，
 * 整段连排成一坨 —— 同一个 App 两种排版节奏，用户要的是「英文时和双语时一样」。
 * 所有文章两档共用同一节奏：句子转块级、句间 10px，段距 24px（2026-09-20 由 18 上调，
 * 原因见 .read-body .para 上面那段注释 —— 那里是全站唯一的段距取值点）。
 * 出口留在 app.js 的 PARA_FLOW_OFF —— 黑名单，加 id 即退回连排（白名单每抓一篇
 * 新文章都要手工补一次，忘了就是「新文章跟别的不一样」，而这种不一致没人会发现）。
 *
 * 句距为什么定 10px：段距 24px。句距一旦逼近段距（样张试过 16px），读者分不清
 * 哪里是新段 —— 段落层次整个糊掉，全篇变成一长串等距的句子。10px 有明确停顿，
 * 又远小于 24px。也刻意不跟段距一起拉：两个同时变大才是「散」的来源
 * （第一版样张把句距和段距**一起**拉到 (20, 30)，观感就是那样崩的）。
 * ⚠️ 「只动段距」不等于没有风险：18 → 24 本身也是一次放大，只是层次比那次清楚。
 * 真机试读若觉得散，**只回退段距这一个数**，别再动句距 —— 同时动就分不清是谁的锅。 */
/* 句末右端留 10px：块级句子撑满整行，右端零留白时文字顶到边、手指也没落点。
 * 10px 与句距同值 —— 留白既是「这行到头了」的视觉收口，也是点句出译文的点击余量
 * （整行都是热区，右端那点空也照点）。 */
/* position: relative 只为给句末朗读喇叭当定位祖先（见下方 .para-tts）。
 * 它不改变布局：句子的盒尺寸、间距、选中态的左装订线都逐像素不动。 */
.read-scroll.para-flow .para .sentence { display: block; padding-right: 10px; position: relative; }
/* 只给同段的后续句子加空隙 —— 第一个句子加了，段首会平白多出 10px。
   用通用兄弟 `~` 而不是相邻 `+`：中间隔着已展开的 .cn 时同样要成立。 */
.read-scroll.para-flow .para .sentence ~ .sentence { margin-top: 10px; }
/* 选中句的左边线要落在文字外面。块级盒撑满整行，inset 阴影会正好压在首字上；
   负 margin 把盒子左扩 10px、padding 再把文字推回原位 —— 文字逐字不动，竖线与
   底纹多出 10px 装订线。跨行的句子左边线是一条贯穿的竖线（盒子高度），
   比 inline 时代「每行一小段」更像个被括起来的整句。 */
.read-scroll.para-flow .para .sentence.sel { margin-left: -10px; padding-left: 10px; }
/* 译文块（.cn）在这个节奏下的三个数值，都按用户 2026-09-19 发来的参考图折
 * （图宽 1409、英文字高 31 图素 → 本 App fs-0 的 --rd-en: 19px，缩放 ≈0.61）：
 *
 * ① 下边距归零 —— 「译文 → 下一句」改由那 10px 句距负责。不撤掉的话
 *    「上句译文 → 下句英文」= 10 + 10 = 20px，中英对照档比纯英文档松一截，
 *    而两档同一节奏正是这次要改的东西。（参考图实测 ≈11px，与 10px 句距同源。）
 * ② 上下内边距 6 → 12px。参考图里译文文字带只占框高的三分之一，框上下各 ≈19 图素
 *    ≈ 11.6px。原来 6px 时译文是「贴在英文屁股上的一条」，用户的原话是「别扭」。
 * ③ 去掉基础样式里那根 2px 品牌紫左边框，底色也从淡紫换成中性 —— 紫色在正文里
 *    已经承担了高亮词和选中句两个语义，译文块再抢一次紫，整页就只剩一种颜色在喊。
 *    底色 ≈3.5% 黑（参考图框底 #F0EFE9 对页底 #F8F7F3 差 8/255），圆角沿用基础样式。
 *    左内边距 12px 顶替原来的 border 2px + padding 12px，译文文字位置逐像素不动。 */
.read-scroll.para-flow .para .cn {
  margin: 6px 0 0;
  padding: 12px 14px 12px 12px;
  border-left: 0;
  background: rgba(125, 122, 148, .07);
}
/* 护眼主题的页面底是暖黄（#F6EFDD），中性灰叠上去会发脏，换同浓度的暖色。 */
.screen.rt-paper .read-scroll.para-flow .para .cn { background: rgba(150, 120, 60, .075); }
/* 当前选中的这一句：左边线 + 轻微底纹。
 * 旧实现只有 7% 透明度的背景 —— 浅色主题下几乎不可见，「点了一句」等于没有确认。
 * 左边线用 inset 阴影而不是 border-left：border 会把整段文字挤动（重排），
 * inset shadow 不占位。inline 元素跨行时每个行盒都会画到这条线，于是整句被
 * 一根竖线括起来 —— 正好对应「我现在看的就是这一句」。 */
.read-body .para .sentence.sel {
  background: rgba(108, 92, 231, .09);
  box-shadow: inset 2px 0 0 var(--brand);
  border-radius: 3px;
}
/* 默认点句显示：句子可点选，段内译文默认收起 */
.read-scroll.no-cn .sentence { cursor: pointer; }
.read-scroll.no-cn .para .cn { display: none; }
/* 中文标题也一并收掉：选了「纯英文阅读」就不该在开头先给一句中文 */
.read-scroll.no-cn .read-hero .title-zh,
.read-scroll.no-cn .para-img .caption-cn { display: none; }
/* 「点句显示」档：点中的那句，译文从相邻兄弟位置展开。
   用 .sentence.peek + .cn 而不是 .sentence.peek .cn —— 译文现在是句子的兄弟节点。
   收起全文后仍可点句，不再有禁用点句译文的档位。 */
.read-scroll.cn-tap .sentence.peek + .cn {
  display: block; animation: peekIn .28s ease;
}
@keyframes peekIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
/* 逐句译文：块级，插在该句下方；字号跟随正文档位 */
.read-body .para .cn {
  display: block;
  font-family: var(--font-cn);
  font-size: var(--rd-cn); line-height: var(--rd-cn-lh);
  color: var(--text-2);
  background: rgba(108, 92, 231, .05);
  border-left: 2px solid var(--brand);
  padding: 6px 0 6px 12px;
  border-radius: 2px;
  margin: 6px 0 10px;
}
/* 单句朗读小喇叭：默认**不占位**。
 * 旧版每句挂一个半透明喇叭，长文里满屏小图标 —— 读的时候是噪音。
 * 上一版改成 opacity:0，噪音是没了，但留下一个更隐蔽的坑：**opacity 不改变布局**，
 * 那个 22×22 + margin-left:5px 的盒子照样在流里占 27px。于是每个句子末尾都拖着
 * 一段看不见的空白；句子在行末结束时，这块空白被折到下一行行首、把首字推开。
 * 截图实测（Edge 无头 + .bak/preview.html）：正文出现
 * `for my Barça teammates.      But my`，新段落首行并多出 27px 缩进 ——
 * 整段因此参差不齐，这正是「读起来像被切碎了」的来源。
 * 现在用 display 切换：不显示时完全不占位。
 * 也刻意不做 hover 展开 —— inline 元素突然出现会让整段重排、文字跟着鼠标跑，会抖。 */
.para-tts {
  display: none;
  align-items: center; justify-content: center;
  margin-left: 4px; width: 22px; height: 22px; border-radius: 11px;
  color: var(--text-3); vertical-align: middle;
  transition: color .15s, background .15s; cursor: pointer;
}
.sentence.sel > .para-tts,
.para.playing .para-tts { display: inline-flex; }
.para-tts:hover, .para.playing .para-tts { color: var(--brand); background: var(--brand-soft); }
/* 选中态**不给底盘**，只上品牌色 —— 这是绝对定位之后必须跟着改的一处。
 * 底盘色是 --brand-soft，和选中句的底纹（editorial.css 的 .sentence.sel）**同色**。
 * 喇叭现在横跨在「选中句底纹」与「页面留白」的交界上（左 6px 在底纹里、右 16px 在外），
 * 同一个盘子一半融进底纹、一半露在外面 —— 截图（.bak/shot-tts-fix-crop.png）里就是一个
 * 被切掉一半的圆，看着像渲染故障。去掉底盘后只剩一个品牌色喇叭字形，落点干净。
 * hover 的圆盘保留（鼠标下的即时反馈），playing 态也保留（那是「正在读」的状态标记）。 */
.sentence.sel > .para-tts { color: var(--brand); }

/* 喇叭不再进正文行盒（2026-09-21）。
 * 旧实现是 `display: none → inline-flex`：控件**只在选中时**进流，于是「选中这一句」
 * 这个动作本身就会改变行宽。块级句子的末行只要离右边界不足 26px（22px 图标 +
 * 4px 左边距），喇叭就被折到下一行 —— 被点句子之下的全部内容瞬间下移一行。
 * 实测（Edge 无头 390×844 · people-anne-hathaway-mother-mary 前 24 句 · cnMode=off
 * 以排除「译文展开」这个混淆项）：24 句里 3 句（第 3、22、24 句）选中后段高 +32px，
 * 恰好一行 --rd-en-lh。已上线的「点句保持位置」只管被点的那一句，挤行发生在它之下，
 * 两者不重叠 —— 所以必须单独修，不能靠那个补偿兜住。
 *
 * 改法：把喇叭提出行盒，绝对定位进句子块右侧的页面留白（--rd-pad，手机档 22px）。
 * 盒子不进流 → 选中不再改行宽 → 挤行根除，且不占任何正文宽度（不用「预留 26px」那种
 * 方案：那会把每一句的换行位置都提前，等于用全篇排版换一个只在 3/24 句发生的抖动）。
 *
 * 两个数字都是量出来的，不是估的：
 * · right 取 -16px —— 绝对定位的 containing block 是句子块的 padding box，右边界 =
 *   正文文本区右边界 + padding-right 10px。喇叭因此占 [文本右界 -4px, +16px]：
 *   左缘留在文本区外 4px（**不压字**，末行占满时也一样），右缘离屏幕边 6px
 *   （不贴边 —— 贴边会撞上 iOS 的边缘返回手势）。取 -20px 就会正好顶到屏幕边。
 * · bottom 按 --rd-en-lh 算 —— 跟着三档字号（32/36/41px）走，喇叭始终压在**末行**的
 *   视觉中线上，而不是句子块的几何中心（跨行句才不会被甩到整句中间）。 */
.read-scroll.para-flow .para .para-tts {
  position: absolute; right: -16px;
  bottom: calc((var(--rd-en-lh) - 22px) / 2);
  margin-left: 0;
}

/* 段级「本段对照」按钮（.para-cn-btn）2026-09-19 整套删除 ——
 * 一句一行之后，每段尾巴那行小字既把段落重新切碎，又和「点句出译文」重复入口。
 * 相关的 cn-open / paraOpen / case "para-cn" 在 app.js 里一并移除。 */

/* ---------- 正文内嵌配图 ---------- */
.read-body .para-img {
  margin: 4px 0;
  display: flex; flex-direction: column; gap: 9px;
  animation: peekIn .3s ease;
}
.read-body .para-img img {
  width: 100%; height: auto; display: block;
  border-radius: 14px;
  background: var(--brand-deep);
  box-shadow: 0 6px 18px rgba(20, 20, 43, .10);
}
.read-body .para-img figcaption {
  display: flex; gap: 7px;
  font-size: 11.5px; line-height: 17px; color: var(--text-3);
  padding-left: 1px;
  flex-wrap: wrap;
}
.read-body .para-img figcaption .caption-cn {
  flex-basis: 100%; color: var(--text-2); font-family: var(--font-cn);
}
.read-body .para-img figcaption::before {
  content: ""; flex: none;
  width: 13px; height: 1px; background: var(--text-3);
  margin-top: 8px; opacity: .55;
}

.read-finish {
  margin: 24px var(--rd-pad) 8px;
  padding: 20px;
  background: linear-gradient(135deg, #F1EFFE 0%, #FBFAFF 100%);
  border-radius: 18px;
  display: flex; flex-direction: column; gap: 14px;
  align-items: center; text-align: center;
}
.read-finish .ico {
  width: 48px; height: 48px; border-radius: 24px;
  background: var(--brand); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.read-finish h3 { font-size: 16px; font-weight: 700; color: var(--text-1); }
.read-finish p { font-size: 12px; color: var(--text-2); line-height: 18px; }
.read-finish .btn {
  width: 100%; height: 46px; border-radius: 14px;
  background: linear-gradient(135deg, var(--brand-2) 0%, var(--brand) 100%);
  color: #fff;
  font-size: 14px; font-weight: 600; cursor: pointer;
  border: 0;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  box-shadow: var(--shadow-3);
  transition: filter .18s ease, transform .12s ease;
}
.read-finish .btn:hover { filter: brightness(1.07); }
.read-finish .btn:active { transform: translateY(1px); }

/* 读完之后：返回列表 / 下一篇（次级动作，不与「打卡」抢视觉） */
.finish-nav {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  width: 100%; padding-top: 4px;
  border-top: 1px solid var(--brand-soft);
}
.finish-nav button {
  height: 40px; border-radius: 12px; border: 0;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-family: var(--font-cn); font-size: 12.5px; font-weight: 600;
  color: var(--brand); background: rgba(255, 255, 255, .72);
  box-shadow: inset 0 0 0 1px var(--brand-soft);
  cursor: pointer; transition: background .18s, color .18s;
}
.finish-nav button:hover { background: var(--brand); color: #fff; }
.finish-nav button[disabled] { color: var(--text-3); box-shadow: inset 0 0 0 1px var(--line); cursor: default; }
.finish-nav button[disabled]:hover { background: rgba(255,255,255,.72); color: var(--text-3); }
.screen.rt-night .finish-nav button { background: rgba(255,255,255,.06); }
.screen.rt-paper .finish-nav button { background: rgba(255,255,255,.55); }
.finish-like {
  min-height: 44px; padding: 10px 18px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card); color: var(--text-2); font: 600 13px var(--font-cn); cursor: pointer;
}
.finish-like[aria-pressed="true"] { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); }

.fab-bar {
  position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 12px; z-index: 50;
  background: rgba(255,255,255,.86);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  padding: 8px 12px; border-radius: 36px;
  box-shadow: 0 8px 32px rgba(60,40,180,.18);
  border: 1px solid rgba(255,255,255,.5);
}
.fab-bar button {
  width: 44px; height: 44px; border-radius: 22px;
  background: #fff;
  display: flex; align-items: center; justify-content: center;
  border: 0; cursor: pointer;
  color: var(--text-2);
}
.fab-bar button.fab-main {
  width: auto; min-width: 64px; padding: 0 12px; gap: 6px;
  border-radius: 18px; font-family: var(--font-cn); font-size: 12px; font-weight: 600;
}
.fab-dots { font-family: var(--font-num); font-size: 15px; font-weight: 700; letter-spacing: 1px; line-height: 1; }
.fab-bar button.active { background: var(--brand); color: var(--bg); }
.fab-bar button:hover { background: var(--brand-soft); }
.fab-bar button.active:hover { background: var(--brand); }
/* 阅读设置入口用「Aa」字样：齿轮/太阳图标在这个尺寸下会读成「亮度」，
   而它管的是字号 + 对照 + 底色三件事 */
.fab-aa { font-family: var(--font-read); font-weight: 700; font-size: 16px; line-height: 1; letter-spacing: .5px; }
/* 朗读控制：全文朗读时 fab-bar 从「工具条」切成「播放器」。
   刻意复用同一个浮层 —— 另起一条控制栏等于再往正文上压一层，
   而 fab-bar 本身已经会挡住进页时的第一句（见 1327 行那条 padding 说明）。 */
.fab-speak { display: none; align-items: center; gap: 4px; }
.fab-bar.speaking > button { display: none; }
.fab-bar.speaking .fab-speak { display: flex; }
.fab-prog {
  font-family: var(--font-num); font-size: 12.5px; font-weight: 700;
  color: var(--text-2); min-width: 44px; text-align: center;
  font-variant-numeric: tabular-nums;   /* 进度从 9/42 跳到 10/42 时数字不等宽会左右晃 */
}
.fab-speak .ic-play { display: none; }
.fab-bar.paused .ic-pause { display: none; }
.fab-bar.paused .ic-play { display: block; }

.read-source-link {
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--brand); font-size: 11px; font-weight: 500;
  text-decoration: none;
  margin-top: 2px;
}
.read-source-link:hover { text-decoration: underline; }

.kw.known {
  color: var(--text-3); font-weight: 400;
  text-decoration: none;
}

/* ---------- 查词浮层 ---------- */
.sheet-mask {
  position: absolute; inset: 0;
  background: rgba(10, 10, 20, .45);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  z-index: 40;
  animation: fade .2s ease;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
/* 阅读设置面板要让正文当预览：遮罩只压暗一点、不模糊。
   默认遮罩带 blur(3px)，那样「改一下就看见效果」会变成隔着毛玻璃猜。 */
.sheet-mask.soft {
  background: rgba(10, 10, 20, .18);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}

.sheet {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: var(--card);
  border-radius: 28px 28px 0 0;
  padding: 12px 20px 24px;
  z-index: 50;
  display: flex; flex-direction: column; gap: 12px;
  animation: up .26s cubic-bezier(.3, .8, .3, 1);
  max-height: 76%;
  overflow-y: auto;
  scrollbar-width: none;
  box-shadow: 0 -14px 44px rgba(15, 17, 51, .22);
}
.sheet::-webkit-scrollbar { display: none; }
@keyframes up { from { transform: translateY(100%); } to { transform: translateY(0); } }
.sheet .grip { width: 36px; height: 4px; border-radius: 2px; background: var(--border); margin: 0 auto; }
.sheet .w { font-family: var(--font-en); font-weight: 700; font-size: 24px; }
.sheet .ph { font-family: var(--font-en); font-size: 13px; color: var(--text-3); }
.sheet .df { font-size: 15px; line-height: 22px; }
.sheet .df.pre { white-space: pre-line; }   /* 点词轻量卡：ECDICT 释义按义项分行 */
.sheet .rt { font-size: 12px; color: var(--text-2); line-height: 19px; }

.sheet-btns { display: flex; gap: 8px; }
.sheet-btns button {
  flex: 1; height: 48px; border: 0; border-radius: 14px; padding: 0 6px;
  font-family: var(--font-cn); font-size: 13px; font-weight: 600; cursor: pointer;
}
.sheet-btns .a { background: var(--brand); color: #fff; }
.sheet-btns .b { background: var(--card-2); color: var(--text); font-weight: 500; }
.sheet-btns .c { background: var(--card-2); color: var(--text-2); font-weight: 500; }
.sheet-btns .c[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand); }

/* 阅读设置浮层：字号 / 底色 / 词汇高亮直接点选。
 * 面板压在正文上方但正文照常可见 —— 改一下就当下看到效果，不用来回开关面板。 */
.rd-set { display: flex; flex-direction: column; gap: 14px; }
.rd-set .rd-row { display: flex; flex-direction: column; gap: 7px; }
.rd-set .rd-lab { font-family: var(--font-cn); font-size: 12px; color: var(--text-2); }
.rd-set .rd-segs { display: flex; gap: 6px; }
.rd-set .rd-seg {
  flex: 1; height: 40px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card-2); color: var(--text-2);
  font-family: var(--font-cn); font-size: 13px; font-weight: 500; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.rd-set .rd-seg.on { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
/* 旧版阅读设置面板的四档高亮样式留给兼容布局；当前独立词源开关使用下方纵向列表。 */
.rd-set .rd-segs.four { gap: 5px; }
.rd-set .rd-segs.four .rd-seg { height: 36px; font-size: 12px; border-radius: 10px; white-space: nowrap; }
.hl-master {
  width: 100%; min-height: 54px; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card-2); color: var(--text-1); text-align: left; cursor: pointer;
  font-family: var(--font-cn);
}
.hl-master > span:first-child { display: flex; flex-direction: column; gap: 3px; }
.hl-master b { font-size: 13px; line-height: 18px; }
.hl-master i { color: var(--text-3); font-size: 11px; line-height: 16px; font-style: normal; font-weight: 400; }
.hl-master-state { flex: none; min-width: 52px; padding: 5px 9px; border-radius: 999px; background: var(--card); color: var(--text-3); font-size: 11px; text-align: center; }
.hl-master.on { border-color: var(--brand); background: var(--brand-soft); }
.hl-master.on .hl-master-state { background: var(--brand); color: var(--bg); }
.hl-sources-label { margin: 10px 2px 2px; color: var(--text-2); font-size: 11px; }
.hl-sources[aria-disabled="true"] { opacity: .5; }

/* ---------- 排序面板 ---------- */
.sort-opt {
  display: flex; align-items: center; justify-content: space-between;
  height: 46px; padding: 0 16px;
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--card-2); color: var(--text-2);
  font-family: var(--font-cn); font-size: 14px; font-weight: 500; cursor: pointer;
}
.sort-opt.on { background: var(--brand-soft); border-color: transparent; color: var(--brand); font-weight: 600; }

/* ---------- 错词行 ---------- */
.notebook-row {
  display: flex; align-items: center; gap: 10px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 10px 12px;
  box-shadow: var(--shadow-1);
  cursor: pointer;
  transition: box-shadow .18s ease, transform .18s ease;
}
.notebook-row:hover { box-shadow: var(--shadow-2); transform: translateY(-1px); }
.notebook-row .w { font-family: var(--font-en); font-weight: 600; font-size: 13px; }
.notebook-row .p { font-family: var(--font-en); font-size: 10px; color: var(--text-3); }
.notebook-row .d { font-size: 11px; color: var(--text-2); }

/* ---------- 分类胶囊 ---------- */
/* 发现页是纵向长列表：禁止子块在可视区变矮时被 flex 压缩。
   （.discover-feat 自带 overflow:hidden，其自动最小尺寸为 0，之前会被压成 0 高度，
     「今日精选」在任何内容超出屏幕的视口里都完全看不见） */
.view-flow > * { flex: none; }

/* 分类切换栏常驻顶部：滚动到任何位置都能换分类，不用回到页面顶部 */
.cats-wrap {
  position: sticky; top: 0; z-index: 30;
  margin: 0 -20px;
  padding: 6px 20px 10px;
  background: var(--bg);
}
.cats-wrap::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -12px; height: 12px;
  background: linear-gradient(180deg, var(--bg), rgba(0,0,0,0));
  pointer-events: none;
}
.cats { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 0; scrollbar-width: none; }
.cats::-webkit-scrollbar { display: none; }
.cat {
  flex: none;
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--border);
  font-size: 12px; font-weight: 500; color: var(--text-2);
  white-space: nowrap; cursor: pointer;
  font-family: var(--font-cn);
  transition: background .18s ease, color .18s ease, transform .18s ease;
}
.cat.on {
  background: var(--cat, var(--brand));
  border-color: transparent; color: #fff; font-weight: 600;
  box-shadow: 0 6px 16px -6px rgba(20, 20, 60, .5), inset 0 1px 0 rgba(255, 255, 255, .18);
}
.cat:active { transform: scale(.96); }

/* ---------- 发现页：分类入口网格（取代纵向大栏） ---------- */
/* ---------- 分类磁贴（v75 已删）----------
 * 「按分类浏览」磁贴网格随 renderDiscover 里的 catGridHtml 一起删除：
 * 它与顶部分类标签是重复的两套入口，还把文章列表推到第二屏开外。
 * 分类入口现在只有顶部标签一处（见 audit [H4] 残骸守卫）。 */

/* ---------- 搜索框 ---------- */
.search {
  display: flex; align-items: center; gap: 10px;
  height: 44px; padding: 0 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  color: var(--text-3);
  transition: border-color .2s ease, box-shadow .2s ease, color .2s ease;
}
.search:focus-within {
  border-color: var(--brand);
  color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.search input {
  flex: 1; border: 0; outline: 0; background: transparent;
  font-family: var(--font-cn); font-size: 13px; color: var(--text);
}
.search input::placeholder { color: var(--text-3); }

/* ---------- 底部导航 ---------- */
.tabbar { padding: 12px 21px 20px; flex: none; }
.tabbar .pill {
  display: flex;
  height: 62px;
  border-radius: 36px;
  /* 玻璃拟态：滚动内容从下面掠过时有一层柔光，比实心卡片更轻 */
  background: color-mix(in srgb, var(--card) 86%, transparent);
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
  border: 1px solid var(--border);
  padding: 4px;
  box-shadow: var(--shadow-2);
}
.tabbar button {
  flex: 1;
  border: 0; background: transparent; border-radius: 26px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  font-family: var(--font-cn); font-size: 10px; font-weight: 500; letter-spacing: .5px;
  color: var(--text-3); cursor: pointer;
  transition: background .2s ease, color .2s ease, transform .12s ease, box-shadow .2s ease;
}
.tabbar button:active { transform: scale(.95); }
.tabbar button.on {
  background: linear-gradient(135deg, var(--brand-2) 0%, var(--brand) 100%);
  color: #fff;
  box-shadow: 0 6px 16px -6px rgba(108, 92, 231, .6), inset 0 1px 0 rgba(255, 255, 255, .2);
}
.tabbar button svg { display: block; }

/* ---------- Toast ---------- */
.toast {
  position: absolute;
  left: 50%; bottom: 108px;
  transform: translateX(-50%);
  background: rgba(26, 26, 46, .88);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  color: #fff;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 13px;
  z-index: 90;
  animation: up .22s ease;
  white-space: nowrap;
  box-shadow: 0 10px 28px -8px rgba(10, 10, 26, .45);
}
[data-theme="dark"] .toast { background: rgba(242, 242, 247, .95); color: #12121C; }

@media (max-width: 560px) {
  body { padding: 0; align-items: stretch; }
  .phone {
    width: 100%; height: 100vh; height: 100dvh;
    border-radius: 0; box-shadow: none;
    /* 真机上刘海/手势条由系统占位，内容要主动避让 */
    --safe-t: env(safe-area-inset-top, 0px);
    --safe-b: env(safe-area-inset-bottom, 0px);
  }
  .tip { display: none; }

  /* —— 把纵向空间还给正文 ——
     状态栏在这版里已经是空的占位条（桌面预览时充刘海），真机上系统自带状态栏，
     所以只保留安全区高度；底栏和内边距同步收窄。 */
  .statusbar { height: max(10px, var(--safe-t)); padding: 0 12px; }
  .view { padding: 2px 16px 6px; gap: 11px; }
  /* 阅读页滚动区必须保留 .fab-bar（z-index:50，可点击）的底部空间，
     否则读毕卡的「下一篇」沉到工具条底下被拦住点击 */
  .view.read-scroll { padding-bottom: 110px; }
  .tabbar { padding: 8px 16px calc(10px + var(--safe-b)); }
  .tabbar .pill { height: 56px; }
  .answer-btn { height: 48px; font-size: 13.5px; }
  .sheet { padding-bottom: calc(24px + var(--safe-b)); }

  .example-box { padding: 10px; gap: 5px; }
  .example-box .en { font-size: 12.5px; line-height: 19px; }
  .example-box .cn { font-size: 12px; line-height: 18px; }
}

/* 宽屏不再把内容锁在 390px 手机壳里：保留圆角作为预览容器，正文限制阅读行长，
   让 1280px 桌面有真正可读的版心；移动端规则仍由上面的媒体查询接管。 */
@media (min-width: 900px) {
  body { padding: 36px clamp(24px, 5vw, 80px); align-items: flex-start; }
  .phone {
    width: min(1080px, 100%);
    height: min(900px, calc(100vh - 72px));
    border-radius: 26px;
    box-shadow: 0 28px 70px -24px rgba(20, 22, 60, .42), 0 0 0 6px #171724;
  }
  .screen > .view { width: 100%; max-width: 1040px; align-self: center; }
  .read-cover { max-width: 860px; }
  .cats, .cats-wrap { max-width: 100%; }
}

/* ---------- 阅读页：护眼 / 夜间主题（只染阅读页） ---------- */
.screen { transition: background .35s ease; }
.screen.rt-paper {
  --brand-soft: rgba(176, 132, 38, .14);
  --bg: #F6EFDD; --card: #FDF8E8; --card-2: #F0E6CC;
  --text: #4A4030; --text-1: #362E20; --text-2: #7A6A50; --text-3: #A89878;
  --line: #E7DBBE; --border: #DDCEAA;
  background: #F6EFDD;
}
.screen.rt-paper .read-finish { background: linear-gradient(135deg, #EFE3C2 0%, #FBF4DE 100%); }
.screen.rt-paper .peek-hint { background: rgba(176, 132, 38, .12); color: #8A6D2F; }
.screen.rt-paper .fab-bar { background: rgba(253, 248, 232, .9); border-color: rgba(255,255,255,.6); }
.screen.rt-paper .fab-bar button { background: #FDF8E8; }
.screen.rt-paper .read-hud { color: #6B5A3A; }
.screen.rt-paper .st-chip { background: rgba(253, 248, 232, .78); border-color: rgba(176, 132, 38, .18); }
.screen.rt-paper .kw,
.screen.rt-paper .word.wb { background: rgba(176, 132, 38, .10); color: #8A6D2F; }

.screen.rt-night {
  --brand: #B0A4FF; --brand-soft: rgba(176, 164, 255, .18);
  --bg: #15151E; --card: #1E1E2A; --card-2: #262633;
  --text: #ECEAF5; --text-1: #F4F2FB; --text-2: #B0ACC4; --text-3: #7C7888;
  --line: #2A2A38; --border: #2E2E3C;
  background: #15151E;
}
.screen.rt-night .read-finish { background: linear-gradient(135deg, #22222E 0%, #1A1A24 100%); }
.screen.rt-night .peek-hint { background: rgba(176, 164, 255, .14); color: #B0A4FF; }
.screen.rt-night .fab-bar { background: rgba(30, 30, 42, .88); border-color: rgba(255,255,255,.06); }
.screen.rt-night .fab-bar button { background: #262633; }
.screen.rt-night .fab-bar button.active { background: var(--brand); }
.screen.rt-night .read-hud { color: #B0ACC4; }
.screen.rt-night .st-chip { background: rgba(38, 38, 51, .85); border-color: rgba(176, 164, 255, .18); color: #C8C2E4; }
.screen.rt-night .kw,
.screen.rt-night .word.wb { background: rgba(176, 164, 255, .14); color: #C8C2FF; }
.screen.rt-night .read-body .para .cn { background: rgba(176, 164, 255, .06); border-color: #B0A4FF; }
.screen.rt-night .read-cover::after { background: linear-gradient(180deg, transparent 50%, rgba(0,0,0,.4) 100%); }

/* ---------- 阅读设置入口（Aa）三主题强化（2026-09-26） ----------
 * 用户原话：Aa 按钮和浮动工具栏都太「通透」，浅色 / 护眼下不突出。它管的是阅读排版，
 * 是三个按钮里的主入口，改成「接近实色的底盘 + 高对比文字 + 一圈淡边框」的稳定盘子；
 * Aa 旁加一枚很小的调节（滑杆）图标点出「设置」语义 —— 不用齿轮，那是整个 App 的设置。
 * 用 var(--text-1) / var(--bg) 这对互为反色的 token：三套阅读主题（默认 / 护眼 rt-paper /
 * 夜间 rt-night）各自自动反转，不靠 hover 也一眼可辨。editorial.css 全站覆盖了这套
 * token（--text-1 是墨绿 #1c2c25、--bg 是暖白 #f8f7f3），所以按钮天然带着阅读页自己的
 * 纸墨配色。rt-paper / rt-night 的按钮各有通配底色（上面两条 0,3,1 规则），这里必须
 * 带上主题选择器（0,4,1）才压得住它们。active（用户调过字号 / 底色）回到品牌色底盘，
 * 字色用 var(--bg)，在夜间浅紫品牌底上也是高对比。 */
.fab-bar button.read-set,
.screen.rt-paper .fab-bar button.read-set,
.screen.rt-night .fab-bar button.read-set {
  background: var(--text-1);
  color: var(--bg);
  border: 1px solid rgba(128, 128, 140, .28);
  gap: 4px;
}
.fab-bar button.read-set:hover,
.screen.rt-paper .fab-bar button.read-set:hover,
.screen.rt-night .fab-bar button.read-set:hover {
  background: var(--text-1);
  color: var(--bg);
  filter: brightness(1.18);
}
.fab-bar button.read-set.active,
.screen.rt-paper .fab-bar button.read-set.active,
.screen.rt-night .fab-bar button.read-set.active {
  background: var(--brand); color: var(--bg); border-color: transparent;
  /* active 的字色用 var(--bg) 不用 #fff：夜间阅读主题的 --brand 是浅紫 #B0A4FF、
     深 App 主题下是浅绿 #b4cfb6 —— 白字只有 2.2:1，深底色字三套主题全都 ≥7:1。 */
}
.fab-bar button.read-set.active:hover,
.screen.rt-paper .fab-bar button.read-set.active:hover,
.screen.rt-night .fab-bar button.read-set.active:hover {
  background: var(--brand); color: var(--bg); filter: none;
}

/* ---------- 发现页：精选 + 分类分栏 ---------- */
.discover-feat {
  border-radius: 20px; overflow: hidden;
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-2);
  cursor: pointer;
  display: flex; flex-direction: column;
  transition: transform .2s ease, box-shadow .2s ease;
}
.discover-feat:hover { transform: translateY(-2px); box-shadow: 0 4px 10px rgba(15,17,51,.06), 0 20px 40px -12px rgba(15,17,51,.16); }
.discover-feat:active { transform: translateY(0) scale(.995); }
.discover-feat .feat-cover {
  height: 196px; position: relative; overflow: hidden;
  background-size: cover; background-position: center;
}
.discover-feat .feat-cover.has-img { height: 218px; }
.discover-feat .feat-when {
  position: absolute; top: 14px; right: 14px;
  background: rgba(20, 20, 43, .5); color: #fff;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 999px;
  z-index: 2; letter-spacing: .3px;
}
.discover-feat .feat-cover::after {
  content:""; position:absolute; inset:0;
  background: linear-gradient(180deg, transparent 30%, rgba(0,0,0,.55) 100%);
  pointer-events: none;
}
.discover-feat .feat-mark {
  position:absolute; top:14px; left:14px;
  background: rgba(255,255,255,.92); color: #1A1A2E;
  font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 999px;
  z-index: 2; letter-spacing: .3px;
}
/* 封面上的标题组：英文主标题 + 中文小字。绝对定位在容器上，
   这样中文行有或没有，底边都对得齐封面下沿。 */
.discover-feat .feat-titles {
  position: absolute; left: 16px; right: 16px; bottom: 14px;
  z-index: 2; pointer-events: none;
  display: flex; flex-direction: column; gap: 4px;
}
.discover-feat .feat-title {
  color:#fff; font-size: 19px; font-weight: 700; line-height: 25px;
  text-shadow: 0 1px 8px rgba(0,0,0,.35);
  font-family: var(--font-read);
  /* 加了中文行后标题组变高，英文最多三行，防止长标题把中文行顶出封面 */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.discover-feat .feat-title-zh {
  color: rgba(255,255,255,.92);
  font-size: 12.5px; font-weight: 500; line-height: 18px;
  font-family: var(--font-cn);
  text-shadow: 0 1px 7px rgba(0,0,0,.6);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.discover-feat .feat-body {
  padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 10px;
}
.discover-feat .feat-cta {
  align-self: flex-start;
  background: var(--brand); color: #fff;
  border: 0; border-radius: 999px;
  padding: 8px 16px; font-size: 12px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer;
}
.cat-section { display: flex; flex-direction: column; gap: 12px; }
.cat-section .cat-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 2px 2px;
}
.cat-section .cat-head .left {
  display: flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 700; color: var(--text-1);
}
.cat-section .cat-head .left .ic {
  width: 28px; height: 28px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; flex: none;
}
.cat-section .cat-head .left .meta { font-size: 11px; color: var(--text-3); font-weight: 500; margin-left: 2px; }
.cat-section .cat-head .more {
  font-size: 12px; color: var(--text-2); cursor: pointer;
  display: inline-flex; align-items: center; gap: 2px;
}
.cat-section .cat-head .more:hover { color: var(--brand); }

/* 完成页反馈：理解体验 + 文章喜好（喂难度模型与推荐模型） */
.fb-block { display: flex; flex-direction: column; gap: 8px; padding: 12px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.fb-row { display: flex; align-items: center; gap: 8px; }
.fb-l { font-size: 12px; color: var(--text-2); flex: none; width: 56px; }
.fb-segs { display: flex; gap: 6px; flex-wrap: wrap; }
.fb-seg {
  border: 1px solid var(--border); background: var(--card); border-radius: 999px;
  padding: 5px 12px; font-size: 12px; color: var(--text-2); cursor: pointer;
  font-family: var(--font-cn); transition: all .15s;
}
.fb-seg.on { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }

/* 阅读工具 sheet 条目 */
.sheet-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 12px 6px; border: 0; border-bottom: 1px solid var(--line);
  background: transparent; color: var(--text-1); font-size: 14px;
  font-family: var(--font-cn); cursor: pointer; text-align: left; text-decoration: none;
}
.sheet-item:last-child { border-bottom: 0; }
.sheet-item:active { background: var(--brand-soft); }

/* FAB 随滚动方向淡出 */
.fab-bar { transition: opacity .25s, transform .25s; }
.fab-bar.hide { opacity: 0; transform: translateY(18px); pointer-events: none; }

/* 正文只保留一种「值得注意」的视觉语义。生词本和所选词库命中的词虽然在
 * 数据上仍分别使用 wb / kw，正文中统一为同一种品牌色和同一种底纹；已认识
 * 仍由 JS 的互斥优先级恢复普通正文。 */
.word.kw,
.word.wb {
  color: var(--brand);
  background: var(--brand-soft);
  font-weight: 650;
}
/* 总开关只隐藏显示，不清空 hlSets，也不删除生词本。 */
.read-scroll.no-kw .word.kw,
.read-scroll.no-kw .word.wb {
  color: inherit;
  background: transparent;
  font-weight: inherit;
}

/* 查词卡 / 词汇页里的「本句含义」块：把词典释义落到具体那句话上 */
.ctx {
  display: flex; flex-direction: column; gap: 4px;
  background: var(--card-2); border-radius: var(--r-sm);
  padding: 10px 12px;
}
.ctx-lab {
  font-family: var(--font-cn); font-size: 11px; font-weight: 600;
  color: var(--text-3); letter-spacing: .3px;
}
.ctx-en { font-family: var(--font-en); font-size: 13.5px; line-height: 20px; color: var(--text-1); }
.ctx-cn { font-size: 12px; line-height: 19px; color: var(--text-2); }
/* 句中目标词：与例句库共用 .w-hl，但语境块里用琥珀色与生词色呼应 */
.ctx .w-hl, .nb-ctx .w-hl {
  background: none; color: var(--amber); font-weight: 700;
}

/* 词汇页：两个 Tab（生词 / 已认识）。
 * 刻意不做「需要重点学习」这类分级 —— 遇到过几次、查过几次都只是行为的副产品，
 * 不构成任何可靠的掌握度证据，硬造一个榜单只会误导。 */
.vocab-tabs { display: flex; gap: 8px; }
.vt {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
  font-family: var(--font-cn); font-size: 13px; font-weight: 600;
  color: var(--text-2); background: var(--card);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 10px 12px; cursor: pointer; transition: all .15s;
}
.vt b { font-family: var(--font-num); font-size: 13px; font-weight: 700; color: var(--text-3); }
.vt.on { color: var(--brand); border-color: var(--brand); background: var(--brand-soft); }
.vt.on b { color: var(--brand); }

/* 词汇高亮词源：独立复选开关只出现在 Aa 阅读设置。
 * 方形勾选标记用 border + ::after 绘制，不依赖图片或系统符号。 */
.hl-list { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
.hl-opt {
  display: flex; align-items: flex-start; gap: 10px; width: 100%;
  padding: 9px 10px; border: 1px solid transparent; border-radius: 10px;
  background: transparent; cursor: pointer; text-align: left;
  font-family: var(--font-cn); color: var(--text-1);
}
.hl-opt:active { background: var(--brand-soft); }
.hl-opt.on { background: var(--brand-soft); border-color: var(--brand-2, var(--brand)); }
.hl-dot {
  width: 15px; height: 15px; border-radius: 50%; flex: 0 0 auto;
  border: 1.5px solid var(--text-3); margin-top: 2px; position: relative;
}
.hl-opt[role="checkbox"] .hl-dot { border-radius: 4px; }
.hl-opt.on .hl-dot { border-color: var(--brand); }
.hl-opt.on .hl-dot::after {
  content: ""; position: absolute; inset: 3px; border-radius: 2px; background: var(--brand);
}
.hl-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.hl-txt b { font-size: 13px; font-weight: 600; line-height: 19px; }
.hl-opt.on .hl-txt b { color: var(--brand); }
.hl-txt i { font-style: normal; font-size: 11px; line-height: 16px; color: var(--text-3); }
/* 生词条目里的原句：复习的锚点，不是装饰 —— 所以字号跟正文保持可读性 */
.nb-ctx {
  margin-top: 6px; padding: 8px 10px; border-radius: 10px;
  background: var(--card-2); display: flex; flex-direction: column; gap: 3px;
}
.nb-ctx-en { font-family: var(--font-en); font-size: 12.5px; line-height: 18px; color: var(--text-1); }
.nb-ctx-cn { font-size: 11.5px; line-height: 17px; color: var(--text-2); }

.nb-known-tag {
  font-family: var(--font-cn); font-size: 10.5px; font-weight: 600;
  color: var(--green); background: var(--green-bg);
  border-radius: 999px; padding: 1px 7px;
}


/* 收藏入口只出现在当前选中句的留白中，不进入英文行盒。 */
.para-note { display: none; position: absolute; right: -16px;
  bottom: calc((var(--rd-en-lh) - 22px) / 2 + 26px);
  width: 22px; height: 22px; align-items: center; justify-content: center;
  border-radius: 11px; color: var(--brand); cursor: pointer; }
.sentence.sel > .para-note { display: inline-flex; }
.para-note:hover, .para-note:focus-visible { background: var(--brand-soft); outline: 2px solid var(--brand); }
.quote-list { display: grid; gap: 16px; }
.quote-card { display: flex; flex-direction: column; gap: 12px; }
.quote-en { font-family: var(--font-en); font-size: 17px; line-height: 1.65; margin: 0; overflow-wrap: anywhere; }
.quote-cn { color: var(--text-2); font-size: 14px; line-height: 1.8; margin: 0; overflow-wrap: anywhere; }
.quote-thought { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 14px; line-height: 1.8;
  margin: 0; padding: 12px; background: var(--brand-soft); border-radius: 10px; }
.quote-source { color: var(--text-3); font-size: 12px; line-height: 1.6; overflow-wrap: anywhere; }
.quote-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.quote-actions .ghost-btn { min-height: 40px; }
.quote-actions button:disabled { opacity: .6; cursor: default; }
.quote-actions .danger { margin-left: auto; }
.quote-preview { max-height: 25vh; overflow-y: auto; display: grid; gap: 10px; }
.quote-thought-input { box-sizing: border-box; width: 100%; resize: vertical; min-height: 108px;
  border: 1px solid var(--border); border-radius: 12px; padding: 12px;
  font: inherit; line-height: 1.7; font-size: 16px; color: var(--text); background: var(--bg); }
.quote-thought-input:focus { outline: 2px solid var(--brand); outline-offset: 2px; }
.quote-editor .sheet-btns > button { flex: 1; }

/* 我的 → 数据与备份：同步配置 */
.sync-field { box-sizing: border-box; width: 100%; min-width: 0; min-height: 44px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--card); color: var(--text-1); font: inherit; font-size: 16px; }
.sync-field:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
[data-act="sync-save"] { height: 54px; border: 1px solid var(--border); border-radius: 8px;
  background: transparent; color: var(--text-2); font-family: var(--font-cn);
  font-size: 16px; font-weight: 600; cursor: pointer; }
.sync-field:disabled, [data-act="sync-save"]:disabled, [data-act="sync-now"]:disabled { opacity: .6; cursor: wait; }
