:root {
  /* 纸与墨。原来的暖黄底（#f7f3ea）铺满整屏会发闷，往灰里收一点，
     接近生宣的手感，久看眼睛更松。赭红保留——那是印章，是这个站的识别。 */
  --bg: #f4f1e9;
  --surface: #fffefb;
  --surface-2: #ece7db;
  --ink: #16140f;
  --ink-2: #3c382f;
  --muted: #7e7664;
  --line: #e3ddcc;
  --line-strong: #cfc6ae;
  --accent: #9a2d21;
  --accent-2: #b24234;
  --accent-soft: #f3e2dc;
  /* 侧栏选中行用这层「淡墨」而不是 accent-soft。整行铺满粉调太重，
     白天看着像贴了一张便签；改成低彩度的暖灰，靠左侧竖线和字色说「当前在这」。 */
  --sel: #e7e1d1;
  --gold: #9d7c3c;

  /* 阴影改成两层极淡：贴边一层定形，远处一层铺开。
     单层重投影是廉价感最直接的来源。 */
  --shadow: 0 1px 2px rgba(40, 32, 18, .05), 0 16px 36px -20px rgba(40, 32, 18, .30);
  --radius: 8px;
  /* 顶栏高度做成变量：吸顶后的工具栏 / 侧栏都要按它算偏移，
     写死三处 60px 迟早有一处漂移。 */
  --topbar-h: 60px;

  /* 字阶只留六档。原来从 10 到 30 散着十八个中间值，
     那不是阶梯，是噪声。 */
  --t-xs: 11px;
  --t-sm: 12.5px;
  --t-base: 14px;
  --t-md: 16px;
  --t-lg: 20px;
  --t-xl: 28px;

  /* 间距一律取 4 的倍数，别再各写 9、11、13 */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;

  --r-sm: 4px; --r: 8px; --r-lg: 14px;

  /* 动效只留一条曲线。位移一律 ≤2px——多出来那 1px 就是「廉价」的味道。 */
  --ease: cubic-bezier(.2, .72, .3, 1);
  --quick: 140ms;

  --serif: "Songti SC", "STSong", "Noto Serif SC", "Source Han Serif SC", "SimSun", "Times New Roman", serif;
  --sans: "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", "Segoe UI", system-ui, sans-serif;
}

[data-theme="dark"] {
  --bg: #12110d;
  --surface: #1a1813;
  --surface-2: #232019;
  --ink: #f2ecdd;
  --ink-2: #cdc5b3;
  /* 小字（11–12px 的顶栏标签、「共 X 部」、卡片底部平台名）在 #1a1813 上
     需要 5:1 才稳；原来的 #8a8271 只有约 4.5:1，刚过线，久看发灰。 */
  --muted: #9a9382;
  --line: #302b22;
  --line-strong: #443d30;
  --accent: #d0655a;
  --accent-2: #e07d72;
  --accent-soft: #33211d;
  --sel: #2a2419;
  --gold: #c2a068;
  --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 18px 40px -22px rgba(0, 0, 0, .85);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-base);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* 纸面的暖光。原来 .5 的强度让整页像蒙了一层膜，收淡一些只留一点呼吸。 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: .34;
  background-image: radial-gradient(circle at 18% 12%, rgba(165, 130, 74, .10), transparent 42%),
    radial-gradient(circle at 82% 0%, rgba(156, 47, 36, .07), transparent 38%);
}

button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: #fff; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* 内容宽度从 1320 收到 1280：宽比收窄一点，两侧留白就出来了，
   这是「聚拢」和「摊平」的分界。 */
.wrap { width: min(1280px, 100%); margin: 0 auto; padding: 0 32px; }
.serif { font-family: var(--serif); }

/* ---------- 顶栏 ---------- */
/* 高度从 68 收到 60：顶栏是工具，不是招牌，别占纵向空间。
   背景用 92% 纸色 + 更重的模糊，滚到内容上时是「蒙住」而不是「盖住」。 */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(18px) saturate(1.2);
  border-bottom: 1px solid var(--line);
}
.topbar-in {
  height: var(--topbar-h);
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s5);
}
.brand { display: flex; align-items: center; gap: 10px; flex: none; }
.seal {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 1.5px solid var(--accent);
  color: var(--accent);
  border-radius: var(--r-sm);
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1;
  letter-spacing: 0;
}
.brand-name { font-family: var(--serif); font-size: 17.5px; letter-spacing: .1em; }
.brand-sub { display: block; font-size: 9px; letter-spacing: .24em; color: var(--muted); text-transform: uppercase; margin-top: 1px; }

.searchbox {
  flex: 1;
  max-width: 520px;
  position: relative;
  display: flex;
  align-items: center;
}
.searchbox svg { position: absolute; left: 12px; width: 16px; height: 16px; color: var(--muted); transition: color var(--quick) var(--ease); }
.searchbox input {
  width: 100%;
  height: 36px;
  padding: 0 72px 0 35px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  outline: none;
  font-size: var(--t-base);
  transition: border-color var(--quick) var(--ease), box-shadow var(--quick) var(--ease), background var(--quick) var(--ease);
}
.searchbox input::placeholder { color: var(--muted); }
.searchbox input:focus { border-color: var(--accent); background: var(--surface); box-shadow: 0 0 0 3px var(--accent-soft); }
.searchbox:focus-within svg { color: var(--accent); }
.searchbox kbd {
  position: absolute; right: 9px;
  font-family: var(--sans); font-size: 10.5px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 3px; padding: 1px 5px; background: var(--bg);
}
.topnav { display: flex; align-items: center; gap: 2px; margin-left: auto; }
/* 「更多」入口与浮层：桌面不出现，≤720 用它把作者 / 随机 / 成就 / 统计收起来。
   七个纯图标挤一行时没有一个能自解释，最右边那个还贴着屏幕边。

   两条 2026-11-06 的修复，改任意一条前请先读：
   ① 选择器必须带 .topnav 前缀。原来写裸 `.morebtn { display:none }`，与紧随其后的
      `.tbtn { display:inline-flex }` 特异性相同、位置更早，被覆盖成 flex —— 桌面端
      因此多出一个三个点按钮，而浮层的 display:block 只在 ≤720 的媒体查询里，
      点它永远只会改 aria-expanded、界面上什么都不出现（用户判定为「点了没反应」）。
      `.topnav .morebtn` 特异性 (0,2,0) 高于 `.tbtn` (0,1,0)，不受规则顺序影响。
   ② 浮层改成「默认 display:block + [hidden] 兜底」而不是「默认 none + 媒体查询打开」。
      显隐由 JS 的 hidden 属性独占，任何宽度下只要设为可见就能真正看见，
      不会再出现「状态变了、画面没变」。 */
.topnav .morebtn { display: none; }
.moremenu {
  display: block; position: absolute; top: calc(100% - 4px); right: 0; z-index: 60;
  min-width: 148px; padding: 6px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow);
}
/* 作者样式会覆盖 UA 的 [hidden]{display:none}，必须显式声明回来 */
.moremenu[hidden] { display: none; }
.moremenu button {
  display: block; width: 100%; text-align: left; padding: 9px 12px;
  font-size: 13px; color: var(--ink-2); border-radius: var(--r-sm);
}
.moremenu button:hover { background: var(--surface-2); color: var(--ink); }
.tbtn {
  height: 32px; padding: 0 10px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--ink-2); font-size: 13px; white-space: nowrap;
  transition: background var(--quick) var(--ease), color var(--quick) var(--ease);
}
.tbtn:hover { background: var(--surface-2); color: var(--ink); }
.tbtn:active { transform: translateY(.5px); }
.tbtn svg { width: 15px; height: 15px; }
.tbtn .count {
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--accent); color: #fff; font-size: 10px;
  display: grid; place-items: center; line-height: 1;
}

/* ---------- 头部 hero ---------- */
/* 全站只在标题这一处用力。字号上限从 68 收到 52、字距收紧，
   宋体大字一旦松就会「虚」，紧一点才立得住。 */
.hero { padding: 56px 0 36px; position: relative; }
.hero h1 {
  font-family: var(--serif);
  font-size: clamp(32px, 4.2vw, 52px);
  line-height: 1.12;
  letter-spacing: .02em;
  margin: 0 0 20px;
  font-weight: 600;
  text-wrap: balance;
}
.hero h1 em { font-style: normal; color: var(--accent); }
.hero p.lead { color: var(--ink-2); max-width: 700px; margin: 0 0 26px; font-size: 15px; line-height: 1.85; }
.hero p.lead b { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.hero-stats { display: flex; flex-wrap: wrap; align-items: center; gap: 0 26px; color: var(--muted); font-size: var(--t-sm); }
.hero-stats b { color: var(--ink); font-family: var(--serif); font-size: 19px; font-weight: 600; margin-right: 4px; font-variant-numeric: tabular-nums; }
.hero-stats .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--line-strong); }
.hero-actions { margin-top: 28px; display: flex; gap: var(--s2); flex-wrap: wrap; }
body.searching .hero { padding: 24px 0 16px; }
body.searching .hero h1 { font-size: 26px; margin-bottom: 0; }
body.searching .hero .lead, body.searching .hero-stats, body.searching .hero-actions { display: none; }
/* 导语折叠按钮只在窄屏出现（桌面那段是品牌叙事，手机上是一堵墙）。 */
.lead-more { display: none; }
@media (max-width: 720px) {
  /* 390×844 的首屏原来从上到下是：品牌 / 图标 / 搜索 / 36px 标题 / 6 行导语 /
     统计 2 行 / 按钮 2 行 / 门类 2 行 / 筛选 3 行——第一本书在 1.5 屏以下。
     用户来是搜书找书的，不是读介绍的，所以这段在窄屏收成两句 + 展开。 */
  .hero { padding: 26px 0 22px; }
  .hero h1 { font-size: clamp(24px, 6.4vw, 32px); margin-bottom: 12px; }
  .hero p.lead {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-size: 13.5px; line-height: 1.7; margin-bottom: 2px;
  }
  .hero p.lead.open { display: block; }
  .lead-more {
    display: inline-block; background: none; border: 0; color: var(--accent);
    font-size: 12px; padding: 4px 0 8px; cursor: pointer;
  }
  .lead-more::after { content: " ⌄"; }
  .lead-more[aria-expanded="true"]::after { content: " ⌃"; }
  /* 统计条从「flex 换行 + 圆点分隔」（会留下「190 位作者 ·」这样的悬空尾巴）
     改成 3 列网格，六项两行，断句自然消失。 */
  .hero-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px 10px; font-size: 11.5px; }
  .hero-stats .dot { display: none; }
  .hero-stats b { font-size: 16px; }
  .hero-actions { margin-top: 16px; flex-wrap: nowrap; }
  .hero-actions .btn { flex: 1 1 0; min-width: 0; justify-content: center; padding: 0 8px; font-size: 12.5px; }
  /* 「看看这座图书馆」与顶栏「更多 → 数据统计」是同一个弹窗，窄屏让位给书。 */
  #openStats2 { display: none; }
  body.searching .lead-more { display: none; }
}
.btn {
  height: 34px; padding: 0 14px; border-radius: var(--r);
  border: 1px solid var(--line-strong); color: var(--ink-2);
  display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px;
  background: var(--surface);
  transition: border-color var(--quick) var(--ease), color var(--quick) var(--ease),
              background var(--quick) var(--ease), transform var(--quick) var(--ease);
}
.btn:hover { border-color: var(--accent); color: var(--accent); }
.btn:active { transform: translateY(.5px); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .14), 0 2px 10px -4px rgba(154, 45, 33, .55); }
.btn.primary:hover { background: var(--accent-2); border-color: var(--accent-2); color: #fff; }
.btn svg { width: 15px; height: 15px; }

/* ---------- 主体布局 ---------- */
/* 这里必须用 clip 而不是 hidden：overflow-x: hidden 会把 body 变成滚动容器，
   顶栏的 position: sticky 就挂在错误的祖先上，表现为「一滚就跟着走」。
   clip 同样裁掉横向溢出，但不产生滚动容器，sticky 照常基于视口计算。 */
html, body { overflow-x: clip; }
@supports not (overflow: clip) {
  html { overflow-x: hidden; }
  body { overflow-x: visible; }
}
/* 侧栏 248px：两列门类每格 (248−4−8)/2 = 118px，文字可用 103px（带滚动条 100），
   「网络小说 224691」是全部门类里唯一的六位数组合，需要 92.7px，仍有 7px 余量。
   主列从 960 降到 928，书目网格仍是 5 列，不亏。 */
.layout { display: grid; grid-template-columns: 248px minmax(0, 1fr); gap: 40px; padding-bottom: 80px; align-items: start; }

/* 顶栏 60px + 16 的空气，侧栏贴着它往下走。
   侧栏是唯一滚动上下文：overscroll-behavior: contain 让滚到底时不把整页拖着走。
   Firefox 的 scrollbar-width: thin 与 WebKit 的 6px 是一对——Windows 上原生 15px
   滚动条会把每格从 118 压到 110 以下，「中国现当代 270」立刻不保。 */
.side { position: sticky; top: 76px; max-height: calc(100vh - 92px); overflow-y: auto; overscroll-behavior: contain; padding-right: 4px; scrollbar-width: thin; }
.side::-webkit-scrollbar { width: 6px; }
.side::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 6px; }
.side-group { margin-bottom: var(--s5); }
.side-title {
  font-size: 10.5px; letter-spacing: .18em; color: var(--muted);
  text-transform: uppercase; margin: 0 0 var(--s2); padding-left: 2px;
  font-weight: 500;
}
details.side-group summary { cursor: pointer; list-style: none; }
details.side-group summary::-webkit-details-marker { display: none; }
details.side-group summary::after { content: " +"; opacity: .6; }
details.side-group[open] summary::after { content: " −"; opacity: .6; }
.catlist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 8px;
  row-gap: 2px;
}

/* ---------- 门类行：常态 ---------- */
.catlist li { min-width: 0; }
.catlist li button {
  width: 100%;
  text-align: left;
  padding: 5px 6px 5px 9px;      /* 左 9：选中竖线占 0–2px，还剩 7px 呼吸 */
  border-radius: 5px;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-2);           /* 10.3:1 */
  font-size: 13px;
  line-height: 20px;             /* 写死，整行 30px，两列逐行对齐 */
  position: relative;
  transition: background var(--quick) var(--ease), color var(--quick) var(--ease);
}

/* 名字：省略号只作为未来兜底，现有数据不触发 */
.catlist .t {
  min-width: 0;                  /* 没有这一行，ellipsis 永远不会生效 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 计数：同行右对齐成列 */
.catlist .n {
  margin-left: auto;
  flex: none;
  font-size: 10.5px;
  line-height: 1;
  color: color-mix(in srgb, var(--ink-2) 78%, var(--bg));   /* #646158，5.5:1 */
  font-variant-numeric: tabular-nums;
}

/* ---------- hover ---------- */
.catlist li button:hover { background: var(--surface-2); color: var(--ink); }

/* ---------- 选中：浅墨底 + 左侧 2px 竖线 ---------- */
.catlist li button.on { color: var(--accent); background: var(--sel); font-weight: 600; }
.catlist li button.on::before {
  content: "";
  position: absolute; left: 0; top: 6px; bottom: 6px;
  width: 2px; border-radius: 1px; background: var(--accent);
}
.catlist li button.on .n { color: var(--accent); }
.catlist li button.on:hover { background: var(--sel); }   /* 选中行 hover 不许被冲淡 */

/* ---------- focus-visible ----------
   outline-offset 必须为负：两列之间只有 8px 间隙，正向外扩 2px 会让相邻两格的
   焦点环贴在间隙里，看着像两格同时被选中。 */
.catlist li button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 5px;
}

/* 暗色主题：--accent 压在 --sel 上只有 4.17:1，换 --accent-2 是 5.38:1。
   左侧 2px 竖线作为非文字元素本就够 3:1，但必须跟着换色——否则一行里会出现
   两个深浅不同的红，比原来的对比度问题更扎眼。 */
[data-theme="dark"] .catlist li button.on,
[data-theme="dark"] .catlist li button.on .n { color: var(--accent-2); }
[data-theme="dark"] .catlist li button.on::before { background: var(--accent-2); }

/* ---------- 「全部书目」：占满整行，下方一道细线 ---------- */
.catlist li.is-all {
  grid-column: 1 / -1;           /* 跨两列 */
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}

/* ---------- 折叠条（原生 details，不做高度动画） ---------- */
.catmore { margin-top: 4px; }

.catmore > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 5px;
  height: 26px;                  /* ≥ WCAG 2.2 的 24×24 */
  padding: 0 9px 0 7px;
  border-radius: 5px;
  font-size: 12.5px;
  color: var(--ink-2);           /* 不用 --muted：交互文字必须 ≥4.5:1 */
  transition: color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.catmore > summary::-webkit-details-marker { display: none; }
.catmore > summary:hover { background: var(--surface-2); color: var(--accent); }
.catmore > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* 箭头：5×5 的直角旋转 45° */
.catmore > summary::after {
  content: "";
  width: 5px; height: 5px; margin: -3px 0 0 2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 180ms var(--ease);
}
.catmore[open] > summary::after { transform: rotate(-135deg); margin-top: 2px; }

.catmore .catlist { margin-top: 4px; }
.catmore #catmore-n { font-variant-numeric: tabular-nums; }

/* 「更多 10 项」/「收起」靠两个 span 切换，不写 JS */
.catmore > summary .less { display: none; }
.catmore[open] > summary .more { display: none; }
.catmore[open] > summary .less { display: inline; }

.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  padding: 4px 9px; border-radius: var(--r-sm); border: 1px solid var(--line);
  font-size: 12px; color: var(--muted); background: transparent;
  transition: border-color var(--quick) var(--ease), color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.chip:hover { border-color: var(--line-strong); color: var(--ink); }
.chip.on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

/* ---------- 工具条 ---------- */
.toolbar {
  display: flex; align-items: center; gap: var(--s3);
  padding: 10px 0 12px; margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
  /* 滚到第 200 张卡片时，用户既看不到「共多少部」也改不了排序，得先回顶。
     贴住顶栏吸顶，代价只有一条 position。背景必须不透明，否则卡片会透上来。 */
  position: sticky; top: var(--topbar-h); z-index: 6;
  background: var(--bg);
}
@media (max-width: 720px) {
  /* 窄屏顶栏是多行的（品牌 / 图标 / 搜索各一行），高度不定，吸顶会和它叠；
     小屏纵向空间也紧，这里不吸。 */
  .toolbar { position: static; padding: 0 0 14px; margin-bottom: 18px; }
}
.result-count { font-size: var(--t-sm); color: var(--muted); }
.result-count b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
/* 「已载入 12%」是副信息：冷层没到时总数仍是全库，这个百分比只说明
   眼前列表覆盖了多少。不能让它比总数更显眼。 */
.count-note { margin-left: 6px; font-size: 11px; color: var(--muted);
  padding: 1px 6px; border: 1px solid var(--line); border-radius: 999px; white-space: nowrap; }
.toolbar .grow { flex: 1; }
.select {
  height: 30px; padding: 0 26px 0 10px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font-size: var(--t-sm); appearance: none; outline: none; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 14px) 13px, calc(100% - 9px) 13px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  transition: border-color var(--quick) var(--ease);
}
.select:hover { border-color: var(--line-strong); }
.viewtoggle { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; }
.viewtoggle button { width: 30px; height: 28px; display: grid; place-items: center; color: var(--muted); transition: background var(--quick) var(--ease), color var(--quick) var(--ease); }
.viewtoggle button:hover { color: var(--ink); }
.viewtoggle button.on { background: var(--surface-2); color: var(--ink); }
.viewtoggle svg { width: 14px; height: 14px; }

/* ---------- 卡片 ---------- */
/* 摘要收到两行：网格里三行小字是噪声，读者扫的是封面和书名。
   需要摘要的时候切列表视图，那里给得下。 */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(206px, 1fr));
  gap: 20px;
}
/* 窗口拉窄时封面跟着缩，而不是死死卡在 206px 上——那样只会先掉列数、
   留下一条大空白，然后突然跳一档。这里用容器查询单位 cqi 以书架这一栏的
   宽度为基准：栏宽 960 时单卡 176（5 列），栏宽 785 时收到 145（仍是 5 列），
   封面始终在 120—160 之间跟着走，不会因为窗口小一点反而变大。
   不支持的浏览器仍走上面那条固定值。 */
@supports (container-type: inline-size) {
  .layout > section { container-type: inline-size; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(clamp(140px, 17cqi, 190px), 1fr)); }
}
/* 卡片是 <a>，不是 <button>：只有真链接才吃得到 ⌘+点击 / 中键「新标签打开」、
   右键「复制链接」，也才能被 Tab 顺序和读屏当成链接念出来。样式上要抹掉
   浏览器给链接的默认下划线与蓝色。 */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 11px;
  display: flex; flex-direction: column;
  transition: transform 180ms var(--ease), box-shadow 180ms var(--ease), border-color 180ms var(--ease);
  position: relative;
  overflow: hidden;
  text-align: left;
  color: inherit;
  text-decoration: none;
}
/* 位移从 3px 收到 2px。上浮越多越像电商促销卡片，少这一点就安静了。 */
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--line-strong); }
.card .coverwrap {
  position: relative; width: 100%; aspect-ratio: 3 / 4.1;
  background: var(--surface-2); border-radius: var(--r-sm); overflow: hidden;
  margin-bottom: 10px;
}
.card .coverwrap img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 520ms var(--ease); }
.card:hover .coverwrap img { transform: scale(1.02); }
.cover-fallback {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  padding: 26px 16px 14px;
  display: flex; flex-direction: column; justify-content: space-between;
  background: var(--cv, #7a4636);
  background-image: linear-gradient(160deg, rgba(255,255,255,.10), rgba(0,0,0,.16)),
    repeating-linear-gradient(90deg, rgba(255,255,255,.035) 0 1px, transparent 1px 4px);
  color: var(--cf, #f3e7d2);
}
.cover-fallback .cf-frame {
  position: absolute; inset: 7px; border: 1px solid currentColor; opacity: .32;
}
.cover-fallback .cf-title {
  font-family: var(--serif); font-size: 21px; line-height: 1.45;
  letter-spacing: .08em; font-weight: 600;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
  text-shadow: 0 1px 0 rgba(0,0,0,.12);
}
.cover-fallback .cf-meta {
  display: flex; justify-content: space-between; gap: 6px;
  font-size: 10px; letter-spacing: .06em; opacity: .8;
}
.book-cover .cf-title { font-size: 27px; }
.relcard .cf-title { display: none; }
.shelf-item .cf-title { font-size: 10px; padding: 0; -webkit-line-clamp: 3; }
.catbox { border: 1px solid var(--line); border-radius: 6px; padding: 10px 14px; font-size: 13px; color: var(--ink-2); }
.catbox summary { cursor: pointer; color: var(--accent); font-size: 12.5px; }
.catbox p { margin: 10px 0 0; line-height: 1.9; }
.relcard .cf-meta, .shelf-item .cf-meta { display: none; }
.relcard .cover-fallback, .shelf-item .cover-fallback { padding: 8px 6px; }
.relcard .cf-frame, .shelf-item .cf-frame { inset: 2px; }
.cover-fallback .cf-author { font-size: 11px; opacity: .7; }
/* 角标不能只在浅色纸上成立：暗色下原来的深灰底与卡片几乎同层，角标消失。
   半透明白底又顶不住米白封面，所以走「深底 + 亮字 + 一道细描边」——
   无论封面深浅都读得清，也不会抢书名的注意力。 */
[data-theme="dark"] .badge-cat {
  background: rgba(14, 12, 9, .72); color: #f0e8d6;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
}
[data-theme="dark"] .badge-rate { background: rgba(245, 240, 228, .9); color: #2a251c; }
/* 暗色下米白封面的书像一块发光的灯箱：一屏 5 本有 3 本在「发光」，
   视线被封面而不是书名抓走。压一点亮度 + 一道极细描边，可辨识但不刺眼。 */
[data-theme="dark"] .card .coverwrap img,
[data-theme="dark"] .rk-cover img,
[data-theme="dark"] .rc-cover img,
[data-theme="dark"] .book-cover img { filter: brightness(.88) contrast(1.02); }
[data-theme="dark"] .card .coverwrap { box-shadow: 0 0 0 1px rgba(255, 255, 255, .06); }
.badge-rate {
  z-index: 3;
  position: absolute; left: 8px; top: 8px;
  background: rgba(20, 18, 14, .78); color: #f6e9c8;
  font-size: 11px; font-variant-numeric: tabular-nums;
  padding: 2px 7px; border-radius: 4px; backdrop-filter: blur(4px);
  display: flex; align-items: center; gap: 3px;
}
.badge-rate::before { content: "★"; color: #e0b464; font-size: 10px; }
.badge-cat {
  z-index: 3;
  position: absolute; right: 8px; top: 8px;
  background: rgba(255, 253, 248, .88); color: #4a4032;
  font-size: 10px; padding: 2px 6px; border-radius: 3px; letter-spacing: .04em;
}
.card h3 {
  font-family: var(--serif); font-size: 15.5px; line-height: 1.45;
  margin: 0 0 3px; font-weight: 600;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card .author { font-size: 11.5px; color: var(--muted); margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 摘要不再叠一层 opacity——那是拿「透明度」当层级，会让小字发灰发虚。
   直接用墨色第二档，清楚但不抢。 */
.card .excerpt {
  font-size: 11.5px; line-height: 1.65; color: var(--ink-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin: 0;
}
.card .cardfoot { margin-top: 8px; min-height: 15px; display: flex; align-items: center; gap: 6px; font-size: 10.5px; color: var(--muted); }
.card .cardfoot .shelfmark { color: var(--accent); }

/* 列表视图 */
/* 「列表」的存在意义是扫读、对比、排序找书。原来的通栏大卡片一行 148px、
   右侧 700px 空白，一屏 3 条，比网格（15 条）还浪费——方向反了。
   改成 60px 上下的紧凑行：封面 | 书名+一行简介 | 作者 | 平台·热度。
   卡内文字包了一层 .cbody，网格视图下它只是普通的纵向容器。 */
.card .cbody { display: flex; flex-direction: column; min-width: 0; }
.grid.list { grid-template-columns: 1fr; gap: 0; }
.grid.list .card {
  flex-direction: row; align-items: center; gap: 12px;
  padding: 7px 10px; border-radius: 0; border-left: 0; border-right: 0; border-top: 0;
  box-shadow: none; background: none;
  transition: background 140ms var(--ease);
}
.grid.list .card:hover { transform: none; background: var(--surface-2); }
.grid.list .coverwrap { width: 34px; flex: none; margin: 0; aspect-ratio: 3/4.1; }
.grid.list .cbody {
  flex: 1; min-width: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) 140px 158px;
  grid-template-areas: "t t a f" "x x a f";
  align-items: center; column-gap: 14px;
}
.grid.list h3 { grid-area: t; font-size: 13.5px; margin: 0; -webkit-line-clamp: 1; }
.grid.list .excerpt { grid-area: x; display: -webkit-box; -webkit-line-clamp: 1; font-size: 11px; }
.grid.list .author { grid-area: a; margin: 0; font-size: 11.5px; }
.grid.list .cardfoot { grid-area: f; margin: 0; justify-content: flex-end; }
@media (max-width: 720px) {
  /* 窄屏没有横向空间，退回两行：书名 / 作者·平台 */
  .grid.list .cbody { grid-template-columns: minmax(0, 1fr) 96px;
    grid-template-areas: "t t" "a f"; row-gap: 2px; }
  .grid.list .excerpt { display: none; }
}

/* ---------- 详情抽屉 ---------- */
.scrim {
  position: fixed; inset: 0; background: rgba(18, 16, 11, .42);
  backdrop-filter: blur(3px); z-index: 60; opacity: 0; pointer-events: none;
  transition: opacity 220ms var(--ease);
}
.scrim.show { opacity: 1; pointer-events: auto; }
/* 100% 而不是 100vw：fixed 的 % 以视口为基准且不含滚动条，100vw 含——
   窄窗口下抽屉会比可见区宽 15px，右侧内容被切掉一条。 */
.drawer {
  position: fixed; top: 0; right: 0; height: 100%; width: min(740px, 100%); max-width: 100%;
  background: var(--surface); z-index: 70;
  transform: translateX(102%); transition: transform 320ms var(--ease);
  display: flex; flex-direction: column; box-shadow: -24px 0 64px -34px rgba(0, 0, 0, .45);
}
.drawer.open { transform: none; }
.drawer-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 22px; border-bottom: 1px solid var(--line); flex: none;
}
.drawer-head .crumb { font-size: 11.5px; color: var(--muted); letter-spacing: .1em; }
.iconbtn {
  width: 30px; height: 30px; border-radius: 5px; display: grid; place-items: center;
  color: var(--muted); margin-left: auto;
  transition: background var(--quick) var(--ease), color var(--quick) var(--ease);
}
.iconbtn:hover { background: var(--surface-2); color: var(--ink); }
.iconbtn svg { width: 16px; height: 16px; }
.drawer-body { padding: 26px 30px 56px; overflow-y: auto; overflow-x: hidden; }

/* .iconbtn 自带 margin-left:auto 把按钮推到右边，第二个要取消，否则中间空一大块 */
.drawer-head .iconbtn + .iconbtn { margin-left: 0; }
/* 详情 / 作者 = 独立整页视图（2026-11-02 起）
   原先是右侧滑出的抽屉 + 模糊遮罩：看完要关掉才能开下一本、窄栏长内容滚很久、
   页面观感像弹层而不像一页。现在改成真正换一屏——铺满视口、无遮罩、无滑入动画，
   头部是 sticky 返回条，地址栏就是 #/b/<id>，浏览器后退直接回列表。 */
.drawer.page-view {
  inset: 0; width: 100%; max-width: 100%; height: 100%;
  transform: none; transition: none; box-shadow: none;
  display: none; overflow: hidden;
}
.drawer.page-view.open { display: flex; }
/* 返回条吸顶：详情内容再长，滚到哪儿都能一眼看见「返回列表」 */
.drawer.page-view .drawer-head {
  position: sticky; top: 0; z-index: 3;
  padding: 10px max(16px, calc((100% - 900px) / 2));
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(10px);
}
/* 返回条上的书名：整页视图没有背景列表作参照，这一行就是「我在哪」 */
.drawer.page-view .drawer-head .crumb {
  font-size: 13px; color: var(--ink-2); letter-spacing: 0;
  font-family: var(--serif); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* 正文列夹在 900px：整页不等于让文字拉成 1600px 的长行 */
.drawer.page-view .drawer-body {
  padding: 22px max(16px, calc((100% - 900px) / 2)) 80px;
}

/* ---------- 并排查看（宽屏） ----------
   详情/作者页在 ≥1200px 时缩成右侧栏，左边列表原地留着：可以边看边挑、接着往下滚、
   接着改筛选，不用「关掉才能开下一本」。中间的分隔条能拖宽，双击复位。
   实现是给 body 加 padding-right 腾位，而不是把详情做成盖在列表上的浮层——列表仍在
   正常文档流里，滚动、吸顶、锚点、Tab 顺序一律不用重算。窄屏（<1200px）没有并排的
   余地，自动退回整页覆盖，交互与之前完全一致。 */
body.split { padding-right: var(--split-w, 620px); }
body.split .drawer.page-view {
  left: auto; right: 0;
  width: var(--split-w, 620px); max-width: var(--split-w, 620px);
  border-left: 1px solid var(--line);
  box-shadow: -18px 0 46px -40px rgba(0, 0, 0, .5);
}
/* 分栏栏宽只有 500-760px，整页那套 900px 夹宽会退化成 16px 贴边，改成固定 22px */
body.split .drawer.page-view .drawer-head,
body.split .drawer.page-view .drawer-body {
  padding-left: 22px; padding-right: 22px;
}
/* 列表就在左边，用不着「返回列表」；「← 上一本」是返回栈，另当别论 */
body.split #detailBack, body.split #authorBack { display: none; }

.split-bar {
  position: fixed; top: 0; bottom: 0; z-index: 72; width: 12px;
  right: calc(var(--split-w, 620px) - 6px);
  cursor: col-resize; touch-action: none; display: none;
}
body.split .split-bar { display: block; }
/* 用 6px 的细条做视觉，外层 12px 是热区——1px 的线太难抓。
   平时是一条淡线（分栏要有可见的分界），悬停/拖动时变成强调色。 */
.split-bar::before {
  content: ""; position: absolute; inset: 0 3px; border-radius: 2px;
  background: var(--line); transition: background 140ms var(--ease), opacity 140ms var(--ease);
}
.split-bar:hover::before, body.split-drag .split-bar::before { background: var(--accent); opacity: .55; }
body.split-drag { user-select: none; cursor: col-resize; }
/* 拖动中别让 iframe/图片抢指针 */
body.split-drag * { cursor: col-resize !important; }

/* 分栏后列表只剩 800px 上下，216px 的固定侧栏会把主区挤成一条——和 1020px 断点一样
   折叠成顶部横向 chips，筛选功能全在，只是不再占一整列。 */
@media (max-width: 1560px) {
  body.split .layout { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  body.split .layout > * { min-width: 0; }
  body.split .side { position: static; max-height: none; overflow: visible; padding-bottom: 4px; }
  body.split .side-group { margin: 0 0 var(--s3); }
  body.split .catlist { display: flex; flex-wrap: nowrap; gap: 6px; overflow-x: auto; padding-bottom: 4px; }
  /* 药丸在分栏里不许被挤窄：名字包进 .t 之后带 min-width:0，不加这两行会被省略成「网…」 */
  body.split .catlist li { flex: none; }
  body.split .catlist .t { overflow: visible; }
  body.split .catlist li button { white-space: nowrap; padding: 4px 9px; border: 1px solid var(--line); font-size: 12.5px; }
  body.split .catlist li button.on::before { display: none; }
  body.split .catlist .n { display: none; }
}

/* 顶栏也得瘦身：让位之后只剩 700px 上下，六个带文字的按钮会把「榜单」「作者」挤成
   一个字一行（真的会竖着排）。先把文字收起来只留图标——title 有提示，肌肉记忆也在。 */
body.split .topbar .wrap { padding: 0 20px; }
body.split .topnav .lbl { display: none; }
body.split .brand-sub { display: none; }
body.split .tbtn { padding: 0 8px; }
body.split .searchbox { max-width: 260px; min-width: 120px; }
body.split .searchbox kbd { display: none; }



.book-head > div { min-width: 0; }
.intro-text { overflow-wrap: anywhere; }

.book-head { display: grid; grid-template-columns: 156px minmax(0, 1fr); gap: var(--s5); }
.book-cover {
  position: relative;
  width: 100%; aspect-ratio: 3/4.1; border-radius: var(--r-sm); overflow: hidden;
  background: var(--surface-2); box-shadow: 0 14px 34px -20px rgba(0, 0, 0, .5);
}
.book-cover img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; display: block; }
.book-head h2 { font-family: var(--serif); font-size: 26px; line-height: 1.3; margin: 2px 0 5px; font-weight: 600; letter-spacing: .01em; }
.book-head .sub { font-size: 12px; color: var(--muted); margin-bottom: var(--s3); }
.book-head .authors { font-size: 13.5px; color: var(--ink-2); margin-bottom: 4px; }
.book-head .authors b { font-weight: 500; }
.honor { font-size: 11.5px; color: var(--gold); margin-top: 6px; letter-spacing: .02em; }
.meta-inline { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; color: var(--muted); margin-top: 10px; }
.rate-row { display: flex; align-items: baseline; gap: 8px; margin: var(--s3) 0 6px; }
.rate-num { font-family: var(--serif); font-size: 24px; color: var(--accent); line-height: 1; font-variant-numeric: tabular-nums; }
.rate-label { font-size: 11.5px; color: var(--muted); }
.stars { color: var(--gold); font-size: 11px; letter-spacing: 2px; }

/* 区块标题允许换行：里面的括号说明有时很长，flex 默认 nowrap 会把容器撑破 */
.section-h {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  font-size: 11px; letter-spacing: .16em; color: var(--muted); text-transform: uppercase;
  margin: var(--s6) 0 var(--s3);
}
.section-h::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.intro-text { font-size: 14px; line-height: 1.9; color: var(--ink-2); white-space: pre-wrap; }
.intro-text p { margin: 0 0 var(--s3); }
.clamp { max-height: 300px; overflow: hidden; position: relative; }
.clamp::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 90px;
  background: linear-gradient(transparent, var(--surface));
}
.more-link { color: var(--accent); font-size: 12.5px; margin-top: 6px; display: inline-block; }

.meta-table { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.meta-table div { background: var(--surface); padding: 9px 13px; font-size: 12.5px; display: flex; gap: 8px; }
.meta-table .mfill { background: var(--surface); }
.meta-table span.k { color: var(--muted); flex: none; width: 52px; }
.meta-table span.v { color: var(--ink-2); word-break: break-all; }

.tagrow { display: flex; flex-wrap: wrap; gap: 7px; }
.tagrow button {
  font-size: 12px; padding: 4px 10px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-2);
  transition: background var(--quick) var(--ease), color var(--quick) var(--ease);
}
.tagrow button:hover { background: var(--accent-soft); color: var(--accent); }

.shelfbar { display: flex; gap: var(--s2); margin-top: 22px; flex-wrap: wrap; }
.shelfbar .btn.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

.related { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.relcard { display: flex; gap: 10px; padding: 8px; border: 1px solid var(--line); border-radius: var(--r-sm); text-align: left;
  transition: border-color var(--quick) var(--ease), background var(--quick) var(--ease); }
.relcard:hover { border-color: var(--accent); background: var(--surface-2); }
.relcard .rc-cover { position: relative; width: 44px; height: 62px; flex: none; border-radius: 3px; overflow: hidden; background: var(--surface-2); }
.relcard img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.relcard .rc-t { font-size: 12.5px; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-family: var(--serif); }
.relcard .rc-a { font-size: 10.5px; color: var(--muted); margin-top: 3px; }

/* ---------- 书架 ---------- */
.shelf-drawer { width: min(440px, 100%); }
.shelf-tabs { display: flex; gap: 4px; padding: 10px 20px 0; border-bottom: 1px solid var(--line); }
.shelf-tabs button { padding: 7px 12px 9px; font-size: 13px; color: var(--muted); border-bottom: 2px solid transparent;
  transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease); }
.shelf-tabs button:hover { color: var(--ink); }
.shelf-tabs button.on { color: var(--accent); border-bottom-color: var(--accent); }
.shelf-list { padding: 14px 20px; overflow-y: auto; flex: 1; }
.shelf-item { cursor: pointer; }
.shelf-item:hover .si-t { color: var(--accent); }
.shelf-item { display: flex; gap: var(--s3); padding: 9px 0; border-bottom: 1px dashed var(--line); align-items: center; }
.shelf-item .si-cover { position: relative; width: 40px; height: 56px; border-radius: 3px; overflow: hidden; background: var(--surface-2); flex: none; }
.shelf-item img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.shelf-item .si-t { font-size: 13.5px; font-family: var(--serif); }
.shelf-item .si-a { font-size: 11px; color: var(--muted); }
.shelf-item .si-del { margin-left: auto; color: var(--muted); font-size: 11px; }
.empty { text-align: center; color: var(--muted); padding: var(--s7) 20px; font-size: 12.5px; }

/* ---------- 弹窗 ---------- */
.modal {
  position: fixed; z-index: 80; left: 50%; top: 50%; transform: translate(-50%, -46%) scale(.98);
  width: min(760px, calc(100% - 32px)); max-height: 84vh; overflow-y: auto;
  background: var(--surface); border-radius: var(--r-lg); border: 1px solid var(--line);
  padding: 26px 30px 32px; opacity: 0; pointer-events: none;
  transition: opacity 220ms var(--ease), transform 220ms var(--ease);
  box-shadow: 0 30px 80px -40px rgba(0, 0, 0, .45);
}
.modal.show { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%) scale(1); }
.modal h2 { font-family: var(--serif); font-size: 21px; margin: 0 0 5px; letter-spacing: .02em; }
.modal .sub { color: var(--muted); font-size: 12px; margin-bottom: 20px; }
.bar-row { display: grid; grid-template-columns: 84px 1fr 44px; align-items: center; gap: var(--s3); margin-bottom: 9px; font-size: 12px; }
.bar-row .b { height: 7px; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
.bar-row .b i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--gold)); border-radius: 4px; }
.bar-row .v { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
.stat-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--s2); margin-bottom: var(--s5); }
.stat-box { border: 1px solid var(--line); border-radius: var(--r); padding: 11px 13px; }
.stat-box b { display: block; font-family: var(--serif); font-size: 20px; line-height: 1.2; white-space: nowrap; font-variant-numeric: tabular-nums; }
.stat-box span { font-size: 11px; color: var(--muted); }

/* ---------- 空状态与提示 ---------- */
.emptystate { padding: 72px 20px; text-align: center; color: var(--muted); }
.emptystate b { display: block; font-family: var(--serif); font-size: 19px; color: var(--ink); margin-bottom: 6px; font-weight: 600; }
.emptystate p { font-size: 13px; }
/* 数据层故障条（app.js 的 bootFailNotice）。正常情况永远不出现，
   所以允许它比别处更响——它的全部价值就是让人一眼看出「不是自己搜错了」。 */
.bootfail {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s4);
  margin: 0 0 var(--s4); padding: 13px 16px 13px 18px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-left: 3px solid var(--accent); border-radius: var(--r);
  box-shadow: var(--shadow);
}
.bootfail-t { font-family: var(--serif); font-size: var(--t-md); font-weight: 600; color: var(--accent); }
.bootfail-d { flex: 1; min-width: 220px; font-size: var(--t-sm); line-height: 1.65; color: var(--ink-2); }
.bootfail .btn { flex: none; }
/* 数据层故障时，网格里的「没有匹配的书目 / 换个说法再试一次」要收起来——
   数据没到，换什么说法都不会有结果，那句话只会让人继续怀疑自己的关键词 */
.data-failed .emptystate { display: none; }
.loadmore { display: flex; justify-content: center; margin-top: 32px; }
.toast {
  position: fixed; left: 50%; bottom: 34px; transform: translate(-50%, 16px);
  background: var(--ink); color: var(--bg); padding: 10px 18px; border-radius: var(--r);
  font-size: 13px; opacity: 0; pointer-events: none;
  transition: opacity 200ms var(--ease), transform 200ms var(--ease); z-index: 99;
  box-shadow: 0 12px 32px -16px rgba(0, 0, 0, .6);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
mark { background: var(--accent-soft); color: var(--accent); padding: 0 1px; border-radius: 2px; }
/* ---------- 页脚：三段声明 ---------- */
.foot {
  border-top: 1px solid var(--line);
  padding: 28px 0 40px;
  color: var(--ink-2);            /* 10.34:1（原来是 --muted，3.99:1 不达标） */
  font-size: var(--t-sm);         /* 12.5px */
  line-height: 1.75;
}

.foot-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px 32px;
}

.foot-block { min-width: 0; }

/* 小标题：宋体 + 字距。页脚的层级完全靠这一行字建立，
   不靠字号——页脚里出现 14px 以上的字会跟正文抢戏。 */
.foot-h {
  font-family: var(--serif);
  font-size: var(--t-sm);         /* 12.5px，和正文同号，靠字体与字重拉开 */
  font-weight: 600;
  letter-spacing: .08em;
  line-height: 1.4;
  color: var(--ink);
  margin: 0 0 var(--s2);          /* 8px */
}

.foot-block p { margin: 0 0 var(--s2); }
.foot-block p:last-child { margin-bottom: 0; }

/* 断点必须用容器查询：页脚所在主列的宽度不随视口单调变化——
   视口从 1021 收到 1020 时侧栏塌掉，主列反而从 669 变宽到 956。
   媒体查询写不出这种「先降后升再降」的曲线。容器是 .layout > section
   （307–310 行已经是 container-type: inline-size）。
   以下两块必须排在上面那组基础规则之后：选择器特异度相同，靠源码顺序生效。 */
@container (max-width: 880px) {
  .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-block:nth-child(3) { grid-column: 1 / -1; }
}
@container (max-width: 560px) {
  .foot-cols { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .foot-block:nth-child(3) { grid-column: auto; }
  .foot { padding: 24px 0 32px; }
}

/* 不支持容器查询时的兜底：整块 @container 会被忽略，退回三栏。
   这几行只在老浏览器上生效，与上面不冲突。 */
@supports not (container-type: inline-size) {
  @media (max-width: 1200px) {
    .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .foot-block:nth-child(3) { grid-column: 1 / -1; }
  }
  @media (max-width: 1020px) {
    .foot-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .foot-block:nth-child(3) { grid-column: auto; }
  }
  @media (max-width: 860px) {
    .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .foot-block:nth-child(3) { grid-column: 1 / -1; }
  }
  @media (max-width: 640px) {
    .foot-cols { grid-template-columns: minmax(0, 1fr); }
    .foot-block:nth-child(3) { grid-column: auto; }
  }
}

/* 滚动条 */
.drawer-body::-webkit-scrollbar, .modal::-webkit-scrollbar { width: 7px; }
.drawer-body::-webkit-scrollbar-thumb, .modal::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 7px; }

@media (max-width: 1020px) {
  .layout { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .layout > * { min-width: 0; }
  /* 窄屏：.catlist 只做横向排列，盒子宽度由内容决定，父级 .catlists 负责横滚 */
  .side, .catlists, #c2chips { min-width: 0; max-width: 100%; }
  .side { position: static; max-height: none; display: block; overflow: visible; padding-bottom: 6px; }
  .side-group { margin: 0 0 var(--s3); }

  /* 窄屏：主门类与长尾并进同一条横滚，折叠控件让位（JS 同时强制 open） */
  .catlists {
    display: flex; flex-wrap: nowrap; gap: 6px;
    overflow-x: auto; padding-bottom: 4px;
    -webkit-mask-image: linear-gradient(90deg, #000 92%, transparent);
            mask-image: linear-gradient(90deg, #000 92%, transparent);
  }
  .catlists::-webkit-scrollbar { display: none; }
  .catmore { margin: 0; }
  .catmore > summary { display: none; }

  /* flex: 0 0 auto 让 ul 按内容定宽不收缩；min-width/max-width 覆盖上面继承来的 0 与 100%，
     否则 ul 盒子会被压成 0 宽，li 溢出绘制，.catmore 按盒子边界排版 → 药丸重叠 */
  .catlist {
    display: flex; flex-wrap: nowrap; gap: 6px; overflow: visible; padding: 0;
    flex: 0 0 auto; min-width: auto; max-width: none;
  }
  .catlist li { flex: none; }
  .catlist li.is-all { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
  .catlist li button {
    white-space: nowrap; padding: 5px 10px; border: 1px solid var(--line);
    font-size: 12.5px; line-height: 1.5;      /* 高 28.75，够 24×24 */
  }
  .catlist .t { overflow: visible; }         /* 横条里不截断 */
  .catlist li button.on::before { display: none; }
  .catlist .n { display: none; }
  .side-group .side-title { margin-bottom: 6px; }
  .side::-webkit-scrollbar { height: 4px; }
  .hero { padding: 36px 0 22px; }
}

/* 721–1020（平板）：侧栏收起成横条后，书单 / 出版年代 / 清空筛选各占一行，
   中间空出一百多像素。三块都是「一次性操作」，挤成一行即可；
   门类横滚与展开后的年代面板仍占整行。 */
@media (min-width: 721px) and (max-width: 1020px) {
  .side { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
  .side .catlists { flex: 1 1 100%; }
  .side .side-group { margin: 0; }
  /* 只收掉纯文字的分组标题；summary 也叫 .side-title，收掉它这一组就没了出口 */
  .side .side-group > .side-title:not(summary) { display: none; }
  .side details.side-group { flex: 0 0 auto; }
  .side details.side-group > summary { margin: 0; font-size: 12.5px; }
  .side details.side-group[open] { flex: 1 1 100%; }
  .side details.side-group[open] > summary { margin-bottom: 6px; }
}

/* 顶栏 721–1060：按钮只留图标。
   720 以下本来就这么做了（见下一段的 .topnav .tbtn span.lbl），
   但 721–940 这一档以前是靠着「少一个入口」才勉强不溢出的；2026-11 加了
   「成就」入口（第 7 个）之后，上限抬到 1060，这一档只收走图标后面的
   两个字的标签——按钮的 title 属性仍在，悬停与读屏都还念得出来。 */
@media (min-width: 721px) and (max-width: 1060px) {
  .topnav .tbtn span.lbl { display: none; }
  .topnav .tbtn { padding: 0 8px; }
}
@media (max-width: 720px) {
  .wrap { padding: 0 18px; }
  .topbar-in { height: auto; flex-wrap: wrap; padding: 9px 18px 10px; gap: 8px 12px; }
  .hero h1 { font-size: clamp(26px, 7vw, 38px); }
  .searchbox { order: 9; flex-basis: 100%; max-width: none; }
  .brand-name { font-size: 17px; }
  .topnav .tbtn span.lbl { display: none; }
  /* 7 个纯图标收成 4 个：榜单 / 书架 / 主题 + 更多。剩下的进浮层，
     每个按钮留 40px 触控区，不再贴屏幕边。 */
  .topnav .tbtn[data-more] { display: none; }
  .topnav .morebtn { display: inline-flex; }
  /* display 已在全局声明为 block，这里只补窄屏的右偏移 */
  .moremenu { right: 18px; }
  .topnav .tbtn { height: 36px; padding: 0 9px; min-width: 40px; justify-content: center; }
  .brand-sub { display: none; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 14px; }
  .card { padding: 9px; }
  .card h3 { font-size: 14px; }
  .card .excerpt { display: none; }
  .book-head { grid-template-columns: 112px 1fr; gap: var(--s4); }
  .book-head h2 { font-size: 21px; }
  .drawer-body { padding: 20px 18px 50px; }
  .meta-table { grid-template-columns: 1fr; }
  .related { grid-template-columns: 1fr 1fr; }
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .searchbox kbd { display: none; }
  .searchbox input { padding-right: 12px; }
  .hero-stats { gap: 5px 12px; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* 网络小说相关 */
.plat-tag { color: var(--accent); border: 1px solid var(--line); border-radius: 4px; padding: 1px 7px; }
/* 网文类型的 chips 不再自己滚动：侧栏里原来套了第二个滚动条，
   选中「网络小说」时上下两个滚动区一起出现，正是「反复上下滚」的来源。
   现在 .side 是唯一的滚动上下文。 */
#c2chips { max-height: none; }
#c2chips .chip i { font-style: normal; opacity: .55; margin-left: 4px; font-size: 11px; }
.badge-cat { max-width: 64%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ================= 作者百科 / 热度榜单 / 百科延伸 ================= */

/* 顶栏返回：详情页改成独立整页后，它是唯一的退出口，要够显眼、带箭头、吸顶可达 */
.back-btn {
  display: inline-flex; align-items: center; gap: 5px;
  height: 30px; padding: 0 11px 0 9px; border-radius: var(--r-sm); font-size: 12.5px;
  border: 1px solid var(--line); color: var(--ink-2); background: var(--surface-2);
  transition: border-color var(--quick) var(--ease), color var(--quick) var(--ease);
  white-space: nowrap;
}
.back-btn:hover { border-color: var(--accent); color: var(--accent); }
.back-btn svg { width: 14px; height: 14px; flex: none; }

/* 搜索结果里的作者提示 */
.author-hint {
  display: flex; align-items: center; flex-wrap: wrap; gap: 7px;
  padding: 11px 13px; margin-bottom: var(--s3);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
}
.author-hint .ah-label {
  font-size: 10.5px; letter-spacing: .16em; color: var(--muted); margin-right: 2px;
}
.author-hint .chip i { font-style: normal; color: var(--muted); margin-left: 5px; font-size: 10px; }

/* 书页作者链接 */
.authors .author-link {
  border-bottom: 1px dotted var(--line-strong); padding: 0; line-height: 1.4;
  font-weight: 500; color: var(--ink);
}
.authors .author-link::after {
  content: "↗"; font-size: 9px; color: var(--accent); margin-left: 2px; opacity: .8;
}
.authors .author-link:hover { color: var(--accent); border-bottom-color: var(--accent); }
.authors .a-sep { color: var(--muted); margin: 0 5px; }

/* 热度条 */
/* 整行可点：点「热度」展开算法说明。做成按钮而不是 div，键盘也能触发。 */
.hot-row {
  display: flex; align-items: center; gap: 9px; margin-top: var(--s3); flex-wrap: wrap;
  width: 100%; padding: 0; text-align: left; cursor: pointer;
}
.hot-lbl { font-size: 10.5px; letter-spacing: .1em; color: var(--muted); }
.hot-bar {
  position: relative; width: 128px; height: 5px; border-radius: 3px;
  background: var(--surface-2); overflow: hidden;
}
.hot-bar i {
  display: block; height: 100%; border-radius: 3px;
  background: linear-gradient(90deg, var(--gold), var(--accent));
  transition: width 520ms var(--ease);
}
.hot-num { font-family: var(--serif); font-size: 15px; color: var(--accent); line-height: 1; font-variant-numeric: tabular-nums; }
.hot-rank { font-size: 11px; color: var(--muted); }
.hot-more {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 10.5px; color: var(--muted); opacity: .8;
  transition: color var(--quick) var(--ease), opacity var(--quick) var(--ease);
}
.hot-more i { font-style: normal; font-size: 13px; line-height: 1; }
.hot-row:hover .hot-more { color: var(--accent); opacity: 1; }
.hot-row:hover .hot-num { text-decoration: underline; text-underline-offset: 3px; }
.hot-note {
  font-size: 11.5px; color: var(--muted); margin-top: 6px;
  padding-left: 10px; border-left: 2px solid var(--line);
}

/* ---------- 热度算法（默认收起） ---------- */
/* 热度是个相对指标，多数人只需要知道数字和名次。算法摊开在页面上是一堵墙，
   收进一层折叠里，想看的人点「热度」或这行标题就行。 */
.heat-fold {
  margin-top: var(--s4);
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface); overflow: hidden;
}
.heat-fold > summary {
  display: flex; align-items: baseline; gap: var(--s2);
  padding: 10px var(--s3); list-style: none; cursor: pointer;
  font-size: var(--t-sm); color: var(--ink-2);
  transition: background var(--quick) var(--ease);
}
.heat-fold > summary::-webkit-details-marker { display: none; }
.heat-fold > summary:hover { background: var(--surface-2); }
.hf-t { color: var(--ink); font-weight: 600; flex: none; }
.hf-s { color: var(--muted); font-size: var(--t-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hf-arrow {
  margin-left: auto; flex: none; font-style: normal; line-height: 1;
  color: var(--muted); transition: transform var(--quick) var(--ease);
}
.heat-fold[open] .hf-arrow { transform: rotate(90deg); }
.heat-fold-b { padding: var(--s3); border-top: 1px solid var(--line); }
.heat-fold-b > :last-child { margin-bottom: 0; }
.heat-fold .heatchart { border: 0; }

/* 金句 */
.book-quote {
  margin: 22px 0 4px; padding: var(--s3) var(--s4);
  font-family: var(--serif); font-size: 15px; line-height: 1.9; color: var(--ink-2);
  background: var(--surface-2); border-radius: var(--r);
  border-left: 3px solid var(--gold);
}

/* 主要角色 */
.chars { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.char {
  border: 1px solid var(--line); border-radius: var(--r); padding: 10px 13px;
  background: var(--surface);
  transition: border-color var(--quick) var(--ease);
}
.char:hover { border-color: var(--line-strong); }
.char-h { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: 4px; }
.char-h b { font-family: var(--serif); font-size: 14px; font-weight: 600; }
.char-h span {
  font-size: 10px; color: var(--accent); border: 1px solid var(--line);
  border-radius: 3px; padding: 0 5px; line-height: 1.6;
}
.char p { margin: 0; font-size: 12px; line-height: 1.75; color: var(--ink-2); }

/* 获奖列表 */
.honorlist { list-style: none; margin: 0; padding: 0; }
.honorlist li {
  position: relative; padding: 7px 0 7px 18px; font-size: 12.5px; color: var(--ink-2);
  border-bottom: 1px dashed var(--line);
}
.honorlist li:last-child { border-bottom: none; }
.honorlist li::before {
  content: "◆"; position: absolute; left: 2px; top: 7px;
  font-size: 8px; color: var(--gold);
}

/* 改编 */
.adaptlist { display: flex; flex-direction: column; gap: var(--s2); }
.adapt {
  display: flex; gap: var(--s3); align-items: flex-start;
  padding: 10px 13px; border: 1px solid var(--line); border-radius: var(--r);
}
.adapt-type {
  flex: none; font-size: 10.5px; color: var(--accent);
  border: 1px solid var(--line); border-radius: 3px; padding: 1px 7px; margin-top: 2px;
  background: var(--accent-soft);
}
.adapt b { font-size: 13px; font-weight: 500; }
.adapt-year { font-size: 11px; color: var(--muted); margin-left: 4px; }
.adapt p { margin: 3px 0 0; font-size: 11.5px; color: var(--muted); line-height: 1.65; }

/* 作者卡片 */
.author-card {
  display: flex; align-items: center; gap: var(--s3); width: 100%; text-align: left;
  padding: 13px 15px; margin-top: 4px;
  border: 1px solid var(--line); border-radius: var(--r); background: var(--surface-2);
  transition: border-color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.author-card:hover { border-color: var(--accent); background: var(--accent-soft); }
.ac-seal {
  flex: none; width: 42px; height: 42px; border-radius: var(--r-sm);
  display: grid; place-items: center;
  border: 1.5px solid var(--accent); color: var(--accent);
  font-family: var(--serif); font-size: 21px; line-height: 1;
}
.ac-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ac-name b { font-family: var(--serif); font-size: 15px; font-weight: 600; }
.ac-name i { font-style: normal; font-size: 11.5px; color: var(--muted); margin-left: 8px; }
.ac-meta { font-size: 11px; color: var(--muted); }
.ac-bio {
  font-size: 11.5px; color: var(--ink-2); line-height: 1.6;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ac-go { flex: none; margin-left: auto; font-size: 11.5px; color: var(--accent); white-space: nowrap; }

/* 作者百科页 */
.author-head { display: flex; gap: 22px; align-items: flex-start; }
.ap-seal {
  flex: none; width: 84px; height: 84px; border-radius: var(--r);
  display: grid; place-items: center;
  border: 2px solid var(--accent); color: var(--accent); background: var(--accent-soft);
  font-family: var(--serif); font-size: 40px; line-height: 1;
}
.author-head h2 {
  font-family: var(--serif); font-size: 26px; margin: 2px 0 var(--s2); font-weight: 600; letter-spacing: .02em;
}
.author-head .sub { font-size: 11.5px; color: var(--muted); letter-spacing: .06em; }
.author-facts { display: flex; flex-wrap: wrap; gap: 4px 18px; font-size: 12px; color: var(--ink-2); margin-bottom: var(--s2); }
.author-facts i { font-style: normal; color: var(--muted); margin-right: 5px; }
.author-stat {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  margin-top: 22px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
}
.author-stat div { background: var(--surface); padding: 11px 13px; display: flex; flex-direction: column; gap: 1px; }
.author-stat b {
  font-family: var(--serif); font-size: 16px; line-height: 1.35; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums;
}
.author-stat span { font-size: 10.5px; color: var(--muted); }

.author-works { display: flex; flex-direction: column; }
.aw-item {
  display: grid; grid-template-columns: 30px minmax(0, 1fr) auto 88px 26px;
  align-items: center; gap: 10px;
  padding: 7px 6px; border-bottom: 1px dashed var(--line); text-align: left;
  border-radius: var(--r-sm);
  transition: background var(--quick) var(--ease);
}
.aw-item:hover { background: var(--surface-2); }
.aw-cover { width: 30px; height: 42px; border-radius: 3px; overflow: hidden; background: var(--surface-2); position: relative; }
.aw-cover img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.aw-t { font-family: var(--serif); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.aw-m { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.aw-h { height: 5px; background: var(--surface-2); border-radius: 3px; overflow: hidden; }
.aw-h i { display: block; height: 100%; background: linear-gradient(90deg, var(--gold), var(--accent)); }
.aw-n { font-size: 11px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }

/* 榜单 */
.rank-drawer { width: min(620px, 100vw); }
/* 一级：出版书 / 网文。选中态跟全站筛选 chip 用同一套（赭红描边 + 淡赭底），
   原来填成纯黑药丸，在一屏暖纸色里是唯一的黑块，读起来像另一个产品的按钮。 */
/* 筛选条：范围 / 榜种 / 时间窗三组控件放同一行。
   原来三组各占一行、第一组还是带副标题的大按钮，视觉重量压过了后两组，
   看着像两个不同的入口。现在统一成胶囊，组间用竖线分隔，时间窗小一号靠右。 */
.rank-filter {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  padding: 10px 18px 8px; flex: none;
}
.rank-groups { display: flex; gap: 6px; padding: 0; flex: none; }
.rank-groups button {
  display: inline-flex; align-items: center; padding: 5px 12px;
  border-radius: 999px; border: 1px solid var(--line); background: var(--surface);
  color: var(--muted); line-height: 1.3;
  transition: background var(--quick) var(--ease), color var(--quick) var(--ease), border-color var(--quick) var(--ease);
}
.rank-groups button b { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
/* 副标题（「纸质出版、人文社科」）在这一行里是噪音：范围靠上面两个词已经说清 */
.rank-groups button i { display: none; }
.rank-groups button:hover { border-color: var(--ink-2); }
.rank-groups button.on { background: var(--accent-soft); border-color: var(--accent); }
.rank-groups button.on b { color: var(--accent); }
.rank-groups button.on:hover { border-color: var(--accent); }
.rank-tabs {
  display: flex; gap: 6px; padding: 0; border-bottom: 0;
  overflow-x: auto; flex: 0 1 auto; scrollbar-width: none;
}
.rank-tabs::-webkit-scrollbar { display: none; }
.rank-tabs::before {
  content: ""; flex: 0 0 auto; width: 1px; height: 16px; margin: 0 4px;
  background: var(--line-strong); align-self: center;
}
.rank-tabs button {
  padding: 5px 11px; font-size: 12.5px; color: var(--muted); white-space: nowrap;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
  transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.rank-tabs button:hover { color: var(--ink); border-color: var(--line-strong); }
.rank-tabs button.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.rank-body { padding: var(--s4) 20px 48px; }
.rank-intro { font-size: 11.5px; color: var(--muted); margin: 0 0 var(--s3); }
/* 时间窗口筛选：历史累计 / 近一年 / 近三月 / 近一月。比榜种小一号，靠右。 */
.rank-wins {
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center;
  padding: 0; margin-left: auto;
}
.rank-wins button {
  padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line);
  font-size: 11.5px; color: var(--muted);
  transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.rank-wins button:hover { color: var(--ink); border-color: var(--line-strong); }
.rank-wins button.on { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }
/* 口径角标：实测 / 估算。这两个词差别很大，不能让用户猜 */
.rank-wins .win-tag {
  font-style: normal; font-size: 9.5px; letter-spacing: .02em;
  margin-left: 4px; padding: 0 4px; border-radius: 3px;
  background: var(--line); color: var(--muted);
}
.rank-wins .win-tag.real { background: var(--accent-soft); color: var(--accent); }
.rank-wins button.on .win-tag { opacity: .85; }

/* 热度构成表（书目详情页）：两段——站内指标 / 第三方讨论，各列「读数 → 名次 → 标准分」 */
.heatchart { display: flex; flex-direction: column; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; margin: 0 0 10px; }
/* 列宽按最长的读数留：站外那列会出「2354 万 播放」，70px 会被裁掉一个「放」字。 */
.hc-row {
  /* 读数列给到 96px：热度统一保留两位小数后，「2354.02 万 播放」比原来的「2354 万」宽出一截，
     84px 会顶破格子 */
  display: grid; grid-template-columns: 72px minmax(0, 1fr) 96px 66px 44px;
  align-items: center; gap: var(--s2); background: var(--surface); padding: 9px 12px;
}
.hc-t { font-size: 12px; color: var(--ink-2); white-space: nowrap; }
.hc-t i { font-style: normal; font-size: 10px; color: var(--muted); }
.hc-b { height: 5px; background: var(--line); border-radius: 999px; overflow: hidden; }
.hc-b i { display: block; height: 100%; background: var(--accent); }
.hc-v, .hc-p { font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; }
.hc-v { color: var(--muted); white-space: nowrap; }
.hc-p { color: var(--ink-2); font-weight: 600; }
.hc-w { font-size: 11px; color: var(--muted); text-align: right; white-space: nowrap; }
.hc-row.hc-off { opacity: .55; }
/* 两段标题：站内 / 站外，把「同一套标准分、两批来源」这件事说清楚 */
.hb-h {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 11.5px; letter-spacing: .08em; color: var(--ink); font-weight: 600;
  margin: var(--s4) 0 var(--s2);
}
.hb-h:first-child { margin-top: 0; }
.hb-h span { font-weight: 400; letter-spacing: 0; color: var(--muted); font-size: 11.5px; }
.hb-sum { color: var(--ink); font-size: 12.5px; }
.hb-sum b { font-family: var(--serif); font-size: 16px; color: var(--accent); }
@media (max-width: 720px) {
  /* 窄屏原来是「60 / 条形 / 82」三列硬排，条形被挤成一小截，名次列还会把右边的
     标准分顶出容器（被 .heatchart 的 overflow:hidden 吃掉）。改成两行：第一行
     书名 + 读数 + 标准分，第二行整条条形铺满。
     只有「第 N 名」藏掉——标准分是这套模型的结论，比名次重要，不能藏。 */
  .hc-row {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "t v p" "b b b";
    row-gap: 6px;
  }
  .hc-row .hc-t { grid-area: t; }
  .hc-row .hc-v { grid-area: v; }
  .hc-row .hc-p { grid-area: p; }
  .hc-row .hc-b { grid-area: b; }
  .hc-w { display: none; }
}
.rank-years { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 var(--s3); }
.rank-years button {
  padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line);
  font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums;
  transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.rank-years button:hover { color: var(--ink); border-color: var(--line-strong); }
.rank-years button.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.rank-list { display: flex; flex-direction: column; }
/* 榜单行：名次 | 封面 | 书名·作者·说明 | 热度分
   原来还有一条无刻度、无标签的进度条紧挨着数值，两者并排会被读成
   「进度 72.7%」——而它其实只是一个相对强度的示意。删掉条形，
   数字右对齐，误读就没了；名次本身已经承担了「相对位置」的信息。 */
.rank-row {
  display: grid; grid-template-columns: 26px 38px minmax(0, 1fr) 62px;
  align-items: center; gap: 11px; text-align: left;
  padding: 8px 4px; border-bottom: 1px dashed var(--line);
  border-radius: var(--r-sm);
  transition: background var(--quick) var(--ease);
}
.rank-row:hover { background: var(--surface-2); }
.rk-no {
  font-family: var(--serif); font-size: 13.5px; color: var(--muted); text-align: center;
  font-variant-numeric: tabular-nums;
}
.rk-no.top { color: var(--accent); font-size: 16px; font-weight: 600; }
.rk-cover { width: 38px; height: 52px; border-radius: 3px; overflow: hidden; background: var(--surface-2); position: relative; }
.rk-cover img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; }
.rk-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rk-main b {
  font-family: var(--serif); font-size: 13.5px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rk-main i { font-style: normal; font-size: 11px; color: var(--muted); }
.rk-main em {
  font-style: normal; font-size: 10.5px; color: var(--gold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
/* 条形不再渲染（见 .rank-row 注释），留一条规则兜住残留 DOM */
.rk-bar { display: none; }
.rk-val {
  font-size: 11.5px; color: var(--accent); text-align: right;
  font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 600;
}
.rk-seal {
  width: 32px; height: 32px; border-radius: 3px; display: grid; place-items: center;
  border: 1px solid var(--line-strong); color: var(--ink-2);
  font-family: var(--serif); font-size: 15px;
}
.author-row { grid-template-columns: 26px 38px minmax(0, 1fr) 62px; }

.rank-foot { margin: 18px 0 0; padding-top: var(--s3); border-top: 1px dashed var(--line);
  font-size: 11px; line-height: 1.7; color: var(--muted); }
.rank-empty { font-size: 12px; color: var(--muted); padding: 18px 4px; }

/* 卡片底部热度 */
.cm-hot { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
  .chars { grid-template-columns: 1fr; }
  .author-stat { grid-template-columns: repeat(2, 1fr); }
  .author-head { gap: 16px; }
  .ap-seal { width: 64px; height: 64px; font-size: 32px; }
  .author-head h2 { font-size: 24px; }
  .aw-item { grid-template-columns: 26px minmax(0, 1fr) 26px; }
  .aw-m, .aw-h { display: none; }
  .rank-row, .author-row { grid-template-columns: 20px 32px minmax(0, 1fr) 56px; }
  .rk-bar { display: none; }
  .rk-main em { display: none; }
  .rank-filter { padding: 10px 14px 6px; gap: 6px 8px; }
  .rank-groups button { padding: 4px 10px; }
  .rank-wins { margin-left: 0; }
  .drawer-body { padding: 20px 18px 50px; }
}

/* 作品档案（派生数据，覆盖全部书目） */
.factgrid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
}
.factgrid > div { background: var(--surface); padding: 11px 13px; display: flex; flex-direction: column; gap: 2px; }
.factgrid i { font-style: normal; font-size: 10.5px; color: var(--muted); letter-spacing: .06em; }
.factgrid b { font-family: var(--serif); font-size: 15px; font-weight: 600; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.factgrid span { font-size: 10.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

@media (max-width: 720px) {
  .factgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 站外讨论四档时间窗口（B 站） */
.winbar {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  margin: 0 0 10px;
}
.win { background: var(--surface); padding: 10px 13px; display: flex; flex-direction: column; gap: 3px; }
.win-empty { opacity: .58; }
.win-h { font-size: 11px; color: var(--muted); letter-spacing: .04em; }
.win-cap { font-style: normal; color: var(--accent); font-weight: 700; margin-left: 2px; cursor: help; }
.win-n { font-family: var(--serif); font-size: 18px; font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
.win-n span { font-family: var(--sans); font-size: 10.5px; font-weight: 400; color: var(--muted); margin-left: 2px; }
.win-p { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.win-b { height: 4px; background: var(--line); border-radius: 999px; overflow: hidden; margin-top: 3px; }
.win-b i { display: block; height: 100%; background: var(--accent); }

@media (max-width: 720px) {
  .winbar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .win-n { font-size: 16px; }
}

/* 全网在售（同一作品跨平台条目） */
.xplist { display: flex; flex-direction: column; background: var(--line); gap: 1px;
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; margin: 0 0 10px; }
.xp-row { display: grid; grid-template-columns: 96px minmax(0, 1fr) 56px; align-items: center;
  gap: 10px; background: var(--surface); padding: 9px 13px; font-size: 12px; }
.xp-me { background: var(--accent-soft, rgba(156, 47, 36, .06)); }
.xp-plat { color: var(--muted); font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xp-t { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xp-h { text-align: right; font-variant-numeric: tabular-nums; color: var(--accent); font-weight: 600; }
@media (max-width: 720px) { .xp-row { grid-template-columns: 80px minmax(0, 1fr) 48px; } }

/* 第三方讨论条目（可点链接 + 排序 / 时间筛选） */
.soc-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }
.soc-tools { display: flex; gap: var(--s2); flex: 1; min-width: 0; }
.soc-tools select {
  appearance: none; -webkit-appearance: none;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 6px 26px 6px 11px; font-size: 12.5px; font-family: inherit;
  cursor: pointer; min-width: 106px;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  transition: border-color var(--quick) var(--ease);
}
.soc-tools select:hover { border-color: var(--accent); }
.soc-count { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.soclist { display: flex; flex-direction: column; background: var(--line); gap: 1px;
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; margin: 0 0 10px; }
.soc-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  gap: var(--s3); background: var(--surface); padding: 9px 13px; text-decoration: none;
  transition: background var(--quick) var(--ease); }
.soc-row:hover { background: var(--accent-soft, rgba(156, 47, 36, .06)); }
/* 视频封面缩略图：在线取 B 站图床的 @160w_100h 缩略图，这里显示 80×50 */
.soc-thumb { width: 80px; height: 50px; flex: 0 0 auto; border-radius: var(--r-sm);
  overflow: hidden; background: var(--line); position: relative; }
.soc-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 图裂时（视频被删、CDN 占位）img 会被前端隐藏，露出这层灰底，行高不会塌 */
.soc-thumb::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 0 1px rgba(0,0,0,.06); border-radius: var(--r-sm); pointer-events: none; }
.soc-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.soc-t { color: var(--ink); font-size: 13px; line-height: 1.45;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  transition: color var(--quick) var(--ease); }
.soc-row:hover .soc-t { color: var(--accent); }
.soc-sub { color: var(--muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.soc-nums { display: flex; gap: 14px; text-align: right; flex-shrink: 0; }
.soc-nums span { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.soc-nums b { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.soc-nums i { font-style: normal; font-size: 10px; color: var(--muted); }
.soc-empty { padding: 13px; font-size: 12.5px; color: var(--muted);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); margin: 0 0 10px; }

@media (max-width: 720px) {
  .soc-thumb { width: 56px; height: 35px; }
  .soc-row { gap: var(--s2); padding: 8px 10px; }
  /* 窄屏放不下「数字 + 标签」并排两组：加了封面缩略图之后讨论数会被挤出屏幕。
     改成竖排（每行「956万 播放」/「5.4万 讨论」），横向需求砍掉一半。 */
  .soc-nums { flex-direction: column; align-items: flex-end; gap: 3px; }
  .soc-nums span { flex-direction: row; align-items: baseline; gap: 4px; }
  .soc-nums b { font-size: 12px; }
  .soc-nums i { font-size: 9.5px; }
  .soc-t { font-size: 12.5px; }
  .soc-tools select { min-width: 0; flex: 1; }
}
.soc-more { display: block; width: 100%; margin: 0 0 10px; padding: 9px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  color: var(--muted); font-size: 12.5px; font-family: inherit; cursor: pointer;
  transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease); }
.soc-more:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- 风格标签（本地模型生成） ---------- */
.tagwall { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 8px; }
.tagchip { font-size: 12px; line-height: 1; padding: 7px 11px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line); }
.tag-note { font-size: 11.5px; color: var(--muted); line-height: 1.65; margin-bottom: 6px; }

/* ---------- 我的感受（推荐的输入） ---------- */
.tastebar { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.taste-lbl { font-size: 12px; color: var(--muted); }
.btn.taste { padding: 5px 12px; font-size: 12.5px; }
.btn.taste.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.taste-hint { font-size: 11.5px; color: var(--muted); }

/* ---------- 猜你喜欢 ---------- */
.rec-note { font-size: 12px; color: var(--muted); padding: 12px 20px 6px; line-height: 1.6; }
/* 导出按钮跟在说明文字后面，别占一整行 */
.rec-note .exp { margin-left: 8px; padding: 3px 10px; font-size: 12px; vertical-align: 1px; }
.rec-why { font-size: 11.5px; color: var(--accent); opacity: .88; margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shelf-tabs { overflow-x: auto; scrollbar-width: none; }
.shelf-tabs::-webkit-scrollbar { display: none; }
.shelf-tabs button { white-space: nowrap; }

/* ---------- 百科扩展层：奖项 / 成就 / 节奏 ----------
   三块内容共用一套「小标签 + 主文 + 弱化说明」的行式排版，
   与既有的 .honorlist / .factgrid 保持同一密度，不新增视觉语言。 */
.sec-note { font-size: 11px; font-weight: 400; color: var(--muted); margin-left: 8px; letter-spacing: 0; }

/* 奖项：年份 - 奖项名（届次）- 结果 */
.awardlist { list-style: none; margin: 0 0 6px; padding: 0; }
.awardlist li { display: flex; align-items: baseline; gap: 10px; padding: 7px 0; border-bottom: 1px dashed var(--line); }
.awardlist li:last-child { border-bottom: none; }
.award-y { font-family: var(--serif); font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; flex: none; min-width: 34px; }
.award-n { font-size: 13.5px; color: var(--ink); flex: 1; min-width: 0; }
.award-n em { font-style: normal; font-size: 11.5px; color: var(--muted); margin-left: 6px; }
.award-r { flex: none; font-size: 11px; line-height: 1; padding: 4px 8px; border-radius: 999px;
  border: 1px solid var(--line-strong); color: var(--muted); }
.award-r[data-r="获奖"] { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.award-r[data-r="提名"], .award-r[data-r="入围"] { border-color: var(--gold); color: var(--gold); }
.award-r[data-r="入选"], .award-r[data-r="荣誉"] { border-color: var(--line-strong); color: var(--ink-2); }
.award-src { font-size: 11px; color: var(--muted); line-height: 1.6; margin: 6px 0 0; }

/* 成就与纪录 */
.achlist { display: flex; flex-direction: column; }
.ach-item { display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px dashed var(--line); align-items: flex-start; }
.ach-item:last-child { border-bottom: none; }
.ach-k { flex: none; font-size: 10.5px; line-height: 1; padding: 4px 7px; border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line); margin-top: 2px; }
.ach-k[data-k="销量"] { color: var(--accent); border-color: var(--accent-soft); background: var(--accent-soft); }
.ach-k[data-k="改编"] { color: var(--gold); border-color: var(--gold); }
.ach-t { font-size: 13px; color: var(--ink-2); line-height: 1.6; min-width: 0; }
.ach-t b { font-weight: 600; color: var(--ink); margin-left: 6px; font-variant-numeric: tabular-nums; }
.ach-t em { font-style: normal; font-size: 11.5px; color: var(--muted); margin-left: 6px; }

/* 节奏：四（三）条横向刻度 */
.pace-bars { display: flex; flex-direction: column; gap: 7px; margin: 2px 0 8px; max-width: 460px; }
.pace-row { display: grid; grid-template-columns: 76px 1fr 18px; align-items: center; gap: 10px; }
.pace-row i { font-style: normal; font-size: 11.5px; color: var(--muted); }
.pace-row em { font-style: normal; font-size: 11.5px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }
.pace-bar { display: block; height: 5px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.pace-bar b { display: block; height: 100%; border-radius: 3px; background: var(--accent); opacity: .72; }
.pace-bar b[data-k="barrier"] { background: var(--gold); opacity: .8; }
.pace-note { font-size: 12.5px; color: var(--ink-2); line-height: 1.75; margin: 8px 0 0; }
/* 缺项说明：缺的项要写出来，不能让板块只剩一根条还不解释。 */
.pace-miss { font-size: 11.5px; color: var(--muted); line-height: 1.7; margin: 6px 0 0; }
.pace-flat { font-size: 12.5px; color: var(--ink-2); line-height: 1.8; margin: 4px 0 0; }
/* 方向注（「越高越难读」）：贴着标签走小字，不占一列。 */
.pace-row i u { text-decoration: none; font-size: 10px; color: var(--muted); opacity: .8; margin-left: 3px; }
.pace-facts { margin-top: 12px; }

/* 书目页的站内徽章 */
.badge-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; }
.badge { font-size: 10.5px; line-height: 1; padding: 5px 8px; border-radius: 999px;
  border: 1px solid var(--line-strong); color: var(--ink-2); background: var(--surface); }
.badge:first-child { border-color: var(--accent); color: var(--accent); }

/* ---------- 阅读成就抽屉 ---------- */
.achv-drawer { width: min(520px, 100%); }
.achv-body { padding: 16px 20px 40px; overflow-y: auto; flex: 1; }
.achv-top { margin-bottom: 14px; }
.achv-total { display: flex; align-items: baseline; gap: 6px; }
.achv-total b { font-family: var(--serif); font-size: 30px; line-height: 1; color: var(--accent); font-variant-numeric: tabular-nums; }
.achv-total span { font-size: 12px; color: var(--muted); }
.achv-bar { height: 4px; border-radius: 2px; background: var(--surface-2); overflow: hidden; margin-top: 8px; }
.achv-bar i { display: block; height: 100%; background: var(--accent); opacity: .8; }
.achv-bar.big { width: 160px; height: 5px; }
.achv-lead { font-size: 11.5px; color: var(--muted); line-height: 1.7; margin: 8px 0 0; }
.achv-tabs { display: flex; gap: 4px; flex-wrap: wrap; padding: 10px 0 12px; border-bottom: 1px solid var(--line); }
.achv-tabs button { padding: 5px 9px; border-radius: 999px; font-size: 12px; color: var(--muted);
  border: 1px solid transparent; transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease); }
.achv-tabs button:hover { color: var(--ink); }
.achv-tabs button.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.achv-tabs button i { font-style: normal; font-size: 10.5px; opacity: .7; margin-left: 4px; }
.achv-list { padding-top: 6px; }
.achv-card { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px dashed var(--line); align-items: flex-start; }
.achv-card:last-child { border-bottom: none; }
.achv-seal { flex: none; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--serif); font-size: 15px; color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--line); }
.achv-card.on .achv-seal.t1 { color: #7a5a2c; border-color: #c9a06a; background: #f0e2cc; }
.achv-card.on .achv-seal.t2 { color: #54595f; border-color: #a9b0b7; background: #e6e9ec; }
.achv-card.on .achv-seal.t3 { color: #8a6a1c; border-color: #d8b45a; background: #f5e9c8; }
[data-theme="dark"] .achv-card.on .achv-seal.t1 { color: #e0c294; border-color: #7a5f33; background: #2c2418; }
[data-theme="dark"] .achv-card.on .achv-seal.t2 { color: #d3d8dd; border-color: #5a6169; background: #23262a; }
[data-theme="dark"] .achv-card.on .achv-seal.t3 { color: #f0d68a; border-color: #8a6f28; background: #2e2716; }
.achv-main { min-width: 0; flex: 1; }
.achv-h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.achv-h b { font-family: var(--serif); font-size: 14.5px; }
.achv-card:not(.on) .achv-h b { color: var(--muted); }
.achv-tier { font-size: 10px; line-height: 1; padding: 3px 5px; border-radius: var(--r-sm); border: 1px solid var(--line-strong); color: var(--muted); }
.achv-tier.t3 { color: var(--gold); border-color: var(--gold); }
.achv-date { font-size: 10.5px; color: var(--muted); margin-left: auto; font-variant-numeric: tabular-nums; }
.achv-main p { font-size: 12px; color: var(--muted); line-height: 1.6; margin: 4px 0 7px; }
.achv-card.on .achv-main p { color: var(--ink-2); }
.achv-foot { font-size: 11px; color: var(--muted); margin-top: 5px; }

/* ---------- 百科词条层（概述 / 设定 / 角色分组 / 评价 / 分卷） ----------
   这一层对着百度百科的「文学作品类词条」体例做：概述是「首段定义 + 主需段」，
   设定是定义列表，评价必须带评价方，分卷是表。样式上刻意比正文更「书」一点
   ——左边一道竖线陈述，不铺卡片，免得整页都是框。 */

/* 概述：左线 + 首段正文 + 主需段 */
.ovbox { border-left: 2px solid var(--line-strong); padding-left: var(--s4); }
.ov-lead {
  margin: 0 0 var(--s3); font-size: var(--t-base); line-height: 1.95;
  color: var(--ink); text-align: justify;
}
/* 主需段：小节名在上、正文在下。原来用「· 字段：正文」的行内写法，
   加上伪元素项目符号与冒号，读起来像一张表格的渲染结果，不像词条。 */
.ov-need {
  position: relative; margin: 0 0 11px; padding-left: 0;
  font-size: 13px; line-height: 1.9; color: var(--ink-2); text-align: justify;
}
.ov-need b {
  display: block; font-family: var(--sans); font-weight: 600;
  font-size: 11.5px; letter-spacing: .1em; color: var(--muted);
  margin-bottom: 1px; line-height: 1.6;
}
.ov-need p { margin: 0; }

/* 自动词条的「平台原文」折叠块。概述的「内容」段是原文按句截断，
   全文收在这里：既不让长简介把整页顶下去，也保证一个字都没删。 */
.ovsrc { margin-top: var(--s3); background: var(--surface); }
.ovsrc summary { font-size: 12px; }
.ovsrc .intro-text { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-2); }
.ovsrc .intro-text p { margin: 0 0 8px; }

/* 角色：按阵营分组。.chars 本身是两列网格，分组版改成块级，组内再两列 */
.chars.chrgroup { display: block; }
/* 角色按阵营分组，组内固定网格。原来写死 2 列，组里只有 1 人时那张卡
   独占半行、旁边空着，看着像瀑布流错位；改 auto-fill 后列宽由容器宽度
   决定，人少不会撑开、人多不会挤窄，各组的左缘也就对齐了。 */
.chargrp {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px; margin-bottom: var(--s3); align-items: stretch;
}
.chargrp-h {
  grid-column: 1 / -1; font-size: var(--t-xs); letter-spacing: .08em;
  color: var(--muted); padding-bottom: 3px; border-bottom: 1px solid var(--line);
}

/* 世界观设定：定义列表，术语在左、解释在右，行间虚线 */
.setlist { margin: 0; padding: 0; border-top: 1px solid var(--line); }
.setrow {
  display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: var(--s3);
  padding: 9px 0; border-bottom: 1px dashed var(--line);
}
.setrow dt {
  font-family: var(--serif); font-size: 12.5px; color: var(--accent);
  line-height: 1.9;
}
.setrow dd { margin: 0; font-size: 12.5px; line-height: 1.85; color: var(--ink-2); }

/* 作品评价：引言块。左边一道金线——和获奖的赭红、节奏的中性灰区分开 */
.revq {
  margin: 0 0 10px; padding: 10px 14px; background: var(--surface);
  border: 1px solid var(--line); border-left: 2px solid var(--gold);
  border-radius: 0 var(--r) var(--r) 0;
}
.revq p { margin: 0 0 4px; font-size: 13px; line-height: 1.85; color: var(--ink-2); }
.revq cite { font-style: normal; font-size: var(--t-xs); color: var(--muted); }

/* 分卷：一张小表。序号用等宽数字，卷名占满剩余宽度 */
.volbox {
  border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; background: var(--surface);
}
.volrow {
  display: flex; align-items: baseline; gap: var(--s3);
  padding: 8px 13px; border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.volrow:last-of-type { border-bottom: 0; }
.volrow i {
  font-style: normal; font-size: 10px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.volrow span { flex: 1; color: var(--ink); }
.volrow em { font-style: normal; font-size: 11px; color: var(--muted); }
.vol-sum {
  margin: 0; padding: 8px 13px; font-size: 11px; color: var(--muted);
  background: var(--surface-2);
}

/* 创作背景与正文同排版，只把行距收一点 */
.bgtext { font-size: 13px; }

/* 出处：整页最后一行，字号最小。它的作用是让「编辑整理」四个字可被核对 */
.entry-ref {
  margin: var(--s5) 0 0; padding-top: var(--s3);
  border-top: 1px dashed var(--line);
  font-size: 11px; line-height: 1.9; color: var(--muted);
}
/* 收尾：长词条读到最末是「词条依据」小灰字，页面就地结束，没有结束感，
   想回顶部还要反向滚。给一句结束语 + 一个回顶入口。 */
.entry-end {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin: 20px 0 6px; padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 11.5px; color: var(--muted);
}
.entry-end button {
  font-size: 11.5px; color: var(--accent); padding: 3px 10px;
  border: 1px solid var(--line); border-radius: 999px;
}
.entry-end button:hover { border-color: var(--accent); background: var(--accent-soft); }

/* ---------- 词条页内目录 ----------
   目录由 DOM 里实际渲染出的板块生成（assets/app.js 的 buildToc），
   所以板块换序、增删都不用再同步第二份清单。做成顶部吸顶的一条，
   长词条里随时能跳——不是侧边固定栏，窄屏也不会挡正文。 */
.entry-toc {
  position: sticky; top: 0; z-index: 7;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin: 0 0 var(--s4); padding: 7px 0 8px;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.entry-toc::-webkit-scrollbar { display: none; }
.toc-h {
  flex: 0 0 auto; font-size: var(--t-xs); letter-spacing: .14em;
  color: var(--muted); padding-right: 9px; border-right: 1px solid var(--line);
}
.entry-toc a {
  flex: 0 0 auto; font-size: 12px; color: var(--ink-2); text-decoration: none;
  padding: 2px 9px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); white-space: nowrap; cursor: pointer;
  transition: color var(--quick) var(--ease), border-color var(--quick) var(--ease);
}
.entry-toc a:hover { color: var(--accent); border-color: var(--accent); }
.entry-toc a.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
/* 目录默认只放前 6 项，其余收在「更多」后面：12–16 项挤两行，
   视觉上像一条杂讯，而真正高频的跳转只有前几个板块。 */
.entry-toc.folded a.toc-x { display: none; }
.entry-toc .toc-more {
  flex: 0 0 auto; font-size: 12px; color: var(--muted); cursor: pointer;
  padding: 2px 9px; border: 1px dashed var(--line-strong); border-radius: 999px; background: none;
}
.entry-toc .toc-more:hover { color: var(--accent); border-color: var(--accent); }
/* 吸顶目录会盖住跳转目标，给板块标题留出这条的高度 */
.drawer-body .section-h[id] { scroll-margin-top: 44px; }

/* ---------- 章节列表 ---------- */
.chapbox {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface); padding: 11px 13px;
}
.chap-meta {
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums;
  padding-bottom: 8px; border-bottom: 1px dashed var(--line); margin-bottom: 9px;
}
/* 章节目录：有序列表用两列网格承载，不用 chip 流。
   原来 flex-wrap + 圆角底色，两章并排会被读成一句长标题，序号也丢了。 */
.chapnames { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px 20px; }
.chapnames span {
  display: flex; align-items: baseline; gap: 7px;
  font-size: 12.5px; color: var(--ink-2); padding: 3px 0;
  background: none; border-radius: 0; line-height: 1.75;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chapnames span i {
  flex: 0 0 auto; font-style: normal; color: var(--muted);
  font-size: 11.5px; font-variant-numeric: tabular-nums; letter-spacing: .01em;
}
@media (max-width: 720px) { .chapnames { grid-template-columns: 1fr; } }
.chapvol {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--serif); font-size: 12.5px; color: var(--accent);
  margin: 11px 0 7px; padding-bottom: 4px; border-bottom: 1px solid var(--line);
}
.chapvol:first-child { margin-top: 0; }
.chapvol i { font-style: normal; font-family: var(--sans); font-size: 11px; color: var(--muted); }
.chap-empty { margin: 0; font-size: 12.5px; color: var(--muted); }
/* 折在 .chapbox 里的 details 不要再套一层边框 */
.chapfold { border: 0; padding: 0; background: transparent; }
.chapfold > summary { margin-bottom: 8px; }
.chapbox .volbox { border: 0; background: transparent; }
.chapbox .vol-sum { background: transparent; padding-left: 0; padding-right: 0; }

/* ---------- 衍生作品介绍 ----------
   左边一道金线，和「作品评价」同一套语言（都是「别的材料怎么讲这本书」）；
   基本信息横排、简介单独一段，扫一眼就知道是什么形式、哪一年、改到哪。 */
.derlist { display: flex; flex-direction: column; gap: 10px; }
.dercard {
  border: 1px solid var(--line); border-left: 2px solid var(--gold);
  border-radius: 0 var(--r) var(--r) 0; background: var(--surface);
  padding: 11px 14px;
}
.der-h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.der-k {
  font-size: 10.5px; letter-spacing: .06em; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 3px; padding: 0 5px;
  line-height: 1.6; flex: 0 0 auto;
}
.der-h b { font-family: var(--serif); font-size: 14px; font-weight: 600; color: var(--ink); }
.der-h em { font-style: normal; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.der-info { display: flex; flex-wrap: wrap; gap: 3px 18px; margin: 6px 0 0; }
.der-info div { display: flex; gap: 6px; font-size: 12px; }
.der-info dt { color: var(--muted); }
.der-info dd { margin: 0; color: var(--ink-2); }
.der-plat { margin: 5px 0 0; font-size: 12px; color: var(--muted); }
.der-intro { margin: 7px 0 0; font-size: 12.5px; line-height: 1.85; color: var(--ink-2); }
/* 没有核实过的简介就明说，不拿「改编自本书」凑一句 */
.der-nointro { margin: 7px 0 0; font-size: 12px; line-height: 1.7; color: var(--muted); }

/* B 站相关视频：统计在上、条目在下，整块是页面最后一段 */
.bili-sec { margin-top: var(--s6); }
.bili-sec .winbar { margin-bottom: var(--s4); }

@media (max-width: 720px) {
  .chargrp { grid-template-columns: minmax(0, 1fr); }
  .setrow { grid-template-columns: 76px minmax(0, 1fr); }
  .der-info { gap: 2px 12px; }
  /* 窄屏上十几个板块换行会吃掉四行高度，改成单行横向滑动；
     两端加渐隐，让人看得出来「右边还有」。右端留 14px 免得把「更多」也虚掉。 */
  .entry-toc {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    padding-right: 14px;
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 18px), transparent);
            mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 18px), transparent);
  }
  .entry-toc::-webkit-scrollbar { display: none; }
  .entry-toc .toc-h { position: sticky; left: 0; background: var(--bg); z-index: 1; }
}

/* ===== 按需加载 · 骨架屏与状态反馈（2026-11-06）
   骨架项挂现有组件类，版式与断点全继承，这里只补灰块与呼吸；
   sk-（骨架与状态）｜srcbanner（降级横幅）。尺寸与 DOM 见 docs/骨架屏规范.md */
:root{--sk-tint:#c1bdb2;--sk-tint-hi:#aca89e;
 --sk-tint:color-mix(in srgb,var(--surface-2) 80%,var(--ink) 20%);
 --sk-tint-hi:color-mix(in srgb,var(--surface-2) 70%,var(--ink) 30%);
 --sk-text-2:color-mix(in srgb,var(--muted) 70%,var(--ink) 30%)}
[data-theme=dark]{--sk-tint:#4c4940;--sk-tint-hi:#615d54;--sk-text-2:#b4ae9d}
/* 一行「字」= 一个 .sk-b：高 9px，行距用 margin；相邻第二行自动收 72% */
.sk-b{display:block;border-radius:3px;background:var(--sk-tint)}
.sk-b:not(.sk-cv){height:9px}
.sk-b+.sk-b{width:72%}
.sk-b.sk-cv{background:var(--sk-tint)}
.sk-root .sk-b{opacity:0}                              /* 视图切换：200 ms 内不画 */
.sk-root.sk-on .sk-b,.sk-root.sk-static .sk-b{opacity:1;animation:sk-pulse 1.6s var(--ease) infinite}
@keyframes sk-pulse{50%{background-color:var(--sk-tint-hi)}}
.sk-sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
/* 骨架上方那行字：不用 opacity 弱化（12.5px 压 55% 只剩 2.2:1） */
.sk-say{margin:0 0 12px;text-align:center;font-size:12.5px;line-height:1.7;color:var(--ink-2)}
.sk-say span{margin-left:8px;font-size:12px;color:var(--sk-text-2)}

/* 1 网格 / 首屏 */
.sk-card{pointer-events:none}
.sk-t{display:flex;flex-direction:column;justify-content:center;gap:7px;height:45px;margin:0 0 3px}
.sk-t .sk-b{height:13px}
.sk-t .sk-b:first-child{width:86%}
.sk-a{display:flex;align-items:center;height:19px;margin-bottom:6px}
.sk-a .sk-b{width:38%}
.sk-intro,.sk-x-on .sk-x{display:flex;flex-direction:column}
.sk-x{display:none}
.sk-x .sk-b{margin:5px 0}
.sk-f{display:flex;justify-content:space-between;align-items:center;height:17px;margin-top:8px}
.sk-f .sk-b{width:46px}

/* 2 紧凑列表 */
.grid.list .sk-card .cbody{display:flex;flex-direction:column;gap:5px}
.grid.list .sk-t{flex:1;height:23px;margin:0;gap:3px}
.grid.list .sk-t .sk-b{height:10px}
.grid.list .sk-a,.grid.list .sk-f{display:none}

/* 3 详情 */
.sk-dhead>div>.sk-b{width:58%;height:24px;margin:2px 0 8px}
.sk-dhead>div>.sk-b+.sk-b{width:40%;height:9px;margin:0 0 11px}
.sk-drate .sk-b{width:56px;height:22px}
.sk-drate .sk-b:last-child{width:88px;height:9px}
.sk-dbtn .sk-b{width:96px;height:34px;border-radius:var(--r);margin-top:22px}
.section-h .sk-b{width:52px}
.sk-intro .sk-b{width:100%;height:11px;margin:8px 0}
.sk-intro .sk-b:last-child{width:62%}
.meta-table .sk-b{width:64%;margin:5px 0}
.sk-char{height:88px}
.sk-char .sk-b{margin-top:8px}
.sk-char .sk-b:first-child{width:34%;height:12px;margin-top:2px}
.sk-hot .sk-b{width:34px}
.sk-hot .sk-b:nth-child(2){width:128px;height:5px}
.sk-hot .sk-b:last-child{width:46px;height:15px}
.hc-row .sk-b{width:64px;margin:5px 0}
.hc-row .sk-b:nth-child(2){flex:1;height:5px;margin:0}
.sk-rel>div>div{flex:1;min-width:0}
.sk-rel>div>div .sk-b{width:88%;margin-bottom:9px}

/* 4 榜单 */
.sk-row .sk-main .sk-b{width:62%;margin-bottom:8px}
.sk-row .sk-main .sk-b:last-child{width:38%;height:8px;margin:0}
.sk-row>.sk-cv{width:38px}
.sk-row>.sk-b:last-child{width:38px;justify-self:end}
.sk-rest{height:828px}

/* 5 作者页 */
.sk-ahead>div>.sk-b{width:46%;margin-bottom:11px}
.sk-ahead>div>.sk-b:first-child{width:34%;height:24px;margin:2px 0 15px}
.sk-astat .sk-b{width:60%;margin:6px 0}
.sk-astat .sk-b:last-child{width:80%;height:8px;margin:6px 0 0}
.sk-aw .sk-b:nth-child(2){width:52%}
.sk-aw .sk-b:last-child{width:88%;height:5px}

/* 6 统计弹窗 */
.sk-sbox .sk-b:first-child{width:72%;height:16px;margin:4px 0 9px}
.sk-sbox .sk-b:last-child{width:56%;height:8px}
.sk-brow .sk-b{margin:5px 0}
.sk-brow .sk-b:nth-child(2){height:7px;border-radius:4px}
.sk-brow .sk-b:last-child{width:30px;justify-self:end}

/* 7 书架 / 猜你喜欢 */
.sk-shelf>div>div{flex:1;min-width:0}
.sk-shelf>div>div .sk-b{width:64%;margin-bottom:9px}
.sk-shelf>div>div .sk-b:last-child{width:40%;margin:0}
.sk-why{width:70%;height:8px;margin-top:6px}

/* 8 「再看 N 部」载入中：定宽 132 防抖动 */
.sk-loadbtn{min-width:132px;justify-content:center}
.sk-loadbtn[aria-busy=true],.sk-loadbtn[aria-busy=true]:hover{color:var(--sk-text-2);border-color:var(--line);cursor:default}

/* 9 错误卡：位置与内距 = .emptystate */
.sk-err{padding:72px 20px;text-align:center}
.sk-err b{display:block;margin-bottom:6px;font-family:var(--serif);font-size:19px;font-weight:600;color:var(--accent)}
.sk-err p{margin:0 0 18px;font-size:13px;color:var(--ink-2)}

/* 10 降级横幅（不是故障，不用赭红） */
.srcbanner{position:sticky;top:var(--topbar-h);z-index:39;background:var(--surface);
 border-bottom:1px solid var(--line-strong)}
.srcbanner-in{display:flex;align-items:center;flex-wrap:wrap;gap:6px 12px;padding:9px 0}
.srcbanner-t{padding-left:10px;border-left:3px solid var(--gold);font-size:13.5px;font-weight:600;color:var(--ink)}
.srcbanner-d{flex:1;min-width:180px;font-size:12.5px;line-height:1.7;color:var(--ink-2)}
.srcbanner .btn{height:28px;padding:0 11px;font-size:12.5px}
.srcbanner-x{width:30px;height:30px;flex:none;display:grid;place-items:center;border-radius:var(--r-sm);color:var(--ink-2)}
.srcbanner-x:hover{background:var(--surface-2);color:var(--ink)}

/* 侧栏 loading（门类 8 行，挂 .catlist li button）；计数条上次值灰显 */
.sk-cat{min-height:30px}
.sk-cat .sk-b{width:62%}
.sk-cat .sk-b:last-child{width:22%;height:8px;margin-left:auto}
.sk-dim,.sk-dim b{color:var(--sk-text-2)}

@media (max-width:720px){
 .sk-t{height:41px}
 .sk-t .sk-b{height:12px}
 .sk-x-on .sk-x{display:none}
 .srcbanner{position:static}
 .srcbanner-d{min-width:100%;order:3}}
@media (prefers-reduced-motion:reduce){
 .sk-root .sk-b{animation:none}}

/* 390 档 hero：发布日期整体换行、绝不拆成 2026-11- / 06 */
#updated{white-space:nowrap}
@media (max-width:720px){
 .hero-stats>span:last-child{grid-column:span 2}}

/* ---------- 账号：登录 / 注册 / 改密（2026-11-06） ---------- */
/* 表单比统计弹窗窄：三行输入铺在 760px 里会拉成一条长线，眼睛要横着跑。
   420px 接近常见表单的舒适宽度，也让「注册 / 登录」两个动作显得轻。 */
#authModal { width: min(420px, calc(100% - 32px)); }
.af-row { display: block; margin-top: var(--s4); }
.af-k {
  display: block; font-size: var(--t-xs); color: var(--muted);
  margin-bottom: 6px; letter-spacing: .02em;
}
.af-in {
  width: 100%; height: 38px; padding: 0 11px;
  border: 1px solid var(--line-strong); border-radius: var(--r);
  background: var(--bg); color: var(--ink);
  font-size: var(--t-base); font-family: var(--sans);
  transition: border-color var(--quick) var(--ease), background var(--quick) var(--ease);
}
.af-in:focus { outline: none; border-color: var(--accent); background: var(--surface); }
.af-in::placeholder { color: var(--muted); opacity: .7; }
/* 校验未过只换边框色：不加图标、不铺红底。错在哪一句已经由下面那行文字说了，
   输入框再喊一遍会让人以为「整个表单都错了」。 */
.af-in.bad { border-color: var(--accent); }
.af-tip { font-size: var(--t-xs); color: var(--accent); margin: 5px 0 0; }
.af-tip:empty { display: none; }
.af-err {
  margin: var(--s4) 0 0; padding: 9px 11px; border-radius: var(--r);
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid rgba(154, 45, 33, .18);
  font-size: var(--t-sm); line-height: 1.5;
}
.af-submit {
  width: 100%; height: 40px; justify-content: center;
  margin-top: var(--s5); font-size: var(--t-md);
}
.af-submit[disabled] { opacity: .55; pointer-events: none; }
.af-switch {
  text-align: center; font-size: var(--t-sm); color: var(--muted);
  margin: var(--s4) 0 0;
}
.linkbtn {
  color: var(--accent); font-size: inherit;
  text-decoration: underline; text-underline-offset: 3px;
}
.linkbtn:hover { color: var(--accent-2); }
.af-me {
  display: flex; align-items: baseline; gap: var(--s3);
  padding: var(--s2) 0 var(--s3);
}
.af-me b { font-family: var(--serif); font-size: var(--t-lg); font-weight: 600; }
.af-me span { font-size: var(--t-xs); color: var(--muted); }
/* 已登录时顶栏那个入口的文字就是用户名，太长要收，不然把「统计」挤走 */
#authLbl { max-width: 7em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
