/* ============================================================
   tokens.css — Dreamanual --dt-* token 体系（统一站合并版）
   my.dreamanual.com，2026-09-11 由 book / words 两侧合并
   ------------------------------------------------------------
   来源与裁定（依据 MY-ARCHITECTURE.md §6.2）：
     - 品牌 / 交互 / 预警色  → 采用 book 的墨黑系（蓝退让给「收入」语义）
     - --dt-income / -expense / --lh-* / --gap-list  → book 独有，保留
     - --fw-bold  → words 独有，并入
     - 字号  → 采用 book 的 5 档，words 旧名走下方【兼容别名层】
   本文件是唯一需要维护的 token 源；两侧不再各持一份。
   ============================================================ */

/* ---- 全局 hidden 守卫（2026-09-14）----
   `hidden` 属性在 UA 样式表里只是 `[hidden] { display: none }`；任何作者样式里的
   `display: flex/block/...` 都会把它覆盖（作者样式胜 UA，与选择器优先级无关）。
   本库有多个组件类自带 display，漏写守卫的元素会「本该隐藏却永远显示」——
   打卡点地图就曾被自己的降级层整块盖住，表现为「白屏且无任何提示」。
   统一在此收口，组件侧不必再逐个写 `[hidden]`。 */
[hidden] { display: none !important; }

/* ---- 全局双击缩放禁用（2026-10-06 第 184 批，用户报障）----
   现象：移动端**快速双击页面**（不是点按钮，是点空白/文字）整页被放大一次，
        放大后不易缩回，用户每页都要手动捏回去。
   修法 = `touch-action: manipulation`：保留 pan（滚动）与 pinch-zoom（双指缩放），
        **只关掉 double-tap-to-zoom**（MDN 明确列出这是 manipulation 唯一的差值）。
   ⚠️ 全站收口写在**根元素 html** 上，一处即覆盖 12 个页面（每页都加载本文件）。
      为什么之前漏：book.css 只在三个触点（键位 / 大号金额 / 提交钮）上写了这条
      —— 那是 78 批为「快速连点数字键被 iOS 判成双击缩放」局部开的药，
      治的是那三个元素，页面其余部分照旧放大。
   ⚠️ 严禁改 viewport 的 `user-scalable=no` / `maximum-scale`（book.css 1136 已记）：
      iOS 10 起 Safari **直接忽略**它，加了只会制造「已经治好了」的错觉。
   ⚠️ 与 places.css 的 `touch-action: none`（地图手柄）、lightbox.css 的 `none`
      不冲突：touch-action 沿祖先链求交集，局部更严的值仍然生效。 */
html { touch-action: manipulation; }

/* ---- 全局横向溢出守卫（2026-09-15）----
   任何元素比视口宽都会把整个页面拖出横向滚动（真机上「页面能左右晃」的根源）。
   只在根上收口：根的 overflow 会传播给视口、不产生新的滚动容器；
   容器内部的横向滚动（.chip-row 单行横滑等）也不受影响。
   hidden → clip 级联：clip 连滚动容器都不产生，对 sticky / 弹性滚动零副作用；
   老浏览器（Safari<16）回退 hidden（Chrome 实测 sticky 不受影响）。
   隐藏溢出 ≠ 修复溢出：各滚动容器自身的 overflow-x 约束见各模块 CSS。 */
html { overflow-x: hidden; overflow-x: clip; }

:root {
    /* ---- 基础表面（2026-09-26 第 127 批机核密度档；2026-10-11 第 209 批收 inset）----
       bg 加深一档（slate-50→100）换取去卡片描边后的分层对比。
       🔴 2026-10-11：inset 由板外色 #eaf0f6（slate-150）**并入 --dt-bg**。
          理由：跨站对齐要求两边都落板（Tailwind v4 没有 150 档，最近的是 slate-200，
          而它是 127 批被真机退回的值）。inset 的宿主（白卡上的井/chip、统计盒、
          图标 chip、hover 淡底）几乎都落在 --dt-raised 白底之上 ⇒ 白 vs 浅灰的层次仍在，
          只是浅灰从 slate-150 变成 slate-100。「直接坐在页面底色上的 inset 元素」
          逐处核过，没有页面级的大面积块。
       🔴 顶栏恒白走 --dt-raised（shell.css .app-topbar），不随 bg 加深。 */
    --dt-bg: #f1f5f9;
    --dt-raised: #FFFFFF;
    --dt-overlay: #FFFFFF;
    --dt-inset: var(--dt-bg);
    /* --dt-fill2（与 inset 同值的重复档）已退役（157 追修④）：零产品消费 */

    /* ---- 品牌与交互：黑白化（2026-09-10）----
       蓝色全面退让给「收入」语义，交互色 = 墨黑；
       hover 染色用黑 alpha，焦点环用深灰，蓝不再承载交互含义 */
    --dt-brand: #0f172b;
    --dt-brand-lt: #1d293d;
    /* --dt-brand-bg / --dt-brand-sec 已退役（157 追修④）：零消费者 */
    --dt-brand-acc: #e2e8f0;
    --dt-brand-surf: #f1f5f9;
    --dt-interact: #0f172b;
    /* --dt-interact-lt 已退役（157 追修④）：零产品消费 */
    --dt-interact-bg: #1d293d;      /* btn-primary / fab hover */
    --dt-interact-sec: #45556c;
    --dt-interact-acc: #90a1b9;
    --dt-interact-surf: #f1f5f9;    /* 激活 chip 底 = inset 灰 */
    /* --dt-focus（深灰描边）已退役（157 追修④）：icon-picker active 收编后零产品
       消费；focus 一律 accent 内描边 + 光晕（shell.css §5b-2 配方）。死 token 会给
       禁用样式开「既有 token = 获批用法」的合法门。
       --dt-focus-light（10% 灰蓝覆底）已退役（157 追修②，用户裁决）：唯一消费者
       tx-focus 高亮正是 §0 红线 2 否决的灰底形态。删 token = 断「既有 token」这扇
       把禁用样式带进来的合法门。 */
    /* ---- 交互强调蓝（2026-09-26 第 127 批）----
       聚焦环专用（filter-bar 搜索卡 :has 聚焦态）。锚在产品已有的 blue-600
       （= --dt-income 同值）上做 color-mix，不新造色相；🔴 刻意独立 token
       而非复用 --dt-income：金额蓝与交互蓝语义解耦，可各自漂移。 */
    --dt-accent: #155dfc;
    --dt-accent-border: color-mix(in srgb, #155dfc 40%, #fff);   /* ≈ blue-300 浅蓝边 */
    --dt-accent-glow: color-mix(in srgb, #155dfc 10%, transparent);
    --dt-interact-a04: rgba(15, 23, 43,.04);
    --dt-interact-a06: rgba(15, 23, 43,.06);
    --dt-interact-a12: rgba(15, 23, 43,.12);
    --dt-interact-a20: rgba(15, 23, 43,.20);

    /* ---- 文本与边框 ---- */
    --dt-text1: #0f172b;
    --dt-text2: #45556c;
    --dt-text3: #62748e;
    --dt-text4: #90a1b9;
    --dt-text5: #cad5e2;
    --dt-text-inv: #FFFFFF;
    --dt-border: #e2e8f0;
    --dt-border-str: #cad5e2;
    /* 卡片描边退役（第 127 批机核模式）：分层靠底色（bg/inset/raised 三层），
       描边透明化而非删 token —— 模块侧仍有 border:1px solid var(--dt-card-border) 引用 */
    --dt-card-border: transparent;

    /* ---- 数据语义色（收支对：蓝橙为色盲安全对） ---- */
    --dt-income: #155dfc;       /* blue-600，蓝只表达收入 */
    --dt-income-bg: #dbeafe;    /* blue-100 */
    --dt-expense: #ff6900;      /* orange-500：橙 = 支出（记账）；评分点亮 327 批定案、348 批改走下方三档阶 */
    --dt-expense-bg: #ffedd4;   /* orange-100 */
    /* 打卡点拇指三档点亮色（348 批用户定案，推翻 327 批「色彩不分档」）：
       v4 官方橙阶 200/400/600 跳档组合，浅到深＝点亮序；跨度 2.24 为三案（甲/乙/丙）最大。
       主站 places.html 补值块有同名令牌（镜像规则，漂移门禁比声明体）。 */
    --dt-rank-1: #ffd6a7;       /* v4 orange-200，白底 1.36 */
    --dt-rank-2: #ff8903;       /* v4 orange-400，白底 2.38 */
    --dt-rank-3: #f54900;       /* v4 orange-600，白底 3.60 */
    --dt-error: #fb2c36;        /* 红 = 涨（行情模块 §15.5 局部类）/ 异常 / 预警 */
    --dt-warning: #fb2c36;      /* 预警并入红（原橙退役，避免与支出橙撞车） */
    --dt-amber: #fe9a00;        /* 保留：words 得分按钮描边、进度段（原评分点亮色，327 批换 --dt-expense） */
    --dt-amber-bg: #fffbeb;
    --dt-amber-text: #e17100;
    /* 评分三档字色（2026-10-12 第 215 批；327 批删除）：五颗圆角星 → 三档文字 → 三个拇指。
       327 批曾定「点亮不分档」全走 --dt-expense；348 批用户定案改按点亮序下发三档
       （上方 --dt-rank-1/2/3），本节仅存历史。历史判据（图形门槛 3:1 / 12px 文字
       4.5:1 的差）见 doc/30-根因与判据/DEV-NOTES §190。 */
    --dt-success: #00a63e;      /* 绿 = 跌（行情模块 §15.5 局部类）/ 收入好 */
    --dt-info: #0084d1;         /* 已退役：原转账天蓝，转账改灰；保留 token 备用 */
    --dt-error-bg: #ffe2e2;
    --dt-warning-bg: #ffe2e2;   /* 预警底随红 */
    --dt-success-bg: #dcfce7;
    --dt-info-bg: #dff2fe;

    /* ---- 语义色边框 ----
       🔴 浅阶边框档全组退役：--dt-warning-border 已删（2026-09-26 第 127 批），
          --dt-success-border / --dt-error-border 零消费者同批删（157 追修④）。
          语义色一律 bg 底 + text 前景，不单独开边框浅阶。 */
    --dt-tooltip-bg: #1d293d;

    /* ⚠️ 原 book 在下方「此处」还有一组 oklch 蓝色重复定义
       （--dt-focus / --dt-focus-light / --dt-interact-a04/06/12/20），
       覆盖了上面的墨黑值，导致「黑白化」实际未生效（R3）。
       合并时已整组删除，只保留墨黑一组。
       验收：--dt-focus 计算值为 #62748e，非 oklch 蓝。 */

    /* ---- 字体 ----
       🔴 2026-10-03（182 批）**全站只用系统字体栈，不加载任何 webfont**。
       原值含 'Inter' / 'Noto Sans SC' 两支 Google Fonts 字体，但：
       ① 骨架内联样式用 `font:` 简写重置了 body 的 font-family，Inter 在 my 上
          **从未真正渲染**（探针 document.fonts.check('12px Inter') = false）——
          11 页文字实际一直由系统字体绘制；
       ② band 无任何 webfont 加载，Inter 靠本机安装命中，于是两站字重观感分叉。
       现两仓 token 同时收成系统栈，band 向 my 看齐，跨站渲染同源。
       ⚠️ 要换网络字体必须同时撤掉骨架 `font:` 简写（check-skeleton-semantic §
       骨架字体段逐项对拍会红），单改本 token 会让骨架与真值脱钩。 */
    --font-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif;
    --font-mono: 'JetBrains Mono', 'SF Mono', Monaco, monospace;
    --font-en: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

    /* ---- 字号阶梯（2026-09-26 第 127 批机核密度档：12/14/16/18/24）----
       heading 20→18（机核整体字号实测；--fs-xl 别名随之 18，与 dates/shelf
       天数块同尺规）。caption/body/title 桌面值不动。 */
    --fs-caption: 12px;  /* 标签/badge/图表角标/时间戳（最小档） */
    --fs-body:   14px;   /* 正文/输入框/按钮（基准，body 默认字号） */
    --fs-title:  16px;   /* 卡片标题/次级标题 */
    --fs-heading: 18px;  /* 卡片大数/次级页标题/弹窗标题 */
    --fs-page:   24px;   /* 页面标题/概览大数 */

    /* ---- 兼容别名层（words 沿用旧名，值即上表，不产生第二套字阶）----
       合并策略：不改 words 的 139 处引用，而在源头做别名。
       下列 5 个 token 在各页面的计算值与 book 同名档位完全一致，视觉不变。 */
    --fs-sm:  var(--fs-caption);   /* 12px ← words 57 处 */
    --fs-md:  var(--fs-body);      /* 14px ← words 31 处 */
    --fs-lg:  var(--fs-title);     /* 16px ← words 13 处 */
    --fs-xl:  var(--fs-heading);   /* 20px ← words  6 处 */
    --fs-2xl: var(--fs-page);      /* 24px ← words  2 处 */

    /* ---- words 的扩展档（book 5 档里无对应值，独立保留） ---- */
    --fs-xs:  10px;   /* 日历/趋势角标（最小可用）       ← words  8 处 */
    --fs-3xl: 28px;   /* 展示级：专注模式的单词大字号    ← words  4 处 */
    --fs-4xl: 36px;   /* 展示级：专注模式 / 总览大数     ← words  2 处 */

    /* ---- 输入框档（2026-09-17），全站输入控件的**唯一**字号开关 ----
       iOS Safari 对「聚焦时字号 < 16px」的 input / select / textarea 会自动放大页面，
       且**不保证缩回**（只要用户捏合过、或在放大态里滚过，blur 后就可能停在放大态）。
       所以正确解法是**不触发**，而不是想办法缩回 —— 触屏下把输入控件抬到 ≥16px。
       ⚠️ 值必须写 var(--fs-body)/var(--fs-caption) 而不是字面 14px/12px：
          一是桌面观感与改动前逐像素一致（零回归），二是将来调字阶时输入框自动跟随。
       ⚠️ 任何作用在输入控件上的 font-size 都必须走这两个 token —— 写死字面值会被
          check:input 门禁咬住（它是跨模块的，见 tools/check-input-zoom.cjs）。
          `::placeholder` 也走同一 token：它不参与缩放判定（缩放只看控件自身字号），
          但让它与控件同档，触屏下不会出现「占位字比输入字小一号」的错位。 */
    --fs-input:    var(--fs-body);      /* 输入框基准档：桌面 14px */
    --fs-input-sm: var(--fs-caption);   /* 输入框小档：桌面 12px（紧凑行内输入） */

    /* ---- 行高（三档，与字号角色配套；book 独有） ---- */
    --lh-tight: 1.35;    /* 标题 / 单行数据 */
    --lh-body:  1.45;    /* 正文 / 列表行（body 基准） */
    --lh-prose: 1.55;    /* 段落 / 说明文字 */

    /* ---- 字重（四档：regular + medium + semibold + bold） ---- */
    --fw-normal: 400;
    --fw-medium: 500;
    --fw-semibold: 600;
    --fw-bold: 700;      /* words 独有，16 处引用 */

    /* ---- 圆角（2026-09-26 第 127 批机核密度档：6/4）----
       机核 radius 全站仅 0/4 两档（0×771 / 4×59）⇒ lg 12→6、md 8→4。
       控件档 --shell-radius-control 在 shell.css（8→4 同批）。
       ⚠️ 旧注释提到的「pages/book.css 密度层覆盖」已不存在（实测全仓无第二覆盖点）。 */
    --radius-sm: 4px;
    --radius-md: 4px;
    --radius-lg: 6px;
    --radius-full: 9999px;   /* 胶囊/圆形：角标 / 开关 / 状态点 / 拖拽把手 */

    /* ---- 阴影 ---- */
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
    --shadow-md: 0 2px 8px rgba(0,0,0,0.08);
    --shadow-lg: 0 8px 24px rgba(0,0,0,0.12);

    /* ---- 间距原子层（2026-09-17），全站间距的**唯一**可调层级 ----
       🔴 语义 token（--gap-* / --pad-*）一律引用本层；模块侧**禁止**写间距字面值 ——
          字面值不参与触屏补偿，会在「字号整条上移」时显得更紧（全站变成
          「有的松了有的还紧」，比不调更难看）。
       为什么需要原子层：字号在触屏下整条上移（见文件末触屏块）后，**绝对间距
          相对变小**、观感变紧。要让间距跟着字号走，就得先让它在源头可调。
          实测（2026-09-17）：全站间距声明 595 处，其中字面值 572 处、
          token 覆盖仅 10.8% —— 所以本轮先建「可调层级」，再分两批收编字面值。
       命名为 --sp-<桌面值>：名字里的数字是**桌面**像素值，触屏值见文件末触屏块
          （与 --fs-caption 在两态下取不同值同理）。
       🔴 奇数档（5 / 7 / 9 / 11 / 13 / 17）是**为保存历史字面值而设的镜像档**，
          它们不构成设计阶梯。之所以保留：补偿只应发生在触屏 —— 桌面必须逐像素
          不动（实机反馈只提到手机），所以不能把 9px 直接吸成 10px。
          新增间距请优先用偶数档，否则触屏阶梯会碎成「差 1px 的半档」。 */
    --sp-4:  4px;
    --sp-5:  5px;
    --sp-6:  6px;
    --sp-7:  7px;
    --sp-8:  8px;
    --sp-9:  9px;
    --sp-10: 10px;
    --sp-11: 11px;
    --sp-12: 12px;
    --sp-14: 14px;
    --sp-16: 16px;
    --sp-18: 18px;
    --sp-20: 20px;
    --sp-24: 24px;   /* 区块级：触屏**刻意不动**（页高涨幅的总闸门） */

    /* --sp-13 / --sp-17 / --sp-22 已退役（157 追修④）：零消费者。
       刻度补档按需新增——先有消费者再进表（check:spacing §1a 双向锁）。 */

    /* ---- 容器间距 / 卡片内边距（2026-09-26 第 127 批机核密度档）----
       🔴 **定值化**：本层从 `var(--sp-N)` 引用改为**字面值**——试验台 17 轮验收的
          就是定值形态（.temp/gcores-bench/ 的注入即落地内容）。取值基线 =
          触屏实值（原 coarse 原子层 +2：sp-12=14、sp-16=18、sp-20=22），
          定值后 coarse 补偿不再作用于本层，桌面与触屏同值。
          第一版按桌面名义值定 pad 的教训（2026-09-25）：与手机断点实值撞车，
          padding 杠杆在手机上空转 —— 所以必须以触屏实值为基线。
       与原子层的关系：--sp-* 原子层保留（触屏 +2 照旧），模块侧直接引用原子的
          地方仍受补偿；本语义层是「设计定档」，不再随指针形态漂移。 */
    --gap-section: 14px;   /* L1 主内容区 / Tab / 统计页区块间距（原 24） */
    --gap-block:   12px;   /* 首页网格 / 中等密度区块间距（原 20/触屏 22） */
    --gap-card:    8px;    /* L2 设置页 / 词库卡片 / 默认卡片间距（原 12/14） */
    --gap-head:    6px;    /* 卡内标题（section-head / card-head）→ 内容间距（与 gap-card 语义分离，勿混用）（原 12/14） */
    --gap-tight:   8px;    /* 统计网格 / 紧凑区块间距（原 12/14） */
    --gap-list:    4px;    /* L3 卡内列表 / 色块子卡间距（各密度统一）（原 8/10） */

    /* ---- 卡片内边距（2026-09-26 第 127 批，与上面间距同批定值化）---- */
    --pad-card-lg: 10px;   /* 大卡片 / 弹窗 / 登录卡垂直（原 16/18） */
    --pad-card-md: 8px;    /* 标准卡片垂直（最常用）（原 12/14） */
    --pad-card-sm: 6px;    /* 紧凑卡片 / 迷你卡垂直（原 8/10） */
    --pad-card-xs: 4px;    /* 列表项 / 词条卡垂直（原 8/10） */
    --pad-x-lg:    12px;   /* 大卡片水平（原 20/22） */
    --pad-x-md:    10px;   /* 标准卡片水平（原 16/18） */
    --pad-x-sm:    8px;    /* 紧凑卡片水平（原 12/14） */
    --pad-x-xs:    8px;    /* 列表项水平（原 12/14） */
}

/* ============================================================
   触屏输入框字号（2026-09-17），防 iOS Safari 聚焦自动缩放
   ------------------------------------------------------------
   判据：iOS 对 font-size < 16px 的 input / select / textarea 聚焦时会放大页面，
        14px 与 12px 两档都在阈值之下 ⇒ 全站输入框都会触发（实机：iPhone 17）。
   🔴 为什么整条阶梯一起上移，而不是只抬输入控件（第 31 批定案）：
      只把输入框抬到 16px 等于**把落差留在原地** —— 实机量测触屏 390px 下
      ≤14px 占文本元素 82.9%（其中 12px 一档就占 58.6%），输入框于是成了页面上
      唯一被拉到正常尺寸的元素，比正文大 2px，观感突兀（用户实机反馈）。
      真身是「整条阶梯按桌面密排定的，搬到手机上偏小」，不是「输入框太大」。
      故 body 14→16 与输入框同档 ⇒ 落差归零；caption 12→13、title 16→18 配套。
      ⚠️ 该约束由 check:input 门禁锁住：--fs-input 必须 **等于** --fs-body。
         将来若要让两者分档，必须同时改门禁与本注释（否则门禁会红）。
   为什么用指针能力查询而不是宽度断点：宽度断点会误伤窄窗桌面 ——
        Mac 上把窗口拖窄不该改变字号。Mac 无触摸屏 ⇒ 媒体查询不匹配，
        各档回到 12 / 14 / 16px，**桌面视觉零变化**。
   ⚠️ 窄屏布局覆盖仍走宽度断点（如 overview.css 的 max-width: 768px 改网格列数）——
      **布局密度与字号是两个正交维度**：窗口窄了要少列，但字号取决于「手指是否在点」。
      所以改字号必须回到本块，别写进宽度断点里（overview 那个块里的 20px 已收编到
      var(--fs-heading)，正是为此）。
   🔴 为什么是 any-pointer 而不是 pointer：`pointer` 取的是**主指针**，iPad 一旦
      接上妙控键盘/触控板，主指针就变成 fine —— 而那台设备照样会有人用手指去点
      输入框（照样缩放）。`any-pointer: coarse` 问的是「这台设备是否具备粗指针」，
      与「手指可能点它」这个真实前提对齐。Mac 无触摸屏，两者皆为 false，无差别。
      代价：带触摸屏的笔记本会一并拿到 16px 输入框 —— 那些机器本来也会缩放，
      属于顺带修好，可接受。
   🔴 为什么在 tokens.css 换值，而不是在 shell.css 写
      `@media (any-pointer: coarse) { .form-input { font-size: 16px } }`：
      CSS 加载顺序是 tokens → shell → 模块，**同特异性规则后加载者胜**，
      tokens.css 里的选择器会被 shell.css 的同名规则反杀（静默失效，且只有真机看得见）。
      自定义属性在 :root 上换值，发生在层叠**之后**的求值阶段，不受文件顺序与
      特异性的影响 —— 既不必上 !important，也不用堆优先级 hack。
   ⚠️ 这一层 jsdom 测不到（不求值媒体查询），真机几何由 check:input:browser 锁
      （puppeteer 触屏模拟 → 逐控件量 computed font-size）。
   ============================================================ */
@media (any-pointer: coarse) {
    :root {
        /* ---- 移动端字号（2026-09-26 第 127 批回落）----
           第 31 批的「整条阶梯上移」（13/16/18）被机核密度档推翻：试验台 17 轮
           在真机验收的就是 12/14/16（bench 超控样式后加载，把本块也压掉了）——
           用户裁决密度优先。正文 14 < 16 意味着输入框**必须**与正文解耦：
           --fs-input 独立锁 16（iOS 阈值），check:input 门禁 1-12/1-13 已同步改口径
           （input ≥ body 且 input ≥ 16；不再要求 input === body）。
           ⚠️ 输入框仍只准走 --fs-input*（段 3 静态扫描照旧）。 */
        --fs-caption:  12px;   /* 13 → 12：与桌面同档（机核移动端小字号） */
        --fs-body:     14px;   /* 16 → 14：密度档正文书（试验台真机验收形态） */
        --fs-title:    16px;   /* 18 → 16：与桌面同档 */
        --fs-input:    16px;   /* 🔴 独立锁 16 ≥ iOS 阈值；不再 = --fs-body（见上） */
        --fs-input-sm: 16px;   /* 紧凑档同样 ≥16，否则照样缩放 */
        /* --fs-heading(18) / --fs-page(24) / --fs-xs(10) 不在本块覆盖：
           heading 已随桌面档落到 18，page/xs 维持原判（大字号够用 / 角标怕挤）。 */

        /* ---- 间距原子层上移（2026-09-17 第 32 批）----
           动机：字号整条上移后，绝对间距**相对变小**（比值被稀释），
                 用户实机反馈「卡片内边距、元素间距显得略微有点小」。
           规则：**并入 2px 网格 + 每档 +2**，小档补得多、大档补得少 ——
                 8→10 是 1.25 倍、12→14 是 1.17 倍、20→22 是 1.10 倍。
                 「每档 +2」而非「等比 ×1.15」，是为了让值全部落在 2px 网格上
                 （等比会产生 9.2 / 13.8 这类非网格值，与相邻元素对不齐）。
           闸门：--sp-24 区块级间距**按住不动** —— 页面变长的主要来源就是区块间距，
                 放它会直接把页高推高 8%+。故本块最大档 = --sp-20 的触屏值 22px。
           ⚠️ 补偿发生在**求值阶段**（:root 上的自定义属性换值），不受文件加载
              顺序与特异性影响；这与字号那层同源，理由详见上方长注释第 4 段。
           ⚠️ 因此模块侧任何间距字面值都不会跟随 —— 收编进度见 check:spacing。 */
        --sp-4:  6px;
        --sp-5:  6px;
        --sp-6:  8px;
        --sp-7:  8px;
        --sp-8:  10px;
        --sp-9:  10px;
        --sp-10: 12px;
        --sp-11: 12px;
        --sp-12: 14px;
        --sp-14: 16px;
        --sp-16: 18px;
        --sp-18: 20px;
        --sp-20: 22px;
        /* --sp-13 / --sp-17 随桌面档退役（157 追修④）；--sp-24 未覆盖：
           区块级，见上方「闸门」。 */
    }
}

/* ============================================================
   颜色书写契约（全站）：颜色一律走 --dt-* 变量，禁止硬编码 hex；
   JS 里同理 —— 返回 token 名，不返回色值。
   ============================================================ */
