:root{
  --bg:#0d1017; --bg2:#11151f; --panel:#161b28; --panel2:#1b2132;
  --line:rgba(216,178,110,.18); --line2:rgba(255,255,255,.07);
  --accent:#d8b26e; --accent2:#f0d9a8; --red:#c05a4e; --jade:#5a9e8f; --blue:#6d94c4;
  --tx:#e8e2d4; --tx2:#a89f8c; --tx3:#6f6a5e;
  --bgArt:none; --bgArtOpacity:0;
  --serif:"Noto Serif SC","STZhongsong","SimSun",serif;
  --sans:"Noto Sans SC","Microsoft YaHei",sans-serif;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;background:var(--bg)}
/* 背景色移到 html、body 留空，是为了让下面的 body::after 插画层能被看见。
   原因在绘制次序：负 z-index 的后代画在「根元素背景之后、普通流的块背景之前」。
   body 自己若有背景，它就属于「普通流的块背景」，永远盖在 z-index:-1 的插画上；
   把底色交给 html（画到画布上），插画才浮得出来，正文又都在它上面。 */
body{background:transparent;color:var(--tx);font-family:var(--sans);font-size:1rem;line-height:1.7;overflow-x:hidden}
body::before{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(1200px 500px at 80% -10%,rgba(var(--accentRGB),.07),transparent 60%),
             radial-gradient(900px 500px at -10% 30%,rgba(var(--jadeRGB),.05),transparent 60%),
             radial-gradient(700px 400px at 60% 110%,rgba(var(--redRGB),.05),transparent 60%)}
/* ---------- 主题背景插画（各套皮肤各一张，见 server/tools/build-bg-art.js）----------
   z-index:-1 + 底色上移到 html：见上面 body 那一行的说明。
   透明度走 --bgArtOpacity，逐主题给值——浅色主题经不起太重的线条，
   深色主题线太淡则等于没画，所以这个数不能全局一套。
   opacity 而不是把颜色调淡：整层等比缩淡，山形与水纹的相对深浅关系才不会被压平。 */
body::after{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--bgArt);background-position:center;background-size:cover;
  background-repeat:no-repeat;opacity:var(--bgArtOpacity);
  transition:opacity .35s ease}
::selection{background:rgba(var(--accentRGB),.35)}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:var(--scroll);border-radius:6px}
::-webkit-scrollbar-track{background:transparent}

header{position:sticky;top:0;z-index:100;backdrop-filter:blur(14px);
  background:var(--hdBg);border-bottom:1px solid var(--line2)}
.hd{max-width:1320px;margin:0 auto;display:flex;align-items:center;gap:20px;padding:0 24px;height:66px}
/* 页头三处字号（品牌 / 导航 / 工具区）按用户要求统一放大约两号。
   ★ 只改 font-size，颜色（--logoGrad / --tx2 / --tx3）与版式一律不动。
   各断点的更小档位在 responsive.css 里，那边是本文件的后续覆盖；
   改动时两边要一起动，否则窄屏会突然比宽屏还大。 */
.logo{display:flex;align-items:baseline;gap:12px;cursor:pointer;user-select:none}
.logo .mark{font-family:var(--serif);font-size:2rem;font-weight:900;letter-spacing:6px;
  background:var(--logoGrad);-webkit-background-clip:text;background-clip:text;color:transparent}
.logo .slog{font-size:0.84rem;color:var(--tx3);letter-spacing:2px}
nav{display:flex;gap:2px;margin-left:auto;flex-wrap:wrap}
nav a{color:var(--tx2);text-decoration:none;font-size:1.0333rem;padding:7px 12px;border-radius:8px;letter-spacing:1px;transition:.25s;cursor:pointer;white-space:nowrap}
nav a:hover{color:var(--accent2);background:rgba(var(--accentRGB),.08)}
nav a.on{color:var(--accent2);background:rgba(var(--accentRGB),.12)}

main{position:relative;z-index:1;max-width:1320px;margin:0 auto;padding:34px 24px 80px}
section.page{display:none;animation:fadeUp .5s ease}
section.page.on{display:block}
@keyframes fadeUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.sec-head{margin:6px 0 26px}
.sec-head .cn{font-family:var(--serif);font-size:2rem;font-weight:700;letter-spacing:3px}
.sec-head .cn::before{content:"◆";color:var(--accent);font-size:0.9333rem;margin-right:12px;vertical-align:3px}
.sec-head .en{color:var(--tx3);font-size:0.8rem;letter-spacing:3px;margin-top:2px;text-transform:uppercase}
.card{background:linear-gradient(180deg,var(--panel),var(--bg2));border:1px solid var(--line2);border-radius:16px;padding:22px;transition:.3s}
.card:hover{border-color:var(--line)}
/* 默认单列。⚠️ 必须写 `minmax(0,1fr)` 而不是留空：
   留空时隐式列的轨道尺寸是 `auto`，其**最小**尺寸 = 内容的 min-content，
   于是子项里只要有一段不肯折行的长内容（长 URL、`white-space:nowrap` 的串），
   轨道就被撑到比容器还宽 —— 在 320px 上实测「学习中心」整块右溢 12px。
   `minmax(0,1fr)` 把最小值钉死为 0，子项才会老实按容器宽度折行。
   各变体（.home-grid/.topic-grid/.fig-grid/.film-grid/.tb-grid/.gv-grid）
   与行内 `style="grid-template-columns:…"` 都在这条之后或特异度更高，不受影响。 */
.grid{display:grid;gap:18px;grid-template-columns:minmax(0,1fr)}
/* 素养课堂左列有三张 .card，间距靠行内 margin-bottom 撑着 —— 最后一张改成 0 时，
   上面几张的间距会连同邻接关系一起丢，实测有一处 0px。这里补一条「相邻卡片至少 18px」：
   margin 会折叠，已有 18px 的地方结果不变（max(18,18)），缺的地方补上。 */
#study .grid > div > .card + .card{margin-top:18px}
.tag{display:inline-block;font-size:0.7333rem;padding:2px 10px;border-radius:99px;border:1px solid var(--line);color:var(--accent);letter-spacing:1px}
.tag.red{color:var(--redTx);border-color:rgba(var(--redRGB),.4)}
.tag.jade{color:var(--jadeTx);border-color:rgba(var(--jadeRGB),.4)}
.tag.blue{color:var(--blueTx);border-color:rgba(var(--blueRGB),.4)}
/* ---- 用户菜单（页头下拉 + 退出登录）----
   未登录时它就是一个普通的「未登录」按钮（点了去个人中心），
   登录后才变成「头像首字 + 用户名 + ▾」并展开下拉。 */
.user-menu{position:relative;flex:0 0 auto;min-width:0}
/* ⚠️ `.um-trigger` / `.um-name` / `.um-uname` 上的 `min-width:0` 不是可有可无的。
   它们默认是 min-width:auto = 「内容的 min-content」，而这两段文字是
   white-space:nowrap 的：`#um-uname` 装 "demo_student" 时 min-content = 113px。
   于是胶囊被顶到 max-width 上限后就**再也缩不动**，flex 只能把页头整体撑宽 ——
   实测 ≤480 档登录态胶囊恒为 132px、页头内容右缘 419px，390 档每页横溢 28px。
   钉上 min-width:0 后，超长用户名会照常走下面的 text-overflow:ellipsis 截断。
   真正决定「只缩谁」的是 responsive.css ≤1023 段里那条页头弹性规则。 */
.um-trigger{display:flex;align-items:center;gap:8px;padding:5px 11px 5px 6px;border-radius:99px;cursor:pointer;
  background:rgba(var(--hlRGB),.04);border:1px solid var(--line2);color:var(--tx);font-family:var(--sans);
  font-size:0.9rem;letter-spacing:1px;transition:.18s;max-width:190px;min-width:0}
.um-trigger:hover{border-color:rgba(var(--accentRGB),.42);background:rgba(var(--accentRGB),.07)}
.um-trigger[aria-expanded="true"]{border-color:rgba(var(--accentRGB),.5);background:rgba(var(--accentRGB),.1)}
.um-avt{flex:0 0 auto;width:24px;height:24px;border-radius:50%;display:grid;place-items:center;
  font-size:0.9rem;font-weight:700;color:var(--onAccent);background:var(--btnGrad)}
.um-name,.um-uname{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.um-uname{font-weight:600;color:var(--accent2)}
.um-caret{flex:0 0 auto;font-size:0.6rem;color:var(--tx3);transition:transform .2s}
.um-trigger[aria-expanded="true"] .um-caret{transform:rotate(180deg)}
.um-panel{position:absolute;right:0;top:calc(100% + 8px);z-index:340;min-width:198px;padding:6px;
  border-radius:12px;border:1px solid var(--line);background:var(--panel);
  box-shadow:0 18px 44px rgba(var(--shRGB),.42);animation:umIn .16s ease both}
@keyframes umIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.um-hd{display:flex;flex-direction:column;gap:2px;padding:9px 11px 11px;
  border-bottom:1px solid var(--line2);margin-bottom:5px}
.um-hd b{font-family:var(--serif);font-size:1rem;color:var(--accent2);letter-spacing:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.um-hd span{font-size:0.7rem;color:var(--tx3);letter-spacing:1px}
.um-item{display:block;width:100%;text-align:left;padding:9px 11px;border:0;border-radius:8px;cursor:pointer;
  background:transparent;color:var(--tx);font-size:0.8333rem;letter-spacing:1px;font-family:inherit;transition:.15s}
.um-item:hover{background:rgba(var(--accentRGB),.1);color:var(--accent2)}
.um-sep{height:1px;background:var(--line2);margin:5px 8px}
.um-item.um-danger{color:var(--red)}
.um-item.um-danger:hover{background:rgba(var(--redRGB),.12);color:var(--red)}
/* 未登录：收起头像与箭头，让它退回成一个普通按钮 */
.user-menu:not(.on) .um-avt,.user-menu:not(.on) .um-caret{display:none}
.user-menu:not(.on) .um-trigger{padding:5px 12px}
/* 长者关怀的定位是降低视觉噪声，下拉不做位移动画 */
html[data-theme="senior"] .um-panel{animation:none}
.btn{display:inline-flex;align-items:center;gap:8px;background:var(--btnGrad);color:var(--onAccent);
  border:none;border-radius:10px;padding:10px 22px;font-size:0.9333rem;font-weight:600;cursor:pointer;letter-spacing:2px;transition:.25s;font-family:var(--sans)}
.btn:hover{filter:brightness(1.1);transform:translateY(-1px)}
.btn.ghost{background:transparent;color:var(--accent);border:1px solid var(--line)}
.btn.ghost:hover{background:rgba(var(--accentRGB),.08)}
.btn.sm{padding:6px 14px;font-size:0.8333rem;border-radius:8px}
/* 禁用态必须看得出来：时段聚焦里的「对准该时段 / 取消聚焦」在未选中时段时不可用，
   不表态会让用户连点几下以为坏了。 */
.btn:disabled{opacity:.45;cursor:not-allowed}
.inp{background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);border-radius:10px;color:var(--tx);
  padding:10px 14px;font-size:0.9333rem;font-family:var(--sans);outline:none;transition:.2s}
.inp:focus{border-color:var(--line)}
/* `max-width:100%` + `min-width:0`：<select> 的固有宽度取**最宽的那个 option**，
   它不认父容器有多窄。学习中心「辩论赛」的辩题下拉在 300px 下算出 293px，
   直接顶出视口（选项文本是整句辩题）。给一个上限，超长的 option 由原生控件自己截断。 */
.sel{background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);border-radius:10px;color:var(--tx);
  padding:8px 12px;font-size:0.8667rem;font-family:var(--sans);outline:none;cursor:pointer;
  max-width:100%;min-width:0}
.chip{padding:5px 14px;border-radius:99px;border:1px solid var(--line2);color:var(--tx2);font-size:0.8333rem;cursor:pointer;transition:.2s;user-select:none;display:inline-block}
.chip:hover{border-color:var(--line);color:var(--tx)}
.chip.on{background:rgba(var(--accentRGB),.14);border-color:var(--line);color:var(--accent2)}
.ai-badge{display:inline-flex;align-items:center;gap:5px;font-size:0.7rem;color:var(--jadeTx);border:1px solid rgba(var(--jadeRGB),.4);border-radius:99px;padding:1px 9px;letter-spacing:1px}

.hero{position:relative;border-radius:22px;overflow:hidden;border:1px solid var(--line);padding:74px 56px;margin-bottom:30px;
  background:linear-gradient(120deg,rgba(var(--accentRGB),.10),rgba(var(--bgRGB),.4) 55%),linear-gradient(200deg,rgba(var(--jadeRGB),.10),transparent 50%),var(--panel)}
.hero::after{content:"山 河 为 卷 · 时 间 为 轴";position:absolute;right:34px;bottom:26px;writing-mode:vertical-rl;
  font-family:var(--serif);font-size:0.8667rem;letter-spacing:10px;color:rgba(var(--accentRGB),.35);
  transition:opacity .45s ease}
/* 右侧配图出现后，这行竖排装饰文案正好压在照片上：低透明度文字叠在复杂照片上，
   看着像屏幕脏点 / 重影，而不是设计。配图在场时让它让位（淡出而非 display:none，
   免得切图时闪一下）。标记由 hero-art.js 打，不用 CSS :has()——
   「图加载失败要退回去」这件事只有 JS 知道（见 hero-art.js 的 syncMark）。 */
.hero.has-art::after{opacity:0}
.hero h1{font-family:var(--serif);font-size:3.7333rem;font-weight:900;letter-spacing:10px;
  background:var(--numGrad);-webkit-background-clip:text;background-clip:text;color:transparent}
.hero .sub{margin-top:14px;font-size:1.1333rem;color:var(--tx2);letter-spacing:3px;font-family:var(--serif)}
.hero .desc{margin-top:22px;max-width:640px;color:var(--tx2);font-size:0.9667rem}
/* 六个主题入口排成两行三列（上排 历史/地理/生物，下排 数学/物理/化学）。
   用「grid 竖排两个 .acts-row + 行内 flex-wrap」而不是直接 flex-wrap：
   直接排的话窄屏会把六个混在一起折行，看不出「上排三科、下排三科」的分组。 */
.hero .acts{margin-top:30px;display:grid;gap:12px;justify-items:start}
.hero .acts-row{display:flex;gap:12px;flex-wrap:wrap}
/* 六个主题入口都带一句悬停介绍（鼠标移上 / 键盘聚焦 / 触屏点一下浮出）。
   ★ 选择器是 .btn[data-soon]（属性选择器），不再是早期的 .soon 类：
     物理与化学两栏 2026-09 上线后，六个入口全部可点击，
     介绍气泡就从「未开放科目的敬请期待」变成了「六个入口各自的介绍」，
     于是统一的判据变成「有没有 data-soon 属性」，.soon 这个类已彻底移除。
   ★ 提示文案走 attr(data-soon)，不能写成按钮里的 <span>：
     i18n 切语言时是整块 textContent 覆盖，塞在里面的子元素会被一起抹掉。
   ★ app.js 的 initSoonTips() 用同一个选择器加/去 .tip-on（触屏兜底），改这里必须同步改那里，
     否则会出现「鼠标移上去有气泡、手指点却没有」这种不报错的静默缺陷。 */
.hero .acts .btn[data-soon]{position:relative;cursor:help}
.hero .acts .btn[data-soon]:hover,.hero .acts .btn[data-soon]:focus-visible{background:rgba(var(--accentRGB),.08)}
.hero .acts .btn[data-soon]::after{content:attr(data-soon);position:absolute;left:50%;bottom:calc(100% + 10px);
  --tx:-50%;--ty:4px;transform:translate(var(--tx),var(--ty));
  /* ★ width:max-content 不能省。
     绝对定位元素在「只给 left、不给 right」时宽度走 shrink-to-fit，而可用宽度
     被算成「包含块宽度 - left」—— 这里 left 是 50%，于是可用宽度只剩按钮的一半，
     再大的 max-width 也救不回来：气泡被挤成一条竖排窄字（实测「格物天地：初中到
     高中物理…」被折成 5 行、每行 3 个字），最后连 hero 的 overflow:hidden 都会切掉半句。
     max-content 让它先按一整句的自然宽度铺开，再由 max-width 封顶，这才轮到 white-space:normal 折行。
     ⚠️ 这条 bug 在 jsdom 里查不出来（没有布局），「有 max-width」和「真能画出来」是两回事。 */
  width:max-content;
  max-width:min(78vw,320px);padding:7px 12px;border-radius:9px;background:var(--panel);color:var(--tx);
  border:1px solid var(--line2);box-shadow:0 10px 24px rgba(0,0,0,.16);
  font-size:0.7667rem;font-weight:400;letter-spacing:0.5px;line-height:1.5;text-align:left;
  white-space:normal;opacity:0;pointer-events:none;z-index:6;transition:opacity .18s ease,transform .18s ease}
/* 下排按钮头上就是上排按钮，气泡改到下方；隐藏态的偏移量也随之翻向 */
.hero .acts-row + .acts-row .btn[data-soon]::after{bottom:auto;top:calc(100% + 10px);--ty:-4px}
/* 行首按钮靠左对齐，气泡居中会伸到 hero 外被 overflow:hidden 裁掉半句 */
.hero .acts-row .btn[data-soon]:first-child::after{left:0;--tx:0}
.hero .acts .btn[data-soon]:hover::after,.hero .acts .btn[data-soon]:focus-visible::after,.hero .acts .btn[data-soon].tip-on::after{
  opacity:1;--ty:0}
/* 文案统一抬到配图之上（配图在 DOM 里排在文案之后，宽屏是绝对定位的右侧出血图） */
.hero h1,.hero .sub,.hero .desc,.hero .acts{position:relative;z-index:2}
/* ---------- 首页右侧配图（建党以来重大事件 / 河南·内蒙古名胜） ----------
   由右向左透明渐变：右端清晰、左端淡出，与左侧文案自然衔接。
   渐变用 mask-image 而不是「叠一层背景色渐变」——叠色会跟着主题底色走，
   换皮肤时底色一变就会露出一条色带；mask 不吃主题变量，11 套皮肤一视同仁。 */
.hero-art{position:absolute;top:0;right:0;bottom:0;width:52%;margin:0;overflow:hidden;
  display:flex;align-items:flex-start;justify-content:flex-end;pointer-events:none;
  opacity:0;transition:opacity .55s ease;
  -webkit-mask-image:linear-gradient(to left,#000 0%,#000 32%,rgba(0,0,0,.5) 62%,rgba(0,0,0,0) 100%);
  mask-image:linear-gradient(to left,#000 0%,#000 32%,rgba(0,0,0,.5) 62%,rgba(0,0,0,0) 100%)}
.hero-art.on{opacity:1}
.hero-art-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.hero-art-cap{position:relative;z-index:2;margin:24px 24px 0 0;max-width:66%;text-align:right;
  display:flex;flex-direction:column;gap:2px;align-items:flex-end}
.hero-art-cap b{font-family:var(--serif);font-size:1rem;letter-spacing:2px;color:var(--accent)}
.hero-art-cap span{font-family:var(--serif);font-size:1.3333rem;font-weight:700;letter-spacing:3px;color:var(--tx)}
.hero-art-cap i{font-style:normal;font-size:0.7667rem;line-height:1.65;color:var(--tx2);text-align:right;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* 角标压在照片上，必须自带可读性：用主题底色做描边光晕，深色浅色照片都读得清 */
.hero-art-cap b,.hero-art-cap span,.hero-art-cap i{text-shadow:0 1px 12px var(--bg),0 0 3px var(--bg),0 0 3px var(--bg)}
.home-grid{grid-template-columns:1.35fr 1fr}
.stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin:26px 0}
.stat{background:linear-gradient(180deg,var(--panel),var(--bg2));border:1px solid var(--line2);border-radius:16px;padding:20px 8px;text-align:center}
.stat .num{font-family:var(--serif);font-size:2.1333rem;font-weight:900;color:var(--accent)}
.stat .lab{font-size:0.8333rem;color:var(--tx2);margin-top:4px;letter-spacing:2px}
.today-item{display:flex;gap:14px;padding:13px 4px;border-bottom:1px dashed var(--line2);cursor:pointer;transition:.2s}
.today-item:last-child{border-bottom:none}
.today-item:hover{transform:translateX(4px)}
.today-item:hover .t-title{color:var(--accent2)}
.today-item .yr{min-width:74px;font-family:var(--serif);font-weight:700;color:var(--accent);font-size:1rem}
.today-item .t-title{font-size:0.9667rem;transition:.2s}
.today-item .t-sub{font-size:0.8rem;color:var(--tx3);margin-top:1px}
.topic-grid{grid-template-columns:repeat(4,1fr)}
.topic{position:relative;border-radius:16px;padding:24px 20px;min-height:150px;overflow:hidden;cursor:pointer;border:1px solid var(--line2);transition:.3s;display:flex;flex-direction:column;justify-content:flex-end}
.topic:hover{transform:translateY(-4px);border-color:var(--line)}
.topic .bg-ico{position:absolute;right:-6px;top:-16px;font-size:5.2rem;opacity:.13;font-family:var(--serif)}
/* 专题卡片压着的是写死的深色美术渐变（见 app.js 的 TOPICS[].g），不是主题色，
   所以卡上文字一律固定浅色。跟着 --tx 走的话，浅色主题下会变成深字压深底（1:1）。 */
.topic h3{font-family:var(--serif);font-size:1.2667rem;letter-spacing:2px;color:#F5EFE3}
.topic p{font-size:0.8rem;color:rgba(245,239,227,.8);margin-top:5px}
.topic .bg-ico{color:#F5EFE3}

.tl-controls{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.zoomer{margin-left:auto;display:flex;gap:6px}
.zoomer button{width:32px;height:32px;border-radius:8px;background:var(--panel2);border:1px solid var(--line2);color:var(--tx);cursor:pointer;font-size:1.0667rem;transition:.2s}
.zoomer button:hover{border-color:var(--line);color:var(--accent)}
.tl-wrap{border:1px solid var(--line2);border-radius:16px;background:var(--bg2);overflow:hidden}
.tl-scroll{overflow-x:auto;overflow-y:hidden;cursor:grab;padding:26px 0 8px;position:relative}
.tl-scroll.dragging{cursor:grabbing}
.tl-inner{position:relative;height:330px}
.tl-axis{position:absolute;left:0;right:0;top:158px;height:2px;background:linear-gradient(90deg,transparent,var(--accent) 4%,var(--accent) 96%,transparent);opacity:.6}
.tl-track-label{position:absolute;left:10px;font-size:0.7333rem;letter-spacing:3px;color:var(--tx3);top:36px}
.tl-track-label.w{top:234px}
.era{position:absolute;height:30px;border-radius:7px;display:flex;align-items:center;justify-content:center;
  font-family:var(--serif);font-size:0.8333rem;letter-spacing:2px;cursor:pointer;transition:.2s;white-space:nowrap;overflow:hidden}
.era:hover{filter:brightness(1.25)}
.era.cn{top:58px;background:rgba(var(--redRGB),.22);border:1px solid rgba(var(--redRGB),.45);color:var(--redTx)}
.era.cn.hot{background:rgba(var(--redRGB),.4)}
.era.wd{top:230px;background:rgba(var(--blueRGB),.18);border:1px solid rgba(var(--blueRGB),.4);color:var(--blueTx)}
.era.wd.hot{background:rgba(var(--blueRGB),.35)}

/* 阶段特征带（需求 3.4.6）——AI 归纳的 2-4 字阶段标签，位于各自时间轴上方 */
.phase{position:absolute;height:22px;border-radius:6px;display:flex;align-items:center;justify-content:center;
  font-family:var(--serif);font-size:0.7667rem;letter-spacing:1px;cursor:pointer;transition:.2s;
  white-space:nowrap;overflow:hidden;z-index:2}
.phase.cn{top:4px;background:rgba(var(--accentRGB),.12);border:1px dashed rgba(var(--accentRGB),.38);color:var(--accent2)}
.phase.cn:hover{background:rgba(var(--accentRGB),.24);border-style:solid}
.phase.wd{top:202px;background:rgba(var(--blueRGB),.10);border:1px dashed rgba(var(--blueRGB),.34);color:var(--blueTx)}
.phase.wd:hover{background:rgba(var(--blueRGB),.2);border-style:solid}
.evt{position:absolute;width:12px;height:12px;border-radius:50%;cursor:pointer;transform:translate(-50%,-50%);border:2px solid var(--bg2);transition:.2s;z-index:3}
.evt:hover{transform:translate(-50%,-50%) scale(1.6);z-index:5}
.evt.cn,.evt.wd,.evt.world{top:158px}
.evt .lab{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);white-space:nowrap;font-size:0.7667rem;color:var(--tx2);
  background:var(--tipBg);padding:2px 9px;border-radius:6px;border:1px solid var(--line2);opacity:0;transition:.2s;pointer-events:none;z-index:6}
.evt:hover .lab{opacity:1}
.tl-yearbar{padding:0 16px 12px;display:flex;justify-content:space-between;font-size:0.7333rem;color:var(--tx3);letter-spacing:1px}
.tl-hint{text-align:center;font-size:0.7667rem;color:var(--tx3);padding-bottom:12px;letter-spacing:1px}

/* ---------- 时间轴悬停卡片（朝代/时代与阶段特征共用） ----------
   挂 body、fixed 定位：时间轴内部是横向滚动容器（overflow:auto），
   卡片若放进容器里，滑到边缘会被直接裁掉。 */
.tl-tip{position:fixed;z-index:320;width:max-content;max-width:308px;pointer-events:none;
  opacity:0;transform:translateY(5px);transition:opacity .16s ease,transform .16s ease;
  background:var(--modalBg);border:1px solid var(--line2);border-radius:12px;padding:12px 15px 13px;
  box-shadow:0 18px 44px rgba(var(--shRGB),.45)}
.tl-tip.on{opacity:1;transform:translateY(0)}
/* 名称在上、简介在下（用户明确要求的次序） */
.tl-tip .tp-n{font-family:var(--serif);font-size:1.1333rem;letter-spacing:2px;color:var(--tx);line-height:1.4}
.tl-tip .tp-y{font-size:0.7333rem;letter-spacing:1px;color:var(--accent2);margin-top:4px}
.tl-tip .tp-d{font-size:0.8333rem;line-height:1.75;color:var(--tx2);margin-top:8px}

/* ---------- 时段聚焦（时间轴点击联动） ---------- */
.tl-focus .tf-hd{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap}
.tl-focus .tf-hd-txt{min-width:0;flex:1 1 320px}
.tl-focus .tf-t{font-family:var(--serif);font-size:1.0667rem;letter-spacing:2px;color:var(--accent);line-height:1.5}
.tl-focus .tf-k{margin-right:10px}
.tl-focus .tf-t b{color:var(--tx);font-weight:700}
.tl-focus .tf-s{font-size:0.8rem;line-height:1.8;color:var(--tx3);margin-top:5px}
.tl-focus .tf-acts{display:flex;gap:8px;flex-wrap:wrap;flex:0 0 auto}
.tl-focus .tf-tags{display:flex;gap:6px;flex-wrap:wrap;margin-top:13px}
.tl-focus .tf-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:8px;margin-top:12px}
.tl-focus .tf-ev{display:flex;gap:10px;align-items:flex-start;min-width:0;padding:9px 12px;cursor:pointer;transition:.2s;
  border:1px solid var(--line2);border-radius:10px;background:rgba(var(--hlRGB),.025)}
.tl-focus .tf-ev:hover{border-color:var(--line);background:rgba(var(--accentRGB),.07)}
.tl-focus .tf-ev .sq{flex:0 0 auto;min-width:46px;padding-top:2px;font-size:0.7333rem;letter-spacing:.5px;color:var(--accent2)}
.tl-focus .tf-ev .tt{font-size:0.9rem;line-height:1.45;color:var(--tx)}
.tl-focus .tf-ev .nn{margin-top:3px;font-size:0.7667rem;line-height:1.55;color:var(--tx3);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tl-focus .tf-empty,.tl-focus .tf-foot{font-size:0.7667rem;line-height:1.8;color:var(--tx3);margin-top:12px}

.modal-mask{position:fixed;inset:0;background:var(--mask);backdrop-filter:blur(6px);z-index:200;display:none;align-items:center;justify-content:center;padding:24px}
.modal-mask.on{display:flex}
.modal{width:min(880px,100%);max-height:88vh;overflow-y:auto;background:var(--modalBg);
  border:1px solid var(--line);border-radius:20px;padding:34px 38px;position:relative;animation:pop .35s ease}
@keyframes pop{from{opacity:0;transform:scale(.94) translateY(10px)}to{opacity:1;transform:none}}
.modal .x{position:absolute;top:16px;right:20px;width:34px;height:34px;border-radius:10px;border:1px solid var(--line2);
  background:transparent;color:var(--tx2);font-size:1.0667rem;cursor:pointer;transition:.2s}
.modal .x:hover{color:var(--accent);border-color:var(--line)}
.modal h2{font-family:var(--serif);font-size:1.7333rem;letter-spacing:2px;color:var(--accent2)}
.modal .meta{display:flex;gap:10px;margin:10px 0 18px;flex-wrap:wrap;align-items:center}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:10px;overflow:hidden;margin:6px 0 16px}
.seg button{background:transparent;border:none;color:var(--tx2);padding:7px 20px;cursor:pointer;font-size:0.8667rem;letter-spacing:2px;font-family:var(--sans)}
.seg button.on{background:rgba(var(--accentRGB),.16);color:var(--accent2)}
.six-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:6px}
.six-cell{background:rgba(var(--hlRGB),.025);border:1px solid var(--line2);border-radius:12px;padding:13px 15px}
.six-cell .k{font-size:0.7333rem;color:var(--accent);letter-spacing:3px;margin-bottom:5px}
.six-cell .v{font-size:0.8667rem;color:var(--tx2)}
.chain{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:10px}
.chain .node{padding:7px 14px;border-radius:10px;background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);font-size:0.8667rem;cursor:pointer;transition:.2s}
.chain .node:hover{border-color:var(--line);transform:translateY(-2px)}
.chain .node.hot{border-color:var(--line);color:var(--accent2);background:rgba(var(--accentRGB),.08)}
.chain .arr{color:var(--accent);font-size:1rem}
.chain .arr small{display:block;font-size:0.6rem;color:var(--tx3);text-align:center;letter-spacing:1px}
.detail-p{color:var(--tx2);font-size:0.9333rem;margin:8px 0}

.geo-grid{display:grid;grid-template-columns:1fr 360px;gap:18px;align-items:start}
#map{width:100%;height:640px;border-radius:16px;border:1px solid var(--line2)}
#map-fallback{width:100%;height:640px;border-radius:16px;border:1px solid var(--line2);background:var(--bg2);display:none;align-items:center;justify-content:center}
/* 左列 = 地图 + 地图正下方的两条（对比模式 / 图例）。
   这两张卡原在右栏末尾，把右栏撑到 1134px，而地图只有 640px —— 地图下方整片空着，
   右栏底部又拖出一段无用留白。移下来后并排铺满地图宽度，与上面左右对齐。
   .geo-main 用 flex 纵向排，min-width:0 防止内层宽内容把 grid 列顶开。 */
.geo-main{display:flex;flex-direction:column;min-width:0}
.geo-under{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px;margin-top:14px;align-items:start}
.map-side .card{margin-bottom:14px}
.map-side > .card:last-child{margin-bottom:0}
.area-num{font-family:var(--serif);font-size:2rem;font-weight:900;color:var(--accent)}
.dyn-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.dyn-chips .chip.on{background:rgba(var(--redRGB),.2);border-color:rgba(var(--redRGB),.5);color:var(--redTx)}
.legend{display:flex;flex-direction:column;gap:8px;font-size:0.8333rem;color:var(--tx2)}
.legend i{display:inline-block;width:14px;height:14px;border-radius:4px;margin-right:8px;vertical-align:-2px}
.map-note{font-size:0.7667rem;color:var(--tx3);margin-top:10px;line-height:1.6}

.fig-grid{grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}
.fig-card{display:flex;flex-direction:column;align-items:center;text-align:center;cursor:pointer;gap:6px}
.avatar{width:76px;height:76px;border-radius:50%;display:flex;align-items:center;justify-content:center;overflow:hidden;
  font-family:var(--serif);font-size:1.8667rem;font-weight:900;color:var(--onAccent);
  background:var(--btnGrad);box-shadow:0 6px 22px rgba(var(--accentRGB),.25)}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
.fig-card h3{font-family:var(--serif);font-size:1.2667rem;letter-spacing:2px;margin-top:6px}
.fig-card .yrs{font-size:0.8rem;color:var(--tx3)}
.fig-card .role{font-size:0.8333rem;color:var(--tx2)}
/* ================= 历史人物 · 页级检索条（深度档案 / 课本人物全集共用） =================
   深度档案原先是「只能一张张翻」；课本人物全集的搜索框又只在另一个页签里，
   切回去关键词就丢了。所以做一条常驻在页签下方的检索条：进页面即可搜，
   切页签筛选不丢，上下两个输入框互相同步（联动逻辑见 app.js 的 FigSetKw）。
   注意别把它塞进 #fig-deep —— 那个容器在「课本人物全集」页签下是 display:none，
   检索条会跟着消失，「页级搜索框」就成了半个。 */
.fig-search{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:-6px 0 20px;
  padding:10px 14px;border:1px solid var(--line);border-radius:12px;background:rgba(var(--hlRGB),.03)}
.fig-search-ico{font-size:1rem;line-height:1;color:var(--accent2)}
.fig-search .inp{flex:1 1 260px;min-width:180px;margin-bottom:0}
.fig-search-n{font-size:0.8rem;color:var(--tx3);letter-spacing:1px;white-space:nowrap}
.fig-search-n b{color:var(--accent2);font-size:0.9333rem}
.fig-empty{grid-column:1/-1;text-align:center;color:var(--tx3);font-size:0.8667rem;line-height:1.9}
.life-node{display:flex;gap:14px;position:relative;padding-bottom:18px}
.life-node::before{content:"";position:absolute;left:5px;top:14px;bottom:0;width:1px;background:var(--line2)}
.life-node:last-child::before{display:none}
.life-node .dot{width:11px;height:11px;border-radius:50%;background:var(--accent);flex-shrink:0;margin-top:5px}
.life-node .yr{font-family:var(--serif);color:var(--accent);font-weight:700;font-size:0.9333rem}
.life-node .tt{font-size:0.9rem;color:var(--tx2)}
.rel-pill{display:inline-flex;align-items:center;gap:6px;padding:5px 13px;border-radius:99px;background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);font-size:0.8333rem;margin:3px}
.rel-pill b{color:var(--accent);font-weight:500;font-size:0.7333rem}

.film-grid{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
.film{overflow:hidden;padding:0;cursor:pointer}
.film .poster{height:190px;position:relative;display:flex;align-items:flex-end;padding:16px}
/* 真实封面（构建期抓取落地到 public/img/covers/，见 server/tools/build-film-covers.js）
   盖在原来的渐变色块上；图片没加载出来（或该片抓不到封面）时什么也不做，
   渐变色块照常显示 —— 绝不出现破图。z-index 显式分层：
   0 封面图 → 1 底部压暗渐变 → 2 压在封面上的文字。 */
.film .poster-img{position:absolute;inset:0;z-index:0;display:block;
  width:100%;height:100%;object-fit:cover;object-position:center}
.film .poster::after{z-index:1;content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 30%,var(--posterFade))}
/* 压在海报上的文字一律不能用主题色变量。
   海报底 = 写死的深色美术渐变（G 色板）+ --posterFade（12 套主题下都是深色半透明），
   而浅色主题的 --tx / --accent 本身是深色 —— 直接继承就是深字压深底。
   实测（浅色主题）：.tt 只有 1.1:1、.era-tag 只有 1.9:1，都看不见。
   故统一定为暖白 + 阴影，与主题解耦；底色深/浅都不影响。 */
.film .poster .tt{position:relative;z-index:2;font-family:var(--serif);font-size:1.4rem;letter-spacing:2px;font-weight:700;
  color:#F5F0E6;text-shadow:0 2px 10px rgba(0,0,0,.6)}
.film .poster .era-tag{position:absolute;top:12px;left:12px;z-index:2;
  color:#F0E6D2;border-color:rgba(240,230,210,.5);background:rgba(12,10,8,.55);backdrop-filter:blur(4px)}
/* 历史性质标记（史实 / 演义 / 虚构）。三档颜色由 app.js 的 KIND 表给内联值——
   海报压的是写死的深色美术渐变，不能用主题变量，否则浅色主题下会深字压深底。
   这里只负责外形：默认作为行内小胶囊（弹窗、正文里用），在 .poster 里才绝对定位。 */
.k-tag{display:inline-block;font-size:0.6667rem;letter-spacing:1px;font-weight:700;padding:2px 8px;border-radius:999px;border:1px solid;line-height:1.6}
.film .poster .k-tag{position:absolute;top:12px;right:12px;z-index:2;backdrop-filter:blur(4px)}
.film .body{padding:16px 18px 18px}
.stars{color:var(--accent);letter-spacing:3px;font-size:0.9333rem}
.stars .off{color:var(--dim)}
.film .meta-line{font-size:0.8rem;color:var(--tx3);margin-top:6px;display:flex;gap:10px;flex-wrap:wrap}

/* ================= 影视播放页（.modal.player） =================
   复用弹窗机制，加宽到 1080px。播放器底色写死深色，标签/按钮文字用主题色变量
   （与海报/专题卡片同一套不变量：压在写死的深底上必须固定浅色、不跟 --tx 走）。 */
.modal.player{width:min(1080px,100%);padding:30px 34px}
.fp-head{margin:0 0 14px}
.fp-head h2{font-family:var(--serif);font-size:1.7333rem;letter-spacing:2px;color:var(--accent2);margin:0 0 8px}
.fp-player{position:relative;width:100%;padding-top:56.25%;border-radius:14px;overflow:hidden;
  background:#0b0d12;box-shadow:0 10px 30px rgba(0,0,0,.35)}
.fp-player iframe{position:absolute;inset:0;width:100%;height:100%;border:0;background:#0b0d12}
.fp-note{font-size:0.7333rem;color:var(--tx);margin-top:8px;line-height:1.5}
.fp-platforms{margin-top:14px;background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);border-radius:14px;padding:14px 16px}
.fp-plabel{font-size:0.8rem;letter-spacing:2px;color:var(--accent2);margin-bottom:10px}
.fp-btns{display:flex;gap:10px;flex-wrap:wrap}
/* 按钮文字用主题色变量（保证浅/深主题都 ≥4.5:1）；品牌色只作小圆点标识，hover 用主题强调色高亮。 */
.fp-btn{display:inline-flex;align-items:center;gap:8px;padding:9px 18px;border-radius:11px;
  background:rgba(var(--hlRGB),.05);border:1px solid var(--line2);color:var(--tx);
  font-size:0.9333rem;font-weight:600;text-decoration:none;transition:.2s}
.fp-btn:hover{border-color:var(--accent);background:rgba(var(--accentRGB),.1);transform:translateY(-2px)}
.fp-btn .fp-dot{width:10px;height:10px;border-radius:50%;background:var(--c);flex-shrink:0}
/* 「正在获取可播放的视频…」遮罩：压在写死的播放器深底（#0b0d12）上，
   所以文字也写死浅色，不跟主题变量走（与海报胶囊同一套不变量）。 */
.fp-load{position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;
  background:#0b0d12;color:#c9d1e0;font-size:0.8667rem;letter-spacing:1px}
/* 可切换的视频列表。播放页不变量：文字只用 --tx（正文）与 --accent2（标签/次级）。 */
.fp-vlist{margin-top:14px}
.fp-vrow{display:grid;grid-template-columns:repeat(auto-fill,minmax(196px,1fr));gap:10px}
.fp-vcard{display:flex;flex-direction:column;gap:6px;padding:8px;border-radius:12px;text-align:left;
  background:rgba(var(--hlRGB),.05);border:1px solid var(--line2);color:var(--tx);
  font:inherit;cursor:pointer;transition:.2s}
.fp-vcard:hover{border-color:var(--accent2)}
.fp-vcard.on{border-color:var(--accent2);border-width:2px;padding:7px;background:rgba(var(--accentRGB),.12)}
.fp-vthumb{position:relative;display:block;aspect-ratio:16/9;border-radius:8px;overflow:hidden;background:#0b0d12}
.fp-vthumb img{width:100%;height:100%;object-fit:cover;display:block}
/* 时长角标压在缩略图上（深色半透明底），固定浅字，不受主题影响。 */
.fp-vdur{position:absolute;right:5px;bottom:5px;padding:1px 6px;border-radius:5px;
  background:rgba(0,0,0,.72);color:#fff;font-size:0.6667rem}
.fp-vtt{font-size:0.8rem;line-height:1.35;color:var(--tx);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.fp-vmeta{font-size:0.6667rem;color:var(--accent2)}
/* ---- 登录页第三方一键登录（微信 / QQ / 支付宝） ----
   未配置的平台置灰，并把「未配置」直接写在按钮上（.oauth-tag）——
   不做「点了跳到报错页」这种假装可用的事。原因在下方 .oauth-hint 里说清去哪配。
   配色沿用既有不变量：正文 --tx、次要 --tx2、更弱 --tx3、强调 --accent，
   底色压卡片 .05 高亮叠加，浅色深色主题都达标。 */
.oauth-row{display:flex;gap:10px;flex-wrap:wrap;margin-top:2px}
.oauth-btn{flex:1 1 140px;display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:10px 14px;border-radius:12px;font:inherit;font-size:0.8667rem;cursor:pointer;transition:.2s;
  background:rgba(var(--hlRGB),.05);border:1px solid var(--line2);color:var(--tx)}
.oauth-btn:hover:not([disabled]){border-color:var(--accent);transform:translateY(-2px)}
.oauth-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.oauth-btn[disabled]{cursor:not-allowed;opacity:.55}
.oauth-ico{font-size:1.05rem;line-height:1}
.oauth-nm{white-space:nowrap}
.oauth-tag{font-size:0.6667rem;padding:1px 6px;border-radius:5px;color:var(--tx2);
  border:1px dashed var(--line2)}
.oauth-hint{font-size:0.8rem;color:var(--tx3);margin-top:10px;line-height:1.7}
.film .fdesc{font-size:0.8333rem;color:var(--tx2);margin-top:8px}
.path-flow{display:flex;gap:0;align-items:stretch;overflow-x:auto;padding:8px 2px 14px}
.path-node{min-width:150px;text-align:center;position:relative;padding:0 12px}
.path-node .box{background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);border-radius:12px;padding:12px 8px;font-size:0.8667rem}
.path-node .box b{font-family:var(--serif);color:var(--accent2);display:block;font-size:0.9333rem}
.path-node .box span{color:var(--tx3);font-size:0.7333rem}
.path-node::after{content:"➤";position:absolute;right:-9px;top:38%;color:var(--accent);font-size:0.8667rem;opacity:.7}
.path-node:last-child::after{display:none}
.rank-row{display:flex;align-items:center;gap:12px;padding:8px 4px;border-bottom:1px dashed var(--line2);font-size:0.9rem}
.rank-row:last-child{border-bottom:none}
.rank-row .rk{font-family:var(--serif);color:var(--accent);font-weight:900;width:26px}
.rank-row .stars{font-size:0.8rem}

.riddle-box{background:rgba(var(--jadeRGB),.06);border:1px solid rgba(var(--jadeRGB),.3);border-radius:16px;padding:26px;text-align:center}
.riddle-q{font-family:var(--serif);font-size:1.6rem;letter-spacing:4px;color:var(--jadeTx);margin:8px 0 18px}
.guess-btns{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.poem{border-left:3px solid var(--accent);padding:10px 16px;margin-bottom:14px;background:rgba(var(--hlRGB),.02);border-radius:0 12px 12px 0}
.poem .line{font-family:var(--serif);font-size:1.0667rem;color:var(--accent2)}
.poem .exp{font-size:0.8333rem;color:var(--tx2);margin-top:4px}
.mn-out{background:rgba(var(--accentRGB),.07);border:1px dashed var(--line);border-radius:14px;padding:22px;margin-top:16px;text-align:center;display:none}
.mn-out.show{display:block;animation:fadeUp .4s}
.mn-out .txt{font-family:var(--serif);font-size:1.4667rem;color:var(--accent2);letter-spacing:3px;margin:8px 0}
.qz{margin-bottom:20px}
.qz .qq{font-size:1rem;margin-bottom:10px}
.qz .opt{display:block;width:100%;text-align:left;background:rgba(var(--hlRGB),.02);border:1px solid var(--line2);border-radius:10px;
  padding:10px 16px;color:var(--tx2);cursor:pointer;margin-bottom:8px;font-size:0.9rem;transition:.2s;font-family:var(--sans)}
.qz .opt:hover{border-color:var(--line)}
.qz .opt.right{border-color:rgba(var(--jadeRGB),.6);color:var(--jadeTx);background:rgba(var(--jadeRGB),.08)}
.qz .opt.wrong{border-color:rgba(var(--redRGB),.6);color:var(--redTx);background:rgba(var(--redRGB),.08)}
/* 未提交前已选中的那个选项：只强调，不判对错 */
.qz .opt.picked{border-color:rgba(var(--accentRGB),.55);color:var(--accent2);background:rgba(var(--accentRGB),.09)}
/* ---- 题型徽章与提示（需求 3.7.3：单选 / 多选 / 判断 / 不定项）----
   徽章要能和「学科标签」区分开：学科是中性色，题型用强调色描边。
   提示行必须写清判分口径（全部选对才得分）——多选漏选也零分，
   不说明的话学生按单选习惯点一个就提交，然后全错却不知道原因。 */
.qz .tag-type{border-color:rgba(var(--accentRGB),.5);color:var(--accent2);letter-spacing:0}
.qz .qz-tip{font-size:0.7667rem;color:var(--tx3);margin:-4px 0 8px;line-height:1.6}
.qz .qz-tip b{color:var(--accent2);font-weight:600}
/* ---- 智能出题分页 ----
   题库 234 道，不分页会拉出一条几十屏的长页。这里只做「工具条 + 页码条」，
   颜色一律走主题变量（--panel / --line2 / --tx3 / --accent2 / --accentRGB），
   不做任何写死色值，避免浅色主题下出现看不见的按钮。 */
.qz-bar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;
  margin-top:14px;padding-top:12px;border-top:1px solid var(--line2);
  font-size:0.8rem;color:var(--tx3)}
/* ---------- 学科筛选条（学习中心「智能出题」） ----------
   与 .qz-bar 分开成两个容器：#qz-bar 里第一个 <select> 是「每页条数」，
   分页用例按位置取它；学科控件塞进去会打乱那个既定顺序。
   颜色全走主题变量，浅色主题下同样可见。 */
.qz-subj{display:flex;align-items:center;flex-wrap:wrap;gap:7px;margin-top:14px}
.qz-sub{padding:5px 12px;border-radius:99px;cursor:pointer;transition:.16s;
  font-size:0.8rem;font-family:var(--sans);font-variant-numeric:tabular-nums;
  background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);color:var(--tx2)}
.qz-sub:hover{border-color:rgba(var(--accentRGB),.45);color:var(--accent2)}
.qz-sub.on{background:rgba(var(--accentRGB),.15);border-color:rgba(var(--accentRGB),.55);
  color:var(--accent2);font-weight:600}
.qz-sub-tip{flex:1 1 100%;font-size:0.7333rem;color:var(--tx3);line-height:1.7;margin-top:2px}
/* 题型条：与学科条同一套 chip 样式，但上边加一条细分隔线 ——
   两行 chips 挨在一起时，要能看出「上一行管学科、这一行管题型」。 */
.qz-types{margin-top:8px;padding-top:10px;border-top:1px dashed var(--line2)}
.qz-bar-l,.qz-bar-r{display:flex;align-items:center;gap:8px}
.qz-sel{padding:5px 10px;font-size:0.8rem;border-radius:8px}
.qz-pager{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:6px;margin-top:20px}
.qz-pg{min-width:34px;height:34px;padding:0 10px;border-radius:9px;cursor:pointer;
  background:rgba(var(--hlRGB),.03);border:1px solid var(--line2);color:var(--tx2);
  font-size:0.8333rem;font-family:var(--sans);transition:.16s}
.qz-pg:hover:not(:disabled){border-color:rgba(var(--accentRGB),.45);color:var(--accent2)}
.qz-pg.on{background:rgba(var(--accentRGB),.15);border-color:rgba(var(--accentRGB),.55);color:var(--accent2);font-weight:600}
.qz-pg:disabled{cursor:default;opacity:.4}
.qz-pg-nav{min-width:auto}
.qz-pg-dots{color:var(--tx3);padding:0 2px;user-select:none}
.qz-pg-info{margin-left:6px;font-size:0.7667rem;color:var(--tx3)}
.mcard{height:200px;perspective:1000px;cursor:pointer}
.mcard .inner{position:relative;width:100%;height:100%;transition:transform .6s;transform-style:preserve-3d}
.mcard.flip .inner{transform:rotateY(180deg)}
.mface{position:absolute;inset:0;backface-visibility:hidden;border-radius:16px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center;border:1px solid var(--line)}
.mface.front{background:var(--cardF)}
.mface.front .f-t{font-family:var(--serif);font-size:1.5333rem;color:var(--accent2);letter-spacing:2px}
.mface.front .hint{font-size:0.7333rem;color:var(--tx3);margin-top:12px;letter-spacing:2px}
.mface.back{background:var(--cardB);transform:rotateY(180deg);font-size:0.8667rem;color:var(--tx2);justify-content:flex-start;align-items:flex-start;text-align:left;overflow-y:auto}
.mface.back b{color:var(--accent)}
.chat-log{height:320px;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:12px;background:var(--deep);border-radius:0 0 14px 14px;border:1px solid var(--line2);border-top:none}
.bubble{max-width:85%;padding:10px 15px;border-radius:14px;font-size:0.9rem;line-height:1.7}
.bubble.user{align-self:flex-end;background:rgba(var(--accentRGB),.16);border:1px solid var(--line);border-bottom-right-radius:4px}
.bubble.bot{align-self:flex-start;background:rgba(var(--hlRGB),.04);border:1px solid var(--line2);border-bottom-left-radius:4px;color:var(--tx2)}
.bubble.thinking{color:var(--tx3);font-size:0.8rem;animation:blink 1.2s infinite}
@keyframes blink{50%{opacity:.3}}
.char-tabs{display:flex;gap:8px;padding:12px 14px;flex-wrap:wrap;border:1px solid var(--line2);border-radius:14px 14px 0 0;background:rgba(var(--hlRGB),.02)}
.presets{display:flex;gap:8px;flex-wrap:wrap;padding:10px 14px;border:1px solid var(--line2);border-top:none;background:rgba(var(--hlRGB),.015)}
/* ---- 数字人（需求 3.7.1）----
   人物卡把「档案 + 人设三要素」摆在明处：学生看到「时代边界」那一行，
   才知道为什么问 1911 年孔子会说没听说过。 */
.char-card{padding:14px;border-left:1px solid var(--line2);border-right:1px solid var(--line2);background:rgba(var(--hlRGB),.03)}
.char-name{font-family:var(--serif);font-size:1.2rem;color:var(--tx);display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.char-era{font-family:var(--sans);font-size:0.7333rem;color:var(--accent2);border:1px solid rgba(var(--accentRGB),.35);border-radius:999px;padding:1px 8px}
.char-meta{font-size:0.8rem;color:var(--tx2);margin-top:3px;line-height:1.5}
.char-set{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line2);font-size:0.8rem;color:var(--tx2);line-height:1.65;display:flex;flex-direction:column;gap:4px}
.char-set b{color:var(--accent);font-weight:600;margin-right:6px}
.char-note{margin-top:8px;font-size:0.7333rem;color:var(--tx3)}
.chat-tools{display:flex;gap:8px;flex-wrap:wrap;align-items:center;padding:10px 14px;border:1px solid var(--line2);border-top:none;background:rgba(var(--hlRGB),.015)}
.chat-tools .inp{flex:1;min-width:200px}
/* 朗读按钮：挂在气泡内部右下，不抢正文的视觉重心 */
.bubble-tools{display:flex;gap:6px;margin-top:6px}
.bubble-btn{font:inherit;font-size:0.7333rem;color:var(--tx3);background:none;border:1px solid var(--line2);border-radius:999px;padding:1px 9px;cursor:pointer}
.bubble-btn:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.45)}
/* 系统提示气泡（如「时代边界」提醒）：不是人物说的话，用虚线与居中区分开 */
.bubble.note{align-self:center;max-width:92%;background:none;border:1px dashed var(--line2);color:var(--tx3);font-size:0.7333rem;border-radius:10px;padding:6px 12px;text-align:center}
.debate-msg{padding:10px 15px;border-radius:12px;font-size:0.9rem;max-width:88%}
.debate-msg.me{align-self:flex-end;background:rgba(var(--accentRGB),.14);border:1px solid var(--line)}
.debate-msg.ai{align-self:flex-start;background:rgba(var(--jadeRGB),.1);border:1px solid rgba(var(--jadeRGB),.35)}
table.cmp{width:100%;border-collapse:collapse;font-size:0.8333rem}
table.cmp th{background:rgba(var(--accentRGB),.1);color:var(--accent2);padding:8px;border:1px solid var(--line2);font-weight:600}
table.cmp td{padding:8px;border:1px solid var(--line2);color:var(--tx2)}
/* 省份轮廓拼图（需求 4.3.1）。2026-09-30 改为真实省界数据后整块重写：
   底图不再是「绝对定位的方块插槽」，而是一整张 SVG（35 个要素的真实轮廓）。
   原来的 .pz-board/.pz-slot/.pz-piece(绝对定位)/.piece-chip 全部作废 ——
   真实省界的包围盒互相重叠（内蒙古是长弧形、甘肃是月牙），
   按包围盒切方块插槽必然互相盖住、谁也点不准。 */
.pz-wrap{position:relative;border:1px solid var(--line2);border-radius:14px;background:var(--deep);overflow:hidden}
.pz-svg{display:block;width:100%;height:auto}
/* ctx＝不在本局的省（浅色底，提供"国家轮廓"上下文） */
.pz-svg .pz-ctx{fill:rgba(var(--hlRGB),.07);stroke:rgba(var(--hlRGB),.22);stroke-width:.6}
/* hole＝本局待拼（虚线空洞） */
.pz-svg .pz-hole{fill:rgba(var(--hlRGB),.02);stroke:rgba(var(--accentRGB),.5);stroke-width:1;stroke-dasharray:5 4}
/* fill＝已拼对 */
.pz-svg .pz-fill{fill:rgba(var(--accentRGB),.34);stroke:var(--accent2);stroke-width:.9}
/* ref＝固定参照（南海诸岛等），始终可见 */
.pz-svg .pz-ref{fill:rgba(var(--hlRGB),.09);stroke:rgba(var(--hlRGB),.45);stroke-width:.7;stroke-dasharray:2 2}
/* ★ 拼图里的字号一律不用 px（全站契约：写死 px 会让「字号调节」在那处失效，
   见 server/tests/theme.test.js 与 life.test.js）。
   ★ 连注释里都不要写那个被禁止的字面量 —— 契约是整文件正则扫描，分不清代码与注释，
     上一版就是在注释里写了一遍，把自己扫红了。
   但 SVG 里的字号有它的特殊性，不能简单换成 rem：
   `<text>` 的 font-size 在 viewBox 坐标系里就是**用户单位**，底图缩放时标签跟着缩放。
   所以这里的口径是「先在 svg 根上立一个用户单位基准，标签再按 em 取」：
     .pz-svg 根字号 1rem          → 16 用户单位（随无障碍字号一起变）
     .pz-lbl 取 .8125em           → 13 用户单位，与原写法逐像素相同
     .pz-inset .pz-lbl 取 .9375em → 15 用户单位（嵌套 svg 自己的坐标系）
   好处：既符合契约，又保留了「调大字号 → 地图标签一并变大」这条无障碍链路。 */
.pz-svg{font-size:1rem}
.pz-svg .pz-lbl{fill:var(--tx3);font-size:.8125em;text-anchor:middle;dominant-baseline:middle;pointer-events:none;font-family:var(--sans)}
.pz-svg .pz-lbl.hint{fill:var(--tx2)}
/* 右下角「南海诸岛」插图框。主图只画陆地，南海诸岛（本数据集里是十段线）
   放进这个嵌套 svg 里 —— 标准中国地图的做法，也必须如此（合规：南海诸岛要在图上）。 */
.pz-svg .pz-inset .pz-inset-frame{fill:rgba(var(--hlRGB),.02);stroke:rgba(var(--hlRGB),.3);stroke-width:1;stroke-dasharray:3 2;vector-effect:non-scaling-stroke}
.pz-svg .pz-inset .pz-lbl{font-size:.9375em}
.pz-svg .pz-inset path{vector-effect:non-scaling-stroke}
.pz-tray{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px;max-height:300px;overflow-y:auto}
.pz-piece{display:flex;flex-direction:column;align-items:center;gap:1px;padding:6px 8px 4px;border:1px solid var(--line2);
  border-radius:10px;background:var(--panel2);cursor:grab;user-select:none;transition:.15s}
.pz-piece:hover{border-color:var(--accent)}
.pz-piece.dragging{opacity:.4}
.pz-piece svg{display:block;overflow:visible}
.pz-piece svg path{fill:rgba(var(--accentRGB),.28);stroke:var(--accent2);stroke-width:1.2;vector-effect:non-scaling-stroke}
.pz-piece .nm{font-size:.72rem;color:var(--tx2);line-height:1.3}
.pz-piece .ar{font-size:.625rem;color:var(--tx3);line-height:1.2}
/* 窄屏时底图被压小，标签按 viewBox 单位等比缩小 —— 所以窄屏要把**根字号**调大
   才能维持可读的实际像素大小（反过来调小就彻底看不见了）。
   调根字号而不是调 .pz-lbl：主图与插图的标签会一起变，两处不会各自跑偏。 */
@media(max-width:760px){.pz-svg{font-size:1.625rem}.pz-tray{max-height:220px}}
.ds-board{position:relative;height:300px;border:1px solid var(--line2);border-radius:14px;background:var(--deep);overflow:hidden;max-width:560px;margin:0 auto}
.ds-region{position:absolute;display:flex;align-items:center;justify-content:center;font-size:0.8rem;letter-spacing:2px;
  border:1px solid rgba(var(--accentRGB),.25);border-radius:10px;color:rgba(var(--accentRGB),.3);cursor:pointer;transition:.3s;background:rgba(var(--hlRGB),.02)}
.ds-region:hover{border-color:var(--line)}
.ds-region.open{color:var(--onAccent);font-weight:700;border:none}
.env-item{display:flex;gap:12px;padding:10px 0;border-bottom:1px dashed var(--line2)}
.env-item:last-child{border-bottom:none}
.env-item .ico{font-size:1.6rem}
.caps-item{display:flex;gap:10px;padding:8px 0;border-bottom:1px dashed var(--line2);font-size:0.8667rem}
.caps-item .yr{min-width:88px;color:var(--accent);font-family:var(--serif);font-weight:700}
.migr{animation:dash 1.4s linear infinite}
@keyframes dash{to{stroke-dashoffset:-24}}
.graph-svg text{fill:var(--tx2);font-size:0.7333rem}
.graph-svg .gnode{cursor:pointer}
.graph-svg .gnode:hover circle{stroke:var(--accent);stroke-width:2}
footer{border-top:1px solid var(--line2);padding:30px;text-align:center;color:var(--tx3);font-size:0.8333rem;letter-spacing:2px;position:relative;z-index:1}
footer .motto{font-family:var(--serif);color:var(--tx2);letter-spacing:4px;margin-bottom:8px}
@media (max-width:1020px){
  /* ⚠️ 折叠成单列时必须写 `minmax(0,1fr)`，不能只写 `1fr`。
     裸 `1fr` 的轨道最小值是 `auto`（= 内容的 min-content），所以「把两栏压成一栏」
     并不解决溢出：原来撑破两栏的那段不肯折行的内容，照样把单栏轨道顶到比容器还宽。
     320px 实测：`.grid[style*="1.2fr 1fr"]`（学习中心）折叠后轨道算出 323px、
     容器只有 302px → 整页右溢 21px。换成 minmax(0,1fr) 才是真的「按容器折行」。 */
  .home-grid,.geo-grid,.grid[style*="grid-template-columns:1.2fr 1fr"]{grid-template-columns:minmax(0,1fr) !important}
  .topic-grid{grid-template-columns:repeat(2,1fr)}
  .stat-row{grid-template-columns:repeat(2,1fr)}
  .hero{padding:44px 26px}
  .hero h1{font-size:2.5333rem}
  .six-grid{grid-template-columns:repeat(2,1fr)}
}
@media print{
  /* 打印一律是白纸黑墨，与屏幕主题无关——所以这里用固定深色而不是主题变量。
     若跟着主题走，深色主题下打出来就是浅字压白纸，几乎看不见。 */
  body{background:#fff;color:#222}
  header,footer,.tl-controls,.btn{display:none !important}
  .card,.stat{border-color:#ddd;background:#fff}
  .sec-head .cn,.modal h2,.stat .num{color:#2C2C2C}
}

/* ---------- 影视关联引擎区块（需求 3.5.1） ---------- */
.fl-wrap{margin-top:20px;padding-top:14px;border-top:1px solid var(--line2)}
.fl-head{font-size:0.8rem;letter-spacing:3px;color:var(--accent);display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.fl-src{font-size:0.7333rem;letter-spacing:1px;color:var(--tx3)}
.fl-group{margin-top:10px}
.fl-label{font-size:0.8rem;color:var(--tx2);margin-bottom:6px}
.fl-hint{font-size:0.7333rem;color:var(--tx3);margin-left:6px}
.fl-chips{display:flex;gap:8px;flex-wrap:wrap}
.fl-chip{display:inline-flex;flex-direction:column;gap:1px;padding:6px 11px;border-radius:10px;
  background:rgba(var(--accentRGB),.07);border:1px solid var(--line);cursor:pointer;transition:.2s;max-width:240px}
.fl-chip:hover{background:rgba(var(--accentRGB),.15);border-color:rgba(var(--accentRGB),.45)}
.fl-chip b{font-size:0.8667rem;color:var(--tx);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fl-meta{font-size:0.7rem;color:var(--tx3)}
.fl-star{font-size:0.6667rem;color:var(--accent);letter-spacing:1px}
.fl-empty{font-size:0.8333rem;color:var(--tx3);margin-top:8px}

/* ---------- 时间粒度刻度与选择器（需求 3.1.2） ---------- */
.tl-tick{position:absolute;top:158px;width:1px;height:9px;background:rgba(var(--accentRGB),.25);pointer-events:none;z-index:1}
.tl-tick span{position:absolute;top:11px;left:50%;transform:translateX(-50%);white-space:nowrap;
  font-size:0.6667rem;color:var(--tx3);font-family:var(--serif);letter-spacing:.5px}
.grain-box{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.grain-badge{font-size:0.7667rem;color:var(--tx2);letter-spacing:1px;border:1px solid var(--line);
  border-radius:99px;padding:3px 11px;background:rgba(var(--accentRGB),.07)}
.grain-badge b{color:var(--accent2);font-family:var(--serif);font-size:0.8667rem;letter-spacing:2px;margin-left:2px}
.grain-note{font-size:0.7333rem;color:var(--tx3)}

/* ---------- 全站公告（后台系统设置可配） ---------- */
.site-notice{position:relative;z-index:99;max-width:1320px;margin:14px auto 0;padding:9px 16px;
  font-size:0.8667rem;line-height:1.7;color:var(--accent2);
  background:rgba(var(--accentRGB),.09);border:1px solid var(--line);border-radius:11px}
/* ---------- 访问门控面板（gate.js 注入，仅锁站未登录时出现） ---------- */
#shj-gate input:focus{border-color:rgba(var(--accentRGB),.6)!important;box-shadow:0 0 0 3px rgba(var(--accentRGB),.12)}
#shj-gate button:disabled{opacity:.62;cursor:not-allowed}

/* 启动面板（检测中）的三行版式。
   字号之所以走表、不内联在 gate.js 里：品牌行放大到 4.1rem 后，
   「山 河 纪」在 360px 视口下会被挤成两行，只能靠媒体查询在窄屏收回去；
   而内联样式没法被 @media 覆盖。颜色仍留在 gate.js（必须写字面色值：
   遮罩底色是写死的 #0d0b08，取主题变量会在浅色皮肤下撞成看不见）。
   约束：三行必须按同一比例一起缩放，只放大第一行会让它看起来像个错误。 */
.gt-splash{text-align:center;padding:0 16px}
.gt-splash>div{font-family:'Noto Serif SC',STZhongsong,SimSun,serif}
.gt-splash-brand{font-size:4.1rem;font-weight:700;letter-spacing:14px;text-indent:14px;
  line-height:1.28;white-space:nowrap}
.gt-splash-motto{margin-top:24px;font-size:1.7rem;letter-spacing:7px;line-height:1.9}
.gt-splash-by{margin-top:40px;font-size:1.45rem;letter-spacing:7px}
/* 窄屏必须收：4.1rem 的「山 河 纪」（含字间空格与字距）约 328px 宽，
   360px 视口下可用只有约 312px，不收就会折成「山 河 / 纪」。 */
@media (max-width:420px){
  .gt-splash-brand{font-size:3.2rem;letter-spacing:8px;text-indent:8px}
  .gt-splash-motto{margin-top:18px;font-size:1.35rem;letter-spacing:4px}
  .gt-splash-by{margin-top:28px;font-size:1.15rem;letter-spacing:4px}
}

/* ================= 国家变迁（需求 3.2） ================= */
.dv-tabs{display:flex;gap:6px;margin-bottom:20px;flex-wrap:wrap}
.dv-tabs span{padding:8px 18px;border-radius:9px;font-size:0.9333rem;letter-spacing:1px;cursor:pointer;
  color:var(--tx2);border:1px solid var(--line);background:rgba(var(--accentRGB),.04);transition:.22s}
.dv-tabs span:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.38)}
.dv-tabs span.on{color:var(--onAccent);background:var(--btnGrad);border-color:transparent;font-weight:700}
/* 并进「地理探索」的人文地理子页签（#gc-tabs）：刻意降一级 ——
   上下两排页签一样重的话，看不出「人文地理」是地理探索下的一个栏目。 */
.dv-tabs.sub{margin-top:-6px;margin-bottom:18px}
.dv-tabs.sub span{padding:6px 14px;font-size:0.8667rem;border-style:dashed}
.dv-tabs.sub span.on{border-style:solid}
/* ================= 风流人物：模块切换（历史人物 / 天下诗文） =================
   本页有两级：这一层是「模块」，下面那层 .dv-tabs 是「模块内的视图」。
   两级不能做成同一种样式 —— 那样就看不出「作品库」究竟是诗文模块里的一个视图，
   还是与诗文并列的一个栏目（用户会以为菜单少了两项）。
   所以这里做成胶囊式分段控件：外层一条灰底轨道，选中项用按钮渐变填充，
   与下面那排「描边 + 透明底」的页签在轮廓和质感上都拉开距离。 */
.ff-seg{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-bottom:20px;
  padding:5px;border-radius:13px;border:1px solid var(--line);background:var(--bg2)}
.ff-seg-b{padding:7px 20px;border-radius:9px;cursor:pointer;font-family:inherit;
  font-size:0.9333rem;letter-spacing:1px;color:var(--tx2);border:1px solid transparent;
  background:transparent;transition:.22s}
.ff-seg-b:hover{color:var(--accent2)}
.ff-seg-b.on{color:var(--onAccent);background:var(--btnGrad);font-weight:700}
/* 右侧那句「读其人，亦读其文」是说明，不是控件：不给边框、不给底色，
   并且用 --tx2 而不是 --tx3 —— 这条在窄屏会单独占一行，太淡会读不出来。 */
.ff-seg-n{margin-left:auto;padding:0 10px;font-size:0.8rem;letter-spacing:1px;color:var(--tx2)}
.dv-side-tabs{display:flex;gap:6px;margin-bottom:10px}
.dv-side-tabs span{flex:1;text-align:center;padding:6px 0;border-radius:8px;font-size:0.8333rem;cursor:pointer;
  color:var(--tx3);border:1px solid var(--line)}
.dv-side-tabs span.on{color:var(--accent2);border-color:rgba(var(--accentRGB),.45);background:rgba(var(--accentRGB),.1)}
/* 只有「朝代档案」是「左列表 + 右详情」两栏；继承关系 / 文明对比 / 历史总结都是单栏。
   早先把 grid 直接写在 #dv-body 上，而 #dv-body 是所有视图的公共容器，
   于是单栏内容被整块塞进 220px 的左侧列——表现就是「整个页面缩成左边一根竖条，
   文字全被挤断行，右边一大片空白」。布局按视图判断，不能让单栏视图继承两栏。 */
#dv-body.dv-split{display:grid;grid-template-columns:220px 1fr;gap:20px;align-items:start}
.dv-list{max-height:640px;overflow-y:auto;padding-right:4px}
.dv-item{padding:8px 11px;border-radius:8px;cursor:pointer;margin-bottom:3px;transition:.18s;
  border:1px solid transparent;display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.dv-item:hover{background:rgba(var(--accentRGB),.07)}
.dv-item.on{background:rgba(var(--accentRGB),.13);border-color:var(--line)}
.dv-item b{font-family:var(--serif);font-size:1rem;color:var(--tx);font-weight:600}
.dv-item.on b{color:var(--accent2)}
.dv-item span{font-size:0.7rem;color:var(--tx3);white-space:nowrap}
.dv-main{min-width:0}
.dv-name{font-family:var(--serif);font-size:2rem;font-weight:700;letter-spacing:3px;color:var(--accent2)}
.dv-span{font-size:0.8333rem;color:var(--tx3);margin-top:6px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.dv-head{margin-bottom:16px}
.dv-card{margin-bottom:14px}
.dv-row{display:grid;grid-template-columns:88px 1fr;gap:14px;padding:9px 0;border-bottom:1px dashed var(--line2)}
.dv-row:last-child{border-bottom:0}
.dv-lab{font-size:0.8333rem;color:var(--accent);letter-spacing:1px}
.dv-val{font-size:0.9rem;color:var(--tx);line-height:1.85}
.dv-caps{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.dv-cap{display:inline-flex;flex-direction:column;font-size:0.8667rem;color:var(--tx);
  background:rgba(var(--accentRGB),.08);border:1px solid var(--line);border-radius:7px;padding:3px 9px}
.dv-cap i{font-style:normal;font-size:0.7rem;color:var(--tx3)}
.dv-arrow{color:var(--tx3);font-size:0.8rem}
.dv-sub{font-size:0.8667rem;letter-spacing:2px;color:var(--jade);margin-bottom:8px}
.dv-p{font-size:0.9rem;color:var(--tx2);line-height:1.95;margin-bottom:14px}
.dv-p:last-child{margin-bottom:0}
.dv-eval{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:12px}
.dv-eval-h{font-size:0.8333rem;letter-spacing:1px;margin-bottom:7px}
.dv-eval-h.up{color:var(--jade)}
.dv-eval-h.down{color:var(--red)}
.dv-ul{list-style:none}
.dv-ul li{font-size:0.8667rem;color:var(--tx2);line-height:1.8;padding-left:2px;margin-bottom:6px;display:flex;gap:7px}
.dv-ul .ic{flex:0 0 auto;font-weight:700}
.dv-ul.up .ic{color:var(--jade)}
.dv-ul.down .ic{color:var(--red)}
.dv-sum{margin-top:14px;padding:12px 14px;border-left:3px solid var(--accent);border-radius:0 9px 9px 0;
  background:rgba(var(--accentRGB),.07);font-family:var(--serif);font-size:0.9rem;line-height:1.95;color:var(--accent2)}
/* 继承关系 */
.dv-axis{display:flex;justify-content:space-between;font-size:0.7rem;color:var(--tx3);
  font-family:var(--serif);letter-spacing:1px;padding:0 0 8px 84px;border-bottom:1px solid var(--line2);margin-bottom:10px}
.dv-tree{max-height:620px;overflow-y:auto;padding-right:6px}
.dv-trow{display:flex;align-items:center;gap:12px;height:26px}
.dv-tname{flex:0 0 72px;font-family:var(--serif);font-size:0.8667rem;color:var(--accent2);text-align:right}
/* 仍在延续的王朝/时期（中华人民共和国等）：名字更长，需要更宽的一列，
   且条尾加一道渐隐 —— 「画到边界还在继续」这个意思只有图形能说清。 */
.dv-trow.live .dv-tname{flex:0 0 96px;font-size:0.7333rem;white-space:nowrap}
.dv-trow.live .dv-tbar{background:linear-gradient(90deg,var(--accent),rgba(var(--accentRGB),.25))}
.dv-tbar-wrap{flex:1;position:relative;height:26px}
.dv-tbar{position:absolute;top:8px;height:11px;border-radius:6px;
  background:linear-gradient(90deg,rgba(var(--accentRGB),.75),rgba(var(--accentRGB),.35));min-width:3px}
.dv-tyear{position:absolute;top:6px;font-size:0.6667rem;color:var(--tx3);white-space:nowrap;padding-left:4px}
.dv-trel{font-size:0.7333rem;color:var(--tx3);padding:1px 0 1px 84px;display:flex;gap:6px;align-items:center}
.dv-trel .rel-type{font-size:0.6667rem;padding:1px 7px;border-radius:99px;border:1px solid var(--line)}
.dv-trel .rel-type.统一,.dv-trel .rel-type.中兴{color:var(--jade);border-color:rgba(var(--jadeRGB),.45)}
.dv-trel .rel-type.分裂{color:var(--red);border-color:rgba(var(--redRGB),.45)}
.dv-trel .rel-type.南渡{color:var(--blue);border-color:rgba(var(--blueRGB),.45)}
.dv-trel .rel-type.延续{color:var(--tx3)}
.dv-parallel{font-size:0.8333rem;color:var(--tx2);margin-bottom:7px;display:flex;gap:8px;align-items:center}
/* 文明对比 */
.dv-picker{display:flex;flex-wrap:wrap;gap:6px}
.dv-pk{font-size:0.8333rem;padding:6px 12px;border-radius:99px;cursor:pointer;transition:.18s;
  border:1px solid var(--line);color:var(--tx2);display:inline-flex;align-items:baseline;gap:5px}
.dv-pk i{font-style:normal;font-size:0.6667rem;color:var(--tx3)}
.dv-pk:hover{border-color:rgba(var(--accentRGB),.4);color:var(--accent2)}
.dv-pk.on{background:var(--btnGrad);border-color:transparent;color:var(--onAccent);font-weight:700}
.dv-pk.on i{color:rgba(var(--onAccentRGB),.6)}
.dv-cmp th{text-align:center}
.dv-cmp th i{display:block;font-style:normal;font-size:0.7rem;color:var(--tx3);margin-top:2px}
.dv-cmp td{text-align:center;vertical-align:middle}
.dv-dim{text-align:left!important;font-size:0.8667rem;color:var(--accent);min-width:150px}
.dv-dim i{display:block;font-style:normal;font-size:0.7rem;color:var(--tx3);margin-top:2px}
.dv-score{display:flex;align-items:center;gap:8px;justify-content:center}
.dv-score b{font-family:var(--serif);font-size:1.0667rem;color:var(--accent2);min-width:18px}
.dv-score .bar{width:74px}
.dv-why{display:grid;gap:10px;margin-top:16px}
.dv-why-item{font-size:0.8667rem;color:var(--tx2);line-height:1.9;padding-left:12px;border-left:2px solid var(--line)}
.dv-why-item b{color:var(--accent2);margin-right:8px}
.dv-hint{font-size:0.8333rem;color:var(--tx3);line-height:1.9}
@media(max-width:900px){
  /* ⚠️ 必须连 `.dv-split` 一起写。上面两栏那条是 `#dv-body.dv-split`（1 id + 1 class），
     只写 `#dv-body`（1 id）特异度更低 —— 同特异度才比源码顺序，这里根本比不过，
     结果是「以为窄屏已经改单列、实际仍是 220px 两栏」：320px 上内容列只剩 27px，
     胶囊撑破卡片，整页右溢 92px。改前真浏览器实测就是这条在作祟。 */
  #dv-body.dv-split{grid-template-columns:1fr}
  .dv-list{max-height:230px}
  .dv-eval{grid-template-columns:1fr;gap:12px}
  .dv-axis{padding-left:0}
  .dv-trel{padding-left:0}
}

/* ---------- 历史总结（国家变迁 · 第四视图） ---------- */
.ds-list{display:grid;gap:12px}
.ds-item{border:1px solid var(--line2);border-radius:12px;padding:14px 16px;background:rgba(var(--hlRGB),.014)}
.ds-era{font-family:var(--serif);font-size:1.1333rem;font-weight:700;color:var(--accent2);letter-spacing:2px;
  display:flex;align-items:baseline;gap:10px;margin-bottom:11px;
  padding-bottom:9px;border-bottom:1px dashed var(--line2)}
.ds-era i{font-style:normal;font-size:0.7333rem;color:var(--tx3);font-family:var(--sans);letter-spacing:0}
.ds-col{margin-bottom:10px}
.ds-h{font-size:0.8rem;letter-spacing:1px;margin-bottom:5px}
.ds-col.up .ds-h{color:var(--jade)}
.ds-col.down .ds-h{color:var(--red)}
.ds-col ul{list-style:none}
.ds-col li{font-size:0.8533rem;color:var(--tx2);line-height:1.8;padding-left:13px;position:relative;margin-bottom:4px}
.ds-col li::before{position:absolute;left:0;top:0;font-size:0.6667rem}
.ds-col.up li::before{content:"＋";color:var(--jade)}
.ds-col.down li::before{content:"－";color:var(--red)}
.ds-sum{font-family:var(--serif);font-size:0.8667rem;line-height:1.9;color:var(--accent2);
  padding:9px 12px;border-left:2px solid var(--accent);border-radius:0 8px 8px 0;background:rgba(var(--accentRGB),.06)}
.ds-theme{border-top:1px solid var(--line2);padding:15px 0}
.ds-theme:first-of-type{border-top:0}
.ds-theme-h{font-family:var(--serif);font-size:1.0667rem;color:var(--accent2);letter-spacing:2px;
  display:flex;align-items:center;gap:10px;margin-bottom:7px}
.ds-theme-h .n{font-family:var(--sans);font-size:0.7333rem;color:var(--accent);border:1px solid var(--line);
  border-radius:99px;padding:1px 8px;letter-spacing:1px}
.ds-line{font-size:0.8333rem;color:var(--blue);letter-spacing:.5px;margin-bottom:11px;
  padding:7px 11px;background:rgba(var(--blueRGB),.07);border-radius:8px;line-height:1.8}
.ds-two{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.ds-two>div{font-size:0.8533rem;color:var(--tx2);line-height:1.9}
.ds-two b{display:block;margin-bottom:4px;font-size:0.8rem;letter-spacing:1px}
.ds-two .up b{color:var(--jade)}
.ds-two .down b{color:var(--red)}
.ds-verdict{margin-top:18px;border-color:rgba(var(--accentRGB),.35)}
.ds-lead{font-size:0.9rem;color:var(--tx);line-height:1.95;margin-bottom:12px}
.ds-points{list-style:none;counter-reset:dp}
.ds-points li{counter-increment:dp;font-size:0.8667rem;color:var(--tx2);line-height:1.95;
  padding-left:30px;position:relative;margin-bottom:11px}
.ds-points li::before{content:counter(dp);position:absolute;left:0;top:2px;width:19px;height:19px;
  border-radius:50%;background:rgba(var(--accentRGB),.14);border:1px solid var(--line);
  color:var(--accent2);font-size:0.7333rem;display:flex;align-items:center;justify-content:center}
.ds-points li b{color:var(--accent2)}
.ds-tail{margin-top:14px;padding:13px 15px;border-radius:11px;background:rgba(var(--jadeRGB),.08);
  border:1px solid rgba(var(--jadeRGB),.22);font-family:var(--serif);font-size:0.9rem;line-height:1.95;color:var(--jade)}
@media(max-width:900px){.ds-two{grid-template-columns:1fr;gap:10px}}

/* ================= 诗文里的中国 ================= */
.lt-bar{margin-bottom:22px}
.lt-filters{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.lt-filters span{padding:6px 15px;border-radius:99px;font-size:0.8333rem;cursor:pointer;transition:.2s;
  border:1px solid var(--line);color:var(--tx2)}
.lt-filters span:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.4)}
.lt-filters span.on{background:var(--btnGrad);border-color:transparent;color:var(--onAccent);font-weight:700}
.lt-search{width:100%;max-width:340px;margin-bottom:12px}
.lt-hint{font-size:0.8rem;color:var(--tx3);line-height:1.9}
.lt-era{margin-bottom:30px}
.lt-era-h{font-family:var(--serif);font-size:1.4rem;font-weight:700;letter-spacing:3px;color:var(--accent2);
  display:flex;align-items:baseline;gap:12px;margin-bottom:14px;
  padding-bottom:9px;border-bottom:1px solid var(--line2)}
.lt-era-n{font-size:0.7333rem;color:var(--tx3);font-family:var(--sans);letter-spacing:1px}
.lt-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:13px}
.lt-card{cursor:pointer;transition:.22s;padding:14px 16px}
.lt-card:hover{transform:translateY(-3px);border-color:rgba(var(--accentRGB),.42)}
.lt-card-h{display:flex;align-items:center;gap:8px;margin-bottom:7px;flex-wrap:wrap}
.lt-card-h b{font-family:var(--serif);font-size:1.0667rem;color:var(--tx);font-weight:600;letter-spacing:1px}
.lt-type{flex:0 0 auto;width:19px;height:19px;border-radius:5px;display:inline-flex;align-items:center;justify-content:center;
  font-size:0.7rem;background:rgba(var(--accentRGB),.15);color:var(--accent2);border:1px solid var(--line)}
.lt-book{font-size:0.6333rem;padding:1px 7px;border-radius:99px;letter-spacing:.5px;margin-left:auto;white-space:nowrap}
.lt-book.in{color:var(--jade);border:1px solid rgba(var(--jadeRGB),.42);background:rgba(var(--jadeRGB),.09)}
.lt-book.out{color:var(--tx3);border:1px solid var(--line2)}
.lt-meta{font-size:0.7333rem;color:var(--tx3);line-height:1.6;margin-bottom:7px}
.lt-pre{font-family:var(--serif);font-size:0.8533rem;color:var(--tx2);line-height:1.75;opacity:.9}
.lt-modal{max-width:760px;width:100%}
.lt-d-head{margin-bottom:18px;padding-right:34px}
.lt-d-head h2{font-family:var(--serif);font-size:1.6667rem;color:var(--accent2);letter-spacing:2px;margin-bottom:10px}
.lt-d-meta{display:flex;gap:7px;flex-wrap:wrap}
.lt-sec{margin-bottom:17px}
.lt-sec-h{font-size:0.8rem;letter-spacing:3px;color:var(--accent);margin-bottom:7px}
.lt-sec-b{font-size:0.9rem;color:var(--tx2);line-height:2}
.lt-text{font-family:var(--serif);font-size:1.0667rem;line-height:2.25;color:var(--tx);letter-spacing:.5px;
  padding:16px 18px;background:rgba(var(--accentRGB),.055);border:1px solid var(--line);border-radius:12px}
.lt-sec.geo .lt-sec-b{color:var(--blue);background:rgba(var(--blueRGB),.06);
  padding:10px 13px;border-radius:9px;border-left:2px solid rgba(var(--blueRGB),.4)}
.lt-sec.people .lt-sec-b{display:flex;gap:8px;flex-wrap:wrap}
.lt-person{font-size:0.8333rem;padding:5px 12px;border-radius:99px;cursor:pointer;transition:.2s;
  border:1px solid var(--line);color:var(--tx);background:rgba(var(--accentRGB),.07);display:inline-flex;align-items:baseline;gap:6px}
.lt-person i{font-style:normal;font-size:0.6667rem;color:var(--accent)}
.lt-person:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.lt-person.off{opacity:.5;cursor:default}
/* 诗中的地方：与「关联人物」同一套视觉语法（同样的底、同样的字色），
   只在左侧多一个「山川 / 景点」小标签区分跳转目标。
   字色只用 --tx / --accent / --accent2 —— 这三者在所有主题里都有定义，
   换主题时不会掉回兜底色（主题测试卡死了变量键集合）。 */
.lt-sec.spots .lt-sec-b{display:flex;gap:8px;flex-wrap:wrap}
.lt-spot{font-size:0.8333rem;padding:5px 12px;border-radius:99px;cursor:pointer;transition:.2s;
  border:1px solid var(--line);color:var(--tx);background:rgba(var(--accentRGB),.07);
  display:inline-flex;align-items:baseline;gap:6px}
.lt-spot em{font-style:normal;font-size:0.6667rem;padding:1px 6px;border-radius:99px;
  color:var(--accent);border:1px solid rgba(var(--accentRGB),.35)}
.lt-spot i{font-style:normal;font-size:0.6667rem;color:var(--accent2)}
.lt-spot:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.lt-d-foot{display:flex;gap:10px;margin-top:20px;flex-wrap:wrap}

/* ============================================================
   课本人物全集（textbook-view.js）
   与「深度档案」共用 #figures 页，靠 #fig-tabs 切换。
   ============================================================ */
.tb-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:14px}
.tb-card{cursor:pointer;padding:16px;display:flex;flex-direction:column;gap:8px;transition:.2s}
.tb-card:hover{border-color:rgba(var(--accentRGB),.42);transform:translateY(-2px)}
.tb-card-h{display:flex;align-items:center;gap:10px}
.tb-avatar{flex:0 0 38px;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;overflow:hidden;
  font-family:var(--serif);font-size:1.2667rem;color:var(--accent2);
  background:linear-gradient(135deg,rgba(var(--accentRGB),.22),rgba(var(--accentRGB),.06));border:1px solid var(--line)}
/* 人物照片：有素材时铺满头像框（cover 裁切，脸在上半部由构建期锚点保证），
   没有素材时退回上面的首字色块 —— 绝不留破图占位 */
.tb-avatar img{width:100%;height:100%;object-fit:cover;display:block}
.tb-d-photo{width:84px;height:84px;border-radius:12px;object-fit:cover;display:block;
  border:1px solid var(--line);background:var(--bg2);float:left;margin:0 14px 10px 0}
.tb-card-t{display:flex;flex-direction:column;min-width:0}
.tb-card-t b{font-family:var(--serif);font-size:1.1333rem;letter-spacing:1px;color:var(--tx)}
.tb-life{font-size:0.7333rem;color:var(--tx3);letter-spacing:.5px}
.tb-tags{display:flex;gap:6px;flex-wrap:wrap}
.tb-era,.tb-field{font-size:0.7333rem;padding:2px 8px;border-radius:6px;letter-spacing:.5px}
.tb-era{color:var(--accent2);background:rgba(var(--accentRGB),.1);border:1px solid rgba(var(--accentRGB),.22)}
.tb-field{color:var(--jade);background:rgba(var(--jadeRGB),.1);border:1px solid rgba(var(--jadeRGB),.22)}
.tb-role{font-size:0.8rem;color:var(--tx2);line-height:1.5}
.tb-pre{font-size:0.8rem;color:var(--tx3);line-height:1.6;border-top:1px dashed var(--line2);padding-top:8px}
.tb-fields{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
.tb-fields span{font-size:0.8rem;padding:3px 10px;border-radius:7px;cursor:pointer;color:var(--tx3);
  border:1px solid var(--line2);transition:.18s}
.tb-fields span:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.36)}
.tb-fields span.on{color:var(--onAccent);background:var(--btnGrad);border-color:transparent;font-weight:700}
.tb-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px}
.tb-facts>div{background:var(--bg2);border:1px solid var(--line2);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:2px}
.tb-facts span{font-size:0.7333rem;letter-spacing:2px;color:var(--tx3)}
.tb-facts b{font-size:0.8667rem;color:var(--tx);font-weight:500;line-height:1.55}
.tb-lit-row{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:8px}
.tb-lit-lb{font-size:0.7333rem;letter-spacing:2px;color:var(--tx3);flex:0 0 100%}
.tb-lit{display:inline-flex;flex-direction:column;gap:1px;padding:6px 11px;border-radius:9px;cursor:pointer;
  border:1px solid var(--line);color:var(--tx2);background:rgba(var(--accentRGB),.06);font-size:0.8667rem;transition:.18s}
.tb-lit i{font-style:normal;font-size:0.6667rem;color:var(--tx3)}
.tb-lit:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.tb-dyns{display:flex;gap:8px;flex-wrap:wrap}
.tb-dyn{display:inline-flex;flex-direction:column;gap:1px;padding:6px 12px;border-radius:9px;cursor:pointer;
  border:1px solid rgba(var(--blueRGB),.3);color:var(--tx2);background:rgba(var(--blueRGB),.08);font-size:0.8667rem;transition:.18s}
.tb-dyn i{font-style:normal;font-size:0.6667rem;color:var(--tx3)}
.tb-dyn:hover{border-color:rgba(var(--blueRGB),.6);color:var(--blueTx)}

/* ---- 名录统计条与翻页（textbook-view.js） ----
   名录 200+ 人，先给「有多少 / 分布如何」，再分页给细节。
   条形图用两层 div 而不是 <progress>/canvas：不引第三方库，也不受主题变量失效影响。 */
.tb-stats{padding:16px 18px;display:flex;flex-direction:column;gap:14px;margin-bottom:14px}
.tb-stats-kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(108px,1fr));gap:10px}
.tb-stat{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border-radius:11px;
  background:var(--bg2);border:1px solid var(--line2)}
.tb-stat b{font-family:var(--serif);font-size:1.4667rem;line-height:1.1;color:var(--accent2)}
.tb-stat span{font-size:0.8rem;color:var(--tx2)}
.tb-stat i{font-style:normal;font-size:0.6667rem;color:var(--tx3);letter-spacing:.5px}
.tb-dist{display:flex;flex-direction:column;gap:6px}
.tb-dist-h{font-size:0.8rem;letter-spacing:2px;color:var(--accent);margin-bottom:2px}
.tb-dist-h span{letter-spacing:0;color:var(--tx3);font-size:0.72rem}
.tb-dist-row{display:grid;grid-template-columns:76px 1fr 34px;align-items:center;gap:10px;font-size:0.8rem}
.tb-dist-n{color:var(--tx2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb-dist-bar{height:8px;border-radius:99px;background:rgba(var(--accentRGB),.1);overflow:hidden}
.tb-dist-bar i{display:block;height:100%;border-radius:99px;background:var(--btnGrad)}
.tb-dist-v{text-align:right;color:var(--tx3);font-variant-numeric:tabular-nums}
.tb-dist-more{font-size:0.72rem;color:var(--tx3)}
.tb-pager{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:12px 16px;margin-top:14px}
.tb-pg-size{display:flex;align-items:center;gap:6px;font-size:0.8rem;color:var(--tx3)}
.tb-pg-size span{font-size:0.8rem;padding:3px 10px;border-radius:7px;cursor:pointer;color:var(--tx3);
  border:1px solid var(--line2);transition:.18s}
.tb-pg-size span:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.36)}
.tb-pg-size span.on{color:var(--onAccent);background:var(--btnGrad);border-color:transparent;font-weight:700}
.tb-pg-nav{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.tb-pg-btn,.tb-pg-num{font-size:0.8rem;padding:5px 11px;border-radius:8px;cursor:pointer;
  border:1px solid var(--line2);color:var(--tx2);transition:.18s;user-select:none}
.tb-pg-btn:hover,.tb-pg-num:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.5)}
.tb-pg-num.on{color:var(--onAccent);background:var(--btnGrad);border-color:transparent;font-weight:700}
/* 首/末页时「上一页/下一页」置灰但仍占位：按钮忽隐忽现会让页码左右跳动 */
.tb-pg-btn.off{opacity:.4;cursor:default}
.tb-pg-btn.off:hover{color:var(--tx2);border-color:var(--line2)}
.tb-pg-gap{color:var(--tx3);padding:0 2px}
.tb-pg-info{margin-left:auto;font-size:0.8rem;color:var(--tx3)}
.tb-pg-info b{color:var(--accent2);font-weight:600}

/* ============================================================
   地理数据库（geo-view.js）
   与「探索游戏」共用 #geo 页，靠 #geo-tabs 切换。
   ============================================================ */
.gv-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}
/* 内边距用变量驱动：出血图的负 margin 必须跟着它走，
   否则哪天给窄屏单独改 padding，图就会比卡片窄出一条底色（本项目的既有教训）。 */
.gv-card{--gv-px:16px;--gv-pt:16px;
  cursor:pointer;padding:var(--gv-pt) var(--gv-px);display:flex;flex-direction:column;gap:7px;transition:.2s}
.gv-card:hover{border-color:rgba(var(--accentRGB),.42);transform:translateY(-2px)}
.gv-card-h{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.gv-card-h b{font-family:var(--serif);font-size:1.1333rem;letter-spacing:1px;color:var(--tx)}
/* 人文地理照片：卡片顶部出血横图（构建期抓取，见 build-images.js）。
   用负外边距把图顶到卡片边缘，视觉上才像「配图」而不是贴在文字上的小方块。 */
.gv-photo{margin:calc(-1 * var(--gv-pt)) calc(-1 * var(--gv-px)) 2px;height:112px;overflow:hidden;border-radius:16px 16px 0 0;background:var(--bg2)}
.gv-photo img{width:100%;height:100%;object-fit:cover;display:block}
/* ---- 地理数据库卡片（34 省级行政区 / 29 世界国家 / 73 处山河）----
   这一栏的卡片改成「照片 + 两三行要点」：照片承担「一眼认得这是哪儿」，
   完整档案（地形 / 气候 / 资源 / 历史 / 名篇）挪进详情弹窗。
   改之前每张卡片都是四五段小字（34+29+73 张全屏文字），一屏看下去认不出哪个是哪个。
   有图时把 .np 节点（= 只在无图时保留的补充文字）隐藏 ——
   节点始终由 geo-view.js 渲染，显隐交给这里，重绘时不需要两套模板。
   ★ .gv-photo 的负 margin 与圆角沿用上面那条，别在这里另写一份
     （写死 padding 会在窄屏单独改 padding 时露出卡片底色，本项目踩过）。 */
.gv-dbcard .gv-photo.lg{height:150px}
.gv-dbcard:not(.nopic) .np{display:none}
.gv-dbcard:not(.nopic) .gv-card-h b{font-size:1.2rem}
/* 无图条目（公开图库里确实没有可用照片的那几条，见 build-images.js 的 GEO_DB_SKIP）：
   给一层极淡的斜向底纹，让它看起来是「有意留白」，而不是「图没加载出来」。 */
.gv-dbcard.nopic{background-image:linear-gradient(145deg,rgba(var(--accentRGB),.06),rgba(var(--hlRGB),.015) 55%,transparent)}
.gv-picnote{margin-top:5px;font-size:0.7333rem}
.gv-d-photo{width:100%;max-height:220px;object-fit:cover;display:block;
  border-radius:12px;border:1px solid var(--line);background:var(--bg2);margin-bottom:14px}
/* 图说 · 署名：只有在后台给这张图填了才出现（见 photos.js 的 credit()）。
   配色只用各主题都定义过的变量，避免某套主题漏了变量时掉回深色兜底。
   margin-top 取负值把它贴到图片下沿 —— 图片本身有 14px 下边距，
   不改的话图说会飘在下一个字段的上方，看着像属于下一段。 */
.ph-credit{margin:-9px 0 14px;font-size:0.7333rem;line-height:1.7;color:var(--tx3);
  letter-spacing:.3px;text-align:right}
.lt-av{flex:0 0 34px;width:34px;height:34px;border-radius:9px;object-fit:cover;display:block;border:1px solid var(--line)}
.gv-short{font-size:0.7333rem;padding:1px 7px;border-radius:6px;color:var(--accent2);
  background:rgba(var(--accentRGB),.14);border:1px solid rgba(var(--accentRGB),.26)}
.gv-tag{font-size:0.7333rem;padding:1px 8px;border-radius:6px;letter-spacing:.5px;
  color:var(--jade);background:rgba(var(--jadeRGB),.1);border:1px solid rgba(var(--jadeRGB),.22)}
.gv-tag.blue{color:var(--blue);background:rgba(var(--blueRGB),.1);border-color:rgba(var(--blueRGB),.24)}
.gv-meta{font-size:0.8rem;color:var(--tx3);line-height:1.5}
.gv-spec{font-size:0.8333rem;color:var(--tx2);line-height:1.65}
.gv-pre{font-size:0.8rem;color:var(--tx3);line-height:1.65;border-top:1px dashed var(--line2);padding-top:8px}
/* 卡片上的名篇摘要：与「历史意义」摘要同一条虚线分隔，改用金色以示区别 */
.gv-lit{font-size:0.7667rem;color:var(--accent2);line-height:1.6;margin-top:-1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 上面这行是 nowrap。网格/弹性子项默认 min-width:auto，会按「最长的
   不换行内容」计算最小宽度，于是这一行会把整条轨道撑到容器以外 —— 表
   现为窄屏（≤320px）横向溢出，且省略号永远不出现。给所有网格子项显式
   归零最小宽度，让 overflow:hidden 真正生效，而不是靠内容恰好够短。 */
.lt-grid>*,.gv-grid>*,.gc-facts>*,.gc-factors>*,.gc-cmp-h>*,.gc-cmp-r>*,
.sp-levels>*,.sp-planets>*,.sp-earth>*,.sp-sun>*,.sp-impacts>*{min-width:0}
.lt-sec.lit .lt-sec-b{border-left:2px solid rgba(var(--accentRGB),.4);padding-left:11px;
  font-family:var(--serif);font-size:0.9333rem;line-height:2;letter-spacing:.2px}
.gv-block{margin-bottom:18px}
.gv-block-h{font-size:0.9333rem;letter-spacing:2px;color:var(--accent);margin-bottom:12px}
.gv-note{font-size:0.8333rem;color:var(--tx3);line-height:1.75;margin-top:10px;
  padding-left:10px;border-left:2px solid var(--line)}
.gv-chart{width:100%;height:auto;display:block}
.gv-links{display:flex;flex-direction:column;gap:10px}
.gv-link{background:var(--bg2);border:1px solid var(--line2);border-radius:11px;padding:11px 14px}
.gv-link-h{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;margin-bottom:5px}
.gv-link-h b{font-size:0.9rem;color:var(--accent2);font-family:var(--serif);letter-spacing:.5px}
.gv-link-h span{font-size:0.7667rem;color:var(--jade)}

/* ============================================================
   宇宙星球（地理探索的第 3 个页签）
   ------------------------------------------------------------
   这一栏的内容不是「条目」而是「知识点」，版式也跟着换一套：
   口诀条 → 四级台阶 → 行星人设卡 → 地球的条件 → 太阳的脾气 → 小挑战。
   ★ 行星卡左侧那道色条用的是**每颗行星自己的颜色**（--sp，由渲染时内联写上），
     所以这里不写死任何颜色：内联值优先级最高，主题切换也不会盖掉它。
   ============================================================ */
.sp-lead{background:linear-gradient(120deg,rgba(var(--accentRGB),.09),transparent 62%),var(--panel)}
.sp-lead-t{font-family:var(--serif);font-size:1.1667rem;letter-spacing:2px;color:var(--accent)}
.sp-lead-b{margin:10px 0 0;font-size:0.9rem;line-height:1.95;color:var(--tx2)}
.sp-hints{display:grid;gap:8px;margin-top:14px}
.sp-hint{display:flex;gap:9px;align-items:baseline;font-size:0.8333rem;line-height:1.85;color:var(--tx2);
  padding:9px 12px;border-radius:9px;border:1px dashed var(--line2);background:rgba(var(--accentRGB),.04)}
.sp-hint b{flex:0 0 auto;color:var(--accent2);font-weight:600;letter-spacing:1px}
.sp-sec{margin:26px 0 12px;font-family:var(--serif);font-size:1.0333rem;letter-spacing:2px;color:var(--jadeTx)}
.sp-sec:first-child{margin-top:0}

/* 天体系统四级台阶：宽屏并排四格，窄屏两格/一格 */
.sp-levels{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.sp-level{position:relative;padding:15px 14px;border-radius:12px;border:1px solid var(--line);
  background:rgba(var(--hlRGB),.03);min-width:0}
.sp-level-i{font-size:1.5rem;line-height:1}
.sp-level-n{margin-top:7px;font-size:0.9667rem;font-weight:600;color:var(--tx)}
.sp-level-n i{display:block;margin-top:2px;font-family:var(--sans);font-style:normal;
  font-size:0.7rem;letter-spacing:.6px;color:var(--tx3)}
.sp-level-s{margin-top:7px;font-size:0.7333rem;line-height:1.7;color:var(--accent2)}
.sp-level-d{margin-top:6px;font-size:0.8rem;line-height:1.85;color:var(--tx2)}
.sp-level-t{position:absolute;top:13px;right:13px;font-size:0.6667rem;letter-spacing:1px;color:var(--tx3)}

/* 八大行星人设卡 */
.sp-planets{display:grid;grid-template-columns:repeat(auto-fill,minmax(236px,1fr));gap:12px}
.sp-planet{position:relative;padding:15px 16px 15px 19px;overflow:hidden}
.sp-planet::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--sp,#8aa)}
.sp-p-h{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.sp-p-sym{display:inline-flex;align-items:center;justify-content:center;width:21px;height:21px;
  border-radius:50%;border:1px solid var(--sp,#8aa);color:var(--tx);font-size:0.8rem}
.sp-p-h b{font-family:var(--serif);font-size:1.1rem;letter-spacing:1px;color:var(--tx)}
.sp-p-en{font-size:0.7rem;letter-spacing:.5px;color:var(--tx3)}
.sp-p-cls{margin-left:auto}
.sp-p-tag{margin-top:8px;font-size:0.8333rem;color:var(--accent2);letter-spacing:.5px}
.sp-p-fact{margin-top:7px;font-size:0.82rem;line-height:1.9;color:var(--tx2)}
.sp-p-mem{margin-top:9px;padding-top:8px;border-top:1px dashed var(--line2);
  font-size:0.8rem;line-height:1.8;color:var(--tx3)}

/* 地球的两张安全牌 / 三份礼物 */
.sp-earth,.sp-sun{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px}
.sp-box-h{font-family:var(--serif);font-size:0.9667rem;letter-spacing:1.5px;color:var(--jadeTx);margin-bottom:10px}
.sp-li{display:flex;flex-direction:column;gap:3px;padding:9px 0;border-bottom:1px dashed var(--line2)}
.sp-li:last-child{border-bottom:none}
.sp-li b{font-size:0.8667rem;color:var(--tx)}
.sp-li span{font-size:0.8rem;line-height:1.85;color:var(--tx2)}
.sp-li-s b::before{content:"✦ ";color:var(--accent)}
.sp-note{margin-top:12px;padding:10px 13px;border-radius:9px;font-size:0.8rem;line-height:1.9;
  color:var(--tx2);background:rgba(var(--jadeRGB),.06);border:1px solid var(--line2)}
.sp-p{margin:0;font-size:0.8333rem;line-height:1.9;color:var(--tx2)}
.sp-cycle{margin-top:10px;padding-top:9px;border-top:1px dashed var(--line2);
  font-size:0.8rem;line-height:1.85;color:var(--accent2)}
.sp-table{width:100%;border-collapse:collapse;font-size:0.8rem}
.sp-table th,.sp-table td{text-align:left;padding:8px 8px 8px 0;vertical-align:top;
  border-bottom:1px dashed var(--line2);line-height:1.8}
.sp-table th{font-weight:600;color:var(--tx3);font-size:0.7667rem;letter-spacing:1px}
.sp-table td{color:var(--tx2)}
.sp-table td b{color:var(--tx)}
.sp-layer{display:inline-block;padding:1px 8px;border-radius:99px;font-size:0.7rem;
  color:var(--accent2);border:1px solid var(--line2);white-space:nowrap}
.sp-impacts{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:12px}
.sp-imp{padding:11px 12px;border-radius:10px;border:1px solid var(--line2);background:rgba(var(--hlRGB),.03)}
.sp-imp b{display:block;font-size:0.84rem;color:var(--accent2);margin-bottom:5px;letter-spacing:.5px}
.sp-imp span{font-size:0.78rem;line-height:1.8;color:var(--tx2)}

/* 记忆挑战 */
.sp-quiz{display:grid;gap:16px}
.sp-q{padding-bottom:14px;border-bottom:1px dashed var(--line2)}
.sp-q:last-child{padding-bottom:0;border-bottom:none}
.sp-q-t{font-size:0.9rem;color:var(--tx);margin-bottom:10px;line-height:1.8}
.sp-opts{display:flex;gap:8px;flex-wrap:wrap}
.sp-opt{padding:7px 15px;border-radius:99px;border:1px solid var(--line2);background:rgba(var(--hlRGB),.03);
  color:var(--tx2);font-size:0.8333rem;cursor:pointer;transition:.2s;user-select:none}
.sp-opt:hover{border-color:var(--line);color:var(--tx)}
/* 判分色是**固定语义色**（对/错），不跟主题的强调色走：
   换成主题强调色以后，答对与答错可能变成同一个颜色。 */
.sp-opt.on{border-color:rgba(var(--jadeRGB),.75);background:rgba(var(--jadeRGB),.14);color:var(--jadeTx);font-weight:600}
.sp-opt.bad{border-color:rgba(var(--redRGB),.7);background:rgba(var(--redRGB),.12);color:var(--red)}
.sp-why{margin-top:10px;font-size:0.8rem;line-height:1.9;padding:9px 12px;border-radius:9px;
  border:1px solid var(--line2);color:var(--tx2);background:rgba(var(--hlRGB),.03)}
.sp-why.ok{border-color:rgba(var(--jadeRGB),.5)}
.sp-why.no{border-color:rgba(var(--redRGB),.42)}
.gv-link-b{font-size:0.8333rem;color:var(--tx2);line-height:1.75}
.gv-monsoon{display:flex;flex-direction:column;gap:8px;margin:10px 0}
.gv-mstep{display:flex;gap:12px;align-items:baseline;background:var(--bg2);
  border:1px solid var(--line2);border-radius:10px;padding:9px 13px}
.gv-mstep b{flex:0 0 118px;font-size:0.8333rem;color:var(--accent);letter-spacing:.5px}
.gv-mstep span{font-size:0.8333rem;color:var(--tx2);line-height:1.6}
.gv-restypes{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.gv-restypes span{font-size:0.8rem;padding:3px 11px;border-radius:7px;color:var(--accent);
  background:rgba(var(--accentRGB),.09);border:1px solid rgba(var(--accentRGB),.22)}
.gv-map{width:100%;height:300px;border-radius:12px;border:1px solid var(--line2);
  background:var(--bg2);overflow:hidden}
.gv-maperr{height:100%;display:flex;align-items:center;justify-content:center;
  font-size:0.8667rem;color:var(--tx3);padding:20px;text-align:center;line-height:1.7}
.gv-modal{max-width:720px}

/* ============================================================
   多语言（i18n.js）：英文界面下的范围说明条
   讲清「哪些已双语、哪些仍是中文、为什么」，而不是假装已全站翻译。
   ============================================================ */
.i18n-scope{max-width:1320px;margin:12px auto 0;padding:11px 16px;border-radius:12px;
  font-size:0.8333rem;line-height:1.75;color:var(--tx2);
  background:rgba(var(--blueRGB),.09);border:1px solid rgba(var(--blueRGB),.26)}
.i18n-scope b{display:block;color:var(--blueTx);letter-spacing:1px;margin-bottom:3px;font-size:0.8333rem}

/* ============================================================
   人文地理（geo-culture-view.js）· 近现代作者（modern-view.js）
   ------------------------------------------------------------
   这里只写这两个文件特有的类；卡片、网格、筛选条直接复用
   geo-view / literature-view 已有的 .gv-* 与 .lt-*，避免三套外观。
   ============================================================ */
.gv-tag.gold{color:var(--accent2);background:rgba(var(--accentRGB),.12);border-color:rgba(var(--accentRGB),.3)}
/* 温度带/干湿区卡片是纯展示，不该有「可点开」的手感 */
.gv-card.gc-static,.gv-card.gc-static:hover{cursor:default;border-color:var(--line2);transform:none}

/* 口径与提示：常驻在每一栏底部，不折叠——读者最易误用的正是这几条 */
.gc-notes{margin-top:22px;padding:16px 18px;display:flex;flex-direction:column;gap:11px}
.gc-note{font-size:0.8rem;line-height:1.9;color:var(--tx3);display:flex;gap:9px;flex-wrap:wrap}
.gc-note b{color:var(--accent2);font-weight:700;flex:0 0 auto;letter-spacing:.5px}

/* 专章 / 气候栏的头块与要点表 */
.gc-hero .lt-hint{margin-bottom:0}
.gc-facts{margin-top:16px;display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:9px}
.gc-fact{display:flex;gap:9px;font-size:0.8333rem;line-height:1.75;padding:9px 12px;
  border-radius:9px;background:rgba(var(--hlRGB),.02);border:1px solid var(--line2)}
.gc-fact b{color:var(--accent2);flex:0 0 auto;min-width:62px}
.gc-fact span{color:var(--tx2)}

/* 「南方热北方冷」的四个因素 */
.gc-factors{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:13px;margin-top:16px}
.gc-factor{background:rgba(var(--hlRGB),.02);padding:15px 16px}
.gc-factor-h{font-size:0.9rem;letter-spacing:1.5px;color:var(--accent2);margin-bottom:8px;font-weight:700}
.gc-factor .lt-sec-b{font-size:0.8667rem;line-height:1.95}
.gc-factor-n{margin-top:9px;padding-top:8px;border-top:1px dashed var(--line2);font-size:0.7667rem}
.gc-caveat{margin-top:16px;color:var(--redTx);border-left:2px solid rgba(var(--redRGB),.55);
  background:rgba(var(--redRGB),.06);padding:11px 13px;border-radius:0 8px 8px 0}

/* 温度带 / 干湿区卡片底部补一行说明 */
.gc-band-note{font-size:0.7667rem;line-height:1.8;color:var(--tx3);margin-top:8px;
  padding-top:8px;border-top:1px dashed var(--line2)}

/* 大陆性气候的三个例子 */
.gc-examples{display:flex;flex-direction:column;gap:11px;margin-top:14px}
.gc-example{display:flex;flex-direction:column;gap:5px;font-size:0.8333rem;line-height:1.85;
  padding:12px 14px;border-radius:10px;background:rgba(var(--hlRGB),.02);border:1px solid var(--line2)}
.gc-example b{color:var(--accent2);font-size:0.8667rem;letter-spacing:.8px}
.gc-ex-fact{color:var(--tx2)}
.gc-ex-why{color:var(--tx3);border-left:2px solid var(--line);padding-left:10px}

/* 南北生活对照表 */
.gc-cmp{margin-top:14px;border:1px solid var(--line2);border-radius:11px;overflow:hidden}
.gc-cmp-h,.gc-cmp-r{display:grid;grid-template-columns:112px 1fr 1fr}
.gc-cmp-h{background:rgba(var(--accentRGB),.1);font-size:0.8rem;letter-spacing:1.5px;color:var(--accent2);font-weight:700}
.gc-cmp-h span,.gc-cmp-r span{padding:10px 13px}
.gc-cmp-r{border-top:1px solid var(--line2);font-size:0.8333rem;line-height:1.8;color:var(--tx2)}
.gc-cmp-r span:first-child{color:var(--tx3)}
.gc-cmp-r span+span{border-left:1px solid var(--line2)}

/* 专章小节正文 */
.gc-sec .gc-sec-b{font-size:0.9rem;line-height:2.05;color:var(--tx2)}
.gc-cmp-note .gc-sec-b{font-size:0.8667rem;line-height:2;color:var(--tx3)}

/* 相关地理事物的 chip：点开即跳到山川档案 */
.gc-chips{display:flex;gap:9px;flex-wrap:wrap;margin-top:13px}
.gc-chip{display:inline-flex;align-items:baseline;gap:7px;cursor:pointer;font-size:0.8667rem;
  padding:7px 14px;border-radius:99px;color:var(--jade);background:rgba(var(--jadeRGB),.08);
  border:1px solid rgba(var(--jadeRGB),.24);transition:.2s}
.gc-chip:hover{border-color:rgba(var(--jadeRGB),.5);color:var(--tx)}
.gc-chip i{font-style:normal;font-size:0.7rem;color:var(--tx3)}

/* 名篇行与跨模块按钮 */
.gc-lit-row{font-family:var(--serif);font-size:0.9333rem;line-height:2;color:var(--tx2)}
.gc-mt{margin-top:12px}

/* ============================================================
   专章「地图简介」（内蒙古 / 河南）—— 天地图静态地图
   ------------------------------------------------------------
   出图是 1024×576 的 PNG，按容器宽度等比缩放：宽高比用 aspect-ratio
   钉死，图片还没到时也不会让下面的文字跳一下（CLS）。
   ★ 不加 object-fit:cover：地图被裁掉边缘就会切掉省界与注记 ——
     这是"示意图"最不能犯的错。整幅contain进去，宁可留白。
   ============================================================ */
.gc-map .gc-mapfig{margin:2px 0 12px;border:1px solid var(--line);border-radius:12px;
  overflow:hidden;background:var(--bg2);aspect-ratio:1024/576}
.gc-map .gc-mapfig img{width:100%;height:100%;object-fit:contain;display:block}
/* 未启用 / 加载失败：同样占住 16:9，免得布局先塌再撑 */
.gc-map .gc-mapfig.off{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:7px;padding:18px 20px;text-align:center;
  background-image:linear-gradient(145deg,rgba(var(--accentRGB),.05),rgba(var(--hlRGB),.015) 60%,transparent)}
.gc-mapoff-t{font-family:var(--serif);font-size:1rem;letter-spacing:1px;color:var(--tx2)}
.gc-mapoff-b{font-size:0.8rem;line-height:1.85;color:var(--tx3);max-width:56ch}
.gc-mapread{margin-bottom:12px}
.gc-mapread-h{font-size:0.8rem;letter-spacing:1.5px;color:var(--accent);margin-bottom:8px}
.gc-mapread-li{position:relative;padding-left:16px;font-size:0.9rem;line-height:1.95;color:var(--tx2)}
.gc-mapread-li+.gc-mapread-li{margin-top:5px}
.gc-mapread-li::before{content:'·';position:absolute;left:4px;color:var(--accent2);font-weight:700}

/* 体裁简述条 */
.gc-brief{margin-bottom:14px;padding-left:10px;border-left:2px solid var(--line)}

/* 近现代作者：代表作 chips 与名句 */
.gc-reps{display:flex;gap:8px;flex-wrap:wrap}
.gc-rep{font-size:0.8333rem;padding:5px 12px;border-radius:99px;color:var(--accent2);
  background:rgba(var(--accentRGB),.09);border:1px solid rgba(var(--accentRGB),.24)}
.gc-quote{font-family:var(--serif);font-size:1.0333rem;line-height:2;color:var(--tx);letter-spacing:.4px}
.gc-quote-src{margin-top:8px;font-size:0.8rem;color:var(--tx3);text-align:right}

/* ============================================================
   党史页：按官方四个历史时期分组的重要会议卡片
   文字色一律走主题变量（--tx 正文 / --tx2 次要 / --tx3 更次 /
   --accent2 标签），不使用硬编码色，也不在正文上用 --accent
   ——强调色压在自己 12% 以上的薄纱上会掉到不达标。
   ============================================================ */
.party-intro{margin-bottom:18px}
.party-intro-t{font-size:0.9333rem;letter-spacing:2px;color:var(--accent2);margin-bottom:8px}
.party-intro-p{margin:0;font-size:0.8333rem;line-height:1.95;color:var(--tx2)}

.party-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.party-tabs .chip{padding:6px 14px}
.party-tabs .chip i{font-style:normal;font-size:0.7rem;color:var(--tx3);margin-left:6px}
.party-tabs .chip.on i{color:var(--accent2)}

/* ---------- 党史会议时间轴（从左至右） ----------
   横向铺开而不是竖排：党代会天然是一条「时间—转折」的线，
   横着读才看得出间隔与密度（建国前后密、中间稀），竖着只是一列条目。
   节点用四个时期的配色区分，鼠标悬停给全称，点击跳到下方对应卡片。 */
.party-tl{margin-bottom:18px;padding:16px 6px 10px;overflow-x:auto;overflow-y:hidden}
.party-tl-hd{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:0 12px;margin-bottom:6px}
.party-tl-hd b{font-size:0.8667rem;letter-spacing:2px;color:var(--accent2)}
.party-tl-hd span{font-size:0.7667rem;color:var(--tx3)}
.party-tl-rail{position:relative;display:flex;align-items:flex-start;min-width:max-content;padding:14px 12px 6px}
.party-tl-rail::before{content:'';position:absolute;left:12px;right:12px;top:22px;height:2px;
  background:linear-gradient(90deg,rgba(var(--accentRGB),.15),rgba(var(--accentRGB),.5),rgba(var(--accentRGB),.15))}
.party-tl-node{flex:0 0 auto;width:82px;text-align:center;cursor:pointer;position:relative;transition:.18s}
.party-tl-node:hover{transform:translateY(-2px)}
.party-tl-node .dot{width:11px;height:11px;border-radius:50%;margin:0 auto 7px;position:relative;z-index:1;
  border:2px solid var(--panel);box-shadow:0 0 0 2px rgba(var(--accentRGB),.28)}
.party-tl-node.on .dot{box-shadow:0 0 0 3px rgba(var(--accentRGB),.55)}
.party-tl-node .yr{font-size:0.7333rem;color:var(--tx3);letter-spacing:.5px}
.party-tl-node.on .yr{color:var(--accent2)}
.party-tl-node .nm{font-size:0.7rem;color:var(--tx3);line-height:1.5;margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.party-tl-node.on .nm{color:var(--tx)}
/* 四个历史时期配色：与「时期」语义挂钩，不另造一套随机色 */
.party-tl-node.pk-xmd .dot{background:var(--accent2)}
.party-tl-node.pk-jsj .dot{background:var(--jade)}
.party-tl-node.pk-ggk .dot{background:var(--blue,#5b8ff9)}
.party-tl-node.pk-xsd .dot{background:var(--gold,#d4a24c)}
.party-tl-empty{font-size:0.8333rem;color:var(--tx3);padding:0 12px}
/* 从时间轴跳过来时闪一下，否则页面一滚到底，用户不知道落在哪张卡片上 */
.pc-flash{animation:pcFlash 1.6s ease}
@keyframes pcFlash{0%{box-shadow:0 0 0 0 rgba(var(--accentRGB),.55)}100%{box-shadow:0 0 0 14px rgba(var(--accentRGB),0)}}
@media (max-width:640px){.party-tl-node{width:64px}.party-tl-node .nm{font-size:0.66rem}}

.party-list{display:grid;gap:14px}
.party-group{margin-top:8px;padding:14px 18px;border-radius:14px;
  border:1px solid var(--line2);background:rgba(var(--hlRGB),.04)}
.party-group-hd{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px}
.party-group-n{font-family:var(--serif);font-size:1.2rem;font-weight:700;
  letter-spacing:2px;color:var(--accent2)}
.party-group-s{font-size:0.7667rem;color:var(--tx3);letter-spacing:1px}
.party-group-d{margin:8px 0 0;font-size:0.8333rem;line-height:1.9;color:var(--tx2)}

/* 会议卡改成两列栅格：左列是标题与「时间/地点/出席」，右列放配图并跨这两行，
   下面的「主要内容 / 历史意义」通栏铺开。
   为什么用栅格、不用 float 或 absolute：配图高度要跟着标题 + 元信息的高度走，
   栅格的 align-self:stretch 天然做到自适应；float 会让图顶进「主要内容」里，
   absolute 则要写死高度，元信息一换行就穿帮。 */
.pc{padding:18px 20px;display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:22px}
.pc-hd,.pc-meta{grid-column:1}
.pc-key,.pc-sig{grid-column:1/-1}
.pc-hd{display:flex;align-items:baseline;justify-content:space-between;
  gap:12px;flex-wrap:wrap}
.pc-n{font-family:var(--serif);font-size:1.3333rem;font-weight:700;
  letter-spacing:2px;color:var(--tx)}
.pc-y{font-family:var(--serif);font-size:1.0667rem;
  letter-spacing:1px;color:var(--accent2)}

/* ---- 会议配图 ----
   「与周边的淡出」用 mask 做：左边与下边渐隐，让图软软地收进卡片底色。
   不要改成「叠一层背景色渐变」——那样会跟着主题底色走，换皮肤就露色带。

   尺寸（用户反馈「会议图片有点小」后放大）：206×104 → 320×176。
   放大前实测只占卡片宽的 18%（1440 档卡片 1143px），确实小到看不清会址门楼。
   ★ 两个尺寸必须**同比例**放，不能只改宽：
     框比 SVG(320×180) 更「扁」时，object-fit:cover 按宽铺满，
     可见的 SVG 横向范围 = [0.32×320, 320] = [102.4, 320] —— 与框的绝对尺寸无关；
     但一旦框的高宽比反超 SVG（宽高比 < 1.7778），cover 会改成按高铺满，
     横向映射整个变掉，五角星的左半边就会滑进左边那道渐隐里（不报错，就是看不见）。
     320/176 = 1.818、250/137 = 1.825，都留了 2% 以上余量。party-images.test.js
     里有一条按 CSS 复算这个宽高比的护栏，改尺寸时它会拦。 */
.pc-fig{grid-column:2;grid-row:1 / span 2;align-self:stretch;position:relative;
  margin:0;width:320px;min-height:176px}
.pc-fig-ph{position:absolute;inset:0;display:block;overflow:hidden;border-radius:12px;
  /* 两段 mask 取交集：Chrome/Safari 走 -webkit(源相入)，Firefox 走标准属性的 intersect。
     两者都不认时只是留下硬边，不会画错内容。 */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 32%),linear-gradient(0deg,transparent 0,#000 26%);
  -webkit-mask-composite:source-in;
  mask-image:linear-gradient(90deg,transparent 0,#000 32%),linear-gradient(0deg,transparent 0,#000 26%);
  mask-composite:intersect}
.pc-fig img{width:100%;height:100%;object-fit:cover;display:block}
/* 图注（第几次大会 + 年份）放在图的右下角——那是渐隐最弱的位置，字看得清。
   它是 .pc-fig-ph 的兄弟而不是子元素，所以不会被 mask 一起淡掉。
   ⚠️ 底色必须用 --panel 这种「不透明面板色」，不能用 --hlRGB 半透明叠加：
   --hlRGB 在浅色主题里是一枚深墨色（拿它做 4% 淡染是对的，做 86% 实心就得到
   近黑底 + 近黑字，图注直接看不见了）。--panel/--tx 本来就是主题里成对定义的一对，
   对比度由主题自己保证。 */
.pc-fig-cap{position:absolute;right:2px;bottom:2px;display:flex;align-items:baseline;gap:6px;
  padding:3px 9px;border-radius:99px;border:1px solid var(--line);
  background:var(--panel);box-shadow:0 1px 6px rgba(0,0,0,.14)}
.pc-fig-cap b{font-family:var(--serif);font-size:0.8rem;font-weight:700;letter-spacing:1px;color:var(--tx)}
.pc-fig-cap i{font-style:normal;font-size:0.7rem;letter-spacing:1px;color:var(--accent2)}
/* 标识图的「示意图」角标：如实告知这不是现场照片 */
.pc-fig-sig{position:absolute;left:26%;top:5px;font-size:0.6333rem;letter-spacing:1px;
  color:var(--tx3);border:1px solid var(--line2);border-radius:4px;padding:0 5px;
  background:var(--panel);opacity:.88}

/* 时间/地点/出席：用 flex + min-width 让长文本自然换行，
   而不是把某个字段挤成竖排单字 */
.pc-meta{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:10px}
.pc-m{font-size:0.8rem;line-height:1.75;color:var(--tx2);flex:1 1 200px;min-width:0}
.pc-m b{font-weight:400;color:var(--tx3);margin-right:6px;letter-spacing:1px}

.pc-key{margin-top:14px}
.pc-lab{display:inline-block;font-size:0.7333rem;letter-spacing:2px;
  color:var(--accent2);border:1px solid var(--line);border-radius:99px;padding:2px 10px}
.pc-key ul{margin:10px 0 0;padding:0;list-style:none}
.pc-key li{position:relative;padding-left:1.1rem;
  font-size:0.8667rem;line-height:1.95;color:var(--tx);margin-bottom:5px}
.pc-key li::before{content:"◆";position:absolute;left:0;top:0;
  color:var(--accent);font-size:0.6rem;line-height:2.6}

.pc-sig{margin-top:14px;padding-top:12px;border-top:1px dashed var(--line2);
  font-size:0.8667rem;line-height:1.95;color:var(--tx2)}
.pc-sig .pc-lab{margin-right:10px}

@media (max-width:900px){
  .pc{column-gap:16px}
  /* 与基础档同比例缩小（320×176 × 0.781）——只缩宽不缩高会破坏 cover 的映射 */
  .pc-fig{width:250px;min-height:137px}
}
@media (max-width:640px){
  /* 单列：配图提到最上面通栏。渐隐方向随之翻过来——只淡下边，
     否则通栏图会被左边缘的渐隐吃掉一大块内容。 */
  .pc{padding:15px 15px;grid-template-columns:minmax(0,1fr);column-gap:0;row-gap:0}
  /* ★ 高度不能写死成 124px，要用宽高比。
     通栏后框很宽，object-fit:cover 只保留中间一条横带；框越扁，裁掉的上下越多。
     写死 124px 时可见的 SVG 纵向范围随屏宽变化：
       360 宽 → y∈[25.6,120.9]（五角星 y∈[24,107.2]，勉强）
       414 宽 → y∈[34.6,116.6]（星的顶尖被削掉一截）
       640 宽 → 更扁，削得更多
     改成固定宽高比后，裁切量与屏宽无关，恒为 y0 = 90 − 160×(h/w)。
     h/w = 1/2.5 = 0.4 → y0 = 26，星只被削掉约 2 个 SVG 单位（≈1px），肉眼不可见；
     顺带这一档的图也真的变大了（360 宽仍是 ~123px，414 宽 143px，640 宽 230px）。 */
  .pc-fig{grid-column:1;grid-row:1;width:100%;height:auto;aspect-ratio:2.5;
    align-self:start;min-height:0;margin-bottom:12px}
  .pc-fig-ph{-webkit-mask-image:linear-gradient(0deg,transparent 0,#000 24%);
    -webkit-mask-composite:source-over;
    mask-image:linear-gradient(0deg,transparent 0,#000 24%);
    mask-composite:add}
  .pc-fig-sig{left:6px}
  .pc-n{font-size:1.2rem}
  .pc-m{flex:1 1 100%}
  .pc-key li,.pc-sig{font-size:0.8333rem}
}

/* ============================================================
   作品库（天下诗文 · 第三个页签）
   ------------------------------------------------------------
   配色一律只用 --tx / --tx2 / --tx3 / --line / --line2 / --accent /
   --accent2 / --accentRGB / --jade / --blue / --redTx 这些在每一套主题里
   都有定义的变量。主题测试卡死了变量键集合，「某套主题少一个变量就掉回
   :root 深色兜底」这类问题不会在这里发生。
   ============================================================ */
.wl-bar{display:flex;gap:9px;flex-wrap:wrap;align-items:center}
.wl-count{font-size:0.8rem;color:var(--tx2);line-height:1.7}
.wl-count b{color:var(--accent2)}
.wl-types{display:flex;gap:6px;flex-wrap:wrap;margin-top:14px}
.wl-chip{font-size:0.8rem;padding:5px 13px;border-radius:99px;cursor:pointer;transition:.2s;
  border:1px solid var(--line2);color:var(--tx2)}
.wl-chip b{font-weight:400;color:var(--tx3);margin-left:3px}
.wl-chip:hover{color:var(--accent2);border-color:rgba(var(--accentRGB),.4)}
.wl-chip.on{background:var(--btnGrad);border-color:transparent;color:var(--onAccent);font-weight:700}
.wl-chip.on b{color:var(--onAccent);opacity:.75}

/* grid-auto-rows:1fr —— 让**每一行**等高（隐式轨道按 1fr 分配，取内容最高的那行）。
   原先没写，行高由各行自己最高的那张卡决定，于是行与行之间高低不一，
   加上卡片内部是 flex 纵向排布，视觉上就是「有的长、有的短」（用户反馈的问题）。
   行内等高之外还要把内容截断（见下面 .wl-t/.wl-sub/.wl-b 的 line-clamp），
   否则一条超长摘要把整页所有行都撑高。完整内容点开详情看，卡片只做索引。 */
.wl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(272px,1fr));
  grid-auto-rows:1fr;gap:13px;margin-top:18px}
/* 列表视图：同一块 #wl-grid 换个排法。
   不改容器的 display，只加一个修饰类 —— 容器 id 与类名都被测试与
   「切页后回到列表顶部」的滚动逻辑依赖，换元素会一起坏掉。 */
.wl-grid.as-list{display:block;margin-top:0}
.wl-table{width:100%;border-collapse:collapse;table-layout:fixed;
  font-size:0.8667rem;color:var(--tx)}
/* 固定布局 + 每格 ellipsis：四列在 320px 上也不会横向溢出（这是本页最容易翻车的地方）。
   序号/作者/年代给固定宽度，作品名称吃掉剩余的全部宽度。 */
/* 表头不做 sticky：本页的滚动容器是整页，sticky 会滑到固定页头下面去，
   而页头是 backdrop-filter 的层 —— 两者的层叠关系在不同宽度下会打架。 */
.wl-table th{text-align:left;font-weight:400;font-size:0.7667rem;letter-spacing:1.5px;
  color:var(--tx2);padding:9px 10px;border-bottom:1px solid var(--line);
  background:rgba(var(--accentRGB),.05)}
/* 表头不换行：窄屏（≤480）时「序号」两个字会被挤成上下两行，
   整行表头跟着变高，看上去像排版坏了。各档的 .wl-no 宽度已按「序号」
   两个字 + 内边距算过（见 responsive.css），所以 nowrap 不会被裁。 */
.wl-table th{white-space:nowrap}
.wl-table td{padding:9px 10px;border-bottom:1px dashed var(--line2);
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis;vertical-align:middle}
.wl-row{cursor:pointer;transition:.18s}
.wl-row:hover{background:rgba(var(--accentRGB),.07)}
.wl-row:hover .wl-name{color:var(--accent2)}
.wl-table .wl-no{width:3.6rem;color:var(--tx3);font-variant-numeric:tabular-nums}
.wl-table .wl-au{width:11rem;color:var(--tx2)}
.wl-table .wl-yr{width:9.5rem;color:var(--tx2)}
.wl-name{font-family:var(--serif);letter-spacing:.5px}
/* 名称列里的角标跟着文字排，不与省略号打架 */
.wl-name .wl-flag{margin-left:7px;vertical-align:1px}
/* 页容量的下拉：与筛选条里的 .sel 同一副样式，只是窄一点 */
#wl-size{min-width:8.5rem}

/* 显示样式 + 每页条数的小工具条。放在网格上方，与筛选条分开 ——
   筛选条管「看哪些」，这条管「怎么看」，混在一排会以为是同一种筛选。 */
.wl-viewbar{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:18px;
  font-size:0.8rem;color:var(--tx2)}
.wl-vb-l{letter-spacing:1px}
.wl-vb-seg{display:inline-flex;padding:3px;border-radius:10px;
  border:1px solid var(--line);background:var(--bg2)}
.wl-vb-b{padding:5px 15px;border-radius:8px;cursor:pointer;font-family:inherit;
  font-size:0.8rem;letter-spacing:1px;color:var(--tx2);border:0;background:transparent;transition:.2s}
.wl-vb-b:hover{color:var(--accent2)}
.wl-vb-b.on{color:var(--onAccent);background:var(--btnGrad);font-weight:700}
/* 页码条复用学习中心的 .qz-pager 组件（见上方定义），只补一条：
   列表视图下它上方没有网格的 margin，需要自己留出间距。 */
.wl-pager{margin-top:18px}
.wl-card{cursor:pointer;transition:.22s;padding:14px 16px;display:flex;flex-direction:column;gap:6px;
  min-width:0;min-height:0}
.wl-card:hover{transform:translateY(-3px);border-color:rgba(var(--accentRGB),.42)}
/* 三处行数上限：卡片宽度由 grid 决定、高度由 grid-auto-rows:1fr 对齐，
   能变的只剩文字长度 —— 不截断就会有卡片"长"出来，把一个行抬高。
   行数按「标题 2 行 + 副题 2 行 + 正文 4 行」定，正好排满一张 272px 宽卡的可用高度；
   -webkit-box 是 line-clamp 的必要条件，Chrome/Edge/Safari 与新版 Firefox 都支持。 */
.wl-t{font-family:var(--serif);font-size:1.0667rem;font-weight:600;letter-spacing:1px;color:var(--tx);
  overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.wl-sub{font-size:0.7333rem;color:var(--tx3);line-height:1.6;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.wl-b{font-size:0.8rem;color:var(--tx2);line-height:1.8;flex:1;
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}

/* ---- 全站内容卡片：行高对齐（用户要求「作品卡片长宽要一致，其他页面也一样」）----
   卡片宽度由各网格的 minmax() 决定，本来就是齐的；不齐的是**高度** ——
   隐式行轨道默认按内容撑高，于是同一行里摘要长短不同的卡片高矮不一，
   一行一个高度，看上去就是「有的长有的短」。
   统一加一条 grid-auto-rows:1fr：每行按该行最高的那张卡取齐（fr 分布取最大值），
   行与行之间也一致。配合各卡片自己的 line-clamp 截断（如上面的 .wl-*），
   就不会再出现「一条超长摘要把整页所有行都撑高」。
   放这一处而不是逐个改前面那几个定义：位置在后面、特异度相同，天然压得住。 */
.lt-grid,.tb-grid,.gv-grid,.fig-grid,.film-grid,.topic-grid,.home-life{grid-auto-rows:1fr}
.wl-foot{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:2px}
.wl-tag{font-size:0.6667rem;padding:1px 9px;border-radius:99px;letter-spacing:.5px;
  color:var(--accent);border:1px solid var(--line)}
.wl-flag{font-size:0.6333rem;padding:1px 7px;border-radius:99px;letter-spacing:.5px;
  color:var(--jade);border:1px solid rgba(var(--jadeRGB),.42);background:rgba(var(--jadeRGB),.09)}
.wl-flag.book{color:var(--redTx);border-color:rgba(var(--redRGB),.42);background:rgba(var(--redRGB),.09)}
.wl-flag.own{color:var(--blue);border-color:rgba(var(--blueRGB),.42);background:rgba(var(--blueRGB),.09)}
.wl-empty{grid-column:1/-1;font-size:0.8333rem;color:var(--tx3);line-height:2;padding:14px 0}

/* ============================================================
   作品库 · 书画名作的图（photos.js 的 works 组）
   ------------------------------------------------------------
   这一组与其它素材组的根本区别：**图保持原比例、不裁**（竖轴是竖的、
   长卷是横的）。所以一律 contain 摆进画框，绝不用 .poster 那套 cover 出血 ——
   把 32:1 的《清明上河图》按 3:2 裁，卡上只剩中间几个百分点。
   画框底色用 --bg2（比卡片深一档）：浅色纸本与大片留白才看得出边界在哪。
   只用各主题都定义过的变量（theme.test.js 会卡 var() 有没有定义）。
   ============================================================ */
.wl-fig{aspect-ratio:3/2;margin:0 -16px 4px;border-radius:15px 15px 0 0;
  background:var(--bg2);border-bottom:1px solid var(--line2);position:relative;
  display:flex;align-items:center;justify-content:center;overflow:hidden}
.wl-fig img{max-width:100%;max-height:100%;width:auto;height:auto;display:block}
/* 手卷（长宽比 > 4:1）：3:2 画框里按 contain 摆只有几像素高，等于没画。
   改成按画框高度铺满、两端自然裁掉 —— 卡上看到的是长卷中间的一段，
   与美术馆的缩略图一个道理（「是哪一版、是局部」由图说交代）。
   ★ 必须**脱离文档流**（position:absolute）。原先写成 in-flow 的 flex 项：
   图片 `max-width:none` 后自然宽 1920，作为 flex 项它的 min-width:auto = 1920，
   于是整条 grid 轨道的 min-content 也变成 1920 —— `.wl-grid` 的
   `minmax(272px,1fr)` 撑不住，卡片被拉到 1920 宽，
   320px 窄屏上页面横向溢出 1607px（`.wl-fig` 自己的 overflow:hidden 只裁**画**，
   裁不掉这个盒子宽度）。绝对定位后它对固有尺寸的贡献是 0。
   left:50% + translateX(-50%) = 取长卷的正中间那一段。 */
.wl-fig img.art-wide{position:absolute;left:50%;top:0;height:100%;width:auto;
  max-width:none;max-height:100%;transform:translateX(-50%)}
/* 有图的卡片不留上内边距，让画框顶到卡片边缘 —— 出血图外面再套一圈白边会显得脏 */
.wl-card.has-art{padding-top:0}

/* 详情里的图：给足高度看细节，但不撑破弹窗（竖轴可到 60vh，长卷自然是一条横带） */
.wk-art{margin:12px 0 2px;text-align:center}
.wk-art img{max-width:100%;max-height:60vh;width:auto;height:auto;display:block;margin:0 auto;
  border-radius:8px;border:1px solid var(--line);background:var(--bg2)}
/* 手卷在详情里**横向展开**：按原始像素铺开（3000 长边），容器横向滚动 ——
   读起来就是「把卷子一点点卷开」，也是手卷本来该有的看法。
   按 contain 摆成一条 27px 高的横线，等于把最重要的细节全抹平了。 */
.wk-art.is-wide{overflow-x:auto;overflow-y:hidden;text-align:left}
.wk-art img.art-wide{max-width:none;max-height:none;margin:0;border-radius:6px;cursor:grab}
.wk-art-cap{font-size:0.7333rem;line-height:1.85;color:var(--tx3);margin-top:8px;text-align:left}
.wk-art-l{margin-top:4px}
.wk-art-l a{color:var(--accent2);text-decoration:none;border-bottom:1px dotted var(--line)}
.wk-art-l a:hover{color:var(--accent)}

.wl-mine{margin-top:18px}
.wl-mine-hd{font-size:0.8rem;letter-spacing:3px;color:var(--accent);margin-bottom:7px}
.wl-mine-note{font-size:0.8rem;color:var(--tx3);line-height:1.9;margin-bottom:10px}
.wl-form{display:flex;gap:8px;flex-wrap:wrap}
.wl-preview{margin-top:9px;display:flex;gap:5px;flex-wrap:wrap}
.wl-mine-row{display:flex;gap:10px;align-items:center;padding:8px 0;border-bottom:1px dashed var(--line2)}
.wl-mine-row:last-child{border-bottom:0}
.wl-same{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
.wl-mini{font-size:0.7667rem;padding:3px 10px;border-radius:99px;cursor:pointer;transition:.2s;
  border:1px solid var(--line2);color:var(--tx2)}
.wl-mini:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.wl-mini.off{cursor:default;opacity:.6}

/* ============================================================
   作品库 · 国别标签 / 来源名片 / 站内全文阅读器
   ------------------------------------------------------------
   只用各主题都定义过的变量（--tx/--tx2/--tx3/--line/--line2/--bg2/--panel/
   --accent/--accent2/--accentRGB/--jade/--jadeRGB）。
   theme.test.js 会检查 var() 是否都有定义，漏一个就会掉回 :root 深色兜底。
   ============================================================ */
/* 域外作品的国别标签：比体裁标签弱一档，避免卡片底部一排同权重标签 */
.wl-tag.nt{color:var(--tx3);border-color:var(--line2);background:transparent}
.wl-flag.full{color:var(--jade);border-color:rgba(var(--jadeRGB),.46);background:rgba(var(--jadeRGB),.1)}

/* 来源名片：一行一张，左边来源名（一眼看出是哪家），右边域名（核对用） */
.wl-src-list{margin-top:8px;display:flex;flex-direction:column;gap:5px}
.wl-src{display:flex;align-items:baseline;gap:10px;text-decoration:none;transition:.2s;
  padding:5px 10px;border-radius:9px;border:1px solid var(--line2);background:var(--bg2)}
.wl-src:hover{border-color:rgba(var(--accentRGB),.45)}
.wl-src .nm{font-size:0.8rem;color:var(--accent2);flex:0 0 auto}
.wl-src .hs{font-size:0.7333rem;color:var(--tx3);word-break:break-all}

/* 站内全文阅读器 */
.wl-full{margin-top:18px;border:1px solid var(--line2);border-radius:14px;background:var(--bg2);overflow:hidden}
.wl-full-hd{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;
  padding:11px 14px;border-bottom:1px solid var(--line2);
  font-size:0.8rem;letter-spacing:3px;color:var(--accent)}
.wl-full-src{font-size:0.7333rem;letter-spacing:0;color:var(--tx3)}
.wl-full-src a{color:var(--accent2);text-decoration:none}
/* 回目目录：横向滚动条带，点多回的书（一百二十回）不占竖向空间
   —— 这条样式保留给「没有分列」的窄屏兜底（见 responsive.css 的 ≤860 段） */
.wl-full-nav{display:flex;gap:5px;overflow-x:auto;padding:10px 14px;
  border-bottom:1px solid var(--line2);background:var(--panel)}
.wl-chap{flex:0 0 auto;font-size:0.7333rem;padding:3px 9px;border-radius:99px;cursor:pointer;
  white-space:nowrap;color:var(--tx2);border:1px solid var(--line2);background:transparent;transition:.18s}
.wl-chap:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.wl-chap.on{color:var(--accent2);border-color:rgba(var(--accentRGB),.55);background:rgba(var(--accentRGB),.12)}

/* ---------- 合集阅读器：左目录（可搜索）/ 右正文 ----------
   合集动辄 300+ 首，顶上一条横向回目带翻到第 180 首要先横拖很久，
   也没法按篇名去找。改成两列：左边是能滚能搜的目录，右边是正文。
   列宽写死 244px 而不是 1fr，是为了让正文的每行字数稳定 ——
   行宽随窗口变化时，同一首诗在不同屏幕上折行位置全都不同，读起来很碎。 */
.wl-full-main{display:grid;grid-template-columns:244px minmax(0,1fr)}
.wl-toc{display:flex;flex-direction:column;min-width:0;
  border-right:1px solid var(--line2);background:var(--panel)}
.wl-toc-hd{display:flex;align-items:center;gap:8px;padding:9px 11px;border-bottom:1px solid var(--line2)}
.wl-toc-kw{flex:1;min-width:0;background:var(--bg2);border:1px solid var(--line2);border-radius:8px;
  padding:5px 9px;font-size:0.7333rem;color:var(--tx);outline:none;font-family:inherit}
.wl-toc-kw:focus{border-color:rgba(var(--accentRGB),.5)}
.wl-toc-kw::placeholder{color:var(--tx3)}
.wl-toc-n{flex:0 0 auto;font-size:0.6667rem;color:var(--tx3);letter-spacing:.5px}
/* 目录改成纵向列表后，靠 max-height 滚动（原先的 overflow-x 横滚条不再需要，
   但 .wl-full-nav 这个类被兜底样式复用，这里只覆盖方向，不删原规则） */
.wl-toc .wl-full-nav{flex-direction:column;overflow-x:hidden;overflow-y:auto;
  max-height:46vh;gap:1px;padding:7px 7px 12px;border-bottom:none;background:transparent}
.wl-toc .wl-chap{display:flex;align-items:baseline;gap:7px;width:100%;flex:0 0 auto;
  border:1px solid transparent;border-radius:8px;padding:5px 8px;white-space:normal;line-height:1.5}
.wl-toc .wl-chap-no{flex:0 0 auto;font-style:normal;font-size:0.6667rem;color:var(--tx3);
  min-width:1.9em;text-align:right;font-variant-numeric:tabular-nums}
.wl-toc .wl-chap b{flex:1;min-width:0;font-weight:400;overflow-wrap:anywhere}
.wl-toc .wl-chap em{flex:0 0 auto;font-style:normal;font-size:0.6667rem;color:var(--tx3)}
.wl-toc .wl-chap.on{background:rgba(var(--accentRGB),.12);border-color:rgba(var(--accentRGB),.45)}
.wl-toc .wl-chap.on .wl-chap-no{color:var(--accent2)}
.wl-toc .wl-chap mark{background:rgba(var(--accentRGB),.28);color:inherit;border-radius:3px;padding:0 1px}
.wl-toc .wl-part{position:sticky;top:0;z-index:1;background:var(--panel);padding:6px 8px 3px}
.wl-toc-empty{font-size:0.7333rem;color:var(--tx3);line-height:1.9;padding:10px 8px}
.wl-full-read{display:flex;flex-direction:column;min-width:0}
.wl-read-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:8px 14px;border-bottom:1px solid var(--line2);background:var(--bg2)}
.wl-read-tip{font-size:0.6667rem;color:var(--tx3);letter-spacing:0}
.wl-full-body{max-height:52vh;overflow-y:auto;padding:16px 18px}
.wl-chap-t{font-family:var(--serif);font-size:1rem;letter-spacing:1.5px;color:var(--tx);
  margin:0 0 12px;padding-bottom:9px;border-bottom:1px dashed var(--line2)}
.wl-p{font-family:var(--serif);font-size:0.9rem;line-height:2.15;color:var(--tx);margin:0 0 12px;text-align:justify}
.wl-p-t{font-family:var(--serif);font-size:0.9333rem;letter-spacing:2px;color:var(--accent2);
  margin:20px 0 9px;padding-left:9px;border-left:2px solid rgba(var(--accentRGB),.5)}
.wl-p-t:first-of-type{margin-top:8px}
.wl-full-load{font-size:0.8rem;color:var(--tx3);line-height:2}
.wl-full-foot{display:flex;gap:10px;align-items:center;justify-content:center;
  padding:11px 14px;border-top:1px solid var(--line2);background:var(--panel)}
.wl-full-pos{font-size:0.8rem;color:var(--tx3);letter-spacing:1px}
/* 选本（唐诗三百首 / 宋词三百首 / 全元曲）的体裁部类小标题
   （五言古诗 / 乐府 / 七言律诗…）。目录已改为左栏纵向列表，不再需要换行 */
.wl-part{font-size:0.7333rem;letter-spacing:2px;color:var(--accent);margin:7px 0 2px}
.wl-part:first-child{margin-top:0}
/* 选本单首的位置提示 + 「收录于哪一本」 */
.wl-full-at{color:var(--accent2);letter-spacing:0}
.wl-full-sub{font-size:0.7667rem;color:var(--tx3);letter-spacing:1px;margin:-6px 0 12px}
.wl-belongs{margin-top:12px;font-size:0.8rem;color:var(--tx3)}

/* ============================================================
   读史要略（#readhistory）
   ------------------------------------------------------------
   这一页有两层，样式上也要能一眼分开：
     · 「其人其书」= 书目导览卡（.rh-book）——单独一卡，讲清不含原书正文；
     · 「阅读正文」= 板块 + 篇目列表（.rh-era / .rh-list-card）——正文层。
   颜色一律走主题变量（--tx/--tx2/--tx3/--accent2/--line*），
   不要写死颜色：多套主题里写死一种，浅色主题上就是「字在、看不见」。
   ============================================================ */
/* 板块之间的垂直间距。
   这一页的板块全是这两个容器的**直接子级**：
     #rh-pane → .card.rh-intro / .card.rh-book / #rh-body
     #rh-body → .card.rh-era / .card.rh-list-card / .card.rh-rel
   而 .card 自己没有外边距（全站只有 .map-side .card 和 a11y 慢速模式才加 margin-bottom），
   所以 display:block 时它们严丝合缝贴在一起，看着像一整块，层次全丢。
   （用户截图反馈「版块间贴合着了」；实测相邻间距 0—1px，5 张卡全部贴死。）
   ★ 用 grid+gap 而不是给 .card 补 margin-bottom：.card 全站都在用，
     加了会漏进那些已经用 gap 排好的网格里（.fig-grid / .film-grid / .gv-grid …），
     在网格项之间又叠一层 margin，行距就会莫名变宽。 */
#rh-pane,#rh-body{display:grid;gap:18px;align-content:start}

.rh-intro{padding:16px 20px}
.rh-intro-t{font-family:var(--serif);font-size:1rem;letter-spacing:2px;color:var(--accent2);margin-bottom:8px}
.rh-intro-p{margin:0;font-size:0.8333rem;line-height:1.95;color:var(--tx2)}

/* ---------- 其人其书 ---------- */
.rh-book{padding:20px 22px}
.rh-book-t{font-family:var(--serif);font-size:1.1333rem;font-weight:700;letter-spacing:2px;
  color:var(--accent2);margin-bottom:14px}
.rh-book-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px}
.rh-col{min-width:0}
.rh-au-name{font-family:var(--serif);font-size:1.2667rem;letter-spacing:2px;color:var(--tx);
  display:flex;align-items:baseline;gap:10px;margin:6px 0 4px}
.rh-au-name i{font-family:var(--sans);font-style:normal;font-size:0.7667rem;
  letter-spacing:2px;color:var(--tx3);text-transform:uppercase}
.rh-au-meta{font-size:0.8rem;color:var(--tx3);letter-spacing:1px;margin-bottom:10px}
.rh-au-bio{margin:0;padding:0;list-style:none}
.rh-au-bio li{position:relative;padding-left:1.1rem;font-size:0.8333rem;line-height:1.95;
  color:var(--tx2);margin-bottom:4px}
.rh-au-bio li::before{content:"·";position:absolute;left:2px;top:0;color:var(--accent)}

/* ---------- 作者照 + 题赠本：摆在「作者小传」这一列右侧的空白里 ----------
   小传的文字只占左半列，右边一大片是空的，作者照就放这儿（用户截图圈的位置）。
   摆法是**左文右图两列**（.rh-au 是 grid），不是把 <img> 插进文字流：
   小传有 4 条、每条一两行，图插进去换行位置会随图高矮漂移，窄屏还得清浮动。
   ★ 图宽 176px（与截图里圈出的框同宽），2 倍图 352px 由
     server/tools/build-read-history-images.js 生成 —— 改这里要同步改那个工具的 SPEC，
     read-history.test.js 里有一条「CSS 宽高比 vs 生成图实际宽高比」的复算护栏。 */
.rh-au{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;align-items:start}
/* 有照片时右列 176px，并在**整块右边**留 26px 呼吸位：
   照片紧贴书目信息栏时两栏挤成一条缝，用户圈出的位置也明显偏左。
   padding 加在 grid 容器上，右列的右边界就整体内收 26px。 */
.rh-au.has-fig{grid-template-columns:minmax(0,1fr) 176px;padding-right:26px}
.rh-au-main{min-width:0}
.rh-au-figs{display:grid;gap:12px}
.rh-fig{margin:0}
/* 图注放在图的**下方**，不压在图上叠字：人像照图上没有稳定的低对比区，
   压字不是糊脸就是糊到背景里。 */
.rh-fig-cap{margin-top:6px;font-size:0.7rem;line-height:1.7;color:var(--tx3);letter-spacing:0.5px}
.rh-fig img{display:block;width:100%;height:auto;border-radius:10px;
  border:1px solid var(--line2);background:var(--panel2);object-fit:cover}
/* ★ 宽高比必须与生成图一致。写错不报错，只会让 cover 多裁一块
   （作者照被裁成一条横带、脸只剩半张），属于「图在、内容不在」那类静默缺陷。
   这里是横长比 176:150，按站主圈出的框定；改这一行必须同步改
   server/tools/build-read-history-images.js 的 SPEC。 */
.rh-fig-portrait img{aspect-ratio:176/150}

.rh-works{display:flex;flex-wrap:wrap;gap:6px}
.rh-work{font-size:0.7667rem;line-height:1.7;padding:3px 10px;border-radius:8px;
  border:1px solid var(--line2);color:var(--tx2)}
.rh-rows{display:grid;gap:1px;background:var(--line2);border:1px solid var(--line2);border-radius:10px;overflow:hidden}
.rh-row{display:flex;gap:12px;background:var(--panel);padding:8px 12px}
.rh-lab{flex:0 0 5.2rem;font-size:0.7667rem;letter-spacing:1px;color:var(--tx3);line-height:1.85}
.rh-val{flex:1 1 auto;min-width:0;font-size:0.8333rem;line-height:1.85;color:var(--tx);word-break:break-word}
.rh-note{margin-top:14px;padding:12px 14px;border-radius:10px;
  border:1px solid var(--line2);background:rgba(var(--hlRGB),.04)}
.rh-note-h{font-size:0.7667rem;letter-spacing:2px;color:var(--accent2);margin-bottom:6px}
.rh-note p{margin:0;font-size:0.8rem;line-height:1.95;color:var(--tx2)}
/* 版权说明要显眼但不刺眼：用强调色左边线提示，不整块染红（红在浅色主题上会糊成一片） */
.rh-warn{border-color:rgba(var(--accentRGB),.35);border-left:3px solid var(--accent)}
.rh-howto{margin:0;padding-left:1.2rem}
.rh-howto li{font-size:0.8rem;line-height:1.95;color:var(--tx2);margin-bottom:3px}
.rh-src{margin:8px 0 0;font-size:0.7333rem;line-height:1.8;color:var(--tx3)}

/* ---------- 板块 ---------- */
.rh-era{padding:18px 20px}
.rh-eras-tabs{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px}
.rh-eras-tabs .chip i{font-style:normal;font-size:0.7rem;color:var(--tx3);margin-left:6px}
.rh-eras-tabs .chip.on i{color:var(--accent2)}
.rh-era-hd{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 14px;margin:18px 0 0}
.rh-era-hd b{font-family:var(--serif);font-size:1.2rem;letter-spacing:2px;color:var(--accent2)}
.rh-era-hd span{font-size:0.7667rem;color:var(--tx3);letter-spacing:1px}
.rh-era-d{margin:8px 0 0;font-size:0.8333rem;line-height:1.95;color:var(--tx2)}
.rh-must{margin-top:14px;padding:12px 14px;border-radius:10px;
  border:1px dashed var(--line2);background:rgba(var(--accentRGB),.04)}
.rh-must-lb{display:block;font-size:0.7333rem;letter-spacing:2px;color:var(--accent2);margin-bottom:8px}
.rh-must-list{display:flex;flex-wrap:wrap;gap:7px}
.rh-must-chip{display:inline-flex;flex-direction:column;gap:2px;cursor:pointer;
  padding:5px 11px;border-radius:9px;border:1px solid var(--line2);
  background:var(--panel);font-size:0.8rem;line-height:1.5;color:var(--tx);transition:.18s}
.rh-must-chip:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.rh-must-chip i{font-style:normal;font-size:0.68rem;color:var(--tx3);letter-spacing:0}
.rh-src-list{margin-top:14px;display:grid;gap:6px}
.rh-src-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;
  font-size:0.7667rem;line-height:1.8;color:var(--tx3);
  padding:8px 12px;border-radius:9px;border:1px solid var(--line2)}
.rh-src-row b{font-weight:400;color:var(--tx2);letter-spacing:1px}
.rh-src-row i{font-style:normal;flex:1 1 100%;color:var(--tx3)}
/* 来源行是 flex（`b` 标签 + `a` 链接 + 整行的 `i` 说明）。
   原先是 `flex:0 0 auto`：flex-basis=auto 让链接基尺寸取 max-content（=整句不折行的宽度），
   flex-shrink=0 又禁止它收缩 —— 于是长句（「维基文库（原文为公有领域；页面文本依 CC BY-SA 4.0 提供）」）
   在 320px 上把整行撑出 29px，flex-wrap 也救不了（它换的是「行」，不是行内的字）。
   改成可收缩 + 允许在任意字间断行。 */
.rh-src-row a{color:var(--accent2);text-decoration:none;flex:1 1 auto;min-width:0;overflow-wrap:anywhere}

/* ---------- 篇目列表 ---------- */
.rh-list-card{padding:18px 20px}
.rh-read-t{font-family:var(--serif);font-size:1.0667rem;letter-spacing:2px;color:var(--accent2);
  margin-bottom:14px}
.rh-list{display:grid;gap:8px}
.rh-item{cursor:pointer;padding:11px 14px;border-radius:11px;
  border:1px solid var(--line2);background:rgba(var(--hlRGB),.03);transition:.18s}
.rh-item:hover{border-color:rgba(var(--accentRGB),.45);transform:translateY(-1px)}
.rh-it-n{font-family:var(--serif);font-size:0.9667rem;letter-spacing:1px;color:var(--tx);line-height:1.65}
.rh-it-m{display:flex;flex-wrap:wrap;gap:4px 14px;margin-top:5px;
  font-size:0.7333rem;letter-spacing:1px;color:var(--tx3)}
.rh-bk{color:var(--accent2)}
.rh-hint{font-size:0.8333rem;color:var(--tx3);line-height:2}
/* 从别处跳过来时闪一下：不然页面一滚到底，用户不知道落在哪一条 */
.rh-flash{animation:pcFlash 1.6s ease}

/* ---------- 翻页 ---------- */
.rh-pager{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;
  margin-top:16px;padding-top:14px;border-top:1px solid var(--line2)}
.rh-pg-sizes{display:flex;align-items:center;gap:6px}
.rh-lb{font-size:0.7333rem;letter-spacing:1px;color:var(--tx3)}
.rh-pg-nav{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.rh-pg{min-width:1.9rem;text-align:center;padding:3px 7px;border-radius:7px;cursor:pointer;
  font-size:0.8rem;color:var(--tx2);border:1px solid transparent;transition:.18s;user-select:none}
.rh-pg:hover{border-color:var(--line2);color:var(--tx)}
.rh-pg.on{background:rgba(var(--accentRGB),.14);border-color:var(--line);color:var(--accent2)}
.rh-pg.off{opacity:.35;pointer-events:none}
.rh-pg-dot{color:var(--tx3);padding:0 2px;font-size:0.8rem}
.rh-pg-info{margin-left:auto;font-size:0.7667rem;color:var(--tx3);letter-spacing:1px}
.rh-pg-info b{font-weight:400;color:var(--accent2)}

/* ---------- 栏目联动 ---------- */
.rh-rel{padding:18px 20px}
.rh-rel-hd{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 14px;margin-bottom:12px}
.rh-rel-t{font-family:var(--serif);font-size:1rem;letter-spacing:2px;color:var(--accent2)}
.rh-rel-s{font-size:0.7667rem;color:var(--tx3);letter-spacing:1px}
.rh-rel-s b{font-weight:400;color:var(--tx2)}
.rh-rel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px}
.rh-rel-card{cursor:pointer;padding:12px 14px;border-radius:11px;
  border:1px solid var(--line2);background:rgba(var(--hlRGB),.03);transition:.18s}
.rh-rel-card:hover{border-color:rgba(var(--accentRGB),.45);transform:translateY(-1px)}
.rh-rel-n{font-family:var(--serif);font-size:0.9333rem;letter-spacing:2px;color:var(--tx)}
.rh-rel-w{font-size:0.7333rem;line-height:1.8;color:var(--tx3);margin-top:4px}
.rh-rel-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:7px}
.rh-rel-tag{font-size:0.68rem;padding:1px 7px;border-radius:99px;
  border:1px solid var(--line2);color:var(--tx2)}

/* ---------- 反向关联块（嵌在朝代档案 / 课本人物详情里） ---------- */
.rh-rel-inline{margin-top:14px;padding:12px 14px;border-radius:11px;
  border:1px dashed rgba(var(--accentRGB),.35);background:rgba(var(--accentRGB),.05)}
.rh-rel-inline-h{font-size:0.7667rem;letter-spacing:1px;color:var(--accent2);margin-bottom:8px}
.rh-rel-chips{display:flex;flex-wrap:wrap;gap:6px}
.rh-rel-chip{cursor:pointer;padding:3px 10px;border-radius:8px;font-size:0.7667rem;
  line-height:1.7;border:1px solid var(--line2);background:var(--panel);color:var(--tx);transition:.18s}
.rh-rel-chip:hover{border-color:rgba(var(--accentRGB),.5);color:var(--accent2)}
.rh-rel-foot{margin-top:9px;font-size:0.7333rem;letter-spacing:1px;
  color:var(--accent2);cursor:pointer}
.rh-rel-foot:hover{text-decoration:underline}

/* ---------- 原文阅读弹窗（.modal.rh-reader） ---------- */
.modal.rh-reader{width:min(920px,100%);padding:26px 30px}
.rh-rd-hd{padding-bottom:14px;border-bottom:1px dashed var(--line2);margin-bottom:14px}
.rh-rd-n{font-family:var(--serif);font-size:1.4rem;font-weight:700;letter-spacing:2px;color:var(--tx)}
.rh-rd-m{font-size:0.7667rem;color:var(--tx3);letter-spacing:1px;margin-top:6px}
.rh-rd-w{color:var(--accent2);margin-left:8px}
.rh-rd-tabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.rh-rd-body{max-height:58vh;overflow-y:auto;padding-right:6px}
.rh-rd-body p{font-family:var(--serif);font-size:0.9333rem;line-height:2.15;
  color:var(--tx);margin:0 0 12px;text-align:justify}
.rh-rd-ft{margin-top:14px;padding-top:12px;border-top:1px solid var(--line2);
  font-size:0.7333rem;line-height:1.9;color:var(--tx3)}
.rh-rd-ft a{color:var(--accent2);text-decoration:none}
.rh-rd-tip{margin-left:8px}

@media (max-width:900px){
  .rh-book-grid{grid-template-columns:1fr;gap:16px}
}
@media (max-width:640px){
  .rh-book,.rh-era,.rh-list-card,.rh-rel{padding:15px 15px}
  .rh-lab{flex:0 0 4.4rem}
  .rh-it-n{font-size:0.9333rem}
  .rh-pg-info{margin-left:0;flex:1 1 100%}
  .modal.rh-reader{padding:20px 16px}
  .rh-rd-body{max-height:64vh}
  /* 作者照那一块落到文字下面：窄屏上 176px 图 + 文字两列并排，文字只剩 5—7 个字一行。
     图的横向占比在窄屏要收住（max-width），否则宽屏那点「横长小像」的比例被撑成
     一大块横幅人像，先看到的就成了一张脸。 */
  .rh-au.has-fig{grid-template-columns:minmax(0,1fr);padding-right:0}
  .rh-au-figs{grid-template-columns:minmax(0,1fr);max-width:240px}
  .rh-fig-cap{font-size:0.6667rem}
}

/* ============================================================
   万物生灵（生物学科子栏目）· 页面样式
   ---------------------------------------------------------------
   内容在 public/life.js，界面在 public/life-view.js，样式在这里。
   三条自定的规矩：
     · 颜色一律走主题变量（12 套皮肤都要能用），只有「类群色」是内联的
       --tc（动物红 / 植物青 / 微生蓝，取自 life.js 的 taxa[].color）。
     · 文字色只用对比度达标的几个：--tx / --tx2 / --accent2 /
       --redTx / --jadeTx / --blueTx。--tx3 只用于装饰线，不做正文。
     · 字号一律 rem（theme.test.js 有「不得出现写死 px」的护栏）。
   ============================================================ */

/* ---------- 顶部统计条 ---------- */
.lf-stat{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:12px;margin:4px 0 22px}
.lf-stat-i{background:linear-gradient(180deg,var(--panel),var(--bg2));border:1px solid var(--line2);
  border-radius:13px;padding:13px 8px;text-align:center}
.lf-stat-i b{display:block;font-family:var(--serif);font-size:1.6rem;font-weight:900;color:var(--accent2);line-height:1.25}
.lf-stat-i span{display:block;font-size:0.7667rem;color:var(--tx2);margin-top:3px;letter-spacing:1px}

/* ---------- 筛选区 ---------- */
/* 筛选卡与下面的图鉴网格是同一层兄弟，原先是 0px —— 筛选卡的边框直接压着第一排卡片。
   全站卡片节奏是 14—16px，这里取 14（与 .lf-grid 自己的 gap 一致）。 */
#lf-pane > * + *{margin-top:14px}
.lf-filter{padding:16px 18px}
.lf-frow{display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin-bottom:9px}
.lf-frow:last-child{margin-bottom:0}
/* 标签是两三个字的短词，不参与收缩；长内容一律放在别的元素上，不在这里冒险 */
.lf-flab{flex:0 0 auto;white-space:nowrap;color:var(--tx2);font-size:0.8rem;letter-spacing:2px;
  min-width:4.2em}
.inp.lf-q{flex:1 1 220px;min-width:0;max-width:100%;padding:7px 12px;font-size:0.8667rem}
.lf-count{flex:0 0 auto;margin-left:auto;color:var(--tx2);font-size:0.8rem;letter-spacing:1px;
  font-variant-numeric:tabular-nums}
.lf-map-chips{margin:14px 0 0}
.lf-map-chips .chip b{color:var(--accent2);margin-left:3px}

/* ---------- 图鉴网格 ---------- */
/* minmax(0,1fr) + auto-fill：窄屏自然退到 1～2 列，不靠断点硬折 */
.lf-grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(226px,1fr));margin-bottom:6px}
/* 卡片内边距做成变量：照片区是**出血**到卡片边缘的（用负 margin 抵消内边距）。
   窄屏收窄 padding 时负 margin 必须跟着收 —— 写死两处迟早错位，
   所以改内边距的分支（responsive.css 的 ≤640）要一并改这两个变量。 */
.lf-card{--lf-px:15px;--lf-pt:13px;
  background:linear-gradient(180deg,var(--panel),var(--bg2));border:1px solid var(--line2);
  border-radius:14px;padding:var(--lf-pt) var(--lf-px) 11px;cursor:pointer;transition:.24s;outline:none}
.lf-card:hover,.lf-card:focus-visible{border-color:var(--line);transform:translateY(-2px)}
.lf-card:focus-visible{box-shadow:0 0 0 2px rgba(var(--accentRGB),.45)}
.lf-card.seen{border-color:rgba(var(--accentRGB),.34)}

/* ---------- 物种照片（图鉴卡片与详情弹窗共用同一张） ----------
   构建期从维基媒体抓「条目首图」——对物种而言那正是该物种的标准照 ——
   转成站内自托管的 960×640（3:2）JPG，卡片与详情
   都从同一张里 cover 裁切，一张图两处用。

   ★ 图上**不叠任何文字**。照片的明暗不可控，把彩色徽标（类群 / 保护等级 /
     IUCN）压上去，必然有几套主题掉到对比度线以下；影视封面那次是靠一整层
     压暗层解决的，这里选择更省事的做法：徽标仍留在照片下方那一行。
   ★ 三种状态各有样式，别合并：正常图 / is-loading（映射表还没取回来，留位
     防跳动）/ is-empty（这个物种确实没有公开影像，写明原因）。 */
.lf-shot{position:relative;margin:calc(-1 * var(--lf-pt)) calc(-1 * var(--lf-px)) 11px;
  border-radius:13px 13px 0 0;overflow:hidden;aspect-ratio:3/2;
  background:linear-gradient(135deg,var(--bg2),var(--panel))}
.lf-shot img{display:block;width:100%;height:100%;object-fit:cover}
.lf-shot.is-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  color:var(--tx2)}
.lf-shot-ico{font-size:1.5rem;line-height:1;opacity:.6}
.lf-shot-tx{font-size:0.7rem;letter-spacing:1px}
/* 详情弹窗顶部大图：.lf-detail > * 给了 24px/26px 的内边距，这里抵消成出血 */
/* ⚠️ 只清 padding，不要写 margin:0 —— 上面 `.lf-detail > *` 靠
   margin-left/right:auto 把 880px 的块水平居中，一旦用 margin:0 覆盖，
   大图就会单独贴到左边，而标题卡、信息卡仍居中（实测 1440 宽下差 264px）。 */
.lf-detail > .lf-d-shot{padding:0;overflow:hidden}
.lf-d-shot{aspect-ratio:3/2;max-height:52vh;
  background:linear-gradient(135deg,var(--bg2),var(--panel))}
.lf-d-shot img{display:block;width:100%;height:100%;object-fit:cover}
.lf-d-shot.is-empty{display:flex;align-items:center;justify-content:center;gap:9px;color:var(--tx2);
  aspect-ratio:auto;height:auto;padding:22px 18px !important}
.lf-card-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:7px}
/* ⚠️ 类群色（--tc）**只做边框，不做文字**。
   第一版是 `color:var(--tc)`，实测在「春节·红金」这套深红皮肤上，
   动物类群的内联色 --red 压在深红卡片底上只有 3.93:1 —— 与 .topic h3 那次
   是同一个坑：写死的/强制的强调色一旦当正文色，总有一套皮肤会翻车。
   文字改用 --tx2（各主题都达标），色相信息由左侧那条 2px 竖线承担。 */
.lf-tax{font-size:0.7667rem;letter-spacing:1px;color:var(--tx2);
  border-left:2px solid var(--tc,var(--line));padding-left:6px;white-space:nowrap}
.lf-card-n{font-family:var(--serif);font-size:1.1333rem;font-weight:700;letter-spacing:1px;color:var(--tx)}
.lf-card-sci{font-size:0.7333rem;color:var(--tx2);font-style:italic;letter-spacing:.3px;
  margin-top:1px;overflow-wrap:anywhere}
.lf-card-grp{font-size:0.7333rem;color:var(--tx2);margin-top:5px;line-height:1.6;overflow-wrap:anywhere}
.lf-card-foot{display:flex;align-items:center;gap:7px;margin-top:9px;padding-top:8px;
  border-top:1px dashed var(--line2);flex-wrap:wrap}
.lf-endem{display:inline-block;font-size:0.6667rem;line-height:1.7;padding:0 6px;border-radius:6px;
  margin-left:6px;color:var(--jadeTx);border:1px solid rgba(var(--jadeRGB),.42);vertical-align:2px}

/* ---------- 保护等级 / IUCN 徽标 ----------
   两套体系用两种形状区分：国内名录是描边胶囊，IUCN 带固定的两字母前缀。
   不做颜色换算、也不合并成一种「等级」。 */
.lf-prot,.lf-iucn{display:inline-block;font-size:0.7rem;line-height:1.75;padding:0 7px;border-radius:999px;
  letter-spacing:.5px;white-space:nowrap;border:1px solid var(--line2);color:var(--tx2);
  font-variant-numeric:tabular-nums}
.lf-prot.red{color:var(--redTx);border-color:rgba(var(--redRGB),.5);background:rgba(var(--redRGB),.08)}
.lf-prot.jade{color:var(--jadeTx);border-color:rgba(var(--jadeRGB),.5);background:rgba(var(--jadeRGB),.08)}
.lf-prot.blue{color:var(--blueTx);border-color:rgba(var(--blueRGB),.5);background:rgba(var(--blueRGB),.08)}
.lf-iucn.i-ex,.lf-iucn.i-cr{color:var(--redTx);border-color:rgba(var(--redRGB),.5)}
.lf-iucn.i-en{color:var(--redTx);border-color:rgba(var(--redRGB),.3)}
.lf-iucn.i-vu{color:var(--accent2);border-color:rgba(var(--accentRGB),.5)}
.lf-iucn.i-nt{color:var(--blueTx);border-color:rgba(var(--blueRGB),.4)}
.lf-iucn.i-lc{color:var(--jadeTx);border-color:rgba(var(--jadeRGB),.4)}
.lf-iucn.i-ne{color:var(--tx2);border-color:var(--line2)}
.lf-fav{color:var(--accent2);margin-left:auto;font-size:0.9333rem;line-height:1}
.lf-seen{color:var(--jadeTx);font-size:0.8667rem;line-height:1}
.lf-fav-bar:empty{display:none}
.lf-empty{color:var(--tx2);text-align:center;padding:34px 16px;font-size:0.9rem}

.lf-note{font-size:0.7667rem;line-height:1.85;color:var(--tx2);margin-top:10px}
.lf-note b{color:var(--accent2)}
.lf-warn{font-size:0.7667rem;line-height:1.85;color:var(--redTx);background:rgba(var(--redRGB),.08);
  border:1px solid rgba(var(--redRGB),.3);border-radius:10px;padding:8px 11px;margin-top:9px}
.lf-quote{font-family:var(--serif);font-size:1.0333rem;letter-spacing:1px;color:var(--accent2);
  margin:10px 0;padding-left:12px;border-left:2px solid var(--accent)}
.lf-h2{font-family:var(--serif);font-size:1.1333rem;font-weight:700;letter-spacing:2px;color:var(--tx);
  margin-bottom:9px}
.lf-h2-out{font-size:1.2667rem;margin:30px 0 12px}
.lf-ol,.lf-ul{padding-left:1.25em;font-size:0.8333rem;line-height:1.85;color:var(--tx)}
.lf-ol li,.lf-ul li{margin-bottom:3px;overflow-wrap:anywhere}
.lf-ul.warn li{color:var(--redTx)}

/* ---------- 生灵地图 ---------- */
.lf-map-wrap{position:relative;border:1px solid var(--line2);border-radius:14px;overflow:hidden;
  background:var(--panel)}
.lf-map{width:100%;height:clamp(260px,42vh,420px)}
.lf-map-fb{padding:16px 18px}
.lf-fb-i{border-top:1px dashed var(--line2);padding:11px 0}
.lf-fb-i:first-of-type{border-top:none}
.lf-fb-i b{font-family:var(--serif);font-size:1rem;letter-spacing:1px;color:var(--tx);margin-right:8px}
.lf-fb-i > span{font-size:0.7333rem;color:var(--tx2)}
.lf-fb-i > div{margin-top:7px;display:flex;flex-wrap:wrap;gap:6px}
.lf-region{margin-top:14px}
.lf-region-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:7px}
.lf-region-h b{font-family:var(--serif);font-size:1.1333rem;letter-spacing:1px;color:var(--accent2)}
.lf-region-h span{font-size:0.7667rem;color:var(--tx2)}
.lf-region p{font-size:0.8667rem;line-height:1.85;color:var(--tx);overflow-wrap:anywhere}
.lf-region-empty{color:var(--tx2);font-size:0.8667rem}
.lf-region-sp{display:flex;flex-wrap:wrap;gap:7px;margin-top:11px}
.lf-sp-pill{cursor:pointer;font-size:0.8rem;padding:3px 10px;border-radius:999px;
  border:1px solid var(--tc,var(--line2));color:var(--tx);background:rgba(var(--hlRGB),.04);
  transition:.18s;max-width:100%;overflow-wrap:anywhere}
.lf-sp-pill:hover{border-color:var(--accent);color:var(--accent2);background:rgba(var(--accentRGB),.08)}

/* ---------- 微观视界 ---------- */
.lf-cellwrap{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);gap:20px;align-items:start}
.lf-cell{min-width:0}
.lf-cell-svg{width:100%;height:auto;display:block}
/* 细胞「底」是圆角矩形：极淡的类群色，无主题依赖 */
.lf-cell-body{fill:rgba(var(--accentRGB),.07);stroke:var(--line);stroke-width:2}
.lf-cell-animal{fill:rgba(var(--redRGB),.07)}
.lf-cell-bacteria{fill:rgba(var(--jadeRGB),.08)}
.lf-cell-virus{fill:rgba(var(--blueRGB),.08)}
/* 结构热点：可点，命中区靠 r=7 的圆点 */
.lf-organ{cursor:pointer}
.lf-organ-dot{fill:var(--panel);stroke:var(--accent);stroke-width:2;transition:.18s}
.lf-organ:hover .lf-organ-dot{fill:var(--accent)}
.lf-organ.on .lf-organ-dot{fill:var(--accent);stroke:var(--accent2);stroke-width:3}
.lf-organ-n{fill:var(--tx2);font-size:0.6111rem;text-anchor:middle;dominant-baseline:middle;
  pointer-events:none;transition:.18s}
.lf-organ.on .lf-organ-n{fill:var(--accent2);font-weight:700}
.lf-cellinfo{min-width:0}
.lf-cell-brief{font-size:0.8667rem;line-height:1.9;color:var(--tx);overflow-wrap:anywhere}
.lf-partbox{margin-top:11px;border:1px solid var(--line);border-radius:12px;padding:11px 13px;
  background:rgba(var(--accentRGB),.06)}
.lf-partbox b{display:block;font-family:var(--serif);font-size:1rem;letter-spacing:1px;color:var(--accent2);
  margin-bottom:4px}
.lf-partbox span{font-size:0.8333rem;line-height:1.85;color:var(--tx);overflow-wrap:anywhere}
.lf-partbox-hint{border-style:dashed;color:var(--tx2);font-size:0.8333rem}

.lf-proc-h{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin:6px 0 4px}
.lf-proc-h b{font-family:var(--serif);font-size:1.2rem;letter-spacing:1px;color:var(--tx)}
.lf-eq{font-family:var(--serif);font-size:0.9rem;color:var(--accent2);letter-spacing:.5px;
  overflow-wrap:anywhere}
.lf-proc-brief{font-size:0.8667rem;line-height:1.9;color:var(--tx);overflow-wrap:anywhere}
.lf-proc-ctl{align-items:center;margin:12px 0 10px}
.lf-step-n{flex:0 0 auto;font-size:0.8333rem;color:var(--accent2);letter-spacing:1px;
  font-variant-numeric:tabular-nums}
.lf-sl{flex:0 0 auto;margin-left:auto;font-size:0.8rem;color:var(--tx2)}
.lf-steps{display:grid;gap:8px}
.lf-step{display:flex;gap:11px;align-items:flex-start;border:1px solid var(--line2);border-radius:11px;
  padding:10px 13px;transition:.22s;min-width:0}
.lf-step.done{border-color:rgba(var(--jadeRGB),.35)}
.lf-step.on{border-color:var(--line);background:rgba(var(--accentRGB),.07)}
.lf-step-i{flex:0 0 1.6rem;width:1.6rem;height:1.6rem;border-radius:50%;display:grid;place-items:center;
  font-size:0.8rem;font-weight:700;color:var(--tx2);border:1px solid var(--line2);background:var(--panel)}
.lf-step.on .lf-step-i{color:var(--onAccent);background:var(--btnGrad);border-color:transparent}
.lf-step.done .lf-step-i{color:var(--jadeTx);border-color:rgba(var(--jadeRGB),.5)}
.lf-step-b{min-width:0;font-size:0.8333rem;line-height:1.85;color:var(--tx);overflow-wrap:anywhere}
.lf-step-b b{display:block;font-family:var(--serif);font-size:0.9333rem;letter-spacing:1px;color:var(--tx)}

.lf-params{display:grid;gap:12px;margin-top:14px;border-top:1px dashed var(--line2);padding-top:14px}
.lf-param{min-width:0}
.lf-param label{display:block;font-size:0.8rem;color:var(--tx2);letter-spacing:1px}
.lf-param-v{color:var(--accent2);font-variant-numeric:tabular-nums}
.lf-range{width:100%;max-width:100%;margin:7px 0 5px;accent-color:var(--accent);cursor:pointer}
.lf-param-eff{font-size:0.8rem;line-height:1.8;color:var(--tx);overflow-wrap:anywhere}

/* ---------- 生灵实验室 ---------- */
.lf-exps{display:grid;gap:12px;margin-top:12px}
.lf-exp{padding:16px 18px;cursor:pointer}
.lf-exp-h{display:flex;align-items:flex-start;gap:10px;justify-content:space-between;flex-wrap:wrap}
.lf-exp-h b{font-family:var(--serif);font-size:1.0667rem;letter-spacing:1px;color:var(--tx);min-width:0}
.lf-exp-t{display:flex;gap:5px;flex-wrap:wrap;flex:0 0 auto}
.lf-exp-aim{font-size:0.8333rem;line-height:1.85;color:var(--tx2);margin-top:6px;overflow-wrap:anywhere}
.lf-exp-body{display:none;margin-top:12px;border-top:1px dashed var(--line2);padding-top:11px}
.lf-exp.open .lf-exp-body{display:block}
.lf-exp-more{margin-top:9px;font-size:0.8rem;color:var(--accent2);letter-spacing:1px}
.lf-exp.open .lf-exp-more{color:var(--tx2)}

.lf-timeline{position:relative;margin-top:14px;padding-left:4px}
/* 年份列宽 6.6rem（约 106px）是量出来的，不是拍的：
   科学史里有几条的 y 是「两个阶段」的写法（孟德尔的「1856—1863 实验 /
   1865 宣读 / 1866 发表」、卡尔文的「1950 年代（卡尔文循环）/ 1941（…）」），
   4.6rem 放不下就被迫在**词中间**断开，页面上读成「1856— / 1863 实 / 验 / 1865」。
   汉字可以任意断行是 CSS 的正常行为，所以只能靠给够宽度让它**在空格处**断。 */
.lf-tl-i{display:grid;grid-template-columns:6.6rem minmax(0,1fr);gap:12px;padding:11px 0;
  border-top:1px dashed var(--line2)}
.lf-tl-i:first-child{border-top:none}
.lf-tl-y{font-family:var(--serif);font-size:0.9667rem;font-weight:700;color:var(--accent2);
  letter-spacing:1px;font-variant-numeric:tabular-nums}
.lf-tl-b{min-width:0}
.lf-tl-b b{font-family:var(--serif);font-size:0.9667rem;letter-spacing:1px;color:var(--tx)}
.lf-tl-w{display:block;font-size:0.7333rem;color:var(--tx2);margin-top:2px}
/* 科学史条目的人像：40 方图、圆角、微微描一圈。
   flex-wrap 是必须的 —— 沃森与克里克那条挂了 3 个人，窄屏要能换行而不是溢出。
   尺寸按 2 倍屏取值：40 CSS px → 需要 ≥80 的图源，构建期出的是 240，富余。 */
.lf-tl-ps{display:flex;flex-wrap:wrap;gap:8px;margin-top:7px}
.lf-tl-p{width:40px;height:40px;object-fit:cover;border-radius:10px;
  border:1px solid var(--line2);background:var(--bg2)}
.lf-tl-i.read .lf-tl-p{border-color:var(--jadeTx)}
.lf-tl-d{font-size:0.8333rem;line-height:1.85;color:var(--tx);margin-top:5px;overflow-wrap:anywhere}
.lf-tl-i.read .lf-tl-b b{color:var(--jadeTx)}

/* ---------- 生灵实践 ---------- */
.lf-pjs,.lf-homes{display:grid;gap:14px}
.lf-pj p,.lf-case p{font-size:0.8333rem;line-height:1.85;color:var(--tx);overflow-wrap:anywhere}
.lf-pj-h,.lf-case-h,.lf-home-h{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  justify-content:space-between;margin-bottom:6px}
.lf-pj-h b,.lf-case-h b,.lf-home-h b{font-family:var(--serif);font-size:1.0667rem;letter-spacing:1px;
  color:var(--tx);min-width:0}
.lf-d-lab{display:block;font-size:0.7333rem;letter-spacing:2px;color:var(--accent2);margin:11px 0 5px}
.lf-home{padding:16px 18px}
.lf-home .lf-d-lab{margin-top:8px}

/* ---------- 表格（评价量表 / 名录 / 记录模板） ---------- */
.lf-tb{width:100%;border-collapse:collapse;font-size:0.8rem;line-height:1.75;table-layout:fixed}
.lf-tb th,.lf-tb td{border:1px solid var(--line2);padding:7px 10px;text-align:left;
  vertical-align:top;overflow-wrap:anywhere;color:var(--tx)}
.lf-tb th{color:var(--accent2);background:rgba(var(--hlRGB),.04);font-weight:600;letter-spacing:1px}
.lf-tb-sub{font-size:0.7rem;color:var(--tx2);margin-top:2px}
/* 记录模板是「标签列 + 空栏」，标签列给一个固定宽度即可 */
.lf-tb-form th{width:5.6em}

/* ---------- 生灵课堂 ---------- */
.lf-tpl{display:grid;gap:9px}
.lf-tpl-i{display:grid;grid-template-columns:1.7rem minmax(0,1fr);gap:10px;align-items:baseline;
  font-size:0.8333rem;line-height:1.8;color:var(--tx);border-bottom:1px dashed var(--line2);padding:8px 0}
.lf-tpl-i:last-child{border-bottom:none}
.lf-tpl-n{width:1.6rem;height:1.6rem;border-radius:50%;display:grid;place-items:center;font-size:0.7333rem;
  font-weight:700;color:var(--accent2);border:1px solid var(--line)}
.lf-tpl-i b{display:block;font-family:var(--serif);font-size:0.9333rem;letter-spacing:1px;color:var(--tx)}
.lf-tpl-i span{display:block;color:var(--tx2);overflow-wrap:anywhere}
.lf-case{margin-top:14px;border-top:1px dashed var(--line2);padding-top:13px}
.lf-case:first-child{margin-top:0;border-top:none;padding-top:0}

/* ---------- 生灵养成 ---------- */
.lf-spirits{display:grid;gap:11px;grid-template-columns:repeat(auto-fill,minmax(118px,1fr));margin-top:12px}
.lf-spirit{text-align:center;border:1px solid var(--line2);border-radius:13px;padding:12px 8px;
  cursor:pointer;transition:.2s;background:rgba(var(--hlRGB),.03);min-width:0}
.lf-spirit:hover{border-color:var(--line);transform:translateY(-2px)}
.lf-spirit.on{border-color:var(--accent);background:rgba(var(--accentRGB),.1)}
.lf-spirit-ico{font-size:1.7333rem;line-height:1.2}
.lf-spirit-n{font-family:var(--serif);font-size:0.9333rem;letter-spacing:1px;color:var(--tx);
  margin-top:3px;overflow-wrap:anywhere}
.lf-spirit-tag{font-size:0.7rem;color:var(--tx2);margin-top:2px;overflow-wrap:anywhere}
.lf-spirit-now{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:14px;
  border:1px solid var(--line);border-radius:12px;padding:11px 14px;background:rgba(var(--accentRGB),.06);
  font-size:1.3333rem}
.lf-spirit-now b{font-family:var(--serif);font-size:1.0667rem;letter-spacing:1px;color:var(--accent2)}
.lf-spirit-now > span{font-size:0.8rem;color:var(--tx)}
.lf-spirit-now .lf-note{margin:0;margin-left:auto}
.lf-coll{display:grid;gap:11px;grid-template-columns:repeat(auto-fit,minmax(104px,1fr));margin-top:6px}
.lf-coll-i{text-align:center;border:1px solid var(--line2);border-radius:12px;padding:11px 6px;min-width:0}
.lf-coll-i b{display:block;font-family:var(--serif);font-size:1.4rem;font-weight:900;color:var(--accent2);
  line-height:1.3;font-variant-numeric:tabular-nums}
.lf-coll-i span{display:block;font-size:0.7333rem;color:var(--tx2);margin-top:2px;overflow-wrap:anywhere}
.lf-bar{height:9px;border-radius:999px;background:rgba(var(--txRGB),.1);overflow:hidden;margin:14px 0}
.lf-bar i{display:block;height:100%;background:var(--btnGrad);border-radius:999px;transition:width .4s ease}
.lf-badges{display:grid;gap:11px;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));margin-top:6px}
.lf-badge{text-align:center;border:1px solid var(--line2);border-radius:13px;padding:13px 8px;
  background:rgba(var(--hlRGB),.03);opacity:.55;transition:.25s;min-width:0}
.lf-badge.on{opacity:1;border-color:var(--accent);background:rgba(var(--accentRGB),.08)}
.lf-badge-ico{font-size:1.6rem;line-height:1.25;filter:grayscale(1)}
.lf-badge.on .lf-badge-ico{filter:none}
.lf-badge-n{font-family:var(--serif);font-size:0.9333rem;letter-spacing:1px;color:var(--tx);
  margin-top:3px;overflow-wrap:anywhere}
.lf-badge-c{font-size:0.7rem;line-height:1.7;color:var(--tx2);margin-top:3px;overflow-wrap:anywhere}

/* ---------- 关于与来源 ---------- */
.lf-src{display:grid;gap:10px}
.lf-src-i{border-left:2px solid var(--line);padding-left:11px;font-size:0.8rem;line-height:1.8;
  color:var(--tx);overflow-wrap:anywhere}
.lf-src-i b{display:block;font-family:var(--serif);font-size:0.9333rem;letter-spacing:1px;color:var(--tx)}
.lf-src-i span{display:block;color:var(--tx2)}
.lf-src-s{color:var(--tx2);font-size:0.7333rem;margin-top:3px;font-style:italic}

/* ---------- 物种详情弹窗 ----------
   自己一层遮罩：内容由 life-view.js 直接写 innerHTML，不走 closeModal()。 */
.lf-detail{position:fixed;inset:0;z-index:400;display:none;overflow-y:auto;
  background:var(--mask);padding:5vh 16px 6vh}
.lf-detail.on{display:block}
/* ⚠️ margin-bottom 不能省：详情是由若干个独立卡片块叠出来的（大图 / 标题 / 信息 / 注释），
   每块自己有圆角和投影 —— 块与块之间不留缝，它们就"长"成一整片，
   看上去像顶部物种照片和下面的正文贴死了（用户反馈的「照片与下面太贴合」）。
   只加下边距，别写成 margin:0 —— 左右那两个 auto 负责把 880px 的块水平居中。 */
.lf-detail > *{width:min(880px,100%);margin-left:auto;margin-right:auto;margin-bottom:14px;
  background:var(--modalBg);border:1px solid var(--line);border-radius:16px;padding:24px 26px;
  box-shadow:0 24px 60px rgba(var(--shRGB),.5);animation:lfIn .22s ease both}
@keyframes lfIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
body.lf-modal-open{overflow:hidden}
.lf-d-head{display:flex;align-items:flex-start;gap:16px;justify-content:space-between;
  flex-wrap:wrap;border-bottom:1px dashed var(--line2);padding-bottom:14px;margin-bottom:14px}
.lf-d-n{font-family:var(--serif);font-size:1.5333rem;font-weight:700;letter-spacing:2px;color:var(--tx)}
.lf-d-sci{font-size:0.8rem;font-style:italic;color:var(--tx);margin-top:3px;overflow-wrap:anywhere}
.lf-d-tags{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.lf-d-grid{display:grid;gap:0}
.lf-d-row{display:grid;grid-template-columns:5.4rem minmax(0,1fr);gap:12px;padding:7px 0;
  border-bottom:1px dashed var(--line2);font-size:0.8333rem;line-height:1.85}
.lf-d-row:last-child{border-bottom:none}
.lf-d-lab{display:block;font-size:0.7333rem;letter-spacing:1px;color:var(--accent2)}
.lf-d-val,.lf-d-row > span:last-child{color:var(--tx);overflow-wrap:anywhere;min-width:0}
/* 「口径与分歧」等注释块。
   原底色是 rgba(var(--accentRGB),.06) —— 一层只有 6% 不透明度的强调色，
   在浅色皮肤上几乎等于没有，整块看着发灰、发虚，正文对比度也被这层半透明底拉低
   （用户反馈「口径与分歧还有点透明，不清晰」）。
   改成不透明的面板底色 + 左侧一条强调竖线：块的边界清楚，正文回到 --tx 满对比度。 */
.lf-d-note{margin-top:12px;border:1px solid var(--line);border-left:3px solid var(--accent2);
  border-radius:12px;padding:12px 15px;
  font-size:0.8333rem;line-height:1.85;color:var(--tx);background:var(--panel2);
  overflow-wrap:anywhere}
.lf-d-note .lf-d-lab{color:var(--accent2);font-weight:700}
.lf-d-acts{display:flex;gap:9px;flex-wrap:wrap;margin-top:16px}
/* 弹窗里的 5.4rem 标签列在窄屏会挤掉内容列，窄屏改上下叠 */
@media (max-width:640px){
  .lf-detail{padding:3vh 12px 5vh}
  .lf-detail > *{padding:18px 16px}
  .lf-d-row{grid-template-columns:minmax(0,1fr);gap:2px}
}

/* ---------- 首页关联块（探万物生灵） ----------
   列数写死 4 列，与上一块「编辑推荐专题」(.topic-grid{repeat(4,1fr)}) 同宽对齐。
   ⚠️ 这里原本是 `repeat(auto-fill,minmax(212px,1fr))`：auto-fill 会按容器宽度**尽量多建轨道**，
   在 1280px 内容宽下建出 5 条列轨道，而 HOME_PICKS 只有 4 个物种 → 第 5 列永远空着，
   四张卡片只铺满左边约 3/4，右侧留一片空白（用户反馈的「右侧有空白区域」）。
   改用固定 4 列后，卡片右边缘与上面的专题卡、下面的页脚同一条竖线。
   少一个物种要加卡时，改 life-view.js 的 HOME_PICKS 即可，列数不用跟着动。 */
.home-life{display:grid;gap:16px;grid-template-columns:repeat(4,minmax(0,1fr))}
.hl-card{--lf-px:16px;--lf-pt:14px;
  position:relative;border:1px solid var(--line2);border-radius:14px;padding:var(--lf-pt) var(--lf-px) 14px;
  background:linear-gradient(180deg,var(--panel),var(--bg2));cursor:pointer;transition:.24s;min-width:0}
.hl-card:hover{transform:translateY(-3px);border-color:var(--line)}
.hl-tax{font-size:0.7333rem;letter-spacing:1px;color:var(--tc,var(--tx2));
  border-left:2px solid var(--tc,var(--line));padding-left:6px}
.hl-n{font-family:var(--serif);font-size:1.2rem;font-weight:700;letter-spacing:1px;color:var(--tx);
  margin-top:7px}
.hl-sci{font-size:0.7333rem;font-style:italic;color:var(--tx2);margin-top:2px;overflow-wrap:anywhere}
.hl-cold{font-size:0.8rem;line-height:1.8;color:var(--tx);margin-top:8px;overflow-wrap:anywhere}
/* 标题行带右侧操作：把「进入万物生灵栏目」这类按钮放到 .sec-head 的右端，
   与标题同一行（原来它单独占一行、贴在卡片下方，右侧那片空白更显眼）。
   窄屏 flex-wrap 后按钮自动落到标题下方并左对齐，不会挤成一团。
   这里只加一个修饰类，不动 .sec-head 本身的块级排版，其它页面照旧。 */
.sec-head.has-act{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}
.sec-head.has-act > .sh-txt{min-width:0}

/* ================= 未成年人模式 · 全站拦截遮罩（guard-shell.js 注入） =================
   这一层由 guard-shell.js 在**任何页面**上按需创建，不依赖治理页。
   颜色一律写字面色值（不走主题变量）：遮罩要压在所有主题之上，取变量会在
   某些浅色皮肤下与页面对撞成看不见 —— 与 gate.js 的启动遮罩同一个理由。
   约束：只做「说明 + 两个出口」，不放倒计时等会让人盯着屏幕的动效 ——
   这时候本来就是要让用户离开。 */
#shj-guard-mask{position:fixed;inset:0;z-index:9998;display:flex;align-items:center;justify-content:center;
  padding:24px;background:rgba(13,11,8,.9);backdrop-filter:blur(3px)}
#shj-guard-mask .gm-card{max-width:460px;width:100%;text-align:center;padding:34px 30px 28px;
  border-radius:18px;background:#1a1712;border:1px solid rgba(232,201,138,.22);
  box-shadow:0 24px 60px rgba(0,0,0,.5)}
#shj-guard-mask .gm-ico{font-size:2.6rem;line-height:1}
#shj-guard-mask .gm-t{margin-top:14px;font-family:'Noto Serif SC',STZhongsong,SimSun,serif;
  font-size:1.35rem;font-weight:700;letter-spacing:2px;color:#f3ece0}
#shj-guard-mask .gm-why{margin-top:12px;font-size:.95rem;line-height:1.8;color:#d9cfbe}
#shj-guard-mask .gm-extra{margin-top:10px;font-size:.85rem;line-height:1.8;color:#a89d8b}
#shj-guard-mask .gm-acts{margin-top:22px;display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
#shj-guard-mask .btn{background:#e8c98a;color:#241f17;border:1px solid #e8c98a}
#shj-guard-mask .btn.ghost{background:transparent;color:#d9cfbe;border-color:rgba(232,201,138,.4)}
#shj-guard-mask.is-busy .gm-acts{opacity:.55;pointer-events:none}
@media (max-width:420px){
  #shj-guard-mask .gm-card{padding:26px 20px 22px}
  #shj-guard-mask .gm-t{font-size:1.2rem}
}

/* ===== 时间轴「时空联动」疆域图（PRD 3.1.3 增补） =====
   自绘 SVG 的容器。栅格直接复用 .geo-grid —— 它已经在窄屏断点里被折成一列
   （responsive 段那句 `grid-template-columns:minmax(0,1fr) !important`），
   所以这里不需要再写一遍 media query，避免两处断点漂移。
   ★ 颜色一律走 CSS 变量，且只写在 style="…" 里而不是 SVG 表现属性上：
     var() 在 CSS 声明里有效，在 stroke="var(--x)" 这类表现属性里不被支持
     （会静默不生效，画出来是黑色）。 */
.tlm-map{width:100%;border-radius:16px;border:1px solid var(--line2);background:var(--bg2);overflow:hidden}
.tlm-map svg{display:block;width:100%;height:auto}
.tlm-ev-hd{font-size:0.8333rem;color:var(--tx2);line-height:1.7}
.tlm-ev{display:flex;gap:8px;align-items:flex-start;padding:6px 0;border-bottom:1px solid var(--line2)}
.tlm-ev:last-child{border-bottom:0}
.tlm-dot{width:7px;height:7px;border-radius:50%;background:var(--accent2);margin-top:6px;flex:0 0 auto}
.tlm-ev .tt{font-size:0.8667rem;color:var(--tx)}
.tlm-ev .nn{font-size:0.7667rem;color:var(--tx3)}
