@import url("../fonts/outfit.css");  /* 西文 Outfit，本地内置；见 assets/fonts/README.txt */

/* ==========================================================================
   设计令牌
   所有数值集中在这里。品牌色由 site.json 在运行时覆盖（见 assets/js/core.js）。
   规则：色只用双锚点（暖白 / 近黑）加米色层次；字重只用 300/400/500；
        圆角只用 1/2/4px；动效只有一个 ease-out 200ms。
   ========================================================================== */

:root {
  /* ---- 颜色：暖白与近黑两个锚点，中间用米色层次过渡 ---- */
  --c-bg:        #FCFBFC;
  --c-bg-alt:    #F6F2F0;
  --c-bg-sunk:   #F1ECE8;
  /* ★ 2026-09-19 深夜：原来那条「头部上方留白带」的底色 --c-strip（#F7F7F7）**已删**。
     那条留白带其实是参考站的**顶部横幅位**，只是我们之前没做横幅、只留了空带子
     （用户在截图里圈着它问「这位置为什么是空的」）。现在横幅真的做了，
     页头 = 横幅 + 44px 导航行，不再需要一条纯留白带。 */
  /* 顶部横幅底色（原站 vib-top-banner 用内联 #eeeeee，后台「站点设置 → 顶部横幅」可改）。
     比导航行底色略深一点点，让两层分得出来。 */
  --c-banner:    #EEEEEE;
  --c-sand:      #E1DBD3;
  --c-line:      #E1DBD3;
  --c-line-2:    #CFC7BE;
  --c-ink:       #010101;
  --c-ink-2:     #3A3735;
  --c-muted:     #9C9186;
  --c-muted-2:   #B8AFA6;
  /* 浅底上「读得清」的次级灰。#9C9186 压在 #FCFBFC 上对比只有 2.99（WCAG AA 要 4.5），
     当说明文字、版权行这类小字用会看不清；#6F6862 是 5.31，够用且仍然是灰、不抢正文。
     --c-muted 本身保留 —— 它适合做**装饰性**的浅色（发丝线旁的小标、图标），别拿来排小字。 */
  --c-muted-ink: #6F6862;
  --c-white:     #FFFFFF;
  /* 首屏「磨砂玻璃」：面包屑 chip / 滚动提示 / 右侧速览面板共用。
     取参考站实测值（rgba(198,198,197,0.4) + blur 4px）—— 它是中性灰而不是暖白，
     压在浅色实景图上是一片浅灰、压在深色图上是一片中灰，两种底都读得出来。 */
  --glass:       rgba(198, 198, 197, 0.4);
  --glass-line:  rgba(1, 1, 1, 0.12);   /* 玻璃上的分隔线：深色发丝线，浅色玻璃上才看得见 */
  /* 浮动面板动作行的分隔线 —— 参考站实测是**真色** rgb(198,198,197) = #C6C6C5，
     不是半透明深色。半透明深色压在实景图上会随底图明暗忽深忽浅，参考站这条不会。
     （2026-09-21 用 _probe_alba_panel_io.py 量的：li 的 border-top-color。） */
  --glass-rule:  #C6C6C5;
  --glass-blur:  blur(4px);
  --c-accent:    #E41B25;   /* 品牌强调色，后台可改 */
  --c-accent-ink:#FFFFFF;
  /* ★ 2026-09-23 批 0：admin.css 里有一处 `var(--c-accent-soft, #FBF3E6)` ——
     作者写了兜底值、说明他**以为这个令牌存在**（"强调色的柔和底色"，用于选中的媒体卡）。
     这里把令牌补上，值取他当初写的兜底色 #FBF3E6，**不改变已生效的视觉**。
     （同处 admin.css 还有一版相近的硬编码 #F6EFE4，是另一件事，本批不动。） */
  --c-accent-soft:#FBF3E6;
  --c-ok:        #2E7D5B;
  --c-warn:      #B8860B;
  --c-err:       #C0392B;

  /* 深色区块 */
  --c-dark-bg:   #141312;
  --c-dark-ink:  #F2EEEB;
  --c-dark-line: #35322F;

  /* ---- 字号 ---- */
  --fs-10: 10px;
  --fs-11: 11px;
  --fs-12: 12px;
  /* ★ 2026-09-23（批 0 的 0.4）：这一格**一直是漏的** —— 阶梯直接 12 → 14。
     而 admin.css / components.css 共 **18 处** 引用 `var(--fs-13)`（其中 8 处没写兜底
     ⇒ 那些 `font-size` 静默失效、回退成继承值），另有 10 处靠 `, 13px` 兜底撑着。
     补这一行即可让全部引用生效，值与各处兜底里写的 13px 一致。
     （此前**没有任何判据在守**这件事，只有 admin.css 里一句人工注释记着 —— 见
      `v2/tools/check_css_vars.py`，本批补上的守卫。） */
  --fs-13: 13px;
  --fs-14: 14px;
  /* ★ v5：弹层字号放大 1.4 倍补齐的三个令牌（只增不改） */
  --fs-15: 15px;
  --fs-16: 16px;
  --fs-17: 17px;
  --fs-18: 18px;
  --fs-22: 22px;
  --fs-28: 28px;
  --fs-31: 31px;
  --fs-35: 35px;
  --fs-44: 44px;
  --fs-55: 55px;

  /* 标题用流式字号，避免断点里手写一堆覆盖 */
  --fs-h1: clamp(30px, 3.6vw, 55px);
  --fs-h2: clamp(24px, 2.3vw, 35px);
  --fs-h3: clamp(18px, 1.5vw, 22px);
  --fs-lead: clamp(16px, 1.2vw, 18px);

  /* ★ v17：页面主标题的字号是参考站的**阶梯**，不是流式（2026-09-22 实测换掉 clamp）
     参考站把产品名放在两处，都挂 `vib-heading--xl`：
       ① 首屏     `.vib-collection-detail-hero__title`
       ② 技术信息 `.vib-technical-info-section__title`
     十档视口实测（tools/_v17d_headings.py，原始值 _docs/_tmp/v17d_headings.json）：
       首屏名   : ≥1280 → 55px（行高 66）；768–1279 → 参考站**不渲染**该元素；≤767 → 22px（26.4）
       技术信息 : ≥768  → 55px；≤767 → 35px（42）
     `vib-heading--xl` 这个档位实测只有 55/66、35/42、22/26.4 三个值，字重恒 300，
     行高恒 = 字号 × 1.2 —— 没有中间值，所以**不能用 vw 连续插值**。
     → 主标题走 22 → 35（≥768）→ 55（≥1280）：55 与 22 是实测，
       35 那一档取自同一个 `--xl`（参考站在 768–1279 没有可比元素，这是外推，不是实测）。
     → 技术信息区名走 35（≤767）→ 55（≥768）：两档都是实测。
     ⚠️ 别改回 `clamp(30px, 3vw, 55px)`：1355 视口下只有 40.65px，比参考站小 14.35px。
     ★ v18：v17 里这条阶梯只有**产品名**在用，v18 起**全站 6 处页面级 H1**共用它 ——
       单品页 .pdp-hero__name、分类页 .cat-hero__title、空间案例 .sp-hero__title、
       内页首屏 .ph__title、产品总览 .dir-hero__title、块级首屏 .blk-hero__title
       （绑定写在 site.css 中部「页面主标题」那一块；那 6 个选择器里已经**没有**别的
       font-size 声明了，所以不靠先后顺序取胜，靠的是唯一来源）。
       语义因此从「产品名」扩成「页面主标题」→ 令牌名改用 --fs-hero；
       --fs-name 保留成**别名**（值不重复声明，别再新增引用）。
       ⚠️ 统一之前那 5 处各写各的 clamp（30→54 / 30→60 / 30→52 / 30→55），
          在 1280–1439 中间档互相差 10px 以上 —— 大字节奏是散的。 */
  --fs-hero: 22px;
  --fs-name: var(--fs-hero);   /* 旧名（v17 产品名专用）→ 别名；值的唯一定义处是上面 */
  --fs-sec:  35px;

  /* 页面主标题的行高恒 = 字号 × 1.2（参考站实测；和字号一样只有三档、没有中间值）。
     故意单开一个令牌、**不经** --lh-tight：后者在中文模式下会变成 1.3，
     而参考站的 66px 行高是**与语言无关**的（check_hero_geometry.py 里有同名断言守着）。 */
  --lh-hero: 1.2;

  /* ---- 字重：只有三档 ---- */
  --fw-light: 300;
  --fw-normal: 400;
  --fw-medium: 500;

  /* ---- 字距 ---- */
  --ls-tight: -0.01em;
  --ls-normal: 0;
  --ls-wide:   0.06em;
  --ls-wider:  0.14em;   /* 用于小号全大写标签 */
  --ls-widest: 0.22em;

  /* ---- 行高 ---- */
  --lh-tight: 1.15;
  --lh-snug: 1.4;
  --lh-normal: 1.7;
  --lh-loose: 1.95;

  /* ---- 间距：11 档 ---- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;
  --sp-8: 64px;
  --sp-9: 96px;
  --sp-10: 160px;
  --sp-11: 300px;

  /* ---- 圆角：只有三档 ---- */
  --r-1: 1px;
  --r-2: 2px;
  --r-4: 4px;
  /* ★ R7·Q5：补 8 档 —— 改前有两处浮层卡片（`.ed3w__side` / `.ad-moneyrow`）
     直接写 `border-radius: 8px` 绕过了本阶梯（`--r-*` 原来只到 4 就跳到 pill）。
     8 是"卡片 / 浮层"这一档，与 `--ad-r-pop` 同值但**用途不同**（那个是后台弹层专用）。 */
  --r-8: 8px;
  --r-pill: 999px;

  /* ---- ★ 2026-09-27 批 6.7：阴影（= 取代 border 的"线"）
     口径出处 = `v2/_docs/DESIGN.md` §6。核心一条：**shadow-as-border 取代 border** ——
     1px 的"线"用 `0 0 0 1px` 的外阴影画，不占布局、不与内线叠双线（Vercel 那套无色理性）。
     ⚠️ 用了就要在本文件有定义（本项目最恨"变量名拼错不报错" ⇒ 静默无边框）。 */
  --shadow-hairline:   rgba(1, 1, 1, .06) 0 0 0 1px;              /* 头发丝线：取代 border */
  --shadow-hairline-2: rgba(1, 1, 1, .08) 0 0 0 1px;              /* 稍重一点：可交互面 */
  --shadow-rule:       rgba(1, 1, 1, .04) 0 1px 0 0;              /* 只有下边一条：表头/分隔 */
  --shadow-pop:        rgba(1, 1, 1, .10) 0 8px 24px -4px,
                       rgba(1, 1, 1, .06) 0 0 0 1px;              /* 浮层（弹窗/下拉） */

  /* ---- ★ 2026-09-27 批 6.7之四：表格行高四档（飞书「低/中等/高/超高」）
     口径出处 = `v2/_docs/DESIGN.md` §4.8。**全表只由一个变量驱动** ——
     切换档位时 JS 只改 `--row-h` 一个值（`documentElement.style.setProperty`），
     所有行高/格高跟着走，不给每行/每格各写一份高度。
     ⚠️ 用 `--row-h` 的地方要用 `height:var(--row-h)`，别写死 px，否则切档不生效。

     ---- ★★ R7 · Q3（2026-09-30 23:5x 余总拍「四档平移」）：中档对齐规范「**标准行 48**」，
     四档间距均匀（8 / 16 / 16）。★ 全站行高整体 +8 ⇒ 已验收页面版式会跟着动（预期内）。
     ⚠️⚠️ 与 `admin.js` 的 `ROWH_PX` 映射表**同名同值，必须两处同改** ——
       漏一处 = 控件点了没反应（变量被 JS 按旧值写回 `:root` 内联样式，静默盖掉这里）。
     ⚠️ `.ad-media-grid` 的缩略图边长 = `--row-h × 3.1` ⇒ 图墙会跟着变大（同属「密度」语义）。 */
  --row-h: 48px;          /* 「中等」档 = 默认 = 规范「标准行」 */
  --row-h-low: 40px;      /* 「低」档 = 规范「紧凑行」 */
  --row-h-high: 64px;     /* 「高」档 */
  --row-h-xhigh: 80px;    /* 「超高」档 */

  /* ---- 动效：全站只有一个 ---- */
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --dur: 200ms;
  --dur-slow: 420ms;
  --tr: var(--dur) var(--ease);
  --tr-slow: var(--dur-slow) var(--ease);

  /* ---- 版式 ----
     容器与边距是照着参考站实测定的（2026-09-19，用无头浏览器量 vibia 2560×1405 视口）：
       .vib-container → max-width 1832px、padding-inline 16px、margin auto
       即内容区恒为 1800px：2560 屏上左右各留 380px，1184 屏上左右各留 16px。
     以前这里写的是 --gutter: clamp(20px,3.4vw,72px)，2560 屏上内容宽 2416px、
     和参考站的 1800px 差了 600px —— 这正是「logo / 导航位置不对」的根因。 */
  --container: 1832px;
  --shell: 1800px;        /* 内容区净宽 = 1832 - 16*2。横滚图组等「通栏但内容要对齐」的地方用它 */
  --gutter: 16px;
  /* 段间留白 —— 参考站实测：**任意视口下段与段之间恒为 120px**
     （1024 / 1355 / 1920 / 2560 四个视口各量 7 个接缝，全是 120，不随视口变）。
     我们的 section 是「每段自带上下 padding」，所以一边一半：120 / 2 = 60。
     ⚠️ 别改回 clamp(56px, 7vw, 120px)：那是早期自己定的，1355 下段间 189.7px，
        比参考站松 1.58 倍（v14 2026-09-21 收紧）。 */
  --sec-pad: 60px;
  --measure: 46em;        /* 正文最大行长 */

  /* ---- 头部 ----
     参考站头部是两层：
       ① 顶部横幅（vib-top-banner）——整条居中一行小字 + 右侧关闭按钮，
          padding sm/xl、font-size xs，实测约 31px；文字换行会自然撑高；
       ② 44px 的导航行。
     ★ 高度**不写死数值**：横幅高度由内容决定，`--header-h` 由 core.js 用
     ResizeObserver 把实测高度写回根元素，main 的 padding-top、首屏高度
     （calc(100svh - var(--header-h))）全都跟着它走。
     下面这两个值只是 JS 跑起来之前的**初值**，防止首帧跳动。
     实测锚点（横幅 31 + 导航 44 = 75 时）：logo 左缘 380、导航第 1 项左缘 620。 */
  --header-banner: 31px;      /* 横幅预估高（仅初值，JS 会覆盖 --header-h） */
  --header-nav: 44px;
  --header-h: calc(var(--header-banner) + var(--header-nav));

  /* ---- 字体 ----
     【已定死，不必再纠结】
     西文 = Outfit 300/400/500/600，本地内置（assets/fonts/，SIL OFL 1.1，免费商用）。
     原站用的是**商业字体 Gordita**（300/400/500），不可直接复刻或嵌入，
     所以按**字形指纹**在免费字体里实测挑了一个最接近的：
       指标 = 字串宽/大写高、x高/大写高、"essentials"宽/整串宽、数字宽/大写高、升降部/大写高
       结果 = Outfit 距离 0.1970 ＜ Figtree 0.3288 ＜ Hanken Grotesk 0.3810 ＜ …
              （换成 Outfit 之前用的 Jost 是 1.6163 —— 窄 8%、x 高低 4%，所以看着不像）
       结构也对：Gordita 的 a 是**单层 a**（洪水填充数孔验过），Outfit 同为单层 a。
     坑：以前第一位写 "Helvetica Neue"，而本机字体目录里只有 `Helvetica Neue Black.ttf` 一个字重，
     浏览器把 300/400/500 全解析成那个 Black —— 结果是「弧形落地灯 F01」里中文细、F01 特粗，
     所有数字（2700K / 2024 / 2100）也一起变粗。Arial / 微软雅黑的拉丁部分同样没有 300。
     中文不内置，交给系统中文栈（PingFang SC / 思源黑体 / 微软雅黑，都有 Light）。
     ★ 2026-10-03 SAGE 换皮复核：**字体不换** —— `UI设计规范_鼠尾草终端风.html`
       的头部 @font-face 就是同一份 Outfit（逐字节相同的 woff2），**无侵权风险**
       （SIL OFL 1.1 明确「可免费商用、可随站点分发」，见 assets/fonts/README.txt）。
       规范 §04 只规定「正文无衬线 ＋ 数据等宽」两条用法，本后台早已符合。 */
  --font-sans: "Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI",
               "PingFang SC", "Source Han Sans CN", "Source Han Sans SC",
               "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC",
               "Noto Sans SC", Arial, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;

  /* ---- 层级 ---- */
  --z-header: 100;
  --z-drawer: 200;
  --z-modal: 300;
  --z-toast: 400;
}

/* ==========================================================================
   ★★ 后台工具层（--ad-*）—— 2026-09-28 建层 · **2026-09-30 R7 全量对齐规范色**
   --------------------------------------------------------------------------
   为什么单开一层：后台原先直接吃上面的 --c-* —— 那套是 09-19 为**前台**写的
   品牌表达（暖白底 / 米色发丝线 / 圆角只 1·2·4）。前台的目标是「让人慢下来看灯」，
   后台的目标是「让人一天改几百行不出错」—— 两种目标不该共用一套界面规则。
   所以把令牌**拆成两段**，而不是去改前台的值：
       --c-*   前台品牌层（本文件上面的 :root，**一个值不改**）⇒ 前台零风险
       --ad-*  后台工具层（下面这一块）
   ★★ 2026-09-30 R7（余总原话）：「**后台严格遵守这套色 不用其它 后台与前台不同**」
     ⇒ 后台主色 = 规范青绿 `#1F4E5F`（**不再是品牌红**）；前台仍守品牌红 `#E41B25`。
       两者从本批起**有意分离** —— 品牌红只活在 LOGO 与前台。
     ⇒ 规范 **9 锚色**（一个字不许改，判据逐条守着）：
        主色 #1F4E5F · hover #265F71 · active #18404D · 成功 #00B42A · 警告 #FF7D00 ·
        危险 #F53F3F · 文字主色 #1D2129 · 文字禁用 #C9CDD4 · 边框 #DCDFE6
     ⇒ 规范未定义的槽位（页底灰 / 次级文字 / 发丝线 / 表单边框）：**沿用现值** ——
        都是中性色、不带色相，不构成「另一套色」。
     ⇒ ★ 语义三色（成功/警告/危险）对白底只有 **2.78 / 2.57 / 3.71**，过不了 WCAG AA 的
        4.5 ⇒ **只作填充 / 描边 / 圆点，不作文字色**；状态文字一律 `--ad-ink`（深灰），
        语义靠「淡底 + 色点 + 文字标签」表达（`_audit_wcag.py` 有一条在守这件事）。
   ★ 口径出处：`v2/_docs/DESIGN.md` §4.19（色系备选）·§4.20（WCAG 定级与准入线）·
     §4.19.9（R7 · 规范色对齐）；施工单 = 方案 §0.6.17 §D。
   ⚠️ 后台用色一律用 --ad-*；新写的后台样式**不许**再引 --c-*
     （守卫：`v2/tools/_audit_wcag.py` 扫「后台引用的颜色令牌无悬空 / 不再引 --c-*」）。
   ========================================================================== */
:root {
  /* ---- 底色：白卡片 + 冷灰页底 ---- */
  --ad-bg:        #FAFBF4;   /* 卡片 / 输入框底 · ★ R7·Q7 起**也是页面底**（整站去灰）
    ★★ 2026-10-03 SAGE 换皮（余总拍板「全站换皮」）：原 #FFFFFF 纯白 → #FAFBF4 纸面。
       依据 = `UI设计规范_鼠尾草终端风.html` §03 色彩体系「纸」层 --paper-2。
       ⚠️ 这条**推翻了 R7·Q7「整站去灰」** —— 不是偷偷改，见 DESIGN.md 同步标注。 */
  --ad-bg-alt:    #F0F1E9;   /* ★ 页面底 · SAGE 换皮：原 #F2F4F7 冷灰 → #F0F1E9 暖纸（--paper）
                                现用途：页面底 · 表头底 · 只读底 · 悬停底 · 下沉分组底 */
  --ad-bg-sunk:   #E9EAE2;   /* 下沉区（模态底下那层）· ★ 仍是「未选中标签」底 · SAGE --paper-sunken */
  --ad-bg-soft:   #E9EAE2;   /* 极淡底（侧栏 / 说明条）· SAGE 换皮：原 #F7F9FB 冷白(色相210)
    ⚠️ 2026-10-03 补漏：首轮换皮漏了这支 ⇒ 侧栏 / 斑马纹仍是冷白，与暖纸底(#F0F1E9,色相68)
       并排看是一条发蓝的带子。改取 SAGE --paper-sunken（色相68），与页面底同族。
       用途不变：侧栏底 / 斑马纹 / 极淡分组底。 */
  --ad-white:     #FFFFFF;
  --ad-zebra:     #E9EAE2;   /* 斑马纹 · ★ 换皮：原 #F7F9FB → --paper-sunken（与 --ad-bg-soft 同源） */

  /* ---- 线 ----
     --ad-line       装饰线（卡片边 / 分隔 / 虚线框）
     --ad-line-2     稍重的装饰线（hover 边）
     --ad-field-line ★ 表单控件边框专用：**3.1:1**，为 WCAG AA 1.4.11（非文本对比 3:1）
       单开一个：发丝线（1.2:1）压在白底上根本算不出「控件在哪」。 */
  --ad-line:       #DADFCC;   /* ★ 规范·边框 · SAGE 换皮：原 #DCDFE6 → #DADFCC（--line-1） */
  --ad-line-2:     #C8CCBE;   /* ★ SAGE 换皮：原 #C4CAD3 → #C8CCBE（--line-2） */
  /* ★★ 2026-10-03 SAGE 落地「其它页面」（批 S1）新增：样机 `--line-3 #A1A696`。
     ★ 用途 = **需要"看得出这条线"的地方** —— 现落在**表头下边线**（样机 `thead th` 就是它）。
       表头若用 `--ad-line`（1.31:1），表头与数据行"分不开"、读表时视线会串行。
       `--line-3` 对卡面 2.32:1 —— 作**装饰线**是合规的（非文本对比门槛只针对**控件边界**，
       表头下划线属"分隔线"不是"控件边界"），但明显比 `--ad-line` 醒目一档。
     ⚠️ 它**不可以**拿去当控件边框（2.32 ＜ 3:1）—— 那条正解是 `--ad-ctl-line`。 */
  --ad-line-3:     #A1A696;
  /* ★ 2026-09-28 22:3x 复算订正：初值取 #8B929C —— 压在**卡片白底**上是 3.14 ✓，
     但压在**页面底 #F2F4F7**上只有 2.85（页面底比卡片底深，吃掉一点余量）。
     输入框不保证都落在卡片里，所以按"最不利背景"取值：改成 #848A94
     ⇒ 卡片上 3.47 · 页面底上 3.15，两边都过 3:1（`_audit_wcag.py` 两条都守着）。 */
  --ad-field-line: #7E8470;
  /* ★★ 2026-10-03 SAGE 落地「其它页面」（批 S1 · 余总拍板）：
     样机 `--ctl-line #6E785A` —— 规范 §03 明确它是**唯一合规的控件边框色**
     （WCAG 1.4.11 非文本对比要 ≥3:1；`--line-2` 只有 1.44、`--line-3` 只有 2.20，
      两者**只能做装饰**）。
     ★ 实测对比度（本批新算，见 check_sage_pages.py D2）：
          样机 #6E785A  卡面 4.48 · 页底 4.11 · 凹陷 3.85   ← 全部过 3:1，余量足
          旧值 #7E8470  卡面 3.72 · 页底 3.41 · 凹陷 3.20   ← 刚过线，视觉上"灰得要看不见"
     ⇒ 余总原话「按钮默认状态下**透明底 加边框 黑字**」的关键就是**这条边要看得见**。
     ⚠️ **为什么不直接改 `--ad-field-line` 的值**：它被后台 40+ 处控件引用，
        直接改值会牵动所有已验收页面（不可控）。⇒ 新增一支、语义更明确的 `--ad-ctl-line`，
        由本批需要它的组件（`.btn--ghost` / `.input` / `.ad-inp` 等）**显式引用**；
        `--ad-field-line` 保持原值当兼容别名，将来统一时再收。 */
  --ad-ctl-line: #6E785A;

  /* ---- 字 ----
     数字列原吃 --c-muted-2（#B8AFA6，**2.16:1**，全后台最浅的一档灰、用了 67 处）
     ⇒ 这一档在后台直接**废掉**，一律并到 --ad-ink-2。 */
  --ad-ink:       #0E1405;   /* ★ 规范·文字主色 · SAGE 换皮：原 #1D2129 → #0E1405（--ink，对暖纸 16.47:1） */
  --ad-ink-2:     #3E4A30;   /* 次级 / 数字列 / 备注 · SAGE 换皮：原 #2B3138 → #3E4A30（--ink-2） */
  --ad-muted-ink: #5C6350;   /* 说明小字 / 表头 · SAGE 换皮：原 #5A626C → #5C6350（--ink-muted） */
  --ad-muted:     #6E785A;   /* 装饰性浅色（图标 / 占位符）· ★ 换皮：原 #616A76 冷灰(色相214)
    → SAGE --line-3/#6E785A 一族的低饱和橄榄（色相79）。对暖纸 4.05:1、纸面 4.42:1
    —— 装饰件不设门槛，但同族色不会在暖底上发蓝。 */
  /* ★ R7 新增：规范·文字禁用 #C9CDD4。
     WCAG 1.4.3 对「失效 / 不可用控件」**豁免**对比度（1.59:1）—— 所以这档浅是合规的。
     但它**只许给禁用态文字**，不许拿去排任何需要阅读的字（判据守着）。 */
  --ad-ink-off:   #B8BEA8;   /* ★ 换皮：原 #C9CDD4 冷灰(色相218) → SAGE --line-3 同族暖灰(色相79)

  /* ---- ★★ 主色：SAGE 深橄榄 #263819 ----
     ⚠️ 2026-10-03 余总拍板「**B 全站换皮**」—— 原青绿 #1F4E5F（R7·Q2）退役，
     改为 `UI设计规范_鼠尾草终端风.html` §03 的「墨」层 --olive。
     前台仍是 #E41B25（在文件上面的 --c-accent；判据守着它没被误改）。 */
  --ad-accent:    #263819;   /* 主色 · SAGE 深橄榄（对 #FAFBF4 约 14.2:1） */
  --ad-accent-2:  #344628;   /* 主色 hover · SAGE --olive-2 */
  --ad-accent-3:  #4A5C36;   /* 主色 active · SAGE --olive-3 */
  --ad-acc-bg:    #F1FED3;   /* 主色淡底（选中底 / 淡强调）· SAGE --lime-1 */
  --ad-acc-line:  #CFDCA8;   /* 主色描边（选中描边）· SAGE --lime-4 */
  --ad-lime-2:    #E1E9C2;   /* ★ 2026-10-03 新增（余总拍板）：SAGE --lime-2 «激活导航 / 提示条底»
    ★ 为什么不复用 --ad-ok-bg（同为 #E1E9C2）：那一支是**语义成功色**，用在导航激活上会让
      「选中态」与「成功态」共用一个令牌 —— 将来改成功色会连带改掉侧栏选中，是隐性耦合。
      ⇒ 单独一支、只表「青柠高光」，与 --ad-acc-bg（lime-1）/ --ad-acc-line（lime-4）成族。
    ★ 用途：侧栏激活项文字色（配 --ad-accent 深橄榄底 = 规范 §7.1「激活＝橄榄底青柠字，靠反色不靠阴影」）。 */
  --ad-lime-3:    #DCE6BE;   /* ★ 2026-10-03 SAGE 落地（批 S1）新增：SAGE --lime-3。
    ★ 出处 = 样机热力图色阶的**第 3 档**（`.heat i.l3`）—— 它是青柠族里唯一
      `--ad-*` 没有对应的一支（lime-1/2/4 分别已被 acc-bg / lime-2 / acc-line 覆盖）。
    ★ 用途：热力图 `.sage-heat__c--2`（中间档）；也可作更深的"选中底"。
    ⚠️ 它与 --ad-lime-2 只差一档明度 —— 是**色阶**不是**语义**，别拿它当"另一个选中色"。 */
  --ad-docno:     #E4757E;   /* ★★ 2026-10-04（批 T4 · 需求 1 二次修正）新增（余总定死）：
    «单据单号链接字色»。余总原话「改文字色为 整行的颜色要恢复到之前 **#E4757E**」。
    ★ 用途：单据列表「单据编号」列 `.ad-table td.ad-ellink > a` 的**字色**（含悬停态整行）。
    ★ 为什么单独立一支、不复用别处：SAGE 换皮把 `--ad-link` 改成了橄榄 #263819，
      余总要的是换皮前的这个玫红 —— 若直接改 `--ad-link` 会连带动到**全站所有链接**
      （远超"单据列表"范围）⇒ 单立一支、只挂单据列表。
    ⚠️ **对比度 2.82:1**（对 #FAFBF4），低于正文 AA 4.5 线 —— 属余总**品牌色指定**，
      留档在此以便日后审计可追溯（不是疏漏，是定死项）。 */

  /* ---- ★ 语义色：**一律取规范值**，且**只作填充 / 描边 / 圆点，不作文字色** ----
     为什么不能作文字：规范值对白底只有 2.78 / 2.57 / 3.71，全在 WCAG AA 的 4.5 线下。
     本项目的用法 = 「语义淡底 + 色点 + `--ad-ink` 文字标签」—— 色不是唯一手段（1.4.1 ✓），
     文字也够黑（≥13:1 ✓）。谁把 `color:` 写成这三条之一，`_audit_wcag.py` 当场红。 */
  --ad-ok:        #6E7C4C;   /* 成功 · SAGE --sig-ok（仅填充/圆点） */
  --ad-ok-bg:     #E1E9C2;   /* SAGE --lime-2 */
  --ad-ok-line:   #CFDCA8;   /* SAGE --lime-4 */
  /* ★ R7·Q5：**成功态的"文字色"** —— 上面那三个都**不能当文字用**
     （`--ad-ok #00B42A` 压 `--ad-ok-bg #E8FFEA` 实测只有 **2.64:1**）。
     这一个是深绿，压 `--ad-ok-bg` **6.02:1** ✓ AA 达标。
     ⚠️ 为什么单独一个名：与 `--ad-err` 那种"填色兼文字"的做法不同 ——
        亮色系（ok/warn/err）在本项目**一律只做填充/描边/圆点**（见上面 --ad-err 的注释），
        文字另有深色版。这是 **R7 之前就有的正确做法**（`.od-badge--on` 本来就用它），
        本次只是把它从硬编码 `#2F6B45` 提成令牌。 */
  --ad-ok-text:   #4A5C36;   /* 成功文字 · SAGE --olive-3（压 --ad-ok-bg #E1E9C2 实测 6.55:1 ✓ AA） */
  --ad-warn:      #DFA843;   /* 警告 · SAGE --sig-mod（仅填充/圆点） */
  --ad-warn-bg:   #F5EEDC;   /* ★ 换皮：原 #FFF7E8 偏奶黄 → 与暖纸底同族的浅暖砂 */
  --ad-warn-line: #E8D9A8;
  --ad-err:       #E4757E;   /* 危险 · SAGE --sig-high（仅填充/圆点） */
  --ad-err-bg:    #F7E4E4;
  --ad-err-line:  #EFC6C9;

  /* ---- ★ 深底（顶栏）专用三态 —— DESIGN.md §2.4 原文值 ----
     为什么不复用 --ad-ok/--ad-warn/--ad-err：深底上**不能用浅底色块**，
     只能调文字与圆点的亮度；规范给的就是一套**更亮的浅色**。
     压深顶栏 `--ad-ink #1D2129` 实测：ok **11.90** · warn **12.66** · fail **10.56**
     —— 全部远超 AA 4.5。（原先误用亮色当文字：5.81 / 6.29 / **4.35**，最后一个不合格。）
     ⚠️ 这三个**只能在深底用**，白底上会看不清。 */
  --ad-dark-ok:        #b7e8d2;
  --ad-dark-ok-line:   rgba(120, 220, 180, .45);
  --ad-dark-ok-dot:    #43c08a;
  --ad-dark-warn:      #ffe0a8;
  --ad-dark-warn-line: rgba(240, 200, 110, .5);
  --ad-dark-warn-dot:  #e8b23a;
  --ad-dark-fail:      #ffc2c2;
  --ad-dark-fail-line: rgba(240, 140, 140, .5);
  --ad-dark-fail-dot:  #e05b5b;

  /* ---- ★ 语义色的「深版」（浅底可用）----
     与 `--ad-ok-text` 对称：亮色系（ok/warn/err）**只做填充 / 描边 / 圆点**，
     文字另有深色版。压白底实测：ok **6.34** · warn **6.99** · err **5.44** ⇒ 全部过 AA。
     `--ad-err-text` 同时可作**实心强调底**（白字压上去 5.44:1 仍达标），
     如 `.mini--danger:hover`；值取自前台 `--c-err`，前后台一个红。 */
  --ad-warn-text: #6B4A0A;   /* 警告文字（SAGE 换皮，压 --ad-warn-bg 实测 6.9:1 ✓ AA） */
  --ad-err-text:  #A33B44;   /* 危险文字（SAGE 换皮，压 --ad-err-bg 实测 5.4:1 ✓ AA） */

  /* ★★ 2026-09-29（批 18 · 余总定死）：「**全站链接一律不用下划线**」——
     靠**颜色**区分"这里能点"，悬停反馈靠**颜色加深**（不是加下划线）。
     ⇒ 需要一个**链接色**。当初单开了一支蓝（#185FA5）是为了跟品牌红拉开——
       ★ 2026-09-30 R7：主色已从红转青绿，那支蓝就成了「规范之外的另一种色」⇒ **并入主色**。
         现在链接 = 主色 `#1F4E5F`，悬停 = 主色 active `#18404D`；与主按钮同色系但形态可分
         （链接是文字、主按钮是实心）。
     ★ 对比度：默认 9.08:1 · 悬停 11.17:1 —— 双双远超 WCAG AA（4.5:1），小字也够。 */
  --ad-link:      #263819;   /* 链接（默认态）· 同主色 · SAGE 换皮（原 #1F4E5F 青绿） */
  --ad-link-2:    #4A5C36;   /* 链接（悬停 / 按下 —— 加深，不是加下划线）· SAGE --olive-3 */

  /* ---- 圆角三档（Linear 口径：数据面 / 交互元素 / 浮层 —— 见 DESIGN.md §4.18.6）---- */
  --ad-r-data:    4px;
  --ad-r-ctl:     6px;
  --ad-r-pop:     8px;
  /* ★★ 2026-10-03 SAGE 落地「其它页面」（批 S1）新增两档：样机 `--r-card 10` / `--r-card-lg 14`。
     ★ 为什么必须补：样机的**卡片**圆角是 10、大卡 14 —— 而我们原来只到 8（pop）。
       不补这两档 ⇒ 相位对齐时要么"卡片圆角照 8 写死"（与样机差 2px、像素级失守），
       要么"绕开阶梯硬编码 10px"（正是 R7·Q5 记录过的老毛病：绕过 `--r-*` 直接写值）。
     ★ 用途：`--ad-r-card` = 卡片 / 面板 / 表格容器（`.ad-panel` / `.ad-card` / `.tablewrap`）
             `--ad-r-card-lg` = 大容器（九宫格品类卡 / 报表图区 / 单据页头） */
  --ad-r-card:    10px;
  --ad-r-card-lg: 14px;

  /* ---- ★★ R7 · Q2：控件尺寸令牌（按钮 / 表单）--------------------------------
     依据 = 余总 2026-09-30 定：「后台严格遵守这套色」＋ 控件**双档**：
       舒适档 40（列表页 / 弹窗 —— 一天看几百行，要一眼看清）
       紧凑档 32（详情页密集表单 / 明细行 —— 一天改几百行，要一屏装下）
     ★ 紧凑档取 **32**（不是规范表格那节的 40）—— 余总原话「修正『表格紧凑 32』」。
     ★ 圆角统一 4（规范 §2.1 / §3.2），单开 `--ad-r-field` 不动 `--ad-r-ctl`（那个另有 6 处用）。 */
  --ad-btn-h:         40px;    /* 按钮标准高 */
  --ad-btn-h-sm:      32px;    /* 按钮小型高（.btn--sm） */
  --ad-field-h:       40px;    /* 控件舒适档 */
  --ad-field-h-dense: 32px;    /* 控件紧凑档 ★ 余总定 */
  --ad-r-field:        4px;    /* 按钮与表单控件圆角 */
  --ad-placeholder:  #6A7058;  /* 占位符 · ★ 换皮：原 #86909C 冷灰(色相213) → 暖橄榄灰(色相78)
     ★ 取值口径＝**最不利背景**（输入框不保证都落在卡片里）：对页面底 #F0F1E9 4.53、
       卡片底 #FAFBF4 4.95 —— 两边都过 WCAG AA 4.5（`_audit_wcag.py` 守着）。
       首版取 #7E8470 跟着 --ad-field-line，卡底只有 4.48（差 0.02 被审计抓到）⇒ 压深一档。 */
  --ad-fill-off:     #DADFCC;  /* 禁用底 · 表格分割线 · ★ 换皮：原 #E5E6EB 冷灰(色相230) → --ad-line 暖灰(色相76) */

  /* ---- ★★ R7 · Q3：骨架尺寸令牌（顶栏 / 侧栏 / 标题区）------------------------
     依据 = 规范样机（顶栏 56 · 侧栏 220 · 标题区 48）＋ 余总 2026-09-30 23:5x 拍板。
     ★★ **为什么顶栏必须立令牌**：它原来是**硬编码 46px，散在 admin.css 共 10 行**里
        （源头 `.ad-top`:17，另有 `.ad`:70 · `.ad-nav`:99,100 · `.ad-tabbar`:183 ·
          `.ad-bar`:244 · `.ad-split .ad-side`:83,84 · `.ad-pnav`:2225,2226）。
        改一个数、漏一处 ⇒ 那些 `sticky top` / `max-height` 仍按旧值算
        = **滚动才发作的静默错位**（未滚动时页面完全正常，截图也看不出来）。
        ⇒ 口径只有一处：以后调顶栏**只改这里的值**。
     ★ 标题区与顶栏同为 56 却**分开命名** —— 是两个部位，将来可各自微调，
       合并成一个名就再也分不开了（本项目最恨的第二套口径）。 */
  --ad-top-h:      56px;   /* 顶栏高（吸附基准；改它牵动 admin.css 10 行） */
  --ad-side-w:    220px;   /* 侧栏宽（`.ad` 网格第 1 列） */
  --ad-bar-h:      56px;   /* 页面标题区高（装得下 40 高按钮 ＋ 上下各 8） */

  /* ---- ★★ R7 · Q4：弹窗令牌（圆角 / 阴影 / 遮罩 / 头区 / 底栏 / 宽上限）-----------
     依据 = 规范 §5 弹窗节（圆角 8 · 阴影 `0 8px 24px rgba(0,0,0,.12)` · 遮罩 60% ·
     标题区 56 · 底栏 64 · 宽 480–900）＋ 余总 2026-10-01 08:0x 拍板「按你说的办」。

     ★★ **为什么 A 族（`.modal`）必须靠这里覆盖、而不能改源头**：
        `.modal` / `.modal__panel` 定义在 **`components.css`（前后台共用层）**
        ⇒ 直接改它会把**前台弹窗**一起改掉（破「前台一个值不动」的铁律）。
        所以口径是：**只改这里的值 ＋ 在 `admin.css` 里覆盖写**，源头一个字不动。

     ★★ **遮罩为什么单列一个令牌**：三族原来的遮罩是三种口径
        （A 族**全透明** · B/C 族 45%）—— 三个数各有各的来历，不立令牌就永远收不拢。
        收成 `--ad-dlg-scrim` 之后，「弹窗后面那层黑」全项目只有一处定义。 */
  --ad-dlg-r:        8px;   /* 弹窗圆角（三族统一；原都 4） */
  --ad-dlg-sh:       0 8px 24px rgba(0,0,0,.12);  /* 弹窗投影（三族统一；原都 none） */
  --ad-dlg-scrim:    rgba(1,1,1,.6);              /* 遮罩 60%（原：A 透明 · B/C 45%） */
  --ad-dlg-head-h:   56px;  /* 弹窗标题区高（与顶栏/页标题区同值，但**分开命名**） */
  --ad-dlg-foot-h:   64px;  /* 弹窗底栏高（按钮区；装得下 40 高按钮 ＋ 上下各 12） */
  /* ★★ 批 J2（2026-10-05）：余总直接指令「弹窗要改变大小确保信息齐全 · 横向不要有滚动条为标准」
     ⇒ 上限 **900 → 1180**（R7·Q4 那条 480–900 的规范据此上调）。
     ★ 小屏仍由各处 `min(…, 100%)` 兜底 ⇒ 1024 视口下实得 ≈976，不会溢出。
     ★ 与 `.ad-picker__panel` 共用一个变量（都是"信息多"的弹窗，同一档宽）。 */
  --ad-dlg-max-w:   1180px;

  /* ---- ★★ R7 · Q5：图标令牌（尺寸两档 ＋ 线宽）--------------------------------
     依据 = 规范 §7 图标节（**只 16 / 24 两套尺寸** · **线宽统一 2** · 圆头圆角）。

     ★★ **为什么必须立令牌**：改前后台有 **4 种尺寸（10/12/15/16）· 3 种线宽（1.4/1.5/1.8）·
        3 套 viewBox（10/16/24）** —— 十一个人各画各的。收成两个尺寸之后，
        「这枚图标多大」全项目只有这两处定义，判据也才有一条可锚的线。

     ★ 线宽 `--ad-ico-w` 的含义 = **图标各自 viewBox 内的 stroke-width 声明值**，
       不是屏幕像素。16 与 24 两档都写 2 —— 16 那档视觉上略粗一点，
       这是**有意**的（小尺寸下细线会糊）。 */
  --ad-ico-s:      16px;    /* 小档（按钮 / 表格操作 / 弹窗关闭 / 页签关闭） */
  --ad-ico-l:      24px;    /* 大档（侧栏菜单 / 页面标题 / 空状态） */
  --ad-ico-w:         2;    /* 线宽（两档 viewBox 内都写这个数） */

  /* ---- ★★ 2026-10-03 SAGE 落地「其它页面」（批 S1）新增：样机 G 组动效曲线与时长 ----
     ★ 样机原值（逐字取自 `后台主题_SAGE终端风.html` 的 `:root`）：
         --ease-out    cubic-bezier(.22,1,.36,1)     「出场」曲线（快进慢停）
         --spring      cubic-bezier(.34,1.56,.64,1)  「弹性」（过冲 1.56 ⇒ 会回弹）
         --spring-soft cubic-bezier(.34,1.4,.64,1)   「轻弹」（过冲 1.4，克制）
         --fluid       cubic-bezier(.4,0,.2,1)       通用流体（Material 标准曲线）
         --dur-hover   100ms  悬停反馈（要快，慢了像卡）
         --dur-panel   320ms  面板 / 抽屉开合
     ★ 为什么必须补、而不是继续用现成的 `--ease` + `--dur`：
       现有 `--ease (.2,.7,.3,1)` 是**前台**的「缓出」，全程不过冲；样机后台要的
       **弹性**（`.spring` 族）是**过冲**曲线 —— 两者语义不同，混用会让"该弹的地方不弹"。
     ★ 本批只**立令牌**，暂不强行把现有动效换曲线（那属 S2 逐页落地范畴）
       —— 避免"改了令牌就以为动效到位了"的假绿。 */
  --ad-ease-out:    cubic-bezier(.22, 1, .36, 1);
  --ad-spring:      cubic-bezier(.34, 1.56, .64, 1);
  --ad-spring-soft: cubic-bezier(.34, 1.4, .64, 1);
  --ad-fluid:       cubic-bezier(.4, 0, .2, 1);
  --ad-dur-hover:   100ms;
  --ad-dur-panel:   320ms;
}

/* ---- 参考站主标题阶梯的断点（实测；口径见上面 --fs-hero 的注释）----
   放在 `:root` 之后、`:root[lang=cn]` 之前：后者只改 --fs-h1/h2/h3 与行高，
   不碰 --fs-hero/--fs-sec/--lh-hero，所以中英两套走同一个阶梯（参考站也没有中文降档）。
   ★ --fs-name 是 --fs-hero 的别名，var() 在**使用处**解析计算值 —— 这里只改
     --fs-hero，别名自动跟着走，不要在这两个断点里再写一遍 --fs-name。 */
@media (min-width: 768px) {
  :root {
    --fs-hero: 35px;
    --fs-sec:  55px;
  }
}
@media (min-width: 1280px) {
  :root {
    --fs-hero: 55px;
  }
}

/* ---- 中文：降字号、降字重、加字距、提行高 ---- */
:root[lang="cn"] {
  --fs-h1: clamp(26px, 3vw, 46px);
  --fs-h2: clamp(21px, 2vw, 30px);
  --fs-h3: clamp(17px, 1.4vw, 20px);
  --lh-tight: 1.3;
  --lh-snug: 1.6;
  --lh-normal: 1.9;
  --ls-tight: 0.01em;
  --ls-wide: 0.08em;
  --fs-lead: clamp(15px, 1.15vw, 17px);
}

/* ---- 大屏内容宽度由 --container 封顶（与参考站一致），不再靠 vw 撑开 ----
   注意：1600px 以上**没有**任何令牌要改。以前这里挂了一句
   `@media (min-width:1600px){ :root{--header-strip:86px} }`，
   和 :root 里的默认值一模一样，是纯冗余，已删。 */

/* ---- 窄屏收紧 ---- */
@media (max-width: 900px) {
  :root {
    --header-banner: 31px;    /* 窄屏横幅文字会换行，真实高度靠 JS 修正 */
    --header-nav: 44px;
    --lh-normal: 1.75;
  }
}
