/* ============================================================
   KKnote V2 — Design Tokens
   Source: 01-layout.html :root + [data-theme]
   默认配色 = 天空蓝（P · Sky）；「默认」不落任何 data-scheme 块，直接由 [data-theme] 表达。
   ============================================================ */

:root {
  /* Layout */
  --sidebar-w: 248px;
  /* 侧栏在**文档流里实际占的宽度**（= .app 网格首列的宽度）。
     桌面段等于 --sidebar-w；769~1024px 被 layout.css 封顶为 min(--sidebar-w, 220px)；
     ≤768px 侧栏改为离屏抽屉、文档流里占 0 —— 这两个断点各自改写本令牌（不在消费端重复写）。
     ★ 任何「按侧栏宽度定位」的规则都必须消费本令牌，**不要**直接写 var(--sidebar-w)：
       否则在 769~1024px 段会比实际多算 28px（2026-09-23 修 —— FAB 让位规则与
       document-edit.css 的 Vditor 全屏 left 都踩过这个坑）。 */
  --sb-w-flow: var(--sidebar-w);
  --header-h: 50px;

  /* Radius */
  --radius-xs: 5px;
  --radius-sm: 8px;
  --radius: 10px;
  --radius-lg: 14px;

  /* Motion */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur: 0.2s;
  --dur-slow: 0.35s;

  /* Scrim —— 遮罩 / 暗化叠层。**刻意定义在 :root，不设 [data-theme] 双份**：
     遮罩的语义是「把底层压暗」，深浅两主题都用黑是通行做法；若随主题改成白，
     语义就变成「提亮」，不再是遮罩。故这几个值不参与主题对称性检查，也不该被
     「两主题键必须对齐」的约定套用。
     档位按用途分档，**不跨档合并**（三档各有实测用途，合并即改观感）：
       --scrim              全屏遮罩（内容阻断型）：抽屉 / 看板模态 / 移动端侧栏
       --scrim-soft         轻量弹层遮罩：AI 浮窗 / 全局搜索
       --scrim-strong       视频缩略图遮罩：需压过明亮缩略图才看得清播放键
       --scrim-fill         气泡内代码块底衬（半透明叠在气泡底色上，随气泡色自动适配，
                            故不能改用不透明的 --code-bg —— 那会变成「比气泡亮」）
       --scrim-fill-inline  气泡内行内 code 底衬（同上，比块级更淡一档）
     注意：不透明的纯黑（如 youtube.css 的 .yt-play-iframe 视频底衬 #000）不属于
     scrim —— 它是「填充」而非「压暗」，且必须绝对不透明，故不并入本组。 */
  --scrim: rgba(0, 0, 0, 0.5);
  --scrim-soft: rgba(0, 0, 0, 0.45);
  --scrim-strong: rgba(0, 0, 0, 0.55);
  --scrim-fill: rgba(0, 0, 0, 0.18);
  --scrim-fill-inline: rgba(0, 0, 0, 0.15);
}

/* Dark theme (default) */
[data-theme="dark"] {
  --bg: #0d1217;
  --bg-card: #13171e;
  --bg-panel: #181b23;
  --bg-hover: #1e2128;
  --bg-input: #0b0f15;

  --border: rgba(102, 119, 132, 0.10);
  --border-md: rgba(102, 119, 132, 0.16);
  --border-lg: rgba(102, 119, 132, 0.22);

  --text: #dcdee0;
  --text-sub: #a3a3a5;
  /* 最淡两档的定档规则（口径见 V1+/audit-v2/TEXT-CONTRAST-AUDIT.md §3.4，
     并由 tools/check_theme_scheme.php 的 A6 机械执行）：
       · --text-muted 达正文 AA 4.5:1、--text-dim 达辅助信息/大字 AA 3.0:1；
       · 沿所在色系的原色相方向调亮度，保持四档单调递减（正文 > sub > muted > dim）；
       · **对四个表面（--bg / --bg-card / --bg-panel / --bg-hover）中最差者达标**，
         并留 0.05 余量防浮点误判 —— 只按 --bg 算会系统性高估：暗色下 --bg-hover
         最亮、亮色下最暗，四个里最苛刻。
     两档均为纯文字色（全站仅 .typing-dot 用 --text-muted 作 background），
     故调这两档只影响文字/图标可读性，不牵动任何背景或边框语义。
     📌 历史：本口径 2026-09 在旧蓝调上确立（当时只按 --bg 算，实测 4.05 / 2.65
        双双不达标 ⇒ 才改成四表面口径）。2026-09-13 默认配色换成天空蓝后，
        按同一口径重新反解为现值 4.50 / 3.01，仍达标。 */
  --text-muted: #888788;   /* 对 --bg-hover 4.50:1（门槛 4.5） */
  --text-dim: #6a6b6b;     /* 对 --bg-hover 3.01:1（门槛 3.0） */
  --text-inverse: #fff;

  /* 看板列色圆点（.col-dot）的描边色。
     圆点底色是 .col-head —— 它是「列色 30% + --bg-card 70%」的叠色，
     而列色由用户自选，可任意明暗 ⇒ **不存在**能对任意圆点色都达 3:1 的
     单一描边色（圆点可以是纯黑也可以是纯白，数学上无解）。
     故本键只保证「圆点所在的色块对 .col-head 底色」恒达 3:1：
       暗色主题 → 白环（对叠底最差 7.92:1）；亮色主题 → 黑环（最差 12.36:1）。
     最差值取自内置 8 色 + 默认 #4f46e5 全量实测。
     默认列色连更严的「圆点 vs 描边」口径也达 6.29（暗）/ 3.34（亮）。 */
  --col-dot-ring: #ffffff;

  --primary: #42a8ff;       /* 前景角色（文字 / 图标 / 描边 / 芯片文字）。
                               天空蓝在暗底上很亮：对四表面取最差（--bg-hover）6.35:1，
                               远超 AA 正文 4.5，也明显优于改版前蓝调的 3.55:1。 */
  --primary-fill: #42a8ff;  /* 实心主色底（按钮/头像/激活页签/FAB…），前景固定配 --on-primary。
                               ── 为什么必须与 --primary 拆开 ──
                               「填充 + 白字」要求填充够暗（L ≤ 0.1833 才够 4.5:1），
                               「前景文字」要求前景够亮（L ≥ 0.2231 才够 4.5:1），
                               两者交集为空 ⇒ **单键无解**（已实算，见审计台账）。
                               天空蓝属**高亮主色**，两键恰好可同值：填充改配深色字即可
                               （见 --on-primary），故本键与 --primary 同为 #42a8ff。
                               ⚠️ 规则：凡「实底主色」的 background，一律写 --primary-fill；
                                  由 tools/check_theme_scheme.php 的 A7 断言机械强制。
                               ⚠️ 未同步项：--primary-rgb / -10 / -sub / -glow 是**字面量** rgba，
                                  不随本键变化，需手动与 --primary 对齐。 */
  --on-primary: #071019;    /* --primary-fill 之上的前景色（**不是** --primary 之上的）。
                               高亮主色必须配深色字：#071019 on #42a8ff = 7.54:1（AA 正文 ✓）；
                               沿用 #fff 只有 2.54:1 —— 这正是「--on-primary 必须随配色方案
                               取值、不能复用 --text-inverse」的原因。
                               新增方案改了 --primary-fill 时必须同步复核本键，由 A6 断言兜底。 */

  --primary-sub: rgba(66, 168, 255, 0.18);
  --primary-10: rgba(66, 168, 255, 0.10);
  --primary-glow: rgba(66, 168, 255, 0.25);

  --green: #4a9e78;
  --green-10: rgba(74, 158, 120, 0.10);
  --yellow: #c9932a;
  --yellow-10: rgba(201, 147, 42, 0.10);
  --red: #c25465;
  --red-10: rgba(194, 84, 101, 0.10);

  /* 语义色 RGB 三元组：供 rgba(var(--x-rgb), <任意透明度>) 使用。
     背景：全站曾把 194,84,101 / 74,158,120 / 74,127,168 / 201,147,42（即本 dark 主题的
     red/green/primary/yellow 数值）硬编码在各页 CSS 里，亮色主题下不会跟着切，
     导致危险/成功提示在浅色底上仍是深色调。改用三元组后透明度档位（.06~.4）全部保留。 */
  --red-rgb: 194, 84, 101;
  --green-rgb: 74, 158, 120;
  --primary-rgb: 66, 168, 255;
  --yellow-rgb: 201, 147, 42;

  /* 代码块 / 代码字色（Markdown 阅读页 + 全屏编辑器）。
     暗色主题的代码块用中性深灰 #1e1e1e（比 --bg-panel 更暗、色相中性），
     亮色主题则沿用 --bg-panel 系浅灰。行内 code 的字色两主题差异很大：
     深底友好色 #e06c75 放到浅色底（--bg-hover #e8eaed）上只有 2.65:1，
     故亮色必须换深红 #a8324a（5.41:1）。**这两个值不可合并成单值。** */
  --code-bg: #1e1e1e;
  --code-fg: #d4d4d4;
  --code-border: #333333;
  --code-scroll: #555555;
  --code-inline-fg: #e06c75;

  --sidebar-bg: #0a0e14;
  --header-bg: rgba(13, 18, 23, 0.88);

  /* Elevation 阴影体系（按用途分档，随主题切换）。
     背景：全站曾有 9 处 box-shadow 直接写死 rgba(0,0,0,α) 且**不随主题切换** ——
     同一组 α 落到浅色底上就是明显的灰污。既有 --shadow / --shadow-sm 早已按主题
     分设 α（Light 约为 Dark 的 0.3 倍），本组沿用同一比例补齐其余用途档位。
     档位含义：xs 小控件（选项卡/滑块）；sm 小构件；无前缀 卡片/常规面板；
     pop 浮层（下拉/小弹窗）；overlay 大浮层（模态/全屏面板）；
     panel 侧栏/侧滑面板（向左投影，方向性 —— 通用档位无法表达方向）。 */
  --shadow-xs: 0 1px 3px rgba(0, 0, 0, 0.15);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.25);
  --shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  --shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.16);
  --shadow-overlay: 0 20px 60px rgba(0, 0, 0, 0.45);
  --shadow-panel: -4px 0 18px rgba(0, 0, 0, 0.16);
}

/* Light theme */
[data-theme="light"] {
  --bg: #e9f2f7;
  --bg-card: #f3f7fa;
  --bg-panel: #e9f0f5;
  --bg-hover: #dee7ed;
  --bg-input: #fff;

  --border: rgba(69, 81, 91, 0.09);
  --border-md: rgba(69, 81, 91, 0.14);
  --border-lg: rgba(69, 81, 91, 0.20);

  --text: #1b1e20;
  --text-sub: #4a4a4b;
  /* 同上（说明见 Dark 块）。浅色底上「越淡」= 越亮，故两档数值都比 --text-muted 亮。 */
  /* 同上：原注释的 4.51 / 3.07 只按 --bg 算；落到四个表面里最暗的 --bg-hover
     上只剩 4.01 / 2.73。现按最差表面达标（含 0.05 余量）。 */
  --text-muted: #676666;   /* 对 --bg-hover 4.57:1（门槛 4.5） */
  --text-dim: #838280;     /* 对 --bg-hover 3.06:1（门槛 3.0） */
  --text-inverse: #fff;
  --col-dot-ring: #000000;  /* 说明见 Dark 块：亮色主题必须配**黑**环才够 3:1 */

  --primary: #0066bd;       /* 前景角色。**没有照搬 demo 的 #42a8ff**：亮底下它作文字
                               只有 2.02:1（现状蓝调 #3a6f98 是 4.46:1），而全站
                               79 处 color: var(--primary) 都吃这个值 ⇒ 会一起塌掉。
                               现沿 P 自己的色相（H 207.6° / S 100%）只压亮度反解到 AA：
                               #0066bd 对四表面最差 4.62:1（已含 0.05 余量）。
                               填充角色 --primary-fill 仍保留 P 原色 #42a8ff ⇒ 按钮观感不变。 */
  --primary-fill: #42a8ff;  /* 实心填充角色，保留 P 的原色 —— 明快天蓝是这套方案的识别点。
                               配 --on-primary #071019 = 7.54:1（AA 正文 ✓）。
                               与 --primary 不同值正是拆键的意义：填充求「跳」，前景求「清」。 */
  --on-primary: #071019;    /* 同 dark 块：高亮主色配深色字；#fff 在其上只有 2.54:1。 */

  --primary-sub: rgba(0, 102, 189, 0.10);
  --primary-10: rgba(0, 102, 189, 0.10);
  --primary-glow: rgba(0, 102, 189, 0.18);

  --green: #2e7d5a;
  --green-10: rgba(46, 125, 90, 0.10);
  --yellow: #a07020;
  --yellow-10: rgba(160, 112, 32, 0.10);
  --red: #a83a4a;
  --red-10: rgba(168, 58, 74, 0.10);

  /* 语义色 RGB 三元组（与 dark 块同名，键对称，见上方注释） */
  --red-rgb: 168, 58, 74;
  --green-rgb: 46, 125, 90;
  --primary-rgb: 0, 102, 189;
  --yellow-rgb: 160, 112, 32;

  /* 代码块 / 代码字色，键与 dark 块对称（说明见上方 dark 块）。
     --code-fg 取 --text：浅色下原先未显式设色、靠继承正文色，此处显式补上，
     避免主题/继承变化导致可读性回退。 */
  --code-bg: #f0f2f5;          /* 略亮于 --bg-panel（#e9f0f5）；换天空蓝后未跟着改，
                                  刻意保留一点反差让代码块从面板里浮出来 */
  --code-fg: var(--text);
  --code-border: #e1e4e8;
  --code-scroll: #cccccc;
  --code-inline-fg: #a8324a;

  --sidebar-bg: #dee7ed;
  --header-bg: rgba(233, 242, 247, 0.92);

  /* 阴影：同上体系，浅色底 α 取 Dark 的约 0.3 倍；最小的 xs/pop/panel 设 0.07 感知下限
     （再低在浅色底上等于看不见），与既有 --shadow-sm 的 0.08 同量级。 */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.07);
  --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.08);
  --shadow: 0 3px 12px rgba(0, 0, 0, 0.10);
  --shadow-pop: 0 6px 18px rgba(0, 0, 0, 0.07);
  --shadow-overlay: 0 14px 40px rgba(0, 0, 0, 0.14);
  --shadow-panel: -3px 0 14px rgba(0, 0, 0, 0.07);
}

/* ============================================================
   配色方案层（第二条轴）—— overlay 模型
   ============================================================
   结构与上面 [data-theme] 的关系：
     · [data-theme]                        特异性 (0,1,0) —— 基线，兼作「无 data-scheme」时的兜底
     · [data-theme][data-scheme="x"]       特异性 (0,2,0) —— **覆盖层，只写要改的键**
   ⇒ 方案块**不需要补全 40 键**，缺的键自动继承 [data-theme] 的值。
   ⇒ 不带 data-scheme 属性 = 当前这套外观，故「加新方案」永远不会动到默认表现。

   ⚠️ 已知「不带 data-scheme」的页面（它们恒为默认方案，不跟随站点设置）：
     · app/view/v2/auth/login.php / install.php / install_server.php
       —— 前两者在登录/安装前渲染，无会话；install 更是**早于 DB 存在**，
          此时 settings 表还没建，读方案必然失败。**这是设计意图，不是遗漏。**
     · 所有导出/打印用的独立 HTML（ImportExportService、DocumentController、
       YoutubeController、ApiController 内拼的 <!DOCTYPE html>）—— 它们是脱机文档，
      本就不属于应用外壳。
   这些页面将来即便新增了第二套方案也**仍显示默认方案**；若届时要求登录页同步配色，
   需单独处理（且 install 页必须排除）。

   为什么必须 [data-theme] + [data-scheme] **双限定**：
   单写 [data-scheme="x"] 与 [data-theme] 同为 (0,1,0)，靠源码顺序决胜，
   会把 dark 的值压到 light 上（或反之）。双限定后既靠特异性胜出，又天然分主题。

   ⚠️ 「默认外观」由上面的 [data-theme] 基线**独自**表达，不再另建一份同值方案块：
   2026-09-13 之前这里有一套 data-scheme="blue"，其 43 个键与基线逐键逐值完全相同
   （当时用作「overlay 机制无副作用」的参照系 —— 切过去若渲染有差异，就说明覆盖机制
   本身有问题，与「选哪套配色」无关）。它带来两个问题：
     · 每改一次默认配色就要同步改两处，漏一处即静默漂移；
     · 语义上「不设 data-scheme」与「设 data-scheme='blue'」是同一件事，属重复表达。
   现改为：**默认 = 不输出 data-scheme 属性**（settings.theme_scheme 为空串）⇒ 直接走基线。
   ⇒ 由此产生一条新禁令：**禁止**再出现与基线逐键全等的方案块。由
     tools/check_theme_scheme.php 的 A3 机械守住 —— A3 已从「blue 必须与基线相同」
     反转为「任何方案块都不得与基线全等」。
   ============================================================ */



/* ==========================================================================
   方案 E —— 暖灰 · 纸感（data-scheme="warm"）
   --------------------------------------------------------------------------
   来源：V1+/audit-v2/THEME-MIGRATION-ASSESSMENT.md 附 A「E 方案的完整令牌值」。
   选 E 而非 F 的理由（附 C.4）：按钮余量 5.64 vs 4.52 属永久性结构差异，
   而 --code-* 调暖只是一次性成本 —— 用一次性的小成本换永久的安全余量。

   ⚠️ 本块对文档值做过 3 处实测修正（文档数字含 opacity 合成，1c 后已不适用）：
     1) 文档称填充对比度 5.64 / 7.63 —— 那是 opacity .9 合成值；1c 移除 opacity
        后按令牌原值实算为 **6.74 / 10.09**，余量比文档更宽裕。
     2) light --text-muted 文档给 #7A7168 并称 4.51:1，实测对 --bg #f5f2ee
        仅 4.29:1、对最差表面 --bg-hover #efebe5 更只有 4.27:1，不达 AA。
     3) light --text-dim 文档给 #948E86 并称 3.06:1，实测对 --bg 仅 2.91:1。

   ⚠️ 与「最差表面」口径的关系：文字 token 现在一律按四个表面
      （--bg / --bg-card / --bg-panel / --bg-hover）中**最差的那个**验收，
      而非只看 --bg。dark 的最差是 --bg-hover（最亮），light 的最差同样是
      --bg-hover（最暗）。故本块两档也按该口径重解为
      dark #938c83 / #726f6b、light #716861 / #8b857f。

   ⚠️ --on-primary 在两主题下**反色**：dark 填充是浅暖灰，故前景用深色
      #161311；light 填充是深暖灰，前景用 #fff。这正是「--on-primary 必须
      随配色方案取值、而不能复用 --text-inverse」的实证。

   ⚠️ --code-* 只暖调 4 个中性值；--code-inline-fg 是语义红，按文档
      「语义三色不变」沿用基线值。语义三色与 --shadow* 一律不动。
   ========================================================================== */

[data-theme="dark"][data-scheme="warm"] {
  --bg: #121110;
  --bg-card: #1c1a18;
  --bg-panel: #211f1c;
  --bg-hover: #282521;
  --bg-input: #0f0e0d;

  --border: rgba(168, 158, 148, 0.10);
  --border-md: rgba(168, 158, 148, 0.16);
  --border-lg: rgba(168, 158, 148, 0.22);

  --text: #e8e3de;
  --text-sub: #b0a89f;
  --text-muted: #938c83;   /* 对 --bg-hover 4.59:1（旧 #89827A 仅 4.02） */
  --text-dim: #726f6b;     /* 对 --bg-hover 3.05:1（旧 #6A6763 仅 2.71） */
  --text-inverse: #fff;

  --primary: #a89a8a;
  --primary-fill: #a89a8a;  /* A′：实心填充走本键；--on-primary 6.74:1 */
  --on-primary: #161311;    /* ★ 跨主题反色：dark 填充浅 ⇒ 前景用深色 */
  --primary-rgb: 168, 154, 138;
  --primary-sub: rgba(168, 154, 138, 0.18);
  --primary-10: rgba(168, 154, 138, 0.10);
  --primary-glow: rgba(168, 154, 138, 0.25);

  --code-bg: #1e1c1a;
  --code-fg: #d8d2cc;
  --code-border: #332f2c;
  --code-scroll: #554f4a;

  --sidebar-bg: #0e0c0b;
  --header-bg: rgba(18, 17, 16, 0.88);
}

[data-theme="light"][data-scheme="warm"] {
  --bg: #f5f2ee;
  --bg-card: #faf8f5;
  --bg-panel: #f6f3ef;
  --bg-hover: #efebe5;
  --bg-input: #ffffff;

  --border: rgba(90, 82, 74, 0.10);
  --border-md: rgba(90, 82, 74, 0.16);
  --border-lg: rgba(90, 82, 74, 0.22);

  --text: #211d19;
  --text-sub: #544c44;
  --text-muted: #716861;   /* 对 --bg-hover 4.59:1（文档 #7A7168 仅 4.29） */
  --text-dim: #8b857f;     /* 对 --bg-hover 3.07:1（文档 #948E86 仅 2.91） */
  --text-inverse: #fff;

  --primary: #4a4038;
  --primary-fill: #4a4038;  /* A′：实心填充走本键；--on-primary 10.09:1 */
  --on-primary: #ffffff;    /* ★ 跨主题反色：light 填充深 ⇒ 前景用白 */
  --primary-rgb: 74, 64, 56;
  --primary-sub: rgba(74, 64, 56, 0.18);
  --primary-10: rgba(74, 64, 56, 0.10);
  --primary-glow: rgba(74, 64, 56, 0.25);

  --code-bg: #f5f1ec;
  --code-fg: var(--text);
  --code-border: #e8e2dc;
  --code-scroll: #cbc5bf;

  --sidebar-bg: #efebe5;
  --header-bg: rgba(245, 242, 238, 0.92);
}

/* ==========================================================================
   方案 D —— 纯黑白 · 极致（data-scheme="mono"）
   --------------------------------------------------------------------------
   来源：V1+/v2-demo/13-button-theme-preview.html 的 D 方案。
   定位：**正式 / 中立**场景（演示、公开项目）—— 全键彩度 ≤ 3，是候选里最接近
   「绝对无彩色」的一套（对比：B 主色彩度 16、C 14、F 28、K 19）。

   为什么是 D 而不是 G（同为纯黑白系，2026-09-13 裁决）：
     G 把明暗两端用到了头（dark bg #000000 / light bg #ffffff），导致三处结构缺陷：
       1) 亮色层级反转：bg 已是纯白，card #fbfbfb 只能更深 ⇒ 卡片「凹陷」，
          与全站两个主题下「card 比 bg 亮」的 elevation 模型相反；
       2) --bg-input 与 --bg 完全同值（亮色均 #ffffff、暗色均 #000000），
          输入框与页面底色无区分，只剩边框；
       3) 主色与正文完全撞色：light --primary 与 --text 同为 #0a0a0a（ΔE00 = 0.00）。
     D 暗色底 #0a0a0b / 亮色底 #f5f5f5，留了 10/255 余量，以上三项均正常。
     而两者观感差异很小：CIEDE2000 平均 ΔE 亮色仅 0.79（基本同款）、暗色 2.56。
     G 唯一不可替代的优势是 OLED 省电（像素全关），那是手机端诉求，桌面端不受益。

   ⚠️ 已知取舍（纯黑白系的固有代价，非缺陷）：
     --primary 与 --text 色差极小（dark ΔE00 1.84 / light 1.30，对比 1.08 / 1.03）
     ⇒ **链接、图标着色、焦点环等在视觉上几乎等同于正文**。
     按钮不受影响：实心填充走 --primary-fill + --on-primary，本方案下
     高达 15.87:1（dark）/ 18.40:1（light），是全候选里最高的一档。
     若日后需要链接可辨，应靠**下划线/字重**区分，而不是把主色拉出中性区。

   ⚠️ 余量告警：dark --text-dim 对 --bg-hover 为 3.01:1（门槛 3.0），余量 0.01。
     与基线 dark --text-dim（同为 3.01）一致，故沿用未改；改动时需重算。

   ⚠️ 与「最差表面」口径的关系：文字 token 按四个表面
      （--bg / --bg-card / --bg-panel / --bg-hover）中最差者验收。
      实测：dark 正文14.10 次级7.36 muted4.60 dim3.01 on-p15.87
            light 正文16.54 次级9.43 muted4.55 dim3.08 on-p18.40 —— 全部达 AA。

   ⚠️ --code-* 按中性灰重推（D 是零彩度，不能用基线的冷灰 也不能用 warm 的暖灰）：
      dark #151516 / light #f0f0f0，比各自 --bg-panel 略深一档（与 warm 块同思路）。
      --code-inline-fg 是语义红，按「语义三色不变」沿用基线值。
      语义三色与 --shadow* 一律不动。
   ========================================================================== */

[data-theme="dark"][data-scheme="mono"] {
  --bg: #0a0a0b;
  --bg-card: #121214;
  --bg-panel: #17181a;
  --bg-hover: #1e1f21;
  --bg-input: #0e0e10;

  --border: rgba(160, 160, 162, 0.10);
  --border-md: rgba(160, 160, 162, 0.16);
  --border-lg: rgba(160, 160, 162, 0.22);

  --text: #ededee;
  --text-sub: #adadaf;
  --text-muted: #87878a;   /* 对 --bg-hover 4.60:1 */
  --text-dim: #69696c;     /* 对 --bg-hover 3.01:1 —— 余量 0.01，改动时需重算 */
  --text-inverse: #fff;

  --primary: #e4e5e6;
  --primary-fill: #e4e5e6;  /* A′：实心填充走本键；--on-primary 15.87:1 */
  --on-primary: #080809;    /* ★ 跨主题反色：dark 填充近白 ⇒ 前景用近黑 */
  --primary-rgb: 228, 229, 230;
  --primary-sub: rgba(228, 229, 230, 0.18);
  --primary-10: rgba(228, 229, 230, 0.10);
  --primary-glow: rgba(228, 229, 230, 0.25);

  --code-bg: #151516;
  --code-fg: #e4e4e4;
  --code-border: #2c2c2d;
  --code-scroll: #555556;

  --sidebar-bg: #080809;
  --header-bg: rgba(10, 10, 11, 0.90);
}

[data-theme="light"][data-scheme="mono"] {
  --bg: #f5f5f5;
  --bg-card: #fcfcfc;
  --bg-panel: #f7f7f7;
  --bg-hover: #efefef;
  --bg-input: #ffffff;

  --border: rgba(50, 50, 52, 0.10);
  --border-md: rgba(50, 50, 52, 0.16);
  --border-lg: rgba(50, 50, 52, 0.22);

  --text: #101011;
  --text-sub: #3d3d3f;
  --text-muted: #6c6c6f;   /* 对 --bg-hover 4.55:1 */
  --text-dim: #88888a;     /* 对 --bg-hover 3.08:1 */
  --text-inverse: #fff;

  --primary: #141416;
  --primary-fill: #141416;  /* A′：实心填充走本键；--on-primary 18.40:1 */
  --on-primary: #ffffff;    /* ★ 跨主题反色：light 填充近黑 ⇒ 前景用白 */
  --primary-rgb: 20, 20, 22;
  --primary-sub: rgba(20, 20, 22, 0.18);
  --primary-10: rgba(20, 20, 22, 0.10);
  --primary-glow: rgba(20, 20, 22, 0.25);

  --code-bg: #f0f0f0;
  --code-fg: var(--text);
  --code-border: #e2e2e2;
  --code-scroll: #c9c9c9;

  --sidebar-bg: #efefef;
  --header-bg: rgba(245, 245, 245, 0.92);
}

/* ==========================================================================
   方案 L —— 泡泡糖粉 · 糖果（data-scheme="bubblegum"）
   --------------------------------------------------------------------------
   来源：V1+/v2-demo/13-button-theme-preview.html 的 L 方案。
   定位：**特色 / 演示** 用的高饱和糖果配色，不是日常主力（见下方"已知取舍"）。

   为什么是 L 而不是 Q（同属红粉族，2026-09-13 裁决）：
     红粉族三套的色相为 L 334° / S 338° / Q 353°，而语义色 --red 在 351°。
        Q 与 --red 仅差 **1.8°** —— 主色几乎等于"危险色"，会让删除 / 报错类 UI
        与主要动作混淆，**不能当全站主色**；
        L 与 --red 差 **17.1°**，是红粉族里拉得最开的一支（属"粉"不属"红"）。
     语义三色（--red/--yellow/--green）按项目决策**不随方案变化**，所以主色必须
     避开这三个色相角 —— 这是选彩色系的第一约束（脚本 V1+/color-system/tools/hue_lab.py，Lab 口径）。
     同理被否掉的还有：M 薄荷绿（与 --green 差 0.4°）、N 柠檬黄（与 --yellow 差 8.6°）。

   ⚠️ 本块对 demo 值做过 2 处实测修正（求解脚本 V1+/color-system/tools/solve_l.py）：
     1) light --primary：demo 是 #FF529E，但它作**文字**用（全站 79 处 color:）
        对最差表面 --bg-hover 仅 **2.34:1**，远不达 AA。沿原色相（334°）
        反解为 **#ac376b（4.64:1）** —— 与 P 当初 #42a8ff → #0066bd 同一套做法。
        实心填充角色 --primary-fill **保留 demo 原色 #FF529E**，不受影响。
     2) muted / dim 两档按「四表面最差」口径微调，跨过门禁"余量 <0.10"告警线：
        dark #8F8484→#918686（4.51→4.65）、#716868→#736a6a（3.02→3.12）
        light #6F6160→#6e605f（4.58→4.65）、#8A7D7B→#897c7a（3.08→3.12）
     3) dark --primary #FF529E 对四表面最差 5.41:1，达标，未改。

   ⚠️ 已知取舍（这套就是"吵"，落地前要有共识）：
     · 主色彩度 **173**，是全场最高的一档（对比 mono 0 / warm 30），
       长时间使用易疲劳 ⇒ 定位为**特色 / 演示 / 活动皮肤**，不是日常主力。
     · --on-primary 在两主题下同为深色 #1a0a12：填充是亮粉，故前景用近黑
       （对 #FF529E 为 6.34:1）。这与 warm 的"跨主题反色"不同，属糖果配色的
       常见做法（明暗共用同一支主色）。

   ⚠️ --code-* 按粉调中性重推（比各自 --bg-panel 略深一档，与 warm / mono 同思路）。
      --code-inline-fg 是语义红，按「语义三色不变」沿用基线值。
      语义三色与 --shadow* 一律不动。
   ========================================================================== */

[data-theme="dark"][data-scheme="bubblegum"] {
  --bg: #160e12;
  --bg-card: #1d1219;
  --bg-panel: #22171e;
  --bg-hover: #271d23;
  --bg-input: #140b10;

  --border: rgba(136, 103, 115, 0.10);
  --border-md: rgba(136, 103, 115, 0.16);
  --border-lg: rgba(136, 103, 115, 0.22);

  --text: #e5dadb;
  --text-sub: #ac9fa0;
  --text-muted: #918686;   /* 对 --bg-hover 4.65:1（demo #8F8484 仅 4.51，余量过薄） */
  --text-dim: #736a6a;     /* 对 --bg-hover 3.12:1（demo #716868 仅 3.02） */
  --text-inverse: #fff;

  --primary: #ff529e;      /* 文字角色：对四表面最差 5.41:1，达标 */
  --primary-fill: #ff529e; /* A′：实心填充走本键；--on-primary 6.34:1 */
  --on-primary: #1a0a12;
  --primary-rgb: 255, 82, 158;
  --primary-sub: rgba(255, 82, 158, 0.18);
  --primary-10: rgba(255, 82, 158, 0.10);
  --primary-glow: rgba(255, 82, 158, 0.25);

  --code-bg: #1e141a;
  --code-fg: #e8dcde;
  --code-border: #34232c;
  --code-scroll: #5a464e;

  --sidebar-bg: #130a10;
  --header-bg: rgba(22, 14, 18, 0.88);
}

[data-theme="light"][data-scheme="bubblegum"] {
  --bg: #f9ebef;
  --bg-card: #fcf3f5;
  --bg-panel: #f8e9ed;
  --bg-hover: #f1dee3;
  --bg-input: #ffffff;

  --border: rgba(98, 68, 76, 0.10);
  --border-md: rgba(98, 68, 76, 0.16);
  --border-lg: rgba(98, 68, 76, 0.22);

  --text: #26191a;
  --text-sub: #554546;
  --text-muted: #6e605f;   /* 对 --bg-hover 4.65:1（demo #6F6160 仅 4.58） */
  --text-dim: #897c7a;     /* 对 --bg-hover 3.12:1（demo #8A7D7B 仅 3.08） */
  --text-inverse: #fff;

  --primary: #ac376b;      /* ★ 沿 demo #FF529E 的色相反解：原色作文字仅 2.34:1 */
  --primary-fill: #ff529e; /* A′：实心填充保留 demo 原色；--on-primary 6.34:1 */
  --on-primary: #1a0a12;
  --primary-rgb: 172, 55, 107;
  --primary-sub: rgba(172, 55, 107, 0.18);
  --primary-10: rgba(172, 55, 107, 0.10);
  --primary-glow: rgba(172, 55, 107, 0.25);

  --code-bg: #f5e4e9;
  --code-fg: var(--text);
  --code-border: #ebd9e0;
  --code-scroll: #cbafb8;

  --sidebar-bg: #f1dee3;
  --header-bg: rgba(249, 235, 239, 0.92);
}

/* ==========================================================================
   方案 M —— 薄荷绿 · 清爽（data-scheme="mint"）
   --------------------------------------------------------------------------
   来源：V1+/v2-demo/13-button-theme-preview.html 的 M 方案。
   定位：**低频特色皮肤**（清爽 / 健康 / 清洁类场景），非日常主力。

   ⚠️ 本套是 A12 的**登记豁免**项（见 tools/check_theme_scheme.php 的 $a12Exempt）：
     主色 #38DB94 与语义 --green（成功 / 低优先级）**同色相**（Lab 角距仅 2.8° / 2.0°），
     但它亮 19~31、彩度高 25~27 ⇒ ΔE00 16.9 / 27.9，落在「明显不同色」区间，
     靠明度与彩度即可区分，不是同一个颜色。
     反例：Q 樱桃与 --red 的 ΔE00 只有 4.01 —— 那个才是真会认错，故不落地。

   落地时对 demo 值的 3 处实测修正（改了哪、为什么，都写在这里）：
     1) light --primary：demo 的 #38DB94 在浅底上作**文字**只有 1.46:1
        （全站 79 处 color: var(--primary) 都吃这个值），必须反解。
        但**单纯沿同色相反解**会得到 #2a7652 —— 它与 --green #2e7d5a 的 ΔE00 只有
        **2.61**、角距 1.8°，等于把浅色链接直接变成「成功绿」，比不反解更糟。
        ⇒ 改为「反解 + 色相偏移」联合求解：#007667（Lab 179.5°，深青），
          最差表面 4.53:1 达标，与 --green 角距 19.6°（余量 4.6°）⇒ 走 A12 正常判据，
          不需要豁免。代价：浅色链接是深青而非薄荷绿（按钮仍是薄荷绿）。
     2) muted / dim：demo 值 4.51 / 3.01 只压线 0.01，浮点一抖就掉到线下
        （基线自身的 4.50 / 3.01 已是前车之鉴）⇒ 抬到 4.69 / 3.13。
     3) code-* 四键：demo 未定义，按 card / panel 的相对关系推导（同 warm / bubblegum）。

   ⚠️ 已知取舍（本套固有，非缺陷）：
     · 浅色 --primary-fill 沿用 demo 高亮薄荷 #38DB94，它对 --bg 只有约 1.5:1
       —— 按钮与页面底色的**亮度**差很小，靠彩度区分。
       同类情况基线自身是 2.24:1、bubblegum 2.6:1，属项目既有水平，非本套引入。
     · dark --primary 与 --green 同色相，靠明度彩度区分（见上），已登记 A12 豁免。
   ========================================================================== */

[data-theme="dark"][data-scheme="mint"] {
  --bg: #0c1412;
  --bg-card: #131918;
  --bg-panel: #181e1d;
  --bg-hover: #1d2423;
  --bg-input: #0a1210;

  --border: rgba(100, 128, 113, 0.10);
  --border-md: rgba(100, 128, 113, 0.16);
  --border-lg: rgba(100, 128, 113, 0.22);

  --text: #dbe1da;
  --text-sub: #a2a69f;
  --text-muted: #898d85;   /* 对 --bg-hover 4.67:1（demo #878A83 仅 4.51，压线 0.01） */
  --text-dim: #6c706a;     /* 对 --bg-hover 3.13:1（demo #6A6D68 仅 3.01） */
  --text-inverse: #fff;

  --primary: #38db94;      /* 文字角色：对四表面最差 8.83:1，达标；A12 已登记豁免 */
  --primary-fill: #38db94; /* A′：实心填充走本键；--on-primary 10.40:1 */
  --on-primary: #08150f;
  --primary-rgb: 56, 219, 148;
  --primary-sub: rgba(56, 219, 148, 0.18);
  --primary-10: rgba(56, 219, 148, 0.10);
  --primary-glow: rgba(56, 219, 148, 0.25);

  --code-bg: #151b1a;
  --code-fg: #d5dbd4;
  --code-border: #2a302f;
  --code-scroll: #4a504f;

  --sidebar-bg: #09110f;
  --header-bg: rgba(12, 20, 18, 0.88);
}

[data-theme="light"][data-scheme="mint"] {
  --bg: #e9f6ee;
  --bg-card: #f2f9f5;
  --bg-panel: #e8f4ec;
  --bg-hover: #ddece2;
  --bg-input: #ffffff;

  --border: rgba(68, 89, 75, 0.10);
  --border-md: rgba(68, 89, 75, 0.16);
  --border-lg: rgba(68, 89, 75, 0.22);

  --text: #1a211a;
  --text-sub: #494d45;
  --text-muted: #65675f;   /* 对 --bg-hover 4.69:1（demo #676A61 仅 4.51，压线 0.01） */
  --text-dim: #82837b;     /* 对 --bg-hover 3.13:1（demo #83857C 仅 3.06） */
  --text-inverse: #fff;

  --primary: #007667;      /* ★ 反解 + 色相偏移：demo #38DB94 作文字仅 1.46:1，
                               纯同色相反解又会撞死 --green（ΔE00 2.61）⇒ 偏到深青 179.5°，
                               4.53:1 达标，角距 19.6° 走 A12 正常判据 */
  --primary-fill: #38db94; /* A′：实心填充保留 demo 原色；--on-primary 10.40:1 */
  --on-primary: #08150f;
  --primary-rgb: 0, 118, 103;
  --primary-sub: rgba(0, 118, 103, 0.18);
  --primary-10: rgba(0, 118, 103, 0.10);
  --primary-glow: rgba(0, 118, 103, 0.25);

  --code-bg: #e5f1e9;
  --code-fg: var(--text);
  --code-border: #dae6d9;
  --code-scroll: #bdc6bc;

  --sidebar-bg: #ddece2;
  --header-bg: rgba(233, 246, 238, 0.92);
}

/* ==========================================================================
   方案 N —— 柠檬黄 · 活力（data-scheme="lemon"）
   --------------------------------------------------------------------------
   来源：V1+/v2-demo/13-button-theme-preview.html 的 N 方案。
   定位：**低频特色皮肤**（惊喜 / 活动 / 强调类场景），非日常主力。

   ⚠️ 本套是 A12 的**登记豁免**项（见 tools/check_theme_scheme.php 的 $a12Exempt）：
     主色 #FFD62E 与语义 --yellow（警示 / 中优先级）**同色相**（Lab 角距 11.1° / 14.1°），
     但它亮 22~36、彩度高 19~30 ⇒ ΔE00 18.7 / 30.8，落在「明显不同色」区间，
     靠明度与彩度即可区分。反例：Q 樱桃与 --red 的 ΔE00 只有 4.01，那个才是真会认错。

   落地时对 demo 值的 3 处实测修正（改了哪、为什么，都写在这里）：
     1) light --primary：demo 的 #FFD62E 在浅底上作**文字**只有 1.19:1
        （全站 79 处 color: var(--primary) 都吃这个值），必须反解。
        但**单纯沿同色相反解**会得到 #7e6921 —— 它与 --yellow #a07020 的 ΔE00 只有
        **9.97**、角距 13.5°，等于把浅色链接直接变成「警示黄」，比不反解更糟。
        ⇒ 改为「反解 + 色相偏移」联合求解：#706d22（Lab 102.3°，深橄榄），
          最差表面 4.55:1 达标，与 --yellow 角距 25.8°、ΔE00 15.8 ⇒ 走 A12 正常判据，
          不需要豁免。代价：浅色链接是深橄榄而非柠檬黄（按钮仍是柠檬黄）。
        · 为什么取偏移 +12° 而不是最小可用的 +2°（#7b6a21，角距 16.3°）：
          bubblegum 落地时只留了 3.5° 余量，已被记为「贴线、改门槛就会红」。
          这里刻意多让 10° 换安全余量（25.8°，余量 10.8°）。
     2) muted / dim：demo 值对最差表面 4.58 / 3.08（余量 0.08），同样偏薄
        ⇒ 抬到 4.69 / 3.13（与 bubblegum / mint 同口径）。
     3) code-* 四键：demo 未定义，按 card / panel 的相对关系推导（同 warm / bubblegum）。

   ⚠️ 已知取舍（本套固有，非缺陷）：
     · 浅色 --primary-fill 沿用 demo 高亮柠檬 #FFD62E，它对 --bg 只有约 1.2:1
       —— 按钮与页面底色的**亮度**差极小，几乎全靠彩度区分。
       这是本套最极端的一处：同类情况基线自身 2.24:1、bubblegum 2.6:1、mint 1.5:1。
       ⇒ 若日后要做「按钮边界必须 3:1」的收敛，本套要第一个改。
     · dark --primary 与 --yellow 同色相，靠明度彩度区分（见上），已登记 A12 豁免。
   ========================================================================== */

[data-theme="dark"][data-scheme="lemon"] {
  --bg: #16140d;
  --bg-card: #1d1913;
  --bg-panel: #221e18;
  --bg-hover: #27231e;
  --bg-input: #14110b;

  --border: rgba(136, 127, 94, 0.10);
  --border-md: rgba(136, 127, 94, 0.16);
  --border-lg: rgba(136, 127, 94, 0.22);

  --text: #e5e0d5;
  --text-sub: #aca69a;
  --text-muted: #938c82;   /* 对 --bg-hover 4.69:1（demo #918A81 仅 4.58） */
  --text-dim: #746f66;     /* 对 --bg-hover 3.13:1（demo #736E66 仅 3.09） */
  --text-inverse: #fff;

  --primary: #ffd62e;      /* 文字角色：对四表面最差 11.08:1，达标；A12 已登记豁免 */
  --primary-fill: #ffd62e; /* A′：实心填充走本键；--on-primary 13.41:1 */
  --on-primary: #1a1506;
  --primary-rgb: 255, 214, 46;
  --primary-sub: rgba(255, 214, 46, 0.18);
  --primary-10: rgba(255, 214, 46, 0.10);
  --primary-glow: rgba(255, 214, 46, 0.25);

  --code-bg: #1f1b15;
  --code-fg: #dfd9cc;
  --code-border: #343028;
  --code-scroll: #545048;

  --sidebar-bg: #13100a;
  --header-bg: rgba(22, 20, 13, 0.88);
}

[data-theme="light"][data-scheme="lemon"] {
  --bg: #f9f5e6;
  --bg-card: #fcf9f0;
  --bg-panel: #f8f3e4;
  --bg-hover: #f1ecd8;
  --bg-input: #ffffff;

  --border: rgba(98, 88, 60, 0.10);
  --border-md: rgba(98, 88, 60, 0.16);
  --border-lg: rgba(98, 88, 60, 0.22);

  --text: #262114;
  --text-sub: #554d3f;
  --text-muted: #6f685a;   /* 对 --bg-hover 4.66:1（demo #726A5C 仅 4.51） */
  --text-dim: #8c8477;     /* 对 --bg-hover 3.12:1（demo #8D8578 仅 3.08） */
  --text-inverse: #fff;

  --primary: #706d22;      /* ★ 反解 + 色相偏移：demo #FFD62E 作文字仅 1.19:1，
                               纯同色相反解又会撞死 --yellow（ΔE00 9.97）⇒ 偏到深橄榄 102.3°，
                               4.55:1 达标，角距 25.8° / ΔE00 15.8，走 A12 正常判据 */
  --primary-fill: #ffd62e; /* A′：实心填充保留 demo 原色；--on-primary 13.41:1 */
  --on-primary: #1a1506;
  --primary-rgb: 112, 109, 34;
  --primary-sub: rgba(112, 109, 34, 0.18);
  --primary-10: rgba(112, 109, 34, 0.10);
  --primary-glow: rgba(112, 109, 34, 0.25);

  --code-bg: #f5f0e1;
  --code-fg: var(--text);
  --code-border: #eae5d7;
  --code-scroll: #cdc8b9;

  --sidebar-bg: #f1ecd8;
  --header-bg: rgba(249, 245, 230, 0.92);
}
