/* ══════════════════════════════════════════════════════════════════════════
   索拉尔的主页 —— 设计系统
   ══════════════════════════════════════════════════════════════════════════

   设计语言基于 DESIGN-x.ai.md：单一近黑画布、1px hairline 承担全部层级线索、
   全站 font-weight 400、无阴影、pill 为唯一交互形状。

   设计程式（Karl Gerstner）：一个圆 = 一年，360° = 12 个月。
   页面上每一根刻针的角度都由文章日期算出，见 build/sun.js。

   #ff7a17 是全站唯一点缀色，只标记「当前太阳的位置」= 最新一篇文章的角度。
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 字体：自托管，服务器在国内，不依赖 Google Fonts ────────────────── */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-latin-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-latin-ext-400.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-latin-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* 色板：锁定，不新增颜色 */
  --canvas: #0a0a0a;
  --card: #191919;
  --soft: #1a1c20;
  --mid: #363a3f;
  --hair: #212327;
  --ink: #ffffff;
  --body: #dadbdf;
  --mute: #7d8187;
  --sun: #ff7a17;

  /* 语法高亮专用色。只在代码块内生效，页面版式一律不用 —— 代码要靠色相
     区分语义类别（关键字/类型/字符串），仅靠上面那几级灰阶做不到：9 个灰
     阶排不出 5 类 token，硬排的结果是关键字反而比变量暗。
     低饱和度以免与 --sun 抢注意力，三者在 #191919 上均 ≥7.6:1（AA）。 */
  --c-key: #8ab4c8; /* 关键字、控制流         7.91:1 */
  --c-type: #b3a4cc; /* 类型、类名           7.62:1 */
  --c-str: #9db894; /* 字符串、字符          8.14:1 */
  --c-note: #868c94; /* 注释                5.18:1 */

  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC',
    'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas,
    monospace;

  /* 4px 基准间距 */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;

  --rail-w: 220px;
  --rail-w-collapsed: 48px;
  --axis-w: 200px;
  --measure: 680px;
}

/* ── 重置 ────────────────────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
  padding: 0;
}
html {
  background: var(--canvas);
  scroll-behavior: smooth;
  scroll-padding-top: var(--s6);
}
body {
  background: var(--canvas);
  color: var(--body);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 24px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* 这套语言从不加粗：层级由字号、负字距与 hairline 密度承担 */
h1,
h2,
h3,
h4,
h5,
h6,
strong,
b,
th,
dt {
  font-weight: 400;
}
a {
  color: inherit;
  text-decoration: none;
}
ul,
ol {
  list-style: none;
}
img {
  max-width: 100%;
  height: auto;
  display: block;
}
::selection {
  background: var(--sun);
  color: var(--canvas);
}
:focus-visible {
  outline: 1px solid var(--sun);
  outline-offset: 2px;
}
.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: var(--s4);
  top: var(--s4);
  z-index: 10;
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: 9999px;
  padding: var(--s2) var(--s4);
  color: var(--ink);
}

/* ── mono caption：与 sans 的两面对照就是这套语言的声音 ──────────────── */
.cap,
.cap14 {
  font-family: var(--mono);
  text-transform: uppercase;
  color: var(--mute);
}
.cap {
  font-size: 12px;
  line-height: 16px;
  letter-spacing: 1.2px;
}
.cap14 {
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 1.4px;
}

/* ══════════════════════════════════════════════════════════════════════
   骨架：固定侧栏 + 主栏
   ══════════════════════════════════════════════════════════════════════ */
.shell {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
}
/* ── 侧栏收起 ────────────────────────────────────────────────────────
   收起后只留 48px 窄条（站名太阳环 + 展开按钮）。读文章时导航用不到，
   而 1180px 以下正文会被侧栏与目录轴挤到 500px 以下 —— 收起后正文多拿
   172px。状态由 <head> 里的脚本在首帧前决定，避免窄屏闪一下宽侧栏。 */
html.rail-collapsed {
  --rail-w: var(--rail-w-collapsed);
  /* 收起后同时放宽正文上限。否则大屏上正文已达 680px 上限，点击收起只会
     多出空白、正文一动不动，按钮看起来就是坏的。760px 约 47 汉字/行，
     仍在长文可读区间内。 */
  --measure: 760px;
}

.rail {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--rail-w);
  height: 100vh;
  border-right: 1px solid var(--hair);
  padding: var(--s6) var(--s5);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background: var(--canvas);
  z-index: 5;
}
/* 站点标记 + 导航。头盔在 .railTop 里而非 .railBody 里，因此收起时
   .railBody 整块隐去、头盔仍留在窄条上。 */
.railTop {
  min-width: 0;
}
/* 站点标记：像素头盔 + 站名。头盔是 24×38 的矢量重建，硬边不发毛。 */
.rail .mark {
  display: flex;
  align-items: center;
  gap: var(--s3);
}
.rail .helm {
  /* 用高度定尺寸 —— 头盔是竖长比例，按宽度定会在收起态里过大 */
  height: 34px;
  width: auto;
  flex: none;
  display: block;
  transition:
    height 0.2s,
    opacity 0.15s;
}
.rail .mark:hover .helm {
  /* 全站没有阴影，也不做位移动效；hover 反馈用极轻的提亮 */
  opacity: 0.82;
}
.rail .markText {
  display: flex;
  flex-direction: column;
  min-width: 0;
  transition:
    opacity 0.16s,
    visibility 0.16s;
}
.rail .sitename {
  font-size: 16px;
  line-height: 22px;
  color: var(--ink);
  letter-spacing: -0.2px;
  white-space: nowrap;
}
.rail .sitesub {
  margin-top: 1px;
  white-space: nowrap;
}
.vnav {
  margin-top: var(--s7);
  display: flex;
  flex-direction: column;
}
.vnav a {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
  padding: var(--s3) 0;
  border-top: 1px solid var(--hair);
  transition: color 0.15s;
}
.vnav a:last-child {
  border-bottom: 1px solid var(--hair);
}
.vnav a .dot {
  width: 5px;
  height: 5px;
  border-radius: 9999px;
  border: 1px solid var(--mid);
  flex: none;
}
.vnav a em {
  font-style: normal;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--mute);
}
.vnav a:hover {
  color: var(--ink);
}
.vnav a:hover .dot {
  border-color: var(--mute);
}
.vnav a.on {
  color: var(--ink);
}
.vnav a.on .dot {
  background: var(--sun);
  border-color: var(--sun);
}
.rail .formula {
  color: var(--mute);
}

/* 收起按钮：常驻在侧栏右上角，收起态下居中于窄条 */
.railToggle {
  position: absolute;
  top: var(--s5);
  right: var(--s5);
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  border-radius: 9999px;
  color: var(--mute);
  cursor: pointer;
  padding: 0;
  transition: color 0.15s;
}
.railToggle:hover {
  color: var(--ink);
}
.railToggle .bars {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 14px;
}
.railToggle .bars i {
  display: block;
  height: 1px;
  background: currentColor;
  transition: width 0.2s;
}
.railToggle .bars i:first-child {
  width: 14px;
}
.railToggle .bars i:last-child {
  width: 9px;
}
.railToggle:hover .bars i:last-child {
  width: 14px;
}
.srOnly {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.rail .formula {
  transition:
    opacity 0.16s,
    visibility 0.16s;
}
html.rail-collapsed .rail .formula {
  /* visibility:hidden 仍占位，会参与 flex 分配 —— 必须退出布局 */
  display: none;
}
html.rail-collapsed .rail {
  padding-left: 0;
  padding-right: 0;
  align-items: center;
  /* 收起后内容只剩「按钮 + 头盔」，改为顶部对齐 —— 展开态的
     space-between 会把头盔推到侧栏垂直中央（实测 y=429），
     那里既不像 logo 也不像导航入口。 */
  justify-content: flex-start;
  gap: var(--s5);
}
html.rail-collapsed .railToggle {
  position: static;
  margin: 0 auto;
}
/* 收起态：站名隐去，只留头盔居中作为回首页的入口。
   头盔常驻在 .railTop（而非 .railBody）里，正是为了收起后仍可见 —— 窄条
   上如果什么标记都没有，就认不出这是哪个站了。

   .railTop 必须限宽：.rail 收起时是 align-items:center，而 markText 里的
   站名 white-space:nowrap，不限宽会把 .railTop 撑到 225px，居中后整块被
   推到画布外（实测 x=-89，头盔完全看不见）。 */
html.rail-collapsed .railTop {
  width: 100%;
  overflow: hidden;
  /* 不撑高 —— .rail 是 space-between 的 flex，.railBody 虽已隐形但
     仍占据高度，会把头盔顶到侧栏底部去 */
  flex: none;
}
html.rail-collapsed .railBody {
  /* 隐形不够，必须退出布局，否则它撑起的高度仍参与 space-between 分配 */
  display: none;
}
html.rail-collapsed .rail .mark {
  justify-content: center;
  margin-top: var(--s5);
}
html.rail-collapsed .rail .markText {
  /* 不只是隐形，还要退出布局 —— 否则它仍参与 flex 的宽度计算 */
  display: none;
}
html.rail-collapsed .rail .helm {
  height: 26px;
}
.rail {
  transition: width 0.2s;
}

main {
  grid-column: 2;
  min-width: 0;
}
.wrap {
  max-width: 1200px;
  padding: 0 var(--s8);
}

/* ══════════════════════════════════════════════════════════════════════
   母题：环 + 刻针
   ══════════════════════════════════════════════════════════════════════ */
.ring {
  position: relative;
  border: 1px solid var(--mid);
  border-radius: 9999px;
  flex: none;
  display: inline-block;
}
.ring i {
  position: absolute;
  left: 50%;
  top: 0;
  width: 1px;
  height: 50%;
  margin-left: -0.5px;
  transform-origin: 50% 100%;
  background: var(--mute);
}
.r12 {
  width: 12px;
  height: 12px;
}
.r40 {
  width: 40px;
  height: 40px;
  border-color: var(--hair);
}
.r56 {
  width: 56px;
  height: 56px;
  border-color: var(--hair);
}
/* 大尺度的环：刻针自圆周向内，不贯穿圆心 */
.r40 i {
  background: linear-gradient(
    to bottom,
    var(--mid) 0,
    var(--mid) 8px,
    transparent 8px
  );
}
.r56 i {
  background: linear-gradient(
    to bottom,
    var(--mid) 0,
    var(--mid) 9px,
    transparent 9px
  );
}
.r40 i.sun {
  background: linear-gradient(
    to bottom,
    var(--sun) 0,
    var(--sun) 8px,
    transparent 8px
  );
}
.r56 i.sun {
  background: linear-gradient(
    to bottom,
    var(--sun) 0,
    var(--sun) 9px,
    transparent 9px
  );
}
.r12 i.sun {
  background: var(--sun);
}

/* ══════════════════════════════════════════════════════════════════════
   首屏：太阳即坐标系
   ══════════════════════════════════════════════════════════════════════ */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 460px;
  gap: var(--s7);
  align-items: center;
  padding: 96px 0 var(--s8);
  border-bottom: 1px solid var(--hair);
}
.hero h1 {
  font-size: 72px;
  line-height: 76px;
  letter-spacing: -1.8px;
  color: var(--ink);
}
.hero .praise {
  margin-top: var(--s5);
  display: flex;
  align-items: baseline;
  gap: var(--s3);
}
.hero .praise .zh {
  font-size: 18px;
  line-height: 28px;
  color: var(--body);
}
.hero .desc {
  margin-top: var(--s5);
  max-width: 520px;
  color: var(--mute);
}
.rule {
  border-top: 1px solid var(--hair);
  margin-top: var(--s6);
}
.facts {
  display: grid;
  grid-template-columns: repeat(4, auto);
  gap: 0 var(--s6);
  margin-top: var(--s4);
  justify-content: start;
}
.facts > div {
  padding-top: var(--s3);
}
.facts .n {
  font-family: var(--mono);
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 1.4px;
  color: var(--body);
}
.facts .k {
  margin-top: var(--s1);
}

.sundial {
  position: relative;
  width: 420px;
  height: 420px;
  justify-self: center;
}
.sundial .disc,
.sundial .disc2,
.sundial .disc3 {
  position: absolute;
  border-radius: 9999px;
}
.sundial .disc {
  inset: 0;
  border: 1px solid var(--mid);
}
.sundial .disc2 {
  inset: 56px;
  border: 1px solid var(--hair);
}
.sundial .disc3 {
  inset: 150px;
  border: 1px solid var(--hair);
}
.sundial .hands {
  position: absolute;
  inset: 0;
}
.sundial .hands span {
  position: absolute;
  left: 50%;
  top: 0;
  width: 1px;
  height: 50%;
  margin-left: -0.5px;
  transform-origin: 50% 100%;
}
/* 月份刻度：外缘短针 */
.sundial .m {
  background: linear-gradient(
    to bottom,
    var(--hair) 0,
    var(--hair) 18px,
    transparent 18px
  );
}
/* 文章落位：内缘一段 */
.sundial .e {
  background: linear-gradient(
    to bottom,
    transparent 0,
    transparent 22px,
    var(--mid) 22px,
    var(--mid) 56px,
    transparent 56px
  );
}
/* 唯一的橙射线 = 当前太阳的位置 */
.sundial .ray {
  background: linear-gradient(
    to bottom,
    var(--sun) 0,
    var(--sun) 56px,
    transparent 56px
  );
}
.sundial .ray::after {
  content: '';
  position: absolute;
  top: -4px;
  left: -3.5px;
  width: 8px;
  height: 8px;
  border-radius: 9999px;
  background: var(--sun);
}
.sundial .core {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.sundial .core .num {
  /* 四位年份在 96px 下宽 228px，会压出 120px 的最内圈、把圆环切断。
     64px 约 152px 宽，落在中圈内，环保持完整。 */
  font-size: 64px;
  line-height: 64px;
  letter-spacing: -1.6px;
  color: var(--ink);
}
.sundial .core .lbl {
  margin-top: var(--s3);
}
/* 圆心的 eyebrow 在数字之上，故改为下间距 */
.sundial .core .lbl.top {
  margin-top: 0;
  margin-bottom: var(--s3);
}
.sundial .legend {
  position: absolute;
  left: 0;
  top: -32px;
}
.sundial .anno {
  position: absolute;
  left: calc(50% + 46px);
  top: calc(50% + 200px);
  white-space: nowrap;
}
.sundial .anno .v {
  color: var(--sun);
}

/* ══════════════════════════════════════════════════════════════════════
   章节标注 / 页面头
   ══════════════════════════════════════════════════════════════════════ */
.seclabel {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s8) 0 var(--s5);
}
.seclabel .bar {
  flex: 1;
  border-top: 1px solid var(--hair);
}
.seclabel .t {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
}

.pageHead {
  padding: var(--s8) 0 0;
}
.pageHead h1 {
  font-size: 48px;
  line-height: 52px;
  letter-spacing: -1.2px;
  color: var(--ink);
}
.pageHead .sub {
  margin-top: var(--s3);
}
.pageHead .sub a:hover {
  color: var(--sun);
}

/* ══════════════════════════════════════════════════════════════════════
   索引：按年分组，年份 + 年环作粘性左轴
   ══════════════════════════════════════════════════════════════════════ */
.yearblock {
  display: grid;
  grid-template-columns: var(--axis-w) minmax(0, 1fr);
  gap: var(--s7);
  padding: var(--s6) 0;
  border-top: 1px solid var(--hair);
}
.yearblock .axis {
  position: sticky;
  top: var(--s6);
  align-self: start;
}
.yearblock .y {
  font-size: 48px;
  line-height: 48px;
  letter-spacing: -1.2px;
  color: var(--ink);
}
.yearblock .axis .ring {
  margin-top: var(--s4);
}
.yearblock .axis .meta {
  margin-top: var(--s3);
}

.row {
  display: grid;
  grid-template-columns: 12px 48px minmax(0, 1fr) auto 88px;
  align-items: center;
  gap: var(--s4);
  padding: var(--s3) 0;
  border-top: 1px solid var(--hair);
}
.rows > .row:first-child {
  border-top: 0;
}
.row .deg {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  color: var(--mute);
}
.row .t {
  font-size: 18px;
  line-height: 28px;
  letter-spacing: -0.2px;
  color: var(--body);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 0.15s;
}
.row .d {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  color: var(--mute);
  text-align: right;
}
.row .tags {
  display: flex;
  gap: var(--s1);
}
.tag {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 16px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
  border: 1px solid var(--hair);
  border-radius: 9999px;
  padding: 2px var(--s2);
  white-space: nowrap;
  transition:
    color 0.15s,
    border-color 0.15s;
}
.tag:hover {
  color: var(--ink);
  border-color: var(--mid);
}
.row:hover .t {
  color: var(--ink);
}
.row:hover .deg {
  color: var(--sun);
}
.row:hover .ring {
  border-color: var(--mute);
}
.row:hover .ring i {
  background: var(--sun);
}
.row.latest .deg {
  color: var(--sun);
}

/* ══════════════════════════════════════════════════════════════════════
   标签总览
   ══════════════════════════════════════════════════════════════════════ */
/* 用 gap 做 1px 分割线时，末行不满会露出底色，所以改由格子自身画边线：
   每格右下各一条 hairline，最右列与最后一行的外侧边线由容器补齐。 */
.taggrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
}
.tagcard {
  border-right: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  margin: 0 -1px -1px 0;
}
.tagcard a {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5);
  height: 100%;
  transition: background 0.15s;
}
.tagcard a:hover {
  background: var(--card);
}
.tagcard .name {
  font-size: 18px;
  line-height: 28px;
  color: var(--body);
  letter-spacing: -0.2px;
}
.tagcard a:hover .name {
  color: var(--ink);
}
.tagcard a:hover .ring {
  border-color: var(--mid);
}

/* ══════════════════════════════════════════════════════════════════════
   文章页：200px 目录轴 + 680px 正文
   ══════════════════════════════════════════════════════════════════════ */
.entryHead {
  padding: var(--s8) 0 var(--s5);
  border-bottom: 1px solid var(--hair);
}
.entryHead .crumb {
  margin-bottom: var(--s4);
}
.entryHead .crumb a:hover {
  color: var(--sun);
}
.entryHead h1 {
  font-size: 48px;
  line-height: 54px;
  letter-spacing: -1.2px;
  color: var(--ink);
  max-width: 900px;
}
.entryHead .meta {
  margin-top: var(--s4);
  display: flex;
  gap: var(--s3);
  align-items: center;
  flex-wrap: wrap;
}

.entryBody {
  display: grid;
  grid-template-columns: var(--axis-w) minmax(0, var(--measure));
  gap: var(--s7);
  padding: var(--s6) 0 96px;
}
.entryBody.single {
  grid-template-columns: minmax(0, var(--measure));
  padding-top: var(--s6);
}
.entryBody .side {
  position: sticky;
  top: var(--s6);
  align-self: start;
  max-height: calc(100vh - var(--s8));
  overflow-y: auto;
}
.toc .h,
.position .h {
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--hair);
}
.toc ol {
  counter-reset: toc;
}
.toc li {
  counter-increment: toc;
  border-bottom: 1px solid var(--hair);
}
.toc a {
  display: flex;
  gap: var(--s2);
  padding: var(--s2) 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--mute);
  transition: color 0.15s;
  /* 标题常含长符号名（std::memory_order_acq_rel），必须允许断行 */
  min-width: 0;
  overflow-wrap: anywhere;
}
.toc a::before {
  content: counter(toc, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  color: var(--mid);
  flex: none;
}
.toc a:hover {
  color: var(--ink);
}
/* 层级缩进：作者正文用 # 起，收集时记的是原始层级 1/2/3 */
.toc li.lv2 a {
  padding-left: var(--s3);
}
.toc li.lv3 a {
  padding-left: var(--s5);
}
.toc li.lv2 a::before,
.toc li.lv3 a::before {
  color: var(--hair);
}
.position {
  margin-top: var(--s6);
}
.position .posRow {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding-top: var(--s3);
}

/* ── 正文排版 ────────────────────────────────────────────────────────── */
.prose {
  font-size: 16px;
  line-height: 26px;
  color: var(--body);
  min-width: 0;
}
.prose > * + * {
  margin-top: var(--s4);
}
.prose h2,
.prose h3,
.prose h4 {
  color: var(--ink);
  letter-spacing: -0.6px;
}
.prose h2 {
  /* border-top 与相邻元素的 margin 会在视觉上贴死，所以上间距给足再画线 */
  margin-top: var(--s8);
  padding-top: var(--s5);
  border-top: 1px solid var(--hair);
  font-size: 32px;
  line-height: 40px;
}
/* 正文开头就是 h2 时不需要那条线 */
.prose > h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.prose h3 {
  margin-top: var(--s6);
  font-size: 24px;
  line-height: 32px;
  letter-spacing: -0.4px;
}
.prose h4 {
  margin-top: var(--s5);
  font-size: 18px;
  line-height: 28px;
  letter-spacing: -0.2px;
}
.prose a {
  color: var(--sun);
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s;
}
.prose a:hover {
  border-bottom-color: var(--sun);
}
/* 站内文章链接（{% post_link %}）。外链是新窗口打开的，这里给一道常显的
   虚线，读者点之前就知道自己不会离开本站。 */
.prose a.postLink {
  border-bottom: 1px dashed var(--mid);
}
.prose a.postLink:hover {
  border-bottom-style: solid;
  border-bottom-color: var(--sun);
}
.prose ul,
.prose ol {
  padding-left: var(--s5);
}
.prose ul li {
  list-style: none;
  position: relative;
}
.prose ul li::before {
  content: '';
  position: absolute;
  left: calc(var(--s5) * -1 + 4px);
  top: 11px;
  width: 4px;
  height: 4px;
  border-radius: 9999px;
  border: 1px solid var(--mid);
}
.prose ol {
  list-style: decimal;
  color: var(--mute);
}
.prose ol > li {
  list-style: decimal;
}
.prose li {
  margin-top: var(--s2);
  color: var(--body);
}
.prose li > ul,
.prose li > ol {
  margin-top: var(--s2);
}
.prose blockquote {
  padding: var(--s4) var(--s5);
  border: 1px solid var(--hair);
  border-radius: 8px;
  color: var(--mute);
}
.prose blockquote > * + * {
  margin-top: var(--s3);
}
.prose hr {
  border: 0;
  border-top: 1px solid var(--hair);
  margin: var(--s7) 0;
}
.prose img {
  margin: var(--s5) auto;
  border: 1px solid var(--hair);
  border-radius: 8px;
}

/* 可点开看原图的截图。原始宽度多在 1500px 以上，满栏也只有三成大小，
   故整图可点。hover 时描边提亮，暗示可交互。 */
.prose .imgLink {
  display: block;
  margin: var(--s5) 0;
}
.prose .imgLink img {
  margin: 0;
  transition: border-color 0.15s;
}
.prose .imgLink:hover img {
  border-color: var(--mid);
}

/* 内联 SVG 图表。
   SVG 自带 #0a0a0a 底色与 hairline，所以不再套边框 —— 它本身就是页面的一部分，
   而不是贴在页面上的一张图。宽度撑满正文栏，按 viewBox 等比缩放。 */
.prose .diagram {
  margin: var(--s6) 0;
}
.prose .diagram svg {
  display: block;
  width: 100%;
  height: auto;
}
.prose .diagram figcaption {
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--hair);
}
.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  line-height: 20px;
}
.prose th {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--body);
  text-align: left;
  background: var(--soft);
}
.prose th,
.prose td {
  padding: var(--s3) var(--s4);
  border: 1px solid var(--hair);
}

/* 行内代码：pill —— 与全站唯一交互形状同源 */
.prose :not(pre) > code {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink);
  background: var(--soft);
  border: 1px solid var(--hair);
  border-radius: 9999px;
  padding: 1px var(--s2);
  white-space: nowrap;
}

/* 代码块。
   pre 自身是卡片 —— 无 JS 时就是最终形态，语言标记留在 pre 内左上方。
   有 JS 时脚本套一层 .codeBlock 并把标记提上去：pre 是横向滚动容器，
   标记若留在里面会随代码滑走（cpo 那篇溢出 206px，标记直接滚出可视区）。

   语言标记不占整行 —— 代码多的文章（memory-order 有 7 个块）里，
   每块顶上一行标签会累积成很吵的横条。 */
.prose pre {
  position: relative;
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: var(--s4) var(--s5);
  overflow-x: auto;
}
/* 语言标记的字体样式与它在哪一层无关，故不写进 .prose pre 的后代选择器 ——
   脚本会把它从 pre 内移到 .codeBlock 上，写死在 pre 后代里会在移动后失效
   （曾因此丢了 uppercase，"CPP" 显示成 "cpp"）。 */
.prose .code-lang {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mute);
}
/* 无 JS 时留在 pre 内，自占一行 */
.prose pre > .code-lang {
  margin-bottom: var(--s3);
}
/* 有 JS：外层容器接管卡片，pre 退化为纯滚动区 */
.prose .codeBlock {
  position: relative;
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: 8px;
  /* 纵向间距交给 .prose > * + * 的统一节奏，这里不自定义 */
}
.prose .codeBlock > pre {
  background: none;
  border: 0;
  border-radius: 0;
  margin: 0;
}
/* 标记被提到外层后钉在右上角，不再占行 */
.prose .codeBlock > .code-lang {
  position: absolute;
  top: 0;
  right: 0;
  margin: 0;
  padding: 7px 10px;
  pointer-events: none;
  z-index: 1;
}
.prose .codeBlock.hasCopy > .code-lang {
  right: 30px;
}
.prose pre code {
  font-family: var(--mono);
  font-size: 14px;
  line-height: 22px;
  color: var(--body);
  display: block;
  white-space: pre;
}

/* 复制按钮：常态几乎隐形，hover 代码块时浮现 —— 不与代码争注意力。
   由 JS 注入，无 JS 时不存在，不会出现点了没反应的死按钮。 */
.prose .codeBlock .copyBtn {
  position: absolute;
  top: 3px;
  right: 3px;
  z-index: 2;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
  background: var(--card);
  border: 1px solid transparent;
  border-radius: 8px;
  color: var(--mute);
  cursor: pointer;
  opacity: 0;
  transition:
    opacity 0.15s,
    color 0.15s,
    border-color 0.15s;
}
.prose .codeBlock:hover .copyBtn,
.prose .codeBlock .copyBtn:focus-visible {
  opacity: 1;
}
.prose .codeBlock .copyBtn:hover {
  color: var(--ink);
  border-color: var(--hair);
}
.prose .codeBlock .copyBtn svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}
/* 复制成功：图标换成对勾并转为点缀色，2 秒后复原 */
.prose .codeBlock .copyBtn.done {
  color: var(--sun);
  opacity: 1;
}
/* 键盘 tab 到按钮时必须可见，否则焦点像消失了 */
.prose .codeBlock .copyBtn:focus-visible {
  outline: 1px solid var(--sun);
  outline-offset: 1px;
}

/* highlight.js
   分层原则：代码的骨架（关键字、类型、函数名）要比周边的标识符更显眼。
   此前反了 —— 关键字用 --mute (4.49:1)、标识符用 --body (12.7:1)，
   于是 void/int/for 比变量名还暗，读者先看到的是噪声而不是结构。 */

/* 注释：明确弱于代码，但仍需可读。旧值 --mid 在卡片上只有 1.54:1。 */
.hljs-comment,
.hljs-quote {
  color: var(--c-note);
  font-style: italic;
}

/* 关键字与控制流 —— 代码的骨架 */
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-doctag {
  color: var(--c-key);
}

/* 类型、类名、内建符号 */
.hljs-type,
.hljs-built_in,
.hljs-class .hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__ {
  color: var(--c-type);
}

/* 字符串与字符字面量 */
.hljs-string,
.hljs-char.escape_,
.hljs-regexp,
.hljs-symbol,
.hljs-template-tag,
.hljs-template-variable {
  color: var(--c-str);
}

/* 数字与预处理指令用点缀色 —— 每个块里出现次数少，不至于稀释 --sun 的语义。
   字符串已改用 --c-str，正是为了把橙色从"满屏都是"收回到"偶尔一点"。 */
.hljs-number,
.hljs-meta,
.hljs-meta .hljs-keyword,
.hljs-meta .hljs-string {
  color: var(--sun);
}

/* 函数名、定义处的标识符 —— 最亮，读代码时的锚点 */
.hljs-title,
.hljs-title.function_,
.hljs-section,
.hljs-name {
  color: var(--ink);
}

/* 属性、参数、变量 —— 正文亮度 */
.hljs-attr,
.hljs-attribute,
.hljs-variable,
.hljs-params,
.hljs-property,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
  color: var(--body);
}

.hljs-emphasis {
  font-style: italic;
}
.hljs-strong {
  /* 全站 font-weight 恒为 400，加粗改用提亮 */
  color: var(--ink);
}
.hljs-deletion {
  color: var(--c-note);
  text-decoration: line-through;
}
.hljs-addition {
  color: var(--c-str);
}

/* ── 上下篇 ──────────────────────────────────────────────────────────── */
.pnnav {
  margin-top: var(--s8);
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
}
.pn {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  padding: var(--s4) var(--s5);
  transition: background 0.15s;
}
.pn.next {
  text-align: right;
  border-left: 1px solid var(--hair);
}
.pn:hover {
  background: var(--card);
}
.pn .t {
  font-size: 16px;
  line-height: 24px;
  color: var(--body);
  letter-spacing: -0.2px;
}
.pn:hover .t {
  color: var(--ink);
}
.pn:only-child {
  grid-column: span 2;
}

.notfound {
  padding: var(--s6) 0 96px;
  color: var(--mute);
}
.notfound a {
  color: var(--sun);
}

/* ══════════════════════════════════════════════════════════════════════
   放大浏览（lightbox）
   遮罩层由脚本运行时建。沿用同一套色板：近黑遮罩 + hairline 描边，
   不引入阴影与新颜色。
   ══════════════════════════════════════════════════════════════════════ */
/* zoom-in 光标只在脚本挂载后出现：无 JS 时 SVG 图表点了没反应，
   显示放大光标是在骗用户（位图有 <a> 降级，不受此限） */
.prose .diagram {
  border-radius: 8px;
  transition: outline-color 0.15s;
  outline: 1px solid transparent;
  outline-offset: 8px;
}
.prose .diagram:hover,
.prose .diagram:focus-visible {
  outline-color: var(--hair);
}
.prose .imgLink {
  cursor: zoom-in;
}

html.lb-ready .prose .diagram {
  cursor: zoom-in;
}

html.lb-open {
  overflow: hidden;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--s8) var(--s7) 96px;
  /* 不用纯黑：留一点画布色，遮罩之下仍能感到页面存在 */
  background: rgba(10, 10, 10, 0.94);
}
.lightbox.on {
  display: flex;
}
.lbStage {
  width: 100%;
  height: 100%;
  overflow: auto;
  /* 内容小于视口时居中，大于视口时可滚动 —— flex 居中会把溢出边缘裁掉，
     故用 grid + place-items 配合 min-content 轨道 */
  display: grid;
  place-items: center;
  grid-auto-rows: min-content;
  scrollbar-width: thin;
}
.lbStage::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.lbStage::-webkit-scrollbar-thumb {
  background: var(--mid);
  border-radius: 9999px;
}
.lbStage::-webkit-scrollbar-track {
  background: transparent;
}
/* 位图放大后按原始像素显示 —— 火焰图原图 2048px 宽，正文里只有 680px，
   放大的意义正在于看清那些细节。超出视口时容器可滚动。 */
.lbImg {
  max-width: none;
  margin: auto;
  border: 1px solid var(--hair);
  border-radius: 8px;
}
/* SVG 是矢量，按视口等比撑开即可 */
.lbSvg {
  width: min(1200px, 92vw);
  height: auto;
  margin: auto;
}

.lbClose,
.lbNav {
  position: absolute;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--canvas);
  border: 1px solid var(--hair);
  border-radius: 9999px;
  color: var(--body);
  font-size: 18px;
  font-family: var(--mono);
  cursor: pointer;
  transition:
    color 0.15s,
    border-color 0.15s;
}
.lbClose:hover,
.lbNav:hover {
  color: var(--ink);
  border-color: var(--mid);
}
.lbClose {
  top: var(--s5);
  right: var(--s5);
}
.lbPrev {
  left: var(--s4);
  top: 50%;
  margin-top: -20px;
}
.lbNext {
  right: var(--s4);
  top: 50%;
  margin-top: -20px;
}
.lbNav[hidden] {
  display: none;
}

.lbBar {
  position: absolute;
  left: var(--s7);
  right: var(--s7);
  bottom: var(--s6);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--hair);
}
.lbCap {
  color: var(--body);
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 20px;
}
.lbIdx {
  flex: none;
  color: var(--sun);
}

@media (max-width: 768px) {
  .lightbox {
    padding: var(--s7) var(--s3) 88px;
  }
  .lbPrev {
    left: var(--s2);
  }
  .lbNext {
    right: var(--s2);
  }
  .lbBar {
    left: var(--s4);
    right: var(--s4);
    flex-direction: column;
    gap: var(--s1);
  }
}

/* ══════════════════════════════════════════════════════════════════════
   页脚
   ══════════════════════════════════════════════════════════════════════ */
footer {
  border-top: 1px solid var(--hair);
  padding: var(--s5) 0 var(--s7);
  display: flex;
  align-items: center;
  gap: var(--s4);
  justify-content: space-between;
  flex-wrap: wrap;
}
footer .l {
  display: flex;
  align-items: center;
  gap: var(--s2);
}

/* ══════════════════════════════════════════════════════════════════════
   响应式：单一断点 768px（与设计文档一致）
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1180px) {
  .hero {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s8);
  }
  .sundial {
    justify-self: start;
  }
  .sundial .anno {
    left: 0;
    top: calc(100% + 12px);
  }
}

@media (max-width: 960px) {
  :root {
    --rail-w: 0px;
  }
  .shell {
    grid-template-columns: minmax(0, 1fr);
  }
  main {
    grid-column: 1;
  }
  /* 侧栏改为顶部横条，不做汉堡菜单：5 个入口横排放得下 */
  .rail {
    position: static;
    width: auto;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--hair);
    padding: var(--s5) var(--s5);
    display: block;
  }
  .rail .formula {
    display: none;
  }
  /* 侧栏已是顶部横条，收起无意义：强制展开并隐藏按钮 */
  .railToggle {
    display: none;
  }
  html.rail-collapsed .railBody {
    display: block;
  }
  html.rail-collapsed .rail .markText {
    display: flex;
  }
  html.rail-collapsed .railTop {
    width: auto;
    overflow: visible;
  }
  html.rail-collapsed .rail .mark {
    justify-content: flex-start;
    margin-top: 0;
  }
  html.rail-collapsed .rail .helm {
    height: 34px;
  }
  html.rail-collapsed {
    --rail-w: 0px;
  }
  .vnav {
    margin-top: var(--s4);
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0 var(--s5);
  }
  .vnav a {
    border-top: 0;
    padding: var(--s2) 0;
  }
  .vnav a:last-child {
    border-bottom: 0;
  }
  .wrap {
    padding: 0 var(--s5);
  }
  .yearblock,
  .entryBody {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s5);
  }
  .yearblock .axis,
  .entryBody .side {
    position: static;
    display: flex;
    align-items: baseline;
    gap: var(--s4);
    max-height: none;
  }
  .yearblock .axis .ring {
    margin-top: 0;
  }
  .yearblock .axis .meta {
    margin-top: 0;
  }
  /* 目录在窄屏折叠为可展开块，避免挤占正文 */
  .entryBody .side {
    display: block;
  }
  .toc {
    border: 1px solid var(--hair);
    border-radius: 8px;
    padding: var(--s4) var(--s5);
  }
  .position {
    display: none;
  }
}

@media (max-width: 768px) {
  .hero {
    padding: var(--s7) 0 var(--s6);
  }
  .hero h1 {
    font-size: 40px;
    line-height: 44px;
    letter-spacing: -1px;
  }
  .pageHead h1,
  .entryHead h1 {
    font-size: 32px;
    line-height: 38px;
    letter-spacing: -0.6px;
  }
  .prose h2 {
    font-size: 26px;
    line-height: 34px;
  }
  .prose h3 {
    font-size: 20px;
    line-height: 28px;
  }
  /* 太阳按视口缩放，保持圆形与刻针关系 */
  .sundial {
    width: min(420px, calc(100vw - var(--s5) * 2));
    height: min(420px, calc(100vw - var(--s5) * 2));
  }
  .sundial .disc2 {
    inset: 13%;
  }
  .sundial .disc3 {
    inset: 36%;
  }
  .sundial .core .num {
    font-size: 64px;
    line-height: 64px;
    letter-spacing: -1.6px;
  }
  .sundial .legend {
    display: none;
  }
  .facts {
    grid-template-columns: repeat(2, auto);
    gap: var(--s4) var(--s6);
  }
  /* 索引行：日期与标签下沉一行，标题不再截断 */
  .row {
    grid-template-columns: 12px 48px minmax(0, 1fr);
    row-gap: var(--s2);
  }
  .row .t {
    white-space: normal;
    font-size: 16px;
    line-height: 24px;
  }
  .row .tags {
    grid-column: 2 / -1;
    flex-wrap: wrap;
  }
  .row .d {
    grid-column: 2 / -1;
    text-align: left;
  }
  .pnnav {
    grid-template-columns: 1fr;
  }
  .pn.next {
    text-align: left;
    border-left: 0;
    border-top: 1px solid var(--hair);
  }
  .prose pre {
    padding: var(--s3) var(--s4);
  }
  footer {
    padding-bottom: var(--s6);
  }
}

/* 打印：黑底不适合打印，唯一允许的浅色场景 */
@media print {
  .rail,
  .toc,
  .position,
  .pnnav,
  .seclabel,
  .sundial {
    display: none;
  }
  body,
  html {
    background: #fff;
    color: #000;
  }
  .shell,
  .entryBody {
    display: block;
  }
  .prose a {
    color: #000;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  * {
    transition: none !important;
  }
}
