/* ==========================================================================
   素稿 · 设计令牌与组件
   设计意图：编辑室 / 朱笔批改。纸墨为底，朱砂做唯一强调色。
   一条强调色锁全站；半径只用一个体系（面板 14 / 控件 10 / 小标 6）。
   ========================================================================== */

/* ---------- 令牌 ---------- */
:root {
  color-scheme: light;

  --paper-0: #F6F4F2;   /* 页底，off-white，往朱砂方向微偏 */
  --paper-1: #FFFFFF;   /* 面板 */
  --paper-2: #EFEBE8;   /* 凹陷 / 次级面 */
  --paper-3: #E6E0DB;   /* 更深的凹陷 */

  --ink-0: #1C1A19;     /* 主文字，off-black，不纯黑 */
  --ink-1: #55504B;
  /* 次级与三级文字。取值不是拍脑袋定的，是 verify/pick_ink.py 算出来的：
     原先 #7A736D 只按 paper-1（白）校准过（4.67:1），可它在界面里大量落在
     paper-0 页底上，实测只有 4.25:1；#A29A93 更差，在页底 2.53:1、白底 2.77:1，
     占位符上的说明文字基本读不清。两档现在都过了 AA（最差 4.60:1）。 */
  --ink-2: #68625D;
  --ink-3: #6E6964;

  --line: #DCD5CF;
  --line-strong: #C7BEB6;

  --accent: #B33A2C;        /* 朱砂 */
  --accent-solid: #B33A2C;
  --accent-on: #FFFFFF;
  --accent-soft: rgba(179, 58, 44, .10);
  --accent-line: rgba(179, 58, 44, .30);

  --good: #3F7A52;
  --good-soft: rgba(63, 122, 82, .13);
  --warn: #94661A;
  --warn-soft: rgba(148, 102, 26, .15);

  --hl-1: rgba(179, 58, 44, .26);   /* 严重类：空话 / 模板 / 排比 */
  --hl-2: rgba(148, 102, 26, .30);  /* 衔接类：开头断言 / 连接词 */
  --hl-3: rgba(43, 106, 116, .24);  /* 字词类：冗余 / 四字格 / 同义 */

  --shadow-1: 0 1px 2px rgba(28, 26, 25, .05);
  --shadow-2: 0 10px 30px -12px rgba(28, 26, 25, .22), 0 2px 6px rgba(28, 26, 25, .05);
  --shadow-3: 0 24px 60px -20px rgba(28, 26, 25, .32);

  --r-lg: 14px;
  --r: 10px;
  --r-sm: 6px;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;

  /* 字号阶梯（2026-11-06 对齐 landing-page-design 的 Tailwind 档位）。
     ★ 只许取这六档，不再出现 13px / 17px 这种"夹在中间"的值：
       尺寸一多，页面上就会出现"这两行差在哪"说不清的层级。
     ★ 最小 12px，不是 11px：用户明确说过"有些字太小费眼睛"。
       中文比拉丁字在同等 px 下更糊，这一档已经是下限。 */
  --fs-micro: 12px;   /* text-xs  标注、字数、角标 */
  --fs-sm: 14px;      /* text-sm  控件、说明 */
  --fs-md: 16px;      /* text-base 正文（中文 16px 才够舒服） */
  --fs-lg: 18px;      /* text-lg  小标题、空态主句 */
  --fs-xl: 21px;      /* text-[21px] 区块标题 */
  --fs-display: 28px; /* 数值、价格 */

  --z-sticky: 20;
  --z-scrim: 40;
  --z-drawer: 50;
  --z-toast: 60;

  /* 动效曲线统一一条：起步快、收尾长，像手指甩出去后自己停下。
     landing-page-design 推荐值。原来的是 (.23,1,.32,1)，肉眼几乎无差，
     但全站只留一条曲线，才不会出现"有的地方弹、有的地方黏"。 */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --t-fast: 120ms;
  --t-base: 220ms;
  --t-slow: 320ms;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
          "Hiragino Sans GB", "Microsoft YaHei", "Source Han Sans SC",
          "Noto Sans CJK SC", sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, "Courier New", monospace;
}

[data-theme="dark"] {
  color-scheme: dark;

  --paper-0: #121110;
  --paper-1: #1A1918;
  --paper-2: #232120;
  --paper-3: #2C2927;

  --ink-0: #F2EFEC;
  --ink-1: #C3BCB6;
  --ink-2: #98908A;   /* 暗色侧同样按最差底色 paper-3 校准，4.60:1 */
  --ink-3: #908880;

  --line: #332F2D;
  --line-strong: #474240;

  --accent: #D9705E;
  --accent-solid: #B84A38;   /* 白字在其上 5.1:1 */
  --accent-on: #FFFFFF;
  --accent-soft: rgba(217, 112, 94, .14);
  --accent-line: rgba(217, 112, 94, .34);

  --good: #6FA97F;
  --good-soft: rgba(111, 169, 127, .16);
  --warn: #D8A657;
  --warn-soft: rgba(216, 166, 87, .16);

  --hl-1: rgba(217, 112, 94, .28);
  --hl-2: rgba(216, 166, 87, .26);
  --hl-3: rgba(109, 176, 190, .22);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 12px 34px -14px rgba(0, 0, 0, .7);
  --shadow-3: 0 28px 70px -24px rgba(0, 0, 0, .8);
}

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

html, body { height: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--paper-0);
  color: var(--ink-0);
  font: var(--fs-md) / 1.6 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -.01em; text-wrap: balance; }
p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; list-style: none; }
button, input, textarea, select { font: inherit; color: inherit; }
b, strong { font-weight: 600; }

/* 必须放在组件规则之前说明用途：.drawer 用了 display:flex，作者样式会压过
   浏览器默认的 [hidden]{display:none}，于是"关着"的抽屉仍然铺在页面上挡点击。
   这条 !important 是刻意的。 */
[hidden] { display: none !important; }

.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;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

::selection { background: var(--accent-soft); }

/* ---------- 顶栏 ---------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: color-mix(in srgb, var(--paper-0) 88%, transparent);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(10px);
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  max-width: 1440px;
  min-height: 64px;
  margin: 0 auto;
  padding: 0 var(--s6);
}

.brand { display: flex; align-items: center; gap: var(--s3); min-width: 0; }

.brand__mark {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  flex: none;
  border-radius: var(--r-sm);
  background: var(--accent-solid);
  color: var(--accent-on);
  font-size: 18px;
  font-weight: 600;
}

.brand__text { display: flex; align-items: baseline; gap: var(--s2); min-width: 0; }
.brand__text b { font-size: var(--fs-lg); letter-spacing: .02em; }
.brand__text i {
  font-style: normal;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  white-space: nowrap;
}

.topbar__actions { display: flex; align-items: center; gap: var(--s2); flex: none; }

/* ---------- 骨架 ----------
   2026-11-06：左栏从 minmax(340px,430px) 收到 minmax(320px,400px)。
   实测 1440 宽下左栏吃掉了 430px，而右栏空态只有一行字，两边严重失衡；
   右栏大部分时间要放"评分 + 逐句对照"，它才是这一页的主体。
   收窄之后左栏里的正文框仍是 16px / 1.75 行高，一屏能放进 18 行左右，
   读自己刚粘的稿子够用。 */
.shell {
  display: grid;
  grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
  gap: var(--s7);
  align-items: start;
  max-width: 1440px;
  margin: 0 auto;
  padding: var(--s6) var(--s6) var(--s8);
}

/* ★ sticky 的元素**不能比视口还高**（2026-09-18 实测）：
   dup 模式（展开了「参考材料」）左栏 1114px，而 1440x900 屏的可用高度只有 812px。
   结果是**没有任何滚动位置能看全这一栏**：滚到页面底部时它的顶部被切掉，
   而「开始查重」按钮初始时又在视口外。给个上限 + 允许内部滚动，整栏才始终可见。
   判据在 verify/probe_layout.mjs 里（sticky 时要求存在"完整可见"的滚动位置）。 */
.col--input {
  position: sticky;
  top: 88px;
  max-height: calc(100dvh - 112px);
  overflow-y: auto;
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
  /* 左栏现在是个滚动窗，凡是"把它里面的某元素滚进视野"（点按钮、Tab 切焦点）
     都会落在裁剪线上：上一行元素被切掉一半，看着像渲染坏了。
     留出上下的滚动内边距，让"滚到边"停在有边距的位置而不是硬贴边。 */
  scroll-padding-top: var(--s4);
  scroll-padding-bottom: var(--s3);
}
/* 单栏时 showPane() 会把结果区滚进视野（app.js 的 revealResult）。
   scroll-margin-top 让"滚到顶"停在粘性顶栏下面，而不是被顶栏盖住第一行。 */
.col--result { min-width: 0; scroll-margin-top: 76px; }

.chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-sm);
  background: var(--paper-2);
  border: 1px solid var(--line);
  font-size: var(--fs-micro);
  font-family: var(--mono);
  color: var(--ink-1);
  white-space: nowrap;
}
.chip--quiet { background: transparent; border-color: transparent; color: var(--ink-2); }

/* ★ 这里原来有一条 position: sticky; bottom: 0（把按钮钉在栏底）。
   它修的是「点按钮时浏览器滚动左栏，把上面一行字卡在裁剪线上切掉一半」。
   但主按钮现在**不再是左栏最后一个元素**：它下面多了「更多选项」折叠块，
   sticky 上浮时（z-index:2 + 不透明底色）会实体盖住折叠块的下沿。
   首屏默认内容只有约 530px，远小于可视高度，压根不需要滚动，那个事故不会来；
   展开折叠之后的裁剪风险，交给 verify/probe_layout.mjs 的「无半切控件」盯着。 */
.col__cta {
  margin-top: var(--s4);
  padding-top: var(--s3);
}
.col__cta-note { margin-top: var(--s2); font-size: var(--fs-sm); color: var(--ink-2); }

/* ---------- 编辑器 ---------- */
.editor {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  transition: border-color var(--t-base) var(--ease);
}
.editor:focus-within { border-color: var(--accent-line); }
.editor.is-dragover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.editor__area {
  display: block;
  width: 100%;
  min-height: 336px;
  max-height: 52vh;
  padding: var(--s4);
  border: 0;
  background: transparent;
  resize: vertical;
  font-size: var(--fs-md);
  line-height: 1.75;
  color: var(--ink-0);
}
.editor__area::placeholder { color: var(--ink-3); }
.editor__area:focus { outline: none; }

.editor__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  padding: var(--s2) var(--s3);
  border-top: 1px solid var(--line);
  background: var(--paper-2);
}
/* 字数和句数是"输入的反馈"，不是控件。挨着放，别再做成按钮的样子。 */
.editor__foot-left { display: flex; align-items: center; gap: var(--s4); }

/* ---------- 更多选项（默认收起） ----------
   首屏只留「输入框 + 一个按钮」。保护名单、要做什么、参考材料全收在这里，
   点一下才出现。用原生 <details>：键盘能开、屏幕阅读器读得出"可展开"，
   不需要一行 JS，也就没有"JS 挂了它打不开"这种坏法。
   ★ 折叠 != 藏起来的东西在悄悄起作用：摘要行右边一直显示当前是哪个模式、
     设了几个保护词，收起时也看得见。 */
.more {
  margin-top: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-1);
}

.more__summary {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: 40px;
  padding: 0 var(--s3);
  border-radius: var(--r);
  font-size: var(--fs-sm);
  color: var(--ink-1);
  cursor: pointer;
  list-style: none;
}
.more__summary::-webkit-details-marker { display: none; }
/* 可展开这件事得看得出来。一个小加号，展开后变减号。 */
.more__summary::before {
  content: "＋";
  flex: none;
  width: 12px;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-2);
  text-align: center;
}
.more[open] .more__summary::before { content: "－"; }
.more__summary:hover { color: var(--ink-0); }
.more__summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.more__summary .more__label { flex: none; }
.more__hint {
  margin-left: auto;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-2);
  text-align: right;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.more__body {
  padding: var(--s4) var(--s3) var(--s3);
  border-top: 1px solid var(--line);
}
/* 折叠面板自己已经有上下两条线了，里面第一块不用再画一条 */
.more__body > .mode:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.more__foot {
  display: flex;
  gap: var(--s2);
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}

/* ---------- 表单 ---------- */
.field { margin-top: var(--s4); }
/* 抽屉里每一节的第一项，紧跟在 legend 后面，不用再加一道上边距 */
.field--first { margin-top: 0; }
.field__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  margin-bottom: var(--s2);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.field__label-hint {
  font-weight: 400;
  font-size: var(--fs-micro);
  color: var(--ink-2);
  font-family: var(--mono);
}
.field__input {
  width: 100%;
  min-height: 40px;
  padding: 9px var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-1);
  transition: border-color var(--t-base) var(--ease);
}
.field__input::placeholder { color: var(--ink-3); }
.field__input:focus { outline: none; border-color: var(--accent); }
.field__help { margin-top: var(--s2); font-size: var(--fs-micro); color: var(--ink-2); }

input[type="range"] {
  width: 100%;
  height: 24px;
  accent-color: var(--accent-solid);
  background: transparent;
}

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 36px;
  padding: 0 var(--s4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--paper-1);
  color: var(--ink-0);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.btn:hover { border-color: var(--accent-line); background: var(--accent-soft); }
.btn:active { transform: scale(.975); }
/* 禁用态不能用「橙红降到 45% 透明」，那看起来像坏掉的粉色条。
   改成中性面 + 次级文字，一眼就能看出"还不该点这里"。 */
.btn[disabled] {
  background: var(--paper-2);
  border-color: var(--line);
  color: var(--ink-3);
  cursor: not-allowed;
}
.btn[disabled]:hover { background: var(--paper-2); border-color: var(--line); }
.btn[disabled]:active { transform: none; }

.btn--quiet { border-color: transparent; background: transparent; color: var(--ink-1); }
.btn--quiet:hover { background: var(--paper-2); border-color: transparent; color: var(--ink-0); }

.btn--ghost { border-color: var(--line); background: transparent; color: var(--ink-1); }
.btn--ghost:hover { border-color: var(--accent-line); color: var(--ink-0); background: var(--accent-soft); }

.btn--primary {
  border-color: transparent;
  background: var(--accent-solid);
  color: var(--accent-on);
  font-weight: 600;
}
.btn--primary:hover { background: color-mix(in srgb, var(--accent-solid) 86%, #000); }
/* 不要再写 .btn--primary[disabled]:hover，它和上面的禁用态同权重但更靠后，
   会把"悬停时不许点"的主按钮重新染成朱砂色。禁用态统一由 .btn[disabled] 管。 */

.btn--tiny { min-height: 28px; padding: 0 var(--s3); font-size: var(--fs-micro); }
.btn--wide { width: 100%; }
/* 首屏唯一的那个按钮。它是这一页的主要动作，值得比普通按钮高一头。 */
.btn--lg { min-height: 46px; font-size: var(--fs-md); font-weight: 600; }

.btn__badge {
  min-width: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--paper-3);
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-1);
}

.btn.is-busy { pointer-events: none; opacity: .8; }
.btn.is-busy::after {
  content: "";
  width: 11px; height: 11px;
  border: 1.5px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- 空态 ----------
   2026-11-06 重做。改之前的实测截图（verify/shots/base-index-desk-light.png）：
   右栏一大片空白上只浮着一行字 + 一个描边按钮，而左栏输入框占满了首屏高度。
   整页信息量全压在左边，右边像"没加载完"。
   现在右栏给三样东西，按"用户此刻需要什么"排：
     1. 一句主句（结果会出现在哪）
     2. 三条要点（这工具怎么工作：回答"我凭什么信它"）
     3. 一个主动作（载入示例）+ 一行退回文字（不载入也行）
   ★ 只加文字，不加插图、不加渐变、不加装饰图形：这一页是工作台，
     不是落地页，装饰会跟右边的诊断结果抢注意力。 */
.empty {
  padding: clamp(var(--s5), 5vh, var(--s7)) var(--s2) var(--s5);
  max-width: 64ch;
}

.empty__lead {
  max-width: 44ch;
  font-size: var(--fs-xl);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: -.01em;
  color: var(--ink-0);
  text-wrap: balance;
}
.empty__lead em {
  font-style: normal;
  color: var(--accent);
  /* 朱砂下划线：只有这一处，用在"下一步动作"上，是全站唯一的装饰线。
     暗色侧 accent 是 #D9705E，压在 #121110 页底上对比度约 7:1，够读。 */
  text-decoration: underline;
  text-decoration-color: var(--accent-line);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* 三条要点。用 CSS 计数器画序号，避免在 HTML 里写 1/2/3
   （将来加删一条时，序号不会对不上）。 */
.empty__points {
  margin-top: var(--s5);
  display: grid;
  gap: var(--s3);
  counter-reset: pt;
}
.empty__points li {
  position: relative;
  padding-left: var(--s6);
  font-size: var(--fs-sm);
  line-height: 1.65;
  color: var(--ink-1);
  counter-increment: pt;
}
.empty__points li::before {
  content: counter(pt);
  position: absolute;
  left: 0;
  top: 1px;
  display: grid;
  place-items: center;
  width: 20px; height: 20px;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
}
.empty__points b { color: var(--ink-0); font-weight: 600; }

.empty__acts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}
.empty__alt {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* 空态示意块。
   ★ 用四边齐全的浅框，不用虚线框：虚线在中文界面里太像"待上传的占位"，
     而这块要表达的是"结果就长这样"。
   ★ 不加阴影，让它比左栏输入框低一层：用户此刻要动手的地方是左边。 */
.empty__demo {
  margin: var(--s7) 0 0;
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-1);
}
.empty__demo-cap {
  margin-bottom: var(--s3);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--ink-3);
}
.empty__demo-line {
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  line-height: 1.8;
  color: var(--ink-1);
}
/* ★ 两行都要有内边距：只给"改后"那行加，它就会比"改前"右缩一格，
   两句话的左边缘错开：而这两行**必须能逐字对齐着看**，
   错开一格，读者就得重新找起点，"哪几个字被换掉了"立刻变难。 */
.empty__demo-line + .empty__demo-line { margin-top: var(--s2); }

/* 「改前 / 改后」小标。做成固定宽度的行内块，两行的正文才能左边缘对齐：
   用普通过来，两行字会因为标签宽度不同而错开一格。 */
.empty__demo-tag {
  display: inline-block;
  min-width: 2.6em;
  margin-right: var(--s2);
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
}
/* 高亮画法与报告里的命中同源：朱砂软底 + 下划线。
   ★ 用 border-bottom 而不是 text-decoration：这里要跟报告的命中样式一致，
     报告那边是用背景色块表达"这几个字被盯上了"。 */
/* 高亮：走"朱砂字 + 实线下划线"，不靠底色。
   ★ 2026-11-06 实测判据为什么绿而人眼看不见：
     正文与高亮底色的对比度是 11.37（亮） / 18.77（暗），铁定过 AA：
     但那量的是"字读不读得清"，而用户要的是"哪几个字被标出来了"。
     后者看的是**色块与底面的差**：亮色 1.52、暗色 1.07，暗色下等同于没有。
     ⇒ 换成字色 + 下划线，这两个都是"线条/文字"级对比，暗底上依然清楚。 */
.empty__demo-line mark {
  padding: 0 1px;
  background: none;
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
/* 「改后」那一行用绿色软底区分，不用左侧竖线：
   单边竖线正是 landing-page-design 禁用的那种"一侧画条线"写法。 */
/* 「改后」只多一层绿底，内边距与「改前」完全相同（不另加 padding），
   这样两行的字左边缘才对得齐。 */
.empty__demo-line--after {
  background: var(--good-soft);
  color: var(--ink-1);
}
.empty__demo-line--after strong { color: var(--ink-0); }
.empty__demo-foot {
  margin-top: var(--s3);
  font-size: var(--fs-micro);
  color: var(--ink-3);
}

/* 兼容旧结构（查重空态仍是「一句话 + 两个按钮」）。 */
.empty .btn { margin-top: var(--s4); }
.empty__acts .btn { margin-top: 0; }

/* ---------- 骨架屏 ---------- */
.pane-skeleton { position: relative; }
.sk {
  border-radius: var(--r);
  background: linear-gradient(90deg, var(--paper-2) 25%, var(--paper-3) 37%, var(--paper-2) 63%);
  background-size: 400% 100%;
  animation: sk 1.4s ease-in-out infinite;
}
@keyframes sk { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.sk--gauge { height: 92px; margin-bottom: var(--s5); }
.sk--row { height: 34px; margin-bottom: var(--s2); }
.sk--para { height: 14px; margin-bottom: var(--s2); }
.sk--para:last-of-type { width: 62%; }
.pane-skeleton__text {
  margin-top: var(--s4);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  font-family: var(--mono);
}

/* ---------- 提示条 ---------- */
/* 提示条不再用「左侧一道彩色竖条」表达状态：那个写法在模板里出现率太高，
   一眼就露馅。改成整圈边框 + 底色，状态由标题自己说清楚（「没跑起来」）。 */
.banner {
  padding: var(--s4);
  border: 1px solid var(--accent-line);
  border-radius: var(--r);
  background: var(--accent-soft);
}
.banner__title { display: block; margin-bottom: var(--s1); }
.banner__body { color: var(--ink-1); font-size: var(--fs-sm); line-height: 1.7; }
.banner .btn { margin-top: var(--s3); }

.notice {
  margin-top: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  font-size: var(--fs-sm);
  color: var(--ink-1);
}

/* ---------- 分数 ---------- */
.report { animation: rise .32s var(--ease) both; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } }

/* ---------- 结论条 ---------- */
/* 三个数并排，每个只带"标签 + 数 + 档位词"。
   原来自数字底下还各挂一句解释（"套话、空话、机械连接词的密度与句式节奏合成"），
   三句占了首屏最贵的位置，却一个字都不随数据变，等于把结论埋进了说明里。
   现在三个数的定义合成一句，挂在整条下面。 */
.verdict { padding-bottom: var(--s5); border-bottom: 1px solid var(--line); }

.scoreline {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s4) var(--s5);
}

.score { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.score__label { font-size: var(--fs-micro); color: var(--ink-2); }
.score__value {
  font-family: var(--mono);
  font-size: var(--fs-display);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--ink-0);
}
.score__value[data-band="good"] { color: var(--good); }
.score__value[data-band="warn"] { color: var(--warn); }
.score__value[data-band="bad"] { color: var(--accent); }
.score__band {
  align-self: flex-start;
  padding: 1px 7px;
  border-radius: var(--r-sm);
  background: var(--paper-2);
  font-size: var(--fs-micro);
  color: var(--ink-1);
}
.score__band[data-band="good"] { background: var(--good-soft); color: var(--good); }
.score__band[data-band="warn"] { background: var(--warn-soft); color: var(--warn); }
.score__band[data-band="bad"] { background: var(--accent-soft); color: var(--accent); }
.score--plain .score__value { color: var(--ink-1); }

.verdict__note {
  margin-top: var(--s4);
  max-width: 74ch;
  font-size: var(--fs-sm);
  line-height: 1.75;
  color: var(--ink-2);
}
.verdict__note b { color: var(--ink-1); }

.block-title {
  margin: var(--s5) 0 var(--s2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-1);
}

/* ---------- 分项：细条无轨道 ---------- */
/* 每项原来是「标签 …… 读数 / 细条 / 一句解释」四行，七项二十八行。
   解释整批收进折叠之后，剩下的三行铺得密一点反而不挤。 */
.meters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--s3) var(--s5);
}
.meter { display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: var(--s2); }
.meter__label { font-size: var(--fs-sm); }
.meter__readout {
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-2);
  text-align: right;
}
.meter__bar {
  grid-column: 1 / -1;
  height: 3px;
  border-radius: 2px;
  background: transparent;
}
.meter__fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: var(--ink-3);
  transform-origin: left;
  animation: grow .5s var(--ease) both;
}
.meter__fill[data-status="good"] { background: var(--good); }
.meter__fill[data-status="warn"] { background: var(--warn); }
.meter__fill[data-status="bad"] { background: var(--accent); }
.meter__fill[data-status="na"] { background: var(--line-strong); }
@keyframes grow { from { transform: scaleX(0); } }
.meter[data-na="1"] .meter__label { color: var(--ink-2); }

/* ---------- 折叠：说明性文字的归处 ---------- */
/* 说明不是不重要，是不该和结论抢同一个平面。
   收进 details：想查原理的人点一下，其余人一眼扫过去。 */
.fold { margin-top: var(--s4); }
.fold summary {
  display: inline-block;
  min-height: 24px;
  font-size: var(--fs-micro);
  color: var(--ink-2);
  cursor: pointer;
}
.fold summary:hover { color: var(--ink-0); }
.fold__list {
  margin-top: var(--s3);
  display: grid;
  gap: var(--s2);
  max-width: 74ch;
  padding-left: var(--s5);
}
.fold__list li { font-size: var(--fs-micro); line-height: 1.7; color: var(--ink-2); }
.fold__list li b { color: var(--ink-1); font-weight: 600; }

/* ---------- 建议 ---------- */
/* 建议原来一条一行、上下都是分隔线，看着像三行数据。
   它是"接下来做什么"，不是数据，用序号起头更像行动清单。 */
.advice { display: grid; gap: var(--s3); max-width: 72ch; counter-reset: adv; }
.advice li {
  position: relative;
  padding-left: var(--s5);
  color: var(--ink-1);
  font-size: var(--fs-sm);
  line-height: 1.75;
  counter-increment: adv;
}
.advice li::before {
  content: counter(adv);
  position: absolute;
  left: 0; top: .15em;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--accent);
}

/* ---------- 重复片段 ---------- */
/* 之前用 ul>li>flex 的写法，长片段会把 li 撑破，在页面上看着像一堆残破的输入框。
   改成流式 chip：整块是一个 片段+次数 的单元，换行由容器负责。 */
.repeats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}
.repeats li {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s2);
  max-width: 100%;
  padding: 4px var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-1);
  font-size: var(--fs-sm);
}
.repeats b {
  font-weight: 500;
  min-width: 0;
  overflow-wrap: anywhere;
}
.repeats .x {
  flex: none;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--accent);
}

/* ---------- 工具条 ---------- */
/* ---------- 操作条 ---------- */
/* 原来是个白底圆角卡片。卡片是"把东西抬起来"的表达，可它周围全是没有边框的
   内容行，只有它自己是张卡；抬起来的那点高度并没有表达出真实层级。
   改成与内容同底的一行，靠间距分组。 */
.actions {
  margin: var(--s6) 0 var(--s4);
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
}
.actions__note {
  flex-basis: 100%;
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.segmented {
  display: inline-flex;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-2);
}
.segmented button {
  min-height: 30px;
  padding: 0 var(--s3);
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.segmented button:hover { color: var(--ink-0); }
.segmented button[aria-checked="true"] {
  background: var(--paper-1);
  color: var(--ink-0);
  font-weight: 600;
  box-shadow: var(--shadow-1);
}
.segmented--sm button { min-height: 26px; font-size: var(--fs-micro); }

/* ---------- 标签页 ---------- */
.tabs {
  display: flex;
  gap: var(--s4);
  border-bottom: 1px solid var(--line);
}
.tabs button {
  position: relative;
  padding: var(--s3) 0;
  border: 0;
  background: transparent;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: color var(--t-fast) var(--ease);
}
.tabs button:hover { color: var(--ink-0); }
.tabs button[disabled] { opacity: .38; cursor: not-allowed; }
.tabs button[disabled]:hover { color: var(--ink-2); }
.tabs button[aria-selected="true"] { color: var(--ink-0); font-weight: 600; }
.tabs button[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--accent);
}

.views { padding-top: var(--s4); }
.view__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  flex-wrap: wrap;
  margin-bottom: var(--s3);
}
/* 勾选框本体只有 15px，但点按目标其实是整条 label（点文字也能勾）。
   给 label 一个最小高度，整行就成了合格的触控目标。 */
.inline-check {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 24px;
  font-size: var(--fs-sm);
  color: var(--ink-1);
}
.inline-check input { width: 15px; height: 15px; accent-color: var(--accent-solid); }

/* ---------- 句级诊断 ---------- */
.doc { counter-reset: s; }

.sent {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: var(--s3);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line);
  transition: background-color var(--t-fast) var(--ease);
}
.sent:hover { background: color-mix(in srgb, var(--paper-2) 60%, transparent); }
/* 严重度不再靠左侧色条表达（那是模板里最廉价的装饰，而且和本页其它地方的
   整边框风格不一致）。改成把**序号染色**：序号本来就在，是真实信息，
   染色不额外占位。正文里的荧光笔高亮和下面的命中标签仍在说同一件事。 */
.sent[data-level="noticeable"] .sent__no { color: var(--warn); }
.sent[data-level="high"] .sent__no,
.sent[data-level="severe"] .sent__no { color: var(--accent); font-weight: 600; }

.sent__no {
  counter-increment: s;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-3);
  text-align: right;
  padding-top: 4px;
}
.sent__no::before { content: counter(s); }

.sent__body { min-width: 0; }
.sent__text {
  font-size: var(--fs-md);
  line-height: 1.85;
  max-width: 74ch;
  text-wrap: pretty;
}
.sent__hits {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s2);
}
.hit {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s2);
  padding: 2px 8px;
  border-radius: var(--r-sm);
  background: var(--paper-2);
  border: 1px solid var(--line);
  font-size: var(--fs-micro);
  color: var(--ink-1);
}
.hit b { font-weight: 600; color: var(--ink-0); }
.hit--hollow, .hit--template, .hit--parallel, .hit--syntax { border-color: var(--accent-line); }
.hit--opening, .hit--connector { border-color: color-mix(in srgb, var(--warn) 40%, transparent); }

.sent__risk {
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-2);
}

/* 高亮：像荧光笔在纸下划了一道 */
mark.hl {
  padding: 0 1px;
  border-radius: 2px;
  background: transparent;
  color: inherit;
  box-shadow: inset 0 -.62em 0 var(--hl-mark, var(--hl-1));
}
mark.hl[data-kind="opening"], mark.hl[data-kind="connector"] { --hl-mark: var(--hl-2); }
mark.hl[data-kind="hollow"], mark.hl[data-kind="template"],
mark.hl[data-kind="parallel"] { --hl-mark: var(--hl-1); }
mark.hl[data-kind="redundant"], mark.hl[data-kind="idiom"],
mark.hl[data-kind="lexical"], mark.hl[data-kind="syntax"] { --hl-mark: var(--hl-3); }

/* ---------- 改写对照 ---------- */
.pairs { display: grid; gap: var(--s3); }

.pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-1);
  overflow: hidden;
}
.pair__side { padding: var(--s3) var(--s4); min-width: 0; }
/* 底色给「原文」侧，让「改写后」保持干净的主表面。
   反过来做的话，结果看起来像"被禁用"的那一半，主次就颠倒了。 */
.pair__side:first-child { background: var(--paper-2); }
/* 两栏之间的竖线是**内部分隔**，不是"只在盒子一侧画条线当装饰"那种单边边框。
   写法上改成 inset 阴影，盒模型里不再出现 border-left：
   布局宽度不用再为这 1px 做补偿，窄屏下也不会出现"线留下来了但位置错了"。 */
.pair__side + .pair__side { box-shadow: inset 1px 0 0 var(--line); }
.pair__tag {
  display: block;
  margin-bottom: var(--s2);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  color: var(--ink-3);
}
.pair__text { font-size: var(--fs-md); line-height: 1.85; text-wrap: pretty; }
.pair--same .pair__text { color: var(--ink-2); }
.pair__rules {
  margin-top: var(--s2);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}
.pair__rule {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
  background: var(--paper-2);
  border-radius: var(--r-sm);
  padding: 1px 6px;
}

del.d { background: var(--accent-soft); color: var(--accent); text-decoration: line-through; text-decoration-thickness: 1px; }
ins.i { background: var(--good-soft); color: var(--good); text-decoration: none; border-radius: 2px; }

/* ---------- 全文 ---------- */
.fulltext {
  margin: 0;
  padding: var(--s4) var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
  font: var(--fs-md) / 1.95 var(--font);
  white-space: pre-wrap;
  word-break: break-word;
  max-width: none;
  text-wrap: pretty;
}

/* ---------- 输出框：结果区的第一屏 ---------- */
/* 用户原话：「这降AI和降重都要有个输出框啊，用户降AI的文字你降过后他不要有个地方复制吗」。
   所以它是结果区里最上面、也是最大的一块；分数与逐句诊断全部收进下面的 .fold--diag。 */
.out {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
  padding: var(--s5);
}
.out__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-bottom: var(--s3);
}
.out__title { font-size: var(--fs-md); font-weight: 600; color: var(--ink-0); }
/* 状态行（改了多少句 / 分数从哪到哪）右对齐：它是结论，不是标题的一部分 */
.out__stat { margin-left: auto; font-size: var(--fs-micro); color: var(--ink-2); }
.out__body {
  margin: 0;
  padding: var(--s4) var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-2);
  font: var(--fs-md) / 1.95 var(--font);
  white-space: pre-wrap;
  word-break: break-word;
  min-height: 180px;
  max-height: 52vh;
  overflow: auto;
  text-wrap: pretty;
}
/* 空的输出框必须自己说明「这里会出现什么」，否则它只是一块灰底。 */
.out__body:empty::before {
  content: "改好的正文会出现在这里，可以直接选中或复制。";
  color: var(--ink-2);
}
.out__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  margin-top: var(--s4);
}
.out__note { margin-top: var(--s3); font-size: var(--fs-micro); line-height: 1.7; color: var(--ink-2); }
.out__note:empty { display: none; }

/* ---------- 诊断折叠：默认收起 ---------- */
/* 用户原话：「你一开始给我看这么多东西我头都晕了」。
   分数、分项、逐句、对照都还在，只是要点一下才展开。 */
.fold--diag {
  margin-top: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
}
.fold--diag > summary {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-height: 46px;
  padding: 0 var(--s5);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-1);
  cursor: pointer;
  list-style: none;
}
.fold--diag > summary::-webkit-details-marker { display: none; }
.fold--diag > summary::before {
  content: "＋";
  font-weight: 400;
  color: var(--ink-3);
}
.fold--diag[open] > summary::before { content: "－"; }
.fold--diag > summary:hover { color: var(--ink-0); }
.fold--diag[open] > summary { border-bottom: 1px solid var(--line); }
.fold__body { padding: var(--s4) var(--s5) var(--s5); }
.fold__body > :first-child { margin-top: 0; }

/* 空态里的两个按钮排一行 */
.empty__acts { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s4); }
.empty__acts .btn { margin-top: 0; }

/* ---------- 缺参考材料：把注意力拉过去 ---------- */
/* 只在用户点了按钮却没材料时闪一次；它是"请你补这里"的手势，不是装饰。 */
@keyframes sugao-attn {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-line); }
  45% { box-shadow: 0 0 0 4px var(--accent-line); }
}
.is-attn { animation: sugao-attn 1.5s ease-in-out 1; border-radius: var(--r-lg); }

.warnstrip {
  margin-top: var(--s4);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  background: var(--warn-soft);
  border: 1px solid color-mix(in srgb, var(--warn) 38%, transparent);
  font-size: var(--fs-sm);
  color: var(--ink-1);
}

.footnote {
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
  max-width: 70ch;
  font-size: var(--fs-micro);
  line-height: 1.75;
  color: var(--ink-2);
}

/* ---------- 抽屉 ---------- */
.scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-scrim);
  background: rgba(20, 18, 17, .42);
  backdrop-filter: blur(2px);
  animation: fade .2s var(--ease) both;
}
@keyframes fade { from { opacity: 0; } }

.drawer {
  position: fixed;
  top: 0; bottom: 0;
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
  width: min(420px, 92vw);
  background: var(--paper-1);
  box-shadow: var(--shadow-3);
  animation: slide-r .26s var(--ease) both;
}
.drawer--right { right: 0; }
.drawer--left { left: 0; animation-name: slide-l; }
@keyframes slide-r { from { transform: translateX(18px); opacity: 0; } }
@keyframes slide-l { from { transform: translateX(-18px); opacity: 0; } }

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  flex: none;
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.drawer__head h2 { font-size: var(--fs-lg); }
.drawer__head-actions { display: flex; gap: var(--s2); }
.drawer__body { flex: 1; overflow-y: auto; padding: var(--s5); }
.drawer__hint { margin-bottom: var(--s4); font-size: var(--fs-micro); color: var(--ink-2); }

.group {
  margin: 0 0 var(--s6);
  padding: 0;
  border: 0;
  border-top: 1px solid var(--line);
  padding-top: var(--s4);
}
.group legend {
  padding: 0;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.group__hint {
  margin-top: var(--s2);
  font-size: var(--fs-micro);
  line-height: 1.7;
  color: var(--ink-2);
  max-width: 52ch;
}
.group__actions { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s4); }
.test-result { font-size: var(--fs-micro); font-family: var(--mono); color: var(--ink-2); }

/* ---------- 历史 ---------- */
.hist { display: grid; gap: var(--s2); }
.hist li { border-bottom: 1px solid var(--line); }
.hist button {
  display: block;
  width: 100%;
  padding: var(--s3) 0;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
}
.hist button:hover .hist__head { color: var(--accent); }
.hist__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  margin-bottom: var(--s1);
  font-size: var(--fs-sm);
  font-weight: 600;
  transition: color var(--t-fast) var(--ease);
}
.hist__meta { font-family: var(--mono); font-size: 11px; color: var(--ink-3); font-weight: 400; }
.hist__excerpt {
  font-size: var(--fs-micro);
  line-height: 1.6;
  color: var(--ink-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hist__empty { font-size: var(--fs-sm); color: var(--ink-2); }

/* ---------- Toast ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: var(--s6);
  z-index: var(--z-toast);
  transform: translateX(-50%);
  max-width: min(560px, 88vw);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-1);
  box-shadow: var(--shadow-2);
  font-size: var(--fs-sm);
  animation: toast-in .24s var(--ease) both;
}
.toast[data-kind="error"] { border-color: var(--accent-line); background: var(--accent-soft); }
.toast[data-kind="ok"] { border-color: color-mix(in srgb, var(--good) 42%, transparent); background: var(--good-soft); }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } }

/* ---------- 窄屏 ---------- */
@media (max-width: 1080px) {
  .shell { grid-template-columns: 1fr; gap: var(--s5); }
  /* 窄屏是单栏，左栏不再 sticky：限高和内部滚动要一起撤掉，
     否则在手机上会把输入区压成一个只有几百像素高的滚动窗。 */
  .col--input { position: static; max-height: none; overflow: visible; }
  /* 单栏布局下左栏不再是滚动窗，钉在"栏底"就等于钉在视口底、会盖住结果区。
     这里必须一起撤掉，否则手机上一路往下读报告时按钮一直压在内容上。 */
  .col__cta { position: static; padding-top: 0; background: none; box-shadow: none; }
  .editor__area { min-height: 200px; max-height: 40vh; }
  .scoreline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .score--plain { grid-column: 1 / -1; }
  .pair { grid-template-columns: 1fr; }
  .pair__side + .pair__side { border-left: 0; box-shadow: inset 0 1px 0 var(--line); }
}

@media (max-width: 640px) {
  .topbar__inner { padding: 0 var(--s4); min-height: 56px; }
  .shell { padding: var(--s4) var(--s4) var(--s8); }
  .brand__text i { display: none; }
  /* 窄屏空态：主句与要点各让出一档字号，否则 390 宽下三行要点会挤成七行。
     引导按钮占满整行，跟着说明文字另起一行：横排时它会和按钮抢同一行，
     在 390 宽上必然折成两截，看着像半句话被切断。 */
  .empty { padding-top: var(--s5); }
  .empty__lead { font-size: var(--fs-lg); }
  .empty__acts { flex-direction: column; align-items: stretch; gap: var(--s2); }
  .empty__acts .btn { width: 100%; }
  .empty__alt { text-align: center; }
  .scoreline { grid-template-columns: 1fr; }
  .score--plain { grid-column: auto; }
  .sent { grid-template-columns: 22px minmax(0, 1fr); gap: var(--s2); }
  /* 手指比鼠标粗：窄屏把可点的东西整体加高。桌面端不加，否则这套密排的
     工作台会松垮得没法用。 */
  .btn--tiny { min-height: 34px; }
  .segmented button { min-height: 34px; }
  .tabs button { padding: var(--s4) 0; }
  .col__cta .btn { min-height: 46px; }
  .inline-check { min-height: 32px; }
  .inline-check input { width: 18px; height: 18px; }
  .ref__btn { min-height: 32px; padding: 4px 10px; }
  .fulltext { padding: var(--s3); }
  .toast { bottom: var(--s4); }
}

/* ---------- 降低动效 ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .btn:active { transform: none; }
}

/* ==========================================================================
   查重 / 降重
   两张脸：查重报告（跟谁重、重在哪）与降重对照（改了什么）。
   刻意把「与参考库重复率」和「文内自重复」分开放，合成一个数是骗人的。
   ========================================================================== */

/* ---------- 模式切换 ---------- */
.mode {
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}
.mode__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  flex-wrap: wrap;
}
.mode__title { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-1); }
.mode__note {
  margin-top: var(--s3);
  font-size: var(--fs-micro);
  line-height: 1.75;
  color: var(--ink-2);
  max-width: 62ch;
}

/* ---------- 参考材料 ---------- */
.refs {
  margin-top: var(--s4);
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
}
.refs__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.refs__title { font-size: var(--fs-sm); font-weight: 600; }
.refs__hint { margin-top: var(--s2); font-size: var(--fs-micro); line-height: 1.75; color: var(--ink-2); }
.refs__actions { margin-top: var(--s3); display: flex; flex-wrap: wrap; gap: var(--s2); }
.refs__empty { font-size: var(--fs-micro); color: var(--ink-2); padding: var(--s3) 0; }

.reflist { margin-top: var(--s3); display: grid; gap: var(--s2); }
.ref {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-0);
  overflow: hidden;
  transition: border-color var(--t-fast) var(--ease);
}
.ref[data-open="1"] { border-color: var(--line-strong); background: var(--paper-1); }
.ref__head { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); }
.ref__name {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  padding: 2px 0;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.ref__name:focus { outline: none; border-bottom: 1px solid var(--accent); }
.ref__meta { flex: 0 0 auto; font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.ref__btn {
  flex: 0 0 auto;
  /* 原来 padding 2px + 11px 行高 = 23.6px，比 WCAG 2.2 AA 的 24px 差一点。
     实测出来的，不是看出来的。 */
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 2px 8px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink-1);
  border-radius: var(--r-sm);
  padding: 2px 8px;
  font-size: 11px;
  line-height: 1.6;
  cursor: pointer;
}
.ref__btn:hover { border-color: var(--accent-line); background: var(--accent-soft); color: var(--ink-0); }
.ref__btn--danger:hover { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }
.ref__body { padding: 0 var(--s3) var(--s3); }
.ref__text {
  display: block;
  width: 100%;
  min-height: 120px;
  max-height: 320px;
  resize: vertical;
  padding: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-0);
  font: var(--fs-sm) / 1.85 var(--font);
  word-break: break-word;
}
.ref__text:focus { outline: none; border-color: var(--accent); }

.field--tight { margin-top: var(--s3); }

/* ---------- 查重报告 ---------- */
.dup { animation: rise .32s var(--ease) both; }
.dup .scoreline { grid-template-columns: 1.15fr 1fr 1fr; }

.block { margin-top: var(--s5); }
.block > .block-title { margin-bottom: var(--s3); }

/* 降重前后 */
.dcmp { display: grid; }
.dcmp li {
  display: grid;
  grid-template-columns: minmax(7.5em, auto) minmax(0, 1fr) minmax(0, 1.5fr);
  align-items: baseline;
  gap: var(--s3);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line);
}
.dcmp li:first-child { border-top: 1px solid var(--line); }
.dcmp__k { font-size: var(--fs-micro); color: var(--ink-2); }
.dcmp__v {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  font-family: var(--mono);
  font-size: var(--fs-micro);
}
.dcmp__was { color: var(--ink-3); }
.dcmp__arrow { color: var(--ink-3); }
.dcmp__now { font-weight: 600; color: var(--ink-0); }
.dcmp__now[data-band="good"] { color: var(--good); }
.dcmp__now[data-band="bad"] { color: var(--accent); }
.dcmp__tag { font-size: var(--fs-micro); line-height: 1.7; color: var(--ink-2); }
.dcmp__foot { margin-top: var(--s3); font-size: var(--fs-micro); line-height: 1.75; color: var(--ink-2); }

/* 各来源命中 */
.srcbars { display: grid; gap: var(--s3); }
.srcbar {
  display: grid;
  grid-template-columns: minmax(6em, 12em) minmax(48px, 1fr) 4.6em;
  grid-template-areas: "name bar num" "meta meta meta";
  align-items: center;
  gap: 2px var(--s3);
}
.srcbar__name {
  grid-area: name;
  font-size: var(--fs-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.srcbar__bar {
  grid-area: bar;
  height: 8px;
  border-radius: 999px;
  background: var(--paper-2);
  overflow: hidden;
}
.srcbar__fill { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
.srcbar__num {
  grid-area: num;
  text-align: right;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-1);
}
.srcbar__meta { grid-area: meta; font-size: 11px; line-height: 1.6; color: var(--ink-3); }

/* 命中片段 */
.segs { display: grid; gap: var(--s2); }
.seg {
  padding: var(--s3);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  background: var(--paper-1);
}
/* 过阈值和没过阈值的片段：区别放在整圈边框的深浅上，不再用左侧色条。
   opacity 也去掉了：它会把「片段长度」这个关键数字一起调淡。 */
.seg[data-hot="0"] { border-color: var(--line); }
.seg__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s2); }
.seg__no { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.seg__len { font-family: var(--mono); font-size: var(--fs-micro); font-weight: 600; color: var(--accent); }
.seg[data-hot="0"] .seg__len { color: var(--ink-2); }
.seg__src { margin-left: auto; font-size: 11px; color: var(--ink-3); }
.seg__text {
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  line-height: 1.85;
  color: var(--ink-1);
  word-break: break-word;
}

/* 标题后面的计数 chip 靠左，别被 .view__bar 的 space-between 推到正中间 */
.view__bar > .block-title + .chip { margin-right: auto; }

/* 句内命中率 */
.sent__ratio {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-2);
}
.sent__ratio-bar {
  display: inline-block;
  width: 54px;
  height: 5px;
  border-radius: 999px;
  background: var(--paper-2);
  overflow: hidden;
}
.sent__ratio-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
.sent__risk--soft { color: var(--ink-3); }

/* 查重命中高亮：过阈值的用朱砂，没过阈值的用赭黄 */
mark.hl[data-kind="dup"] { --hl-mark: var(--hl-2); }
mark.hl[data-kind="dup"][data-hot="1"] { --hl-mark: var(--hl-1); }

/* 降重对照里的指标行 */
.pair__metric {
  margin-top: var(--s2);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
}
.pair__metric b { font-weight: 600; color: var(--ink-1); }
.pair__metric b[data-band="good"] { color: var(--good); }
.pair__metric b[data-band="bad"] { color: var(--accent); }
.pair__bad { color: var(--accent); }

@media (max-width: 1080px) {
  .dup .scoreline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dup .scoreline > .score:last-child { grid-column: 1 / -1; }
  .dcmp li { grid-template-columns: 1fr; gap: 4px; }
}

@media (max-width: 640px) {
  .dup .scoreline { grid-template-columns: 1fr; }
  .dup .scoreline > .score:last-child { grid-column: auto; }
  .srcbar {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name num" "bar bar" "meta meta";
  }
  .ref__meta { display: none; }
  .refs { padding: var(--s3); }
  /* 小屏上输出框要占满宽，且别被 max-height 压成一条缝 */
  .out { padding: var(--s4); }
  .out__body { padding: var(--s4); font-size: var(--fs-sm); max-height: 60vh; }
  .out__stat { margin-left: 0; }
  .fold--diag > summary { padding: 0 var(--s4); }
  .fold__body { padding: var(--s4); }
}

/* ==========================================================================
   页脚与条款页（2026-09-22 上线新增）
   页脚是全站信息，不归属任何一栏；条款页是独立文档，走 .legal 一套排版。
   ★ 两处都在 T12g 的管辖范围内：文案里不许有 em dash。
   ========================================================================== */

.pagefoot {
  border-top: 1px solid var(--line);
  background: var(--paper-1);
}

.pagefoot__inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s2) var(--s5);
  max-width: 1440px;
  margin: 0 auto;
  padding: var(--s4) var(--s5);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.pagefoot__brand {
  font-weight: 600;
  color: var(--ink-1);
  letter-spacing: .04em;
}

.pagefoot__links { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s4); }

.pagefoot__links a {
  color: var(--ink-1);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-strong);
}

.pagefoot__links a:hover { color: var(--accent); text-decoration-color: var(--accent-line); }

/* ★ 触控目标下限（WCAG 2.5.8 是 24px）。
   13px 的行内文字本身只有 21px 高。2026-09-22 实测：新加的页脚链接
   当场被 probe-layout 报红（「服务条款与隐私说明:21px」），这条是真 bug 不是假红。
   页脚与条款页里的这些链接都是**独立的可点目标**（不在句子里，没有行高豁免），
   所以用 inline-flex + min-height 把可点区域撑到 28px；文字位置与视觉外观不变。
   ★ 只对独立链接这么做。正文里的行内链接（比如「见条款页」夹在句子中间）
     按 WCAG 的行内豁免不动：给它们加 28px 行高会把行距撑坏。 */
.pagefoot__links a,
#contact a {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
}

/* 这句跟着右边走；窄屏折行后它自己占一行，不许被压成一列字 */
.pagefoot__note { margin-left: auto; }

@media (max-width: 640px) {
  .pagefoot__note { margin-left: 0; flex-basis: 100%; }
}

/* ---------- 条款页 ---------- */
.legal {
  max-width: 780px;
  margin: 0 auto;
  padding: var(--s6) var(--s5) var(--s8);
}

/* ★ 这里原本有一条 .legal__back（条款页左上角的「返回」链接），已删除：
   条款页顶上就是顶栏里的「返回工作台」，再加一个重复入口只是多一处要维护的样式。
   删它的直接证据是 grep：整个仓库里除这两行 CSS 之外没有任何地方用过这个类名。 */
.legal h1 { font-size: var(--fs-display); }
.legal__meta { margin-top: var(--s2); color: var(--ink-2); font-size: var(--fs-sm); }

.legal h2 {
  margin: var(--s6) 0 var(--s3);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
  font-size: var(--fs-xl);
}
.legal h2:first-of-type { margin-top: var(--s6); border-top: 0; padding-top: 0; }

.legal h3 { margin: var(--s5) 0 var(--s2); font-size: var(--fs-lg); }

.legal p, .legal li, .legal dd { color: var(--ink-1); }
.legal p + p, .legal p + ul, .legal ul + p, .legal p + dl { margin-top: var(--s3); }

.legal ul { list-style: disc; padding-left: 1.4em; }
.legal ul li { margin-top: var(--s2); }
.legal ul li::marker { color: var(--ink-3); }

.legal dl dt { margin-top: var(--s3); font-weight: 600; color: var(--ink-0); }
.legal dl dd { margin-top: 2px; }

.legal code {
  font-family: var(--mono);
  font-size: .92em;
  padding: 1px 5px;
  border-radius: var(--r-sm);
  background: var(--paper-2);
}

/* ★ 表格必须自己吃下横向溢出（overflow-x: auto），否则它会顶到文档级，
   verify/probe_layout.mjs 量的是 document.scrollWidth 差，一超就报红。 */
.legal__scroll { margin-top: var(--s3); overflow-x: auto; }
.legal table { width: 100%; min-width: 420px; border-collapse: collapse; font-size: var(--fs-sm); }
.legal th, .legal td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.legal th { background: var(--paper-2); color: var(--ink-0); font-weight: 600; }
.legal td { color: var(--ink-1); }

/* 提示块：原来是一条 3px 左边线 + 直角圆角，是典型的"引用条"。
   landing-page-design 明确禁单边边框：它不是装饰，而是把"这是一个块"
   这件事交给一条线去说，读者得自己补完四边。现在改成四边齐全的软底块：
   底色浅、边框淡、圆角一致，一眼就是"一整块提醒"。 */
.legal__callout {
  margin-top: var(--s4);
  padding: var(--s4);
  border: 1px solid var(--accent-line);
  border-radius: var(--r);
  background: var(--accent-soft);
}
.legal__callout p { color: var(--ink-0); }

/* ==========================================================================
   定价页（2026-10-08）
   复用条款页的 .legal 容器与全部令牌，只补卡片和购买弹窗。
   ★ 没有引入任何新颜色：价格是文字，不需要第二种强调色。
   ========================================================================== */

.price__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5);
  margin-top: var(--s5);
}
/* ★ minmax(0, 1fr) 而不是 1fr：长列表项会把网格撑破（T12 那类横向溢出），
   窄屏下改成单列，与工作台的分栏断裂点一致。 */
@media (max-width: 640px) {
  .price__grid { grid-template-columns: minmax(0, 1fr); }
}

.price__card {
  display: flex;
  flex-direction: column;
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
}
.price__card--pro { border-color: var(--accent-line); }

.price__name {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-lg);
  font-weight: 600;
}
.price__badge {
  padding: 2px var(--s2);
  border-radius: var(--r-sm);
  background: var(--warn-soft);
  color: var(--warn);
  font-size: var(--fs-micro);
  font-weight: 400;
}
.price__amount {
  margin-top: var(--s3);
  font-size: var(--fs-display);
  font-weight: 600;
  color: var(--ink-0);
  font-variant-numeric: tabular-nums;
}
.price__per { font-size: var(--fs-md); font-weight: 400; color: var(--ink-2); }
.price__unit { margin-top: var(--s1); font-size: var(--fs-sm); color: var(--ink-2); }

.price__list {
  flex: 1;
  margin: var(--s4) 0 0;
  padding: 0;
  list-style: none;
}
.price__list li {
  position: relative;
  margin-top: var(--s2);
  padding-left: 1.4em;
  font-size: var(--fs-sm);
  color: var(--ink-1);
  /* ★ 必须写在 li 上。.legal ul { list-style: disc } 命中的是 ul，
     而 li 会继承它：只在 .price__list（ul）上写 none 挡不住，
     结果就是每一项同时画了灰色默认圆点和下面那个朱砂圆点。
     2026-11-06 放大三倍才看见，1x 截图里只是两个挨着的点。 */
  list-style: none;
}
.price__list li::before {
  content: "";
  position: absolute;
  left: .3em;
  top: .72em;
  width: .36em;
  height: .36em;
  border-radius: 50%;
  background: var(--accent);
}
.price__cta { margin-top: var(--s5); }
.price__cta .btn { text-decoration: none; }

.modal {
  position: fixed;
  z-index: var(--z-drawer);
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  width: min(440px, calc(100vw - var(--s5)));
  max-height: calc(100vh - var(--s6));
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-1);
  box-shadow: var(--shadow-3);
}
/* ★ display:flex 会盖掉 hidden 的默认 display:none，必须显式关掉，
   否则弹窗从页面一打开就杵在中间（这类"隐藏不生效"不会报任何错）。 */
.modal[hidden] { display: none; }

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.modal__head h2 { margin: 0; font-size: var(--fs-lg); }
.modal__body { padding: var(--s5); }
.modal__body p, .modal__body li { color: var(--ink-1); }
.modal__lead { font-size: var(--fs-sm); }
.buy__price {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--ink-0);
  font-variant-numeric: tabular-nums;
}
.modal__notice {
  margin-top: var(--s4);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper-2);
  font-size: var(--fs-sm);
}
.modal__notice p + p { margin-top: var(--s2); }
.modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--s2);
  padding: var(--s4) var(--s5);
  border-top: 1px solid var(--line);
}
