/* ============================================================
   佛山木版年画数字图谱 · 布局与组件
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; display: block; }
p { margin: 0 0 1em; }

/* ---------- 纸纹 ----------
   一层全屏的噪点，压住纯色底的「屏幕感」。
   用 SVG feTurbulence 现算，不加载图片——file:// 下也不会跨源失败。
   pointer-events:none 保证它不吃点击；blend 让它在明暗两底上都只是「质感」。 */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: .055;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.86' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] body::after {
  mix-blend-mode: screen;
  opacity: .04;
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) body::after {
    mix-blend-mode: screen;
    opacity: .04;
  }
}
/* 高对比度偏好下直接关掉噪点，别拿质感换可读性 */
@media (prefers-contrast: more) {
  body::after { display: none; }
}

/* ---------- 顶栏 ---------- */
.topbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gap);
  padding: .7rem var(--pad-x);
  /* 旧内核没有 color-mix：给实底，别让顶栏文字和下面的正文混在一起。 */
  background: var(--paper);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule-soft);
}
.topbar__id {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .18em;
  color: var(--ink-2);
}
.topbar__nav { display: flex; gap: .15rem; flex-wrap: wrap; }
.topbar__nav a {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-2);
  text-decoration: none;
  padding: .3rem .6rem;
  border-radius: var(--radius);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.topbar__nav a:hover { background: var(--paper-sunk); color: var(--ink); }
.topbar__nav a:focus-visible { outline: 2px solid var(--dan-ink); outline-offset: 2px; }

.themetoggle {
  font-family: var(--font-sans); font-size: var(--fs-xs);
  background: none; border: 1px solid var(--rule); color: var(--ink-2);
  border-radius: var(--radius); padding: .3rem .6rem; cursor: pointer;
}
.themetoggle:hover { border-color: var(--ink-3); color: var(--ink); }

/* ---------- 幕 ---------- */
.act {
  padding: var(--gap-xl) var(--pad-x);
  max-width: 1180px;
  margin: 0 auto;
}
.act + .act { border-top: 1px solid var(--rule-soft); }
/* 环面只是容器，不是控件。浏览器把焦点落到它身上时（窄屏纵向排布下会这样），
   不要画默认焦点框——真正的控件（索引点、翻页钮）各有自己的焦点样式。 */
.act:focus, .act:focus-visible { outline: none; }

/* ── 幕的背景纹样 ──
   每一幕垫一层极淡的线纹（<use> 引 <symbol>，见 index.html）。
   颜色走 currentColor：明暗两套自动换，不用做第二份图。
   isolation 让 z-index:-1 落在本幕之内；没有它，负层会钻到页面底色后面。 */
.act { position: relative; isolation: isolate; }
.deco-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.act__bg {
  position: absolute;
  z-index: -1;
  display: block;
  height: auto;
  pointer-events: none;
  color: var(--ink);
  opacity: .055;
}
/* 位置各自错开：五个幕都用同一角，会看出是模板 */
.act__bg--see    { width: 34rem; left: -12rem;  bottom: -18rem; }
.act__bg--source { width: 46rem; right: -12rem; top: -2rem; opacity: .05; }
.act__bg--craft  { width: 34rem; right: -5rem;  top: 1rem; }
.act__bg--opera  { width: 24rem; right: -2rem;  top: -3rem; }
.act__bg--legacy { width: 18rem; right: 0;      top: -3rem; }

/* 窄屏：纹样退到更小，别和正文抢地方 */
@media (max-width: 900px) {
  .act__bg { opacity: .035; }
  .act__bg--see    { width: 26rem; }
  .act__bg--source { width: 34rem; left: calc(50% - 17rem); }
  .act__bg--craft  { width: 22rem; }
  .act__bg--opera  { width: 26rem; }
  .act__bg--legacy { width: 18rem; }
}

.act__head { max-width: 54rem; margin-bottom: var(--gap-m); }
.act__head .lede, .act__head .body { max-width: var(--measure); }
/* 中文标题靠 text-wrap:balance 分两行时不会剩下一个字（幕四曾孤零零掉一个「孔」） */
.act__title, .hero-title, .sub, .tp__title, .turn__h { text-wrap: balance; }
.kicker {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .24em;
  color: var(--ink-3);
  margin: 0 0 .8rem;
}
.act__title, .hero-title {
  font-size: var(--fs-h1);
  line-height: 1.14;
  letter-spacing: var(--ls-title);
  margin: 0 0 .6rem;
  font-weight: 600;
}
/* 主标题：字号越大，字距越要收——六字以内的大字加上 .06em 会散掉 */
.hero-title {
  font-size: var(--fs-hero);
  line-height: 1.02;
  letter-spacing: .02em;
  font-weight: 500;
  margin-bottom: .8rem;
}
.hero-alias {
  font-family: var(--font-sans); font-size: var(--fs-sm);
  color: var(--ink-3); letter-spacing: .1em; margin: 0;
}
.lede { font-size: 1.08em; color: var(--ink-2); }
.body { color: var(--ink-2); max-width: var(--measure); }
.sub {
  font-size: var(--fs-h3);
  letter-spacing: var(--ls-title);
  /* inline-block 的上下外边距不会和相邻块合并，给大了就是一道空壕 */
  margin: var(--gap-m) 0 var(--gap);
  padding-bottom: .4rem;
  border-bottom: 1px solid var(--dan);
  display: inline-block;
}
.note {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.75;
  color: var(--ink-3);
}
.note--box {
  border-left: 3px solid var(--rule);
  padding: .8rem 0 .8rem 1rem;
  margin-top: var(--gap-l);
}

/* ---------- 标签 ---------- */
.tag {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  padding: .15rem .5rem;
  border: 1px solid var(--rule);
  color: var(--ink-3);
  white-space: nowrap;
}
.tag--warn {
  border-color: var(--dan);
  color: var(--dan-ink);
  background: color-mix(in srgb, var(--dan) 8%, transparent);
}

/* ============================================================
   证据等级
   有序色阶 + 图标 + 文字。颜色是冗余通道，不是唯一通道。
   ============================================================ */
.ev {
  display: inline-flex; align-items: center; gap: .32em;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1;
  padding: .3em .5em;
  white-space: nowrap;
  vertical-align: middle;
}
.ev__mark { font-size: .85em; }
.ev--4 { background: var(--ev-4); color: var(--ev-on); }
.ev--3 { background: var(--ev-3); color: var(--ev-on); }
.ev--2 { background: var(--ev-2); color: var(--ev-on); }
.ev--1 { background: var(--ev-1); color: var(--ev-on-1, var(--ev-on)); }

/* 行内引用标记 */
.refmark { display: inline-flex; gap: .18em; margin-left: .25em; vertical-align: super; }
.refmark__dot {
  font-family: var(--font-sans);
  font-size: .62em;
  line-height: 1;
  width: 1.5em; height: 1.5em;
  display: inline-grid; place-items: center;
  border: 1px solid var(--ev-3);
  color: var(--ev-3);
  background: none;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.refmark__dot:hover { background: var(--ev-3); color: var(--ev-on); }
.refmark__dot:focus-visible { outline: 2px solid var(--dan-ink); outline-offset: 2px; }

/* ============================================================
   幕一 · 见 —— 图谱
   ------------------------------------------------------------
   进来只看得见图与索引点。点开：图缩放到该处，标签滑出。
   克制：无投影、无卡片底色，只有一条发丝线与字距。
   ============================================================ */
.atlas {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

.atlas__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .3rem 1.1rem;
  padding-bottom: .6rem;
  border-bottom: 1px solid var(--rule-soft);
  margin-bottom: .55rem;
}
.atlas__kicker {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .2em;
  color: var(--ink-3);
  margin: 0;
}
.atlas__title {
  font-family: var(--font-serif);
  font-size: clamp(1.3rem, 2vw, 1.75rem);
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--ink);
  margin: 0;
}
.atlas__alias {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: .05em;
  margin: 0;
}

/* 画布：只负责居中。尺寸由 js 量出来写到 .atlas__frame 上，
   这样索引点的百分比坐标永远落在图上，不会落进留白。 */
.atlas__stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
/* ── 两侧栏 · 著录与细目 ──
   图在正中，两栏贴着图左右剩下的空白。绝对定位在画布里，
   不参与量图（fitFrame 量的是 clientWidth，两栏不吃宽度）。
   展开后整块淡出：放大四倍的纸面会盖过来，字不能从纸边露头。 */
.atlas__rec,
.atlas__idx {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: clamp(10.5rem, 19%, 14.5rem);
  max-height: 100%;
  overflow-y: auto;
  scrollbar-width: none;
  z-index: 2;
  transition: opacity .4s var(--ease), visibility 0s;
}
.atlas__rec::-webkit-scrollbar,
.atlas__idx::-webkit-scrollbar { width: 0; }
.atlas__rec { left: 0; }
.atlas__idx { right: 0; }

.atlas[data-open="1"] .atlas__rec,
.atlas[data-open="1"] .atlas__idx {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .26s var(--ease), visibility 0s linear .26s;
}

/* 栏目头：小字、宽字距，下面一条发丝线 */
.rail__hd {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .6rem;
  margin: 0 0 .55rem;
  padding-bottom: .42rem;
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-sans);
  font-size: .66rem;
  letter-spacing: .22em;
  color: var(--ink-2);
}
.rail__sub {
  font-size: .56rem;
  letter-spacing: .1em;
  color: var(--ink-3);
}

/* 著录：术语在左，值在右，行间一条发丝线 */
.rec {
  margin: 0;
  font-size: var(--fs-xs);
  line-height: 1.6;
}
.rec > div {
  display: grid;
  grid-template-columns: 3.1rem 1fr;
  gap: .1rem .6rem;
  padding: .34rem 0;
  border-bottom: 1px solid var(--rule-soft);
}
.rec > div:last-child { border-bottom: 0; }
.rec dt {
  font-family: var(--font-sans);
  font-size: .62rem;
  letter-spacing: .14em;
  color: var(--ink-3);
  padding-top: .12rem;
}
.rec dd {
  margin: 0;
  font-family: var(--font-serif);
  font-size: .78rem;
  line-height: 1.65;
  color: var(--ink-2);
  letter-spacing: .02em;
}
.rail__note {
  margin: .9rem 0 0;
  padding-top: .8rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-serif);
  font-size: .76rem;
  line-height: 1.95;
  color: var(--ink-3);
  letter-spacing: .03em;
  text-wrap: pretty;
}

/* 细目 */
.idx__grp {
  margin: .9rem 0 .3rem;
  font-family: var(--font-sans);
  font-size: .6rem;
  letter-spacing: .16em;
  color: var(--ink-3);
}
.idx__grp:first-of-type { margin-top: .2rem; }
.idx__list { list-style: none; margin: 0; padding: 0; }
.idx__item {
  display: grid;
  grid-template-columns: 1.6rem 1fr;
  align-items: baseline;
  gap: .1rem .4rem;
  width: 100%;
  padding: .2rem 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  color: var(--ink-2);
  transition: color .25s var(--ease);
}
.idx__n {
  font-family: var(--font-sans);
  font-size: .58rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: .06em;
  color: var(--ink-3);
  transition: color .25s var(--ease);
}
.idx__t {
  font-family: var(--font-serif);
  font-size: .79rem;
  line-height: 1.55;
  letter-spacing: .02em;
}
.idx__item:hover,
.idx__item:focus-visible {
  color: var(--dan-ink);
}
.idx__item:focus-visible {
  outline: 1px solid color-mix(in srgb, var(--dan) 55%, transparent);
  outline-offset: 2px;
}
.idx__item:hover .idx__n,
.idx__item:focus-visible .idx__n { color: var(--dan); }
.idx__item.is-on { color: var(--dan-ink); }
.idx__item.is-on .idx__n { color: var(--dan); }

/* 中段宽度：图变窄，两栏也必须跟着收，否则著录的术语行会甩到图底下 */
@media (max-width: 1200px) {
  .atlas__rec, .atlas__idx { width: clamp(9.5rem, 18%, 12.5rem); }
  .rec > div { grid-template-columns: 2.7rem 1fr; }
  .rec dd { font-size: .74rem; }
  .idx__t { font-size: .76rem; }
  .idx__item { grid-template-columns: 1.35rem 1fr; }
}

/* 倍数是自定义属性，注册成 <number> 才能补间；
   否则索引点的反缩放会在起手一瞬跳变。 */
@property --zoom {
  syntax: '<number>';
  inherits: true;
  initial-value: 1;
}
.atlas__frame {
  position: relative;
  margin: 0;
  line-height: 0;
  transform-origin: 50% 50%;
  transition: transform .78s cubic-bezier(.22, .61, .36, 1);
  /* 支持 @property 的浏览器走这条：图与索引点同步补间 */
  transition: transform .78s cubic-bezier(.22, .61, .36, 1),
              --zoom .78s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .atlas__frame { transition: none; }
  .atlas__dot { transition: background .3s var(--ease), color .3s var(--ease); }
}
.atlas__plate {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #FFF;
}

/* ── 索引点 ── */
.atlas__dots { position: absolute; inset: 0; }
.atlas__dot {
  position: absolute;
  left: var(--x);
  top: var(--y);
  /* 点在纸面里，会跟着图一起放大；除回去，让它始终保持一个点的大小。
     --zoom 是注册过的 <number>，会跟着图一起补间，所以这里不用再过渡。
     悬停放大走独立的 scale 属性，省得两者抢同一个 transform。 */
  transform: translate(-50%, -50%) scale(calc(1 / var(--zoom, 1)));
  scale: 1;
  width: 1.45rem; height: 1.45rem;
  padding: 0;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--ev-4) 42%, transparent);
  background: color-mix(in srgb, var(--paper-raised) 88%, transparent);
  color: var(--ev-4);
  /* 纸色外环：相邻两点挨得近时仍分得开，也不像投影 */
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--paper) 78%, transparent);
  font-family: var(--font-sans);
  font-size: .52rem;
  letter-spacing: .01em;
  line-height: 1;
  cursor: pointer;
  transition: scale .3s var(--ease), background .3s var(--ease),
              border-color .3s var(--ease), color .3s var(--ease),
              opacity .32s var(--ease);
}
.atlas__dot:hover,
.atlas__dot:focus-visible {
  background: var(--dan);
  border-color: var(--dan-ink);
  color: #FFF6EC;
  scale: 1.2;
  outline: none;
}
/* 展开后索引点退场，免得压在放大图上。
   只淡出、不缩放：缩放倍数 --zoom 是瞬时切换的，一旦参与计算
   这些点会先「跳」一下再消失。 */
.atlas[data-open="1"] .atlas__dot {
  opacity: 0;
  pointer-events: none;
  transition-delay: calc(var(--i) * 14ms);
}

/* ── 标签面板 ── */
.atlas__panel {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(27rem, 46%);
  display: flex;
  flex-direction: column;
  padding: 1.4rem 1.6rem 1rem;
  background: var(--paper);
  border-left: 1px solid var(--rule-soft);
  transform: translateX(101%);
  opacity: 0;
  visibility: hidden;
  z-index: 3;
  transition: transform .74s cubic-bezier(.22, .61, .36, 1),
              opacity .5s var(--ease),
              visibility 0s linear .74s;
}
.atlas[data-open="1"] .atlas__panel {
  transform: none;
  opacity: 1;
  visibility: visible;
  transition-delay: .1s, .16s, 0s;
}
.atlas__sheets { flex: 1 1 auto; min-height: 0; display: flex; }
/* 一张标签＝可滚的上半截 ＋ 钉在底部的出处 */
.atlas__sheet { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.atlas__sheet[hidden] { display: none; }
.atlas__scroll {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; padding-right: .3rem;
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}
/* 下面还有字时，底边淡出，别硬切（is-more 由 js 在滚动时摘挂） */
.atlas__scroll.is-more {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 1.8rem), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 1.8rem), transparent);
}
.atlas__scroll::-webkit-scrollbar { width: 6px; }
.atlas__scroll::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }
.atlas__scroll::-webkit-scrollbar-track { background: transparent; }

.atlas__grp {
  display: flex; align-items: baseline; gap: .8rem;
  /* 右端留给「返回全图」 */
  padding-right: 6.4rem;
  font-family: var(--font-sans);
  font-size: .66rem;
  letter-spacing: .16em;
  color: var(--ink-3);
  margin: 0 0 .5rem;
}
.atlas__num { order: -1; font-variant-numeric: tabular-nums; }
.atlas__name {
  font-family: var(--font-serif);
  font-size: 1.4rem;
  font-weight: 500;
  letter-spacing: .06em;
  line-height: 1.35;
  margin: 0 0 1rem;
  outline: none;
}
.atlas__crop { margin: 0 0 .9rem; text-align: center; }
/* 面板高度有限：裁片压到 17rem，整张标签（形、义、出处）才不用滚。
   保持方图比例，不裁不拉——这本就是「原样裁切」。 */
.atlas__crop img {
  display: block;
  width: auto; height: auto;
  max-width: 100%;
  max-height: 17rem;
  margin: 0 auto;
  border: 1px solid var(--rule);
  background: #FFF;
}
.atlas__crop figcaption {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  margin-top: .45rem;
  letter-spacing: .04em;
}
.atlas__facts {
  display: grid;
  grid-template-columns: 4.6rem 1fr;
  gap: .3rem .9rem;
  margin: 0 0 .9rem;
}
.atlas__facts > div { display: contents; }
.atlas__facts dt {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .1em;
  color: var(--ink-3);
}
.atlas__facts dd { margin: 0; font-size: var(--fs-sm); color: var(--ink-2); }
.atlas__form {
  font-size: var(--fs-sm);
  line-height: 1.95;
  color: var(--ink);
  margin: 0 0 .9rem;
}
.atlas__body {
  font-size: var(--fs-sm);
  line-height: 1.95;
  color: var(--ink-2);
  margin: 0 0 1rem;
}
.atlas__cite {
  flex: none;
  border-top: 1px solid var(--rule-soft);
  padding-top: .65rem;
  font-size: var(--fs-xs);
  line-height: 1.9;
  color: var(--ink-3);
  margin: .2rem 0 .6rem;
  /* 出处是长书名串，宁可断行也不许顶出面板 */
  overflow-wrap: anywhere;
}
.atlas__cite-k {
  display: inline-block;
  min-width: 3.4rem;
  letter-spacing: .16em;
  color: var(--ink-2);
}
.atlas__foot {
  flex: none;
  border-top: 1px solid var(--rule-soft);
  padding-top: .65rem;
  margin-top: .5rem;
}
.atlas__credit {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.7;
  color: var(--ink-3);
  margin: 0;
}

/* ── 返回 ──
   挂在题头行末（margin-left:auto），跟着标题一起读，
   不做浮在画上的按钮。未展开时只是隐藏，仍占位，展开不跳版。 */
.atlas__back {
  position: absolute;
  top: 1.12rem; right: 1.35rem;
  z-index: 4;
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .2rem 0;
  border: 0;
  background: none;
  color: var(--ink-3);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .12em;
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateX(.4rem);
  transition: opacity .4s var(--ease), transform .5s var(--ease),
              color .3s, visibility 0s linear .5s;
}
.atlas[data-open="1"] .atlas__back {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: .2s, .2s, 0s, 0s;
}
.atlas__back:hover, .atlas__back:focus-visible { color: var(--dan-ink); outline: none; }

.atlas__hint {
  flex: none;
  margin: .4rem 0 0;
  text-align: center;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .08em;
  color: var(--ink-3);
  transition: opacity .35s var(--ease);
}
.atlas__hint.is-gone { opacity: 0; }

/* 窄屏：面板改为底部抽屉 */
@media (max-width: 900px) {
  .atlas__panel {
    top: auto; left: 0; right: 0; bottom: 0;
    width: auto;
    max-height: 64%;
    border-left: 0;
    border-top: 1px solid var(--rule-soft);
    padding: 1.2rem 1.2rem .9rem;
    transform: translateY(101%);
  }
  .atlas[data-open="1"] .atlas__panel { transform: none; }
  /* 窄屏上，抽屉正上方的放大图就是这张裁片；
     再摆一张，只会把形与义挤出屏幕。 */
  .atlas__crop { display: none; }
  /* 两栏在窄屏没有位置：抽屉会压住下半，留白也不够 */
  .atlas__rec, .atlas__idx { display: none; }
}

/* 非环模式（脚本未跑时的纵向文档）给画布一个确定高度 */
body:not(.is-ring) .atlas__stage { height: min(74vh, 680px); }

.artwrap { margin: 0; }
.art {
  width: 100%; height: auto;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
}
.art__anchor {
  fill: var(--paper-raised);
  stroke: var(--ev-3);
  stroke-width: 2.5;
  cursor: pointer;
  transition: r var(--dur) var(--ease), fill var(--dur) var(--ease);
}
.art__anchor.is-on { fill: var(--dan); stroke: var(--dan-ink); r: 11; }

.tag--real {
  background: var(--ev-4);
  color: var(--ev-on);
  border-color: transparent;
}
.artwrap__cap {
  display: flex; flex-wrap: wrap; gap: .5rem;
  align-items: center;
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--ink-3);
  margin-top: .7rem;
}

/* ============================================================
   幕二 · 立体时间轴
   ------------------------------------------------------------
   一条「脊」沿 X 轴铺开，节点左右交错、前后错落，
   各用一根立杆接回脊上。整条轴放在一个被透视的平面里，
   拖动时平面的角度跟着变——深度是真的，不是画出来的。
   ============================================================ */
.act--source { display: flex; flex-direction: column; position: relative; }
/* 环面上底部有一条导览条，抽屉要停在它上面 */
body.is-ring .act--source { --tp-b: 4.2rem; }
.act--source .act__head { max-width: none; margin-bottom: 1rem; }
/* 幕二的门面：标题放大一号，说明压成一行。
   两处加起来省下近百像素，全部让给下面的立体轴。 */
.act--source .act__title {
  font-size: clamp(1.85rem, 4.7vw, 3.3rem);
  line-height: 1.1;
  margin-bottom: .3rem;
}
.act--source .act__head .lede {
  max-width: none;
  font-size: 1rem;
  line-height: 1.7;
}
.act--source .chips { margin-bottom: .85rem; }

/* ---------- 篇章 chips ---------- */
.chips {
  display: flex; flex-wrap: wrap; gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--gap);
}
.chchip {
  appearance: none; background: none; border: 0; cursor: pointer;
  display: flex; align-items: baseline; gap: .45rem;
  padding: .62rem clamp(.7rem, 1.4vw, 1.1rem);
  border-right: 1px solid var(--rule-soft);
  font: inherit; color: var(--ink-3);
  transition: color .25s var(--ease), background .25s var(--ease);
}
.chchip:last-child { border-right: 0; }
.chchip:hover { color: var(--ink); background: var(--paper-sunk); }
.chchip:focus-visible { outline: 1px solid var(--ink); outline-offset: -2px; }
.chchip.is-on { color: var(--ink); background: var(--paper-sunk); }
.chchip.is-on .chchip__n { color: var(--dan-ink); }
.chchip__n {
  font-family: var(--font-sans); font-size: var(--fs-xs);
  letter-spacing: .08em; transition: color .25s var(--ease);
}
.chchip__t { font-size: var(--fs-sm); letter-spacing: .06em; }
.chchip__s {
  font-family: var(--font-sans); font-size: 11px;
  letter-spacing: .06em; opacity: .7;
}

/* ---------- 舞台 ---------- */
.tree {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  height: clamp(330px, 52vh, 560px);
  overflow: hidden;
  perspective: 1500px;
  perspective-origin: 50% 42%;
  cursor: grab;
  touch-action: pan-y;
  /* 边缘淡出：轴的两端不要被硬切 */
  mask-image: linear-gradient(to right, transparent, #000 2.5%, #000 97.5%, transparent);
}
.tree.is-drag { cursor: grabbing; }
.tree__pan {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}
.tree__stage {
  position: relative;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 24deg)) rotateY(var(--ry, 0deg));
  transition: transform .5s var(--ease);
}
.tree.is-drag .tree__stage { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .tree__stage { transition: none; transform: none; }
}

/* 地平面上的网格：这一步是「立体」最便宜也最有效的一笔 */
/* ⚠️ 网格和脊都铺满整个舞台，又是 z=0 的一块「实面」。
   远节点在平面之后（translateZ 为负），指针会先撞上这两块，
   于是「轴下半边的点点不动」。装饰层一律不吃指针。 */
.tree__grid {
  position: absolute; inset: -30% 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, var(--rule) 0 1px, transparent 1px 158px),
    repeating-linear-gradient(0deg, var(--rule-soft) 0 1px, transparent 1px 74px);
  opacity: .62;
  mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
}
/* 脊 */
.tree__spine {
  position: absolute; left: 0; right: 0; top: 50%;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(to right,
    transparent, var(--ink-3) 2%, var(--ink-3) 98%, transparent);
  opacity: .9;
}
/* 立杆 */
.tn__stem {
  position: absolute; left: 0; width: 1px;
  pointer-events: none;
  background: linear-gradient(to bottom, var(--ink-3), var(--rule));
  opacity: .55;
}

/* ---------- 节点 ---------- */
/* ⚠️ 这张 <ol> 铺满整个舞台，又是一块 z=0 的实面。
   轴下半边的节点 translateZ 为负、落在它后面，指针就先撞上它——
   「下半场点点不动」就是这个原因。容器一律不吃指针，只放按钮进来。 */
.tree__tns {
  position: absolute; inset: 0;
  list-style: none; margin: 0; padding: 0;
  transform-style: preserve-3d;
  pointer-events: none;
}
/* --fit 由 JS 按树高写回（见 applyCam）：小窗口里树只有一百来像素高，
   而节点是按 ±150px 的波形布开的，不整体收一点，轴就会画到页签条上，
   命中也跟着出界。0.26 是下限：再扁就不像一条走廊了。 */
.tn {
  position: absolute; left: 0; top: calc(50% + var(--y) * var(--fit, 1));
  width: 0; height: 0;
  transform-style: preserve-3d;
}
/* 地面上的一枚接触影：节点浮着，还是贴在地上，靠这一笔分辨。
   刻意压到 12% ——它是深度的线索，不是投影效果。 */
.tn__sh {
  position: absolute; left: -17px; top: -5px;
  pointer-events: none;
  width: 26px; height: 8px; border-radius: 50%;
  background: radial-gradient(ellipse at center,
    color-mix(in srgb, var(--ink) 30%, transparent), transparent 72%);
  opacity: .26;
}
.tn__rod {
  position: absolute; left: 0; bottom: 0;
  pointer-events: none;
  width: 1px; height: var(--h);
  transform-origin: 50% 100%;
  transform: rotateX(var(--r));
  background: linear-gradient(to top, var(--rule), var(--ink-3));
  opacity: .55;
}
.tn__b {
  position: absolute; left: -11px; top: -11px;
  width: 22px; height: 22px; padding: 0;
  appearance: none; background: none; border: 0; cursor: pointer;
  /* 先落到深度上，再把镜头转回来——节点是「立牌」，不是贴在地上的字。
     反转的顺序必须是 rotateY 再 rotateX，才真正抵掉父级的 Rx·Ry。 */
  transform: translateZ(calc(var(--z) * var(--fit, 1)))
             rotateY(var(--cry, 0deg)) rotateX(var(--crx, 0deg));
  transform-style: preserve-3d;
  /* 父级 .tree__tns 已经 pointer-events:none，得在这里把事件收回来 */
  pointer-events: auto;
  font: inherit; color: var(--ink-2);
}
.tn__dot {
  position: absolute; inset: 2px;
  border: 1px solid var(--ink-3); border-radius: 50%;
  background: var(--paper);
  transition: background .25s var(--ease), border-color .25s var(--ease),
              box-shadow .25s var(--ease);
}
/* ---------- 章标：落在轴下方的分期 ---------- */
.tree__chs {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  pointer-events: none;
}
.tch {
  position: absolute; left: 0; top: calc(50% + 184px * var(--fit, 1));
  width: 0; height: 0;
  transform-style: preserve-3d;
}
.tch__in {
  position: absolute; left: 0; top: 0;
  display: flex; align-items: baseline; gap: .5rem;
  white-space: nowrap;
  transform: translate(-50%, -50%) rotateY(var(--cry, 0deg)) rotateX(var(--crx, 0deg));
  font-family: var(--font-sans);
  color: var(--ink-3);
}
/* 首段的章标贴左摆：它离轴端太近，居中会被 .tree 的淡出吃掉半个字 */
.tch--flush .tch__in {
  transform: translate(0, -50%) rotateY(var(--cry, 0deg)) rotateX(var(--crx, 0deg));
}
.tch--flush::before { left: 0; }
.tch__n { font-size: 11px; letter-spacing: .18em; color: var(--dan-ink); }
.tch__t { font-size: 16px; letter-spacing: .16em; color: var(--ink-2); }
.tch__s { font-size: 10px; letter-spacing: .1em; opacity: .8; }
.tch::before {
  /* 分期下面一道极短的横线，把这段「框」住 */
  content: ''; position: absolute;
  left: -26px; top: -7px; width: 52px; height: 1px;
  background: var(--rule);
}
.tch--c1 .tch__n { color: var(--qing); }
.tch--c2 .tch__n { color: var(--dan); }
.tch--c3 .tch__n { color: var(--mo); }
.tch--c5 .tch__n { color: var(--dan-ink); }

/* 章色：只落在圆环这一道上，不染满节点 */
.tn--c1 .tn__dot { border-color: var(--qing); }
.tn--c2 .tn__dot { border-color: var(--dan); }
.tn--c3 .tn__dot { border-color: var(--mo); }
.tn--c5 .tn__dot { border-color: var(--dan-ink); }
/* 窄屏时间轴被压到约 240px 高，章标会与底部节点文字叠在一起。
   顶部章次条已经给出同样的分期，窄屏直接收起章标。 */
@media (max-width: 560px) {
  .tree__chs { display: none; }
}
.tn__b:hover .tn__dot,
.tn__b:focus-visible .tn__dot { background: var(--dan); border-color: var(--dan); }
.tn__b:focus-visible { outline: none; }
.tn__b:focus-visible .tn__tt { color: var(--ink); text-decoration: underline; }
.tn.is-on .tn__dot { background: var(--ink); border-color: var(--ink); }
.tn.is-on .tn__tt { color: var(--ink); }

/* 年份在点上方，标题在点下方——两行字都是「贴片」，
   不随平面倾斜而倒下去，读起来才不吃力。 */
.tn__yr {
  position: absolute; left: 50%; top: 100%;
  transform: translateX(-50%);
  margin-top: 7px; white-space: nowrap;
  font-family: var(--font-sans); font-size: 11.5px;
  letter-spacing: .07em; color: var(--ink-2);
  pointer-events: none;
}
.tn__tt {
  position: absolute; left: 50%; top: 100%;
  transform: translateX(-50%);
  margin-top: 25px; width: 130px;
  font-size: 12.5px; line-height: 1.5; letter-spacing: .02em;
  text-align: center; color: var(--ink-2);
  pointer-events: none;
  transition: color .25s var(--ease);
}
/* 单数格把整块说明翻到点上方，双数格留在下方——
   相邻两格的标题永远不在同一行。 */
.tn--up .tn__tt {
  top: auto; bottom: 100%; margin: 0 0 25px;
}
.tn--up .tn__yr {
  top: auto; bottom: 100%; margin: 0 0 7px;
}

/* 旁支：菱形 + 抬高，一眼能看出「这条不在主干上」 */
.tn--branch .tn__dot { border-radius: 0; transform: rotate(45deg) scale(.82); }
.tn--branch .tn__tt { font-style: italic; }
/* 勘误节点：唯一一处淡朱底 */
.tn--err .tn__dot { background: color-mix(in srgb, var(--dan) 18%, var(--paper)); border-color: var(--dan-ink); }
/* 谷底：唯一一处灰调 */
.tn--dark .tn__dot { background: var(--paper-sunk); border-color: var(--ink-3); opacity: .75; }
.tn--dark .tn__tt { color: var(--ink-3); }

/* ---------- 首尾翻页 + 提示 ---------- */
.tree__arrow {
  position: absolute; top: 50%; z-index: 3;
  width: 2.1rem; height: 2.1rem; margin-top: -1.05rem;
  appearance: none; background: color-mix(in srgb, var(--paper) 86%, transparent);
  border: 1px solid var(--rule); border-radius: 50%;
  color: var(--ink-2); font-size: 1rem; line-height: 1; cursor: pointer;
  backdrop-filter: blur(4px);
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.tree__arrow:hover { color: var(--ink); border-color: var(--ink-3); }
.tree__arrow:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
.tree__arrow--l { left: .2rem; }
.tree__arrow--r { right: .2rem; }
.tree__hint {
  position: absolute; right: 1rem; bottom: .5rem;
  margin: 0; font-family: var(--font-sans);
  font-size: 10px; letter-spacing: .16em; color: var(--ink-3);
  pointer-events: none;
  transition: opacity .4s var(--ease);
}
.tree.is-open .tree__hint { opacity: 0; }

/* ---------- 底部的全轴缩略 ----------
   不只是「位置指示」：整条可以按住拖，窗口跟着手指走，轴同步平移。
   命中区做成一整条 30px，比 5px 的刻度好按得多。 */
.tmap {
  position: relative;
  height: 30px; margin-top: .3rem;
  border-top: 1px solid var(--rule);
  flex: 0 0 auto;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.tmap.is-drag { cursor: grabbing; }
.tmap__tick {
  position: absolute; top: 12px;
  width: 5px; height: 5px; padding: 0; margin-left: -2.5px;
  appearance: none; border: 0; border-radius: 50%;
  background: var(--ink-3); cursor: pointer;
  transition: background .2s var(--ease), transform .2s var(--ease);
}
.tmap__tick::before {
  /* 5px 的点太难点，命中区放大到 18px */
  content: ''; position: absolute; inset: -7px;
}
.tmap__tick:hover { transform: scale(1.5); }
.tmap__tick--c1 { background: var(--qing); }
.tmap__tick--c2 { background: var(--dan); }
.tmap__tick--c3 { background: var(--mo); }
.tmap__tick--c4 { background: var(--ink-3); }
.tmap__tick--c5 { background: var(--dan-ink); }
.tmap__tick.is-on { transform: scale(1.9); }
.tmap__win {
  position: absolute; top: 8px; height: 15px;
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  pointer-events: none;
  transition: left .3s var(--ease), width .3s var(--ease),
              border-color .25s var(--ease);
}
.tmap:hover .tmap__win { border-color: color-mix(in srgb, var(--ink) 40%, transparent); }
/* 拖动时窗口必须跟手，不能有补间，否则总慢半拍 */
.tmap.is-drag .tmap__win {
  transition: none;
  border-color: var(--dan);
  background: color-mix(in srgb, var(--dan) 10%, transparent);
}

/* ---------- 节点详情面板 ---------- */
.tpanel {
  position: absolute; top: 0; right: 0; bottom: var(--tp-b, 0);
  width: min(30rem, 44%);
  display: flex; flex-direction: column;
  background: var(--paper-raised);
  border-left: 1px solid var(--rule);
  transform: translateX(101%);
  transition: transform .72s var(--ease);
  z-index: 5;
}
.act--source.is-open .tpanel { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .tpanel { transition: none; }
}
.tpanel__back {
  position: absolute; top: .85rem; right: 1rem; z-index: 2;
  appearance: none; background: none; border: 0; cursor: pointer;
  font-family: var(--font-sans); font-size: var(--fs-xs);
  letter-spacing: .1em; color: var(--ink-3);
  padding: .3rem .1rem;
  transition: color .25s var(--ease);
}
.tpanel__back:hover { color: var(--ink); }
.tpanel__back:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
.tpanel__scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 1.15rem clamp(1rem, 2vw, 1.6rem) 1.5rem;
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}
.tp__meta {
  display: flex; align-items: center; gap: .6rem;
  margin: 0 0 .5rem; padding-right: 6.5rem;
  font-family: var(--font-sans); font-size: 11px;
  letter-spacing: .1em; color: var(--ink-3);
}
.tp__ch { color: var(--dan-ink); }
.tp__num { margin-left: auto; letter-spacing: .06em; }
.tp__year {
  margin: 0 0 .2rem;
  font-size: 1.55rem; letter-spacing: .02em; line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.tp__yn {
  display: block; margin-top: .18rem;
  font-family: var(--font-sans); font-size: 11px;
  letter-spacing: .12em; color: var(--ink-3);
}
.tp__title {
  margin: .3rem 0 .9rem; font-size: var(--fs-h3);
  font-weight: 400; letter-spacing: .03em; text-wrap: balance;
}
.tp__title:focus { outline: none; }

/* 图像位：每一格都配一张核对过的图。
   图注分两行——上行为「画的是什么」，下行为「图从哪来」。 */
.tp__fig {
  position: relative; margin: 0 0 1rem;
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
  overflow: hidden;
}
/* 竖幅年画按宽度铺满会把抽屉撑到两屏高。给高度封顶，图完整、字还能看见 */
.tp__fig img {
  width: 100%; height: auto; display: block;
  max-height: 46vh; object-fit: contain;
  background: var(--paper-sunk);
}
.tp__fig--sub img { max-height: 30vh; }
.tp__cap {
  margin: 0; padding: .55rem .8rem .6rem;
  border-top: 1px solid var(--rule);
  background: var(--paper-raised);
  font-family: var(--font-sans); font-size: 11px; line-height: 1.65;
  color: var(--ink-3);
  text-align: left;
}
.tp__cap-c { display: block; }
.tp__cap-s { display: block; margin-top: .28rem; }
.tp__cap-s a {
  color: inherit; text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 2px;
}
.tp__cap-s a:hover { color: var(--dan-ink); }
.tp__lead { font-size: var(--fs-sm); line-height: 1.85; color: var(--ink-2); }
.tp__quote {
  margin: 0 0 .5rem; padding: .1rem 0 .1rem .9rem;
  border-left: 1px solid var(--dan);
  font-size: var(--fs-sm); line-height: 1.9;
}
.tp__quote p { margin: 0 0 .35rem; }
.tp__quote p:last-child { margin-bottom: 0; }
.tp__from {
  margin: 0 0 1.1rem;
  font-family: var(--font-sans); font-size: 11px;
  letter-spacing: .04em; color: var(--ink-3);
}
.tp__body { font-size: var(--fs-sm); line-height: 1.85; color: var(--ink-2); }
.tp__note {
  display: grid; grid-template-columns: 3.2rem minmax(0, 1fr);
  gap: .6rem; padding-top: .8rem; margin-top: .4rem;
  border-top: 1px solid var(--rule-soft);
}
.tp__note-k {
  font-family: var(--font-sans); font-size: 10px;
  letter-spacing: .16em; color: var(--dan-ink); padding-top: .2rem;
}
.tp__note p { margin: 0; font-size: 12px; line-height: 1.75; color: var(--ink-3); }
.tp__cite {
  flex: 0 0 auto;
  margin: 0; padding: .8rem clamp(1rem, 2vw, 1.6rem);
  border-top: 1px solid var(--rule);
  background: var(--paper-raised);
  font-size: 11px; line-height: 1.7; color: var(--ink-3);
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem;
}
.tp__cite-k {
  font-family: var(--font-sans); font-size: 10px;
  letter-spacing: .16em; color: var(--ink-2);
}
.ev--0 { color: var(--ink-3); }

/* 矮窗口（1366×768、1024×700 这类笔记本）：幕二的头压一压，
   省下的高度全给下面那条轴。树高每多一点，--fit 就大一点，
   字才不会挤成一片——这条轴要的是竖向余量，不是大字。 */
@media (max-height: 780px) {
  .act--source .act__head { margin-bottom: .5rem; }
  .act--source .act__title {
    font-size: clamp(1.5rem, 3.6vw, 2.35rem);
    margin-bottom: .2rem;
  }
  .act--source .act__head .lede { font-size: .94rem; line-height: 1.5; }
  .act--source .chips { margin-bottom: .5rem; }
  .act--source .chchip { padding-top: .42rem; padding-bottom: .42rem; }
}

@media (max-width: 900px) {
  .tree { height: clamp(300px, 46vh, 420px); }
  .tn__tt { width: 84px; font-size: 11px; }
  .chchip__s { display: none; }
  .tpanel {
    top: auto; left: 0; right: 0; width: auto;
    height: 66%;
    border-left: 0; border-top: 1px solid var(--rule);
    transform: translateY(101%);
  }
  .act--source.is-open .tpanel { transform: none; }
  /* 抽屉开时锁住幕本身：它是绝对定位、随幕滚动的，
     幕再滚一格，抽屉就往上跑一格，最终钻到顶栏后面。 */
  body.is-ring .ring > .act--source.is-drawer { overflow-y: hidden; }
  .tp__quote, .tp__from, .tp__body, .tp__note { display: none; }
}

/* ============================================================
   幕三 · 套印
   ============================================================ */
.layerlab {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--gap-l);
  align-items: start;
}
.layerlab__art {
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  position: relative;
  /* 不能 overflow:hidden —— 一裁就把拉开后的版片切掉。
     透视放在这一层，.stack 只负责 preserve-3d。 */
  padding: 1.5rem 1rem 2.4rem;
  margin: 0;
  perspective: 1900px;
  perspective-origin: 50% 42%;
}

/* ── 版片叠印台 ──
   每一层是「纸白 → 该色」的可乘图层，用 multiply 叠起来即复原成画。
   内衬必须是纯白（不是纸色），否则 multiply 会整体偏色。
   这是唯一一处页面里出现纯白的地方——它是印纸，不是界面。 */
.stack {
  position: relative;
  /* 比容器窄 4rem：拉开时纸要往两边错，不留出这条余量就会压到画框边上 */
  width: calc(100% - 4rem);
  margin: 0 auto;
  aspect-ratio: 1200 / 2104;
  background: #FFFFFF;
  border: 1px solid var(--rule-soft);
  transform-style: preserve-3d;
}
/* 每层按 --k 沿三个轴错开：z 拉开厚度，x/y 轻微斜推，
   否则同尺寸的纸会完全叠住，看不出有几块版。
   数值由 #explodeslider 写在 .stack 上，0 时三者皆为 0，即原来的合版。 */
.stack__l {
  position: absolute; inset: 0;
  /* 这张白纸是「版」的实体：合版时 multiply 会把白色吃掉，
     拉开时它是唯一挡住下层的东西。 */
  background: #FFFFFF;
  mix-blend-mode: multiply;
  opacity: 0;
  /* 末尾那个反向缩放是关键：透视会把靠前的纸放大，
     不抵消的话前面的纸会把后面的整个盖住，拉开也看不见「几块版」。
     1 - z/P 正好抵掉透视放大，各纸看起来一样大，只剩错位。 */
  /* --kc 以这叠纸的中心为 0，往前一张右上一格、往后一张左下一格，
     扇面因此是居中展开的，不会把纸推出画框。 */
  --kc: calc(var(--k, 0) - var(--half, 0));
  transform: translate3d(
    calc(var(--kc) * var(--sx, 0px)),
    calc(var(--kc) * var(--sy, 0px)),
    calc(var(--kc) * var(--sz, 0px))
  ) scale(calc(1 - var(--k, 0) * 0.024 * var(--e, 0)))
    rotate(calc(var(--kc) * var(--rot, 0deg)));
  transition: opacity .4s var(--ease), transform .45s var(--ease);
}
.stack__l img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
}
.stack__l.is-on { opacity: 1; }

/* 拉开后每张纸是独立的一张「印张」，不能再用 multiply——
   三维里前后层的混合底不再是那块纯白。 */
.stack.is-open .stack__l {
  mix-blend-mode: normal;
  /* 每张纸染一点它自己的色，再描一道同色细边——
     四张白纸叠在浅底上，不给边就只剩影子。
     只在拉开时生效：合版时任何底色都会污染复原结果。 */
  background: color-mix(in srgb, var(--tint, #FFF) 10%, #FFF);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tint, #000) 26%, transparent);
}
.stack.is-open { background: transparent; border-color: transparent; }

.layerlab__tag {
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  margin: .75rem 0 .75rem;
}

.layerlab__ctrl { display: flex; flex-direction: column; gap: .6rem; }
.note--method {
  border-left: 2px solid var(--rule);
  padding-left: .75rem;
  line-height: 1.7;
}

/* ============================================================
   纹样志 —— 从实物上裁下来的单元 + 出处定位图
   ============================================================ */
/* ============================================================
   同题异本 + 真版片
   ============================================================ */
.vars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--gap-l);
  align-items: start;
}

.var { margin: 0; }

/* 图版高度不一（立轴高、版片扁），统一到一个画框高度里居中，避免参差 */
.var__art {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 340px;
  padding: .5rem;
  background: #FFFFFF;
  border: 1px solid var(--rule);
}
.var__art img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

.var__cap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem;
  margin-top: .7rem;
}
.var__tag {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--paper);
  background: var(--dan-ink);
  padding: .1em .5em;
}
.var__n {
  font-size: 1.05em;
  font-weight: 600;
  letter-spacing: .04em;
}
.var__spec {
  margin-top: .35rem;
  font-size: var(--fs-xs);
  color: var(--ink-3);
  line-height: 1.7;
}
.var__b {
  margin-top: .55rem;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.85;
}

@media (max-width: 720px) {
  .var__art { height: 260px; }
}

.lbl {
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--ink-2); letter-spacing: .06em;
}
input[type=range] {
  width: 100%; accent-color: var(--dan);
  margin: .2rem 0 .8rem;
}
.layerlist { list-style: none; margin: 0; padding: 0; }
.layerlist li {
  display: grid;
  grid-template-columns: auto auto;
  gap: .1rem .7rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--rule-soft);
  opacity: .38;
  transition: opacity var(--dur) var(--ease);
}
.layerlist li.is-on { opacity: 1; }
.swatch {
  width: 1.1rem; height: 1.1rem;
  border-radius: 2px;
  border: 1px solid rgba(0,0,0,.12);
  grid-row: span 2;
  margin-top: .25rem;
}
.layerlist__name { font-size: var(--fs-sm); }
.layerlist__note {
  grid-column: 2;
  margin: 0;
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--ink-3); line-height: 1.7;
}
.layerlist__hint {
  margin: 0 0 .2rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .04em;
  color: var(--ink-3);
}

/* 色块是按钮：点一下单看这一版，再点回到合版 */
.swatch {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  padding: 0;
  width: 1.1rem; height: 1.1rem;
  border-radius: 2px;
  border: 1px solid rgba(0,0,0,.18);
  grid-row: span 2;
  margin-top: .25rem;
  cursor: pointer;
  touch-action: manipulation;
  transition: box-shadow .2s var(--ease), transform .2s var(--ease);
}
/* 色块本身只有 1.1rem，把可点范围撑到约 42px，手指也够得着 */
.swatch::after {
  content: '';
  position: absolute;
  inset: -11px;
}
.swatch:hover { transform: scale(1.16); }
.swatch:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
.swatch[aria-pressed="true"] {
  box-shadow: 0 0 0 2px var(--paper-raised), 0 0 0 3px var(--ink);
}
.layerlist li.is-solo-on { opacity: 1; }
.layerlist li.is-solo-on .layerlist__name { font-weight: 600; }

/* 单看一版：其余印张退到后面，只留这一张 */
.stack.is-solo .stack__l { opacity: 0; }
.stack.is-solo .stack__l.is-soloed { opacity: 1; }
.stack.is-solo .stack__l.is-soloed {
  transform: translate3d(0, 0, 46px) scale(1.012);
  box-shadow: 0 26px 60px -34px rgba(0, 0, 0, .55);
}
.stack.is-solo {
  border-color: color-mix(in srgb, var(--solo-tint, var(--ink)) 40%, transparent);
}

/* ============================================================
   图像志 · 六个看得见的证据
   六张细部从本谱图版原样裁下；卡片随指针微倾，点开看细节与定位
   ============================================================ */
.icono__hint {
  margin: .2rem 0 0;
  max-width: var(--measure);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.8;
  color: var(--ink-3);
}
.icono {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap);
  margin-top: var(--gap);
  perspective: 1500px;
}
.icono__card {
  --rx: 0deg;
  --ry: 0deg;
  --mx: 50%;
  --my: 50%;
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  background: var(--paper-raised);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: zoom-in;
  transform: rotateX(var(--rx)) rotateY(var(--ry));
  transition: transform .18s ease-out, border-color .3s var(--ease),
              box-shadow .3s var(--ease);
  align-self: stretch;
}
.icono__card:hover,
.icono__card:focus-visible {
  border-color: var(--ink-3);
  box-shadow: 0 30px 54px -34px rgba(0, 0, 0, .5);
}
.icono__card:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
.icono__fig {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: #FAF5E9;
  border-bottom: 1px solid var(--rule-soft);
}
.icono__fig img {
  width: 100%; height: 100%;
  display: block;
  object-fit: contain;
  transition: transform .6s var(--ease);
}
.icono__card:hover .icono__fig img,
.icono__card:focus-visible .icono__fig img {
  transform: scale(1.05);
}
/* 指针经过时的一层斜光，让卡面有纸的厚度 */
.icono__fig::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    420px circle at var(--mx) var(--my),
    rgba(255, 255, 255, .45),
    rgba(255, 255, 255, 0) 62%
  );
  mix-blend-mode: soft-light;
  transition: opacity .3s var(--ease);
}
.icono__card:hover .icono__fig::after { opacity: 1; }
.icono__no {
  position: absolute;
  top: .55rem; left: .55rem;
  padding: .08rem .38rem;
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: .12em;
  color: var(--paper);
  background: rgba(28, 26, 23, .76);
  border-radius: 2px;
}
.icono__zoom {
  position: absolute;
  right: .55rem; bottom: .55rem;
  padding: .12rem .5rem;
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: .06em;
  color: var(--ink);
  background: color-mix(in srgb, var(--paper-raised) 90%, transparent);
  border: 1px solid var(--rule);
  border-radius: 999px;
  opacity: 0;
  transform: translateY(5px);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.icono__card:hover .icono__zoom,
.icono__card:focus-visible .icono__zoom {
  opacity: 1;
  transform: none;
}
.icono__body {
  display: block;
  flex: 1 1 auto;
  padding: .85rem 1rem 0;
}
.icono__t {
  display: block;
  margin-bottom: .35rem;
  font-size: var(--fs-h3);
  letter-spacing: .04em;
}
.icono__b {
  display: block;
  font-size: var(--fs-sm);
  line-height: 1.8;
  color: var(--ink-2);
}
.icono__credit {
  display: block;
  margin: .7rem 1rem 0;
  padding: .45rem 0 .9rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: var(--ink-3);
}

/* ── 细部放大 ── */
.icov {
  position: fixed;
  inset: 0;
  z-index: 95;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vh 3vw;
}
.icov[hidden] { display: none; }
.icov__bd {
  position: absolute;
  inset: 0;
  background: rgba(18, 16, 13, .64);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.icov__sheet {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(0, .82fr);
  gap: 1.4rem;
  width: min(1080px, 94vw);
  max-height: 90vh;
  padding: 1.2rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 44px 96px -34px rgba(0, 0, 0, .6);
  overflow: auto;
  animation: icovIn .34s var(--ease) both;
}
@keyframes icovIn {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
.icov__x {
  position: absolute;
  top: .55rem; right: .55rem;
  z-index: 2;
  width: 2rem; height: 2rem;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 1.15rem;
  line-height: 1;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 50%;
  cursor: pointer;
}
.icov__x:hover { border-color: var(--ink-3); }
.icov__x:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.icov__art {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 240px;
  padding: .4rem;
  background: #FFFFFF;
  border: 1px solid var(--rule-soft);
}
.icov__art img {
  display: block;
  width: auto; height: auto;
  max-width: 100%;
  max-height: 74vh;
  object-fit: contain;
}
.icov__cap {
  position: relative;
  padding: .3rem .3rem .3rem .1rem;
  overflow: auto;
}
.icov__k {
  margin: 0 0 .35rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .16em;
  color: var(--ink-3);
}
.icov__t {
  margin: 0 0 .6rem;
  font-size: var(--fs-h2);
  letter-spacing: var(--ls-title);
}
.icov__b {
  margin: 0 0 .85rem;
  font-size: var(--fs-sm);
  line-height: 1.9;
  color: var(--ink-2);
}
.icov__map {
  float: right;
  width: 92px;
  margin: 0 0 .6rem .9rem;
}
.icov__mapart {
  position: relative;
  display: block;
  overflow: hidden;
  border: 1px solid var(--rule);
  background: #FFFFFF;
}
.icov__mapart img {
  display: block;
  width: 100%; height: auto;
}
.icov__box {
  position: absolute;
  border: 2px solid #E03A20;
  box-shadow: 0 0 0 9999px rgba(18, 16, 13, .36);
  pointer-events: none;
}
.icov__map em {
  display: block;
  margin-top: .32rem;
  font-style: normal;
  font-family: var(--font-sans);
  font-size: 10.5px;
  line-height: 1.5;
  text-align: center;
  color: var(--ink-3);
}
.icov__src {
  clear: both;
  margin: 0;
  padding-top: .7rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.75;
  color: var(--ink-3);
}

@media (max-width: 1100px) {
  .icono { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .icov { padding: 0; align-items: stretch; }
  .icov__sheet {
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
    max-height: 100vh;
    border: 0;
    border-radius: 0;
    padding: 2.6rem 1rem 1.4rem;
  }
  .icov__art { min-height: 0; }
  .icov__art img { max-height: 48vh; }
  .icov__t { font-size: var(--fs-h3); }
}
@media (max-width: 720px) {
  .icono { grid-template-columns: minmax(0, 1fr); }
  .icov__map { width: 72px; }
}
@media (prefers-reduced-motion: reduce) {
  .icono__card,
  .icono__fig img,
  .icono__fig::after,
  .icono__zoom,
  .swatch,
  .icov__sheet {
    transition: none;
    animation: none;
  }
  .icono__card { transform: none; }
}

/* 卡片 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--gap);
  margin-top: var(--gap);
}
.card {
  background: var(--paper-raised);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
}
.card--ghost { border-style: dashed; opacity: .7; }
.card__t { font-size: var(--fs-h3); margin: 0 0 .4rem; letter-spacing: .04em; }
.card p { font-size: var(--fs-sm); color: var(--ink-2); margin: 0; }

/* ============================================================
   幕四 · 戏
   ============================================================ */
.fanzhuang { margin-bottom: var(--gap-l); }
.fanzhuang__lede {
  font-family: var(--font-sans); font-size: var(--fs-sm);
  color: var(--ink-3); margin-left: 1rem; letter-spacing: .06em;
}
/* ── 反宫装 · 实物台 ──
   一张真东西，盖一层素色纸。纸上是帔风的线描——那是示意，不是实物。
   把纸往右拖开，1915 年那件袍服露出来。
   --p 由脚本写：0 盖满，1 全开。 */
.robe {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(12.5rem, 15.5rem);
  gap: var(--gap-m);
  align-items: start;
  margin: .9rem 0 var(--gap);
}
.robe__left { min-width: 0; }

.robe__stage {
  position: relative;
  margin: 0;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}
.robe__stage.is-dragging { cursor: grabbing; }

.robe__img {
  position: absolute; inset: 0;
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  /* 纸面退开时实物略微前推，两层才有前后关系 */
  transform: scale(calc(1.03 - var(--p) * .03));
}

.robe__veil {
  position: absolute; inset: 0;
  background: var(--paper-raised);
  color: var(--ink-3);
  transform-origin: 0 50%;
  transform:
    translate3d(calc(var(--p) * 106%), calc(var(--p) * -2.2%), 0)
    rotate(calc(var(--p) * -1.1deg));
  will-change: transform;
}
/* 纸的左边就是「折边」：一条两端虚掉发丝线，拖到哪儿跟到哪儿 */
.robe__veil::after {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 1px;
  background: linear-gradient(to bottom,
    transparent,
    color-mix(in srgb, var(--ink) 24%, transparent) 16%,
    color-mix(in srgb, var(--ink) 24%, transparent) 84%,
    transparent);
  opacity: calc(var(--p) * 2.2);
}
/* 帘纹：极细的横纹，让这层读作「纸」而不是一块白底。
   右缘一道极淡的暗，是纸被掀起时的那点背光 */
.robe__veil::before {
  content: '';
  position: absolute; inset: 0;
  background:
    linear-gradient(to left,
      color-mix(in srgb, var(--ink) 8%, transparent),
      transparent 6%),
    repeating-linear-gradient(
      to bottom,
      transparent 0 3px,
      color-mix(in srgb, var(--ink) 4%, transparent) 3px 4px);
  opacity: .9;
}
.robe__art {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  /* 素色外层也不是一张白纸：石青丝地的明暗、团花与云头都画出来，
     但仍标明「形制示意 · 非实物」，不冒充第二件藏品。 */
  filter: drop-shadow(0 10px 18px color-mix(in srgb, var(--ink) 16%, transparent));
}
.robe__veillab {
  position: absolute; top: 1.1rem; left: 1.15rem;
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .14em;
  color: var(--ink-2);
  line-height: 1.6;
}
.robe__veillab b {
  font-weight: 400;
  letter-spacing: .3em;
  color: var(--ink);
  margin-right: .55rem;
}
.robe__veillab span {
  display: block;
  margin-top: .1rem;
  font-size: .62rem;
  letter-spacing: .16em;
  color: var(--ink-3);
}
/* 「拖开」：贴在纸的右缘，纸一动手就淡掉 */
.robe__pull {
  position: absolute;
  right: .95rem; bottom: 2.35rem;
  margin: 0;
  text-align: right;
  font-family: var(--font-sans);
  font-size: .62rem;
  letter-spacing: .22em;
  color: var(--ink-3);
  opacity: clamp(0, calc(1 - var(--p) * 6), 1);
  pointer-events: none;
}
.robe__pull span {
  display: block;
  margin-top: .15rem;
  text-align: center;
  font-size: .78rem;
  letter-spacing: 0;
  opacity: .8;
}

.robe__zoom,
.robe__toggle {
  position: absolute; z-index: 2;
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .42rem .8rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .16em;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 0;
  cursor: pointer;
  transition: background .22s var(--ease), color .22s var(--ease), border-color .22s var(--ease);
}
.robe__zoom { top: .8rem; right: .8rem; }
.robe__toggle { left: .8rem; bottom: .8rem; border-color: var(--ink-3); }
.robe__zoom:hover,
.robe__toggle:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.robe__zoom:focus-visible,
.robe__toggle:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 3px; }

.robe__cap {
  margin: .55rem 0 0;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.75;
  letter-spacing: .04em;
  color: var(--ink-3);
  text-wrap: pretty;
}
.robe__src {
  display: block;
  margin-top: .18rem;
  color: var(--ink-3);
  opacity: .85;
}
.robe__veilnote {
  margin: .4rem 0 0;
  max-width: 48rem;
  font-family: var(--font-sans);
  font-size: .66rem;
  line-height: 1.8;
  letter-spacing: .03em;
  color: var(--ink-3);
  text-wrap: pretty;
}
.robe__side { min-width: 0; }
.robe__side .rail__note { margin-top: .8rem; }

/* ── 源流四则 ── */
.trail {
  list-style: none;
  margin: 0 0 var(--gap);
  padding: 0;
  max-width: 56rem;
  border-top: 1px solid var(--rule);
}
.trail li {
  display: grid;
  grid-template-columns: 9.5rem 1fr;
  gap: 1rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--rule-soft);
}
.trail__d {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .1em;
  color: var(--ink-3);
  padding-top: .12rem;
}
.trail__t {
  font-family: var(--font-serif);
  font-size: .8rem;
  line-height: 1.85;
  color: var(--ink-2);
  letter-spacing: .02em;
  text-wrap: pretty;
}

/* ── 三面戏台：三个版本，三张戏牌 ──
   透视写在每张牌自己的 transform 里，父级不设 preserve-3d。
   这样 3D 变换过的按钮仍然能被真实鼠标命中（此前的坑）。 */
.versions {
  margin: 1.1rem 0 var(--gap);
}
.versions__fan {
  position: relative;
  height: clamp(19rem, 42vh, 23rem);
  max-width: 54rem;
  margin: 0 auto;
}
.vcard {
  position: absolute; top: 0; left: 50%;
  width: clamp(13rem, 27vw, 17rem);
  height: 100%;
  margin: 0; padding: 0;
  overflow: hidden;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
  border-radius: 0;
  cursor: pointer;
  transform-origin: 50% 82%;
  transform:
    translateX(-50%)
    translateX(var(--x, 0))
    perspective(1200px)
    rotateY(var(--ry, 0deg))
    translateZ(var(--z, 0px))
    scale(var(--sc, 1));
  transition:
    transform .62s var(--ease),
    filter .45s var(--ease),
    opacity .45s var(--ease),
    box-shadow .4s var(--ease),
    border-color .3s var(--ease);
  will-change: transform;
  opacity: .58;
  filter: saturate(.5) brightness(.84);
  z-index: 1;
}
.vcard.is-left  { --x: -14rem; --ry: 22deg;  --z: -55px; --sc: .84; }
.vcard.is-right { --x: 14rem;  --ry: -22deg; --z: -55px; --sc: .84; }
.vcard.is-on {
  --x: 0rem; --ry: 0deg; --z: 62px; --sc: 1;
  z-index: 3;
  opacity: 1;
  filter: none;
  border-color: var(--ink-3);
  box-shadow: 0 22px 46px -26px color-mix(in srgb, var(--ink) 55%, transparent);
}
.vcard:hover:not(.is-on) { opacity: .82; filter: saturate(.78) brightness(.94); }
.vcard:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 4px; }
.vcard__img { position: absolute; inset: 0; display: block; }
.vcard__img img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 34%;
}
.vcard__shade {
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    color-mix(in srgb, #171613 84%, transparent) 0%,
    color-mix(in srgb, #171613 22%, transparent) 46%,
    transparent 72%);
}
.vcard__kind {
  position: absolute; top: .6rem; left: .6rem;
  padding: .12rem .48rem;
  font-family: var(--font-sans);
  font-size: .6rem;
  letter-spacing: .18em;
  color: var(--ink-2);
  background: color-mix(in srgb, var(--paper-raised) 92%, transparent);
}
.vcard__body {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column; gap: .2rem;
  padding: 1rem 1rem 1.15rem;
  text-align: left;
  color: #f4efe3;
}
.vcard__rank {
  font-family: var(--font-sans);
  font-size: .62rem;
  letter-spacing: .22em;
  opacity: .78;
}
.vcard__name {
  font-family: var(--font-serif);
  font-size: 1.38rem;
  letter-spacing: .14em;
  line-height: 1.2;
}
.versions__hint { display: none; }
.versions__info {
  position: relative;
  max-width: 54rem;
  min-height: 8.6rem;
  margin: 1.1rem auto 0;
  padding-top: .9rem;
  border-top: 1px solid var(--rule);
}
.vinfo[hidden] { display: none; }
.vinfo { animation: vfade .42s var(--ease) both; }
.vinfo__k {
  margin: 0;
  font-family: var(--font-sans);
  font-size: .66rem;
  letter-spacing: .2em;
  color: var(--ink-3);
}
.vinfo__t {
  margin: .16rem 0 .34rem;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-h3);
  letter-spacing: .1em;
}
.vinfo__n {
  margin: 0;
  max-width: 46rem;
  font-family: var(--font-serif);
  font-size: var(--fs-sm);
  line-height: 1.85;
  color: var(--ink-2);
  text-wrap: pretty;
}
.vinfo__c {
  margin: .55rem 0 0;
  max-width: 46rem;
  font-family: var(--font-sans);
  font-size: .67rem;
  line-height: 1.75;
  color: var(--ink-3);
  text-wrap: pretty;
}
@keyframes vfade {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

/* ── 两座戏台：琼花会馆 / 万福台 ── */
.venues {
  display: grid;
  /* 320px 的屏上正文只有 288px：给 19rem 的下限会让卡片顶出画布。
     用 min() 把下限压到可用宽度，窄屏自动改单列。 */
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  gap: var(--gap);
  margin-top: var(--gap);
}
.venue {
  overflow: hidden;
  background: var(--paper-raised);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius);
  transform: perspective(1000px) translateY(0);
  transition: transform .55s var(--ease), box-shadow .55s var(--ease), border-color .3s var(--ease);
}
.venue:hover {
  transform: perspective(1000px) translateY(-5px) rotateX(1.2deg);
  border-color: var(--rule);
  box-shadow: 0 24px 44px -32px color-mix(in srgb, var(--ink) 62%, transparent);
}
.venue__fig {
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--paper-sunk);
}
.venue__fig img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .9s var(--ease);
}
.venue:hover .venue__fig img { transform: scale(1.045); }
.venue__fig::after {
  content: '';
  position: absolute; inset: auto 0 0; height: 46%;
  background: linear-gradient(to top, color-mix(in srgb, #171613 52%, transparent), transparent);
  pointer-events: none;
}
.venue__date {
  position: absolute; left: .85rem; bottom: .7rem; z-index: 1;
  font-family: var(--font-sans);
  font-size: .64rem;
  letter-spacing: .16em;
  color: #f4efe3;
}
.venue__bd { padding: .95rem 1.05rem 1.1rem; }
.venue__t {
  margin: 0 0 .35rem;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-h3);
  letter-spacing: .12em;
}
.venue__n {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--fs-sm);
  line-height: 1.8;
  color: var(--ink-2);
  text-wrap: pretty;
}
.venue__c {
  margin: .6rem 0 0;
  font-family: var(--font-sans);
  font-size: .65rem;
  line-height: 1.7;
  color: var(--ink-3);
}

@media (max-width: 860px) {
  .versions__fan { height: 19rem; }
  .vcard { width: 13rem; }
  .vcard.is-left  { --x: -9.2rem; }
  .vcard.is-right { --x: 9.2rem; }
}
@media (max-width: 620px) {
  .versions__fan {
    display: flex;
    gap: .7rem;
    height: 14.5rem;
    padding: 0 .1rem .55rem;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
  }
  .vcard {
    position: relative; left: auto;
    flex: 0 0 72%;
    width: auto; height: 100%;
    transform: none;
    opacity: .74;
    filter: saturate(.65) brightness(.9);
    scroll-snap-align: center;
  }
  .vcard.is-on { opacity: 1; filter: none; }
  .versions__hint {
    display: block;
    margin: .5rem 0 0;
    text-align: center;
    font-family: var(--font-sans);
    font-size: .62rem;
    letter-spacing: .2em;
    color: var(--ink-3);
  }
  .versions__info { min-height: 0; margin-top: .7rem; }
}

/* ── 实物展开层 ──
   台面那张图原位放大到整屏，关掉时缩回原位。
   位移与缩放由脚本算，这里只管盒子和侧栏。 */
body.is-rv { overflow: hidden; }
.rv {
  /* 旧内核不认 inset，四边分开兜底。 */
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem, 5vh, 3rem) clamp(1rem, 4vw, 3.2rem);
}
.rv[hidden] { display: none; }
.rv__bd {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  /* 没有 color-mix 的旧内核：用实纸色兜底，弹层背后不能透出正文。 */
  background: var(--paper);
  background: color-mix(in srgb, var(--paper) 97%, transparent);
  -webkit-backdrop-filter: blur(3px) saturate(.92);
  backdrop-filter: blur(3px) saturate(.92);
  animation: rvIn .34s var(--ease) both;
}
.rv__shell {
  position: relative;
  display: flex; align-items: stretch; justify-content: center;
  gap: clamp(1.2rem, 3vw, 2.6rem);
  width: min(100%, 82rem);
  height: min(74vh, 40rem);
  max-height: 100%;
}
.rv__fig {
  position: relative;
  margin: 0;
  height: 100%;
  aspect-ratio: 4 / 3;
  width: auto;
  flex: 0 1 auto;
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
}
.rv__img {
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
  transform-origin: 50% 50%;
  will-change: transform;
}
.rv__img.is-facefade { animation: rvFaceFade .38s var(--ease) both; }
@keyframes rvFaceFade {
  from { opacity: .25; }
  to   { opacity: 1; }
}
.rv__cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.4rem 1rem .7rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .14em;
  color: #f4efe3;
  background: linear-gradient(to top,
    color-mix(in srgb, #171613 78%, transparent), transparent);
  pointer-events: none;
}
.rv__side {
  flex: 0 1 23rem;
  min-width: 17rem;
  height: 100%;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  padding-right: .6rem;
  animation: rvIn .46s var(--ease) both;
}
.rv__side:focus { outline: none; }
.rv__side .rec { margin-top: .2rem; }
.rv__h {
  margin: .25rem 0 .15rem;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-h2);
  letter-spacing: var(--ls-title);
  line-height: 1.2;
}
.rv__sub {
  margin: 0 0 1rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .06em;
  color: var(--ink-3);
}
.rv__hint {
  margin: -.3rem 0 .9rem;
  font-family: var(--font-sans);
  font-size: .66rem;
  letter-spacing: .1em;
  color: var(--ink-3);
}
.rv__faces { display: grid; gap: .6rem; }
.face {
  display: block;
  width: 100%;
  margin: 0;
  padding: .55rem .7rem .6rem .9rem;
  text-align: left;
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-left: 2px solid var(--c);
  border-radius: 0;
  cursor: pointer;
  transition: background .25s var(--ease), border-color .25s var(--ease);
}
.face:hover { background: color-mix(in srgb, var(--c) 7%, transparent); }
.face.is-on {
  background: color-mix(in srgb, var(--c) 11%, transparent);
  border-color: color-mix(in srgb, var(--c) 34%, transparent);
  border-left-color: var(--c);
}
.face:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 2px; }
.face__k {
  display: flex; align-items: center; gap: .5rem;
  margin: 0 0 .35rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .16em;
  color: var(--ink);
}
.face__k b { font-weight: 400; color: var(--c); letter-spacing: .05em; }
.face__chip {
  width: .62rem; height: .62rem;
  margin-left: auto;
  border-radius: 50%;
  background: var(--c);
}
.face__t {
  display: block;
  margin: 0;
  font-family: var(--font-serif);
  font-size: .8rem;
  line-height: 1.9;
  color: var(--ink-2);
  letter-spacing: .02em;
  text-wrap: pretty;
}
.rv__viewbar {
  display: flex; align-items: center; gap: .4rem;
  margin: 1rem 0 .2rem;
}
.rv__viewlab {
  margin-right: .15rem;
  font-family: var(--font-sans);
  font-size: .64rem;
  letter-spacing: .18em;
  color: var(--ink-3);
}
.rv__viewbar button {
  padding: .3rem .75rem;
  font-family: var(--font-sans);
  font-size: .7rem;
  letter-spacing: .14em;
  color: var(--ink-2);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 0;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.rv__viewbar button:hover { border-color: var(--ink-3); color: var(--ink); }
.rv__viewbar button.is-on {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}
.rv__viewbar button:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 3px; }
.rv__cite {
  margin: 1.2rem 0 0;
  padding-top: .8rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-sans);
  font-size: .68rem;
  line-height: 1.85;
  color: var(--ink-3);
  text-wrap: pretty;
}
.rv__x {
  position: fixed; top: clamp(.8rem, 2.6vh, 1.6rem); right: clamp(.8rem, 2.6vw, 1.8rem);
  z-index: 3;
  display: grid; place-items: center;
  width: 2.4rem; height: 2.4rem;
  font-family: var(--font-sans);
  font-size: 1.15rem; line-height: 1;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 50%;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.rv__x:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.rv__x:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 3px; }

.rv.is-closing .rv__bd { animation: rvOut .3s var(--ease) both; }
.rv.is-closing .rv__side { animation: rvOut .26s var(--ease) both; }
@keyframes rvIn  { from { opacity: 0 } to { opacity: 1 } }
@keyframes rvOut { from { opacity: 1 } to { opacity: 0 } }

@media (prefers-reduced-motion: reduce) {
  .rv__bd, .rv__side, .rv.is-closing .rv__bd, .rv.is-closing .rv__side { animation: none; }
}

/* 窄一些：实物与著录上下排，图占满宽度 */
@media (max-width: 960px) {
  .robe { grid-template-columns: 1fr; gap: var(--gap); }
  .robe__stage { max-width: none; }
  .trail li { grid-template-columns: 1fr; gap: .15rem; padding: .55rem 0; }
}

/* 展开层：图在上，著录在下，整体可滚 */
@media (max-width: 1080px), (max-height: 620px) {
  .rv { display: block; overflow-y: auto; padding-block: 1.2rem 2rem;
        /* 这一层自己会滚：底衬若是 absolute，会随内容一起滚走，
           滚到下半段就把背后的页面露出来。改成 fixed 并给容器实底。 */
        background: var(--paper); }
  .rv__bd { position: fixed; }
  .rv__shell {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    height: auto;
    max-height: none;
    margin: 0 auto;
    max-width: 44rem;
  }
  .rv__fig { flex: none; width: 100%; height: auto; }
  .rv__side {
    flex: none; min-width: 0;
    height: auto; max-height: none;
    overflow: visible; padding-right: 0;
  }
}
.quotes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--gap);
  margin: var(--gap) 0;
}
.quotes blockquote {
  margin: 0;
  padding: 1rem 0 1rem 1.1rem;
  border-left: 3px solid var(--qing);
  background: color-mix(in srgb, var(--qing) 5%, transparent);
  font-size: var(--fs-sm);
}
.quotes cite {
  display: block;
  font-style: normal;
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--ink-3); margin-top: .5rem;
}
.thesis {
  font-size: 1.1em;
  border-top: 1px solid var(--dan);
  border-bottom: 1px solid var(--dan);
  padding: 1rem 0;
  margin-top: var(--gap);
  color: var(--ink);
  max-width: var(--measure);
}
.combo__lead {
  margin: var(--gap) 0 -.5rem;
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--ink-3);
}
.combo {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  font-family: var(--font-sans); font-size: var(--fs-sm);
  margin: var(--gap) 0;
}
.combo__sep { color: var(--dan); }

/* 语言层转折 */
.turn {
  margin-top: var(--gap-xl);
  padding: var(--gap-l);
  background: var(--paper-sunk);
  border-radius: var(--radius);
  border-left: 4px solid var(--ev-3);
}
.turn__h { font-size: var(--fs-h2); margin: 0 0 .6rem; letter-spacing: .04em; }
.turn__lead { color: var(--ink-2); font-size: 1.05em; }
.turn__turn {
  font-size: 1.35em;
  color: var(--dan-ink);
  font-weight: 600;
  letter-spacing: .06em;
  margin: .4rem 0 1rem;
}

/* ============================================================
   幕四 · 唱词对读（只列文字，不附音频）
   ============================================================ */
.lb {
  margin-top: var(--gap-l);
  padding-top: var(--gap-m);
  border-top: 1px solid var(--rule);
}
.lb__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap); flex-wrap: wrap;
}
.lb__head .sub { margin-top: 0; }
/* 两个本子：先各自交代身份，再进入逐段对读 */
.lb__versions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
  margin: var(--gap-m) 0;
}
.lbv {
  padding: 1rem 1.1rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule-soft);
  border-top: 3px solid var(--ink-3);
}
.lbv--mandarin  { border-top-color: var(--qing); }
.lbv--cantonese { border-top-color: var(--dan); }
.lbv__k {
  margin: 0 0 .35rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .04em;
}
.lbv__tag {
  display: inline-block;
  margin-right: .45rem;
  padding: .05rem .4rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 400;
  color: var(--ev-on);
  background: var(--qing);
}
.lbv--cantonese .lbv__tag { background: var(--dan-ink); }
.lbv__meta {
  margin: 0 0 .5rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  line-height: 1.7;
}
.lbv__b {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.8;
}

/* 显示方式：并置 / 单看一本 */
.lb__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gap); flex-wrap: wrap;
  margin: var(--gap) 0 var(--gap-s);
}
.lb__seg {
  display: inline-flex;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
}
.lb__seg button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .06em;
  padding: .5rem .85rem;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease);
}
.lb__seg button + button { border-left: 1px solid var(--rule); }
.lb__seg button[aria-pressed="true"] {
  background: var(--ink);
  color: var(--paper);
}
.lb__seg button:focus-visible {
  outline: 2px solid var(--dan-ink);
  outline-offset: 2px;
}
.lb__hint {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: .08em;
}

/* 逐段对读 */
.lb__pairs { list-style: none; margin: 0; padding: 0; }
.lbpair {
  padding: var(--gap-m) 0;
  border-top: 1px solid var(--rule-soft);
}
.lbpair__head {
  display: grid;
  grid-template-columns: 2.2rem 1fr;
  gap: .8rem;
  align-items: start;
  margin-bottom: var(--gap);
}
.lbpair__no {
  font-family: var(--font-serif);
  font-size: 1.6rem;
  line-height: 1;
  color: var(--dan-ink);
  opacity: .85;
  padding-top: .15rem;
}
.lbpair__t { margin: 0; font-size: var(--fs-h3); letter-spacing: .06em; }
.lbpair__s {
  margin: .2rem 0 0;
  font-size: var(--fs-sm);
  color: var(--ink-3);
  line-height: 1.7;
}
.lbpair__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
}
.lbcol {
  padding: 1rem 1.1rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule-soft);
}
.lbcol--mandarin  { border-left: 3px solid var(--qing); }
.lbcol--cantonese { border-left: 3px solid var(--dan); }
.lbcol__k {
  margin: 0 0 .55rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .12em;
  color: var(--ink-3);
}
.lbcol__p {
  margin: 0 0 .7rem;
  font-size: var(--fs-sm);
  color: var(--dan-ink);
  letter-spacing: .04em;
}
.lbline {
  display: grid;
  grid-template-columns: 2.4rem 1fr;
  gap: .35rem .65rem;
  margin: 0 0 .55rem;
  align-items: baseline;
}
.lbline:last-child { margin-bottom: 0; }
.lbline__r {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  white-space: nowrap;
}
.lbline__x { font-size: var(--fs-sm); line-height: 1.85; color: var(--ink); }
.lbline.is-bai .lbline__x { color: var(--ink-2); }
.lbline__b {
  display: inline-block;
  margin-left: .2rem;
  padding: 0 .18rem;
  font-family: var(--font-sans);
  font-size: .58rem;
  font-weight: 400;
  line-height: 1.35;
  color: var(--dan-ink);
  border: 1px solid currentColor;
  vertical-align: .1em;
}

/* 单看一本时，另一栏让位 */
.lb[data-lb-mode="mandarin"] .lbpair__grid,
.lb[data-lb-mode="cantonese"] .lbpair__grid { grid-template-columns: 1fr; }
.lb[data-lb-mode="mandarin"] .lbcol--cantonese,
.lb[data-lb-mode="cantonese"] .lbcol--mandarin { display: none; }
.lb[data-lb-mode="mandarin"] .lbv--cantonese,
.lb[data-lb-mode="cantonese"] .lbv--mandarin { opacity: .45; }
/* 官话全本在「只看粤语」时一并收起，否则模式名不副实 */
.lb[data-lb-mode="cantonese"] .lbfull { display: none; }

/* 对读按语 */
.lbpair__read {
  margin: var(--gap) 0 0;
  padding: .75rem 0 .75rem 1rem;
  border-left: 3px solid var(--rule);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.85;
}
.lbpair__read b {
  margin-right: .55rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .12em;
  color: var(--dan-ink);
}

/* 官话全本：默认收起，不抢五段对照的注意力 */
.lbfull {
  margin-top: var(--gap-m);
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
}
.lbfull summary {
  display: flex; align-items: baseline; gap: var(--gap);
  padding: 1rem 1.1rem;
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .04em;
}
.lbfull summary::-webkit-details-marker { display: none; }
.lbfull summary::after {
  content: '＋';
  margin-left: auto;
  font-family: var(--font-sans);
  font-weight: 400;
  color: var(--ink-3);
}
.lbfull[open] summary::after { content: '－'; }
.lbfull summary em {
  font-style: normal;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 400;
  color: var(--ink-3);
  letter-spacing: .06em;
}
.lbfull__bd {
  padding: 0 1.1rem 1.1rem;
  border-top: 1px solid var(--rule-soft);
}
.lbfull__intro {
  margin: 1rem 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.lbfull__list { list-style: none; margin: 0; padding: 0; }
.lbqu {
  padding: 1rem 0;
  border-top: 1px solid var(--rule-soft);
}
.lbqu:first-child { border-top: 0; padding-top: .5rem; }
.lbqu__h {
  display: flex; align-items: baseline; gap: .6rem;
  margin-bottom: .55rem;
}
.lbqu__no {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}
.lbqu__p {
  font-size: var(--fs-sm);
  color: var(--dan-ink);
  letter-spacing: .04em;
}
.lbqu__bai .lbline { margin-top: .4rem; }

/* 出处 */
.lb__src {
  margin-top: var(--gap-m);
  padding-top: var(--gap-s);
  border-top: 1px solid var(--rule-soft);
}
.lb__src p {
  margin: 0 0 .35rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.8;
  color: var(--ink-3);
}
.lb__src a { color: var(--dan-ink); text-underline-offset: 2px; }
.lb__cr {
  margin-top: .7rem !important;
  padding-top: .6rem;
  border-top: 1px dashed var(--rule);
}

@media (max-width: 900px) {
  .lb__versions,
  .lbpair__grid { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .lb__seg { width: 100%; }
  .lb__seg button { flex: 1 1 0; padding: .55rem .4rem; }
  .lbpair__head { grid-template-columns: 1.5rem 1fr; gap: .5rem; }
}

/* ============================================================
   幕五 · 传
   ============================================================ */
.trail__d { display: block; font-family: var(--font-sans); font-size: var(--fs-xs); color: var(--ink-3); margin-top: .3rem; line-height: 1.7; }

/* 小标题 + 一句副行：副行靠基线排，别另起一块 */
.sec-h {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: .2rem var(--gap);
  margin: var(--gap-l) 0 0;
}
.sec-h .sub { margin: 0; }
.sec-h__n {
  margin: 0; padding-bottom: .4rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .14em;
  color: var(--ink-3);
}

/* ── 四条屏 ──
   四块板折成一扇。外两块靠前、向里侧转，中间两块退半步。
   整扇的俯仰与左右转由脚本写 --rx / --ry；
   脚本每帧都在改，所以这里不能挂 transition，否则会追着跑偏。 */
.screen {
  margin: var(--gap) 0 var(--gap-m);
  padding: 1.1rem 0 .3rem;
}
.screen__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(.5rem, 1.3vw, 1.1rem);
}
.screen__hint {
  margin: 1.15rem 0 0;
  text-align: right;
  font-family: var(--font-sans);
  font-size: .64rem;
  letter-spacing: .15em;
  color: var(--ink-3);
  opacity: .85;
}

.panel {
  position: relative;
  display: flex; flex-direction: column; align-items: stretch;
  gap: .42rem;
  padding: .5rem .5rem .8rem;
  text-align: left;
  font: inherit; color: inherit;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 14px 30px -26px rgba(18, 16, 12, .95);
  transition: box-shadow .45s var(--ease), border-color .3s var(--ease),
              transform .45s var(--ease);
}
/* 折缝：靠里的一侧压一道暗，板才像折出来的，不像贴上去的 */
.panel::after {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(to right,
    color-mix(in srgb, var(--ink) 6%, transparent), transparent 10%,
    transparent 90%, color-mix(in srgb, var(--ink) 6%, transparent));
  opacity: .7;
  transition: opacity .4s var(--ease);
}
.panel:hover::after, .panel:focus-visible::after { opacity: .25; }

.panel__gen {
  position: absolute; top: .24rem; right: .55rem;
  font-family: var(--font-serif);
  font-size: 2rem; line-height: 1;
  color: var(--ink);
  opacity: .11;
  pointer-events: none;
}
.panel__kind {
  font-family: var(--font-sans);
  font-size: .6rem;
  letter-spacing: .2em;
  color: var(--dan-ink);
  padding-right: 2.2rem;
}
/* 图一律留一圈纸（像照片裱在卡纸上）。四张底片比例差得远，
   留白一致，排在一起才不显得忽高忽低。 */
.panel__fig {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  padding: 4%;
  background: var(--paper-sunk);
  overflow: hidden;
}
/* 证件照：多留一圈，蓝色块别整块压过来 */
.panel__fig.is-mat { padding: 14% 16%; }
.panel__img {
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
  transition: transform .7s var(--ease);
}
.panel:hover .panel__img, .panel:focus-visible .panel__img { transform: scale(1.035); }
.panel__empty {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 1.2rem;
  letter-spacing: .2em;
  color: var(--ink-3);
  background:
    repeating-linear-gradient(45deg, transparent 0 6px,
      color-mix(in srgb, var(--ink) 4%, transparent) 6px 7px);
}
.panel__name {
  margin-top: .1rem;
  font-size: clamp(1.1rem, 1.6vw, 1.35rem);
  letter-spacing: .14em;
  line-height: 1.3;
}
.panel__role {
  font-family: var(--font-sans);
  font-size: .64rem;
  letter-spacing: .06em;
  color: var(--ink-3);
  margin-top: -.22rem;
}
.panel__note {
  font-size: .74rem;
  line-height: 1.75;
  color: var(--ink-2);
}
.panel__open {
  margin-top: auto;
  display: flex; align-items: center; justify-content: space-between;
  padding-top: .5rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-sans);
  font-size: .6rem;
  letter-spacing: .16em;
  color: var(--ink-3);
}
.panel__open b { font-weight: 400; font-size: .95rem; color: var(--dan-ink); line-height: 1; }

/* 够宽才折；窄屏退成平面网格，转起来只会晕 */
@media (min-width: 901px) {
  .screen { perspective: 1150px; perspective-origin: 50% 40%; }
  .screen__row {
    transform-style: preserve-3d;
    transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
    will-change: transform;
  }
  .panel {
    --k: 0; --z: 0px;
    transform-style: preserve-3d;
    transform: rotateY(calc(var(--k) * 2.2deg)) translateZ(var(--z));
    will-change: transform;
  }
  .panel:hover, .panel:focus-visible {
    transform: rotateY(0deg) translateZ(calc(var(--z) + 40px));
    z-index: 3;
    border-color: var(--ink-3);
    box-shadow: 0 34px 50px -32px rgba(18, 16, 12, .9);
    outline: none;
  }
  .panel:focus-visible {
    border-color: var(--dan-ink);
    box-shadow: 0 0 0 1px var(--dan-ink), 0 34px 50px -32px rgba(18, 16, 12, .9);
  }
}

/* ── 展牌廊 ──
   横向一条，越靠中间越正：--t / --o 由脚本按滚动位置写。
   用原生滚动容器，不用 transform 假滚——键盘、触摸板、读屏都还在。 */
.rail { position: relative; margin: var(--gap) 0 var(--gap-m); }
.rail::before, .rail::after {
  content: '';
  position: absolute; top: 0; bottom: 3.4rem;
  width: clamp(.7rem, 2.6vw, 2rem);
  z-index: 2;
  pointer-events: none;
}
.rail::before { left: 0;  background: linear-gradient(to right, var(--paper), transparent); }
.rail::after  { right: 0; background: linear-gradient(to left,  var(--paper), transparent); }

.rail__vp {
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  padding: 1.9rem 0 1.7rem;
  touch-action: pan-y;
  cursor: grab;
  /* 横向拖动的是一整条展廊：别让浏览器顺手选中卡上的字，
     也别让卡里的图触发原生的「拖拽图片」——那会吃掉 pointermove，
     展廊拖到一半就断，看起来像拖不动。 */
  -webkit-user-select: none;
  user-select: none;
}
.rail__vp img { -webkit-user-drag: none; }
.rail__vp::-webkit-scrollbar { display: none; }
.rail__vp.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.rail__vp:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 4px; }
.rail__track {
  /* ⚠️ 这一层不能再挂 preserve-3d。
     展牌位于横向滚动容器里，Chromium 对「preserve-3d 子树中的
     3D 变换子级」做命中测试时会算错位置：整张牌明明在眼前，
     elementFromPoint 却只返回 .rail__track，于是展牌点不开。
     （和第二幕时间轴「看着在、点不动」是同一类问题。）
     透视改为写进每张牌自己的 transform（见 .mu），
     纵深不变，命中恢复原生；牌的 3D 也不再向外传递。 */
  transform-style: flat;
  display: flex;
  gap: clamp(.7rem, 1.8vw, 1.4rem);
  list-style: none; margin: 0;
  padding: 0 clamp(1rem, 7vw, 6rem) 0 0;
  width: max-content;
}

.mu {
  flex: 0 0 auto;
  width: clamp(14rem, 24vw, 18.5rem);
  scroll-snap-align: center;
  /* 透视自带在牌的变换里：不再依赖祖先的 perspective + preserve-3d，
     每张牌各自成一层，点击命中才不会被 3D 渲染上下文算歪。 */
  transform: perspective(1250px) rotateY(var(--t, 0deg)) translateZ(var(--tz, 0px));
  opacity: var(--o, 1);
  will-change: transform, opacity;
}

.mu__card {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: .34rem;
  width: 100%; height: 100%;
  padding: .5rem .5rem .9rem;
  text-align: left;
  font: inherit; color: inherit;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 18px 34px -30px rgba(18, 16, 12, .95);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .3s var(--ease);
}
.mu__card:hover, .mu__card:focus-visible {
  transform: translateY(-4px);
  border-color: var(--ink-3);
  box-shadow: 0 28px 44px -30px rgba(18, 16, 12, .9);
  outline: none;
}
.mu__card:focus-visible { border-color: var(--dan-ink); box-shadow: 0 0 0 1px var(--dan-ink); }

.mu__fig {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--paper-sunk);
  overflow: hidden;
}
.mu__img {
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
  transition: transform .7s var(--ease);
}
.mu__card:hover .mu__img { transform: scale(1.03); }

/* 没有图就明说没有图，不拿别的东西顶上 */
.mu__blank {
  position: absolute; inset: 0;
  display: grid; place-content: center; justify-items: center;
  gap: .45rem;
  background:
    repeating-linear-gradient(45deg, transparent 0 6px,
      color-mix(in srgb, var(--ink) 4%, transparent) 6px 7px);
}
.mu__blank-y {
  font-family: var(--font-serif);
  font-size: 2.2rem; line-height: 1;
  color: var(--ink);
  opacity: .2;
  letter-spacing: .06em;
}
.mu__seal {
  writing-mode: vertical-rl;
  padding: .22rem .16rem;
  font-size: .6rem;
  letter-spacing: .2em;
  color: var(--dan-ink);
  border: 1px solid var(--dan-ink);
}
.mu__blank em {
  font-style: normal;
  font-family: var(--font-sans);
  font-size: .6rem;
  letter-spacing: .14em;
  color: var(--ink-3);
}

.mu__tag {
  margin-top: .25rem;
  padding: .04rem .3rem;
  font-family: var(--font-sans);
  font-size: .58rem;
  letter-spacing: .18em;
  color: var(--ink-3);
  border: 1px solid var(--rule);
}
.mu__y {
  font-family: var(--font-sans);
  font-size: .68rem;
  letter-spacing: .18em;
  color: var(--dan-ink);
}
.mu__t {
  text-wrap: balance;
  font-size: .96rem;
  line-height: 1.45;
  letter-spacing: .04em;
}
.mu__n {
  font-size: .72rem;
  line-height: 1.72;
  color: var(--ink-2);
}

.rail__note {
  max-width: 46rem;
  margin: .2rem 0 0;
  font-family: var(--font-sans);
  font-size: .68rem;
  line-height: 1.8;
  letter-spacing: .04em;
  color: var(--ink-3);
  text-wrap: pretty;
}
.rail__nav {
  display: flex; align-items: center; justify-content: flex-end;
  gap: .7rem;
  padding-top: .2rem;
}
.rail__btn {
  display: grid; place-items: center;
  width: 2.05rem; height: 2.05rem;
  font-size: 1.05rem; line-height: 1;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 50%;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.rail__btn:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.rail__btn:focus-visible { outline: 2px solid var(--dan-ink); outline-offset: 2px; }
.rail__idx {
  font-family: var(--font-sans);
  font-size: .64rem;
  letter-spacing: .14em;
  color: var(--ink-3);
}
.rail__idx b { font-weight: 400; color: var(--ink); }

.next { margin-top: var(--gap-m); }

/* 续谱流程：四步，无具体篇目 */
.nextflow {
  list-style: none;
  margin: var(--gap) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .7rem 1.5rem;
}
.nextflow__s {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .58rem 1.15rem .58rem .62rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule-soft);
}
.nextflow__s:not([data-last])::after {
  content: '';
  position: absolute;
  right: -.92rem;
  top: 50%;
  width: .36rem;
  height: .36rem;
  border-top: 1px solid color-mix(in srgb, var(--teng) 70%, var(--rule));
  border-right: 1px solid color-mix(in srgb, var(--teng) 70%, var(--rule));
  transform: translateY(-50%) rotate(45deg);
}
.nextflow__n {
  display: inline-grid;
  place-items: center;
  width: 1.32rem;
  height: 1.32rem;
  flex: 0 0 auto;
  background: color-mix(in srgb, var(--dan) 11%, transparent);
  border: 1px solid color-mix(in srgb, var(--dan) 38%, transparent);
  color: var(--dan-ink);
  font-family: var(--font-sans);
  font-size: .64rem;
  line-height: 1;
}
.nextflow__t {
  font-size: .95rem;
  letter-spacing: .12em;
  color: var(--ink-2);
}
@media (max-width: 620px) {
  .nextflow { gap: .55rem; }
  .nextflow__s { flex: 1 1 calc(50% - .55rem); }
  .nextflow__s:not([data-last])::after { display: none; }
}

/* ── 档案层 ──
   四面屏、六块展牌共用一个层，内容由脚本填。 */
.lgv {
  /* 旧内核不认 inset，四边分开兜底。 */
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem, 5vh, 3rem) clamp(1rem, 4vw, 3.2rem);
}
.lgv[hidden] { display: none; }
.lgv__bd {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  /* 同上：旧内核没有 color-mix，用实纸色兜底。 */
  background: var(--paper);
  background: color-mix(in srgb, var(--paper) 98.5%, transparent);
  -webkit-backdrop-filter: blur(9px) saturate(.88);
  backdrop-filter: blur(9px) saturate(.88);
  opacity: 0;
  transition: opacity .32s var(--ease);
}
.lgv.is-open .lgv__bd { opacity: 1; }
.lgv__shell {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  gap: clamp(1.2rem, 3vw, 2.6rem);
  width: min(100%, 80rem);
  max-height: 100%;
  opacity: 0;
  transform: translateY(18px) scale(.994);
  transition: opacity .42s var(--ease), transform .52s var(--ease);
}
.lgv.is-open .lgv__shell { opacity: 1; transform: none; }

.lgv__fig {
  margin: 0;
  display: flex; flex: 0 1 auto;
  min-width: 0;
  max-height: min(74vh, 40rem);
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--paper-sunk);
}
.lgv__img {
  display: block;
  width: auto; height: auto;
  max-width: 58vw;
  max-height: min(74vh, 40rem);
  object-fit: contain;
}
.lgv__shell.is-nofig .lgv__img { display: none; }
.lgv__shell.is-small .lgv__img { max-width: 23rem; }
.lgv__shell.is-nofig .lgv__fig {
  width: min(22rem, 34vw);
  height: auto;
  aspect-ratio: 4 / 5;
}
.lgv__blank { display: none; }
.lgv__shell.is-nofig .lgv__blank {
  position: absolute; inset: 0;
  display: grid; place-content: center; justify-items: center;
  gap: .8rem;
  background:
    repeating-linear-gradient(45deg, transparent 0 7px,
      color-mix(in srgb, var(--ink) 4%, transparent) 7px 8px);
}
.lgv__fig { position: relative; }
.lgv__blank-y {
  font-family: var(--font-serif);
  font-size: 3rem; line-height: 1;
  letter-spacing: .08em;
  color: var(--ink);
  opacity: .2;
}
.lgv__seal {
  writing-mode: vertical-rl;
  padding: .45rem .3rem;
  font-size: .78rem;
  letter-spacing: .28em;
  color: var(--dan-ink);
  border: 1px solid var(--dan-ink);
}
.lgv__blank em {
  font-style: normal;
  font-family: var(--font-sans);
  font-size: .68rem;
  letter-spacing: .16em;
  color: var(--ink-3);
}

.lgv__side {
  flex: 0 1 23.5rem;
  min-width: 17rem;
  max-height: 100%;
  overflow-y: auto;
  padding-right: .5rem;
}
.lgv__side:focus { outline: none; }
.lgv__shell.is-nofig .lgv__side { flex: 0 1 32rem; }
.lgv__h {
  margin: .2rem 0 .12rem;
  text-wrap: balance;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  letter-spacing: .06em;
  line-height: 1.26;
}
.lgv__sub {
  margin: 0 0 1rem;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .1em;
  color: var(--ink-3);
}
.lgv__rec { margin: 0 0 1rem; }
.lgv__body {
  font-size: .86rem;
  line-height: 1.95;
  color: var(--ink-2);
  text-wrap: pretty;
}
.lgv__note {
  margin: .2rem 0 0;
  padding: .5rem .7rem;
  font-family: var(--font-sans);
  font-size: .66rem;
  line-height: 1.7;
  letter-spacing: .04em;
  color: var(--dan-ink);
  background: color-mix(in srgb, var(--dan) 7%, transparent);
  border-left: 2px solid var(--dan);
}
.lgv__cite {
  margin: 1rem 0 0;
  padding-top: .8rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-sans);
  font-size: .66rem;
  line-height: 1.85;
  color: var(--ink-3);
  text-wrap: pretty;
}
.lgv__x {
  position: fixed; top: clamp(.8rem, 2.6vh, 1.6rem); right: clamp(.8rem, 2.6vw, 1.8rem);
  z-index: 3;
  display: grid; place-items: center;
  width: 2.4rem; height: 2.4rem;
  font-family: var(--font-sans);
  font-size: 1.15rem; line-height: 1;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 50%;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.lgv__x:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.lgv__x:focus-visible { outline: 1px solid var(--dan-ink); outline-offset: 3px; }

@media (max-width: 1080px), (max-height: 640px) {
  .lgv { display: block; overflow-y: auto; padding-block: 1.2rem 2rem;
         background: var(--paper); }
  .lgv__bd { position: fixed; }
  .lgv__shell {
    flex-direction: column; align-items: stretch;
    width: 100%; max-width: 44rem;
    margin: 0 auto;
    max-height: none;
  }
  .lgv__shell .lgv__fig { justify-content: center; max-height: none; }
  .lgv__shell.is-small .lgv__img { max-width: 23rem; }
.lgv__shell.is-nofig .lgv__fig { width: 100%; max-width: 18rem; margin: 0 auto 1.2rem; }
  .lgv__img { max-width: 100%; max-height: 58vh; margin: 0 auto; }
  .lgv__side,
  .lgv__shell.is-nofig .lgv__side {
    flex: none; min-width: 0;
    max-height: none; overflow: visible;
    padding-right: 0;
  }
}

/* 窄屏：屏风退成平面网格，展牌缩一手 */
@media (max-width: 900px) {
  .screen__row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
  .screen__hint { display: none; }
  .panel__fig { aspect-ratio: 1 / 1; }
  .mu { width: min(19rem, 78vw); }
}
@media (max-width: 520px) {
  .panel__note { font-size: .7rem; }
  .sec-h { margin-top: var(--gap-m); }
}

/* ---------- 页脚 ---------- */
.foot {
  max-width: 1180px;
  margin: 0 auto;
  padding: var(--gap-xl) var(--pad-x);
  border-top: 1px solid var(--rule);
  color: var(--ink-2);
}

/* ============================================================
   溯源弹层
   ============================================================ */
.pop {
  position: fixed; z-index: 60;
  background: var(--paper-raised);
  border: 1px solid var(--ink-3);
  box-shadow: 6px 6px 0 var(--paper-sunk), 7px 7px 0 var(--rule);
  padding: 1.1rem 1.2rem;
  max-height: 70vh; overflow: auto;
}
.pop[hidden] { display: none; }
.pop__close {
  position: absolute; top: .5rem; right: .6rem;
  background: none; border: none; cursor: pointer;
  font-size: 1.2rem; line-height: 1; color: var(--ink-3);
  padding: .2rem .4rem;
}
.pop__close:hover { color: var(--ink); }
.src__head { display: flex; align-items: center; gap: .5rem; margin-bottom: .6rem; }
.src__type { font-family: var(--font-sans); font-size: var(--fs-xs); color: var(--ink-3); }
.src__title { font-size: 1rem; margin: 0 0 .6rem; letter-spacing: .03em; line-height: 1.5; }
.src__quote {
  margin: 0 0 .8rem; padding: .5rem 0 .5rem .8rem;
  border-left: 2px solid var(--qing);
  font-size: var(--fs-sm); color: var(--ink-2);
}
.src__meta {
  display: grid; grid-template-columns: 4.5rem 1fr;
  gap: .25rem .6rem; margin: 0 0 .8rem;
  font-family: var(--font-sans); font-size: var(--fs-xs);
}
.src__meta dt { color: var(--ink-3); }
.src__meta dd { margin: 0; color: var(--ink-2); }
.src__note {
  font-size: var(--fs-xs); color: var(--ink-3);
  border-top: 1px solid var(--rule-soft); padding-top: .6rem; margin: 0;
}
.src__missing { color: var(--dan-ink); font-size: var(--fs-sm); }

/* ============================================================
   进场与深度
   ------------------------------------------------------------
   两条纪律：
   · 位移只做一次（进场），之后交给 hover 的 Z 轴，不在平面上晃。
   · 卡片悬停抬 Z 不抬阴影——极简的「浮起」靠透视，不靠模糊。
   ============================================================ */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

.cards { perspective: 1100px; }
.card {
  transition: transform .5s var(--ease), border-color .3s var(--ease);
}
.card:hover { transform: translateZ(12px); border-color: var(--ink-3); }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .card:hover { transform: none; }
}

/* ---------- 响应式 ---------- */
@media (max-width: 860px) {
  .layerlab { grid-template-columns: 1fr; }
  .tl__item { grid-template-columns: 2.2rem minmax(0, 1fr); }
  .topbar { flex-wrap: wrap; }
  .topbar__nav { order: 3; width: 100%; }
}

/* ---------- 打印 / 强制色彩 ---------- */
@media print {
  .topbar, .pop { display: none; }
  .act { padding: 1.5rem 0; }
}
@media (forced-colors: active) {
  .ev { border: 1px solid CanvasText; }
  .ev__mark { forced-color-adjust: none; }
}

/* ============================================================
   五面环导览 —— 正五棱柱，左右旋转
   ------------------------------------------------------------
   只看这一段就能懂结构：
     .stage  →  撑开透视（perspective）
     .ring   →  preserve-3d，整环绕 Y 轴转
     .act    →  每个面自己 rotateY + translateZ，并各自滚动

   ⚠️ 两条硬规则，改动前务必看：
   1. 不要把 overflow 加到 .ring 或 .stage 上。
      overflow ≠ visible 会把该元素的 transform-style 强制成 flat，
      子级的 translateZ 立刻失效，整个环塌成一张纸。
   2. 面内的 3D（如四色分版的爆炸图）要自成一层 preserve-3d，
      它与环的 3D 是两套独立坐标系，互不影响。
   ============================================================ */

/* 默认（脚本未跑 / 旧浏览器）：老老实实一份纵向文档 */
.stage { display: block; }
.ring { display: block; }
.ringnav { display: none; }

html.is-ring {
  height: 100%;
  overflow: hidden;
  /* hidden 仍是可编程滚动的容器：scrollIntoView 会把整页横推，
     顶栏和正文一起被裁掉左边。clip 不允许任何滚动。 */
  overflow: clip;
  overscroll-behavior: none;
}
body.is-ring {
  /* 旧版移动浏览器没有 dvh：先给 vh 兜底，支持时再取动态视口高。 */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overflow: clip;
  display: flex;
  flex-direction: column;
}
/* 环模式下整个文档不滚动，顶栏不再需要 sticky */
body.is-ring .topbar { flex: 0 0 auto; position: relative; }
/* 底部控制条已经是一份完整目录，顶栏这六个锚点纯属重复 */
body.is-ring .topbar__nav { display: none; }
body.is-ring #app {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
body.is-ring .foot,
body.is-ring .act + .act { border-top: 0; }
body.is-ring .foot { display: none; }

body.is-ring .stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  /* 透视放在 stage 上，不能放 body（移动端 Safari 会错位） */
  perspective: 1800px;
  perspective-origin: 50% 50%;
}

body.is-ring .ring {
  /* 旧内核（Chromium <87）不认 inset：先写四边，下面的 inset 只是简写。 */
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  --face-w: min(1180px, calc(100vw - 2 * clamp(1rem, 5vw, 5rem)));
  /* 正五边形：中心到面中点 = (面宽 / 2) ÷ tan36° ≈ 0.6882 × 面宽。
     nav.js 会按实际面宽写入精确值，这里只是脚本未跑时的兜底。 */
  --ring-r: calc(var(--face-w) * 0.6882);
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform:
    translateZ(calc(-1 * var(--ring-r)))
    rotateY(calc(var(--idx, 0) * -1 * var(--step, 72deg)));
  will-change: transform;
}
body.is-ring .ring.is-ready {
  transition: transform .82s cubic-bezier(.22,.61,.36,1);
}
@media (prefers-reduced-motion: reduce) {
  body.is-ring .ring.is-ready { transition: none; }
}

body.is-ring .ring > .act {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--face-w);
  height: 100%;
  max-width: none;
  margin: 0 0 0 calc(var(--face-w) / -2);
  padding: clamp(1.5rem, 3.2vw, 2.8rem) clamp(1.1rem, 3vw, 2.6rem) 4.5rem;

  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--rule-soft);
  transform:
    rotateY(calc(var(--i, 0) * var(--step, 72deg)))
    translateZ(var(--ring-r));

  overflow-y: auto;
  /* 横向一律夹住，不光是藏起来：hidden 仍可被 scrollIntoView / 焦点
     程序化地推着横移，窄屏上曾出现整幕被推走 32px 的错位。
     clip 不允许任何横向滚动，旧浏览器忽略后回落到上一行。 */
  overflow-x: hidden;
  overflow-x: clip;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;

  /* 侧面压暗：静止时左右的邻面本来就露一条边（棱柱的侧面），
     不给它们降一档，前景和邻面会抢同一层注意力。
     用 opacity 而不是 filter：opacity 只把这一面拍平，面本身的
     三维姿态仍由 .ring 的 preserve-3d 决定，不会把环弄塌。 */
  opacity: .13;
  transition: opacity .82s var(--ease);
}
body.is-ring .ring > .act.is-front { opacity: 1; }

/* ⚠️ 静置时必须关掉 .stage 的透视。
   Chromium 对「preserve-3d 子树里、带 overflow:auto 的 3D 变换元素」
   做命中测试时会算错位置：正面明明铺在眼前，elementFromPoint 却只返回
   .ring / .stage，于是幕内的按钮、拖拽、滚动、抽屉全部点不到。
   （第二部分时间轴「看着在、点不动」就是这个原因。）
   正面的 3D 变换与环的变换合成后本来就是恒等，关掉透视视觉不变；
   命中与滚动则恢复原生。切换动画期间再把透视打开，棱柱的纵深还在。 */
body.is-ring.is-settled .stage { perspective: none; }
/* 没有透视时，邻面会以原尺寸平铺到画面两侧；静置时先让它们退场。
   切换开始时 is-settled 被移除，邻面立刻回来参与旋转。 */
body.is-ring.is-settled .ring > .act:not(.is-front) {
  opacity: 0;
  visibility: hidden;
}

/* 展开纹样标签时，环上邻面也退干净：
   否则纸边会透出别幕的字，放大图上压着一层灰字，很脏。 */
body.is-atlas.is-ring .ring > .act:not(.is-front) { opacity: 0; }
body.is-ring .ring > .act::-webkit-scrollbar { width: 8px; }
body.is-ring .ring > .act::-webkit-scrollbar-thumb {
  background: var(--rule);
  border-radius: 4px;
}
body.is-ring .ring > .act::-webkit-scrollbar-track { background: transparent; }

/* 关于上一段的 opacity：它只把「这一面内部」的 3D 拍平
   （图版微倾、四版爆炸图），不影响这一面在环里的三维姿态——
   环的 preserve-3d 挂在 .ring 上，不在这。
   面内 3D 只在正面用得到，所以给非正面压暗是安全的。
   ⚠️ 但别换成 filter：filter 还会新建包含块，滚动和 sticky 一起坏。 */

/* 图谱这一面不滚：图、索引点、标签全在一屏里。
   高度由 .atlas 撑满，图的尺寸由 js 按画布实测后写入。 */
/* 幕一做成定高纵向 flex：.atlas 拿到确定高度，
   .atlas__stage 才量得准，图的尺寸也才不会和画布互相撑。
   不设 overflow 在 .atlas 上——那会让 stage 的 flex 高度失效。 */
body.is-ring .act--see {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* 这一面不滚，上下留白直接换算成图的大小：
     省下的每一像素都进画心，而不是空在纸边。 */
  padding-top: 1.35rem;
  padding-bottom: .35rem;
}
body.is-ring .act--see .atlas { flex: 1 1 auto; min-height: 0; height: auto; }

/* 小屏：透视拉近一点，让「转过去」的感觉更明显；底留白避开控制条 */
@media (max-width: 700px) {
  body.is-ring .stage { perspective: 1300px; }
  body.is-ring .ring > .act { padding-bottom: 5.5rem; }
}

/* 矮屏（小手机竖屏、手机横屏、矮笔电）：图谱这一面允许纵向滚动，
   并给画心一个下限。否则定高 flex 会把图压成邮票，十四个索引点
   挤在一起，既看不清也点不准。 */
@media (max-height: 700px) {
  body.is-ring .ring > .act--see {
    overflow-y: auto;
    overflow-x: clip;
    padding-bottom: 1rem;
  }
  body.is-ring .act--see .atlas { min-height: 40rem; }
}

/* ---------- 底部控制条 ---------- */
body.is-ring .ringnav {
  position: relative;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: .55rem var(--pad-x) calc(.55rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--rule-soft);
  /* 旧内核没有 color-mix：给实底，导览条才不会和幕内文字叠在一起。 */
  background: var(--paper);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(10px);
}

.ringnav__btn {
  font-family: var(--font-sans);
  font-size: 1.15rem;
  line-height: 1;
  width: 2.1rem;
  height: 2.1rem;
  display: grid;
  place-items: center;
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
@media (pointer: coarse) {
  .ringnav__btn { width: 2.75rem; height: 2.75rem; }
}
.ringnav__btn:hover { border-color: var(--ink-3); color: var(--ink); }
.ringnav__btn:focus-visible { outline: 2px solid var(--dan-ink); outline-offset: 2px; }

/* 回封面：竖排两字，形同一枚小印，和五幕圆点分开 */
.ringnav__btn--cover {
  margin-right: .15rem;
  font-family: var(--font-serif);
  font-size: .58rem;
  letter-spacing: .06em;
  line-height: 1.1;
  color: var(--dan-ink);
  border-color: color-mix(in srgb, var(--dan) 42%, var(--rule));
}
.ringnav__btn--cover:hover { border-color: var(--dan-ink); color: var(--dan-ink); }
.ringnav__cover-t { writing-mode: vertical-rl; text-orientation: upright; }

.ringnav__dots { display: flex; gap: .15rem; }

.ringnav__dot {
  display: flex;
  align-items: baseline;
  gap: .25em;
  padding: .4rem .55rem;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--ink-3);
  font-family: var(--font-serif);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ringnav__dot-n { font-size: var(--fs-xs); letter-spacing: .1em; }
.ringnav__dot-x { font-size: .92rem; letter-spacing: .08em; }
.ringnav__dot:hover { color: var(--ink-2); }
.ringnav__dot.is-on { color: var(--dan-ink); border-bottom-color: var(--dan-ink); }
.ringnav__dot:focus-visible { outline: 2px solid var(--dan-ink); outline-offset: 1px; }

.ringnav__hint {
  position: absolute;
  right: var(--pad-x);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: .06em;
  transition: opacity .5s var(--ease);
}
.ringnav__hint.is-gone { opacity: 0; }

@media (max-width: 900px) {
  .ringnav__hint { display: none; }
}
@media (max-width: 440px) {
  .ringnav__dot { padding: .4rem .35rem; }
  .ringnav__dot-x { display: none; }
}

/* 打印时永远走纵向文档，别把六个面叠在一起 */
@media print {
  body.is-ring { height: auto; overflow: visible; display: block; }
  body.is-ring .ringnav { display: none; }
  body.is-ring .ring { position: static; transform: none; }
  body.is-ring .ring > .act {
    position: static; width: auto; height: auto; margin: 0;
    transform: none; box-shadow: none; overflow: visible; background: none;
    padding: 1.5rem 0;
    /* 静置态的邻面隐藏是为屏幕上的环服务的；打印时每一幕都要出现。
       静置选择器的优先级更高，这里必须 !important 才压得住。 */
    opacity: 1 !important; visibility: visible !important;
  }
  body.is-ring .ring > .act + .act { border-top: 1px solid var(--rule); }
}

/* ============================================================
   封面 · 入谱
   ------------------------------------------------------------
   一纸门画，一轮月洞门，一道朱线。
   指针移动时，画版、月环、云气按不同幅度错动。
   点「入谱」、向下滚轮或上滑，封面退场，五幕环接住。
   ============================================================ */
.cover {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  /* ⚠️ 先铺一层实纸色。下面那条 background 里用了 color-mix()，
     旧内核（Chromium <111、Safari <16.2、Firefox <113，以及不少
     国产浏览器的兼容内核）会把整条声明判为无效并丢弃。没有这行兜底，
     封面就变成透明，第一幕的文字和画版会直接透上来，和封面叠在一起。 */
  background: var(--paper);
  background:
    radial-gradient(120% 80% at 50% -10%,
      color-mix(in srgb, var(--paper-raised) 92%, var(--teng) 8%) 0%, transparent 58%),
    radial-gradient(70% 60% at 100% 100%,
      color-mix(in srgb, var(--qing) 7%, transparent) 0%, transparent 64%),
    radial-gradient(60% 50% at 0% 80%,
      color-mix(in srgb, var(--dan) 6%, transparent) 0%, transparent 60%),
    var(--paper);
  isolation: isolate;
}
body.is-ring .cover {
  position: fixed;
  /* 旧内核不认 inset：四边分开写，封面才会真正铺满整屏。
     少了这一步，封面会缩成固定定位的「静态大小」，和第一幕叠在一起。 */
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  inset: 0;
  z-index: 35;
}
.cover[hidden] { display: none; }
body.is-cover { overflow: hidden; }
body.is-cover .topbar {
  background: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
  z-index: 60;
}
body.is-cover .topbar__id,
body.is-cover .topbar__nav { display: none; }
body.is-cover .topbar .themetoggle { margin-left: auto; }

/* 纸面下的水墨晕染 */
.cover__wash {
  position: absolute;
  inset: -10%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(32rem 26rem at 72% 44%,
      color-mix(in srgb, var(--teng) 13%, transparent) 0%, transparent 62%),
    radial-gradient(26rem 22rem at 24% 72%,
      color-mix(in srgb, var(--dan) 8%, transparent) 0%, transparent 68%),
    radial-gradient(22rem 18rem at 58% 8%,
      color-mix(in srgb, var(--qing) 7%, transparent) 0%, transparent 70%);
  filter: blur(2px);
}

/* 云气 */
.cover__cloud {
  position: absolute;
  z-index: 1;
  width: min(52rem, 68vw);
  height: auto;
  color: color-mix(in srgb, var(--teng) 46%, var(--rule));
  opacity: .34;
  pointer-events: none;
}
.cover__cloud--tl { top: -6rem; left: -14rem; transform: rotate(-6deg); }
.cover__cloud--br { right: -16rem; bottom: -7rem; transform: rotate(174deg); opacity: .26; }

/* 左侧朱线：书口 / 门框 */
.cover__thread {
  position: absolute;
  z-index: 2;
  left: clamp(1rem, 3.6vw, 3.2rem);
  top: 13vh;
  bottom: 13vh;
  width: 1px;
  background: linear-gradient(to bottom,
    transparent, color-mix(in srgb, var(--dan) 62%, transparent) 18%,
    color-mix(in srgb, var(--dan) 62%, transparent) 82%, transparent);
  pointer-events: none;
}
.cover__thread::before,
.cover__thread::after {
  content: '';
  position: absolute;
  left: -3px;
  width: 7px;
  height: 7px;
  border: 1px solid color-mix(in srgb, var(--dan) 62%, transparent);
  transform: rotate(45deg);
}
.cover__thread::before { top: -3px; }
.cover__thread::after { bottom: -3px; }

/* 版心 */
.cover__inner {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: minmax(17rem, .82fr) minmax(0, 1.18fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4.5rem);
  width: min(100%, 1320px);
  min-height: 100vh;
  margin: 0 auto;
  padding: clamp(4.2rem, 9vh, 7rem) clamp(1.5rem, 6vw, 6.5rem)
           clamp(3.6rem, 8vh, 5.6rem);
}

/* ---- 左：题名 ---- */
.cover__text { position: relative; }
.cover__kicker {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: 0 0 clamp(1.2rem, 4vh, 2.4rem);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .22em;
  color: var(--ink-3);
}
.cover__seal {
  display: inline-grid;
  place-items: center;
  width: 1.55rem;
  height: 1.55rem;
  flex: 0 0 auto;
  background: var(--dan-ink);
  color: #FDF8EC;
  font-family: var(--font-serif);
  font-size: .82rem;
  line-height: 1;
  letter-spacing: 0;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #FDF8EC 35%, transparent);
  transform: rotate(-2deg);
}
.cover__lead {
  display: flex;
  align-items: flex-start;
  gap: clamp(.7rem, 2vw, 1.5rem);
}
.cover__title {
  writing-mode: vertical-rl;
  text-orientation: upright;
  margin: 0;
  font-size: clamp(3.1rem, 8.4vh, 6.4rem);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: .09em;
  color: var(--ink);
  text-shadow: 0 1px 0 color-mix(in srgb, var(--paper-raised) 80%, transparent);
}
.cover__title span { display: inline; }
.cover__title span:nth-child(1) { animation-delay: .10s; }
.cover__title span:nth-child(2) { animation-delay: .19s; }
.cover__title span:nth-child(3) { animation-delay: .28s; }
.cover__title span:nth-child(4) { animation-delay: .37s; }
.cover__side {
  writing-mode: vertical-rl;
  margin: .35rem 0 0;
  padding-left: .55rem;
  border-left: 1px solid color-mix(in srgb, var(--dan) 45%, transparent);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .42em;
  color: var(--ink-3);
}
.cover__sub {
  margin: clamp(1.1rem, 3vh, 1.8rem) 0 .45rem;
  font-size: clamp(.98rem, 1.4vw, 1.16rem);
  letter-spacing: .16em;
  color: var(--ink-2);
}
.cover__lede {
  margin: 0 0 clamp(1.5rem, 4vh, 2.6rem);
  color: var(--ink-3);
  font-size: .98rem;
  line-height: 2;
  letter-spacing: .08em;
}
.cover__enter {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .18rem;
  padding: .78rem 1.6rem .72rem;
  background: transparent;
  /* 旧内核没有 color-mix：保留一圈实线，入谱按钮不能变成裸字。 */
  border: 1px solid var(--dan-ink);
  border: 1px solid color-mix(in srgb, var(--dan-ink) 72%, var(--rule));
  color: var(--dan-ink);
  cursor: pointer;
  overflow: hidden;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.cover__enter::before {
  content: '';
  position: absolute;
  inset: 3px;
  border: 1px solid color-mix(in srgb, var(--dan-ink) 22%, transparent);
  pointer-events: none;
  transition: border-color var(--dur) var(--ease);
}
.cover__enter:hover,
.cover__enter:focus-visible {
  background: var(--dan-ink);
  border-color: var(--dan-ink);
  color: #FDF8EC;
  transform: translateY(-2px);
}
.cover__enter:hover::before,
.cover__enter:focus-visible::before {
  border-color: color-mix(in srgb, #FDF8EC 40%, transparent);
}
.cover__enter:focus-visible { outline: 2px solid var(--dan-ink); outline-offset: 4px; }
.cover__enter-cn {
  font-family: var(--font-serif);
  font-size: 1.18rem;
  letter-spacing: .3em;
  line-height: 1.2;
}
.cover__enter-en {
  font-family: var(--font-sans);
  font-size: .62rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: .68;
}
.cover__hint {
  margin: 1.1rem 0 0;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .14em;
  color: var(--ink-3);
  opacity: .75;
}

/* ---- 右：月洞门与画版 ---- */
.cover__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 0;
  height: clamp(27rem, 66vh, 43rem);
}
.cover__moon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(37vw, 31rem);
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -52%);
  background:
    radial-gradient(circle at 50% 42%,
      color-mix(in srgb, var(--teng) 13%, var(--paper-raised)) 0%,
      color-mix(in srgb, var(--paper-raised) 55%, transparent) 58%,
      transparent 72%);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teng) 36%, transparent),
    0 0 4.5rem color-mix(in srgb, var(--teng) 12%, transparent);
  pointer-events: none;
}
.cover__moon-ring {
  position: absolute;
  inset: 6.5%;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teng) 26%, transparent);
}
.cover__moon-ring--2 {
  inset: 13%;
  border-style: dashed;
  border-color: color-mix(in srgb, var(--dan) 19%, transparent);
}
.cover__plate {
  position: relative;
  z-index: 2;
  margin: 0;
  height: min(62vh, 38rem);
  max-height: calc(100% - 2.4rem);
  transform:
    perspective(1000px)
    rotateY(calc(var(--mx, 0) * 8deg))
    rotateX(calc(var(--my, 0) * -7deg))
    translate3d(calc(var(--mx, 0) * -8px), calc(var(--my, 0) * -6px), 0);
  transition: transform .22s cubic-bezier(.22,.61,.36,1);
  will-change: transform;
}
.cover__plate::before {
  content: '';
  position: absolute;
  inset: -9px;
  border: 1px solid color-mix(in srgb, var(--teng) 34%, transparent);
  pointer-events: none;
}
.cover__plate img {
  height: 100%;
  width: auto;
  max-width: none;
  object-fit: contain;
  box-shadow:
    0 1.4rem 3.2rem color-mix(in srgb, var(--ink) 16%, transparent),
    0 0 0 1px color-mix(in srgb, var(--ink) 8%, transparent);
  animation: coverPlate 1.15s cubic-bezier(.22,.61,.36,1) both;
}
.cover__stamp {
  position: absolute;
  right: -1.05rem;
  bottom: 1.3rem;
  z-index: 3;
  writing-mode: vertical-rl;
  text-orientation: upright;
  padding: .42rem .3rem;
  background: var(--dan-ink);
  color: #FDF8EC;
  font-family: var(--font-serif);
  font-size: .68rem;
  line-height: 1.05;
  letter-spacing: .14em;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #FDF8EC 38%, transparent);
  transform: rotate(1.5deg);
  opacity: .92;
}
.cover__credit {
  position: relative;
  z-index: 2;
  max-width: 26rem;
  margin: 1.15rem 0 0;
  font-family: var(--font-sans);
  font-size: .63rem;
  line-height: 1.65;
  letter-spacing: .04em;
  color: var(--ink-3);
  text-align: center;
  opacity: .82;
}

/* ---- 页脚 ---- */
.cover__foot {
  position: absolute;
  z-index: 4;
  left: clamp(2.2rem, 6vw, 6.5rem);
  right: clamp(1.5rem, 6vw, 6.5rem);
  bottom: clamp(1.1rem, 3vh, 2rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding-top: .8rem;
  border-top: 1px solid color-mix(in srgb, var(--rule) 72%, transparent);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: .16em;
  color: var(--ink-3);
}
.cover__roll { display: inline-flex; align-items: center; gap: .55rem; }
.cover__roll i {
  display: inline-block;
  width: 1px;
  height: 1.55rem;
  background: linear-gradient(to bottom, transparent, var(--dan));
  animation: coverRoll 2.4s ease-in-out infinite;
}

/* ---- 动画 ---- */
.cover__title span {
  display: inline-block;
  animation: coverChar .9s cubic-bezier(.22,.61,.36,1) both;
}
.cover__kicker,
.cover__sub,
.cover__lede,
.cover__enter,
.cover__hint {
  animation: coverFade .95s cubic-bezier(.22,.61,.36,1) both;
}
.cover__kicker { animation-delay: .32s; }
.cover__sub { animation-delay: .46s; }
.cover__lede { animation-delay: .55s; }
.cover__enter { animation-delay: .66s; }
.cover__hint { animation-delay: .82s; }
.cover__moon-ring--2 { animation: coverSpin 90s linear infinite; }
.cover__cloud--tl { animation: coverDrift 22s ease-in-out infinite alternate; }
.cover__cloud--br { animation: coverDrift 27s ease-in-out infinite alternate-reverse; }

@keyframes coverChar {
  from { opacity: 0; transform: translateY(1.1em); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: none; }
}
@keyframes coverFade {
  from { opacity: 0; transform: translateY(.9rem); }
  to   { opacity: 1; transform: none; }
}
@keyframes coverPlate {
  from { opacity: 0; transform: translateY(1.6rem) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes coverSpin { to { transform: rotate(360deg); } }
@keyframes coverDrift {
  from { translate: 0 0; }
  to   { translate: 1.4rem -1rem; }
}
@keyframes coverRoll {
  0%, 100% { transform: scaleY(.3); opacity: .4; }
  50%      { transform: scaleY(1); opacity: 1; }
}

/* 离场：纸面淡出、版心上浮，环在背后显影 */
.cover.is-leaving {
  pointer-events: none;
  opacity: 0;
  transition: opacity .8s cubic-bezier(.22,.61,.36,1) .12s;
}
.cover.is-leaving .cover__inner {
  transform: translateY(-1.4rem) scale(1.012);
  transition: transform .8s cubic-bezier(.22,.61,.36,1);
}

/* 窄屏：题名改横排，画版先入眼 */
@media (max-width: 760px) {
  .cover__inner {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: .55rem;
    padding: 3.6rem 1.4rem 3.2rem;
  }
  .cover__stage {
    order: -1;
    height: auto;
    min-height: 0;
    width: 100%;
  }
  .cover__moon {
    width: min(62vw, 18rem);
    top: 42%;
  }
  .cover__plate { height: 32vh; max-height: 32vh; }
  /* 窄屏仍留一行出处：画版可以缩小，来源不能省。 */
  .cover__credit {
    display: block;
    max-width: 21rem;
    margin: .35rem 0 0;
    font-size: .53rem;
    line-height: 1.45;
    text-align: center;
    color: var(--ink-3);
    opacity: .78;
  }
  .cover__lead { align-items: center; }
  .cover__title {
    writing-mode: horizontal-tb;
    display: flex;
    gap: .1em;
    font-size: clamp(2.55rem, 12vw, 3.6rem);
    letter-spacing: .04em;
  }
  .cover__title span { display: inline-block; }
  .cover__side { display: none; }
  .cover__kicker { margin-bottom: .7rem; }
  .cover__sub { margin-top: .3rem; font-size: .95rem; letter-spacing: .1em; }
  .cover__lede { display: none; }
  .cover__enter { margin-top: .9rem; }
  .cover__hint { display: none; }
  .cover__foot { left: 1.4rem; right: 1.4rem; justify-content: center; }
  .cover__foot > span:not(.cover__roll) { display: none; }
  .cover__thread { left: .7rem; top: 16vh; bottom: 16vh; }
}
/* 中等高度（768–900）：题名与留白一起收一档。
   标题按 vh 放大、内边距也按 vh 放大，两者相加会在 768 左右
   超过一屏，把页脚压到提示语上。收一档后整块重新回到屏内。 */
@media (max-height: 900px) and (min-width: 761px) {
  .cover__inner {
    padding-top: clamp(2.6rem, 6vh, 4.6rem);
    padding-bottom: clamp(2.2rem, 5vh, 3.4rem);
  }
  .cover__title { font-size: clamp(2.7rem, 6.6vh, 5.4rem); }
  .cover__kicker { margin-bottom: clamp(.7rem, 2.2vh, 1.4rem); }
  .cover__sub { margin-top: clamp(.7rem, 1.8vh, 1.2rem); }
  .cover__lede { margin-bottom: clamp(.9rem, 2.4vh, 1.8rem); line-height: 1.85; }
  .cover__hint { margin-top: .6rem; }
}

/* 矮屏（笔电横屏、手机横屏）：删去次要段落，让画版与题名并排收进一屏，
   「入谱」永远在首屏可见。 */
@media (max-height: 720px) and (min-width: 761px) {
  .cover__inner {
    padding-top: 1.6rem;
    padding-bottom: 1.4rem;
    gap: clamp(1rem, 3vw, 2.4rem);
  }
  .cover__title { font-size: clamp(2.1rem, 6.4vh, 3.2rem); }
  .cover__kicker { margin-bottom: .45rem; font-size: .68rem; }
  .cover__sub {
    margin-top: .35rem;
    margin-bottom: .3rem;
    font-size: .88rem;
    letter-spacing: .1em;
  }
  .cover__lede, .cover__hint { display: none; }
  .cover__enter { margin-top: .5rem; padding: .55rem 1.25rem .5rem; }
  .cover__enter-cn { font-size: 1rem; }
  .cover__stage { height: 82vh; }
  .cover__plate { height: min(72vh, 22rem); }
  .cover__credit {
    margin-top: .45rem;
    font-size: .54rem;
    line-height: 1.45;
  }
  .cover__foot { font-size: .58rem; bottom: .8rem; }
}

/* 窄而矮（如 667×375 手机横屏）：仍走单列，但把画版和留白再收一档 */
@media (max-height: 520px) and (max-width: 760px) {
  .cover__inner {
    padding: 1.2rem 1.2rem 1rem;
    gap: .3rem;
  }
  .cover__stage { height: auto; }
  .cover__plate { height: 26vh; max-height: 26vh; }
  .cover__moon { width: min(36vw, 11rem); top: 40%; }
  .cover__credit {
    max-width: 21rem;
    margin-top: .25rem;
    font-size: .48rem;
    line-height: 1.35;
  }
  .cover__kicker { margin-bottom: .35rem; font-size: .66rem; }
  .cover__seal { width: 1.2rem; height: 1.2rem; font-size: .68rem; }
  .cover__title { font-size: clamp(1.8rem, 8vh, 2.4rem); }
  .cover__sub { display: none; }
  .cover__enter { margin-top: .35rem; padding: .45rem 1rem .4rem; }
  .cover__enter-cn { font-size: .95rem; }
  .cover__enter-en { font-size: .54rem; }
  .cover__foot { left: .9rem; right: .9rem; bottom: .5rem; font-size: .54rem; }
}

/* 480–760px 宽的横屏（如 667×375、568×320）：单栏会把画版压成
   邮票，改回两栏——题名竖排、画版占右侧，横屏的高度才用得满。
   这一段必须排在上面那条「窄而矮」之后，否则单栏的尺寸会把
   画版高度、月亮尺寸和题名字号一并盖回去。 */
@media (max-height: 520px) and (min-width: 480px) and (max-width: 760px) {
  .cover__inner {
    display: grid;
    grid-template-columns: minmax(11.5rem, .82fr) minmax(0, 1.18fr);
    align-items: center;
    gap: 1rem;
    padding: 1.1rem 1.3rem 1rem;
  }
  .cover__stage { order: 0; height: auto; }
  .cover__moon { width: min(30vw, 12rem); top: 50%; }
  .cover__plate { height: min(78vh, 17rem); max-height: 78vh; }
  .cover__title {
    writing-mode: vertical-rl;
    text-orientation: upright;
    display: block;
    font-size: clamp(1.7rem, 7.6vh, 2.3rem);
    letter-spacing: .09em;
  }
  .cover__title span { display: inline; }
  .cover__side { display: none; }
  .cover__kicker {
    margin-bottom: .3rem;
    font-size: .6rem;
    letter-spacing: .1em;
  }
  .cover__credit {
    max-width: 100%;
    margin-top: .35rem;
    font-size: .48rem;
    line-height: 1.4;
  }
  .cover__enter { margin-top: .3rem; }
}

/* 480–540px 宽、≤380px 高（如 480×320、500×360）：两栏仍成立，
   但画版要再收一档，给上方的主题开关和下方的出处让出位置；
   页脚那行「向下·入谱」此时会压到出处上，整行隐去。 */
@media (max-height: 380px) and (min-width: 480px) and (max-width: 540px) {
  .cover__inner {
    grid-template-columns: minmax(10.5rem, .78fr) minmax(0, 1.22fr);
    gap: .7rem;
    padding: .9rem 1rem .8rem;
  }
  .cover__plate { height: min(62vh, 13rem); max-height: 62vh; }
  .cover__moon { width: min(30vw, 10rem); }
  .cover__title { font-size: clamp(1.45rem, 7vh, 1.9rem); }
  .cover__kicker { font-size: .54rem; letter-spacing: .06em; }
  .cover__credit { font-size: .42rem; line-height: 1.3; }
  .cover__enter { margin-top: .2rem; padding: .35rem .8rem .3rem; }
  .cover__enter-cn { font-size: .85rem; }
  .cover__enter-en { font-size: .48rem; }
  .cover__foot { display: none; }
}
/* 320 级高度（568×320 等）：页脚那行「向下·入谱」会压到画版出处上。
   左侧已有入谱按钮，页脚让位，出处才能完整读完。 */
@media (max-height: 340px) and (min-width: 480px) and (max-width: 760px) {
  .cover__foot { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cover__title span,
  .cover__kicker, .cover__sub, .cover__lede, .cover__enter, .cover__hint,
  .cover__plate img, .cover__moon-ring--2,
  .cover__cloud--tl, .cover__cloud--br,
  .cover__roll i { animation: none !important; }
  .cover__plate { transition: none; }
  .cover.is-leaving { transition-duration: .01s; }
  .cover.is-leaving .cover__inner { transition: none; }
}

/* ============================================================
   古韵层 · 纸、墨、金、朱
   ------------------------------------------------------------
   只做加法：在既有版式上补纸色晕染、书口角标、朱砂印与
   描金细线。所有效果都不改变排版尺寸，窄屏自动退场。
   ============================================================ */
::selection {
  background: color-mix(in srgb, var(--dan) 26%, transparent);
  color: var(--ink);
}

/* 纸色：极淡的藤黄与石青从两角洇开 */
body {
  background-color: var(--paper);
  background-image:
    radial-gradient(70rem 46rem at 50% -18%,
      color-mix(in srgb, var(--teng) 7%, transparent), transparent 62%),
    radial-gradient(48rem 38rem at 104% 102%,
      color-mix(in srgb, var(--qing) 6%, transparent), transparent 66%);
  background-attachment: fixed;
}

/* 每一幕：纸心稍亮，四边略沉，像一张托裱过的画心 */
body.is-ring .ring > .act {
  background:
    radial-gradient(118% 74% at 50% 0%,
      color-mix(in srgb, var(--paper-raised) 62%, transparent), transparent 62%),
    radial-gradient(86% 66% at 100% 102%,
      color-mix(in srgb, var(--teng) 5%, transparent), transparent 64%),
    var(--paper);
  box-shadow:
    inset 0 0 0 1px var(--rule-soft),
    inset 0 0 9rem color-mix(in srgb, var(--teng) 4%, transparent);
}

/* 四角描金细框：像册页的包角 */
@media screen and (min-width: 761px) {
  body.is-ring::before {
    content: '';
    position: fixed;
    inset: .58rem;
    z-index: 70;
    pointer-events: none;
    opacity: .5;
    background:
      linear-gradient(var(--teng), var(--teng)) left top / 1.35rem 1px no-repeat,
      linear-gradient(var(--teng), var(--teng)) left top / 1px 1.35rem no-repeat,
      linear-gradient(var(--teng), var(--teng)) right top / 1.35rem 1px no-repeat,
      linear-gradient(var(--teng), var(--teng)) right top / 1px 1.35rem no-repeat,
      linear-gradient(var(--teng), var(--teng)) left bottom / 1.35rem 1px no-repeat,
      linear-gradient(var(--teng), var(--teng)) left bottom / 1px 1.35rem no-repeat,
      linear-gradient(var(--teng), var(--teng)) right bottom / 1.35rem 1px no-repeat,
      linear-gradient(var(--teng), var(--teng)) right bottom / 1px 1.35rem no-repeat;
  }
}

/* 顶栏：一枚朱印 */
.topbar__id {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
}
.topbar__id:hover { color: var(--ink); }
.topbar__id:hover::before { background: var(--dan); }
.topbar__id::before {
  content: '天';
  display: inline-grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  flex: 0 0 auto;
  background: var(--dan-ink);
  color: #FDF8EC;
  font-family: var(--font-serif);
  font-size: .72rem;
  line-height: 1;
  letter-spacing: 0;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #FDF8EC 32%, transparent);
}
.topbar { border-bottom-color: color-mix(in srgb, var(--rule) 74%, var(--teng)); }

/* 小引题：一枚朱砂菱点 */
.kicker::before {
  content: '';
  display: inline-block;
  width: .38rem;
  height: .38rem;
  margin-right: .62em;
  background: var(--dan);
  transform: rotate(45deg) translateY(-.06em);
  opacity: .85;
}

/* 幕首：题下添一道朱→金细线 */
.act__head::after {
  content: '';
  display: block;
  width: 5.6rem;
  height: 1px;
  margin-top: 1.05rem;
  background: linear-gradient(90deg,
    var(--dan), color-mix(in srgb, var(--teng) 72%, transparent) 62%, transparent);
}

/* 大标题：纸面微微托起 */
.act__title, .hero-title {
  text-shadow: 0 1px 0 color-mix(in srgb, var(--paper-raised) 62%, transparent);
}

/* 小标题下的朱线，末端收成金 */
.sub { border-bottom-color: transparent; position: relative; }
.sub::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--dan), color-mix(in srgb, var(--teng) 62%, var(--dan)));
}

/* 底部控制条：描金上沿，当前幕留一枚朱点 */
body.is-ring .ringnav {
  border-top-color: color-mix(in srgb, var(--teng) 46%, var(--rule-soft));
}
.ringnav__dot.is-on { position: relative; }
.ringnav__dot.is-on::after {
  content: '';
  position: absolute;
  top: -.12rem;
  left: 50%;
  width: .3rem;
  height: .3rem;
  background: var(--dan);
  transform: translateX(-50%) rotate(45deg);
}

/* 页脚：上下两道渐隐细线 */
.foot { position: relative; }
.foot::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--rule) 14%, var(--rule) 86%, transparent);
}

/* 焦点：朱砂色，不用系统蓝 */
:where(a, button, [tabindex]):focus-visible {
  outline-color: var(--dan-ink);
}

/* 暗色：金线压暗，别让描金在夜里发亮 */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) body.is-ring::before { opacity: .3; }
}
:root[data-theme="dark"] body.is-ring::before { opacity: .3; }
:root[data-theme="dark"] .act__title,
:root[data-theme="dark"] .hero-title { text-shadow: none; }

/* 320px 级窄屏：顶栏不换行。
   标题全文不删，只把字距和印章收小，让「明/暗」留在同一行——
   顶栏每多一行，幕内可用高度就少一截。 */
@media (max-width: 380px) {
  .topbar { gap: .4rem; padding: .5rem var(--pad-x); }
  .topbar__id { font-size: .64rem; letter-spacing: .06em; gap: .4rem; }
  .topbar__id::before { width: 1.2rem; height: 1.2rem; font-size: .68rem; }
  .themetoggle { padding: .25rem .45rem; font-size: .66rem; }
}

/* ============================================================
   幕背景照片
   ------------------------------------------------------------
   只用 background-image 垫在幕的纸色之下，不新增任何命中层：
   背景不是元素，滑块、热点、3D 节点的命中测试不受影响。
   幕本身是滚动容器时，默认的 background-attachment:scroll
   让底图跟着「幕」而不是「内容」走，滚动时始终铺满可见面。
   每层压一道纸色蒙版，正文对比度不随底图深浅变化。
   ============================================================ */
.act--see,
body.is-ring .ring > .act--see {
  background-image:
    linear-gradient(var(--photo-veil-see), var(--photo-veil-see)),
    url("../assets/bg/act-see.jpg");
  background-size: cover, cover;
  background-position: center, center 44%;
  background-repeat: no-repeat, no-repeat;
}

.act--source,
body.is-ring .ring > .act--source {
  background-image:
    linear-gradient(var(--photo-veil-source), var(--photo-veil-source)),
    url("../assets/bg/act-source-fragment.jpg");
  background-size: cover, cover;
  background-position: center, right 18%;
  background-repeat: no-repeat, no-repeat;
}

.act--craft,
body.is-ring .ring > .act--craft {
  background-image:
    linear-gradient(var(--photo-veil-craft), var(--photo-veil-craft)),
    url("../assets/bg/act-craft-print.jpg");
  background-size: cover, cover;
  background-position: center, right 8%;
  background-repeat: no-repeat, no-repeat;
}

.act--opera,
body.is-ring .ring > .act--opera {
  background-image:
    linear-gradient(var(--photo-veil-opera), var(--photo-veil-opera)),
    url("../assets/bg/act-opera-embroidery.jpg");
  background-size: cover, cover;
  background-position: center, right top;
  background-repeat: no-repeat, no-repeat;
}

.act--legacy,
body.is-ring .ring > .act--legacy {
  background-image:
    linear-gradient(var(--photo-veil-legacy), var(--photo-veil-legacy)),
    url("../assets/bg/act-legacy-mother.jpg");
  background-size: cover, cover;
  background-position: center, right 34%;
  background-repeat: no-repeat, no-repeat;
}

/* 时间轴：底图只铺在 3D 舞台里，不碰页签、缩略轴与详情抽屉。
   .tree 自带 mask-image，左右两端会自然淡出。
   底图中段自带一根轴线和几枚圆点，不额外压掉会和真实节点混淆；
   所以除通铺蒙版外，再叠一道上下渐隐的厚蒙版，只露出底部山形。 */
.tree {
  background-image:
    linear-gradient(to bottom,
      var(--photo-veil-timeline-clear) 0%,
      var(--photo-veil-timeline-band) 12%,
      var(--photo-veil-timeline-band) 62%,
      var(--photo-veil-timeline-clear) 80%),
    linear-gradient(var(--photo-veil-timeline), var(--photo-veil-timeline)),
    url("../assets/bg/timeline.jpg");
  background-size: 100% 100%, cover, cover;
  background-position: center, center, center 62%;
  background-repeat: no-repeat, no-repeat, no-repeat;
}

@media print {
  body.is-ring::before { display: none; }
  .act--see, .act--source, .act--craft, .act--opera, .act--legacy, .tree,
  body.is-ring .ring > .act {
    background-image: none;
  }
}
