/* 认知库 —— 手写样式。没有框架、没有 CDN、没有构建步骤。

   命题：这是一个思考的地方，不是管理笔记的地方。
   安静、有重量、像纸和墨。agent 的活动是这里唯一活着的东西。

   四条规矩：
   1. 纸与墨。暖白纸面，正文近黑不是纯黑。没有卡片、没有阴影、没有圆角滥用 ——
      分隔一律用发丝线，层级靠留白和字重。
   2. 两个强调色，各自只指一件事：
        蓝 = 留下的（你写下的判断、长出来的概念、当前所在、可交互）
        琥珀 = 带回来的（材料与笔记）和 agent 正在做的事（轨迹、正在思考的脉动）
      除此之外只用墨色。色彩是信号，不是装饰。
   3. 字是主材料。标题一律宋体、正文一律黑体 —— 这是中文排版里最稳的一组搭配，
      也是这一页想给人的东西：库说话的时候像书，材料本身还是屏上的字。
      正文按中文的阅读节奏排：行宽约 36 个汉字，行高 1.85。
   4. 空间有节奏：大空隙与紧密簇交替，不是到处均等的边距。

   字体：两份都是自托管的子集，没有 CDN，页面能离线打开。
     Newsreader（拉丁与数字，40KB）—— 给 display 定性格。
     CogSerif SC（中文，688KB）—— Noto Serif SC 的子集，见 fonts/README.md。
   中文落到系统字体会掉进黑体，一行宋一行黑是最难看的；所以中文这份按
   《GB2312 一级字表》切，常用字全覆盖，只有真正的生僻字才回退，
   而回退链里排的都是宋体 —— 掉下去也还是宋体。 */

/* ---------- 0. 字体 ---------- */

/* 只含拉丁字母、数字、常用标点。汉字不在这一份里，由下面的 CogSerif SC 接住 ——
   「10月6日」的 10 和 6 是 Newsreader，月日 是宋体，两份都是衬线，接得上。 */
@font-face {
  font-family: "Newsreader";
  src: url("/static/fonts/newsreader-latin.woff2?v=1") format("woff2-variations"),
       url("/static/fonts/newsreader-latin.woff2?v=1") format("woff2");
  font-weight: 350 700;
  font-style: normal;
  font-display: swap;
  /* 只声明实际拿到的字形范围：范围之外浏览器直接用回退字体，不必下载 */
  unicode-range: U+0020-007E, U+00A0-00AD, U+2009-200F, U+2018-201F,
                 U+2022, U+2026-2027, U+2030, U+2039-203A, U+2044,
                 U+20AC, U+2122, U+2190-2193, U+2212, U+2215;
}

/* 中文宋体：Noto Serif SC（思源宋体，SIL OFL）的中文子集，688KB。
   3985 个字：《GB2312 一级字表》3755 常用字 + 这个界面自己会用到的全部汉字与标点。
   为什么敢这么大 —— 实测这条链路（中国 → 这台 VPS）约 500KB/s，688KB 是 1.4 秒，
   而且只在第一次：文件名带版本号，之后由浏览器缓存接管。一级字表之外的字
   （生僻字、人名用字）不在里面，它们会往下掉到系统宋体，见 --font-display 的栈。

   一份静态 Medium 实例，却声明 400–700：告诉浏览器这一份就能撑起整个 display 档，
   别去合成假粗体（font-synthesis-weight 已经是 none，这是第二道保险）。
   宋体不靠字重分层级 —— 中文书里的层级是字号给的，不是粗细给的。 */
@font-face {
  font-family: "CogSerif SC";
  src: url("/static/fonts/cogserif-sc.woff2?v=1") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- 1. 令牌 ---------- */

:root {
  color-scheme: light dark;

  --paper: #faf8f3;        /* 纸面：暖白的极浅米色，比纯白耐看 */
  --paper-2: #f2efe6;      /* 凹下去的地方：hover、代码、输入框 */
  --paper-3: #eae6da;      /* 再深一层：选中、按下 */
  --ink: #1a1915;          /* 墨：带一点暖的近黑 */
  --ink-2: #4a4840;
  --muted: #63604f;        /* 次级文字：全部过 WCAG AA */
  --faint: #6f6c60;        /* 最小一号的字也得看得清 —— 不再是「浅到看不见」 */
  --rule: #e6e1d6;         /* 发丝线 */
  --rule-2: #cdc5b1;       /* 竖线。它是主线，要比发丝线站得住 */

  --mine: #1e3fa8;         /* 蓝 = 留下的（判断 / 概念） */
  --mine-soft: rgba(30, 63, 168, .08);
  --mine-line: rgba(30, 63, 168, .28);
  --agent: #9c5a05;        /* 琥珀 = 带回来的（材料 / 笔记） */
  --agent-soft: rgba(156, 90, 5, .09);
  --agent-line: rgba(156, 90, 5, .42);

  /* 版面即秤：首页那两个区域的纸色。它不是「在纸上刷了一块颜色」，
     是两种纸 —— 所以用实色而不是透明度：蓝叠在暖白纸上，一淡就成灰，
     把颜色本身调亮才留得住色相。 */
  --mine-field: #eff2fb;
  --agent-field: #faf3e9;

  --mark: rgba(30, 63, 168, .17);
  --mark-ink: #16307f;
  --danger: #a3342a;
  --danger-soft: rgba(163, 52, 42, .08);

  --on-solid: #fdfcf9;     /* 实心色块上的字 */

  /* 排版阶梯。display 与 micro 相差 5 倍以上 —— 窄区间没有戏剧性。 */
  --t-display: clamp(2.75rem, 1.6rem + 5.2vw, 3.875rem);  /* 44 → 62px */
  --t-h1: clamp(1.75rem, 1.1rem + 2.6vw, 2.25rem);        /* 28 → 36px */
  --t-h2: 1.3125rem;                                      /* 21px */
  --t-h3: 1.0625rem;                                      /* 17px */
  --t-body: 1.0625rem;                                    /* 17px */
  --t-sm: .875rem;                                        /* 14px */
  --t-xs: .75rem;                                         /* 12px */

  --lh-body: 1.85;
  --measure: 36em;

  --shell: 1060px;
  --shell-pad: 28px;       /* 页边。首页那两个区域要往外出血，得知道它多宽 */
  --gutter: 30px;          /* 脊柱到内容 */
  --spine-x: 5px;          /* 竖线在左侧的位置 */

  --ease: cubic-bezier(.22, .61, .36, 1);      /* 统一缓动：快出慢收 */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur: .18s;
  --dur-slow: .42s;

  /* 标题的字栈。拉丁与数字走 Newsreader，汉字走 CogSerif SC。
     后面那串全是宋体：CogSerif 里没有的字（生僻字）掉下来的时候，
     接住它的必须还是宋体 —— 掉进黑体就是一行两个字体，比不做这件事还糟。
     macOS/iOS 有 Songti SC，Windows 有 SimSun，Linux/VPS 上是 Noto Serif CJK。 */
  --font-display: "Newsreader", "CogSerif SC", "Iowan Old Style", Georgia,
                  "Songti SC", "Source Han Serif SC", "Noto Serif CJK SC",
                  "SimSun", "STSong", serif;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
             "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC",
             "Microsoft YaHei", "WenQuanYi Micro Hei", Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", "Courier New", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #131210;
    --paper-2: #1c1b18;
    --paper-3: #262420;
    --ink: #edeae2;
    --ink-2: #b5b1a6;
    --muted: #9a968a;
    --faint: #8a8779;
    --rule: #2a2823;
    --rule-2: #454136;

    --mine: #a8bcff;
    --mine-soft: rgba(168, 188, 255, .1);
    --mine-line: rgba(168, 188, 255, .36);
    --agent: #e5ae5c;
    --agent-soft: rgba(229, 174, 92, .11);
    --agent-line: rgba(229, 174, 92, .42);

    --mine-field: rgba(168, 188, 255, .085);
    --agent-field: rgba(229, 174, 92, .095);

    --mark: rgba(168, 188, 255, .22);
    --mark-ink: #e2e8ff;
    --danger: #e08375;
    --danger-soft: rgba(224, 131, 117, .1);

    --on-solid: #14130f;
  }
}

/* ---------- 2. 基础 ---------- */

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

html {
  /* 中文标点不要占满一个字宽；中西文之间自动留一点气口 */
  text-spacing-trim: space-first;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: var(--t-body)/var(--lh-body) var(--font-ui);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0; font-weight: 600; line-height: 1.3;
  letter-spacing: -.012em;
  text-wrap: balance;                    /* 标题不要孤字成行 */
}
h1, .display {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -.022em;
}
p { margin: 0; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
svg { display: block; }
img { max-width: 100%; }
time, .num { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); font-size: .9em; }

/* 中西文自动间距：正文里「把 LLM 当作」不用手打空格 */
.prose, .entry-sub, .lede, .task-prompt, .entry-title { text-autospace: normal; }

/* 焦点环：自定义，别用浏览器默认的。两层 —— 外圈纸色把环从背景里托出来 */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--mine);
  outline-offset: 2px;
  border-radius: 2px;
}
.on-dark:focus-visible, .btn:focus-visible { outline-color: var(--ink); }

::selection { background: var(--mark); color: var(--mark-ink); }

/* 滚动条也自己画：默认的那条和纸墨不是一套东西 */
* { scrollbar-width: thin; scrollbar-color: var(--rule-2) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--rule-2); border: 3px solid var(--paper); border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: var(--faint); }

.skip {
  position: absolute; left: -9999px; z-index: 60;
  background: var(--ink); color: var(--paper);
  padding: 10px 16px; font-size: var(--t-sm);
}
.skip:focus { left: 12px; top: 12px; }

.shell {
  width: 100%; max-width: var(--shell);
  margin: 0 auto; padding: 0 var(--shell-pad);
}

.muted { color: var(--muted); }
.link { color: var(--mine); }
.link:hover {
  text-decoration: underline;
  text-underline-offset: .2em; text-decoration-thickness: 1px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* 少量间距工具类：避免在模板里写 style="" */
.mt-md { margin-top: 34px; }
.mt-lg { margin-top: 48px; }
.section-gap { margin-top: 40px; }
.form-row { margin-top: 12px; }
.foot-note { margin-top: 16px; color: var(--muted); font-size: var(--t-sm); }

/* ---------- 3. 顶栏 ---------- */

.topbar {
  position: sticky; top: 0; z-index: 30;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
@supports (backdrop-filter: blur(1px)) {
  .topbar {
    background: color-mix(in srgb, var(--paper) 88%, transparent);
    backdrop-filter: saturate(140%) blur(12px);
  }
}

.topbar-in {
  display: flex; align-items: center; gap: 30px; height: 60px;
}

/* 标识：不画图形，靠字距和一条量尺站住。
   字标放在最后一位字的右边距会拖出一截空气，用等量的负 margin 收回来。 */
.brand {
  display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: 6px; white-space: nowrap; padding: 3px 0;
}
/* 字标和首页那个刊头是同一句话、同一种字 —— 标识认得出来，
   靠的不是图形，是这三个字在宋体里的样子 */
.wordmark {
  font-family: var(--font-display); font-weight: 500;
  font-size: 1.1875rem; line-height: 1.15;
  letter-spacing: .16em; margin-right: -.16em;
  transition: color var(--dur) var(--ease);
}
.brand:hover .wordmark { color: var(--mine); }

/* 量尺：字标上面那条按存量分段的横线。它是首页那把秤的小号 —— 蓝是你留下的，
   琥珀是它抓回来的，空库就是一条发丝线。颜色在这里是数据，不是装饰。
   放在字上面而不是下面：导航栏的当前页标记就是一条下划线，
   同一条基线上放两个同样的东西，读的人只会当成重复。 */
.gauge {
  display: flex; gap: 2px; height: 4px;
  width: 84px;                       /* 比字标略宽：读成尺，不读成下划线 */
  background: var(--rule);
}
.gauge i { display: block; height: 100%; }
.gauge .g-mine { background: var(--mine); }
.gauge .g-agent { background: var(--agent); }
.gauge .g-empty { flex: 1; background: var(--rule-2); }

.nav { display: flex; gap: 22px; font-size: var(--t-sm); }
.nav a {
  position: relative; color: var(--muted);
  padding: 18px 6px; margin: 0 -6px;
  transition: color var(--dur) var(--ease);
}
.nav a:focus-visible { outline-offset: -2px; }
.nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 14px;
  height: 1.5px; background: var(--mine);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-out);
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current] { color: var(--ink); }
.nav a[aria-current]::after { transform: scaleX(1); }

.search { position: relative; margin-left: auto; }
.search input {
  width: 200px; padding: 7px 34px 7px 12px;
  background: var(--paper-2); border: 1px solid transparent; border-radius: 3px;
  font-size: var(--t-sm);
  transition: width var(--dur-slow) var(--ease), background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.search input::placeholder { color: var(--muted); }
.search input:hover { background: var(--paper-3); }
.search input:focus {
  width: 264px; outline: none; background: var(--paper);
  border-color: var(--mine-line);
  box-shadow: 0 0 0 3px var(--mine-soft);
}
.search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.search kbd {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  font: var(--t-xs)/1.4 var(--font-mono); color: var(--muted);
  border: 1px solid var(--rule-2); border-radius: 3px; padding: 1px 5px;
  pointer-events: none;
}
.search:focus-within kbd { opacity: 0; }

/* 移动端底栏：桌面不存在 */
.tabbar { display: none; }

/* ---------- 4. 页脚 ---------- */

.foot {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  margin-top: 80px; padding-top: 20px; padding-bottom: 48px;
  border-top: 1px solid var(--rule);
  color: var(--muted); font-size: var(--t-xs);
}
/* 字重钉在 500：中文那一份只有 Medium 一档，拉丁那份是可变的，
   两边落在同一个字重上，中西混排才不会一段粗一段细 */
.foot .creed { font-family: var(--font-display); font-size: var(--t-sm); font-weight: 500; }
.foot a { color: var(--muted); transition: color var(--dur) var(--ease);
          display: inline-flex; align-items: center; min-height: 24px; }
@media (max-width: 720px) { .foot a { min-height: 44px; } }
.foot a:hover { color: var(--ink); }

/* ---------- 5. 通用零件 ---------- */

.page-head { padding: 52px 0 0; }
.page-head h1 { font-size: var(--t-h1); }
.page-head .lede {
  margin-top: 12px; max-width: 30em;
  color: var(--ink-2); font-size: var(--t-body); line-height: 1.75;
}

.pill {
  display: inline-block; font-size: var(--t-xs); line-height: 1.6;
  padding: 0 6px; border: 1px solid var(--rule-2); border-radius: 2px;
  color: var(--ink-2); white-space: nowrap; letter-spacing: .01em;
}
.pill-source { color: var(--agent); border-color: var(--agent-line); }
.pill-judgment { color: var(--mine); border-color: var(--mine-line); }

/* 成熟度：三种墨迹，不是一个色轮。种子是中空的，常青是实心的。 */
.status {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-sm); color: var(--ink-2); white-space: nowrap;
}
.status::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  border: 1px solid currentColor; background: none; flex: none;
  color: var(--mine);
}
.status[data-s="growing"]::before {
  background: linear-gradient(to right, currentColor 50%, transparent 50%);
}
.status[data-s="evergreen"]::before { background: currentColor; }
.status[data-s="seed"]::before { color: var(--faint); }
.status[data-s="running"]::before { background: var(--agent); border-color: var(--agent); }
.status[data-s="done"]::before { background: var(--mine); border-color: var(--mine); }
.status[data-s="error"]::before,
.status[data-s="cancelled"]::before { background: var(--danger); border-color: var(--danger); }

@media (prefers-reduced-motion: no-preference) {
  .status[data-s="running"]::before {
    animation: pulse-dot 1.6s var(--ease) infinite;
  }
  @keyframes pulse-dot {
    0%, 100% { opacity: 1; transform: scale(1) }
    50% { opacity: .35; transform: scale(.8) }
  }
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 20px; min-height: 44px;
  border: 1px solid var(--ink); border-radius: 3px;
  background: var(--ink); color: var(--paper);
  font-size: var(--t-sm); font-weight: 500; cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.btn:hover { background: var(--mine); border-color: var(--mine); color: var(--on-solid); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] {
  background: none; border-color: var(--rule-2); color: var(--faint);
  cursor: not-allowed; transform: none;
}

.btn-quiet {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; min-height: 36px;
  border: 1px solid var(--rule-2); border-radius: 3px;
  background: none; color: var(--ink-2); font-size: var(--t-sm); cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn-quiet:hover { color: var(--ink); border-color: var(--ink-2); }
.btn-quiet[disabled] { color: var(--faint); border-color: var(--rule); cursor: not-allowed; }

/* 提示条 */
.notice {
  margin: 22px 0; padding: 14px 18px;
  border: 1px solid var(--rule); border-left: 2px solid var(--faint);
  background: var(--paper-2);
  font-size: var(--t-sm); line-height: 1.7; color: var(--ink-2);
}
.notice-err { border-left-color: var(--danger); background: var(--danger-soft); }

/* ---------- 6. 首页：库的编排 ---------- */

.hero { padding: 60px 0 0; }
/* 报头：三个汉字放到 62px 就不是「标题」了，是刊头。放开字距让它们有空气，
   负 margin 把最后一个字的右边距收掉，右边缘才是齐的。 */
.hero h1 {
  font-size: var(--t-display);
  line-height: 1.06;
  /* 宋体的字身比黑体略窄，字距得比原来再放一点才不显挤 ——
     顺势放成刊头的分寸：三个字之间是空气，不是间隔 */
  letter-spacing: .13em;
  margin-right: -.13em;
  font-weight: 500;
}
.hero .lede {
  margin-top: 14px; max-width: 30em;
  color: var(--ink-2); font-size: var(--t-body); line-height: 1.8;
}

.hero-foot {
  margin-top: 16px; color: var(--muted); font-size: var(--t-sm);
}

/* —— 首页那个框 ——
   这个站的入口是和 agent 说话，不是浏览，所以它排在最上面：
   报头之下、秤之上，第一屏一定看得见。它是普通表单，没有 JS 也能提交。 */
.compose-hero { margin-top: 30px; }
.compose-hero textarea {
  display: block; width: 100%; min-height: 64px;
  padding: 16px 18px;
  border: 1px solid var(--rule-2); border-radius: 3px;
  background: var(--paper-2);
  font-size: 1.0625rem; line-height: 1.7; resize: none;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.compose-hero textarea::placeholder { color: var(--faint); }
.compose-hero textarea:focus {
  outline: none; background: var(--paper); border-color: var(--mine-line);
  box-shadow: 0 0 0 3px var(--mine-soft);
}
.compose-hero-foot {
  display: flex; align-items: center; gap: 14px; margin-top: 12px;
}
.compose-hero-foot select {
  padding: 8px 10px; min-height: 40px;
  border: 1px solid var(--rule-2); border-radius: 3px;
  background: var(--paper); font-size: var(--t-sm); color: var(--ink-2);
  cursor: pointer;
}
/* 按钮贴右：左边那半留给模型选择，它是这一行里唯一可以不被看见的东西 */
.compose-hero-foot .btn { margin-left: auto; }

/* —— 接着聊 ——
   框的正下方。它和那个框是同一件事的两半：开一件新的，或者接着旧的。
   **要一眼看出是能点的** —— 原先「历史」里那些行是纯文字，
   功能在、人找不到，等于没做。所以这里有底线、有 hover、有指向。 */
.resume {
  margin-top: 26px; padding-top: 14px;
  border-top: 1px solid var(--rule);
}
.resume-head { display: flex; align-items: baseline; gap: 18px; }
.resume-lab {
  flex: none; font-size: var(--t-xs); color: var(--muted);
  letter-spacing: .12em;
}
.resume-all {
  flex: none; margin-left: auto;
  font-size: var(--t-xs); color: var(--muted); text-decoration: none;
  border-bottom: 1px solid var(--rule-2); padding-bottom: 1px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.resume-all:hover { color: var(--ink); border-bottom-color: var(--ink); }
.resume-x {
  flex: none; display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--t-xs); color: var(--muted); text-decoration: none;
  transition: color var(--dur) var(--ease);
}
.resume-x:hover { color: var(--ink); }
.resume-x .status { font-size: var(--t-xs); }

.resume-list { list-style: none; margin: 8px 0 0; padding: 0; }
.resume-list li + li { border-top: 1px solid var(--rule); }
.resume-list a {
  display: flex; align-items: baseline; gap: 10px;
  padding: 8px 10px 8px 8px; border-radius: 3px;
  color: var(--ink-2); text-decoration: none;
  transition: background-color var(--dur) var(--ease);
}
.resume-list a:hover { background: var(--paper-2); }
/* 提示词是这一行里唯一要读的东西，给它剩下的全部宽度，别的都不许挤它 */
.resume-txt {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.resume-list time {
  flex: none; font-size: var(--t-xs); color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.resume-none { margin: 10px 0 0; font-size: var(--t-sm); color: var(--faint); }

/* 收支条：筛选之后只剩一股流，秤就没有意义了 —— 退回这条发丝线。
   蓝段是留下的（判断与概念），琥珀段是带回来的（材料与笔记）：
   这条系统的核心张力，就在这一条上。 */
.balance {
  display: flex; gap: 2px; height: 2px; margin-top: 30px;
  background: var(--rule);
}
.balance span { display: block; background: var(--mine); }
.balance .b-agent { background: var(--agent); }
.balance .b-empty { flex: 1; background: var(--rule-2); }
.balance-legend {
  display: flex; flex-wrap: wrap; gap: 4px 20px; margin-top: 14px;
  font-size: var(--t-sm); color: var(--muted);
}
.balance-legend a { display: inline-flex; align-items: baseline; gap: 7px; }
.balance-legend .swatch { align-self: center; }
.balance-legend a:hover { color: var(--ink); }
.balance-legend b {
  font-family: var(--font-display); font-weight: 500;
  font-size: 1.0625rem; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.balance-legend .swatch {
  width: 8px; height: 8px; flex: none; border-radius: 50%;
  background: var(--mine); transform: translateY(-1px);
}
.balance-legend .swatch-agent { background: var(--agent); }

/* 筛选条 */
.bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  margin: 44px 0 0;
}
.seg { display: flex; gap: 4px; }
.seg a {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 6px 11px; border: 1px solid transparent; border-radius: 3px;
  font-size: var(--t-sm); color: var(--muted);
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.seg a:hover { color: var(--ink); background: var(--paper-2); }
.seg a[aria-current] { color: var(--ink); border-color: var(--rule-2); }
.seg .n {
  color: var(--faint); font-size: var(--t-xs);
  font-family: var(--font-display); font-variant-numeric: tabular-nums;
}
.seg a[aria-current] .n { color: var(--muted); }

.sort { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: var(--t-sm); }
.sort select {
  padding: 6px 10px; min-height: 36px;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--paper); font-size: var(--t-sm); cursor: pointer;
  transition: border-color var(--dur) var(--ease);
}
.sort select:hover { border-color: var(--rule-2); }

/* —— 脊柱：日期分组 + 一条竖线 ——
   竖线用 padding 撑开而不是 margin：绝对定位的线只覆盖 padding box，
   用 margin 会在条目之间留出断口。 */
.days { list-style: none; margin: 0; padding: 0; }

.day { margin-top: 62px; }
.day:first-child { margin-top: 40px; }

.day-head {
  display: flex; align-items: baseline; gap: 14px;
  padding-bottom: 18px;
}
.day-n {
  order: 1;
  font-family: var(--font-display);
  font-size: 1.75rem; font-weight: 500; letter-spacing: -.02em;
  line-height: 1.1; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.day-w { order: 2; font-size: var(--t-xs); color: var(--muted); letter-spacing: .04em; }
/* 顺序：日期 · 星期 · ————线———— · 计数 */
.day-head::after {
  content: ""; order: 3; flex: 1; height: 1px;
  background: var(--rule); align-self: center;
}
.day-c {
  order: 4;
  font-size: var(--t-xs); color: var(--faint); white-space: nowrap;
}

.entries { list-style: none; margin: 0; padding: 0; }
.entry-li { position: relative; padding-left: var(--gutter); }
/* 竖线：一整条连着，条目之间不断 */
.entry-li::before {
  content: ""; position: absolute; left: var(--spine-x); top: 0; bottom: 0;
  width: 1px; background: var(--rule-2);
}
/* 最后一条下面线就收住，不拖着半截 */
.entry-li:last-child::before { bottom: auto; height: 46px; }
/* 节点：蓝是留下的（判断、概念），琥珀是带回来的（笔记、材料）。
   带回来的那两种收成一根横线 —— 它们不是你自己的痕迹。 */
.entry-li::after {
  content: ""; position: absolute; left: calc(var(--spine-x) - 2px); top: 36px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--mine);
}
.entry-li[data-kind="note"]::after,
.entry-li[data-kind="source"]::after {
  background: var(--agent); border-radius: 0; height: 1px; top: 38px;
}

.entry {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 32px; align-items: start;
  padding: 22px 0 24px;
  border-top: 1px solid var(--rule);
  margin-right: -14px; padding-right: 14px;
  transition: background-color var(--dur) var(--ease);
}
.entry-li:first-child .entry { border-top: 0; }

/* 条目标题是这一页的目录。宋体、Medium、字号比正文大一档 ——
   它不是「加粗的正文」，是书名。 */
.entry-title {
  font-family: var(--font-display);
  font-size: 1.25rem; font-weight: 500; line-height: 1.5;
  letter-spacing: -.01em; overflow-wrap: anywhere; max-width: 27em;
  transition: color var(--dur) var(--ease);
}
.entry-sub {
  margin-top: 7px; max-width: 34em;
  color: var(--muted); font-size: var(--t-sm); line-height: 1.7;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow-wrap: anywhere;
}
.entry-meta {
  display: flex; align-items: center; gap: 12px;
  color: var(--muted); font-size: var(--t-xs); white-space: nowrap;
  padding-top: .35em;
}
.entry:hover { background: var(--paper-2); }
.entry:hover .entry-title { color: var(--mine); }
.entry:focus-visible { outline-offset: -2px; }

/* 概念：知识的实体，比笔记稍微收一点 */
.entry-li[data-kind="concept"] .entry-title { font-size: 1.1875rem; }

/* 来源：agent 抓回来的原料。它必须明显弱于笔记，
   否则整个库看起来全是抓来的东西。 */
.entry-li[data-kind="source"] .entry-title {
  font-size: 1rem; font-weight: 400; color: var(--ink-2);
  font-family: var(--font-ui);
}
.entry-li[data-kind="source"] .entry-sub { font-size: var(--t-xs); max-width: 38em; color: var(--faint); }
.entry-li[data-kind="source"] .entry { padding-top: 18px; padding-bottom: 20px; }
/* 原料在列表里收成**两行以内**：标题一行，摘要一行。
   14 份材料各占四五行的话，整页就是一堵没有节奏的墙 ——
   而它们本来就只是原料，认得出来是哪一篇就够了，细节点进去看。 */
.entry-li[data-kind="source"] .entry-sub { -webkit-line-clamp: 1; }

/* 标题封顶。标题是拿来扫的，不是拿来读的 —— 模型偶尔会写一整句当标题，
   不封顶的话一条就占掉半个屏幕。
   ⚠️ 这里**不用 `-webkit-line-clamp`**：实测它会把盒子的高度算成两行，
   但第三行照旧画出来，于是标题压在下面的摘要上，两行字糊成一团。
   `max-height` + `overflow: hidden` 是笨办法，但它真的切。
   em 是相对自身字号算的，所以概念（1.1875rem）和材料（1rem）各按各的来。 */
.entry-li:not([data-kind="source"]) .entry-title {
  max-height: 3em;      /* 2 行 × line-height 1.5 */
  overflow: hidden;
}
.entry-li[data-kind="source"] .entry-title {
  max-height: 1.5em;    /* 1 行 */
  overflow: hidden;
}
.entry-li[data-kind="source"]::after { top: 30px; }
.entry-li[data-kind="source"]:hover .entry-title,
.entry-li[data-kind="source"] .entry:hover .entry-title { color: var(--agent); }

/* 笔记也是带回来的 —— 它和来源同色，但仍然是这一页最该读的东西：
   来源收小、变灰，笔记保持原来的字号与宋体标题。 */
.entry-li[data-kind="note"]:hover .entry-title,
.entry-li[data-kind="note"] .entry:hover .entry-title { color: var(--agent); }

/* 判断：用户自己写的那一条。它是这个库里唯一属于你的东西，给它蓝色。 */
.entry-li[data-kind="judgment"] .entry-sub { color: var(--ink-2); }

mark {
  background: var(--mark); color: var(--mark-ink);
  border-radius: 2px; padding: 0 1px;
}

.pager {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  margin-top: 44px; padding-top: 18px; border-top: 1px solid var(--rule);
  color: var(--muted); font-size: var(--t-sm);
}
.pager a { color: var(--ink-2); }
.pager a:hover { color: var(--mine); }

/* —— 库还薄的时候，列表也换一种排法 ——
   四条记录不该摆出四十条的密度。条目放开、日期放大、脊柱加深：
   同一份数据，这里读起来像一本薄书的目录，而不是一张流水账。
   来源仍然明显弱于笔记 —— 这一条走到哪都不能丢。 */
.is-thin .day { margin-top: 84px; }
.is-thin .day:first-child { margin-top: 60px; }
.is-thin .day-n { font-size: 2.375rem; }
.is-thin .entry { padding: 32px 0 34px; }
.is-thin .entry-title { font-size: 1.75rem; line-height: 1.4; }
.is-thin .entry-sub { margin-top: 10px; font-size: .9375rem; -webkit-line-clamp: 3; }
.is-thin .entry-li[data-kind="concept"] .entry-title { font-size: 1.625rem; }
.is-thin .entry-li[data-kind="source"] .entry-title { font-size: 1.25rem; }
.is-thin .entry-li[data-kind="source"] .entry-sub { font-size: var(--t-sm); }
.is-thin .entry-li[data-kind="source"] .entry { padding-top: 22px; padding-bottom: 24px; }
.is-thin .entry-li::before { background: var(--ink-2); }
.is-thin .entry-li::after { top: 44px; width: 6px; height: 6px; left: calc(var(--spine-x) - 2.5px); }
.is-thin .entry-li[data-kind="source"]::after { top: 36px; }
.is-thin .entry-li:last-child::before { height: 60px; }

/* ---------- 6b. 版面即秤 ----------

   秤不再是一根摆在页面上的条 —— 它就是页面的结构。
   首页按作者把库劈成两个区域：「留下的」在左，「带回来的」在右，
   **两个区域的宽度就是两者的存量之比**。两栏的顶边是两条实心量尺，
   接起来正好是完整的一条，断口就是比例；那条断口往下落成一条折痕，
   把整页分成两半。留下来的多，蓝就一直铺到最右边；带回来的多，
   琥珀接管。这不是装饰，是这个产品独有的、会随使用长出来的版面。

   两个数字都靠在断口上：像天平两端的东西落在支点上，谁多谁少，
   看的是支点两边那两条量尺各有多长。宽度在模板里算好（有内容的那栏
   最少 26%，空着的那栏只要放得下一个数字，可以窄到 12%）——
   所以「一条都没有」反而量得出最悬殊的那一次。 */

.fields {
  --fpad: 26px;
  display: grid;
  grid-template-columns: minmax(0, var(--a)) minmax(0, var(--b));
  grid-template-rows: auto 1fr;
  position: relative;
  /* 两个区域往外出血到页边之外：它们得像版面的骨架，不像一块贴上去的卡片。
     内边距把字拉回和报头同一条竖线上。 */
  margin: 30px calc(-1 * var(--fpad)) 0;
}
/* 折痕：从量尺的断口一直落到脚底 —— 断在哪儿，一眼看得见 */
.fields::before {
  content: ""; position: absolute; top: 3px; bottom: 0; left: var(--a);
  width: 1px; background: var(--ink-2);
}
.fhead-mine  { grid-area: 1 / 1; }
.fhead-agent { grid-area: 1 / 2; }
.fbody-mine  { grid-area: 2 / 1; }
.fbody-agent { grid-area: 2 / 2; }

/* 两栏的头。量尺就是它的上边框，宽度天然等于这一栏的宽度。
   左边的头靠右站、右边的头靠左站，两个数字都贴在断口上。

   梁现在有两个读数。宽度是存量之比 —— 那是平的多数时候量不出什么
   （2 比 2）。所以梁还分实虚：**已经缝进这个库里的那一截是实笔，
   还散着的那一截收成一根发丝线**。梁从支点往外长，中缝是根，
   越往外越虚 —— 两栏的实笔都贴在断口上，断口才是这杆秤立住的地方。
   一个读数看宽度，一个读数看梁的粗细；都不需要多画一根线。 */
.fhead {
  display: flex; flex-direction: column;
  position: relative;
  min-height: 166px;
  padding: 25px var(--fpad) 24px;
  transition: background-color var(--dur) var(--ease);
}
/* 拿不到实虚数据时（模板里没有那截梁）退回原来那根实心量尺 —— 少一个读数，
   但秤还是完整的。:has 不认的浏览器会整条丢掉，正好也退回原样。 */
.fhead:not(:has(> .beam)) { border-top: 3px solid var(--mine); padding-top: 22px; }
.fhead-agent:not(:has(> .beam)) { border-top-color: var(--agent); }

.beam { position: absolute; left: 0; right: 0; top: 0; height: 3px; }
.beam::before,
.beam::after { content: ""; position: absolute; }
/* 实笔：缝上了的那一截，是一条整线 */
.beam::before { top: 0; bottom: 0; background: var(--mine); }
/* 虚笔：还没缝上的一截，同样一段梁，收成一根点线。
   点线本来就是「一段一段、还没连起来」—— 这里不是拿线型做花样，
   是线型本来就说这件事。 */
.beam::after {
  top: 1px; bottom: 1px; background-color: transparent;
  background-image: repeating-linear-gradient(to right,
      var(--mine) 0 3px, transparent 3px 6px);
}
/* 左栏的支点在右（中缝），右栏的支点在左 —— 实笔一律贴着支点 */
.fhead-mine  .beam::before { right: 0; width: var(--solid, 100%); }
.fhead-mine  .beam::after  { left: 0; right: var(--solid, 100%); }
.fhead-agent .beam::before { left: 0;  width: var(--solid, 100%); }
.fhead-agent .beam::after  { right: 0; left: var(--solid, 100%); }
.fhead-agent .beam::before { background: var(--agent); }
.fhead-agent .beam::after {
  background-image: repeating-linear-gradient(to right,
      var(--agent) 0 3px, transparent 3px 6px);
}

.fhead-agent { align-items: flex-start; }
.fhead-mine  { align-items: flex-end; text-align: right; }
/* 底色接成一片：头就是栏的上端，中间不能断开 */
.fhead-mine, .fbody-mine   { background: var(--mine-field); }
.fhead-agent, .fbody-agent { background: var(--agent-field); }
/* 悬停时往自己的颜色里再走一步，不换成纸色 —— 一换，这一栏就断了 */
.fhead-mine:hover  { background: color-mix(in srgb, var(--mine) 7%, var(--mine-field)); }
.fhead-agent:hover { background: color-mix(in srgb, var(--agent) 7%, var(--agent-field)); }
.fbody-mine .entry:hover  { background: color-mix(in srgb, var(--mine) 6%, var(--mine-field)); }
.fbody-agent .entry:hover { background: color-mix(in srgb, var(--agent) 6%, var(--agent-field)); }

/* 数字钉在顶上，两行说明落在底下：中间那截空气是量出来的，不是排出来的 */
.fnum {
  display: block; margin-bottom: auto;
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 1.5rem + 2.6vw, 3.25rem);
  font-weight: 500; line-height: .95;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  color: var(--mine);
}
.fhead-agent .fnum { color: var(--agent); }
/* 梁的读数。数字说这一边有多少，这一行说其中多少已经缝进来了 ——
   两边一样多的时候（2 比 2），就靠它把对称破开。 */
.fstate {
  display: block; margin-top: 9px;
  font-size: var(--t-sm); color: var(--ink-2);
}
.flab {
  display: block; margin-top: 14px;
  font-size: var(--t-xs); letter-spacing: .02em; color: var(--ink-2);
}
/* 「留下的 / 带回来的」—— 这两句是这一栏的定语，跟着上面的数字走宋体，
   和它们下面的条目连成同一种声音 */
.fwho {
  display: block; margin-top: 3px; font-size: var(--t-sm);
  color: var(--muted);
  font-family: var(--font-display); font-weight: 500;
}

/* 数据多起来，头收一档，构图的力气留给条目 */
body:not(.is-thin) .fhead { min-height: 134px; }
body:not(.is-thin) .fnum { font-size: clamp(1.75rem, 1.2rem + 1.5vw, 2.25rem); }
body:not(.is-thin) .flab { margin-top: 12px; }
body:not(.is-thin) .fstate { margin-top: 7px; }

.fbody {
  container-type: inline-size;
  padding: 4px var(--fpad) 38px;
}
/* 「留下的」那一股通常短得多 —— 4 条对你 19 条，右边还在往下长的时候，
   左边早就空了，往下滚三千像素全是白。让它跟着滚：
   这一栏的内容贴在顶上走，你读到哪儿，你的那几条就在旁边。
   底色不跟着动（它在网格行上），所以那一栏仍然是完整的一整片。 */
.fbody-mine .days { position: sticky; top: 88px; }
.fempty, .fempty-cta {
  color: var(--muted); font-size: var(--t-sm); line-height: 1.75;
  max-width: 20em;
}
/* 空的那一栏只放得下几个字 —— 话要短，而且要跟这一栏的头对齐 */
.fempty-cta { margin-top: 10px; }
.fbody-mine .fempty, .fbody-mine .fempty-cta { margin-left: auto; text-align: right; }
.fempty-cta .link { white-space: nowrap; }

/* —— 栏内的编排：栏比整页窄，装置要跟着收 —— */
.fields .day { margin-top: 46px; }
.fields .day:first-child { margin-top: 10px; }
.fields .entry { grid-template-columns: minmax(0, 1fr); gap: 2px 30px; }
.fields .entry-title { font-size: 1.1875rem; line-height: 1.5; }
.fields .entry-sub { -webkit-line-clamp: 3; }
.fields .entry-meta { padding-top: 10px; gap: 10px; flex-wrap: wrap; }
.fields .entry-li[data-kind="concept"] .entry-title { font-size: 1.125rem; }
.fields .entry-li[data-kind="source"] .entry-title { font-size: 1rem; }
.fields .entry-li[data-kind="source"] .entry-sub { font-size: var(--t-xs); }
.fields .entry-li::before { background: var(--rule-2); }
.fields .entry-li::after { top: 30px; }
.fields .entry-li[data-kind="source"]::after { top: 26px; }
.fields .entry-li:last-child::before { height: 42px; }

/* 栏够宽的时候，元信息回到标题右侧的那一列 —— 一个窄栏里它是挤，宽栏里它是气口 */
@container (min-width: 560px) {
  .fields .entry { grid-template-columns: minmax(0, 1fr) auto; }
  .fields .entry-meta { padding-top: .35em; gap: 12px; flex-wrap: nowrap; }
}

/* 栏窄到只够放下一行日期的时候，日期头里的东西要按重要性依次让位：
   先让星期，再让日期和计数的字号。日期头溢出过一次 —— 26% 那一栏在 768px
   上只剩 154px，三个 nowrap 的东西加起来比它还宽。 */
@container (max-width: 300px) {
  .fields .day-w { display: none; }
  .fields .day-head { gap: 10px; }
}
@container (max-width: 250px) {
  .fields .day-n, .is-thin .fields .day-n { font-size: 1.5rem; }
  .fields .day-c { font-size: 11px; }
}

/* 薄库：条目放开、日期放大，但幅度比整页时收一档 —— 一栏只有半页宽 */
.is-thin .fields .day { margin-top: 66px; }
.is-thin .fields .day:first-child { margin-top: 14px; }
.is-thin .fields .day-n { font-size: 1.875rem; }
.is-thin .fields .entry { padding: 26px 0 28px; }
.is-thin .fields .entry-title { font-size: 1.4375rem; line-height: 1.45; }
.is-thin .fields .entry-sub { margin-top: 9px; font-size: .875rem; }
.is-thin .fields .entry-li[data-kind="concept"] .entry-title { font-size: 1.375rem; }
.is-thin .fields .entry-li[data-kind="source"] .entry-title { font-size: 1.125rem; }
.is-thin .fields .entry-li[data-kind="source"] .entry-sub { font-size: var(--t-sm); }
.is-thin .fields .entry-li[data-kind="source"] .entry { padding-top: 20px; padding-bottom: 22px; }
.is-thin .fields .entry-li::before { background: var(--ink-2); }
.is-thin .fields .entry-li::after { top: 38px; width: 6px; height: 6px; left: calc(var(--spine-x) - 2.5px); }
.is-thin .fields .entry-li[data-kind="source"]::after { top: 32px; }
.is-thin .fields .entry-li:last-child::before { height: 54px; }

/* 收尾：最后一条下面不该是一片白。这个位置留给「这里在长什么」——
   一段话，一个入口，不是一条横幅。 */
.grow {
  margin-top: 76px; padding-top: 26px;
  border-top: 1px solid var(--ink);
  max-width: 34em;
}
/* 两个区域下面，收尾的话单独起一行 —— 它不属于任何一边 */
.grow-split { margin-top: 88px; }
.grow h2 {
  font-family: var(--font-display);
  font-size: 1.625rem; font-weight: 500; letter-spacing: -.02em;
  margin-bottom: 12px;
}
.grow p { color: var(--ink-2); font-size: var(--t-body); line-height: 1.8; }
.grow-cta { margin-top: 16px; color: var(--muted); font-size: var(--t-sm); }

/* ---------- 7. 空态 / 骨架 / 错误 ---------- */

.empty {
  margin-top: 46px; padding: 52px 0 56px;
  border-top: 1px solid var(--rule);
  max-width: 34em;
}
.empty h2 {
  font-family: var(--font-display);
  font-size: 1.625rem; font-weight: 500; color: var(--ink);
  letter-spacing: -.02em; margin-bottom: 12px;
}
.empty p { color: var(--ink-2); font-size: var(--t-body); line-height: 1.8; }
.empty .cta { margin-top: 24px; display: flex; gap: 12px; flex-wrap: wrap; }

/* 骨架屏：加载时给形状，不给转圈 */
.skeleton { display: block; }
.sk {
  height: 12px; background: var(--paper-2); border-radius: 2px;
  margin: 14px 0;
}
.sk-t { height: 18px; width: 46%; }
.sk-s { width: 82%; }
.sk-m { width: 28%; }
@media (prefers-reduced-motion: no-preference) {
  .sk { animation: sk-fade 1.5s var(--ease) infinite; }
  @keyframes sk-fade { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }
}

.oops { padding: 60px 0 0; max-width: 34em; }
.oops h1 { font-size: var(--t-h1); margin-bottom: 16px; }

/* ---------- 8. 详情页 ---------- */

.doc-layout {
  display: grid; grid-template-columns: minmax(0, 1fr) 216px;
  gap: 64px; align-items: start;
  padding: 46px 0 0;
}

.doc-head { padding-bottom: 26px; border-bottom: 1px solid var(--ink); }
.doc-head h1 {
  font-size: var(--t-h1); font-weight: 500;
  margin: 16px 0 14px; line-height: 1.28; letter-spacing: -.005em;
  overflow-wrap: anywhere;
}
.doc-meta {
  display: flex; align-items: center; gap: 8px 16px; flex-wrap: wrap;
  color: var(--muted); font-size: var(--t-sm);
}
.doc-meta time { font-variant-numeric: tabular-nums; }
.doc-meta a { color: var(--mine); }
.doc-meta a:hover {
  text-decoration: underline;
  text-underline-offset: .2em; text-decoration-thickness: 1px;
}
.doc-meta .dot { color: var(--faint); }

.doc-body { padding-top: 34px; }

/* 元信息栏：桌面在右侧，移动端折叠到正文之后（见响应式一节） */
.rail { position: sticky; top: 88px; font-size: var(--t-sm); }
.rail h2 {
  font-size: var(--t-xs); font-weight: 500; color: var(--muted);
  letter-spacing: .06em; margin-bottom: 12px;
}
.rail dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 16px; margin: 0; }
.rail dt { color: var(--faint); white-space: nowrap; }
.rail dd { margin: 0; color: var(--ink-2); overflow-wrap: anywhere; }
.rail dd a { color: var(--mine); }
.rail .tags { display: flex; flex-wrap: wrap; gap: 5px; }
.rail nav { margin-top: 30px; }
.rail .toc ul { list-style: none; margin: 0; padding: 0; line-height: 1.75; }
.rail .toc ul ul { padding-left: 12px; }
.rail .toc a { color: var(--ink-2); display: inline-block; padding: 2px 0; }
.rail .toc a:hover { color: var(--mine); }

.related { margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--rule); }
.related h2 {
  font-size: var(--t-xs); color: var(--muted); font-weight: 500;
  letter-spacing: .06em; margin-bottom: 16px;
}
.related ul { list-style: none; margin: 0; padding: 0; }
.related li {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline; gap: 12px; padding: 9px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-sm);
}
.related li:last-child { border-bottom: 0; }
.related li a {
  color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.related li a:hover { border-bottom-color: var(--mine-line); color: var(--mine); }
.related .rel { color: var(--faint); font-size: var(--t-xs); }

/* —— 我的判断：这个页面存在的理由 ——
   判断是独立文档（judgments/），一条文档可以有好几条 —— 你会改主意，
   所以这里是**一列**，不是一格可以覆盖的字段。每条都是你的痕迹，用蓝色；
   它和正文不是一回事，所以另起一节，排在最下面。 */
.judgments {
  margin-top: 3.4em; padding-top: 26px;
  border-top: 1px solid var(--rule);
  max-width: 34em;
  scroll-margin-top: 84px;    /* 从锚点跳过来时别贴到顶栏上 */
}
.judgment-label {
  display: block; font-size: var(--t-xs); font-weight: 500;
  letter-spacing: .1em; color: var(--mine);
  margin-bottom: 10px;
}
.judgment-label::before {
  content: ""; display: inline-block; vertical-align: middle;
  width: 12px; height: 1px; background: var(--mine); margin-right: 8px;
}
.judgment {
  margin: 0 0 22px;
  padding: 2px 0 2px 20px;
  border-left: 3px solid var(--mine);
}
.judgment .prose { font-size: var(--t-body); line-height: 1.85; max-width: 31em; }
.judgment .prose > *:last-child { margin-bottom: 0; }
/* 时间就是那一页的入口：判断是独立的一条，点开看它自己 */
.judgment-meta {
  margin-top: 10px; font-size: var(--t-xs);
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px;
}
/* 「改」和「删」跟在时间后面 —— 同一行小字，不抢判断本身的注意力。
   判断是能改的：打错一个字不该逼人去改文件。 */
.judgment-meta .judgment-edit { display: inline; }
.judgment-meta .judgment-edit summary {
  display: inline; cursor: pointer; list-style: none;
  color: var(--faint);
  border-bottom: 1px solid var(--rule); padding-bottom: 1px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.judgment-meta .judgment-edit summary::-webkit-details-marker { display: none; }
.judgment-meta .judgment-edit summary:hover { color: var(--mine); border-color: var(--mine-line); }
.judgment-meta .judgment-edit[open] summary { display: none; }
.judgment-meta .judgment-edit .judgment-form { margin-top: 12px; }
.judgment-del { display: inline; }
.link-quiet {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--faint); font-size: inherit;
  border-bottom: 1px solid transparent; padding-bottom: 1px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.link-quiet:hover { color: var(--danger); border-color: var(--danger); }

.judgment-meta a {
  color: var(--faint);
  border-bottom: 1px solid var(--rule); padding-bottom: 1px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.judgment-meta a::after { content: " →"; }
.judgment-meta a:hover { color: var(--mine); border-color: var(--mine-line); }

/* 还没写过判断：不要一个「卡片」，要一条**能写字的线**。
   已经写下的判断在正文里是用一条蓝色竖线标的（见 .judgment），
   那么写它的地方就用同一条线 —— 输入和产出看起来是同一个东西，
   只不过其中一个还没写字。
   ⚠️ 这里原来是个带边框和蓝底的方盒子，实测和全站的语言对不上：
   整页都是发丝线和开放的文字，只有这一块像个贴上去的控件。
   这一节仍然必须**真能写**（它曾经只是一句「写进 xxx.md 的 ## 我的判断 一节」，
   那是把给 agent 的 schema 贴到了人脸上）。 */
.judgments.is-empty { max-width: 34em; }
.judgments.is-empty .judgment-label { margin-bottom: 14px; }
.judgment-form { margin-top: 16px; }
/* 判断是**散文**，所以用正文那一支笔、那个字号 —— 不是表单控件。
   左边那条竖线和 .judgment 用同一条，写和读在视觉上是同一件事。 */
.judgment-form textarea {
  display: block; width: 100%; max-width: 31em;
  font-family: var(--font-display); font-size: var(--t-body); line-height: 1.85;
  color: var(--ink); background: transparent;
  border: 0; border-left: 3px solid var(--mine-line); border-radius: 0;
  padding: 4px 0 4px 20px; min-height: 5.6em; resize: vertical;
  transition: border-color var(--dur) var(--ease);
}
.judgment-form textarea::placeholder { color: var(--faint); }
.judgment-form textarea:hover { border-left-color: var(--mine); }
/* 焦点环用软蓝：一圈实蓝会把这条发丝线压过去，而整页的分寸都在发丝上 */
.judgment-form textarea:focus-visible {
  outline: 2px solid var(--mine-soft); outline-offset: 3px;
  border-left-color: var(--mine);
}
.judgment-actions {
  display: flex; align-items: center; gap: 12px; margin-top: 10px; flex-wrap: wrap;
}
.judgment-hint { color: var(--faint); font-size: var(--t-xs); }

/* 判断自己那一页：标题下说清它判断的是谁 */
.doc-about {
  margin: -4px 0 14px; font-size: var(--t-sm); color: var(--muted);
}
.doc-about a { color: var(--mine); }
.doc-about a:hover {
  text-decoration: underline;
  text-underline-offset: .2em; text-decoration-thickness: 1px;
}

/* ---------- 9. 正文排版 ---------- */

.prose {
  max-width: var(--measure);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  overflow-wrap: anywhere;
  text-wrap: pretty;
}
.prose > *:first-child { margin-top: 0; }
.prose h2, .prose h3, .prose h4 {
  margin: 2.3em 0 .6em; letter-spacing: -.01em; text-wrap: balance;
  scroll-margin-top: 80px;
}
/* 正文里的小节标题也走宋体。理由和条目标题一样：中文书里「标题」是一种
   字体身份，不是「加粗的正文」。h4 留着黑体 —— 它是第四级，
   再往下一档就该是正文自己的重音，不是标题了。 */
.prose h2, .prose h3 {
  font-family: var(--font-display); font-weight: 500;
}
.prose h2 { font-size: var(--t-h2); }
.prose h3 { font-size: var(--t-h3); }
.prose h4 { font-size: 1rem; color: var(--ink-2); }
.prose h2 + p, .prose h3 + p { margin-top: 0; }
.prose p { margin: 0 0 1.1em; }
.prose ul, .prose ol { margin: 0 0 1.1em; padding-left: 1.4em; }
.prose li { margin: .3em 0; }
.prose li::marker { color: var(--faint); }
.prose blockquote {
  margin: 1.6em 0; padding: .1em 0 .1em 20px;
  border-left: 1px solid var(--rule-2); color: var(--ink-2);
}
.prose blockquote p:last-child { margin-bottom: 0; }
.prose a {
  color: var(--mine);
  text-decoration: underline; text-decoration-color: var(--mine-line);
  text-underline-offset: .2em; text-decoration-thickness: 1px;
  transition: text-decoration-color var(--dur) var(--ease);
}
.prose a:hover { text-decoration-color: var(--mine); }
.prose strong { font-weight: 600; }
.prose code {
  font-family: var(--font-mono); font-size: .86em;
  background: var(--paper-2); padding: .12em .38em; border-radius: 2px;
  overflow-wrap: anywhere;
}
.prose pre {
  margin: 0 0 1.3em; padding: 15px 17px; overflow-x: auto;
  background: var(--paper-2); border: 1px solid var(--rule);
  font-size: .8125rem; line-height: 1.7;
}
.prose pre code { background: none; padding: 0; font-size: 1em; }
.prose hr { margin: 2.4em 0; border: 0; border-top: 1px solid var(--rule); }
.prose table {
  display: block; width: 100%; overflow-x: auto; margin: 0 0 1.3em;
  border-collapse: collapse; font-size: var(--t-sm);
}
.prose th, .prose td {
  padding: 8px 13px; border-bottom: 1px solid var(--rule); text-align: left;
}
.prose th { color: var(--ink-2); font-weight: 500; }

/* ---------- 10. 任务页 ---------- */

.compose {
  margin-top: 34px;
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink);
  background: var(--paper-2);
  padding: 6px 20px 0;
  transition: background-color var(--dur) var(--ease);
}
.compose:focus-within { background: var(--paper); }
.compose textarea {
  display: block; width: 100%; min-height: 96px; padding: 16px 0 8px;
  border: 0; background: none; resize: vertical;
  font-size: 1.0625rem; line-height: 1.8;
}
.compose textarea:focus { outline: none; }
.compose textarea::placeholder { color: var(--faint); }
.compose-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 14px;
  padding: 12px 0 14px; border-top: 1px solid var(--rule);
}
.compose-foot select {
  padding: 8px 10px; min-height: 40px;
  border: 1px solid var(--rule-2); border-radius: 3px;
  background: var(--paper); font-size: var(--t-sm); color: var(--ink-2); cursor: pointer;
}

.hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.hints button {
  padding: 9px 14px; min-height: 38px;
  border: 1px dashed var(--rule-2); border-radius: 3px;
  background: none; color: var(--muted); font-size: var(--t-sm); cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              border-style var(--dur) var(--ease);
}
.hints button:hover { color: var(--mine); border-color: var(--mine-line); border-style: solid; }

.task-list { margin-top: 56px; }
.task-list h2, .cols h2, .answer-bar h2, .usage-sub {
  font-size: var(--t-xs); font-weight: 500; color: var(--muted);
  letter-spacing: .06em; padding-bottom: 12px; border-bottom: 1px solid var(--rule);
}
.task-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline; gap: 16px;
  padding: 14px 0; border-bottom: 1px solid var(--rule);
  font-size: var(--t-sm);
  transition: color var(--dur) var(--ease);
}
.task-row .txt {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink);
}
.task-row time { color: var(--faint); font-size: var(--t-xs); white-space: nowrap; }
/* 这一行点得进去 —— 而且点进去就是**接着聊**，不是看一份报告。
   原先只有 hover 变蓝，等于把「能点」这件事藏起来：静态看过去
   它就是三行灰字，用户的原话是「找不到之前的任务」。
   箭头沿用全站既有那个约定（见 .judgment-meta a::after），不新造符号。 */
.task-row time::after {
  content: " →"; color: var(--rule-2);
  transition: color var(--dur) var(--ease);
}
.task-row:hover time::after { color: var(--mine); }
/* 第三列：跑了几轮 + 什么时候。轮数在一段对话超过一轮时才写 */
.task-row .when {
  display: inline-flex; align-items: baseline; gap: 12px; white-space: nowrap;
}
.task-row .when .num { color: var(--muted); font-size: var(--t-xs); }
.task-row:hover .txt { color: var(--mine); }

.task-head { padding: 44px 0 0; }
.task-prompt {
  max-width: 30em;
  font-family: var(--font-display);
  font-size: var(--t-h1); font-weight: 500; line-height: 1.35;
  letter-spacing: -.02em; overflow-wrap: anywhere;
}
.task-meta {
  display: flex; align-items: center; gap: 10px 18px; flex-wrap: wrap;
  margin-top: 16px; color: var(--muted); font-size: var(--t-sm);
}

/* —— 轨迹：全站唯一该有生命感的地方 ——
   一条琥珀色的竖线把「一串有先后的动作」画出来。整条轨迹只有一个 <ol>，
   线才能从第一轮连到最后一轮。
   间距一律用 padding 不用 margin：绝对定位的线只覆盖 padding box。

   它关在一个**固定高度的框**里自己滚：跑二十轮，页面的长度也不变 ——
   新事件滚的是框，不是整页。框外下面是这一轮的结果（.answer），
   那是结果，不该跟着过程一起滚走。 */
.rounds {
  /* 高度封顶，不是钉死：跑二十轮它就停在 600px 自己滚，页面不再跟着长；
     但只跑了一轮的时候，它不硬撑着一块空地方 —— 那样结果会被顶到屏幕外，
     正好是「别把交付挤下去」要避免的事。 */
  max-height: min(62vh, 600px);
  min-height: 180px;
  overflow-y: auto;
  overflow-x: hidden;          /* 块外面的负边距别在框里顶出一条横滚 */
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}
/* 上下两条渐隐：这一头还有内容没露出来的时候，字是淡下去的，不是被切断的。
   画在滚动容器外面（里面的会跟着滚），由 app.js 按滚动位置开关。 */
.rounds-wrap { position: relative; margin-top: 34px; }
.rounds-wrap::before,
.rounds-wrap::after {
  content: ""; position: absolute; left: 0; right: 0; height: 44px;
  pointer-events: none; opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.rounds-wrap::before {
  top: 0; background: linear-gradient(to bottom, var(--paper), transparent);
}
.rounds-wrap::after {
  bottom: 0; background: linear-gradient(to top, var(--paper), transparent);
}
.rounds-wrap.can-up::before { opacity: 1; }
.rounds-wrap.can-down::after { opacity: 1; }
.trace { list-style: none; margin: 0; padding: 0; }

.ev, .round-head { position: relative; padding-left: 38px; }
.ev::before, .round-head::before {
  content: ""; position: absolute; left: 11px; top: 0; bottom: 0;
  width: 1px; background: var(--agent-line);
}
/* 最后一个节点下面不拖半截线（对话块也可能是最后一个） */
.trace > li:last-child::before { bottom: auto; height: 13px; }

/* 轮次：这一页的章节号。数字交给衬线体放到 28px —— 一列 12px 的日志
   是没法读成文章的，先得有章节的尺度。 */
.round-head {
  display: flex; align-items: baseline; gap: 14px;
  padding-top: 46px; padding-bottom: 18px;
  font-size: var(--t-xs); color: var(--faint);
  letter-spacing: .04em;
}
.trace > .round-head:first-child { padding-top: 4px; }
.round-tag { display: inline-flex; align-items: baseline; gap: 2px; }
.round-k, .round-w { color: var(--faint); letter-spacing: .1em; }
.round-n {
  font-family: var(--font-display);
  font-size: 1.75rem; font-weight: 500; line-height: 1;
  letter-spacing: -.02em; color: var(--ink);
  font-variant-numeric: tabular-nums;
  margin: 0 3px;
  transition: color var(--dur) var(--ease);
}
/* 目录里跑到哪一轮了，这里也标一下 —— 长轨迹里这是唯一的定位点 */
.round-head::after {
  content: ""; order: 2; flex: 1; height: 1px; background: var(--rule);
  align-self: center;
}
.round-head .spent {
  order: 3; white-space: nowrap;
  font-family: var(--font-display); font-size: var(--t-sm); font-weight: 500;
  font-variant-numeric: tabular-nums; color: var(--muted);
}

.ev { padding-bottom: 22px; }
.ev-dot {
  position: absolute; left: 8px; top: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--rule-2);
}
.ev-warn .ev-dot { background: var(--paper); box-shadow: inset 0 0 0 2px var(--agent); }
.ev-err .ev-dot { background: var(--danger); box-shadow: none; }

.ev-name {
  font-family: var(--font-mono); font-size: .8438rem; color: var(--ink);
  overflow-wrap: anywhere; line-height: 1.7;
}
.ev-note { margin-top: 3px; color: var(--muted); font-size: var(--t-sm); line-height: 1.7; }
.ev-err .ev-note { color: var(--danger); }

/* —— 工具调用：块级事件 ——
   这一页不是拿来看日志的，是拿来看一个心智怎么工作的。所以工具调用不再是
   一行 mono：它是一块，左边一道 3px 的琥珀压住轨迹的细线（线走到这里就变粗、
   变成事件本身），里面是工具名、参数表、它带回来的那段原文。
   代价是密度 —— 这一页认了。 */
.ev-tool { padding-bottom: 26px; }
.ev-tool::before { left: 10px; width: 3px; background: var(--agent); }
.ev-tool .ev-dot { display: none; }

/* 块的右边缘收在 46rem 上，不铺满整行 —— 一行拉满 1000px 的时候，
   它读起来是一条被高亮的行；收窄之后它才是一块。
   右边空出来的那一条留给轮次的 token 数，像页边的批注。 */
.ev-block {
  margin-left: -27px;
  max-width: calc(46rem + 45px);
  padding: 15px 20px 17px 27px;
  background: var(--agent-soft);
}
.ev-tool .ev-name {
  font-family: var(--font-mono); font-size: 1rem; font-weight: 500;
  color: var(--agent); letter-spacing: -.01em; line-height: 1.5;
}
/* 参数按「名 → 值」列出来，不挤成一行 */
.ev-args { margin: 10px 0 0; display: grid; gap: 3px; }
.ev-arg {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 12px; align-items: baseline;
}
.ev-args dt {
  font-family: var(--font-mono); font-size: var(--t-xs);
  color: var(--muted); white-space: nowrap;
}
.ev-args dd {
  margin: 0; font-family: var(--font-mono); font-size: .8125rem;
  line-height: 1.7; color: var(--ink); overflow-wrap: anywhere;
}

/* 派出去的 worker：缩进一层、安静一点，表示「不在主线上」 */
.ev-sub { margin-top: 11px; padding-left: 14px; border-left: 1px solid var(--rule-2); }
.ev-sub-line {
  font-family: var(--font-mono); font-size: .8125rem; line-height: 1.75;
  color: var(--faint); overflow-wrap: anywhere;
}
.ev-sub-line.is-warn { color: var(--agent); }
.ev-sub-line.is-err { color: var(--danger); }

/* 它带回来的东西：直接摊在块里，不藏在折叠后面 ——
   这一页要让人看见「它读到了什么」，而不是知道「它读了多少」。 */
.ev-out { margin-top: 14px; }
.ev-out-cap {
  display: block; margin-bottom: 7px;
  font-size: var(--t-xs); color: var(--muted);
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
}
.ev-out pre {
  margin: 0; padding: 13px 15px; max-height: 188px; overflow: auto;
  background: var(--paper); border: 1px solid var(--rule);
  font-family: var(--font-mono); font-size: .7813rem; line-height: 1.7;
  white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink-2);
}
.ev-more { margin-top: 8px; }
.ev-more summary {
  display: inline-block; cursor: pointer; list-style: none;
  color: var(--muted); font-size: var(--t-xs);
  border-bottom: 1px dashed var(--rule-2); padding: 3px 0;
}
.ev-more summary::-webkit-details-marker { display: none; }
.ev-more summary:hover { color: var(--agent); border-bottom-color: var(--agent-line); }
.ev-more pre { margin-top: 9px; max-height: 420px; }

/* 新事件出现：推开，不是跳变 */
@media (prefers-reduced-motion: no-preference) {
  .rounds[data-state="running"] .ev,
  .rounds[data-state="running"] .round-head {
    animation: ev-in var(--dur-slow) var(--ease-out) both;
  }
  @keyframes ev-in {
    from { opacity: 0; transform: translateY(-6px) }
    to { opacity: 1; transform: none }
  }
}

/* 正在思考：最后一个节点上有一圈琥珀色的呼吸。
   两层信号 —— 节点自己在呼吸（任何一帧都看得见），外面一圈扩散的环（偶尔抓到）。
   只有一个环的话，截图和余光都容易错过它。 */
.trace > .is-tip .ev-dot { background: var(--agent); box-shadow: none; }
.trace > .is-tip::after {
  content: ""; position: absolute; left: 3.5px; top: 3.5px;
  width: 16px; height: 16px; border-radius: 50%;
  border: 1px solid var(--agent); opacity: 0;
}
/* 一轮从「模型在想」开始 —— 那几秒里页面上唯一该动的东西是章节号。
   工具调用那次节点是隐藏的（块左边那道粗线就是它的节点），
   所以呼吸挪到那道线上：整条边在明暗之间，块就是活的。 */
.trace > .round-head.is-tip .round-n { color: var(--agent); }
.trace > .ev-tool.is-tip::after { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .trace > .is-tip .ev-dot { animation: tip-breathe 1.9s ease-in-out infinite; }
  .trace > .round-head.is-tip .round-n { animation: tip-breathe 1.9s ease-in-out infinite; }
  .trace > .ev-tool.is-tip::before { animation: tip-breathe 1.9s ease-in-out infinite; }
  @keyframes tip-breathe { 0%, 100% { opacity: 1 } 50% { opacity: .3 } }
  .trace > .is-tip::after { animation: pulse-ring 1.9s linear infinite; }
  @keyframes pulse-ring {
    0%   { opacity: .9; transform: scale(.45) }
    55%  { opacity: .3; transform: scale(1.25) }
    100% { opacity: 0;  transform: scale(1.7) }
  }
}
/* 完成之后脉动停下，轨迹成了一条静止的线：末端收一个小方点，表示「到此为止」 */
.rounds[data-state="done"] .trace > .is-tip::after { animation: none; }
.rounds[data-state="done"] .trace > .ev:last-child .ev-dot { border-radius: 1px; }

/* —— 对话的两种块 ——

   一个任务 = 一段可以接着说下去的对话，所以框里除了 agent 的动作，
   还有用户说的每一句、以及前面每一轮交出来的东西。

   你说的话用蓝色（这个库里凡是「你的」都是蓝的），左边一道竖杠 ——
   它不是过程的一部分，它是过程之间的一条分界。前面几轮的结果收在
   「第 N 轮的结果」这条横线下面，形式上退到安静的一档：它们已经读过了。
   最新一轮的结果不在框里，在框外的 .answer —— 那个是结果，不是过程。 */
.turn-user {
  margin: 34px 0 24px;
  padding: 14px 18px 16px;
  border-left: 3px solid var(--mine);
  background: var(--mine-soft);
}
.turn-user .turn-who {
  font-size: var(--t-xs); letter-spacing: .08em; color: var(--mine);
  margin-bottom: 7px;
}
.turn-user .turn-said {
  font-size: var(--t-body); line-height: 1.75; color: var(--ink);
  white-space: pre-wrap; overflow-wrap: anywhere; max-width: 34em;
}
.trace > .turn-user:first-child { margin-top: 4px; }

.turn-end { margin: 28px 0 34px; }
.turn-label {
  display: flex; align-items: center; gap: 14px;
  font-size: var(--t-xs); letter-spacing: .06em; color: var(--muted);
  margin-bottom: 16px;
}
.turn-label::after {
  content: ""; flex: 1; height: 1px; background: var(--rule);
}
.turn-end .prose { max-width: 34em; }

.answer { margin-top: 20px; padding-top: 34px; border-top: 1px solid var(--ink); }
.answer-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 22px;
}

/* —— 交付之后接着说的那个框 ——
   它就是把用户的话接进同一段对话的入口；历史、预算都在服务端管着，
   这里只负责把话送出去。 */
.reply { margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--rule); }
.reply textarea {
  display: block; width: 100%; min-height: 78px;
  padding: 13px 16px;
  border: 1px solid var(--rule-2); border-radius: 3px;
  background: var(--paper-2); color: var(--ink);
  font-size: var(--t-body); line-height: 1.8; resize: vertical;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.reply textarea::placeholder { color: var(--faint); }
.reply textarea:focus {
  outline: none; background: var(--paper); border-color: var(--mine-line);
  box-shadow: 0 0 0 3px var(--mine-soft);
}
.reply-foot {
  display: flex; align-items: center; justify-content: flex-end; margin-top: 12px;
}

/* 收场：说清为什么不再接了，并给出唯一该做的事 —— 开一段新的 */
.notice-closed { border-left-color: var(--agent); }
.notice-closed a { margin-left: 10px; white-space: nowrap; }

/* ---------- 11. 总览 ---------- */

.stats {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 0; margin-top: 40px;
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--rule);
}
.stat {
  padding: 22px 22px 24px 0;
  border-right: 1px solid var(--rule);
}
.stat:last-child { border-right: 0; }
.stat a { display: block; }
.stat b {
  display: block;
  font-family: var(--font-display);
  font-size: 2.5rem; font-weight: 500; line-height: 1;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  transition: color var(--dur) var(--ease);
}
.stat a:hover b { color: var(--mine); }
.stat span {
  display: block; margin-top: 8px;
  color: var(--muted); font-size: var(--t-xs); letter-spacing: .04em;
}

.cols {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px; margin-top: 60px;
}
.cols .list, .cols .entries { margin-top: 4px; --gutter: 18px; }
.cols .entry-title { font-size: 1rem; }
.rail-note { color: var(--ink-2); font-size: var(--t-sm); line-height: 1.8; }

/* —— 用量审计 ——
   数字来自网关的账本，和命令行 `gateway.py --report` 同源。
   三块：总量、分来源与分天、最近调用。仍是发丝线，没有卡片。
   蓝色和琥珀在这站上有别的意思（留下的 / 带回来的），用量两边都不是，
   所以这一块只用墨与灰；红只留给失败和没报来源的调用。 */

.usage { margin-top: 76px; padding-top: 28px; border-top: 1px solid var(--rule); }
.usage-head {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: 10px 20px;
}
.usage-title {
  font-family: var(--font-display);
  font-size: 1.625rem; font-weight: 500; letter-spacing: -.02em;
}

/* 总量：一格一个数。auto-fit 让格数跟着实际有数的项走 ——
   没配单价时少一格，不会在末尾留个洞。 */
.ufigs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 20px 24px;
  margin-top: 26px; padding: 22px 0 24px;
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--rule);
}
.ufig b {
  display: block;
  font-family: var(--font-display);
  font-size: 1.75rem; font-weight: 500; line-height: 1.1;
  letter-spacing: -.025em; font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.ufig b.is-bad { color: var(--danger); }
.ufig span {
  display: block; margin-top: 7px;
  color: var(--muted); font-size: var(--t-xs); letter-spacing: .04em;
}
.ufig span.usub {
  margin-top: 4px; color: var(--faint); letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* unknown 说明有调用没打 source 头 —— 这是这套记账自己的体检指标，给它红色 */
.usage-warn {
  margin-top: 22px; padding: 12px 16px;
  border-left: 2px solid var(--danger); background: var(--danger-soft);
  color: var(--ink-2); font-size: var(--t-sm); line-height: 1.7;
}

.usage-cols {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 44px 56px; margin-top: 44px;
}
.usage-cols > section { min-width: 0; }

/* 排行：一行一个来源 / 一天。下面那条量尺就是这一行的下边线 ——
   长度的基准各栏不同（来源比的是总量、天比的是峰值），尺子只用来比长短。 */
.urank { list-style: none; margin: 0; padding: 0; }
.urank li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: baseline; column-gap: 14px;
  padding-top: 12px;
  font-size: var(--t-sm);
}
.urank .uk { grid-area: 1 / 1; min-width: 0; overflow-wrap: anywhere;
             font-family: var(--font-mono); font-size: .8125rem; }
.urank .un { grid-area: 1 / 2; color: var(--muted); font-size: var(--t-xs); white-space: nowrap; }
.urank .ut { grid-area: 1 / 3; text-align: right; white-space: nowrap; color: var(--ink-2);
             font-variant-numeric: tabular-nums; }
.urank .ubad { grid-area: 1 / 4; color: var(--danger); font-size: var(--t-xs); white-space: nowrap; }
.urank .ubar {
  grid-area: 2 / 1 / 3 / -1;
  height: 2px; margin-top: 9px; background: var(--rule);
}
.urank .ubar i { display: block; height: 100%; background: var(--faint); }
.urank .is-unknown .uk { color: var(--danger); }
.urank .is-day .uk {
  font-family: var(--font-display); font-size: 1rem;
  font-variant-numeric: tabular-nums;
}
.urank .is-day .uw {
  margin-left: 8px; font-family: var(--font-ui);
  font-size: var(--t-xs); color: var(--faint);
}

/* 最近调用：时间、来源、model、token、延迟各占一列，失败的多一行说明。 */
.ucalls { list-style: none; margin: 0; padding: 0; }
.ucall {
  display: grid;
  grid-template-columns: 9px auto minmax(5rem, 1fr) auto auto;
  grid-template-areas:
    "dot when id  tok lat"
    ".   err  err err err";
  align-items: baseline; column-gap: 14px;
  padding: 10px 0 11px;
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-sm);
}
.ucall .udot {
  grid-area: dot; align-self: center; flex: none;
  width: 6px; height: 6px; border-radius: 50%;
  border: 1px solid var(--faint);
}
.ucall.is-bad .udot { border-color: var(--danger); background: var(--danger); }
.ucall time {
  grid-area: when; color: var(--faint); font-size: var(--t-xs);
  white-space: nowrap;
}
.ucall .uid { grid-area: id; display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.ucall .usrc { flex: none; font-family: var(--font-mono); font-size: .8125rem; color: var(--ink-2); }
.ucall .umodel {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-mono); font-size: .8125rem; color: var(--faint);
}
.ucall .utok { grid-area: tok; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.ucall .ulat {
  grid-area: lat; text-align: right; white-space: nowrap;
  color: var(--muted); font-size: var(--t-xs); font-variant-numeric: tabular-nums;
}
.ucall .uerr {
  grid-area: err; margin-top: 3px;
  color: var(--danger); font-size: var(--t-xs); overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ---------- 12. 登录 ---------- */

.login-page {
  margin: 0; min-height: 100vh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 30px; padding: 32px;
  background: var(--paper);
}
.login-card {
  width: 100%; max-width: 352px;
  border-top: 1px solid var(--ink);
  padding-top: 30px;
}
.login-card h1 {
  font-family: var(--font-display);
  font-size: 2.25rem; font-weight: 500; letter-spacing: -.03em;
  margin-bottom: 10px;
}
.login-card .sub {
  color: var(--muted); font-size: var(--t-sm); line-height: 1.75;
  margin-bottom: 28px; max-width: 26em;
}
.login-card input[type=password] {
  width: 100%; padding: 12px 14px; margin-bottom: 14px; min-height: 48px;
  background: var(--paper-2); border: 1px solid var(--rule-2); border-radius: 3px;
  font-size: 1rem;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.login-card input[type=password]:focus {
  outline: none; border-color: var(--mine-line); background: var(--paper);
  box-shadow: 0 0 0 3px var(--mine-soft);
}
.login-card .btn { width: 100%; }
.login-card .notice { margin: 0 0 18px; }
.login-foot { color: var(--faint); font-size: var(--t-xs); }

[hidden] { display: none !important; }

/* ---------- 13. X 登录 ---------- */

/* 凭据这一块：状态在上，动作在下。它和「维护」那一块是同一类东西 ——
   系统里的一件事实和它的开关，所以用同一套零件（发丝线 + 说明小字）。 */
/* 「为什么不能在这儿输账号密码」。放在抬头和状态卡之间 ——
   先回答完这个问题，下面的四步操作才读得下去。 */
.cred-why {
  margin-top: 22px; padding-left: 18px;
  border-left: 2px solid var(--rule-2);
  max-width: 44em;
  font-size: var(--t-sm); line-height: 1.85; color: var(--ink-2);
}
.cred {
  margin-top: 40px; padding: 18px 20px 20px;
  border: 1px solid var(--rule); border-top: 1px solid var(--ink);
  background: var(--paper-2);
}
.cred-state {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  font-size: var(--t-sm); color: var(--muted);
}
.cred .foot-note { margin-top: 10px; }
.cred-test {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 18px;
}
.cred-test-msg { font-size: var(--t-sm); color: var(--muted); min-width: 12em; }
.cred-test-msg.is-ok { color: var(--mine); }
.cred-test-msg.is-bad { color: var(--danger); }

.notice-warn { border-left-color: var(--agent); background: var(--agent-soft); }

/* 步骤。这里必须一步一步写清楚 —— "把 cookie 填进来"对没做过这件事的人
   等于没说，而他得先知道去哪儿装扩展、导出成什么形状。 */
.howto { margin-top: 44px; max-width: 40em; }
.howto h2 { font-size: var(--t-h2); }
.howto ol {
  margin: 18px 0 0; padding-left: 1.4em;
  color: var(--ink-2); font-size: var(--t-body);
}
.howto li { margin-top: 10px; line-height: 1.8; }
.howto b { color: var(--ink); font-weight: 600; }

.cred-form { margin-top: 26px; }
.cred-form textarea {
  display: block; width: 100%; padding: 12px 14px;
  border: 1px solid var(--rule-2); border-radius: 3px;
  background: var(--paper); color: var(--ink);
  font-family: var(--font-mono); font-size: var(--t-sm); line-height: 1.6;
  resize: vertical; word-break: break-all;
}
.cred-form textarea::placeholder { color: var(--faint); }
.cred-form textarea:focus {
  outline: none; border-color: var(--mine-line);
  box-shadow: 0 0 0 3px var(--mine-soft);
}
.cred-foot { display: flex; justify-content: flex-end; margin-top: 12px; }

/* ---------- 14. 动效 ---------- */

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
  /* 页面转场：跨文档 View Transitions，不支持的浏览器直接跳，行为不变 */
  @view-transition { navigation: auto; }
  ::view-transition-old(root) { animation: vt-out .16s var(--ease) both; }
  ::view-transition-new(root) { animation: vt-in .3s var(--ease-out) both; }
  @keyframes vt-out { to { opacity: 0 } }
  @keyframes vt-in { from { opacity: 0; transform: translateY(6px) } }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- 15. 响应式 ---------- */

/* 中窄屏：元信息栏回到正文之后，统计两列 */
@media (max-width: 980px) {
  .doc-layout { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .rail { position: static; order: 2; margin-top: 8px; padding-top: 26px;
          border-top: 1px solid var(--rule); }
  .rail dl { grid-template-columns: auto minmax(0, 1fr); }
  .cols { grid-template-columns: 1fr; gap: 48px; }
  .usage-cols { grid-template-columns: 1fr; gap: 40px; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:nth-child(2n) { border-right: 0; }
  .stat:nth-child(-n+4) { border-bottom: 1px solid var(--rule); }
}

/* 移动端：重新组织，不是把桌面压窄。
   导航不在头部挤 —— 它搬到拇指够得着的底栏。 */
@media (max-width: 720px) {
  :root { --gutter: 22px; --spine-x: 3px; }

  body { padding-bottom: calc(58px + env(safe-area-inset-bottom, 0px)); }
  .shell { padding: 0 18px; }
  :root { --shell-pad: 18px; }

  /* 紧凑粘性头部：只有身份和搜索 */
  .topbar-in { height: auto; padding: 4px 0; gap: 12px; flex-wrap: nowrap; }
  .brand { font-size: 1rem; min-height: 44px; }
  .nav { display: none; }
  .search { flex: 1; margin-left: 0; }
  .search input, .search input:focus { width: 100%; min-height: 44px; }
  .search kbd { display: none; }

  /* 底栏：三个入口，44px 以上，任务居中且是实心的那一个 */
  .tabbar {
    display: grid; grid-template-columns: repeat(3, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    background: var(--paper);
    border-top: 1px solid var(--rule);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  @supports (backdrop-filter: blur(1px)) {
    .tabbar {
      background: color-mix(in srgb, var(--paper) 92%, transparent);
      backdrop-filter: saturate(140%) blur(12px);
    }
  }
  .tabbar a {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; min-height: 58px; padding: 8px 4px;
    font-size: var(--t-xs); color: var(--muted);
  }
  .tabbar a[aria-current] { color: var(--mine); }
  .tabbar a.t-primary {
    color: var(--ink); font-weight: 500;
  }
  .tabbar a.t-primary[aria-current] { color: var(--mine); }
  .tabbar .ico { width: 18px; height: 18px; }

  /* 首屏 */
  .hero { padding-top: 30px; }
  .hero h1 { font-size: clamp(2.25rem, 12vw, 2.75rem); letter-spacing: .08em; margin-right: -.08em; }
  .hero .lede { font-size: 1rem; }
  /* 输入框在手机上就是首屏的主角：报头收一档，把框顶上来 */
  .compose-hero { margin-top: 22px; }
  .compose-hero textarea { min-height: 58px; padding: 14px 15px; }
  .compose-hero-foot select { flex: 1; min-width: 0; min-height: 44px; }
  .compose-hero-foot .btn { margin-left: 0; }
  .balance { margin-top: 26px; }

  /* 秤：手机上还是并排 —— 并排才是秤，摞起来就成了两张卡片 */
  .hero-foot { font-size: var(--t-xs); }

  /* 版面即秤，竖过来：两个头并排在最上面（两条量尺接起来还是完整的一条），
     两个区域上下摞着铺满整屏宽 —— 从上往下滚，就是从蓝的地界走进琥珀的地界。
     栏宽在这里另夹一次：手机上并排的头各要留住能读的四个字。 */
  .fields {
    --fpad: 0px;
    grid-template-columns: clamp(31%, var(--a), 69%) clamp(31%, var(--b), 69%);
    grid-template-rows: auto auto auto;
    margin: 24px calc(-1 * var(--shell-pad)) 0;
  }
  .fields::before { display: none; }
  .fhead-mine  { grid-area: 1 / 1; padding: 15px 10px 0 var(--shell-pad); }
  .fhead-agent { grid-area: 1 / 2; padding: 15px 0 0 10px; }
  .fbody-mine  { grid-area: 2 / 1 / 3 / 3; padding: 16px var(--shell-pad) 30px; }
  .fbody-agent { grid-area: 3 / 1 / 4 / 3; padding: 20px var(--shell-pad) 30px; }
  .fhead { min-height: 0; }
  body:not(.is-thin) .fhead { min-height: 0; }
  .fnum, body:not(.is-thin) .fnum { font-size: 2.125rem; }
  .flab, body:not(.is-thin) .flab { margin-top: 10px; font-size: 11px; }
  .fwho { font-size: var(--t-xs); }
  /* 手机上头并排、栏很窄：梁只有一百多像素，虚笔太碎就看不见了，
     所以这边的话比梁本身更要紧，字号不再往下掉 */
  .fstate, body:not(.is-thin) .fstate {
    margin-top: 6px; font-size: var(--t-xs); line-height: 1.45;
  }

  .fields .day { margin-top: 40px; }
  .fields .day:first-child { margin-top: 6px; }
  .fields .entry { padding: 18px 0 20px; margin-right: -12px; padding-right: 12px; }
  .fields .entry-title { font-size: 1.125rem; }
  .fields .entry-sub { -webkit-line-clamp: 2; font-size: .8125rem; }
  .fields .entry-li[data-kind="concept"] .entry-title { font-size: 1.0625rem; }
  .fields .entry-li[data-kind="source"] .entry-title { font-size: .9375rem; }
  .fields .entry-li::after { top: 32px; }
  .fields .entry-li[data-kind="source"]::after { top: 27px; }
  .fields .entry-li:last-child::before { height: 40px; }
  .is-thin .fields .day { margin-top: 44px; }
  .is-thin .fields .day:first-child { margin-top: 6px; }
  .is-thin .fields .day-n { font-size: 1.5rem; }
  .is-thin .fields .entry { padding: 20px 0 22px; }
  .is-thin .fields .entry-title { font-size: 1.1875rem; }
  .is-thin .fields .entry-li[data-kind="concept"] .entry-title { font-size: 1.125rem; }
  .is-thin .fields .entry-li[data-kind="source"] .entry-title { font-size: 1rem; }
  .is-thin .fields .entry-li::after { top: 30px; }
  .is-thin .fields .entry-li[data-kind="source"]::after { top: 26px; }
  .is-thin .fields .entry-li:last-child::before { height: 38px; }

  .is-thin .day { margin-top: 58px; }
  .is-thin .day:first-child { margin-top: 38px; }
  .is-thin .day-n { font-size: 1.75rem; }
  .is-thin .entry { padding: 24px 0 26px; }
  .is-thin .entry-title { font-size: 1.3125rem; }
  .is-thin .entry-li[data-kind="concept"] .entry-title { font-size: 1.25rem; }
  .is-thin .entry-li[data-kind="source"] .entry-title { font-size: 1.0625rem; }
  .is-thin .entry-li::after { top: 34px; }
  .is-thin .entry-li[data-kind="source"]::after { top: 30px; }
  .is-thin .entry-li:last-child::before { height: 44px; }
  .grow { margin-top: 52px; }
  .grow h2 { font-size: 1.375rem; }

  .bar { margin-top: 30px; gap: 12px; }
  .seg { overflow-x: auto; scrollbar-width: none; }
  .seg::-webkit-scrollbar { display: none; }
  .seg a { padding: 9px 12px; min-height: 44px; align-items: center; }
  .sort { width: 100%; justify-content: space-between; }
  .sort select { min-height: 44px; flex: 1; }
  .balance-legend { gap: 2px 18px; }
  .balance-legend a { min-height: 44px; }
  .btn-quiet { min-height: 44px; }
  /* 空栏里和收尾处的入口：字不动，命中区撑到 44px */
  .fempty-cta a, .grow-cta a { display: inline-flex; align-items: center; min-height: 44px; }
  .compose-foot select { min-height: 44px; }
  /* 行内链接也给足命中区：文字本身不动，靠上下 padding 撑开 */
  .doc-meta { gap: 0 16px; }
  .doc-meta a { padding: 11px 0; }
  .rail dd a { display: inline-block; padding: 11px 0; }
  .rail .toc a { padding: 10px 0; }
  .related li { padding: 4px 0; }
  .related li a { display: inline-block; padding: 10px 0; }

  .day { margin-top: 46px; }
  .day:first-child { margin-top: 30px; }
  .day-n { font-size: 1.5rem; }

  /* 条目：标题先说话，元信息退到下面 */
  .entry {
    grid-template-columns: minmax(0, 1fr);
    gap: 0 0; padding: 18px 0 20px;
    margin-right: -12px; padding-right: 12px;
  }
  .entry-title { font-size: 1.125rem; }
  .entry-li[data-kind="concept"] .entry-title { font-size: 1.0625rem; }
  .entry-li[data-kind="source"] .entry-title { font-size: .9375rem; }
  .entry-sub { -webkit-line-clamp: 2; font-size: .8125rem; }
  .entry-meta {
    padding-top: 10px; gap: 10px; white-space: normal; flex-wrap: wrap;
  }
  /* 触控目标：整行就是链接，天然超过 44px */
  .entry-li::after { top: 32px; }
  .entry-li[data-kind="source"]::after { top: 27px; }
  .entry-li:last-child::before { height: 40px; }

  .empty { padding: 38px 0 42px; }
  .empty h2 { font-size: 1.375rem; }

  /* 详情页 */
  .doc-layout { padding-top: 26px; }
  .doc-head { padding-bottom: 20px; }
  .doc-body { padding-top: 26px; }
  .judgments { margin-top: 2.6em; }
  .judgment { padding-left: 16px; }
  .judgments.is-empty { padding: 20px 18px 18px; }
  /* 时间就是入口，命中区撑到 44px（文字本身不动） */
  .judgment-meta a { display: inline-flex; align-items: center; min-height: 44px; }
  .doc-about a { display: inline-block; padding: 11px 0; }
  .related { margin-top: 44px; }
  .related li { grid-template-columns: auto minmax(0, 1fr); }
  .related .rel { grid-column: 2; }

  /* 任务 */
  .task-head { padding-top: 26px; }
  .compose { padding: 4px 16px 0; }
  .compose-foot { flex-wrap: wrap; }
  .compose-foot select { flex: 1; min-width: 0; }
  .hints button { min-height: 44px; }
  .task-row { grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; padding: 14px 0; }
  .task-row .when { grid-column: 2; }

  /* 轨迹：手机上块要占满宽度，参数名单独一行。
     框也跟着矮一档 —— 视口本来就小，框占满了，结果就掉到屏幕外面去了。 */
  .rounds { max-height: min(56vh, 520px); min-height: 150px; }
  .rounds-wrap { margin-top: 26px; }
  .ev, .round-head { padding-left: 26px; }
  .ev::before, .round-head::before { left: 5px; }
  .ev-tool::before { left: 4px; }
  .ev-block {
    margin-left: -21px; margin-right: -12px;
    padding: 13px 14px 15px 21px;
  }
  .ev-arg { grid-template-columns: minmax(0, 1fr); gap: 0; margin-bottom: 6px; }
  .ev-args dd { padding-left: 0; }
  .ev-out pre { max-height: 160px; font-size: .75rem; }
  .ev-more summary { min-height: 44px; display: flex; align-items: center; }
  .round-head { padding-top: 36px; gap: 10px; }
  .round-n { font-size: 1.5rem; }
  /* 框里有自己的滚动条：块不再往右出血（出血的那几像素会把框顶出一条横滚） */
  .ev-block { max-width: none; margin-right: 0; }
  .turn-user { margin: 28px 0 20px; padding: 13px 14px 15px; }
  .reply { margin-top: 34px; }
  .reply-foot .btn { width: 100%; }

  .stats { margin-top: 28px; }
  .stat { padding: 18px 16px 20px 0; }
  .stat b { font-size: 2rem; }

  /* 用量：手机上总量仍是两列，最近调用折成两行 —— 时间与延迟一行，
     来源、model、token 一行。 */
  .usage { margin-top: 56px; padding-top: 24px; }
  .usage-title { font-size: 1.375rem; }
  .ufigs { margin-top: 22px; padding: 20px 0 22px; }
  .ufig b { font-size: 1.5rem; }
  .ucall {
    grid-template-columns: 9px minmax(0, 1fr) auto;
    grid-template-areas:
      "dot when lat"
      ".   id   tok"
      ".   err  err";
    column-gap: 12px;
  }

  .foot { margin-top: 56px; padding-bottom: 32px; flex-direction: column; gap: 8px; }
}

/* 小屏：320px 也不许出现横向滚动 */
@media (max-width: 380px) {
  .shell { padding: 0 14px; }
  :root { --shell-pad: 14px; }
  .entry-title { font-size: 1.0625rem; }
  /* 320px 上薄库的大标题要收回来一点：四行标题在这么窄的屏幕上不成段落 */
  .is-thin .entry-title { font-size: 1.1875rem; }
  .is-thin .day-n { font-size: 1.5rem; }
  .hero h1 { font-size: 2.125rem; }
  .day-head { gap: 10px; }
  .day-n { font-size: 1.3125rem; }
}
