/* @pages-only:start
 *
 * 这一段到 @pages-only:end 之间，只有品牌站自己的页面用得上（首页各节、排盘工具介绍页）。
 * 内容层那四千多页（古籍 / 词条 / 工具落地页）一条都不需要，所以构建时把它切成单独一个
 * 文件，只让品牌页去链——见 build-legal-static.mjs 的 writeCss。
 *
 * 分开的理由不是省那几十 KB 的磁盘，而是：搜索来的访客几乎每次都是第一次访问，
 * 缓存永远轮不到发挥，渲染阻塞的字节是每一次访问都要付的。
 *
 * 加新的首页板块请写在这两个标记之间；写在外面会让四千多页跟着变重。
 */

/* ── Hero ─────────────────────────────────────────────── */

/*
 * Hero 刻意压扁：openai.com 的首屏在标题 + 输入框 + 气泡之后就直接露出下一屏内容，
 * 让人一眼知道页面还有东西。留白给多了会把板块整个推到折叠线以下。
 */
.hero {
  padding: 40px 0 32px;
  text-align: center;
}

@media (min-width: 768px) {
  .hero {
    padding: 64px 0 40px;
  }
}

/*
 * 中间那一档用 vw 而不是固定值：桌面上 3.2vw 早就顶到 2.5rem 的上限，可到了手机
 * 3.2vw 只有 12px，会一路掉到 1.6rem 的下限，一句大标题缩成正文大小。
 * 改成 8vw 后，390 宽的手机上约 33px，正好占满一行，桌面仍旧封顶在 2.5rem。
 */
.hero h1 {
  margin: 0 auto 1.5rem;
  max-width: 20em;
  font-size: clamp(1.6rem, 8vw, 2.5rem);
  line-height: 1.25;
  /* 居中多行标题最忌末行只剩一两个字；balance 让各行长度均匀。不支持的浏览器按普通换行。 */
  text-wrap: balance;
}

/*
 * 首页大标题专用字体。拉丁那份排在前面：它没有 CJK 字形，中文会自动落到 Hero CJK，
 * 一条 font-family 同时管住两种语言。只作用于 .display，板块页的 h1 不受影响
 * （那些字不在子集里）。
 */
.hero h1.display {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: 0.01em;
}

/*
 * Great Vibes 是连笔体：字距一放宽字母之间就断开，所以必须贴着排；
 * 又因为它的上下伸展远超字身，窄屏折行时 1.25 的行距会让上一行的下沿撞到下一行的上沿。
 */
html[lang="en"] .hero h1.display {
  letter-spacing: 0;
  line-height: 1.45;
}

/*
 * 逐字模糊渐显，与应用「问 AI」流式回答的 tokenFade 同参数（0.4s ease-out，
 * opacity 0→1 配 blur(1px)→0）。起跑时刻由 JS 写在各 span 的 animation-delay 上。
 */
.hero h1.display .ch {
  opacity: 0;
  animation: tokenFade 0.4s ease-out forwards;
}

@keyframes tokenFade {
  from {
    opacity: 0;
    filter: blur(1px);
  }

  to {
    opacity: 1;
    filter: blur(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero h1.display .ch {
    opacity: 1;
    animation: none;
  }
}

.hero .lede {
  margin: 0 auto 2.25rem;
  max-width: 40rem;
  color: var(--muted);
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  text-wrap: balance;
}

/* 对话框：整体一个圆角面板。openai.com 实测是 700px，这里放宽到 820px。 */
.composer {
  max-width: 820px;
  margin: 0 auto;
  text-align: left;
}

/*
 * 发送键绝对定位在右下角，不单独占一行——占一行会平白把面板拉高一截。
 * 文字不会压到按钮上：textarea 自己留了 padding-bottom，正文永远排在按钮所在的那条带之上。
 */
.composer form {
  position: relative;
  padding: 0.9rem 1rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: 0 6px 24px rgba(31, 27, 22, 0.06);
}

/*
 * 输入框聚焦不做任何描边或高亮：页面一进来就自动聚焦，任何焦点样式都会一直亮着，
 * 看上去像是报错或选中态。文本框本身有闪烁的光标，那已经是它的焦点指示；
 * 发送键仍保留全局的 :focus-visible 轮廓，键盘导航不会失去落点。
 */

/*
 * 轮换占位的容器。
 *
 * 高度锁一行、overflow:hidden，文字才能「从下方推上来」而不是在框外露头。
 * 只覆盖第一行：输入超过一行时 ghost 已经被 JS 隐藏，不会挡住内容。
 */
.composer .field {
  position: relative;
}

.composer .ghost {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1.6em;
  overflow: hidden;
  pointer-events: none;
  color: #a99374;
  font-size: 1rem;
  line-height: 1.6;
  text-align: left;
}

.composer .ghost .t {
  display: block;
  white-space: nowrap;
}

.composer .ghost .t.in {
  animation: ghostIn 0.34s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.composer .ghost .t.out {
  animation: ghostOut 0.24s ease-in both;
}

/* 进出方向一致（都朝上走），读起来才像一条向上滚动的列表，而不是原地闪烁。 */
@keyframes ghostIn {
  from {
    opacity: 0;
    transform: translateY(100%);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes ghostOut {
  from {
    opacity: 1;
    transform: translateY(0);
  }

  to {
    opacity: 0;
    transform: translateY(-100%);
  }
}

.composer textarea {
  display: block;
  width: 100%;
  /* 两行正文 + 一条留给发送键的底带。 */
  height: 5.4em;
  max-height: 12rem;
  padding: 0 0 2.2em;
  border: 0;
  outline: none;
  resize: none;
  overflow-y: auto;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.6;
}

.composer textarea::placeholder {
  color: #a99374;
}

.composer .send {
  position: absolute;
  right: 0.85rem;
  bottom: 0.85rem;
  width: 2.2rem;
  height: 2.2rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.composer .send:hover {
  background: var(--accent-ink);
}

.composer .hint {
  margin: 0.75rem 0 0;
  color: var(--muted);
  font-size: 0.85rem;
  text-align: center;
}

/* 示例问题：点一下填进输入框 */
.suggests {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
}

.suggests a {
  display: inline-block;
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 0.88rem;
}

.suggests a:hover {
  background: var(--tint);
  border-color: var(--accent);
  text-decoration: none;
}

/* @pages-only:end */
/* @pages-only:start */

/* ── 中道 ─────────────────────────────────────────────── */

/*
 * 首页第二屏，也是首页唯一一屏内容。
 *
 * 整块是一条墨色通栏，与上方米色的 Hero 硬接——这一刀本身就是分界，不再加分隔线。
 * 中心压一层极淡的暖光，像纸被灯照着；四周沉下去，字浮上来。
 *
 * 配色不进 :root：这套墨底金字只服务这一节，放进全局令牌会诱使别处误用。
 */
/*
 * 首屏：Hero 撑到「一屏 − 入口引导 − 顶栏」，于是折叠线正好落在中道那一节的上沿——
 * 首屏因此是完整的一片米白，墨色一点都不露。
 *
 * 顶栏要减掉：它虽然是 sticky，停在页顶时仍然实打实占着文档流的那一格，
 * 并没有浮在 Hero 上面。
 */
.hero:has(+ .tao-enter) {
  display: grid;
  align-content: center;
  min-height: calc(100svh - var(--enter-h) - var(--header-h));
  padding-top: 0;
  padding-bottom: 0;
}

/*
 * 首屏底部的入口：箭头 + 一句引导语，点它进中道。
 *
 * 这块不带底色。此前试过在这里探出一道墨色（先是四级阶梯，后来是一条横带），
 * 两版都不成立：首屏是米白的场，底下压一条黑就把整屏割成两截，
 * 而那条黑既不承载信息也不属于 Hero。现在留白到底，邀请全交给箭头和文字，
 * 墨色一直等到折叠线以下才出现。
 */
.tao-enter {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  height: var(--enter-h);
  text-decoration: none;
}

.tao-enter:hover {
  text-decoration: none;
}

/* 引导语：与箭头同为邀请的一部分，字距放开，像页脚上题的一行小字。 */
.tao-enter-label {
  color: var(--muted);
  font-family: var(--font-serif);
  font-size: 0.95rem;
  letter-spacing: 0.42em;
  /* 字距是加在每个字右侧的，末字之后那一份会让整行看起来偏左，补回去。 */
  text-indent: 0.42em;
  transition: color 0.25s ease;
}

.tao-enter:hover .tao-enter-label,
.tao-enter:focus-visible .tao-enter-label {
  color: var(--accent-ink);
}

/* 箭头落在引导语上方。 */
.tao-enter-arrow {
  display: block;
  width: 26px;
  color: var(--line-strong);
  transition:
    color 0.25s ease,
    transform 0.25s ease;
}

.tao-enter-arrow svg {
  display: block;
  width: 100%;
  height: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.tao-enter:hover .tao-enter-arrow,
.tao-enter:focus-visible .tao-enter-arrow {
  color: var(--accent-ink);
  transform: translateY(3px);
}

/* 一下一下地点，像在招手。指到它上面就停——已经不需要再提示了。 */
@media (prefers-reduced-motion: no-preference) {
  .tao-enter-arrow {
    animation: enterBeckon 2.4s ease-in-out infinite;
  }

  .tao-enter:hover .tao-enter-arrow {
    animation: none;
  }
}

@keyframes enterBeckon {
  0%,
  62%,
  100% {
    transform: translateY(0);
  }

  28% {
    transform: translateY(5px);
  }
}

.tao {
  position: relative;
  background:
    radial-gradient(115% 62% at 50% 34%, rgba(200, 165, 106, 0.11), transparent 62%),
    var(--ink-bg);
  color: var(--ink-fg);
  /*
   * 必须是 clip 不能是 hidden：hidden 会让这一节变成滚动容器，里面 sticky 的舞台
   * 就改为相对它定位，钉屏直接失效。clip 同样挡住横向溢出（起手时放大的圆相），
   * 但不创建滚动容器。
   */
  overflow-x: clip;

  /* 编排进度，由脚本按滚动位置逐帧改写；没有脚本时就是收势那一帧。 */
  --enso: 1;
  --reveal: 1;
  --tail: 1;
  --n: 9999;
}

.tao.anim {
  --enso: 0;
  --reveal: 0;
  --tail: 0;
  --n: 0;
}

.tao-stage {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: clamp(1.5rem, 4vh, 2.4rem);
  width: 100%;
  max-width: calc(72rem + var(--gutter) * 2);
  min-height: 100vh;
  margin: 0 auto;
  /* 顶栏是 sticky 的，永远压在这一节上沿，上边距得把它让出来。 */
  padding: calc(clamp(56px, 9vh, 104px) + var(--header-h)) var(--gutter) clamp(56px, 9vh, 104px);
  text-align: center;
}

.tao-mark {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.tao-crest {
  position: relative;
  display: grid;
  place-items: center;
  /* 题名按圆径取字号，两者的比例才不会随断点走样。 */
  --crest: clamp(180px, 46vw, 244px);
  width: var(--crest);
  aspect-ratio: 1;
}

/* 圆相：从顶端起笔顺时针描一圈，收笔处留一道口子——圆相本就不闭合。 */
.tao-enso {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-96deg);
  overflow: visible;
}

/*
 * r=112 的周长约 703.7（用户单位，与渲染尺寸无关）。dasharray 取整到 704——
 * 实线与间隔等长且都盖满一整圈，所以圆是闭合的，起收笔处不留缺口；
 * 略微超出周长也是有意的，免得收尾差零点几个单位露出一道发丝缝。
 * dashoffset 从 704 收到 0 就是一笔描完，进度由 --enso 给。
 */
.tao-enso circle {
  fill: none;
  stroke: rgba(212, 180, 126, 0.34);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-dasharray: 704;
  stroke-dashoffset: calc(704 * (1 - var(--enso)));
}

.tao-name {
  position: relative;
  margin: 0;
  font-family: "Hero CJK", var(--font-serif);
  font-weight: 400;
  font-size: calc(var(--crest) * 0.3);
  line-height: 1;
  letter-spacing: 0.14em;
  /* 字距会在末字右侧多留一格，缩进同量补回来才是真居中。 */
  text-indent: 0.14em;
  color: #f7f0e3;
  /* 圆相描到一半时题名才浮出来。 */
  opacity: clamp(0, calc(var(--enso) * 2 - 0.55), 1);
}

.tao-latin {
  margin: 1.15rem 0 0;
  color: rgba(212, 180, 126, 0.82);
  font-size: clamp(0.7rem, 1.5vw, 0.82rem);
  font-weight: 500;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  text-transform: uppercase;
  opacity: var(--reveal);
}

/* 引线：从名号垂下来一道金丝，把视线带到偈子上。 */
.tao-rule {
  width: 1px;
  height: clamp(36px, 6vh, 60px);
  margin: 1.5rem 0 0;
  background: linear-gradient(
    180deg,
    rgba(212, 180, 126, 0),
    rgba(212, 180, 126, 0.55),
    rgba(212, 180, 126, 0)
  );
  transform: scaleY(var(--reveal));
  transform-origin: top;
}

/*
 * 竖排偈子。
 *
 * writing-mode: vertical-rl 之后每个 .line 就是一列，从右往左排——与古籍的读序一致，
 * DOM 里照常按第一句到第三句写即可。此时 line-height 管的是列间距，height 管的是列长，
 * 所以给 max-content 让它按最长那句自己撑开，nowrap 兜住不让某句折成两列。
 */
.tao-verse {
  writing-mode: vertical-rl;
  height: max-content;
  margin: 0;
  /*
   * 竖排下 text-align 管的是列内的纵向对齐，继承来的 center 会让短的那列吊在半空。
   * 各列一律从顶端起写，才是古籍的样子。
   */
  text-align: start;
  font-family: var(--font-serif);
  font-size: clamp(1.1rem, 2.4vw, 1.8rem);
  line-height: 2.9;
  letter-spacing: 0.14em;
  color: #efe4d2;
}

.tao-verse .line {
  display: block;
  white-space: nowrap;
}

/*
 * 中文版把落款竖排收在偈子左侧——竖排卷轴的题款本就写在正文之后，
 * 而 vertical-rl 里「之后」就是更左的那一列。row-reverse 让 DOM 顺序保持
 * 「正文在前、题款在后」（读屏与复制都按这个序），视觉上题款落到左边。
 */
.tao-scroll {
  display: flex;
  flex-direction: row-reverse;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(0.9rem, 2.5vw, 2rem);
}

.tao-source-aside {
  writing-mode: vertical-rl;
  height: max-content;
  /*
   * 与偈子的末字齐脚。题款比正文短得多，齐头的话下面会空出一大截，
   * 整列像是吊在半空；卷轴上的落款本来也是沉在末尾的。
   */
  align-self: flex-end;
  margin: 0;
  font-size: clamp(0.72rem, 1.6vh, 0.92rem);
  letter-spacing: 0.2em;
  white-space: nowrap;
  /* 落款跟着偈子的收尾一起浮出来，不自成一拍。 */
  opacity: var(--tail);
}

/*
 * 逐字渗墨。--n 是「已写到第几个字」，--i 是这个字的序号；两者相减钳到 0..1
 * 就是它该显到几分。除以 3 让每个字的渐显跨三格，笔画像是漫上来的，不是一格一格跳。
 * 全部由 CSS 现算，滚动时脚本只改 --n 一个值，不碰 DOM。
 */
.tao-verse .ch {
  --shown: clamp(0, calc((var(--n) - var(--i)) / 3), 1);
  opacity: var(--shown);
  filter: blur(calc((1 - var(--shown)) * 3px));
}

.tao-colophon {
  opacity: var(--tail);
}

.tao-gloss {
  max-width: 30rem;
  margin: 0 auto;
  color: rgba(240, 230, 214, 0.5);
  font-size: 0.9rem;
  line-height: 1.85;
}

/* 落款 */
.tao-source {
  margin: 1.1rem 0 0;
  color: rgba(212, 180, 126, 0.72);
  font-family: var(--font-serif);
  font-size: 0.9rem;
  letter-spacing: 0.08em;
}

.tao-act {
  margin: 1.8rem 0 0;
}

.tao-cta {
  display: inline-block;
  padding: 0.85rem 2.4rem;
  border: 1px solid rgba(212, 180, 126, 0.42);
  /* 方角比胶囊更像一方牌记，与这一节的气口一致；全站的圆角按钮留在别处。 */
  border-radius: 2px;
  background: transparent;
  color: #e8d6b0;
  font-family: inherit;
  font-size: 0.95rem;
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  text-decoration: none;
  cursor: pointer;
  transition:
    background 0.32s ease,
    border-color 0.32s ease,
    color 0.32s ease;
}

.tao-cta:hover {
  border-color: rgba(212, 180, 126, 0.8);
  background: rgba(212, 180, 126, 0.1);
  color: #f8efdb;
  text-decoration: none;
}

/*
 * 宽屏：题名与落款分列左侧上下，竖排偈子立在右侧，中间大片留白——
 * 这是卷轴的章法，正文在右，题款在后（也就是左）。
 *
 * 徽记的位移由脚本写 transform，所以这里只管收势那一帧的位置；起手的居中大圆
 * 是从这个位置反推出来的，改这里的排布不用回去改脚本。
 */
@media (min-width: 900px) {
  .tao-stage {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
      "mark  verse"
      ".     verse"
      "colo  verse";
    align-content: stretch;
    justify-items: start;
    gap: 0 clamp(2rem, 7vw, 6rem);
    padding-right: clamp(var(--gutter), 9vw, 148px);
    text-align: left;
  }

  .tao-mark {
    grid-area: mark;
    align-items: flex-start;
  }

  .tao-crest {
    --crest: clamp(104px, 11vw, 140px);
  }

  /*
   * 竖排要立得住：列长跟着视口高走（vh 而不是 vw），一屏之内偈子才占得满，
   * 不至于在大片墨色里缩成一小簇。
   */
  /* 竖排那一栏整体占 verse 格：中文版里它装着偈子与题款两列，英文版只有偈子。 */
  .tao-scroll {
    grid-area: verse;
    align-self: center;
  }

  .tao-verse {
    align-self: center;
    font-size: clamp(1.4rem, 5vh, 2.75rem);
    line-height: 2.5;
  }

  .tao-colophon {
    grid-area: colo;
    align-self: end;
    max-width: 26rem;
  }

  .tao-gloss {
    margin: 0;
  }

  /* 左栏那道金丝拉长成一条界行，把题名与落款之间的空档串起来。 */
  .tao-rule {
    height: clamp(64px, 20vh, 200px);
  }
}

/* 脚本已按减动效偏好整段跳过，这里再兜一层，免得将来改脚本时漏掉。 */
@media (prefers-reduced-motion: reduce) {
  .tao,
  .tao.anim {
    --enso: 1;
    --reveal: 1;
    --tail: 1;
    --n: 9999;
  }
}

/* ── 入口两卡（人生解读 / 趋势占测） ───────────────────── */

/*
 * 中道之后回到米白。这一节是全站唯一的产品入口，所以只放两张卡，别的什么都不放。
 */
.entries {
  text-align: center;
}

.entries-head {
  max-width: 40rem;
  margin: 0 auto clamp(1.8rem, 5vh, 3rem);
}

.entries-head h2 {
  margin: 0 0 0.7rem;
  font-size: clamp(1.4rem, 3vw, 2rem);
  line-height: 1.35;
  text-wrap: balance;
}

.entries-head p {
  margin: 0;
  color: var(--muted);
  font-size: clamp(0.95rem, 1.6vw, 1.05rem);
}

/*
 * 两栏摊开，中间一道竖线分界。
 *
 * 竖线用容器的伪元素画在 50% 处，而不是给右栏加 border-left——后者会贴在栏的左沿，
 * 也就是间隙的右边，不在正中。
 */
.entry-cols {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 9vw, 8rem);
  /* 比正文栏宽：这一节要摊到接近版心两侧，画才立得住。 */
  max-width: 88rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
  text-align: left;
}

.entry-cols::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--line);
}

.entry-cols li {
  margin: 0;
}

/* 不是卡片：没有底色、没有描边，画与字直接落在纸面上。 */
.entry {
  display: block;
  color: var(--ink);
  text-decoration: none;
}

.entry:hover {
  text-decoration: none;
}

/*
 * 切图自带透明，落在米色上就是纸上的一幅画，不垫底色。
 *
 * 画框与正文同宽同心（都是 26rem 居中），画在里面 cover 填满。两张横图的比例并不一致
 * （1.38 与 1.91），cover 会各裁掉一点：窄的那张削去上下一线，宽的那张削去左右一截。
 * 这样两栏的画与字左右齐平、两张画彼此等高，下面的标题也就齐平。
 * 用 contain 的话宽度会各随各的比例，画比正文宽出一截，看着就散了。
 */
.entry-art {
  display: block;
  width: 100%;
  max-width: 26rem;
  height: clamp(170px, 24vw, 290px);
  margin: 0 auto clamp(1rem, 3vh, 1.8rem);
  object-fit: cover;
  /* 画是插图，别在触屏上被长按当成可保存的图片。 */
  pointer-events: none;
  user-select: none;
}

/* 贴右摆：多出来的宽度从左边裁，把焦点留在框内（见 pages.mjs 的 ENTRY_ART.anchor）。 */
.entry-art-right {
  object-position: right center;
}

/* 图居中、字左齐；文字块限宽后整体居中，两者的重心才对得上。 */
.entry-body {
  display: block;
  max-width: 26rem;
  margin: 0 auto;
}

.entry .t {
  display: block;
  font-family: var(--font-serif);
  font-size: clamp(1.15rem, 2.2vw, 1.45rem);
  font-weight: 700;
}

/* 题前一点朱，是这一节唯一的颜色。 */
.entry .t::before {
  content: "";
  display: inline-block;
  width: 0.4em;
  height: 0.4em;
  margin-right: 0.55em;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.1em;
}

.entry:hover .t {
  color: var(--accent-ink);
}

.entry .d {
  display: block;
  margin-top: 0.4rem;
  color: var(--muted);
  font-size: 1rem;
}

.entry-lines {
  display: block;
  margin-top: 1.1rem;
}

/* 一句一行，句子自己该换行就换行。 */
.entry-lines span {
  display: block;
  margin-top: 0.45rem;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.85;
}

@media (max-width: 767px) {
  /* 竖排下中缝改成横线：两栏高度不一，伪元素定位不准，交给相邻兄弟的上边框。 */
  .entry-cols {
    grid-template-columns: 1fr;
    gap: 2.4rem;
  }

  .entry-cols::before {
    display: none;
  }

  .entry-cols li + li {
    padding-top: 2.4rem;
    border-top: 1px solid var(--line);
  }
}

/*
 * 入场，全站共用一套。
 *
 * 带 data-reveal 的元素是一个入场单元，脚本给它挂 .anim（内部 .reveal 先藏起来），
 * 滚到跟前挂 .in 放行；每个元素差多少由生成时算好的 --d 决定（见 pages.mjs）。
 * .anim 由脚本挂，所以没有 JS 时下面这些「先藏起来」的规则一条都不生效，页面是静态的。
 */
.anim .reveal {
  opacity: 0;
}

.anim.in .reveal {
  animation: entryRise 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) var(--d, 0ms) forwards;
}

/* 画不走位移，改成从虚到实收拢一点——像墨落在纸上洇开又收住。 */
.anim.in .entry-art.reveal,
.anim.in .row-art.reveal,
.anim.in .master-portrait.reveal {
  animation: entryArtIn 1.15s cubic-bezier(0.22, 0.61, 0.36, 1) var(--d, 0ms) forwards;
}

.entries.anim .entry-cols::before {
  transform: scaleY(0);
  transform-origin: top;
}

.entries.anim.in .entry-cols::before {
  animation: entryRule 1s cubic-bezier(0.22, 0.61, 0.36, 1) 0.18s forwards;
}

@keyframes entryRise {
  from {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(3px);
  }

  to {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

@keyframes entryArtIn {
  from {
    opacity: 0;
    transform: scale(1.035);
    filter: blur(7px);
  }

  to {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

@keyframes entryRule {
  to {
    transform: scaleY(1);
  }
}

/* 脚本已按减动效偏好整段跳过，这里再兜一层，免得将来改脚本时漏掉。 */
@media (prefers-reduced-motion: reduce) {
  .anim .reveal {
    opacity: 1;
    animation: none;
  }

  .entries.anim .entry-cols::before {
    transform: none;
    animation: none;
  }
}

/* ── 提问条 ───────────────────────────────────────────── */

/*
 * 穿插在各节之间的一条：左边一问，右边一个输入框直达问 AI。
 * 整页读到底才见到入口对多数人来说太晚，这一条让人随时能开口。
 */
.askband {
  padding: clamp(28px, 5vh, 48px) 0;
}

.askband-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  max-width: var(--maxw-text);
  margin: 0 auto;
  padding: clamp(1.1rem, 3vw, 1.9rem) clamp(1.2rem, 3.5vw, 2.4rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.askband-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: clamp(1.05rem, 2.4vw, 1.5rem);
  font-weight: 700;
}

.askband-field {
  display: flex;
  align-items: center;
  flex: 1 1 20rem;
  /*
   * 弹性子项的最小宽度默认是 auto，也就是「不小于自身内容」。里面的按钮是 nowrap 的，
   * 窄屏上这一条就把整个输入框顶得比视口还宽，整页跟着能横向拖。显式归零才允许它收缩。
   */
  min-width: 0;
  max-width: 30rem;
  padding: 0.3rem 0.3rem 0.3rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--bg);
}

.askband-field:focus-within {
  border-color: var(--accent);
}

.askband-field input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 0.95rem;
}

.askband-field input:focus {
  outline: none;
}

.askband-field button {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex: none;
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s ease;
}

.askband-field button:hover {
  background: var(--accent-ink);
}

/*
 * 窄屏：一问一框并排放不下，改成上下两行，输入框独占一行。
 * 按钮标签在有些语种里很长（英文的「Ask your first question」），所以这里放开 nowrap，
 * 宁可折成两行也不要把整条顶宽。
 */
@media (max-width: 560px) {
  .askband-box {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
  }

  .askband-field {
    flex-basis: auto;
    max-width: none;
  }

  .askband-field button {
    white-space: normal;
  }
}

/* ── 康立波老师 ───────────────────────────────────────── */

/*
 * 三段往下排：其人（像左字右）→ 玄天模式 → 九门术数。
 * 头一段左右分栏，后两段居中成块，层次才拉得开。
 */
.master-who {
  display: grid;
  gap: clamp(1.4rem, 5vw, 3.5rem);
  align-items: center;
  /* 两列都按内容定宽再整组居中，不铺满整行——否则右边会空出一大块。 */
  justify-content: center;
  justify-items: center;
  max-width: var(--maxw-text);
  margin: 0 auto clamp(2.5rem, 7vh, 4.5rem);
  text-align: center;
}

@media (min-width: 760px) {
  .master-who {
    grid-template-columns: auto auto;
  }

  /* 名字与头衔右对齐，右缘取齐；画像在左，两边各自成边。 */
  .master-intro {
    text-align: right;
  }

  .master-intro .master-since {
    margin-right: 0;
  }
}

.master-intro {
  max-width: 34rem;
}

/* 线描画像，与整站的纸面是一路的；不用真人照片。 */
.master-portrait {
  display: block;
  width: clamp(150px, 20vw, 220px);
  height: auto;
  pointer-events: none;
  user-select: none;
}

.master-name {
  margin: 0;
  font-size: clamp(1.5rem, 3.2vw, 2.1rem);
}

.master-titles {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.9;
}

.master-since {
  max-width: 30rem;
  margin: 1rem auto 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.8;
  /* 两行之间匀一匀，免得末行只剩一个字。 */
  text-wrap: balance;
}

/*
 * 结尾那句同行：套 Hero 的书法体写成大字，逐字浮现。
 *
 * 字是构建期就拆好的（见 pages.mjs 的 typeChars），所以没有 JS 时它只是一行正常的大字；
 * .anim 由脚本挂、.in 由 IntersectionObserver 挂，下面「先藏起来」那条才会生效。
 */
.master-oath {
  /* 放得下中文那句的一整行；英文长句自然折行，靠 balance 匀开。 */
  max-width: 52rem;
  margin: clamp(2.2rem, 6vh, 3.6rem) auto 0;
  font-family: var(--font-display);
  /* 同 .hero h1：中间那一档要够大，否则手机上这句大字会掉到下限，跟正文分不出来。 */
  font-size: clamp(1.5rem, 7vw, 2.9rem);
  line-height: 1.7;
  text-align: center;
  text-wrap: balance;
}

.master-oath .w {
  white-space: nowrap;
}

.master-oath.anim .ch {
  opacity: 0;
}

.master-oath.anim.in .ch {
  animation: tokenFade 0.42s ease-out var(--d, 0ms) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .master-oath.anim .ch {
    opacity: 1;
    animation: none;
  }
}

/*
 * 玄天这段：标题 → 九门格 → 解释。
 * 九门正是玄天可调的那些盘，所以标题统领它们，解释放在格子之后收口。
 */
.xuantian {
  /* 与上面老师那一段拉开一档，两件事才不粘在一起。 */
  margin-top: clamp(3rem, 9vh, 5.5rem);
}

.xuantian-head {
  margin: 0 0 clamp(1.4rem, 3.5vh, 2.2rem);
  font-size: clamp(1.35rem, 2.8vw, 1.85rem);
  line-height: 1.4;
  text-align: center;
}

/* 与上面的九宫格同宽，左右缘对齐。 */
.xuantian-lede {
  max-width: var(--maxw-text);
  margin: clamp(1.6rem, 4vh, 2.4rem) auto 0;
  color: var(--muted);
  font-size: 0.98rem;
  line-height: 1.95;
  text-align: center;
  text-wrap: pretty;
}

/* ── 九门术数：1 + 2×4 ────────────────────────────────── */


/*
 * 卡片规格照搬应用（见 h5/components/GuoxueCard.module.css）：竖卡 175×205、整卡底图、
 * 文字压在画面底部居中、10px 圆角、#cab49f 细线。切图 525×615 与卡片同比例，所以铺满
 * 既不拉伸也不裁切。
 *
 * 宽度取正文栏，与下面「立波择吉」那三行左右缘对齐，整页的版心才是一条线。
 * 卡片随之比应用里的 175px 大一点，但切图是 525×615、比版位还大，放大不会糊。
 */
.shushu-grid {
  --scard-gap: 0.7rem;
  display: grid;
  gap: var(--scard-gap);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: var(--maxw-text);
  margin: 0 auto;
}

/* 六列两行：八字占左边两列两行，其余八门填右边四列。 */
@media (min-width: 780px) {
  .shushu-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .scard-lead {
    grid-column: span 2;
    grid-row: span 2;
    /* 跨两格两行时高度由行高决定，不再自带比例，否则会与行高打架。 */
    aspect-ratio: auto;
  }
}

.scard {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  /* 175:205 —— 应用里竖卡的尺寸。 */
  aspect-ratio: 175 / 205;
  padding: 0 6px 8px;
  border: 1px solid #cab49f;
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
  overflow: hidden;
  text-align: center;
  text-decoration: none;
  transition:
    border-color 0.25s ease,
    transform 0.25s ease;
}

.scard:hover {
  border-color: var(--accent);
  text-decoration: none;
}

/* 底图铺满整卡，文字直接叠在画面上——与应用一致。 */
.scard-art {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  user-select: none;
  transition: transform 0.35s ease;
}

.scard:hover .scard-art {
  transform: scale(1.04);
}

.scard-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  max-width: 164px;
}

.scard .t {
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.3;
}

.scard .d {
  color: #8f6f4c;
  font-size: 0.75rem;
  line-height: 1.35;
}

/* 八字是主位，卡片大一倍，字也跟着放一档。 */
.scard-lead .scard-copy {
  max-width: 22rem;
}

.scard-lead .t {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
}

.scard-lead .d {
  font-size: 0.85rem;
}

@media (min-width: 780px) {
  .scard-lead {
    padding-bottom: 1.4rem;
  }

  /*
   * 风水那张是横版列表卡的切图（616×366），放进竖格若按整卡 cover，等于只取中间三成再放大，
   * 罗盘会撑满整格；若按 contain 整幅缩进去，又比另外八张小一截。
   * 折中：只占上面六成半的高度，在这个盒子里 cover——左右轻裁一点，罗盘的尺度就和其余八门齐了。
   */
  .scard:last-child .scard-art {
    inset: 5% 0 auto;
    height: 70%;
    object-position: center;
  }
}

/*
 * 两列版的末位（风水）横过来占满一行。
 *
 * 九张卡两列排会多出一张落单，而风水那张切图本就是横版列表卡用的（616×366），应用里
 * 也正是把它单独做成横卡（见 GuoxueCard.module.css 的 .list.fengshui）。这里照搬：
 * 画按卡高贴右、不裁，左边留给文字。
 */
@media (max-width: 779px) {
  .scard:last-child {
    grid-column: span 2;
    aspect-ratio: 362 / 122;
    align-items: flex-start;
    justify-content: center;
    padding: 0 0 0 15px;
    text-align: start;
  }

  .scard:last-child .scard-art {
    object-fit: contain;
    object-position: right center;
  }

  .scard:last-child .scard-copy {
    max-width: 68%;
  }
}

/* ── 交错三行 ─────────────────────────────────────────── */

.row-list {
  display: grid;
  gap: clamp(3rem, 9vh, 6rem);
  max-width: var(--maxw-text);
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.row {
  display: grid;
  gap: clamp(1.4rem, 4vw, 3.5rem);
  align-items: center;
  margin: 0;
}

@media (min-width: 860px) {
  .row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /*
   * 左右交错：DOM 恒为「图在前、字在后」，偶数行靠列序翻转而不是换一套结构——
   * 读屏与窄屏堆叠的顺序才始终一致。
   */
  .row:nth-child(even) .row-art {
    grid-column: 2;
    grid-row: 1;
  }

  .row:nth-child(even) .row-copy {
    grid-column: 1;
    grid-row: 1;
  }
}

/*
 * 三张画裁去透明边之后比例各不相同（1.60 / 1.72 / 0.89），所以按等高摆放、宽度各随各的，
 * 三行的分量才一致；否则那张竖的会比另外两张矮一大截。
 */
.row-art {
  display: block;
  width: 100%;
  max-width: 26rem;
  height: clamp(190px, 26vw, 300px);
  margin: 0 auto;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

.row-copy h3 {
  margin: 0;
  font-size: clamp(1.25rem, 2.6vw, 1.6rem);
}

.row-sub {
  margin: 0.35rem 0 0;
  color: var(--accent-ink);
  font-size: 0.95rem;
}

.row-lines {
  margin-top: 1rem;
}

.row-lines span {
  display: block;
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.9;
}

.row-act {
  margin: 1.4rem 0 0;
}

/* ── 用户评价 ─────────────────────────────────────────── */

.voices-head {
  margin: 0 0 clamp(1.6rem, 4vh, 2.4rem);
  font-size: clamp(1.35rem, 3vw, 1.9rem);
  text-align: center;
}

/*
 * 跑马灯：两份同样的卡片并排，一起左移一整份的宽度，走完正好接上，看不出断点。
 * 轨道要出血到版心之外，两端的卡片半露在屏幕边上，才有「还在往下滚」的意思。
 */
.voices-rail {
  display: flex;
  overflow: hidden;
  /* 两端各淡出一截，卡片是滚进滚出而不是被切断。 */
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.voices-track {
  --voice-gap: clamp(1rem, 2vw, 1.6rem);
  display: flex;
  flex: none;
  gap: var(--voice-gap);
  margin: 0;
  padding: 0.6rem var(--voice-gap) 0.6rem 0;
  list-style: none;
  animation: voicesRoll 72s linear infinite;
}

@keyframes voicesRoll {
  to {
    transform: translateX(-100%);
  }
}

/* 停下来才读得完：鼠标停住、或键盘走到里面的链接时都暂停。 */
.voices-rail:hover .voices-track,
.voices-rail:focus-within .voices-track {
  animation-play-state: paused;
}

.voice {
  display: flex;
  flex-direction: column;
  flex: none;
  width: clamp(17rem, 26vw, 22rem);
  margin: 0;
  padding: 1.6rem 1.7rem 1.5rem;
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(60, 42, 24, 0.05), 0 8px 24px rgba(60, 42, 24, 0.06);
}

.voice-mark {
  color: var(--accent);
  font-family: var(--font-serif);
  font-size: 2rem;
  line-height: 1;
}

.voice blockquote {
  flex: 1 1 auto;
  margin: 0.7rem 0 0;
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.95;
}

.voice-who {
  margin: 1.4rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.85rem;
}

.voice-who .n {
  color: var(--ink);
}

.voice-who .m::before {
  content: " · ";
}

/*
 * 要求减少动态效果时不自动滚，退成一条可以自己横向拖的卡片带——内容一条都不少。
 * 遮罩也去掉，否则拖到两端的卡片会被淡成半透明。
 */
@media (prefers-reduced-motion: reduce) {
  .voices-rail {
    overflow-x: auto;
    mask-image: none;
  }

  .voices-track {
    animation: none;
  }

  /* 第二份是给无缝滚动用的复制品，不滚了就没有它的位置。 */
  .voices-track[aria-hidden='true'] {
    display: none;
  }
}

/* ── 结尾 ─────────────────────────────────────────────── */

/* 页尾用的还是提问条那个盒子，上面先落一句中道的话安顿一下。 */
.closing {
  text-align: center;
}

.closing-lede {
  max-width: 34rem;
  margin: 0 auto clamp(1.6rem, 4vh, 2.4rem);
  color: var(--muted);
  font-size: clamp(0.98rem, 1.8vw, 1.08rem);
  line-height: 1.95;
  text-wrap: pretty;
}

/* ── 排盘工具页：页顶九门跑马灯 ─────────────────────────── */

/*
 * 九张竖卡从右往左滚。做法与「听听他们怎么说」同一套：两份同样的卡片并排，一起向左平移
 * 一整份的宽度，走完正好接上，看不出断点（详见 .voices-rail 那段说明）。轨道出血到版心
 * 之外、两端各淡出一截，卡片是滚进滚出而不是被切断。
 *
 * 卡片刻意不是链接：它一直在动，点移动的目标本身就难受；这一节要说的是「有哪九门」，
 * 真要进去，下面那个「立即尝试」是唯一且明确的入口。
 */
.crail {
  padding: 0 0 clamp(2.2rem, 6vh, 3.4rem);
}

.crail-rail {
  display: flex;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}

.crail-track {
  --crail-gap: clamp(0.7rem, 1.4vw, 1.1rem);
  display: flex;
  flex: none;
  gap: var(--crail-gap);
  margin: 0;
  padding: 0.4rem var(--crail-gap) 0.4rem 0;
  list-style: none;
  animation: crailRoll 56s linear infinite;
}

@keyframes crailRoll {
  to {
    transform: translateX(-100%);
  }
}

/* 停下来才看得清哪张是哪张。 */
.crail-rail:hover .crail-track {
  animation-play-state: paused;
}

/* 与首页九宫格那九张同一个规格：175:205，是应用里竖卡的尺寸。 */
.crail-card {
  position: relative;
  display: flex;
  flex: none;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  width: clamp(138px, 15vw, 184px);
  aspect-ratio: 175 / 205;
  margin: 0;
  padding: 0 6px 8px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--bg);
  overflow: hidden;
  text-align: center;
}

.crail-art {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  user-select: none;
}

/*
 * 风水那张是横版列表卡的切图（616×366）。塞进竖格按整卡 cover，等于只取中间三成再放大，
 * 罗盘会撑破格子；只让它占上面约七成高、在那个盒子里 cover，尺度就和另外八门齐了。
 * 与首页九宫格里 .scard:last-child 同一处理。
 */
.crail-card:last-child .crail-art {
  inset: 6% 0 auto;
  height: 68%;
}

.crail-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
}

.crail-copy .t {
  font-family: var(--font-serif);
  font-size: clamp(1rem, 1.5vw, 1.24rem);
  font-weight: 600;
  line-height: 1.3;
}

.crail-copy .d {
  color: var(--muted);
  font-size: 0.7rem;
  line-height: 1.35;
}

.crail-act {
  margin-top: clamp(1.5rem, 4vh, 2.2rem);
  text-align: center;
}

/*
 * 要求减少动态效果时不自动滚，退成一条可以自己横向拖的卡片带——内容一条都不少。
 * 遮罩也去掉，否则拖到两端的卡片会被淡成半透明。
 */
@media (prefers-reduced-motion: reduce) {
  .crail-rail {
    overflow-x: auto;
    mask-image: none;
  }

  .crail-track {
    animation: none;
  }

  /* 第二份是给无缝滚动用的复制品，不滚了就没有它的位置。 */
  .crail-track[aria-hidden='true'] {
    display: none;
  }
}

/* ── 排盘工具页：九门交错长节 ───────────────────────────── */

.csys-head {
  max-width: 46rem;
  margin: 0 auto clamp(2rem, 6vh, 3.2rem);
  text-align: center;
}

.csys-list {
  display: grid;
  gap: clamp(3.5rem, 10vh, 6.5rem);
  max-width: 84rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.csys {
  display: grid;
  gap: clamp(1.6rem, 4vw, 3.4rem);
  align-items: center;
  margin: 0;
  /* 顶栏是 sticky，从跑马灯或外链锚点跳过来时要给它让出高度。 */
  scroll-margin-top: calc(var(--header-h) + 16px);
}

@media (min-width: 900px) {
  /* 盘面那栏窄一点：盘本来就有自己的宽度上限，两栏均分会让它孤零零浮在半栏正中。 */
  .csys {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  }

  /*
   * 左右交错：DOM 恒为「盘在前、字在后」，偶数节靠列序翻转而不是换一套结构——
   * 读屏与窄屏堆叠的顺序才始终一致。与首页交错三行同一做法。
   */
  .csys:nth-child(even) .csys-chart {
    grid-column: 2;
    grid-row: 1;
  }

  .csys:nth-child(even) .csys-copy {
    grid-column: 1;
    grid-row: 1;
  }
}

.csys-chart {
  display: flex;
  justify-content: center;
  min-width: 0;
}

/*
 * 排盘卡片的位置。
 *
 * 这里摆的是问 AI 对话里那张卡（不是整页排盘），所以不封高度也不裁切——那张卡在应用里
 * 本来就是随内容长高的一块，硬压一个框反而不像了。九门的卡高矮略有出入（八字多一行大运），
 * 靠 .csys 的 align-items: center 各自居中，看下来仍是齐的。
 *
 * 卡自带发丝线，底色与页面纸面同色，所以它就这么落在版面上——与落在对话流里是一个样子。
 */
.csys-frame {
  position: relative;
  width: 100%;
  max-width: 27rem;
}

/*
 * 入场时卡片不做位移，改成从虚到实收拢一点——与首页那几张画同一条规则（见 entryArtIn）。
 * 一整块界面上下弹一下太重，何况它旁边的文字正在逐行浮起，两种动作叠在一起会打架。
 */
.anim.in .csys-frame.reveal {
  animation: entryArtIn 1.15s cubic-bezier(0.22, 0.61, 0.36, 1) var(--d, 0ms) forwards;
}

/*
 * 文字那一栏。
 *
 * overflow 收住是为了底纹：那张图贴着栏的外沿、还要探出去一点，不收的话它会把整页撑宽，
 * 在窄屏上多出一条横向滚动条。
 */
.csys-copy {
  position: relative;
  min-width: 0;
  overflow: hidden;
}

/*
 * 文字背后压着的那张门类配图——就是页顶跑马灯上的同一张，放大、调淡、贴在版心外侧。
 *
 * 它不承载信息（alt 为空、aria-hidden），作用是让每一节有自己的气质：九节结构完全相同，
 * 只靠文字区分会读成一张长表格。靠内的一侧用遮罩渐隐，免得图的硬边横穿正文。
 */
.csys-ghost {
  position: absolute;
  z-index: 0;
  top: 50%;
  right: -1.5rem;
  width: auto;
  height: min(115%, 25rem);
  transform: translateY(-50%);
  opacity: 0.085;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  mask-image: linear-gradient(90deg, transparent, #000 55%);
}

/* 交错到左边那几节，底纹跟着挪到左外沿，始终背对盘面那一栏。 */
.csys:nth-child(even) .csys-ghost {
  right: auto;
  left: -1.5rem;
  mask-image: linear-gradient(270deg, transparent, #000 55%);
}

.csys-text {
  position: relative;
  z-index: 1;
  max-width: 34rem;
}

.csys-name {
  margin: 0;
  font-family: var(--font-serif);
  font-size: clamp(1.3rem, 2.8vw, 1.75rem);
  line-height: 1.3;
  color: var(--accent-ink);
}

/* 罗马字副名跟在门名后面，小一档淡一档——像书口上的拉丁转写，不与门名争。 */
.csys-sub {
  margin-left: 0.7em;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 0.68em;
  font-style: italic;
  font-weight: 400;
  letter-spacing: 0.02em;
}

.csys-lines {
  margin-top: 1rem;
}

.csys-lines p {
  margin: 0.7rem 0 0;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.95;
}

.csys-acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem 1.4rem;
  margin: 1.6rem 0 0;
}

/*
 * 「排盘示例」不做成按钮。
 *
 * 它不通向任何地方，只是把旁边那张盘放大看清楚；做成按钮就要和「立即排盘」并排争夺
 * 同等的分量，而这两件事根本不是一个级别。所以是一行带下划线的字。
 * 用 <button> 而不是 <span>：键盘要能走到它，读屏也该知道这是一个可以按的东西。
 */
.csys-example {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 0.32em;
  cursor: pointer;
}

.csys-example:hover {
  color: var(--accent-ink);
  text-decoration-color: currentColor;
}

/* 门类介绍页还没做，所以这一项眼下只是一行字。有了地址就换成 <a>，样式照旧。 */
.csys-wiki {
  color: var(--muted);
  font-size: 0.92rem;
  cursor: default;
}

/* ── 排盘工具页：排盘示例弹窗 ───────────────────────────── */

/*
 * 用原生 <dialog>：焦点困住、Esc 关闭、背景惰性化都是浏览器给的，自己用 div 搭一遍很难做全。
 *
 * 九门的整页排盘都摆在这一个弹窗里，开哪一门显哪一门（见 chartingScript）。页比弹窗高就在
 * 框内滚——这一屏的意思就是「真实排盘页面长什么样」，截断了等于没给。
 */
.cdlg {
  width: min(94vw, 31rem);
  max-height: min(90vh, 58rem);
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
  overflow: hidden;
}

/*
 * 入场动画。触发是「鼠标放上去」，没有点击那一下的确认感，全靠这 260ms 交代
 * 「有东西从这里弹出来了」——所以它不是装饰，是这个交互能不能被看懂的关键。
 */
.cdlg[open] {
  animation: cdlgIn 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.cdlg::backdrop {
  background: rgba(23, 18, 13, 0.55);
  backdrop-filter: blur(3px);
}

.cdlg[open]::backdrop {
  animation: cdlgFade 260ms ease;
}

@keyframes cdlgIn {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.985);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes cdlgFade {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cdlg[open],
  .cdlg[open]::backdrop {
    animation: none;
  }
}

.cdlg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.95rem 1.1rem 0.8rem;
  border-bottom: 1px solid var(--line);
}

.cdlg-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1.05rem;
  font-weight: 700;
}

.cdlg-x {
  flex: none;
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}

.cdlg-x:hover {
  background: var(--tint);
  color: var(--ink);
}

/*
 * 排盘页在这里是完整的一页，高了就在框内滚。滚动容器是这一层而不是页面本身：
 * 盘面整块 pointer-events:none（它是一幅画，不该被点也不该被选中），自己接不到滚轮。
 */
.cdlg-stage {
  max-height: calc(90vh - 8rem);
  padding: 1.1rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg);
}

/* 弹窗里那一页不封高：它要能一路滚到底，这才是「完整的排盘页面」。 */
.cdlg-page > .ppv {
  height: auto;
}

.cdlg-note {
  margin: 0;
  padding: 0.75rem 1.1rem 0.95rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.6;
}

/* @pages-only:end */