/*
 * 垂光台 · 首页
 * 世界：垂光 The Descending Light（见 tokens.css 顶部 / DESIGN.md）
 *
 * 背景做过三版（石墙 / 深空 / 铜版星图），三版都被否掉，
 * 三版错的是同一件事：**正文背后有东西**。
 * 这一版把那一层拿掉了，只留项目自己的名字 —— 一束从上面垂下来的光。
 *
 * 四条形式约束，破一条整页就散：
 *   1. 正文背后**什么都没有**。要加东西之前先问：它能不能长在组件上？
 *      能，就长在组件上；不能，多半是不该有。
 *   2. 地只有一种。整页一块纯色，不会因为你走到哪儿就换。
 *   3. 只有一个光源，而且它在标题上方就散尽 —— 读正文时背后是干净的。
 *   4. 朱砂只干两件事：标记已认领的槽，标记能按下去的东西。
 */

body.wallside {
  margin: 0;
  color: var(--lime-mid);
  font: var(--t-md)/1.85 var(--sans);
  background: var(--ground);
  overflow-x: clip;
  text-wrap: pretty;
  line-break: strict;
}

/*
 * ══ 层序 ══ 这一页只有一条，改任何一层之前先看这里：
 *
 *   0  body::before   地 + 垂光（两层渐变，全部是 CSS）
 *   1  body::after    颗粒（抖动，防止渐变出条带）
 *   2+ 正文           .stage 4 / .deck 5 / .panels 8 / .skip 20
 *
 * 前三版这里有一块画布（星野 / 刻线）和一层暗角。**都删了。**
 * 没有 canvas、没有 rAF、没有视差、没有 JS —— 背景现在是两条 CSS 规则，
 * 首屏第一帧就完整，也没有任何东西需要在标签页不可见时管理。
 */

/*
 * 地与垂光。
 *
 * 两层，就两层：
 *   1) 一束光，从顶上垂下来。整页唯一的光源，也是唯一一处非纯色。
 *      形状是**竖的**（74% 宽 × 96% 高）：横向铺开会变成"顶上一团泛光"，
 *      那是任何一个深色模板都有的东西；收窄之后它才读得出是**一束**，
 *      两侧和四角真的暗下去，页面才有方向。
 *      落点也是算过的：中心在视口外 -12%，到 45% 高度基本散尽 ——
 *      等读到正文，背后已经是干净的地。
 *   2) 地。上略透气、下沉一点。三档之间的差极小，
 *      **看不出是渐变**，只看得出页面有上下。
 */
body.wallside::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(74% 96% at 50% -12%, var(--shaft), transparent 64%),
    linear-gradient(180deg,
      var(--ground-hi) 0%, var(--ground) 46%, var(--ground-lo) 100%);
}

/*
 * 颗粒。
 *
 * 这一版唯一的纹理，而它存在的理由是**消除瑕疵，不是增加花样**：
 * 上面那束光是一大片暗部渐变，8 位色下必然出同心条带 ——
 * 抖动是唯一的解，也是这一行里"渐变做得好不好"最实际的分界线。
 *
 * feTurbulence 直接内联成 data URI：不请求、不缓存失效、不依赖任何构建步骤。
 * overlay 混合意味着中灰不改变底色，只在正负两侧各抖一点点，
 * 所以它抬不动整体亮度 —— 那条 Y ≤ 0.0395 不用为它让位。
 */
body.wallside::after {
  content: ""; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  padding: 10px 16px; background: var(--seal); color: var(--paper);
  font: var(--t-sm)/1 var(--sans); text-decoration: none;
}
.skip:focus { left: 8px; top: 8px; }

/* ═══════════════════════════════════════════ 板号索引 */

/*
 * 纪念墙按板编号，你沿着墙走，板号一块一块过去。
 * 所以它**横在页顶**，不竖在页侧 —— 这一条是这一版和上一版最直接的分野。
 * 它自己也是一面被走过的墙：走过的板留着刻痕，没到的板是空的。
 */
.panels {
  position: sticky; top: 0; z-index: 8;
  /*
   * 顶上这条索引压在**垂光最亮的那一段**上。
   * 上一版给它一层 0.88 的深色玻璃，等于把整页唯一的光源挡掉了 ——
   * 页面看起来又是一块死黑，而原因根本不在背景里。
   * 所以这里收到几乎透明：只在滚动时靠模糊把底下的内容化开，
   * 颜色只留一点点，够让索引的字站住就行。
   */
  background: linear-gradient(180deg,
    oklch(0.128 0.007 172 / 0.42) 0%,
    oklch(0.128 0.007 172 / 0.22) 62%,
    transparent 100%);
  backdrop-filter: blur(10px);
  padding: var(--s3) var(--s6) var(--s5);
}
.panel-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: 1px;
  max-width: 1280px; margin-inline: auto;
}
.panel-i { flex: 1 1 0; min-width: 0; }
.panel-i a {
  display: grid; gap: 3px;
  padding: var(--s2) var(--s3) var(--s3);
  text-decoration: none;
  /* 每一块板的上沿是一道刻线。当前板把它换成朱砂 —— 索引上唯一的颜色。
     底色去掉了：六块深色片压在光上，读起来是六个按钮，不是一条刻度 */
  border-top: 2px solid var(--rule);
  transition: background .16s, border-color .16s;
}
.panel-i b {
  font: 400 var(--t-2xs)/1 var(--mono); letter-spacing: var(--ls-wider);
  color: var(--lime-faint);
}
.panel-i span {
  font: 700 var(--t-xs)/1.3 var(--carve); letter-spacing: var(--ls-carve);
  color: var(--lime-low);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.panel-i.past a { border-top-color: var(--rule-strong); }
.panel-i.past span { color: var(--lime-mid); }
.panel-i.here a { border-top-color: var(--seal); }
.panel-i.here b { color: var(--seal-light); }
.panel-i.here span { color: var(--lime); }
.panel-i a:hover { background: var(--sunk-1); }
.panel-i a:hover span { color: var(--lime); }

@media (max-width: 900px) {
  .panels { padding: var(--s2) var(--s4) var(--s4); }
  /* 窄屏上板名排不下，但**板号必须留着** —— 索引没有号就不是索引了 */
  .panel-i span { display: none; }
  .panel-i a { padding: var(--s2) var(--s2) var(--s3); justify-items: center; }
}

/* ═══════════════════════════════════════════ 顶栏 */

.deck {
  position: relative; z-index: 5;
  display: flex; align-items: center; gap: var(--s6);
  padding: var(--s5) var(--s6) var(--s4);
  max-width: 1280px; margin-inline: auto;
}
.mark { display: flex; align-items: center; gap: 11px; text-decoration: none; }
.sigil {
  width: 30px; height: 30px; flex: none;
  fill: none; stroke: var(--lime); stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.mark-txt { display: grid; gap: 2px; }
.mark-txt b {
  font: 700 var(--t-lg)/1 var(--carve);
  letter-spacing: var(--ls-carve); color: var(--lime);
}
.mark-txt i {
  font: var(--t-3xs)/1 var(--mono); font-style: normal;
  letter-spacing: var(--ls-widest); color: var(--lime-faint);
}
/* 顶栏那组重复的章节链接删掉了（顶端的进度条已经列了同样六节），
   把人推到右边的活儿原来是那组链接的 margin-left:auto 干的，
   现在交给按钮自己 —— 少一个元素，右对齐不能跟着一起没了 */
.deck > .btn { margin-left: auto; }
@media (max-width: 560px) { .mark-txt i { display: none; } }

/* ═══════════════════════════════════════════ 段 */

/*
 * 段之间没有颜色变化 —— 墙不会因为你走到哪一块就换石头。
 * 分段靠**板缝**：一道凿进去的横缝，上沿暗、下沿被光擦亮。
 */
/* 4 —— 正文的第一层，必须高过暗角（3）。见文件顶部的层序表 */
.stage { position: relative; z-index: 4; }
.stage + .stage::before {
  content: ""; display: block; height: 1px;
  /* 一道被星光擦亮的横缝，两端淡出去 —— 一条通到底的实线会把天切成两半 */
  background: linear-gradient(90deg,
    transparent, var(--rule-strong) 22%, var(--rule-strong) 78%, transparent);
}
.stage-in {
  position: relative; z-index: 4;
  max-width: 1280px; margin: 0 auto;
  padding: var(--s8) var(--s6);
}
/* 首屏顶部不留大空 —— 板号索引和顶栏已经占掉两行，墙要挤进第一屏 */
.wall-stage .stage-in { padding-top: var(--s5); }
@media (max-width: 560px) { .stage-in { padding: var(--s7) var(--s4); } }

/* ═══════════════════════════════════════════ 墙面（首屏） */



/*
 * 整面墙。
 * 这是穹顶内壁**展开**之后的样子：四道肋环 12/20/26/30 拉直成四道横列。
 * 四道列不等长，而且不该等长 —— 槽是一个规格，列有多长由它装了多少个决定。
 */
/*
 * 墙面本身。
 *
 * 上一版这里什么都不用画：整页就是石头，槽直接凿在页面上。
 * 开顶之后不行了 —— 凹槽要靠光影读出来，而**光影需要一个面**。
 * 不给它一块板，88 个空槽就变成 88 个直接开在天上的黑方块：
 * 那不是凿进去的，那是挖穿了。
 *
 * 所以这里立一块板：从天上抬起来（落影在下），上沿被星光擦亮，
 * 板面比天亮一档但仍然是压暗的 —— 星在它后面，不在它上面。
 */
.wall-face {
  position: relative;
  padding: var(--s5) var(--s5) var(--s4);
  border-radius: var(--r-slab);
  background: var(--sunk-2);
  box-shadow:
    inset 0 1px 0 var(--edge-lit),
    inset 0 -1px 0 var(--edge-dim),
    var(--slab);
}
@media (max-width: 560px) { .wall-face { padding: var(--s4) var(--s3); } }
.courses { display: grid; gap: var(--s5); }
.course { display: grid; gap: var(--s2); }
.course-d {
  margin: 0;
  display: flex; align-items: baseline; gap: var(--s3);
  font: 700 var(--t-2xs)/1 var(--carve); letter-spacing: var(--ls-carve);
  color: var(--lime-low);
}
.course-d i {
  font: 400 var(--t-3xs)/1 var(--mono); font-style: normal;
  letter-spacing: var(--ls-wider); color: var(--lime-faint);
}
/*
 * 左对齐，不铺满：短列就是短的。
 * 间距 6px 不是随手取的：刻过的槽是可操作目标，WCAG 2.2 AA 要求 24×24 CSS px
 * 或等效间距，所以**槽宽 + 间距（pitch）在任何断点上都不低于 24px**。
 * 改槽的尺寸就必须一起改这里，否则窄屏上两个相邻的槽会挤进同一个指尖。
 */
.course-row { display: flex; flex-wrap: wrap; gap: 6px; }

/*
 * 凹槽。
 * 它必须读起来是**凿进去的**：上唇被光打亮、下沿背光、槽底最黑。
 * 只给亮不给暗，字就是浮在石头上的，不是刻进去的。
 * 拱顶的起拱去掉了 —— 墙上的槽是方的，那是石匠切出来的口子。
 */
.niche {
  position: relative;
  width: 26px; height: 30px; flex: none;
  border-radius: var(--r-cut);
  background: var(--cut-floor);
  box-shadow: var(--groove);
}
/* 刻过的槽是链接。它是 <a>，所以指针形状、键盘可达、焦点圈都是白来的 */
.niche.filled { cursor: pointer; display: block; text-decoration: none; }
/* 天区的色。和藏品图、观星台的穹顶用的是同一组 */
.niche.filled.r0 { background: linear-gradient(172deg, var(--region-n-pit), var(--region-n-bed)); }
.niche.filled.r1 { background: linear-gradient(172deg, var(--region-s-pit), var(--region-s-bed)); }
.niche.filled.r2 { background: linear-gradient(172deg, var(--region-e-pit), var(--region-e-bed)); }

.asterism { width: 17px; height: 20px; display: block; overflow: visible; margin: 5px auto 0; }
.asterism path { stroke: var(--asterism-line); stroke-width: 0.9; fill: none; }
.asterism .mags { fill: var(--asterism-star); }
.niche.filled.r0 .asterism .mags { fill: var(--region-n); }
.niche.filled.r1 .asterism .mags { fill: var(--region-s); }
.niche.filled.r2 .asterism .mags { fill: var(--region-e); }

.niche img { display: none; }
.niche.filled:hover, .niche.filled:focus-visible {
  /* 被看的槽从墙面**抬起来**一点：落影在右下，因为光在左上 */
  transform: translateY(-2px);
  box-shadow: var(--groove), 0 5px 12px oklch(0.05 0.004 158 / 0.75);
  z-index: 2;
}
.niche.filled:hover .asterism path { stroke: var(--asterism-line-lit); }
/* 你自己的那个槽盖着印 */
.niche.mine { box-shadow: var(--groove), inset 0 0 0 1.5px var(--seal); }
.niche .nd {
  position: absolute; inset: auto 0 -15px 0;
  font: var(--t-3xs)/1 var(--mono); text-align: center;
  color: var(--lime-faint); opacity: 0; transition: opacity .14s;
}
.niche:hover .nd, .niche:focus-visible .nd { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .niche { transition: none; }
  .niche.filled:hover, .niche.filled:focus-visible { transform: none; }
}

/* pitch = 22 + 6 = 28 */
@media (max-width: 900px) { .niche { width: 22px; height: 26px; } .asterism { width: 14px; height: 16px; } }
/* pitch = 18 + 6 = 24 —— 这是底线，不能再小 */
@media (max-width: 560px) { .niche { width: 18px; height: 22px; } .asterism { display: none; } }

/* 墙自己报它还剩多少。它紧贴墙面，因为这是墙的读数，不是页面的统计 */
.tally {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3) var(--s5);
  margin: 0; padding: var(--s4) 0 0;
  border-top: 1px solid var(--rule);
  font: var(--t-xs)/1.4 var(--sans); color: var(--lime-low);
}
.tally b { font: 700 var(--t-2xl)/1 var(--mono); color: var(--lime); margin-right: 5px; }
.tally-note { color: var(--lime-faint); font-size: var(--t-2xs); }

/* ═══════════════════════════════════════════ 首屏文字 */

/*
 * 首屏的编排顺序是有意的：**标题 → 墙 → 计数 → 读数**。
 * 标题先说这是什么，墙立刻给出证据（还剩多少空位），计数把证据变成数字。
 * 墙放在标题上面的话，访客第一眼看到的是一堆看不懂的方格。
 */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--s6) var(--s7);
  align-items: start;
}
.hero-copy { grid-column: 1; grid-row: 1; }
.hero-spec { grid-column: 2; grid-row: 1; }
.wall-face  { grid-column: 1 / -1; grid-row: 2; }
.tally      { grid-column: 1 / -1; grid-row: 3; }
.hero-rest  { grid-column: 1 / -1; grid-row: 4; }
@media (max-width: 1040px) {
  .hero { grid-template-columns: 1fr; gap: var(--s6); }
  .hero-copy, .hero-spec, .wall-face, .tally, .hero-rest { grid-column: 1; grid-row: auto; }
}

/*
 * 主标题是**刻在墙上的字**：明体、不收字距、一格一格排。
 * 上一版用黑体加负字距把标题收紧成一块 —— 那是海报的做法。
 * 碑上的字不收缩，它按格走。
 */
.headline {
  margin: 0 0 var(--s5);
  font: 700 var(--t-4xl)/1.22 var(--carve);
  letter-spacing: var(--ls-carve);
  color: var(--lime);
  text-wrap: balance;
}
.headline em {
  font-style: normal;
  /* 第二行压一道朱砂，不换字色 —— 印是盖上去的，不是把字染红 */
  box-shadow: inset 0 -0.14em 0 var(--seal-wash), inset 0 -0.16em 0 -0.13em var(--seal);
}
@media (max-width: 900px) { .headline { font-size: var(--t-3xl); } }
@media (max-width: 560px) { .headline { font-size: var(--t-2xl); } }

.whatis {
  margin: 0 0 var(--s4); max-width: 42em;
  color: var(--lime-mid);
  padding-left: var(--s4);
  border-left: 2px solid var(--rule-seal);
}
.whatis b { color: var(--lime); font-weight: 600; }
.standfirst { margin: 0 0 var(--s6); max-width: 40em; font-size: var(--t-sm); color: var(--lime-low); }

/*
 * 读数带。三个数里有两个只会往下走，那正是这一页要讲的事。
 * 它是**凿在墙上的一排格子**，不是三张统计卡：共用一个外框、一条基线。
 */
.computer {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px; margin: 0 0 var(--s6);
  background: var(--rule);
  box-shadow: var(--groove);
  border-radius: var(--r-cut);
  overflow: hidden;
}
.read { display: grid; gap: 4px; padding: var(--s4) var(--s4) var(--s5); background: var(--sunk-2); }
.read-k { font: var(--t-3xs)/1 var(--mono); letter-spacing: var(--ls-wider); color: var(--lime-faint); }
.read-v { font: 700 var(--t-3xl)/1 var(--mono); color: var(--lime); }
.read-word { font: 700 var(--t-xl)/1.2 var(--carve); letter-spacing: var(--ls-carve); color: var(--seal-light); }
.read-u { font: var(--t-2xs)/1.3 var(--mono); color: var(--lime-faint); }
@media (max-width: 640px) { .computer { grid-template-columns: 1fr; } .read-v { font-size: var(--t-2xl); } }

.actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin-bottom: var(--s4); }
.hint { margin: 0; font-size: var(--t-xs); color: var(--lime-faint); }

/* ═══════════════════════════════════════════ 按钮 */

/*
 * 主行动**是一枚印**。
 * 碑帖上唯一会出现的颜色就是印泥，盖章的人在说"这一份经我手"。
 * 所以它不是一个填了红色的圆角矩形：它是一方朱砂的印，
 * 内圈那道深边是印泥被压实的地方，按下去时它整个陷进纸里。
 */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  font: var(--t-sm)/1 var(--sans); letter-spacing: var(--ls-wide);
  text-decoration: none; cursor: pointer;
  border: 0; border-radius: var(--r-cut);
  padding: 13px 20px;
  transition: background .16s, color .16s, transform .1s, box-shadow .16s;
}
.btn-fill {
  background: var(--seal); color: var(--paper); font-weight: 600;
  box-shadow: inset 0 0 0 1.5px var(--seal-deep);
}
/* 印被按下去是**更深**，不是更亮：印泥被压实。
   之前 hover 调亮到 seal-light，纸白字掉到 2.8:1 —— 又不真实又不合格 */
.btn-fill:hover { background: var(--seal-deep); }
.btn-fill:active { transform: translateY(1px); box-shadow: inset 0 0 0 1.5px var(--seal-deep), inset 0 2px 4px oklch(0.05 0.004 158 / .45); }
/*
 * 次行动。上一版是**全透明**的描边按钮 —— 在黑屋子里那没问题，
 * 露天之后不行：朱砂本来就是暗色，压在天最亮的那几片上实测只剩 4.69:1，
 * 而且按钮是可按的东西，它本来就该有一块自己的地，不该是一圈浮在天上的线。
 * 所以给它凿一块底。
 */
.btn-line {
  background: var(--sunk-2); color: var(--seal-light);
  box-shadow: inset 0 0 0 1px var(--rule-seal);
  padding: 11px 18px;
}
.btn-line:hover { background: var(--seal-wash); }
.btn-sm { padding: 8px 14px; font-size: var(--t-xs); }
.ico { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } .btn-fill:active { transform: none; } }

/* ═══════════════════════════════════════════ 拓片 */

/*
 * 纸。这是**你带走的那一份** —— 把纸贴在名字上拓下来。
 * 石是公共的、深的；纸是私有的、亮的。整套系统就是这两种材料的对话，
 * 所以这块必须真的亮，不是"深色卡片上加一点白"。
 */
/* 拓片限宽：它是首屏的证物，不是主角 —— 放大到占半屏会把墙整个挤出视口 */
.hero-spec { margin: 0; max-width: 330px; justify-self: end; width: 100%; }
@media (max-width: 1040px) { .hero-spec { justify-self: start; } }
.plate {
  position: relative;
  background: var(--paper);
  padding: var(--s4) var(--s4) var(--s5);
  border-radius: var(--r-slab);
  /* 纸浮在墙前面，落影在右下 */
  box-shadow: var(--slab);
}
.plate-art { background: var(--cut-floor); border-radius: var(--r-cut); overflow: hidden; }
.plate-art img, .plate-art svg { width: 100%; display: block; }
.plate-no {
  display: block; margin-top: var(--s3);
  font: var(--t-3xs)/1 var(--mono); letter-spacing: var(--ls-wider);
  color: var(--graphite-soft); text-align: right;
}
.hero-spec figcaption { display: grid; gap: 3px; padding: var(--s4) var(--s1) 0; }
.hero-spec figcaption b {
  font: 700 var(--t-xl)/1.3 var(--carve); letter-spacing: var(--ls-carve); color: var(--lime);
}
.hero-spec figcaption span { font: var(--t-2xs)/1.5 var(--mono); color: var(--lime-faint); }
.hero-spec-d em { font-style: normal; color: var(--seal-light); }

/* ═══════════════════════════════════════════ 标题与正文 */

.h-sec {
  margin: 0 0 var(--s4);
  font: 700 var(--t-3xl)/1.3 var(--carve);
  letter-spacing: var(--ls-carve); color: var(--lime);
  text-wrap: balance;
}
.lede { margin: 0 0 var(--s5); max-width: 40em; color: var(--lime-mid); }
.lede strong { color: var(--lime); font-weight: 600; }
.aside { display: block; margin-top: 6px; font-size: var(--t-xs); color: var(--lime-faint); }

/* ═══════════════════════════════════════════ 板 02 · 怎么留名 */

.steps {
  list-style: none; margin: var(--s6) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5);
  align-items: start;
}
/*
 * 三步是一段往上走的路，不是三个并列的选项 —— 等宽三列会读成后者。
 * 每一步的刻线比前一步高一档。
 */
@media (min-width: 901px) {
  .steps li:nth-child(1) { margin-top: var(--s7); }
  .steps li:nth-child(2) { margin-top: var(--s5); }
}
@media (max-width: 900px) { .steps { grid-template-columns: 1fr; gap: var(--s4); } }
.steps li {
  display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: var(--s3);
  padding-top: var(--s4);
  border-top: 2px solid var(--rule-seal);
}
.step-n { font: 700 var(--t-xl)/1 var(--mono); color: var(--seal-light); }
.steps h3 {
  margin: 0 0 var(--s2);
  font: 700 var(--t-lg)/1.4 var(--carve); letter-spacing: var(--ls-carve); color: var(--lime);
}
.steps p { margin: 0 0 var(--s3); font-size: var(--t-sm); }
.steps strong { color: var(--lime); font-weight: 600; }

/*
 * 七格 = 七天 = 拾满 14 枚。
 * 用槽的语言画，因为它们和墙上那 88 个槽是同一件事：空的位置，等人来占。
 */
.seven { display: grid; gap: var(--s2); margin: 0 0 var(--s3); }
.seven-slots { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; max-width: 154px; }
.seven-slots i { height: 15px; border-radius: var(--r-cut); background: var(--cut-floor); box-shadow: var(--groove); }
.seven-cap { font: var(--t-3xs)/1.4 var(--mono); letter-spacing: var(--ls-wider); color: var(--lime-faint); }

/* ═══════════════════════════════════════════ 板 03 · 两种东西 */

/*
 * 一张双通道读数表，不是两张卡片。
 * 行标签只写一次，两栏落在同一条基线上 —— 这一段的意义就是横着读一行就能比出来。
 */
.pair {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr) minmax(0, 1fr);
  column-gap: var(--s5);
  margin-top: var(--s6);
}
.pair-head:nth-child(1) { grid-column: 2; }
.pair-head:nth-child(2) { grid-column: 3; }
.pair-spec, .pair-row { display: contents; }
.pair-head:nth-child(2),
.pair-row dd:last-child { border-left: 1px solid var(--rule-strong); padding-left: var(--s5); }

.pair-head { padding-bottom: var(--s5); }
.pair-head h3 {
  margin: var(--s4) 0 var(--s3);
  font: 700 var(--t-xl)/1.3 var(--carve); letter-spacing: var(--ls-carve); color: var(--lime);
  display: grid; gap: 3px;
}
.pair-head h3 i {
  font: var(--t-2xs)/1 var(--mono); font-style: normal;
  letter-spacing: var(--ls-wide); color: var(--lime-faint);
}
.pair-head p { margin: 0; font-size: var(--t-sm); color: var(--lime-mid); }
.obs-fig {
  width: 92px; height: 92px; border-radius: var(--r-cut);
  background: var(--cut-floor); box-shadow: var(--groove); overflow: hidden;
}
.obs-fig img, .obs-fig svg { width: 100%; height: 100%; display: block; }

.pair dt, .pair dd { margin: 0; padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.pair dt { font: var(--t-3xs)/1.6 var(--mono); letter-spacing: var(--ls-wider); color: var(--lime-faint); }
.pair dd { font: 700 var(--t-md)/1.4 var(--mono); color: var(--lime); }
.pair dd .unit { font-weight: 400; font-size: var(--t-2xs); color: var(--lime-faint); }
/* 星屑没有第二条路。空格是这张表最该说清楚的一件事，所以它有字，只是退到最暗一级 */
.pair dd.none { font-weight: 400; color: var(--lime-faint); }

@media (max-width: 820px) {
  .pair { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s4); }
  .pair-head:nth-child(1) { grid-column: 1; }
  .pair-head:nth-child(2) { grid-column: 2; }
  .pair dt { grid-column: 1 / -1; padding-bottom: 0; border-top: none; }
  .pair dd { border-top: none; }
  .pair-row dd:last-child { padding-left: var(--s4); }
}
/*
 * 窄屏上**不能**退成单列：两个值上下堆叠，读者就分不清哪个是星屑、哪个是星座。
 * 列的身份靠位置对住上面那两个抬头，塌了这张表就没有意义了。
 */
@media (max-width: 560px) {
  .pair { column-gap: var(--s3); }
  .pair-head:nth-child(2), .pair-row dd:last-child { padding-left: var(--s3); }
  .pair dd { font-size: var(--t-sm); }
  .pair-head p { font-size: var(--t-xs); }
  .obs-fig { width: 64px; height: 64px; }
}

/* ═══════════════════════════════════════════ 板 04 · 门槛 */

/*
 * 全站唯一一条硬边。
 * 它不是段落的顶边，它是那道门限本身，所以它长在版面中间，
 * 把该收钱的和不该收钱的真的分开。那句话骑在线上，因为它就是这条线。
 */
.cut { margin-top: var(--s6); }
.cut-side { padding: var(--s5) 0; }
.cut-tag {
  display: block; margin-bottom: var(--s2);
  font: var(--t-3xs)/1 var(--mono); letter-spacing: var(--ls-wider); color: var(--lime-faint);
}
.cut-side p { margin: 0; max-width: 44em; color: var(--lime-mid); }
.cut-side strong, .cut-side b { color: var(--lime); font-weight: 600; }
.cut-line {
  margin: 0; padding: var(--s5) 0 var(--s6);
  border-top: 1px solid var(--seal);
  background: linear-gradient(180deg, var(--seal-wash), transparent 70%);
  font: 700 var(--t-2xl)/1.45 var(--carve);
  letter-spacing: var(--ls-carve); color: var(--lime);
}

/* ═══════════════════════════════════════════ 板 05 · 三条规矩 */

.rules { list-style: none; margin: var(--s6) 0 0; padding: 0; display: grid; gap: 1px; }
.rules li {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  grid-template-areas: "n title" "n body";
  gap: var(--s2) var(--s4);
  padding: var(--s5) var(--s4);
  background: var(--sunk-2);
  outline: none;
}
.rules .rule-mark { grid-area: n; }
.rules h3 { grid-area: title; }
.rules p { grid-area: body; }
.rules li:hover, .rules li:focus-visible { background: var(--sunk-3); }
/*
 * 这三条是三条并列的不变量，不是三个步骤 —— 所以不给它们编号。
 * 真正的序列在板 02，数字留给那一段。这里标的是每一条"凭什么改不掉"。
 * 不用等宽：它们不是测量值。
 */
.rule-mark {
  font: 700 var(--t-sm)/1.35 var(--carve);
  letter-spacing: var(--ls-carve); color: var(--seal-light);
}
.rules h3 { margin: 0 0 var(--s2); font: 700 var(--t-lg)/1.4 var(--carve); letter-spacing: var(--ls-carve); color: var(--lime); }
.rules p { margin: 0; font-size: var(--t-sm); max-width: 44em; }
@media (max-width: 560px) { .rules li { grid-template-columns: 48px 1fr; gap: var(--s3); padding: var(--s4) var(--s3); } }

/* ═══════════════════════════════════════════ 板 06 · 纪年 */

/*
 * 刻痕志的形式：一层层钉上去的标牌，只追加，永远不覆盖。
 * 最新一条的左边压一道朱砂 —— 那是"此刻"。
 */
.logbook { display: grid; gap: 1px; margin-top: var(--s6); }
.log-row {
  display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: var(--s5);
  padding: var(--s5) var(--s4);
  background: var(--sunk-2);
  border-left: 2px solid var(--rule-strong);
}
.log-row.now { border-left-color: var(--seal); }
.log-when {
  margin: 0; display: flex; align-items: center; gap: var(--s2);
  font: var(--t-2xs)/1.4 var(--mono); letter-spacing: var(--ls-wider); color: var(--lime-faint);
}
.log-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--lime-faint); flex: none; }
.log-row.now .log-dot { background: var(--seal); }
.log-row h3 { margin: 0 0 var(--s2); font: 700 var(--t-lg)/1.4 var(--carve); letter-spacing: var(--ls-carve); color: var(--lime); }
.log-row p { margin: 0; font-size: var(--t-sm); }
.log-live {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  margin-top: var(--s4) !important; padding-top: var(--s3);
  border-top: 1px solid var(--rule);
  font: var(--t-2xs)/1.4 var(--mono); color: var(--lime-faint);
}
.log-live b { font-size: var(--t-md); color: var(--lime); margin-right: 4px; }
@media (max-width: 720px) { .log-row { grid-template-columns: 1fr; gap: var(--s3); } }

/* ═══════════════════════════════════════════ 页脚 */

.stow { border-top: 2px solid var(--rule-strong); }
.stow .stage-in { padding-block: var(--s7); }
