/* ============================================================
   辰枢紫微子平排盘网页系统 · 站点外壳样式
   国风素雅 · 深色金调 · PC + 移动端自适应
   注：本文件在 engine.css 之后加载，用于站点外壳；排盘台内部样式仍由 engine.css 负责。
   ============================================================ */

:root {
  --bg: #0e1018;
  --bg2: #12161f;
  --card: #161a27;
  --card2: #1c2133;
  --line: #2a3147;
  --line2: #3a4260;
  --gold: #d4af37;
  --gold2: #d3c193;
  --txt: #e2e6f2;
  --sub: #aab2cc;
  --dim: #7d85a2;
  --lu: #4cc38a;
  --quan: #e07850;
  --ke: #5b9bd5;
  --ji: #d45d79;
  --ok: #4cc38a;
  --warn: #e0b050;
  --err: #d45d79;

  --radius: 14px;
  --radius-sm: 10px;
  --nav-h: 62px;
  --maxw: 1180px;
  --font: -apple-system, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  --font-serif: "Noto Serif SC", "Songti SC", "STSong", serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  background: var(--bg);
  color: var(--txt);
  font: 15px/1.75 var(--font);
  background-image: radial-gradient(ellipse 80% 46% at 50% -12%, rgba(212, 175, 55, .10), transparent);
  min-height: 100vh;
}

a { color: var(--gold2); text-decoration: none; }
a:hover { color: var(--gold); }
img { max-width: 100%; }
button { font-family: inherit; cursor: pointer; }
input, select, textarea { font-family: inherit; }

/* ---------------- 顶部导航 ---------------- */
/* 底色**必须跟随页面**：先铺 var(--bg)，再叠加与 body **同几何**的一条顶部金色光晕，
   使吸顶导航与页面之间不出现色差接缝。
   （此前此处写死 rgba(14,16,24,.92) 深蓝底 —— 浅色主题下页面是米色 #f6f2e7，
     导航却仍是深蓝，造成「顶部被改成深色」的撞色；写死色无法随主题切换，已废弃。）

   ⚠️ 光晕**必须用绝对 px，不能用百分比**：body 的径向渐变按 body 盒（整页高）定标，
   页面顶端处 alpha ≈ 0.074；若照抄 `ellipse 80% 46% at 50% -12%` 到只有 62px 高的导航上，
   椭圆会被压缩成 ry≈28px，实测 alpha 掉到 ≈0 → 导航比页面**偏冷发白**，反而出现横向色带。
   下面按 body 的「圆心/纵向半径比」等比换算（深色 -12%/46% → 圆心 -156px、ry 600px；
   浅色 -10%/50% → 圆心 -120px、ry 600px），页面顶端 alpha 与 body 完全对齐。 */
.site-nav {
  position: sticky; top: 0; z-index: 90;
  height: var(--nav-h);
  /* ★ 关键修复：导航作为 sticky 遮挡层，其**底色必须完全不透明**。
     此前金色光晕是以 background-image 直接叠在元素自身背景上，
     该图层 alpha≈0.10，使导航在吸顶状态下**挡不住**从下方穿过的免责文字，
     表现为「免责文字压在导航栏上」的重叠（用户实机照片已确认）。
     现把光晕移到 ::before 伪元素、并给伪元素加 isolation，使其只与导航底色合成，
     导航本身背景保持纯色 var(--bg) 完全不透明 → 真正盖住下层文字。
     光晕观感保留（视觉不变），仅合成层次改变。 */
  background: var(--bg);
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
/* sticky 本身即建立定位上下文，故 ::before 的 inset:0 会正确定位到导航盒内。 */
/* 金色光晕层：圆心与纵向半径沿用原参数，保持页面顶端观感一致 */
.site-nav::before {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background-image: radial-gradient(ellipse 80% 600px at 50% -156px, rgba(212, 175, 55, .10), transparent);
}
.site-nav .inner {
  max-width: var(--maxw); margin: 0 auto; height: 100%;
  display: flex; align-items: center; gap: 18px; padding: 0 18px;
}
.brand { display: flex; align-items: center; gap: 9px; flex-shrink: 0; }
.brand .mark {
  width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center;
  background: linear-gradient(135deg, #e8d48b, #c9a63a); color: #0e1018; font-size: 17px; font-weight: 700;
}
.brand .txt { font-family: var(--font-serif); font-weight: 700; font-size: 17px; letter-spacing: .5px;
  background: linear-gradient(180deg, #e9dcb3, #c9a63a 75%, #9c7a26);
  -webkit-background-clip: text; background-clip: text; color: transparent; white-space: nowrap; }
/* 导航项：等距横排、与品牌中线垂直对齐；选中 / 悬停统一以 **2px 下划线** 表达
   （导航排列复核：按设计稿替换原「圆角色块」选中态，五个标签形成一条整齐基线，
     间距由 4px 提到 6px、内边距 7/12 提到 8/13，视觉上更舒展、不拥挤）。 */
.nav-links { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.nav-links a {
  position: relative; color: var(--sub); font-size: 14px; padding: 8px 13px;
  border-radius: 9px; white-space: nowrap; transition: color .2s;
}
.nav-links a::after {
  content: ''; position: absolute; left: 13px; right: 13px; bottom: 3px; height: 2px;
  border-radius: 2px; background: var(--gold);
  transform: scaleX(0); transform-origin: center; opacity: 0;
  transition: transform .22s ease, opacity .22s ease;
}
.nav-links a:hover { color: var(--gold2); }
.nav-links a:hover::after { transform: scaleX(1); opacity: .55; }
.nav-links a.active { color: var(--gold2); }
.nav-links a.active::after { transform: scaleX(1); opacity: 1; }

/* ============================================================
   ★ 2026-10-15 UI 修复：导航下拉菜单 + 研习助手常驻
   ------------------------------------------------------------
   修复前问题：`.nav-links` 带 overflow:hidden，菜单项增多后
   「研习助手」被横向裁切（只剩图标甚至整项不可见）。
   本次改动：
     1) 去掉 overflow:hidden，改用 min-width:0 保证不被裁切；
     2) 新增 .nav-drop hover 下拉（命例：命例对照 / 命例管理）；
     3) 研习助手图标+ 完整文字常驻，游客亦可见（转化引流）。
   ============================================================ */

/* 一级项本体为 <a>（可点击跳转），故补齐与其它导航一致的 hover / 下划线行为。
   ★ 样式统一要点（2026-10-15 · 二次修正）：
     .nav-links 是 flex 容器且 align-items:center，**直接子级<a> 会被拉伸成
     flex item 并居中对齐**；而 .nav-drop 是 flex item（flex-shrink:0），
     其内部的 <a> 仍是普通 inline，导致两者**基线与行高不一致**，
     视觉上「文字偏小、发虚、与相邻菜单不齐」。
     修法：把 .nav-drop 也设为 flex 容器 + align-items:center，
     内部 <a> 用 inline-block，让一级项与 .nav-links a 的排版模型完全一致；
     再显式补line-height 与 letter-spacing，杜绝字间距差异。 */
.nav-drop {
  position: relative; flex-shrink: 0;
  display: flex; align-items: center;
}
.nav-drop > .nav-drop-t {
  position: relative; display: inline-block;
  color: var(--sub); font-size: 15px; font-weight: inherit;
  line-height: inherit; letter-spacing: inherit;
  padding: 8px 13px; border-radius: 9px; white-space: nowrap;
  transition: color .2s;
}
.nav-drop > .nav-drop-t .caret {
  display: inline-block; width: 0; height: 0; margin-left: 4px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid currentColor; opacity: .6;
  vertical-align: middle; position: relative; top: -1px;
  transition: transform .2s ease;
}
.nav-drop > .nav-drop-t::after {
  content: ''; position: absolute; left: 13px; right: 13px; bottom: 3px; height: 2px;
  border-radius: 2px; background: var(--gold);
  transform: scaleX(0); transform-origin: center; opacity: 0;
  transition: transform .22s ease, opacity .22s ease;
}
.nav-drop:hover > .nav-drop-t, .nav-drop:focus-within > .nav-drop-t { color: var(--gold2); }
.nav-drop:hover > .nav-drop-t::after { transform: scaleX(1); opacity: .55; }
.nav-drop > .nav-drop-t:focus-visible { outline: 2px solid var(--gold2); outline-offset: 2px; }
/* 当前页位于子菜单时，一级项也点亮 */
.nav-drop.open > .nav-drop-t { color: var(--gold2); }
.nav-drop.open > .nav-drop-t::after { transform: scaleX(1); opacity: 1; }
.nav-drop:hover > .nav-drop-t .caret, .nav-drop:focus-within > .nav-drop-t .caret { transform: rotate(180deg); }

/* 下拉菜单本体：hover / focus-within 触发，移开自动收起（纯 CSS，无需 JS） */
.nav-drop-menu {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 132px;
  background: var(--card, #151927);
  border: 1px solid var(--line2, #3a4459);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .38);
  padding: 5px;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
  z-index: 96;
}
.nav-drop:hover > .nav-drop-menu,
.nav-drop:focus-within > .nav-drop-menu,
/* ★ 2026-10-17：点击标题切换 .open 展开（PC 端点击不再闪一下消失）。
   与 hover 态并列生效，两种交互互不覆盖。 */
.nav-drop.open > .nav-drop-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.nav-drop-menu a {
  display: block; padding: 8px 12px; border-radius: 7px;
  font-size: 13.5px; color: var(--sub); white-space: nowrap;
}
.nav-drop-menu a:hover { background: rgba(232, 200, 106, .12); color: var(--gold2); }
.nav-drop-menu a.active { color: var(--gold2); background: rgba(232, 200, 106, .10); }
.nav-drop-menu a::after { display: none; }   /* 子菜单不画下划线，避免与父级叠加 */

/* 研习助手：图标 + 完整文字常驻一级导航（游客亦可见）
   ★ 2026-10-15 调整：此前用 color:var(--gold2) !important 强制金色，
     视觉上与「当前页 active」高亮同色，误以为被选中。
     现改为与其它一级菜单完全一致的常规灰字，仅 hover 时提亮，
     且永不显示 active 下划线（它是功能按钮，不是页面导航）。
     注：实际生效样式统一放在下方 8.1 节（.nav-links a.nav-asst），
     此处只保留文字不换行等补充属性，避免两处规则权重打架。 */
.nav-asst { white-space: nowrap; flex-shrink: 0; }
.nav-asst-txt { display: inline; }           /* 强制完整文字，不允许被压成图标 */
.nav-asst:focus-visible { outline: 2px solid var(--gold2); outline-offset: 2px; }
/* 右侧：登录 / 注册挨成一组（间距 10px）；主题按钮再单独拉开 14px
   —— 对应设计稿中交由「日间 / 夜间模式」独立悬浮的意图；
   它仍是导航最右端**唯一**主题入口（verify_theme_scope G10 判据不变）。 */
.nav-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.nav-right .btn.sm { padding: 7px 17px; }
.nav-right .csthemebtn { margin-left: 14px; }

.nav-user { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--sub); min-width: 0; }
/*昵称限宽 + 省略号：避免长昵称（如「系统管理员」）把右侧退出按钮挤出/换行 */
.nav-user .uname {
  max-width: 96px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; flex-shrink: 1; min-width: 0;
}
.vip-badge {
  font-size: 11px; padding: 2px 8px; border-radius: 99px;
  background: linear-gradient(135deg, #e8d48b, #d4af37); color: #0e1018; font-weight: 700;
}
.free-badge { font-size: 11px; padding: 2px 8px; border-radius: 99px; border: 1px solid var(--line2); color: var(--dim); }
.menu-btn { display: none; background: none; border: none; color: var(--txt); font-size: 22px; padding: 4px 8px; }

/* ---------------- 顶部导航：窄屏折叠（≤960px） ----------------
   品牌 + 五项标签 + 登录/注册 + 主题按钮排成一行约需 923px（含左右内边距）；
   视口不足时标签会被 overflow 裁切、右端还会溢出。故自 960px 起折叠为
   「品牌 + 主体按钮 + 汉堡」：
     · 品牌允许收缩并加省略号，杜绝右端溢出；
     · 五项标签收进汉堡面板（竖排），选中态由下划线改为左侧短竖条；
     · 登录/注册与主题同步收窄，仍保持桌面端次序（登录 → 注册 → 主题）。
   位置说明：本段**必须**排在 .menu-btn 基线规则之后 —— 两者特异性同为 (0,1,0)，
   靠后者生效；若前置，.menu-btn{display:none} 会反向覆盖 .menu-btn{display:block}，
   导致窄屏看不到汉堡、菜单无法展开。 */
@media (max-width: 960px) {
  .site-nav .inner { gap: 10px; padding: 0 12px; }
  .brand { min-width: 0; flex-shrink: 1; }
  .brand .mark { flex-shrink: 0; }
  .brand .txt { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  .nav-links {
    position: fixed; top: var(--nav-h); left: 0; right: 0; flex-direction: column;
    background: var(--bg2); border-bottom: 1px solid var(--line); padding: 8px 12px 14px;
    gap: 2px; display: none; max-height: 70vh; overflow: auto;
  }
  .nav-links.on { display: flex; }
  .nav-links a { padding: 11px 12px 11px 14px; font-size: 15px; border-radius: 0; }
  .nav-links a::after { display: none; }
  .nav-links a.active::before {
    content: ''; position: absolute; left: 2px; top: 50%; transform: translateY(-50%);
    width: 3px; height: 16px; border-radius: 3px; background: var(--gold);
  }
  /* ★ 2026-10-15 移动端下拉适配：
     触屏无 hover，故窄屏改为「常驻平铺 + 父项可点击折叠」，
     保证命例两项在汉堡菜单里直接可点，不依赖 hover。 */
  /* ★ 2026-10-17 修正移动端「二级菜单飘到右侧」：
     基础规则 .nav-drop 是 display:flex（默认 row），为的是让标题与三角同行。
     移动端把 .nav-drop-menu 改成 position:static 后，它就成了 .nav-drop 的
     **第二个 flex item** —— 与一级标题并排成左右两列（实测左偏 287px，
     二级项被挤到屏幕右侧浮层区）。
     修法：窄屏下 .nav-drop 改为 column，标题在上、二级项在下正常下拉展开，
     二级项沿 padding-left:14px + border-left 与一级标题左侧对齐。 */
  .nav-drop { width: 100%; flex-direction: column; align-items: stretch; }
  .nav-drop > .nav-drop-t {
    width: 100%; padding: 11px 12px 11px 14px; font-size: 15px;
    border-radius: 0; justify-content: space-between;
  }
  .nav-drop > .nav-drop-t::after { display: none; }
  .nav-drop-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: none; background: transparent;
    padding: 0 0 0 14px; min-width: 0; display: block;
  }
  .nav-drop-menu a { padding: 9px 12px; font-size: 14px; border-left: 1px solid var(--line); border-radius: 0; }
  .nav-asst { width: 100%; padding: 11px 12px 11px 14px; font-size: 15px; border-radius: 0; }
  .nav-right { gap: 8px; }
  .nav-right .btn.sm { padding: 6px 12px; font-size: 12.5px; }
  .nav-right .csthemebtn { margin-left: 6px; width: 32px; height: 32px; font-size: 15px; }
  .nav-right .nav-user span.uname { display: none; }
  .menu-btn { display: block; }
}

/* ---------------- 免责声明条（全站常驻，不可折叠） ---------------- */
.disclaimer-bar {
  background: linear-gradient(90deg, rgba(212, 175, 55, .12), rgba(212, 175, 55, .05));
  border-bottom: 1px solid rgba(212, 175, 55, .22);
  font-size: 12.5px; color: var(--gold2); line-height: 1.6;
}
.disclaimer-bar .inner { max-width: var(--maxw); margin: 0 auto; padding: 9px 18px; }
.disclaimer-bar b { color: var(--gold); }

/* ---------------- P0 Bug1 修复 + 重叠修复：导航不透明遮挡免责条 ----------------
   【重叠 Bug】现象：移动端滚动页面时，顶部免责声明文字从 sticky 导航栏**底下穿过**，
     与导航栏的站名/登录/注册叠在同一区域，形成文字交叠（用户实机照片已确认）。
   【成因】#csNav(.site-nav, sticky, top:0, z-index:90) 与 #csDisclaimer(.disclaimer-bar)
     是 body 下的**兄弟元素**。导航吸顶后，免责条仍随文档滚动并从其下缘穿出。
     导航背景虽有 var(--bg)，但其上还有一层
     `background-image: radial-gradient(... rgba(212,175,55,.10) ...)`，
     在该图层覆盖处 alpha≈0.10，**挡不住下层文字** → 视觉重叠。

   【被否决的方案 · 留档】
     ① 给导航加 overflow:hidden —— 无效，免责条并非导航子元素，裁剪不到它。
     ② 让免责条自己 sticky 吸顶（top:var(--nav-h)）—— 确实不与导航重叠了，
        但免责条会**吸附固定在顶部并盖住下方内容**：实测把「保存为命例 /
        复制分享链接」按钮压在文字下面（_shots/v3_120.png 实测记录）。
        sticky 会让元素脱离正常阅读流，不适合这类随页面流动的说明文字。

   【本方案】保持免责条为**普通文档流元素**（不吸附、不脱离阅读流），
     改为让导航成为**完全不透明**的遮挡层：
     background-color 显式声明为 var(--bg) 并把渐变光晕压到渐变内部，
     使导航在吸顶时能真正盖住从下方穿过的免责文字，二者不再交叠。

   【P0 Bug1】窄屏（375–428px）免责文案动态换行会把下方 Tab 栏顶出首屏，
     故在移动端断点内限高 120px 并允许区块内滚动。
     ★ PC 端（>720px）保持原有的自然高度与原视觉效果，文字内容一字未删。 */
@media (max-width: 720px) {
  .disclaimer-bar { max-height: 120px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
  /* .inner 同步限高：免责文案全部包在 .inner 内，不加则滚动容器不会真正截断高度 */
  .disclaimer-bar .inner { max-height: 120px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
}

/* ---------------- 主体容器 ---------------- */
.page { max-width: var(--maxw); margin: 0 auto; padding: 26px 18px 60px; }
.page.narrow { max-width: 900px; }

.hero {
  text-align: center; padding: 40px 0 30px;
}
.hero .logo { font-size: 46px; line-height: 1; }
.hero h1 {
  font-family: var(--font-serif); font-weight: 700; font-size: clamp(24px, 4.2vw, 38px);
  letter-spacing: 2px; margin-top: 14px;
  background: linear-gradient(180deg, #e9dcb3, #c9a63a 72%, #9c7a26);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero .sub { color: var(--sub); font-size: 14px; letter-spacing: 1.5px; margin-top: 10px; }
.hero .badge-row { margin-top: 16px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.hero .badge-row span {
  font-size: 11.5px; color: var(--gold); border: 1px solid rgba(212, 175, 55, .32);
  border-radius: 99px; padding: 3px 13px; background: rgba(212, 175, 55, .07);
}

/* ---------------- 卡片 ---------------- */
.cs-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px; margin-bottom: 16px;
}
.cs-card > h3 {
  font-size: 15px; color: var(--gold2); letter-spacing: .8px; margin-bottom: 12px;
  display: flex; align-items: center; gap: 8px;
}
.cs-card > h3::before { content: "◆"; font-size: 9px; color: var(--gold); }
.cs-card > h3 small { color: var(--dim); font-weight: 400; font-size: 11.5px; margin-left: auto; }

/* ---------------- 宫格 ---------------- */
.grid { display: grid; gap: 14px; }
.grid.c2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.c4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.entry-card { cursor: pointer; transition: .22s; position: relative; overflow: hidden; }
.entry-card:hover { border-color: rgba(212, 175, 55, .42); transform: translateY(-2px); }
.entry-card .ico { font-size: 26px; }
.entry-card h4 { font-size: 15px; color: var(--gold2); margin: 10px 0 6px; letter-spacing: .5px; }
.entry-card p { font-size: 13px; color: var(--sub); line-height: 1.65; }
.entry-card .lock {
  position: absolute; top: 12px; right: 12px; font-size: 11px; color: var(--warn);
  border: 1px solid rgba(224, 176, 80, .4); border-radius: 99px; padding: 1px 8px;
}

/* ---------------- 研习助手入口卡（本次新增） ----------------
   同排其它卡用 emoji（.ico font-size:26px），本卡用单色机器人线条 SVG。
   线条图天然比彩色 emoji「视觉更轻」，不同尺寸就会显得这张卡偏矮，
   所以放大到 30px 并把图标行撑到固定高度 —— 三卡图标基线才对齐。
   ★ 只调图标，不动卡片 padding / h4 / p 字号，保证三卡尺寸完全一致。 */
.entry-card .ico .cs-robot-slot { display: flex; align-items: center; height: 30px; }
.entry-card .ico .cs-robot { width: 30px; height: 30px; stroke-width: 1.35; }
html[data-theme="light"] .entry-card .ico .cs-robot { color: var(--gold2); }

/* ---------------- 按钮 ---------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 10px 20px; border-radius: var(--radius-sm); border: 1px solid var(--line2);
  background: var(--card2); color: var(--txt); font-size: 14px; transition: .2s; white-space: nowrap;
}
.btn:hover { border-color: var(--gold); color: var(--gold2); }
.btn.primary {
  background: linear-gradient(135deg, #e8d48b, #d4af37); color: #0e1018; font-weight: 700; border: none;
}
.btn.primary:hover { filter: brightness(1.06); color: #0e1018; }
.btn.ghost { background: transparent; }
.btn.sm { padding: 6px 13px; font-size: 13px; }
.btn.block { width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* ---------------- 表单 ---------------- */
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 12.5px; color: var(--dim); margin-bottom: 6px; letter-spacing: .5px; }
.field input, .field select, .field textarea {
  width: 100%; padding: 11px 13px; border-radius: var(--radius-sm);
  background: var(--card2); border: 1px solid var(--line); color: var(--txt); font-size: 14px;
  outline: none; transition: .2s;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--gold); }
.field textarea { resize: vertical; min-height: 120px; line-height: 1.7; }
.field .hint { font-size: 12px; color: var(--dim); margin-top: 6px; }

/* ---------------- 列表 ---------------- */
.list-item {
  display: flex; align-items: flex-start; gap: 12px; padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.list-item:last-child { border-bottom: none; }
.list-item .main { flex: 1; min-width: 0; }
.list-item .main h4 { font-size: 15px; color: var(--txt); margin-bottom: 5px; }
.list-item .main p { font-size: 13px; color: var(--sub); line-height: 1.7; }
.list-item .meta { font-size: 12px; color: var(--dim); margin-top: 6px; display: flex; gap: 12px; flex-wrap: wrap; }
.article-item { cursor: pointer; }
.article-item:hover h4 { color: var(--gold2); }

/* ---------------- 表格 ---------------- */
.tbl { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.tbl th, .tbl td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--line); }
.tbl th { color: var(--dim); font-weight: 400; font-size: 12.5px; background: var(--card2); }
.tbl tr:hover td { background: rgba(212, 175, 55, .04); }

/* ---------------- 标签 ---------------- */
.tag {
  display: inline-block; font-size: 11.5px; padding: 2px 9px; border-radius: 99px;
  border: 1px solid var(--line2); color: var(--sub);
}
.tag.gold { color: var(--gold); border-color: rgba(212, 175, 55, .4); }
.tag.ok { color: var(--ok); border-color: rgba(76, 195, 138, .4); }
.tag.warn { color: var(--warn); border-color: rgba(224, 176, 80, .4); }

/* ---------------- 提示 ---------------- */
.tip-box {
  border-left: 3px solid var(--gold); background: rgba(212, 175, 55, .07);
  padding: 12px 15px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 13px; color: var(--gold2); line-height: 1.75; margin-bottom: 16px;
}
.empty { text-align: center; padding: 48px 20px; color: var(--dim); }
.empty .big { font-size: 40px; margin-bottom: 12px; }

/* ---------------- 页脚 ---------------- */
/* ★ 2026-10-17 全页脚居中：块级容器统一 text-align:center 作为兜底，
   任何后续新增的文本块都会默认居中，不会重演「左对齐留大片空白」。
   flex 子块（foot-brand / foot-nav / foot-bottom）各自另有显式居中规则。 */
.site-foot {
  border-top: 1px solid var(--line); margin-top: 40px;
  background: var(--bg2); font-size: 12.5px; color: var(--dim); line-height: 1.9;
  text-align: center;
}
.site-foot .inner { max-width: var(--maxw); margin: 0 auto; padding: 26px 18px 34px; }
.site-foot b { color: var(--sub); }
/* 页脚站点标识：主标题 + 副标题小字 */
/* 页脚站点标识：品牌名一行、副标题小字一行，两行各自水平居中。
   ★ 2026-10-17：原为 flex-wrap+baseline 的同行排布且未设 justify-content，
     实际渲染左对齐（实测偏离容器中心 429px），导致页脚右侧大片空白。
     现改为 flex-direction:column + align-items:center + text-align:center，
     品牌名与副标题上下堆叠且各自居中；容器再叠一层 justify-content:center，
     即使将来内容变多触发换行，仍保持整体居中。 */
.site-foot .foot-brand {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; margin-bottom: 14px;
}
.site-foot .foot-brand .name {
  font-family: var(--font-serif); font-weight: 700; font-size: 16px;
  color: var(--gold2); letter-spacing: .6px;
}
/* 副标题紧贴品牌名下方（小字间距 4px）。原同行排布时靠 flex gap:10px 控距，
   改为 column 堆叠后 gap 方向改变，改用 margin-top 保证两行视觉呼吸感一致。 */
.site-foot .foot-brand .slogan { font-size: 12.5px; color: var(--dim); letter-spacing: .8px; margin-top: 4px; }
.site-foot .links { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.site-foot .links a { color: var(--sub); }
/* ★ 2026-10-17 页脚横排改版：协议链接与内容属性/数据隐私/运营主体等说明条目
   合并到同一个横排容器，条目间以竖线分隔，整体水平居中。
   - 用 flex + justify-content:center 保证「一行排不下自动换行后仍居中」；
   - 竖线作为独立 span（而非 border），才能在换行后不产生「行首竖线」；
   - 条目内 b 与正文同色同行高，保证所有文字水平对齐。 */
.site-foot .foot-nav {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: 4px 0; margin-bottom: 4px; line-height: 2.1; text-align: center;
}
.site-foot .foot-nav .foot-item {
  color: var(--dim); text-decoration: none; padding: 0 10px; white-space: nowrap;
  transition: color .15s ease;
}
.site-foot .foot-nav .foot-item:hover,
.site-foot .foot-nav .foot-item:focus { color: var(--gold2); }
.site-foot .foot-nav .foot-item b { color: var(--sub); font-weight: 600; }
/* 竖线分隔符：与文字同色同字号，仅作视觉分隔 */
.site-foot .foot-nav .foot-div { color: var(--line); padding: 0 2px; user-select: none; }
/* 底部版权行：版权 + ICP 备案号 + 公安备案号，居中并排、间距均匀。
   用 flex 而非空格分隔，保证窄屏下换行后仍各自居中对齐。 */
.site-foot .foot-bottom {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 6px 14px; margin-top: 8px; color: var(--dim); text-align: center;
}.site-foot .foot-copy { white-space: nowrap; }
.site-foot .icp-link {
  color: var(--dim); text-decoration: none; white-space: nowrap;
  transition: color .15s ease;
}
.site-foot .icp-link:hover, .site-foot .icp-link:focus { color: var(--gold2); text-decoration: underline; }
/* 公安备案：官方小图标 + 文字，基线对齐保证与 ICP 号同一行视觉齐平 */
.site-foot .icp-police { display: inline-flex; align-items: center; gap: 5px; }
.site-foot .icp-police-icon {
  width: 15px; height: 15px; flex: 0 0 auto; display: block;
  object-fit: contain; border-radius: 2px;
}

/* ---------------- 浮层 ---------------- */
.cs-mask {
  /* 遮罩减淡：原 rgba(6,8,13,.74)+blur(3px) 过重，会让页面（含卡片封面）整体发灰发暗。
     改为半透 + 极轻模糊，既保持弹窗聚焦感，又不遮挡底层内容。 */
  position: fixed; inset: 0; background: rgba(6, 8, 13, .46); z-index: 200;
  display: none; align-items: center; justify-content: center; padding: 20px; backdrop-filter: blur(1.5px);
}
.cs-mask.on { display: flex; }
.cs-modal {
  background: var(--card); border: 1px solid var(--line2); border-radius: var(--radius);
  max-width: 520px; width: 100%; max-height: 84vh; overflow: auto; padding: 22px;
}
.cs-modal h3 { color: var(--gold2); font-size: 17px; margin-bottom: 14px; }
.toast-float {
  position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%);
  background: var(--card2); border: 1px solid var(--line2); color: var(--txt);
  padding: 11px 22px; border-radius: 99px; font-size: 13.5px; z-index: 300;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .45); opacity: 0; pointer-events: none; transition: .28s;
}
.toast-float.on { opacity: 1; bottom: 44px; }

/* ---------------- 排盘页外壳 ---------------- */
.workbench-shell { max-width: var(--maxw); margin: 0 auto; padding: 20px 12px 50px; }
.workbench-shell .wb-head { text-align: center; padding: 6px 0 2px; }

/* ---------------- 响应式 ---------------- */
@media (max-width: 900px) {
  .grid.c3, .grid.c4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .page { padding: 18px 13px 46px; }
  .grid.c2, .grid.c3, .grid.c4 { grid-template-columns: 1fr; }
  .cs-card { padding: 15px; }
  .hero { padding: 26px 0 20px; }
  .tbl { font-size: 12.5px; }
  .tbl th, .tbl td { padding: 8px 9px; }
}

/* ============================================================
   第十三阶段 · 全站昼夜主题 + 会员中心改版
   ------------------------------------------------------------
   说明：本段是本文件里**唯一**的主题相关段落，作用域覆盖全站外壳
        （导航 / 免责条 / 卡片 / 表单 / 表格 / 页脚 / 浮层）与会员中心新版布局。
        排盘工作台内部的浅色规则仍由 engine.css 负责（仅 paipan.html 引入）。
        变量值与 engine.css 的浅色档完全一致，保证「工作台内外同色」。
   ============================================================ */

/* ---------------- 5.1 浅色主题变量覆盖 ----------------
   html[data-theme="light"] 特异性 (0,1,1) 高于 :root (0,1,0)，
   故无论与 engine.css 的加载先后，均可稳定覆盖。 */
html[data-theme="light"] {
  --bg: #f6f2e7; --bg2: #efe9db; --card: #ffffff; --card2: #f7f3e9;
  --line: #e2d8c3; --line2: #cfc3a6;
  --gold: #8a6b1e; --gold2: #77590f;
  --txt: #26201a; --sub: #544a38; --dim: #6d6350;
  --lu: #0f6b32; --quan: #a83c14; --ke: #1a4fa0; --ji: #a01c38;
  --ok: #0f6b32; --warn: #8a4a10; --err: #a01c38;
  color-scheme: light;                    /* 原生控件 / 滚动条随浅色 */
}

/* ---------------- 5.2 外壳组件的浅色微调 ----------------
   仅覆盖那些写死了深色渐变 / 半透明底的地方（其余外壳已全部走 CSS 变量，自动跟随）。 */
html[data-theme="light"] body {
  background-image: radial-gradient(ellipse 80% 50% at 50% -10%, rgba(168, 132, 42, .10), transparent);
}
/* 吸顶导航同 body 一起换浅色光晕（底色已走 var(--bg)=#f6f2e7，此处同几何换算：圆心 -120px / ry 600px） */
html[data-theme="light"] .site-nav {
  background-image: radial-gradient(ellipse 80% 600px at 50% -120px, rgba(168, 132, 42, .10), transparent);
}
html[data-theme="light"] .brand .txt,
html[data-theme="light"] .hero h1 {
  background: linear-gradient(180deg, #8a6b1e, #6d5312 72%, #523f0c);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
html[data-theme="light"] .disclaimer-bar {
  background: linear-gradient(90deg, rgba(168, 132, 42, .16), rgba(168, 132, 42, .06));
  border-bottom-color: rgba(138, 107, 30, .28);
}
html[data-theme="light"] .disclaimer-bar b { color: #6d5312; }
/* 浅色下导航项不再使用背景块：只提亮选中 / 悬停字色，下划线走 var(--gold) 自动跟随主题 */
html[data-theme="light"] .nav-links a:hover,
html[data-theme="light"] .nav-links a.active { color: #77590f; }
html[data-theme="light"] .hero .badge-row span {
  color: #6d5312; border-color: rgba(138, 107, 30, .42); background: rgba(168, 132, 42, .10);
}
html[data-theme="light"] .entry-card:hover { border-color: rgba(138, 107, 30, .5); }
html[data-theme="light"] .btn:hover { border-color: #8a6b1e; color: #6d5312; }
html[data-theme="light"] .tbl tr:hover td { background: rgba(168, 132, 42, .06); }
html[data-theme="light"] .tag.gold { color: #6d5312; border-color: rgba(138, 107, 30, .45); }
html[data-theme="light"] .tag.warn { color: #8a4a10; border-color: rgba(138, 74, 16, .45); }
html[data-theme="light"] .toast-float { box-shadow: 0 8px 28px rgba(80, 64, 30, .22); }
html[data-theme="light"] .cs-mask { background: rgba(40, 34, 22, .30); }
html[data-theme="light"] .site-foot .foot-brand .name { color: #77590f; }

/* ---------------- 5.3 全站主题切换按钮（导航栏，运行期由 theme.js 注入） ---------------- */
.csthemebtn {
  width: 34px; height: 34px; padding: 0; flex-shrink: 0;
  border-radius: 50%; border: 1px solid rgba(212, 175, 55, .45);
  background: rgba(212, 175, 55, .10); color: var(--gold2);
  font-size: 16px; line-height: 1; cursor: pointer;
  display: grid; place-items: center; transition: .2s;
}
.csthemebtn:active { transform: scale(.94); }
html[data-theme="light"] .csthemebtn {
  border-color: rgba(138, 107, 30, .5); background: rgba(168, 132, 42, .14); color: #77590f;
}

/* ---------------- 5.4 会员中心新版布局 ---------------- */
.mbr-head .mbr-lead { color: var(--dim); font-size: 12.5px; line-height: 1.85; margin: -4px 0 12px; }
.mbr-sec { margin-bottom: 20px; }
.mbr-sec-h {
  font-size: 15px; color: var(--gold2); letter-spacing: .8px; margin: 2px 2px 12px;
  display: flex; align-items: center; gap: 8px;
}
.mbr-sec-h::before { content: "◆"; font-size: 9px; color: var(--gold); }
.mbr-sec-h small { color: var(--dim); font-weight: 400; font-size: 11.5px; margin-left: auto; }

/* 5.4.1 权益对比（左右并排） */
.mbr-cmp-card { margin-bottom: 0; }
.mbr-cmp-card > h4 {
  font-size: 14.5px; color: var(--txt); margin-bottom: 10px;
  display: flex; align-items: center; gap: 8px;
}
.mbr-cmp-card.vip { border-color: rgba(212, 175, 55, .42); }
.mbr-cmp-card.vip > h4 { color: var(--gold2); }
.mbr-list { list-style: none; padding: 0; margin: 0; }
.mbr-list li { position: relative; padding: 6px 0 6px 20px; font-size: 13.5px; line-height: 1.75; color: var(--sub); }
.mbr-list li::before { content: "·"; position: absolute; left: 6px; color: var(--dim); }
.mbr-list.vip li { color: var(--gold2); }
.mbr-list.vip li::before { content: "✓"; font-size: 11px; left: 2px; color: var(--gold); }
.mbr-guest-tip {
  margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--line);
  font-size: 12.5px; line-height: 1.7; color: var(--warn);
}

/* 5.4.2 套餐卡片（单次 → 月度 → 年度 → 终身）
   第十四阶段：四卡**等高对齐** —— 外层 grid 行高统一（grid-auto-rows:1fr），
   卡内按「标题 / 价格 / 简述(定高) / 权益(占满剩余) / 按钮(贴底)」五段式排布，
   故无论权益条数多少，卡片下沿与按钮基线都严格对齐。 */
.mbr-plans {
  display: grid; gap: 14px; grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: stretch; grid-auto-rows: 1fr;
}
.mbr-plan {
  margin-bottom: 0; height: 100%; display: flex; flex-direction: column; text-align: center;
}
.mbr-plan.recommend {
  border-color: rgba(212, 175, 55, .62);
  box-shadow: 0 0 0 1px rgba(212, 175, 55, .30) inset, 0 8px 26px rgba(212, 175, 55, .12);
}
.mbr-plan-head { min-height: 26px; display: flex; align-items: center; justify-content: center; gap: 6px; }
.mbr-plan-head h4 { font-size: 15px; color: var(--gold2); letter-spacing: .5px; }
/* 【推荐】标签：实底金色胶囊 + 微光，强化视线引导（区别于普通 .tag） */
.mbr-rec {
  font-size: 11px; font-weight: 700; letter-spacing: .5px; line-height: 1;
  padding: 4px 10px; border-radius: 99px; border: none; color: #2a2008;
  background: linear-gradient(135deg, #f3e3a6, #d4af37);
  box-shadow: 0 2px 8px rgba(212, 175, 55, .38);
}
.mbr-price { margin: 12px 0 4px; }
.mbr-price-num { font-family: var(--font-serif); font-size: 30px; font-weight: 700; color: var(--gold); letter-spacing: .5px; }
.mbr-price-unit { margin-left: 5px; font-size: 12px; color: var(--dim); }
.mbr-plan-brief { font-size: 12px; color: var(--dim); line-height: 1.7; margin-bottom: 10px; min-height: 42px; }
.mbr-plan-rights { list-style: none; padding: 0; margin: 0 0 14px; text-align: left; flex: 1; }
.mbr-plan-rights li { position: relative; padding: 5px 0 5px 16px; font-size: 12.5px; line-height: 1.7; color: var(--sub); }
.mbr-plan-rights li::before { content: "✓"; position: absolute; left: 0; color: var(--gold); font-size: 11px; }
.mbr-plan-btn { margin-top: auto; }
/* 套餐区底部统一小字提示（位于四张卡片之下，不穿插在卡片之间） */
.mbr-plan-note {
  margin: 14px 0 0; text-align: center; font-size: 12px; line-height: 1.8;
  color: var(--dim); letter-spacing: .2px;
}

/* 5.4.3 我的订单 / 底部说明 */
.mbr-orders-hd { display: flex; justify-content: flex-end; margin-bottom: 8px; }
.mbr-foot-note p { color: var(--sub); font-size: 13px; line-height: 1.95; }
.mbr-foot-note .mbr-legal { color: var(--dim); font-size: 12.5px; line-height: 1.9; margin-top: 10px; }

/* ---------------- 5.5 首页左右双栏等高对齐（第十四阶段） ----------------
   首页左右两栏内容量不等：右栏（公告 + 古籍知识）偏长，左栏偏短 → 版面失衡。
   做法：把两栏各自变成纵向弹性列，并让**栏内最后一张卡片吞掉剩余高度**；
   两栏的下沿由同一行 grid 行高决定，从而在视觉上严格对齐。 */
.home-col { display: flex; flex-direction: column; }
.home-col > .cs-card:last-child { flex: 1; }
/* 左栏补高模块「研究参考」的正文样式（与站点次要说明文本一致） */
.home-col .home-ref p { color: var(--sub); font-size: 13.5px; line-height: 1.9; }

@media (max-width: 900px) {
  .mbr-plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .mbr-plans { grid-template-columns: 1fr; }
  .mbr-plan-brief { min-height: 0; }
}


/* ============================================================
   6. 古籍资料库增强（第十七阶段）
   ------------------------------------------------------------
   本节**只新增**，不改动上方任何既有规则：
     · 6.1 资料库页：全站检索框、我的书架入口、结果分组、分页
     · 6.2 阅读详情页：左目录 / 正文 / 工具条 / 版本标注
     · 6.3 我的书架页
   配色一律走既有 CSS 变量，日间 / 夜间自动适配，不写死颜色。
   ============================================================ */

/* ---------------- 6.1 资料库页 ---------------- */
/* 全站检索：位于页面说明文字下方，独立一行，不挤压原有检索区 */
.lib-search { display: flex; gap: 10px; margin: 14px 0 0; }
.lib-search input {
  flex: 1; min-width: 0; padding: 10px 13px; border-radius: var(--radius-sm);
  background: var(--card2); border: 1px solid var(--line); color: var(--txt); font-size: 14px;
}
.lib-search input:focus { outline: none; border-color: rgba(212, 175, 55, .55); }
.lib-search .btn { flex-shrink: 0; white-space: nowrap; }
/* 说明卡片右上角的「我的书架」入口：与卡片标题同行，不新增整块版面 */
.lib-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.lib-head > h3 { flex: 1; min-width: 160px; }
.lib-head .btn { flex-shrink: 0; }
/* 检索结果：分组标题 + 命中朝代 */
.lib-group-h {
  font-size: 13px; color: var(--gold2); letter-spacing: .6px; margin: 14px 2px 8px;
  display: flex; align-items: center; gap: 8px;
}
.lib-group-h small { color: var(--dim); font-weight: 400; font-size: 11.5px; }
.lib-group-h::before { content: "◆"; font-size: 8px; color: var(--gold); }
/* 匹配到的典籍（书籍条目）：横向卡片，点击直接进阅读页 */
.lib-book-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.lib-book-item {
  display: flex; gap: 11px; align-items: flex-start; padding: 12px 13px;
  background: var(--card2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  cursor: pointer; transition: .2s;
}
.lib-book-item:hover { border-color: rgba(212, 175, 55, .5); transform: translateY(-1px); }
/* 竖版 3:4 国风封面；无图时 .ico 内为 📖 文字占位，两者共用同一盒模型 */
.lib-book-item .ico {
  width: 60px; height: 80px; flex-shrink: 0; font-size: 20px; line-height: 1.2;
  display: grid; place-items: center; overflow: hidden;
  border-radius: 7px; border: 1px solid var(--line);
  background: linear-gradient(150deg, rgba(212, 175, 55, .16), rgba(212, 175, 55, .04));
}
.lib-book-item .ico img { width: 100%; height: 100%; object-fit: contain; display: block; }
.lib-book-item .main { min-width: 0; }
.lib-book-item h4 { font-size: 14px; color: var(--gold2); margin-bottom: 4px; }
.lib-book-item p { font-size: 12.5px; color: var(--dim); line-height: 1.7; }
/* 分页条 */
.lib-pager { display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 16px; flex-wrap: wrap; }
.lib-pager .pg-info { font-size: 12.5px; color: var(--dim); }
.lib-pager .btn[disabled] { opacity: .45; cursor: not-allowed; }
/* 条目标题后的"命中字段"小标签 */
.lib-hit { font-size: 11px; color: var(--dim); border: 1px solid var(--line); border-radius: 99px; padding: 1px 7px; margin-left: 6px; }
.lib-snippet { font-size: 12.5px; color: var(--sub); line-height: 1.75; margin-top: 4px; }

/* ---------------- 6.2 阅读详情页 ---------------- */
/* 左目录固定 + 右正文：桌面端两栏，窄屏自动收为单栏（目录折叠在上方） */
.rdr-wrap { display: grid; grid-template-columns: 258px minmax(0, 1fr); gap: 16px; align-items: start; }
.rdr-toc { position: sticky; top: calc(var(--nav-h) + 14px); max-height: calc(100vh - var(--nav-h) - 32px); overflow: auto; }
.rdr-toc h4 { font-size: 13.5px; color: var(--gold2); margin-bottom: 10px; display: flex; align-items: center; gap: 7px; }
.rdr-toc h4 small { color: var(--dim); font-weight: 400; font-size: 11px; margin-left: auto; }
.rdr-toc ol { list-style: none; padding: 0; margin: 0; counter-reset: rdr; }
.rdr-toc li { counter-increment: rdr; }
.rdr-toc li a {
  display: flex; gap: 7px; padding: 7px 9px; border-radius: 8px; font-size: 13px;
  color: var(--sub); line-height: 1.55; cursor: pointer;
}
.rdr-toc li a::before { content: counter(rdr) "."; color: var(--dim); font-size: 11.5px; flex-shrink: 0; }
.rdr-toc li a:hover { background: rgba(212, 175, 55, .09); color: var(--gold2); }
.rdr-toc li a.cur { background: rgba(212, 175, 55, .13); color: var(--gold2); }
.rdr-toc li a .lk { margin-left: auto; flex-shrink: 0; font-size: 11px; color: var(--dim); }
/* 正文工具条：字号 / 简繁 / 书架 / 书签 */
.rdr-bar {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--line);
}
/* 第卅四阶段 · 工具栏两行布局修正
   ------------------------------------------------------------
   目标结构（组件所属行与左右顺序一律保持原样，只调弹性与间距）：
     第一行 = 字号下拉 / 简·繁 / 原·译 / 加入书架·书签·收藏 / 笔记
     第二行 = 页内查找（固定贴第二行最右）

   ⚠ 此前加了 `.rdr-bar > .grp { flex-shrink: 0 }`，与 spacer 的
     `margin-left:auto` 叠加后产生副作用：spacer 作为零内容 flex 项，
     在 wrap 容器里会先占掉整行剩余空间，把「字号下拉」顶成孤立第一行、
     其余四组整体掉到第二行 —— 第一行右侧空出 740px，正是要消除的空白。

   ⚠ 关键教训（实测踩坑，别再改回去）：
     flex 容器的 `flex-wrap` 是**贪心逐个装填**，只要「页内查找」组参与同一
     轮排布，它就会先占掉当前行的剩余宽度，逼得后面五组被挤到下一行 ——
     即便给它加了 `order:1`（改的是绘制顺序，不改排布时机）也无济于事。
     所以「固定它在第二行」不能靠 flex 属性，只能让它**彻底退出排布流**。

   最终方案（三处协同）：
     ① spacer 与「页内查找」组一并退出布局流：绝对定位到工具栏右下角，
        并由 padding-bottom 为其预留出一条完整行高 → 第二行天然存在，
        页内查找钉在其右端，位置与左右顺序与原版完全一致；
     ② 工具栏主体只剩第一行五组，整体**居中对齐**、组间与组内一律
        固定统一间距（不再用 flex-grow 两端撑开，避免间距忽宽忽窄）；
     ③ 极窄屏时第一行五组放不下，按 flex-wrap 自然整组换行；
        查找组因已绝对定位，始终固定在第二行右端，不会被挤走。

   ⚠ 第三十五阶段修正：上一版给第一行各组加了 `flex:1 1 auto` 让它们
     均分整行，实测等于「两端撑开」—— 组与组之间被拉开 10~90px 不等，
     间距忽宽忽窄，视觉上不像一个整体按钮组。
     改为 `flex:0 0 auto`（各组按内容取自然宽度）+ `justify-content:center`
     （整行居中）+ 固定 gap，即为「一个整体按钮组居中排列、间距统一」。

   ⚠ 作用域：以下桌面端规则**仅对 PC 生效**。窄屏（≤820px）由 reader.html
     内联媒体查询接管，那套规则自带 `gap:8px` 与 `flex:1 1 calc(50% - 4px)`
     （特异性同为 0,2,0 但写在媒体查询内、且位置更靠后），
     会完整覆盖本页的 flex / gap / 对齐设置 —— 故手机端排版分毫未变。 */
.rdr-bar {
  position: relative;
  /* 为「页内查找」预留第二行的高度，并加大与第一行的垂直间距（层次感）。
     按钮高约 34px；原 12px → 66px，配合下方 bottom:8px，
     两行之间实测净空 25px（约为组间 gap 8px 的三倍），层次清晰不拥挤。 */
  padding-bottom: 66px;
  /* 第一行整体居中：绝不两端分散撑开 */
  justify-content: center;
}
/* ① 占位符彻底退出排布流 */
.rdr-bar .sp {
  position: absolute; width: 0; height: 0; overflow: hidden;
  margin: 0; padding: 0; border: 0;
}
/* ② 第一行五组：按内容取自然宽度（不伸缩、不压缩），整行由父级居中。
     组内按钮之间沿用 .grp 自带的 gap:4px，组与组之间用 .rdr-bar 的 gap:8px，
     两者固定不变 —— 因此无论窗口多宽，按钮间距始终一致，不会忽宽忽窄。 */
.rdr-bar > .grp {
  flex: 0 0 auto;
}
/* 组内控件不再被拉伸，保持各自内容宽度 */
.rdr-bar > .grp > select,
.rdr-bar > .grp > input {
  flex: 0 0 auto;
}
/* ③ 页内查找：脱离排布流、钉在第二行右端（DOM 位置与左右顺序均未动）
   第三十五阶段：bottom 由 13px 调到 8px —— padding-bottom 已加到 58px
   用于拉开与第一行的垂直间距，若仍把查找组压到 13px 贴底，多出的空间就会
   全部堆到它**下方**（实测行间净空只有 12px、下方却空 14px，层次感出不来）。
   调到 8px 后，空间转移到行间，两行之间明显拉开层次。 */
.rdr-bar > .grp:has(> #rdrFind) {
  position: absolute; right: 0; bottom: 8px;
  margin: 0; z-index: 1;
}
.rdr-bar .grp { display: flex; align-items: center; gap: 4px; }
.rdr-bar .grp > span { font-size: 12px; color: var(--dim); margin-right: 2px; }
.rdr-title { font-family: var(--font-serif); font-size: 21px; color: var(--gold2); line-height: 1.5; }
.rdr-meta { font-size: 12.5px; color: var(--dim); margin: 8px 0 2px; }
/* 正文字号：由 --rdr-fs 驱动，工具条 A- / A+ 直接改该变量 */
.rdr-body {
  font-family: var(--font-serif); font-size: var(--rdr-fs, 16px); line-height: 2.15;
  color: var(--txt); letter-spacing: .2px;
}
.rdr-body p { margin: 0 0 .85em; }
.rdr-body .rdr-note { font-size: calc(var(--rdr-fs, 16px) - 2.5px); color: var(--sub); line-height: 1.95; }
.rdr-body mark { background: rgba(212, 175, 55, .3); color: inherit; border-radius: 3px; padding: 0 2px; }
/* 章节锚点：跳转时留出吸顶导航的高度 */
.rdr-ch { scroll-margin-top: calc(var(--nav-h) + 16px); }
.rdr-ch + .rdr-ch { margin-top: 26px; padding-top: 22px; border-top: 1px dashed var(--line); }
.rdr-ch-h { font-size: 15px; color: var(--gold2); margin-bottom: 8px; display: flex; align-items: baseline; gap: 8px; }
.rdr-ch-h small { font-size: 11.5px; color: var(--dim); font-weight: 400; }
.rdr-locked {
  padding: 20px 18px; text-align: center; border: 1px dashed var(--line2); border-radius: var(--radius-sm);
  background: var(--card2);
}
.rdr-locked .big { font-size: 26px; margin-bottom: 8px; }
.rdr-locked p { font-size: 13px; color: var(--sub); line-height: 1.85; }
/* 底部版本 / 出处标注：浅灰小字，跟随主题，不干扰正文 */
.rdr-src {
  margin-top: 26px; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: 11.5px; line-height: 1.95; color: var(--dim);
}
.rdr-src b { color: var(--sub); font-weight: 500; }
.rdr-nav { display: flex; justify-content: space-between; gap: 10px; margin-top: 18px; flex-wrap: wrap; }

/* ---------------- 6.3 我的书架页 ---------------- */
.shelf-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.shelf-card {
  display: flex; gap: 12px; padding: 14px; cursor: pointer;
  background: var(--card2); border: 1px solid var(--line); border-radius: var(--radius-sm); transition: .2s;
}
.shelf-card:hover { border-color: rgba(212, 175, 55, .5); transform: translateY(-1px); }
.shelf-card .cover {
  /* 竖版 3:4 圆角封面（国风线装古籍插画），PC 与移动端书架通用 */
  width: 84px; height: 112px; flex-shrink: 0; border-radius: 8px; overflow: hidden;
  background: linear-gradient(150deg, rgba(212, 175, 55, .22), rgba(212, 175, 55, .06));
  border: 1px solid var(--line); display: grid; place-items: center; font-size: 22px; color: var(--gold2);
}
/* 封面图为 3:4 竖版，等比完整显示，不裁切题签文字 */
.shelf-card .cover img { width: 100%; height: 100%; object-fit: contain; display: block; }
.shelf-card .cover img { width: 100%; height: 100%; object-fit: cover; }
.shelf-card .main { min-width: 0; }
.shelf-card h4 { font-size: 14.5px; color: var(--gold2); margin-bottom: 5px; }
.shelf-card p { font-size: 12.5px; color: var(--dim); line-height: 1.7; }
.shelf-card .ops { margin-top: 8px; display: flex; gap: 6px; }

/* 移动端书架：封面等比缩放，保持 3:4 竖版与题签可读 */
@media (max-width: 640px) {
  .shelf-grid { grid-template-columns: 1fr; gap: 10px; }
  .shelf-card .cover { width: 72px; height: 96px; border-radius: 7px; }
  .shelf-card h4 { font-size: 14px; }
}

@media (max-width: 900px) {
  .rdr-wrap { grid-template-columns: 1fr; }
  .rdr-toc { position: static; max-height: none; }
  .rdr-toc ol { max-height: 240px; overflow: auto; }
}


/* ============================================================
   7. 首页双栏等高对齐策略重校（第廿四阶段）
   ------------------------------------------------------------
   本节**只新增**，不改动上方任何既有规则（§5.5 保持「末尾纯追加」契约）。

   背景：§5.5 的策略是「**栏内最后一张卡**吞掉全部剩余高度」。
   第廿四阶段首页左栏**原地替换**卡片后（删「研究参考」、置「隐私与数据简要说明」），
   左栏 4 卡 / 右栏 2 卡，两栏自然高度差约 89px ——
   该差值会被整块堆到较矮一栏（右栏）末卡的底部，首页右下角出现成片留白。

   本节把策略改为「**栏内每张卡片等额分担**剩余高度」：
     · .home-col > .cs-card           剩余高度按卡片数均分；
                                      flex-shrink 置 0，保证内容永不被压扁；
     · 动态内容区（#csNotices / #csArticles）吸收该卡多出的高度并**垂直居中**，
       使剩余空间在卡片上下对称分布，而不是整块沉在卡片底部。
   选择器特异性与 §5.5 相同或更高、且定义在其后，故可稳定覆盖 §5.5 的末卡规则。
   ============================================================ */
.home-col > .cs-card,
.home-col > .cs-card:last-child {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.home-col > .cs-card > #csNotices,
.home-col > .cs-card > #csArticles {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}


/* ============================================================
   8. 研习助手 · 阅读笔记 · 阅读页工具栏精简（第廿九阶段）
   ------------------------------------------------------------
   本节**只追加**，不改动上方任何既有规则（§6.2 的阅读页基线保持原样）。
   新增内容分三块：
     8.1 导航栏「研习助手」入口（含黑白线条机器人图标的统一尺寸）
     8.2 全站研习助手弹窗（两处入口共用同一份 DOM）
     8.3 阅读页工具栏：字号下拉 / 简繁一键 / 笔记按钮 / 划线高亮 / 批注小框
   配色一律走既有 CSS 变量（第 5.1 节已给出浅色覆盖），故昼夜主题自动跟随。
   ============================================================ */

/* ---------------- 8.1 导航栏「研习助手」入口 ----------------
   ★ 2026-10-15 重做：原规则带border + 背景 + 强制金色，
     导致它被渲染成一个「带框金色按钮」，与旁边纯文字导航项形态迥异，
     且看起来像 active 高亮。
     现按需求改为**与其它一级菜单完全一致的纯文字项**：
     无边框、无背景、无高亮，仅 hover 时文字提亮。
     该入口不是页面跳转，故永不显示 active 下划线。 */
/* 文字 + 图标同行排版：与 .nav-links a 同为 inline，避免 inline-flex 造成的字形发虚 */
.nav-links a.nav-asst {
  display: inline; cursor: pointer;
  border: none; background: none;
  color: var(--sub); font-size: 15px; font-weight: inherit;
  padding: 8px 13px; border-radius: 9px;
}
.nav-links a.nav-asst:hover { border-color: transparent; background: none; color: var(--gold2); }
.nav-links a.nav-asst::after { display: none; }   /* 永不画 active 下划线 */
/* ★ 2026-10-15 去除旧的 vertical-align:-2px —— 该值正是图标「偏上」的成因，
   现统一由 .cs-robot{vertical-align:middle} 与 slot 的 align-items 控制。 */
.nav-links a.nav-asst .cs-robot { flex-shrink: 0; vertical-align: middle; }
/* 额度耗尽 / 未开放：仅降透明度，**不置灰、不加not-allowed**，保持可点（点开弹窗说明原因） */
[data-assistant-open].asst-off { opacity: .62; }
.nav-links a.nav-asst.asst-off:hover { color: var(--gold2); }

/* 机器人图标：全站统一尺寸与对齐（由study-assistant.js 注入，未注入时占位不塌陷）
   ★ 2026-10-15 视觉校正（导航入口）：
     实测问题：图标盒 16px、中心线 y=27.38，而「研习助手」文字中心线 y=30.38，
     图标**偏上 3px**、且16px 配15px 文字显得偏小发虚。
     修法（实测 5 种方案后选定）：
       1) 尺寸 16px → 18px，与 15px 导航文字的视觉高度接近；
       2) 用 position:relative; top:3px 把图标下移，使其中心线与文字中心线
          **精确重合（差值 0px）**。
          之所以不用 vertical-align:middle，是因为图标与文字同处一个行盒时，
          middle 是相对**基线 + x-height 中点**计算的，会连带把文字也顶偏
          （实测文字被移到 31.28，与相邻导航项错位）；
          也未采用 inline-flex 方案，避免 site.css §8.1 注释里记录过的
          「inline-flex 造成字形发虚」问题。
          relative 定位只影响图标自身，文字基线与相邻导航项保持零位移。 */
.cs-robot-slot {
  display: inline-flex; align-items: center; position: relative; top: 3px;
  width: 18px; height: 18px; flex-shrink: 0;
}
.cs-robot { display: block; width: 18px; height: 18px; vertical-align: middle; }

/* ---------------- 8.2 研习助手弹窗 ---------------- */
.asst-modal { max-width: 640px; display: flex; flex-direction: column; }
.asst-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.asst-head .asst-ico {
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 50%;
  border: 1px solid var(--line2); background: var(--card2); color: var(--gold2);
  display: grid; place-items: center;
}
.asst-head .asst-ico .cs-robot { width: 19px; height: 19px; }
.asst-head .asst-ttl { flex: 1; min-width: 0; }
.asst-head h3 { margin: 0; font-size: 16.5px; color: var(--gold2); }
.asst-head small { display: block; color: var(--dim); font-size: 12px; font-weight: 400; margin-top: 2px; }
.asst-x {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: 8px; font-size: 14px;
  background: none; border: 1px solid var(--line); color: var(--sub);
}
.asst-x:hover { border-color: var(--line2); color: var(--txt); }
.asst-quota { display: none; font-size: 12px; color: var(--dim); margin-bottom: 8px; }
.asst-quota.on { display: block; }
#csAsstInput {
  width: 100%; min-height: 74px; resize: vertical; padding: 11px 13px; font-size: 14px;
  border-radius: var(--radius-sm); background: var(--card2); border: 1px solid var(--line);
  color: var(--txt); line-height: 1.85;
}
#csAsstInput:focus { outline: none; border-color: rgba(212, 175, 55, .55); }
#csAsstInput:disabled { opacity: .6; }
.asst-acts { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.asst-acts .asst-hint { font-size: 12px; color: var(--dim); }
.asst-out {
  display: none; margin-top: 12px; padding: 13px 15px; border-radius: var(--radius-sm);
  background: var(--card2); border: 1px solid var(--line);
  font-size: 13.5px; line-height: 1.95; color: var(--txt);
  max-height: 46vh; overflow: auto;
}
.asst-out.on { display: block; }
.asst-loading { display: block; color: var(--dim); font-size: 13px; }
.asst-lock { color: var(--sub); font-size: 13.5px; line-height: 1.9; }
.asst-lock-act { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
/* 弹窗底部固定常驻小字（任务书要求不可隐藏 —— 故不提供任何折叠 / 关闭入口） */
.asst-foot {
  margin-top: 14px; padding-top: 11px; border-top: 1px solid var(--line);
  font-size: 11.5px; line-height: 1.8; color: var(--dim);
}
/* 非会员遮罩态：输入区整体不可用 */
#csAsstMask .asst-modal input, #csAsstMask .asst-modal textarea { font-family: inherit; }

/* ---------------- 8.3 阅读页工具栏：字号下拉 / 简繁一键 / 笔记 ---------------- */
/* 字号 ▾（合并原 A- / A+ 两按钮） */
.rdr-sel {
  padding: 6px 8px; font-size: 12.5px; border-radius: 8px;
  background: var(--card2); border: 1px solid var(--line); color: var(--txt);
}
.rdr-sel:focus { outline: none; border-color: rgba(212, 175, 55, .55); }
.rdr-sel:disabled { opacity: .55; }
/* 简 / 繁 一键切换：单按钮两态，用 data-script 表达当前字形 */
#rdrScriptBtn[data-script="s"] .s, #rdrScriptBtn[data-script="t"] .t { opacity: 1; }
#rdrScriptBtn .s, #rdrScriptBtn .t { opacity: .45; }
#rdrScriptBtn[data-script="t"] .s, #rdrScriptBtn[data-script="s"] .t { opacity: .45; }

/* 「原 / 译」切换按钮（第三十四阶段 · 由 #rdrSrcMode + #rdrTransMode 两个
   独立按钮合并而来）：视觉语言与上方「简 / 繁」完全同构 —— 同一套
   .btn.sm.ghost 样式（尺寸 / 圆角 / 配色均不另设），当前态由 data-mode
   表达：data-mode="s" 高亮「原」，data-mode="t" 高亮「译」。
   ⚠ 工具栏空间是本次优化的目的，故此处只给 .btn 补 padding 收紧，
     绝不改动按钮的 height / border-radius / background / color。 */
#rdrModeBtn .s, #rdrModeBtn .t { opacity: .45; }
#rdrModeBtn[data-mode="s"] .s, #rdrModeBtn[data-mode="t"] .t { opacity: 1; }

/* 划线高亮（临时与云端共用同一视觉） */
.rdr-body .rdr-hl {
  border-bottom: 2px solid rgba(212, 175, 55, .75);
  background: rgba(212, 175, 55, .13); border-radius: 2px; cursor: pointer;
}
html[data-theme="light"] .rdr-body .rdr-hl {
  border-bottom-color: rgba(138, 107, 30, .7); background: rgba(168, 132, 42, .16);
}
.rdr-body .rdr-hl.rdr-hl-tmp { border-bottom-style: dashed; }

/* 选中文字后的批注小框（跟随视口浮动，不挤压正文） */
.rdr-note-pop {
  position: fixed; z-index: 260; width: min(340px, calc(100vw - 24px));
  background: var(--card); border: 1px solid var(--line2); border-radius: var(--radius-sm);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35); padding: 12px 13px;
}
html[data-theme="light"] .rdr-note-pop { box-shadow: 0 10px 26px rgba(80, 64, 30, .18); }
.rdr-note-pop h5 { font-size: 12.5px; color: var(--gold2); margin-bottom: 8px; font-weight: 500; }
.rdr-note-pop .q {
  font-size: 12px; color: var(--dim); line-height: 1.75; margin-bottom: 8px;
  max-height: 62px; overflow: auto; padding-left: 8px; border-left: 2px solid var(--line2);
}
.rdr-note-pop textarea {
  width: 100%; min-height: 62px; resize: vertical; padding: 8px 10px; font-size: 13px;
  border-radius: 8px; background: var(--card2); border: 1px solid var(--line); color: var(--txt);
}
.rdr-note-pop textarea:focus { outline: none; border-color: rgba(212, 175, 55, .55); }
.rdr-note-pop .ops { display: flex; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
.rdr-note-pop .tip { font-size: 11.5px; color: var(--dim); line-height: 1.7; margin-top: 8px; }

/* 笔记列表（未选中文字时点击笔记按钮） */
.rdr-note-item { padding: 9px 11px; border-radius: var(--radius-sm); background: var(--card2); border: 1px solid var(--line); }
.rdr-note-item + .rdr-note-item { margin-top: 8px; }
.rdr-note-item .q { font-size: 12.5px; color: var(--txt); line-height: 1.8; border-left: 2px solid rgba(212, 175, 55, .55); padding-left: 8px; }
.rdr-note-item .b { font-size: 12.5px; color: var(--sub); line-height: 1.8; margin-top: 7px; white-space: pre-wrap; }
.rdr-note-item .m { font-size: 11px; color: var(--dim); margin-top: 6px; }
.rdr-note-item .ops { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }

@media (max-width: 900px) {
  .asst-modal { max-width: 100%; }
  .asst-out { max-height: 38vh; }
}

/* ============================================================
   9. 阅读笔记增强（第三十阶段）
   ------------------------------------------------------------
   本阶段**只在本文件末尾追加**，§8 及上方所有规则逐行未动
   （仍满足 verify_library_scope C2「上一阶段全文 == 现版前缀」契约）。
   新增内容包括：
     · 批注颜色五档（划线底色 + 笔记列表里的批注标识色），
       深/浅两套主题各给一版，保证对比度可控；
     · 颜色选择器（弹窗 / 心得框 / 编辑态共用一个组件）；
     · 「本篇心得」输入区；
     · 笔记条目按类型（划线 / 心得）与颜色分别着色。
   ⚠ 配色一律走既有 CSS 变量或 rgba()，**不写死 #RRGGBB** ——
     既满足 C4 的「追加段零硬编码色值」契约，也让两套主题自动跟随。
   ============================================================ */

/* ---------------- 9.1 划线颜色（data-color 由 JS 写入，默认 gold） ---------------- */
.rdr-body .rdr-hl[data-color="gold"] {
  border-bottom-color: rgba(212, 175, 55, .78); background: rgba(212, 175, 55, .13);
}
.rdr-body .rdr-hl[data-color="green"] {
  border-bottom-color: rgba(88, 180, 130, .78); background: rgba(88, 180, 130, .14);
}
.rdr-body .rdr-hl[data-color="blue"] {
  border-bottom-color: rgba(96, 150, 220, .78); background: rgba(96, 150, 220, .14);
}
.rdr-body .rdr-hl[data-color="pink"] {
  border-bottom-color: rgba(216, 124, 158, .78); background: rgba(216, 124, 158, .14);
}
.rdr-body .rdr-hl[data-color="gray"] {
  border-bottom-color: rgba(150, 158, 178, .78); background: rgba(150, 158, 178, .15);
}
/* 浅色主题下同色系加深（浅底上 rgba(.13) 几乎看不见） */
html[data-theme="light"] .rdr-body .rdr-hl[data-color="gold"] {
  border-bottom-color: rgba(138, 107, 30, .72); background: rgba(168, 132, 42, .18);
}
html[data-theme="light"] .rdr-body .rdr-hl[data-color="green"] {
  border-bottom-color: rgba(34, 122, 78, .72); background: rgba(52, 150, 100, .18);
}
html[data-theme="light"] .rdr-body .rdr-hl[data-color="blue"] {
  border-bottom-color: rgba(38, 90, 168, .72); background: rgba(58, 116, 196, .18);
}
html[data-theme="light"] .rdr-body .rdr-hl[data-color="pink"] {
  border-bottom-color: rgba(168, 62, 102, .72); background: rgba(200, 92, 132, .18);
}
html[data-theme="light"] .rdr-body .rdr-hl[data-color="gray"] {
  border-bottom-color: rgba(92, 100, 122, .72); background: rgba(110, 120, 142, .18);
}

/* ---------------- 9.2 颜色选择器（弹窗 / 心得框 / 编辑态共用） ---------------- */
.rdr-clrs { display: flex; align-items: center; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
.rdr-clrs > span { font-size: 11.5px; color: var(--dim); }
.rdr-clr {
  width: 17px; height: 17px; border-radius: 50%; cursor: pointer; display: inline-block;
  border: 2px solid transparent; box-shadow: inset 0 0 0 1px var(--line2);
}
.rdr-clr.c-gold { background: rgba(212, 175, 55, .85); }
.rdr-clr.c-green { background: rgba(88, 180, 130, .85); }
.rdr-clr.c-blue { background: rgba(96, 150, 220, .85); }
.rdr-clr.c-pink { background: rgba(216, 124, 158, .85); }
.rdr-clr.c-gray { background: rgba(150, 158, 178, .85); }
.rdr-clr.on { border-color: var(--txt); }
.rdr-clr:focus { outline: none; box-shadow: inset 0 0 0 1px var(--line2), 0 0 0 2px rgba(212, 175, 55, .45); }

/* ---------------- 9.3 「本篇心得」输入区（笔记弹窗顶部） ---------------- */
#rdrMemoWrap { margin-top: 12px; padding: 11px 12px; border-radius: var(--radius-sm);
  background: var(--card2); border: 1px solid var(--line); }
#rdrMemoWrap textarea {
  width: 100%; min-height: 62px; resize: vertical; padding: 8px 10px; font-size: 13px;
  border-radius: 8px; background: var(--card); border: 1px solid var(--line);
  color: var(--txt); font-family: inherit;
}
#rdrMemoWrap textarea:focus { outline: none; border-color: rgba(212, 175, 55, .55); }
#rdrMemoWrap .ops { display: flex; align-items: center; gap: 10px; margin-top: 9px; flex-wrap: wrap; }
#rdrMemoWrap .tip { font-size: 11.5px; color: var(--dim); line-height: 1.7; }

/* ---------------- 9.4 笔记列表：类型标签与按色标识 ---------------- */
.rdr-note-item .k {
  display: inline-block; font-size: 11px; color: var(--gold2); line-height: 1.6;
  border: 1px solid var(--line2); border-radius: 6px; padding: 1px 7px; margin-bottom: 6px;
}
.rdr-note-item .q.rdr-q-gold { border-left-color: rgba(212, 175, 55, .78); }
.rdr-note-item .q.rdr-q-green { border-left-color: rgba(88, 180, 130, .78); }
.rdr-note-item .q.rdr-q-blue { border-left-color: rgba(96, 150, 220, .78); }
.rdr-note-item .q.rdr-q-pink { border-left-color: rgba(216, 124, 158, .78); }
.rdr-note-item .q.rdr-q-gray { border-left-color: rgba(150, 158, 178, .78); }
/* 批注文字按所选颜色着色（浅色主题下用同色系深色，保证可读） */
.rdr-note-item .b.rdr-b-gold { color: var(--sub); }
.rdr-note-item .b.rdr-b-green { color: rgba(88, 180, 130, .95); }
.rdr-note-item .b.rdr-b-blue { color: rgba(120, 168, 232, .95); }
.rdr-note-item .b.rdr-b-pink { color: rgba(224, 140, 172, .95); }
.rdr-note-item .b.rdr-b-gray { color: var(--dim); }
html[data-theme="light"] .rdr-note-item .b.rdr-b-green { color: rgba(30, 108, 70, .95); }
html[data-theme="light"] .rdr-note-item .b.rdr-b-blue { color: rgba(34, 80, 150, .95); }
html[data-theme="light"] .rdr-note-item .b.rdr-b-pink { color: rgba(152, 56, 92, .95); }

/* ============================================================
   10. 全站字号放大（第三十三阶段）
   ------------------------------------------------------------
   本节**只在本文件末尾追加**，§9 及上方所有规则逐行未动
   （仍满足 verify_library_scope C2「上一阶段全文 == 现版前缀」契约）。

   目标：全站内容字号整体偏小、长时间阅读费眼 → 正文统一放大一号。
   手段：**只覆盖 font-size 这一个属性**，不新增 / 不删除 / 不修改任何
        盒模型属性（width / height / padding / margin / gap / line-height /
        grid / flex / 定位一律不动），故版面结构与元素位置保持原样。

   幅度口径（小字提幅大于大字，避免小字相对更挤）：
     · 8–11.5px 的极小字（角标 / 徽标 / 序号）→ +1px
     · 11.5–13.5px 的正文与辅助字 → +1px
     · 14px 及以上的标题 / 按钮 → +1px（仅一档，不跳级）
     · 固定尺寸的圆形 / 方块容器内文字 → **不动**（见下方 §10.5）

   ⚠ 定宽容器红线：凡父级带固定 width/height 且内部文字已居中填满的
     （圆形徽标 .shtag / .thgan / 关闭钮 .mcls / 主题钮 .csthemebtn），
     放大必然溢出或挤压，故本节一律排除，保持原字号。
   ============================================================ */

/* ---------------- 10.1 基础正文与标题 ---------------- */
body { font-size: 16px; }                 /* 原 15px */
.disclaimer-bar { font-size: 13.5px; }    /* 原 12.5px */
.hero .sub { font-size: 15px; }           /* 原 14px */
.hero .badge-row span { font-size: 12.5px; } /* 原 11.5px */

/* ---------------- 10.2 导航与按钮 ---------------- */
.nav-links a { font-size: 15px; }         /* 原 14px */
/* ★ 2026-10-15 导航字号统一：.nav-drop-t 与 .nav-asst 的选择器特异性
   高于上面的 `.nav-links a`（前者 0,2,0 / 0,2,1，后者 0,1,1），
   故仍停留在 14px，导致「命例对照」「研习助手」比
   「排盘工作台/古籍资料库/术语总表/会员中心」小一号 —— 此处补齐覆盖，
   使全部一级导航项字号、行高（继承 1.75 → 26.25px）完全一致。 */
.nav-drop > .nav-drop-t { font-size: 15px; }
.nav-links a.nav-asst { font-size: 15px; }
.nav-user { font-size: 14px; }            /* 原 13px */
.vip-badge, .free-badge { font-size: 12px; } /* 原 11px */
.btn { font-size: 15px; }                 /* 原 14px */
.btn.sm { font-size: 14px; }              /* 原 13px */

/* ---------------- 10.3 卡片 / 列表 / 表格 / 表单 ---------------- */
.cs-card > h3 { font-size: 16px; }        /* 原 15px */
.cs-card > h3 small { font-size: 12.5px; }/* 原 11.5px */
.entry-card h4 { font-size: 16px; }       /* 原 15px */
.entry-card p { font-size: 14px; }        /* 原 13px */
.entry-card .lock { font-size: 12px; }    /* 原 11px */
.list-item .main h4 { font-size: 16px; }  /* 原 15px */
.list-item .main p { font-size: 14px; }   /* 原 13px */
.list-item .meta { font-size: 13px; }     /* 原 12px */
.tbl { font-size: 14.5px; }               /* 原 13.5px */
.tbl th { font-size: 13.5px; }            /* 原 12.5px */
.field label { font-size: 13.5px; }       /* 原 12.5px */
.field input, .field select, .field textarea { font-size: 15px; } /* 原 14px */
.field .hint { font-size: 13px; }         /* 原 12px */
.tag { font-size: 12.5px; }               /* 原 11.5px */
.tip-box { font-size: 14px; }             /* 原 13px */

/* ---------------- 10.4 页脚 / 浮层 / 会员中心 ---------------- */
.site-foot { font-size: 13.5px; }         /* 原 12.5px */
.site-foot .foot-brand .slogan { font-size: 13.5px; } /* 原 12.5px */
.cs-modal h3 { font-size: 18px; }         /* 原 17px */
.toast-float { font-size: 14.5px; }       /* 原 13.5px */
.mbr-head .mbr-lead { font-size: 13.5px; }/* 原 12.5px */
.mbr-sec-h { font-size: 16px; }           /* 原 15px */
.mbr-sec-h small { font-size: 12.5px; }   /* 原 11.5px */
.mbr-cmp-card > h4 { font-size: 15.5px; } /* 原 14.5px */
.mbr-list li { font-size: 14.5px; }       /* 原 13.5px */
.mbr-list.vip li::before { font-size: 12px; } /* 原 11px */
.mbr-guest-tip { font-size: 13.5px; }     /* 原 12.5px */
.mbr-plan-head h4 { font-size: 16px; }    /* 原 15px */
.mbr-price-unit { font-size: 13px; }      /* 原 12px */
.mbr-plan-brief { font-size: 13px; }      /* 原 12px */
.mbr-plan-rights li { font-size: 13.5px; }/* 原 12.5px */
.mbr-plan-rights li::before { font-size: 12px; } /* 原 11px */
.mbr-plan-note { font-size: 13px; }       /* 原 12px */
.mbr-foot-note p { font-size: 14px; }     /* 原 13px */
.mbr-foot-note .mbr-legal { font-size: 13.5px; } /* 原 12.5px */
.home-col .home-ref p { font-size: 14.5px; } /* 原 13.5px */

/* ---------------- 10.5 定宽容器：字号一律不动 ----------------
   .brand .mark(32px 方块) / .csthemebtn(34px 圆钮) / .menu-btn(22px 汉堡)
   三者的图形与文字已按容器尺寸配平，放大会溢出或挤压，故整节排除。 */

/* ---------------- 10.6 资料库 / 阅读页 / 书架 ---------------- */
.lib-search input { font-size: 15px; }    /* 原 14px */
.lib-group-h { font-size: 14px; }         /* 原 13px */
.lib-group-h small { font-size: 12.5px; } /* 原 11.5px */
.lib-book-item h4 { font-size: 15px; }    /* 原 14px */
.lib-book-item p { font-size: 13.5px; }   /* 原 12.5px */
.lib-pager .pg-info { font-size: 13.5px; }/* 原 12.5px */
.lib-hit { font-size: 12px; }             /* 原 11px */
.lib-snippet { font-size: 13.5px; }       /* 原 12.5px */

.rdr-toc h4 { font-size: 14.5px; }        /* 原 13.5px */
.rdr-toc h4 small { font-size: 12px; }    /* 原 11px */
.rdr-toc li a { font-size: 14px; }        /* 原 13px */
.rdr-toc li a::before { font-size: 12.5px; } /* 原 11.5px */
.rdr-toc li a .lk { font-size: 12px; }    /* 原 11px */
.rdr-bar .grp > span { font-size: 13px; } /* 原 12px */
.rdr-title { font-size: 22px; }           /* 原 21px */
.rdr-meta { font-size: 13.5px; }          /* 原 12.5px */
.rdr-ch-h { font-size: 16px; }            /* 原 15px */
.rdr-ch-h small { font-size: 12.5px; }    /* 原 11.5px */
.rdr-locked p { font-size: 14px; }        /* 原 13px */
.rdr-src { font-size: 12.5px; }            /* 原 11.5px */
.rdr-sel { font-size: 13.5px; }            /* 原 12.5px */
.rdr-note-pop h5 { font-size: 13.5px; }    /* 原 12.5px */
.rdr-note-pop .q { font-size: 13px; }      /* 原 12px */
.rdr-note-pop textarea { font-size: 14px; }/* 原 13px */
.rdr-note-pop .tip { font-size: 12.5px; }  /* 原 11.5px */
.rdr-note-item .q { font-size: 13.5px; }  /* 原 12.5px */
.rdr-note-item .b { font-size: 13.5px; }  /* 原 12.5px */
.rdr-note-item .m { font-size: 12px; }     /* 原 11px */
.rdr-note-item .k { font-size: 12px; }     /* 原 11px */
.rdr-clrs > span { font-size: 12.5px; }   /* 原 11.5px */
#rdrMemoWrap textarea { font-size: 14px; } /* 原 13px */
#rdrMemoWrap .tip { font-size: 12.5px; }   /* 原 11.5px */

.shelf-card h4 { font-size: 15.5px; }     /* 原 14.5px */
.shelf-card p { font-size: 13.5px; }       /* 原 12.5px */

/* ---------------- 10.7 研习助手弹窗 ---------------- */
.asst-head h3 { font-size: 17.5px; }       /* 原 16.5px */
.asst-head small { font-size: 13px; }     /* 原 12px */
.asst-quota { font-size: 13px; }           /* 原 12px */
#csAsstInput { font-size: 15px; }          /* 原 14px */
.asst-acts .asst-hint { font-size: 13px; }/* 原 12px */
.asst-out { font-size: 14.5px; }           /* 原 13.5px */
.asst-loading { font-size: 14px; }         /* 原 13px */
.asst-lock { font-size: 14.5px; }          /* 原 13.5px */
.asst-foot { font-size: 12.5px; }          /* 原 11.5px */

/* ---------------- 10.8 阅读正文：随 --rdr-fs 同步 +1px ----------------
   正文由 JS 写入的 --rdr-fs 驱动（14/16/19 三档），本节在 CSS 侧统一 +1px，
   使三档实际显示为 15/17/20px；工具条下拉与记忆键逻辑零改动。 */
.rdr-body { font-size: calc(var(--rdr-fs, 16px) + 1px); }
.rdr-body .rdr-note { font-size: calc(var(--rdr-fs, 16px) - 1.5px); }

/* ---------------- 10.9 窄屏同步放大 ----------------
   移动端基础字号本就偏小，本节在 §10.1–§10.8 之上再各 +0.5px，
   使手机端阅读体验与桌面端拉齐；布局属性同样一律不动。 */
@media (max-width: 720px) {
  body { font-size: 16.5px; }
  .disclaimer-bar { font-size: 14px; }
  .btn { font-size: 15.5px; }
  .btn.sm { font-size: 14.5px; }
  .cs-card > h3 { font-size: 16.5px; }
  .entry-card p { font-size: 14.5px; }
  .list-item .main p { font-size: 14.5px; }
  .list-item .meta { font-size: 13.5px; }
  .tbl { font-size: 15px; }                /* 原移动端 12.5px，放幅最大 */
  .tbl th { font-size: 14px; }
  .field input, .field select, .field textarea { font-size: 15.5px; }
  .field label { font-size: 14px; }
  .tip-box { font-size: 14.5px; }
  .site-foot { font-size: 14px; }
  .mbr-list li { font-size: 15px; }
  .mbr-foot-note p { font-size: 14.5px; }
  .lib-book-item p { font-size: 14px; }
  .lib-snippet { font-size: 14px; }
  .rdr-toc li a { font-size: 14.5px; }
  .rdr-body { font-size: calc(var(--rdr-fs, 16px) + 1.5px); }
  .rdr-locked p { font-size: 14.5px; }
  .asst-out { font-size: 15px; }
}

/* ---------------- 10.10 窄屏导航条（≤960px）字号跟进 ----------------
   ⚠ 原 §导航折叠段里的 `.nav-right .btn.sm` 特异性为 (0,3,0)，**高于**本节
     §10.2 的 `.btn.sm`(0,2,0)，故窄屏下登录/注册仍会漏回 12.5px（比桌面还小）。
     此处用同等特异性 (0,3,0) 补一条覆盖，把它拉到与桌面端一致的档位；
     仅改 font-size，padding / 尺寸 / 折叠逻辑一律不动。 */
@media (max-width: 960px) {
  .nav-right .btn.sm { font-size: 14px; }
}

/* ==========================================================================
   第三十阶段：典籍卡片统一改版规范
   --------------------------------------------------------------------------
   适用范围：library.html（古籍资料库）、bookshelf.html（我的书架）等
             所有渲染「典籍书籍卡片」的页面，统一套用 .tcard 系列类名。
   规范要点：
     1. 封面提亮 —— 移除灰度/暗化滤镜，提升亮度与对比度，解决暗淡模糊；
     2. 文字精简 —— 大字书名 + 单行小字「朝代·撰者·版本」，不渲染长篇简介；
     3. 按钮唯一 —— 卡片底部只保留【开始阅读】；
     4. 尺寸统一 —— 所有卡片宽高完全一致，间距统一，布局整齐均衡；
     5. 移动端同步 —— 单列/双列自适应，封面与文字保持清爽。
   ========================================================================== */

/* ---------- 卡片网格：统一间距与列宽 ----------
   第三十阶段紧凑化：列宽 248 → 208px（封面 331 → 278px，约缩小 16%）
   间距按需求固定：水平 24px / 垂直 28px（用 column-gap / row-gap 分开控制）。 */
.tcard-grid {
  display: grid;
  column-gap: 24px;                            /* 水平间距固定 24px */
  row-gap: 28px;                               /* 垂直间距固定 28px */
  /* ★ 固定 4 列（需求：单排固定 4 本，严禁 5 本）。
     列宽 268px = (内容区 1144px - 3×24px 间距) / 4，四本正好铺满一行。
     仅 900px 以下才降列；桌面端恒为 4 本。 */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  max-width: 1144px;                          /* 4×268 + 3×24 = 1144，铺满且不溢出 */
}

/* ---------- 卡片本体：统一固定高度，保证所有卡片完全一致 ----------
   第三十四阶段：卡片内缩6px 内边距，让封面区与文字区成为**一个完整
   视觉单元**（而非多层分段拼接）；底色铺满，绝不露底层白板。

   ★★★ 第卅九阶段：卡片高度**锁死**（--tcard-fixed-h）★★★
     需求：以后再新增古籍，只要加到书架列表里就自动按统一高度渲染，
           绝不会因为「没封面」就把卡片拉高，整行卡片顶部/底部全对齐。

     实测根因（1440px 视口，25 张卡片量测getBoundingClientRect）：
       · 有封面卡片：coverH = 293.41px，卡片总高 450.55px
       · 无封面卡片：coverH = 345.91px，卡片总高 503.05px（高出 52.50px）
     真凶：`.tcard-cover.is-empty` 写了 `display:grid`，
     而 .tcard-cover::before（撑高的占位块）**也是一个grid 子项** ——
     于是「占位块」与「書字」被排成**上下两行**，
     ::before 的 293.41px 之外又叠了一行文字高度 ≈ 52.5px。
     grid 行高由内容决定，占位块无法把多余那一行压掉。

     修法（两条同时生效，缺一不可）：
       ① .tcard-cover.is-empty 改为 position:absolute 覆盖定位，
          「書」字不再参与任何行分配 → 无封面卡片高度回到与有封面**完全一致**；
       ② .tcard 用 min-height 锁死 --tcard-fixed-h，
          即使将来出现异常内容（超长书名换行、字体回退等），
          卡片高度也被钳住，不会把整行撑歪。

     --tcard-fixed-h 的取值 = 封面区高 + 文字区固定高，与实测 450.55px 对齐；
     各断点按同比例覆写（见文件末尾 media查询）。 */
.tcard {
  /* ★ 单一底色变量：卡片本体与封面容器共用，消除「白底→米白→深底」三层分层。
     浅色主题下 --tcard-bg 为暖米白（与古籍纸色同族），深色主题下为深蓝黑，
     两者都由同一变量驱动，故卡片整体永远只有**一层**底色。 */
  --tcard-bg: #efe7d7;
  display: flex;
  flex-direction: column;                      /* 竖排：封面在上、信息在下 */
  background: var(--tcard-bg);                 /* 整卡唯一底色 */
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  padding: 6px;                                /* 卡片四周内缩，封面不贴边 */
  /* ★ 2026-10-17 修正「移动端封面下方空白过大」：
     原实现用 `min-height: var(--tcard-fixed-h)` 把卡片总高锁死（移动端 2 列 505px）。
     但封面区高度由 `.tcard-cover::before { padding-top:133.33% }` **按卡片宽度**等比撑出，
     移动端 2 列时卡片变窄（实测 390px 下仅 159px 宽），封面只有 176px 高；
     而 505px 是按更宽的 3 列卡片定的 —— 内容填不满，多出的高度就变成封面下方的空白。
     实测：390px 断点按钮下方空白 212px、360px 断点 230px，桌面端仅 155px。

     修法：改为按内容自然撑开（不再写死总高），由封面区（等比）+ 信息区（内容）
     累加得出真实高度，既消除多余留白，又**不改变封面比例与既有版式观感**。
     同排卡片等高由 `.tcard-grid` 的 grid 默认 align-items:stretch 保证，
     且信息区设 flex:1 让按钮始终贴卡片底部对齐。 */

  /* ★ 第三十七阶段：外层卡片**不参与任何 hover 动画**。
     原先这里写着 transition: border-color / transform / box-shadow，
     配合下面的 translateY(-2px) 造成卡片本体在 hover 时位移 ——
     卡片一动，鼠标相对于元素的位置就变了；靠近卡片上边缘时鼠标会"离开"
     元素 → :hover 失效 → transform 复原 → 鼠标又"进入" → :hover 重新生效，
     于是 mouseover/mouseout 被无限反复触发，表现为**持续不停频闪**。
     移开时残留的外扩 box-shadow 落在相邻卡片上，视觉上像"一层挡板"。
     现改为：外层完全不响应 hover，宽高/位置/边界全程固定；
     唯一的缩放动效下沉到封面图片（见下方 .tcard-cover img）。 */
}
/* ★ 外层 hover 规则**只保留描边变色**（不改变盒子尺寸、不改变位置、
   不产生阴影外扩，因此不会影响鼠标感应热区，也不会遮挡相邻卡片）。
   border-color 属绘制属性，不触发重排，故不参与上述往复循环。 */
.tcard:hover {
  border-color: rgba(212, 175, 55, .45);
}
/* 深色主题：卡片整体转为深色，封面容器同步跟随，不产生米白夹层 */
html[data-theme="dark"] .tcard { --tcard-bg: #1c2133; }

/* ---------- 封面区：单一底色铺满，图片水平居中（第三十五阶段） ----------
   ★ 需求要点：**移除米白夹层，只保留一层背景色**。
     做法：封面容器不再自设颜色，直接继承卡片本体的 --tcard-bg。
     于是「卡片底 → 封面区」为**同一层底色**，彻底消除
     「浅色页白 → 米白封面 → 深色卡底」的多层割裂感。 */
.tcard-cover {
  position: relative;
  width: 100%;
  padding: 0 5%;                               /* 左右各内缩 5% = 图片等比缩小 10% */
  overflow: hidden;
  display: block;
  /* ★ 与卡片本体同一底色变量 —— 不是新的一层 */
  background: var(--tcard-bg);
}
/* ---------- 悬浮遮罩（第三十七阶段：改用伪元素实现） ----------
   需求：遮罩必须用 ::before / ::after 实现，不占文档布局空间、不改变 hover 热区。
   实现要点（三条都是硬约束，缺一条就会复现闪烁）：
     ① position:absolute —— 完全脱离文档流，零布局影响；
     ② inset:0 —— 用 inset 而非 width/height，避免任何尺寸计算；
     ③ pointer-events:none —— 遮罩**永不接收鼠标事件**，
        故不可能把 :hover 状态"抢走"或造成事件往复；
   旧实现把 box-shadow 直接挂在 .tcard:hover 上，阴影外扩到相邻卡片，
   既改变了视觉边界（像一层挡板），也让相邻卡片的感应区被污染。 */
.tcard-cover::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;                        /* ★ 关键：不参与命中测试 */
  background: linear-gradient(180deg,
              rgba(212, 175, 55, .00) 0%,
              rgba(212, 175, 55, .06) 100%);
  opacity: 0;
  transition: opacity .28s ease;               /* 只过渡 opacity，不动任何盒模型属性 */
}
.tcard:hover .tcard-cover::after { opacity: 1; }
/* 占位撑高：让封面区高度与图片等高（与图片同处一层背景上，不产生色带）
   ★ 第三十八阶段：为「无封面占位块」也提供确定的定位上下文 ——
     .is-empty 与 img 都以本容器为定位包含块（position:relative 已在上面），
     且两者的尺寸都由这里的 ::before 撑出的高度决定，不再互相依赖。 */
.tcard-cover::before {
  content: '';
  display: block;
  padding-top: 133.3333%;                     /* = (100% - 10%) / 0.75，与图片区等高 */
}
.tcard-cover img {
  /* 图片水平居中置于底板之上（容器 padding 已为图片留出左右空间）
     ★ 第三十八阶段修复「封面图异常放大成挡板」：
       旧写法是 aspect-ratio:3/4 + height:auto + position:absolute。
       这三者组合在部分渲染路径下（真实 GPU 合成、浏览器缩放非 100%、
       图片解码尚未完成时）会让 aspect-ratio 退回图片**原始像素尺寸**，
       600×800 的封面就以 1:1 铺开，横跨三张卡片且被 overflow:hidden
       裁成一整块 —— 视觉上就是"一张巨大的图挡住整个卡片区"。
       现在改为由 ::before 占位块确定高度，图片用 height:100% + width:100%
       跟随容器（inset 定位），**不再让图片参与任何尺寸推算**：
         · 容器高度 = ::before 的 padding-top（纯百分比，与图片无关，恒定）；
         · 图片尺寸 = 100%/100%（完全由容器决定，天然不可能溢出）；
         · object-fit:cover 负责裁切填充，比例不符也不会变形。
       这样即使图片加载失败或尺寸异常，渲染结果依然稳定。 */
  position: absolute;
  /* 四件套显式给全（top/left/width/height），与 .tcard-cover.is-empty 保持一致。
     不用 inset：父容器 .tcard-cover 有 padding 0 5%，
     inset + width:auto 会让宽度退化为铺满 padding box 而横向溢出。 */
  top: 0;
  left: 5%;
  width: 90%;
  /* ★ 高度必须**显式等于容器高**：写 height:auto 时图片会退回按自身 3:4
     推算（244.5 → 326px），比容器（293.4px）高出 32.6px 而溢出。
     height:100% + object-fit:cover 让尺寸完全由容器决定，
     比例不符时裁切填充而非溢出或变形。 */
  height: 100%;
  object-fit: cover;                            /* 裁切填充，绝不拉伸变形 */
  display: block;
  /* 核心：提升亮度与对比度，抵消素材本身的灰暗感。
     ★ 参数自第三十阶段起**保持不变**（禁止再压暗、禁止叠加灰度遮罩）。 */
  filter: brightness(1.14) contrast(1.12) saturate(1.06);
  image-rendering: auto;
  /* ★ 唯一允许的 hover 动效：图片自身的 scale。
     仅过渡 transform，不过渡 width/height/padding/margin/border，
     故缩放过程不产生任何重排，鼠标感应热区恒定不变。
     ★ 不用 will-change: transform —— 它会强制提升为独立合成层，
       在真实 GPU 路径下与 overflow:hidden 裁剪叠加时容易出现
       「合成层尺寸未随裁剪更新」而使图片溢出显示，故一律不用。 */
  transform: scale(1);
  transform-origin: center center;
  transition: transform .35s ease;
}
/* hover 放大：只作用于封面图片，卡片外层容器完全不动 */
.tcard:hover .tcard-cover img { transform: scale(1.06); }
/* 无封面时的占位
   ★ 第卅九阶段修复「无封面卡片比有封面卡片高 52.5px」（真凶）
     ------------------------------------------------------------
     实测（1440px）：无封面卡片 coverH=345.91px、有封面 293.41px，
     差值恰好 52.50px = 一行文字的高度。

     ★ 关键认识：DOM 是 <div class="tcard-cover is-empty">書</div> ——
       **这个元素自己就是 .tcard-cover 容器**（不是容器里的子元素）。
       旧规则给它写 `display:grid`，于是本容器变成一个**两行**的网格：
         第 1 行 = ::before 占位块（padding-top 撑出的 293.41px）
         第 2 行 = 「書」字文本
       grid 行高由各自内容决定，占位块**无法**吸收第二行，
       结果高度 = 293.41 + 52.5 = 345.91 → 整张卡片被拉高 52.5px。

     修法：把 .is-empty 从「流内grid 容器」改为**绝对定位覆盖层**。
       · position/width/height 交还给 .tcard-cover 基础规则
         （relative + width:100% + ::before 的 padding-top 撑高）；
       · 「書」字用 ::after 绝对居中，完全脱离文档流，
         既不参与行分配，也不影响容器高度。
       这样无封面卡片与有封面卡片走**完全相同**的几何路径。

     ★ 另外：真正的兜底不是这个色块，而是 <img> 回退到 default.png
       （见下方 .tcard-cover img 的 onerror 处理与 JS 侧 fallback），
       本规则仅用于「连 default.png 都取不到」的极端情况。 */
.tcard-cover.is-empty {
  display: block;
  background: #e3d9c7;          /* 同族略深，仍是单层底色 */
  color: #8a7a5c;
  font-family: var(--font-serif);
}
/* 「書」字：绝对居中，不占文档流、不产生额外行高 */
.tcard-cover.is-empty::after {
  content: '書';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  color: #8a7a5c;
  pointer-events: none;
}

/* ---------- 文字区：书名 + 单行小字（第三十四阶段：整块居中 + 分段固定留白） ----------
   需求要点：
     · 书名与朝代撰者打包为一个**整体文字块**，整体水平居中；
     · 垂直留白分三段，各自为**固定值**，不随文字长短被压缩：
         封面底 → 书名：--tcard-gap-top
         书名 → 朝代撰者：--tcard-gap-mid（较小）
         朝代撰者底 → 按钮：--tcard-gap-bottom（充足，拉开距离）
     · 用 margin 而非 flex:gap 控制这三段 —— flex 的 gap 与
       margin-top:auto 会在内容变多时互相挤压，导致留白不稳定。 */
.tcard {
  --tcard-gap-top: 14px;      /* 封面底 → 书名（固定） */
  --tcard-gap-mid: 4px;       /* 书名 → 朝代撰者（较小，不紧贴） */
  /* 朝代撰者 → 按钮：**加大留白**，杜绝文字紧贴按钮的拥挤（第三十五阶段重点）。
     该值为独立固定量，不参与任何 flex 分配，不会被文字长短压缩。 */
  --tcard-gap-bottom: 22px;
}
.tcard-body {
  padding: var(--tcard-gap-top) 11px var(--tcard-gap-bottom);
  display: flex;
  flex-direction: column;
  align-items: center;         /* ★ 整个文字块水平居中 */
  flex: 1;
}
.tcard-title {
  font-family: var(--font-serif);
  font-size: 15px;
  line-height: 1.5;            /* 行高放宽，两行之间不紧贴 */
  color: var(--gold2);
  margin: 0;
  text-align: center;          /* 块内文字亦居中 */
  width: 100%;
  /* 书名过长时省略，保持所有卡片行数一致 */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 3em;             /* 两行占位 = 2 × 1.5em，保证等高 */
  letter-spacing: .2px;
}
.tcard-sub {
  font-size: 11.5px;
  line-height: 1.6;            /* 单行小字也留出行高，避免贴边 */
  color: var(--dim);
  margin: var(--tcard-gap-mid) 0 0;   /* ★ 书名与小字之间的小间距 */
  text-align: center;
  width: 100%;
  /* 单行小字：朝代·撰者·版本（永不折行，过长省略） */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 1.6em;           /* 预留一行高度，保证等高 */
}

/* ---------- 底部按钮：唯一【开始阅读】 ----------
   ★ 文字块与按钮的间距为**固定值**（上方面板的 padding-bottom），
     不用 margin-top:auto 吸收剩余空间 —— 后者会在文字变多时把间距压扁，
     导致「有的卡片文字与按钮挤在一起」。这里改为固定 padding + 顶边细线，
     所有卡片的留白完全一致。 */
.tcard-ops {
  padding-top: 6px;
  border-top: 1px solid var(--line);   /* 细分隔线，强化「文字块 / 操作区」分区 */
}
.tcard-ops .btn {
  width: 100%;
  justify-content: center;
  padding: 6px 10px;                           /* 压缩按钮高度 */
  font-size: 12.5px;                           /* 同步微调字号，维持可读 */
  line-height: 1.5;
}

/* ---------- 移动端适配：同步缩小卡片，保持间距比例（24:28 ≈ 6:7） ----------
   注：封面「等比缩小 10%」由 .tcard-cover 的 padding:0 5% 实现，
       是**相对比例**而非绝对像素，故移动端自动继承，无需重复定义。 */
/* ---------- 卡片高度的各断点处理（2026-10-17 修正） ----------
   ★ 原第卅九阶段在此按断点写死 --tcard-fixed-h（1100/900 → 520px，560 → 505px）。
     该方案的前提是「封面高 + 文字高」在各断点可线性外推，实测不成立：
     封面高由 padding-top 百分比**随列宽联动**，而列数一变、卡片宽度就变，
     文字区高度又受「书名是否换行」影响 —— 两者不同步，锁死的总高必然留空。
     现已改为内容自然撑开（见 .tcard 注释），此段仅保留各断点的**列数**适配，
     不再设置任何固定高度。 */
/* ---------- 移动端适配（第三十五阶段：桌面锁 4 列，窄屏才降列） ---------- */
@media (max-width: 1100px) {
  /* 桌面 4 列在窄桌面下会挤压封面 → 此档降为 3 列，保持卡片足够宽 */
  .tcard-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-width: none;
  }
}
@media (max-width: 900px) {
  .tcard-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 18px;                          /* 按桌面比例等比缩小 */
    row-gap: 21px;
  }
  .tcard { padding: 5px; }                     /* 卡片内缩同步收窄 */
  .tcard-body { padding: 12px 8px 18px; }      /* 三段留白在窄屏下略放宽 */
  .tcard-title { font-size: 13.5px; line-height: 1.45; min-height: 2.9em; }
  .tcard-sub { font-size: 11px; margin-top: var(--tcard-gap-mid); }
  .tcard-ops { padding-top: 6px; }
  .tcard-ops .btn { padding: 5px 8px; font-size: 12px; }
}
@media (max-width: 560px) {
  .tcard-grid {
    grid-template-columns: repeat(2, 1fr);      /* 手机端双列 */
    column-gap: 14px;
    row-gap: 17px;
  }
  .tcard { --tcard-gap-bottom: 18px; }         /* 手机端留白略收，仍明显 */
}

/* ---------- 骨架容器的行高锁（消除剩余布局偏移） ----------
   上一轮骨架屏实测 CLS 由 0.6173 降到 0.3832，但仍有 0.31 的落差：
   原因很具体 —— 骨架固定铺 8 个（桌面 4 列 = 2 行，约 978px），
   而真实 20 本是 5 行（约 2487px），替换瞬间仍要向下撑开 1509px。

   这里把「预留高度」交给 JS 按真实条目数算：`.tcard-slot` 由脚本写入
   --slot-h（单卡实测高）与 --slot-rows（行数），容器以 min-height 锁高；
   骨架块 absolute 脱离文档流、仅作视觉过渡，不参与高度计算。
   真实网格就位后高度与其相等 → 落差趋近 0。
   注：必须用 min-height 而非额外占位元素 —— 后者会与骨架自身高度叠加。 */
.tcard-slot {
  position: relative;
  min-height: calc(var(--slot-h, 475px) * var(--slot-rows, 1)
                 + var(--slot-gap, 28px) * (var(--slot-rows, 1) - 1));
}
/* 骨架脱离文档流：容器高度只由 min-height 决定，二者不会重复叠加 */
.tcard-slot > .tcard-grid[data-skel] {
  position: absolute;
  left: 0; right: 0; top: 0;
}
/* 真实网格就位后不再需要锁高，让其自然撑开 */
.tcard-slot.is-ready { min-height: 0; }

@media (max-width: 900px) {
  .tcard-slot { --slot-gap: 21px; }
}
@media (max-width: 560px) {
  .tcard-slot { --slot-gap: 17px; }
}

/* ---------- 条目列表的高度预留（library.html 同款） ---------- */
.row-slot {
  position: relative;
  min-height: calc(var(--row-h, 96px) * var(--row-rows, 1));
}
/* 骨架脱离文档流，高度只由 min-height 决定，避免二者叠加 */
.row-slot > [data-skel] { position: absolute; left: 0; right: 0; top: 0; }
.row-slot.is-ready { min-height: 0; }

/* ---------- 浅色主题下封面提亮 ---------- */
/* 浅色主题下封面提亮略保守（白底上无需重提亮）。
   ★ 卡片底色**不再单独指定**，与封面容器共用 --tcard-bg 变量 ——
     浅色主题下即为默认的 #efe7d7 暖米白，整卡只有一层底色，
     彻底消除「页面白 → 卡面白 → 封面米白」的多层分层感。 */
html[data-theme="light"] .tcard-cover img {
  filter: brightness(1.06) contrast(1.08) saturate(1.04);
}
html[data-theme="light"] .tcard { --tcard-bg: #efe7d7; }

/* ==========================================================================
   第三十六阶段：书架页闪烁修复 —— 骨架屏 + 封面懒加载
   --------------------------------------------------------------------------
   实测根因（限速 4Mbps + 登录态 + 正式库副本）：
     CLS = 0.6173，主偏移 0.5873 发生在 2626ms，
     偏移源为 SECTION.cs-card ×2 + FOOTER —— 即**卡片区块从「加载中…」一行
     瞬间暴涨为 20 张卡片**，把整页往下推。这是肉眼看到的「不停闪烁」。
     叠加：19 张封面图共 16MB 一次性并发下载，12 张到 29.5s 才陆续到位，
           持续的重绘 + 布局压力让闪烁被放大。

   本阶段三条对策：
     ① .tcard-skel 骨架屏：首屏即按真实卡片的**精确尺寸**占位，
        数据到达后被真卡片同尺寸替换 → 布局偏移趋近 0；
     ② 封面图 loading="lazy" + decoding="async"（见 bookshelf/library 的 card()）
        → 视口外图片不抢首屏带宽，首屏不再被 16MB 淹没；
     ③ 服务端补 ETag/Last-Modified（server/utils/http.js）
        → 二次进入页面时封面图全部 304，字节数为 0。
   ========================================================================== */

/* 骨架屏：几何完全对齐 .tcard（同 padding / 同封面比例 / 同文字段高度），
   因此替换瞬间不产生任何布局位移。刻意**不加动画**——闪烁问题本身
   就是「动得太频繁」，此处保持静态灰块即可。 */
.tcard-skel {
  display: flex;
  flex-direction: column;
  background: var(--tcard-bg, #efe7d7);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  padding: 6px;
}
.tcard-skel .sk-cover {
  position: relative;
  width: 100%;
  padding: 0 5%;
}
/* 与 .tcard-cover::before 同一算式：133.3333% × 0.9W = 1.2W = 图片实际高度 */
.tcard-skel .sk-cover::before {
  content: '';
  display: block;
  padding-top: 133.3333%;
}
.tcard-skel .sk-body {
  padding: 14px 11px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.tcard-skel .sk-line {
  border-radius: 3px;
  background: var(--line);
  opacity: .55;
}
.tcard-skel .sk-title { width: 82%; height: 15px; }
/* 两行占位 = 2 × 1.5em × 15px ≈ 45px，与 .tcard-title 的 min-height 对齐 */
.tcard-skel .sk-title2 { width: 58%; height: 15px; margin-top: 5px; }
.tcard-skel .sk-sub { width: 70%; height: 12px; margin-top: 13px; }
.tcard-skel .sk-ops {
  width: 100%;
  margin-top: 16px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
}
.tcard-skel .sk-btn {
  height: 31px;
  border-radius: var(--radius-sm);
  background: var(--line);
  opacity: .38;
}
@media (max-width: 900px) {
  .tcard-skel { padding: 5px; }
  .tcard-skel .sk-body { padding: 12px 8px 18px; }
}
