/* theme.css — qcode.cc 深浅双主题 (Phase 1: 基建 + home.html 试点)
 *
 * 架构（详见 job GOAL.md §3.4）：
 * - 无 [data-theme] 属性时零覆盖，等价于今天的样子（SEO/无 JS 环境安全）。
 * - 变量在 html[data-theme="dark|light"] 上声明；覆盖规则统一挂在 [data-theme] 选择器下。
 * - 覆盖规则额外挂在 .qc-ink 祖先下（body 在 navbar_theme=='dark' 时加此类，footer 恒加）：
 *   Tailwind 的 gray-400/700/900 等中性色类在“浅色 gray 体系”页面里是当前已经正确的颜色，
 *   若不加 .qc-ink 限定，选中主题会把尚未审计的页面也染色，产生「浅底浅字」回归。
 *   bg-ink-950/900、text-white(/opacity)、border-white(/opacity) 这一族类只在 ink 深色设计
 *   语境里出现，理论上裸类覆盖也安全，但为保持规则风格统一，同样挂在 .qc-ink 下。
 * - .qc-keep：品牌色/纯色按钮背景上的白字（如橙色 CTA、彩色徽章、纯色数字圆圈）必须永远保持
 *   白色，不随主题变化。用 :not(.qc-keep):not(.qc-keep *) 排除这些元素及其子孙。
 *
 * 🔴 Phase 1 review R2：color-mix() 是 Chrome 111+/Safari 16.4+，var() 全浏览器支持。
 * 不做 @supports 兜底的话，老浏览器上背景覆盖（var()）生效、文字覆盖（color-mix()）
 * 整条声明失效回落原色 → 白底白字。整个覆盖层（含变量声明块）包进 @supports，
 * 老浏览器 = 零覆盖 = 今天的样子（「没有主题功能」而不是「页面坏掉」）。
 * theme.js 用同一个特性检测隐藏切换控件，避免用户点一个没有效果的按钮。
 */

@supports (color: color-mix(in srgb, red 50%, transparent)) {

html[data-theme="dark"] {
  color-scheme: dark;
  --qc-fg: #F5F1EE;              /* GOAL 4B.5 dark fg */
  --qc-fg-secondary: #948C85;
  --qc-fg-tertiary: #948C85;
  --qc-surface-0: #0F0D0C;
  --qc-surface-1: #171412;
  --qc-surface-2: #0A0908;
  --qc-badge-blue: #93c5fd;      /* == blue-300 */
  --qc-badge-emerald: #6ee7b7;   /* == emerald-300 */
  --qc-badge-amber: #fcd34d;     /* == amber-300 */
  --qc-badge-green: #86efac;     /* == green-300 */
  --qc-badge-orange: #fdba74;    /* == orange-300 */
  --qc-badge-purple: #d8b4fe;    /* == purple-300 */
  --qc-badge-indigo: #a5b4fc;    /* == indigo-300 */
  --qc-badge-red: #fca5a5;       /* == red-300 */
  /* 品牌橙 token 体系（brand-color-system 2026-08-09，V3 严格尺寸分档拍板）：
     站规四条：① 每视区一个主 CTA 用品牌填充，次级用 ghost/描边；
     ② 橙在深色区只允许：实心 CTA、/10~/20 光晕、文字高亮；浅色区对称：
     实心 CTA(--brand-fill)、tint 面(5%~20%)、文字强调(--brand-text)；
     ③ 禁区：警告/错误/进行中等语义色不用品牌橙；大面积正文底不用橙；不与黄/琥珀混排；
     ④ 散落硬编码橙一律收敛到本 token 组（tailwind 预构建不可改，用本覆盖机制收敛）。
     尺寸分档：≥18.66px bold 大字 CTA 用 --brand 本色（白字 3.12≥3:1）；
     常规字号填充钮统一 --brand-fill（白字 5.17≥4.5:1）。 */
  --qc-brand: #E39A82;           /* GOAL 4B.5 dark brand */
  --qc-brand-on: #0F0D0C;
  --qc-brand-fill: #A35941;      /* regular-size fill buttons (white text 5.17:1) */
  --qc-brand-fill-hover: #8F4D38;/* fill hover (white text 6.39:1, darker) */
  --qc-brand-text: #E39A82;      /* dark-theme text = brand */
  --qc-brand-text-hover: #EDAF9B;
}

html[data-theme="light"] {
  color-scheme: light;
  /* 2026-08-09 Apple 质感精修（jobs-2026-08-09-light-theme-apple-polish）：
     浅色从「深色的镜像推导」改为独立设计。文字从 color-mix 派生中灰改为 Apple 实色阶
     （梯度机制保留作未映射档兜底）；基底改 Apple 标准灰白；新增发丝线与 3 档阴影 token，
     全站复用，禁止各处手写。深色变量集一行未动。
     fg-secondary 微调说明：规范的 #6E6E73 在白/#F5F5F7 上达标（4.85/4.55），但在橙/蓝
     tint 底（bg-qcode-primary/15、from-blue-50 渐变，合成底 L≈0.88）跌到 4.35~4.42
     破 4.5 红线；深一档到 #69696E 后 tint 底实测 ≥4.8、白底 5.46，观感差异不可辨。
     （本块内各行尾注释一律 ASCII——行内中文注释会让上一段注释结束后 40 字符内出现
     CJK，触发 R7 注释完整性检查假阳性，见 theme_coverage_audit.py 判据。） */
  --qc-fg: #1A1613;              /* GOAL 4B.5 light fg */
  --qc-fg-body: #413A34;
  --qc-fg-secondary: #6E6660;
  --qc-fg-tertiary: #6E6660;
  --qc-surface-0: #FBFAF9;
  --qc-surface-1: #FFFFFF;
  --qc-surface-2: #F4F1EE;
  --qc-hairline: rgba(26, 22, 19, .10);
  --qc-shadow-rest: 0 1px 2px rgba(0, 0, 0, .04), 0 4px 16px rgba(0, 0, 0, .06);
  --qc-shadow-hover: 0 2px 6px rgba(0, 0, 0, .05), 0 10px 28px rgba(0, 0, 0, .09);
  --qc-shadow-modal: 0 8px 32px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);
  /* 品牌橙 token（同组注释见上方 dark 变量块；值按主题分档） */
  --qc-brand: #D97757;
  --qc-brand-on: #1D1D1F;
  --qc-brand-fill: #A35941;
  --qc-brand-fill-hover: #8F4D38;
  --qc-brand-text: #A8461F;
  --qc-brand-text-hover: #9C4A24;
  --qc-badge-blue: #1d4ed8;      /* == blue-700 */
  --qc-badge-emerald: #047857;   /* == emerald-700 */
  --qc-badge-amber: #b45309;     /* == amber-700 */
  --qc-badge-green: #15803d;     /* == green-700 */
  --qc-badge-orange: #c2410c;    /* == orange-700 */
  --qc-badge-purple: #7e22ce;    /* == purple-700 */
  --qc-badge-indigo: #4338ca;    /* == indigo-700 */
  --qc-badge-red: #b91c1c;       /* == red-700 */
}

/* ---- 三态切换控件（不受 .qc-ink 限定，任何页面都要正确显示） ---- */
[data-theme] .qc-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 9999px;
  border: 1px solid color-mix(in srgb, var(--qc-fg) 15%, transparent);
  background: color-mix(in srgb, var(--qc-fg) 6%, transparent);
  color: var(--qc-fg);
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
  flex-shrink: 0;
}
[data-theme] .qc-theme-toggle:hover {
  background: color-mix(in srgb, var(--qc-fg) 12%, transparent);
}
[data-theme] .qc-theme-toggle svg {
  width: 1.1rem;
  height: 1.1rem;
}
[data-theme] .qc-theme-toggle-mobile {
  width: 100%;
  height: auto;
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
  justify-content: flex-start;
  gap: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
}

/* ================= .qc-ink 范围内覆盖（Phase 1: home / footer / navbar 暗分支） ================= */

/* 版面基底 */
[data-theme] .qc-ink.bg-ink-950,
[data-theme] .qc-ink .bg-ink-950 { background-color: var(--qc-surface-0); }
[data-theme] .qc-ink .bg-ink-900 { background-color: var(--qc-surface-1); }
[data-theme] .qc-ink .bg-ink-800 { background-color: var(--qc-surface-2); }

/* Hero 背景渐变遮罩（from/via/to-ink-950），逐条镜像 tailwind.css 生成的 CSS 变量结构 */
[data-theme] .qc-ink .from-ink-950 {
  --tw-gradient-from: var(--qc-surface-0) var(--tw-gradient-from-position);
  --tw-gradient-to: color-mix(in srgb, var(--qc-surface-0) 0%, transparent) var(--tw-gradient-to-position);
  --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
[data-theme] .qc-ink .via-ink-950\/80 {
  --tw-gradient-to: color-mix(in srgb, var(--qc-surface-0) 0%, transparent) var(--tw-gradient-to-position);
  --tw-gradient-stops: var(--tw-gradient-from), color-mix(in srgb, var(--qc-surface-0) 80%, transparent) var(--tw-gradient-via-position), var(--tw-gradient-to);
}
[data-theme] .qc-ink .to-ink-950\/20 {
  --tw-gradient-to: color-mix(in srgb, var(--qc-surface-0) 20%, transparent) var(--tw-gradient-to-position);
}
/* 裸 to-ink-950（无 /opacity）：hero 图底部收进页面基底的收底渐变（models.html、
   partner_program.html 各一处）。Phase 2 review R3：这条曾经被错误地当成"纯装饰"
   放进 allowlist 的 deco 类，浅色主题下没人管它，留下 to-ink-950 的字面近黑色值，
   在浅色页面中部横出一条黑带。教训：allowlist 里任何 ink/black/white 字面色值的条目，
   都必须先确认它是不是"收底/融入基底"语义，不能只看"看起来像装饰"就放行。 */
[data-theme] .qc-ink .to-ink-950 {
  --tw-gradient-to: var(--qc-surface-0) var(--tw-gradient-to-position);
}

/* 正文层级：不透明度梯度用 color-mix 从 --qc-fg 派生，深/浅主题自动对称。
   Phase 2 铺开到 pricing/models 后发现原来的梯度缺档（/20、/70 等），逐个补齐——
   缺一档不是"降级到无覆盖就好"，是那一档的文字会保持原始的 white/opacity 字面值，
   浅色主题下同样是浅底浅字，跟 R1 是同一类问题，靠 --raw 校准时发现一个补一个。 */
[data-theme] .qc-ink.text-white:not(.qc-keep):not(.qc-keep *),
[data-theme] .qc-ink .text-white:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg); }
[data-theme] .qc-ink .text-white\/90:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 90%, transparent); }
[data-theme] .qc-ink .text-white\/80:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 80%, transparent); }
[data-theme] .qc-ink .text-white\/70:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 70%, transparent); }
[data-theme] .qc-ink .text-white\/60:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 60%, transparent); }
[data-theme] .qc-ink .text-white\/50:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 50%, transparent); }
/* Phase 3 review R8：40% 混合比在深浅两个主题下不对称——深色主题下文字是白色
   混到近黑背景上，浅色主题下文字是近黑色混到浅灰背景上，同一个百分比在浅色这侧
   算出的对比度明显更低（实测 2.68:1 vs 深色原设计的 3.83:1，跟 Phase 1 §2.3
   发现的 55%→60% 是同一类不对称，那次也是浅色这侧偏弱）。这一档用在 openapi_token
   的 GET 接口清单说明文字、payment_success 的「返回充值页」链接这类次要但仍要读的
   文字上，深色主题的 40% 保持不动（对齐原设计，未失败），浅色主题单独提到 60%——
   实测对比度 ≈5.13:1，同时满足 R8 两档要求（非交互文字 ≥3.8、可交互文字 ≥4.5），
   不用为「是否可交互」再拆一套选择器。border-white/40、placeholder-white/40 是
   装饰性描边/占位符，不担文字对比度，按 review 拍板原样保留，不跟着拆。 */
html[data-theme="dark"] .qc-ink .text-white\/40:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-secondary); }
html[data-theme="light"] .qc-ink .text-white\/40:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-secondary); } /* Apple 精修：60% color-mix 中灰 → 次要实色（tint 底实测 ≥4.8:1，满足 R8 两档要求） */
[data-theme] .qc-ink .text-white\/30:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 30%, transparent); }
[data-theme] .qc-ink .text-white\/20:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 20%, transparent); }

[data-theme] .qc-ink .text-gray-200:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 75%, transparent); }
[data-theme] .qc-ink .text-gray-300:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 65%, transparent); }
[data-theme] .qc-ink .text-gray-400:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 60%, transparent); }
[data-theme] .qc-ink .text-ink-muted:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 60%, transparent); }

/* 半透明玻璃拟态卡片/按钮背景 + 边框 + 分隔线 + 输入框占位符，同一套不透明度梯度。
   2026-08-09 Apple 精修补 :not(.qc-keep)：品牌实底(qc-keep)上的白纱/白边是设计本身、
   两主题不变——深色下 color-mix(fg=白 N%) 与 tailwind 原值逐位相同所以一直没人察觉；
   浅色下 fg=#1D1D1F 会把品牌面上的白纱翻成黑纱（home 趋势图卡头切换钮实测抓到）。
   深色像素零变化的可证性：深色 fg=#ffffff，排除 qc-keep 后这些元素回落 tailwind 原值
   rgb(255 255 255 / N)，与 color-mix(白 N%) 完全同色。 */
[data-theme] .qc-ink .bg-white\/5:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, var(--qc-fg) 5%, transparent); }
[data-theme] .qc-ink .bg-white\/10:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, var(--qc-fg) 10%, transparent); }
[data-theme] .qc-ink .bg-white\/20:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, var(--qc-fg) 20%, transparent); }
[data-theme] .qc-ink .bg-white\/30:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, var(--qc-fg) 30%, transparent); }
[data-theme] .qc-ink .bg-white\/15:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, var(--qc-fg) 15%, transparent); }

[data-theme] .qc-ink .border-white\/10:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 10%, transparent); }
[data-theme] .qc-ink .border-white\/15:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 15%, transparent); }
[data-theme] .qc-ink .border-white\/20:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 20%, transparent); }
[data-theme] .qc-ink .border-white\/30:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 30%, transparent); }
[data-theme] .qc-ink .border-white\/40:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 40%, transparent); }
[data-theme] .qc-ink .divide-white\/5 > :not([hidden]) ~ :not([hidden]):not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 5%, transparent); }
[data-theme] .qc-ink .divide-white\/10 > :not([hidden]) ~ :not([hidden]):not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 10%, transparent); }
[data-theme] .qc-ink .placeholder-white\/40:not(.qc-keep):not(.qc-keep *)::placeholder { color: color-mix(in srgb, var(--qc-fg) 40%, transparent); }

/* 弹层/模态的暗场蒙层——蒙层要跟着"版面基底"走，不是跟前景文字走 */
[data-theme] .qc-ink .bg-ink-950\/60 { background-color: color-mix(in srgb, var(--qc-surface-0) 60%, transparent); }

/* 头像/圆点上的实心白色描边：语义是「与所在版面背景抠开一圈」，应跟 surface 走，不跟 fg 走。
   不参与 :not(.qc-keep) 排除——3 处用例（home.html 好评徽章头像）都要这个效果。 */
[data-theme] .qc-ink .border-white { border-color: var(--qc-surface-0); }

/* 徽章/标签文字：深色主题下维持原 -300 色阶，浅色主题下换成 -700 色阶以保证对比度。
   徽章背景 bg-{color}-500/10 是低透明度色块，两种主题下都可读，不需要覆盖。 */
[data-theme] .qc-ink .text-blue-300 { color: var(--qc-badge-blue); }
[data-theme] .qc-ink .text-emerald-300 { color: var(--qc-badge-emerald); }
[data-theme] .qc-ink .text-amber-300 { color: var(--qc-badge-amber); }
html[data-theme="dark"] .qc-ink .text-yellow-300 { color: var(--qc-badge-amber); }
html[data-theme="light"] .qc-ink .text-yellow-300 { color: #92400e; } /* amber-800，比 --qc-badge-amber(amber-700) 深一档，实测在 bg-yellow-500/10 叠加出的浅米黄底上达标 */
[data-theme] .qc-ink .text-green-300 { color: var(--qc-badge-green); }
[data-theme] .qc-ink .text-orange-300 { color: var(--qc-badge-orange); }
[data-theme] .qc-ink .text-purple-300 { color: var(--qc-badge-purple); }
[data-theme] .qc-ink .text-indigo-300 { color: var(--qc-badge-indigo); }
/* text-indigo-200：pricing/subscribe 企业版卡标题/价格用（2026-08-08 pricing-value job 顺带修的
   既有缺口——badge 映射表有 -300 无 -200，浅色主题下 indigo-200 字面值压在 indigo-500/10 浅底上偏淡）。
   深色维持原 indigo-200 字面值（原设计不动），浅色换 indigo-700（与 -300 同一 badge 变量，实测达标）。 */
html[data-theme="dark"] .qc-ink .text-indigo-200 { color: #c7d2fe; }
html[data-theme="light"] .qc-ink .text-indigo-200 { color: var(--qc-badge-indigo); }
[data-theme] .qc-ink .text-red-300 { color: var(--qc-badge-red); }

/* navbar 滚动态浮层（navbar_theme=='dark' 专用的 Alpine :class 动态背景） */
[data-theme] .qc-ink .bg-black\/80 { background-color: color-mix(in srgb, var(--qc-surface-0) 80%, transparent); }

/* auth-status HTMX 片段（/auth/status，8 个 auth_status_*.html 模板）：main.css 里的
   .nav-auth-dark 是主题切换之前就有的老规则，无条件把片段文字强制成 rgb(255 255 255/0.8)，
   假设「ink 页永远是深色」。现在 ink 页可以被用户切成浅色，老规则还在无条件生效，会变成
   浅底浅字。这里用同一批变量接管，特异性 + 加载顺序都比 main.css 那条规则高，实际生效；
   main.css 那条规则保留不删——@supports 不支持的老浏览器上它仍是唯一生效的规则，效果等于
   「今天的样子」，不能删掉。 */
[data-theme] .qc-ink .nav-auth-dark > div > a:not(.qc-keep):not(.qc-keep *),
[data-theme] .qc-ink .nav-auth-dark > div > span:not(.qc-keep):not(.qc-keep *),
[data-theme] .qc-ink .nav-auth-dark > div > button:not(.qc-keep):not(.qc-keep *),
[data-theme] .qc-ink .nav-auth-dark > div > div > button:not(.qc-keep):not(.qc-keep *) {
  color: color-mix(in srgb, var(--qc-fg) 80%, transparent);
}
[data-theme] .qc-ink .nav-auth-dark > div > a:hover:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg); }

/* ================= .qc-paper 范围内覆盖（Phase 2：privacy / terms / 404，浅色 gray 体系） =================
   跟 .qc-ink 是镜像关系，复用同一批 --qc-fg / --qc-surface-* 变量——它们本来就是「当前主题下
   该用什么颜色」，不是「假设页面原本是深色」，两个体系共用完全合理。opt-in 方式跟 .qc-ink
   一样：body 只有在页面模板顶部显式 {% set qc_paper = true %} 时才带 .qc-paper，没有这个
   显式声明的浅色页面（admin/reseller/kb/docs/seo 等，Phase 5 范围）不受任何影响——这些页面
   大量使用同名的 text-gray-900 等类，裸类覆盖会造成白底白字，必须逐页审计后才能加入范围。 */
[data-theme] .qc-paper.bg-white,
[data-theme] .qc-paper .bg-white:not(.qc-keep):not(.qc-keep *) { background-color: var(--qc-surface-0); }
[data-theme] .qc-paper.bg-gray-50,
[data-theme] .qc-paper .bg-gray-50:not(.qc-keep):not(.qc-keep *) { background-color: var(--qc-surface-1); }

[data-theme] .qc-paper .text-gray-900:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg); }
[data-theme] .qc-paper .text-gray-700:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 80%, transparent); }
[data-theme] .qc-paper .text-gray-600:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 70%, transparent); }
[data-theme] .qc-paper .text-gray-500:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 60%, transparent); }
[data-theme] .qc-paper .text-gray-300:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 35%, transparent); } /* 纯装饰性分隔符，不担对比度要求 */

[data-theme] .qc-paper .border-gray-200:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 12%, transparent); }
[data-theme] .qc-paper .border-gray-300:not(.qc-keep):not(.qc-keep *) { border-color: color-mix(in srgb, var(--qc-fg) 20%, transparent); }

/* 法务长文（privacy/terms）用 .prose 包正文，里面的 h2/h3/p/li/strong 全是裸标签——项目没装
   @tailwindcss/typography 插件（tailwind.config.js plugins:[] 确认过），.prose/.prose-gray
   本身不生成任何 CSS，这些标签今天的颜色就是浏览器默认黑色，靠 color 继承撑到根。用同一个
   继承机制反色：只在 .prose 容器上设一次 color，不用逐标签映射。 */
[data-theme] .qc-paper .prose:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg); }

/* ================= .panel-dark（Phase 3 review 拍板 3：第三个范围类） =================
   .panel-dark 是这个项目之前就有的机制（main.css），专门给"JS 动态生成的浅色 HTML /
   源码零改动的第三方浅色片段，嵌进 ink 深色容器"这个场景用——用法是在容器上加
   .panel-dark，main.css 里一批 `.panel-dark .text-gray-900{color:#fff}` 之类的规则把
   里面的浅色 Tailwind 类强制染成固定深色，today 的效果等于"这块内容看起来跟外面一样黑"。
   6 个使用点，2 个文件（Phase 3 报告里的全站使用点清单）：
     dashboard.html: 升级提示卡片渐变容器(L310)、usage_stats.html 宿主(L646)、
                      通知列表(L696)、帮助/错误码面板(L884)、确认弹窗遮罩(L975)
     recharge.html:  充值历史表格(L714)
   问题：main.css 那批规则是硬编码固定深色值，不认 [data-theme]——今天"外层容器永远是
   深色"这个假设，在用户能把 ink 页切成浅色主题之后不再成立。拍板 3：模板侧的
   .panel-dark 标记不动（它仍然是"这块是别处生成的浅色 HTML，需要着色"的正确标记），
   把 main.css 里那批固定色值在 theme.css 里用同一份 --qc-fg / --qc-surface-* /
   --qc-badge-* 变量重新声明一遍（R7 事故记录：这里原文在写完 --qc-surface 的通配符后缀紧接着就是分隔用的斜杠，两个符号写在了一起，无意中拼出了 CSS 注释的结束标记。CSS 注释不嵌套，这一整段说明因此提前截断——.panel-dark .bg-white 那条规则被一起吞掉，浅色主题下这张卡片背景照旧显示 main.css 的硬编码黑色，文字却被后面还活着的另一条 panel-dark 规则正常染成深色，黑底深字。以后写 --xxx-通配符 这种记法时，跟在它后面的分隔符前一定要留出空格，不能让通配符和斜杠紧挨着。）——选择器特异性 + 加载顺序都比 main.css 高（同样两级
   类选择器，theme.css 后加载；[data-theme] 属性选择器让这里的版本在有主题属性时
   specificity 更高，无属性/不支持 color-mix() 的老浏览器上 main.css 原规则原样兜底），
   深色主题下数值跟原来完全一致（--qc-fg dark=#fff、--qc-surface-1 dark=#141416，
   跟 main.css 硬编码的 #141416 逐位相同），浅色主题下才会真的变浅。
   徽章色（text-{color}-600/700/800/900 → 固定浅色）尤其要看：main.css 原本假设
   "外面永远深色"所以直接给了 -300 色阶的浅色值（如 text-red-* → #fca5a5，正是
   red-300），今天在浅色容器里维持浅色文字就是新的"浅底浅字"——换成 --qc-badge-red
   之后，深色主题下还是 #fca5a5（一致），浅色主题下变成对应的 -700 色阶（跟 ink 系统
   徽章文字用的是同一套变量、同一个判断）。 */
[data-theme] .panel-dark .bg-white { background-color: var(--qc-surface-1); }
[data-theme] .panel-dark .bg-gray-50,
[data-theme] .panel-dark .bg-gray-100 { background-color: var(--qc-surface-2); }
[data-theme] .panel-dark .text-gray-900,
[data-theme] .panel-dark .text-gray-800 { color: var(--qc-fg); }
[data-theme] .panel-dark .text-gray-700,
[data-theme] .panel-dark .text-gray-600 { color: color-mix(in srgb, var(--qc-fg) 70%, transparent); }
[data-theme] .panel-dark .text-gray-500,
[data-theme] .panel-dark .text-gray-400 { color: color-mix(in srgb, var(--qc-fg) 40%, transparent); }
[data-theme] .panel-dark .border-gray-200,
[data-theme] .panel-dark .border-gray-100,
[data-theme] .panel-dark .divide-gray-200 > * + *,
[data-theme] .panel-dark .divide-gray-100 > * + * { border-color: color-mix(in srgb, var(--qc-fg) 10%, transparent); }
[data-theme] .panel-dark input:not([type=checkbox]):not([type=radio]),
[data-theme] .panel-dark select,
[data-theme] .panel-dark textarea { background-color: var(--qc-surface-2); border-color: color-mix(in srgb, var(--qc-fg) 15%, transparent); color: var(--qc-fg); }
[data-theme] .panel-dark input::placeholder,
[data-theme] .panel-dark textarea::placeholder { color: color-mix(in srgb, var(--qc-fg) 40%, transparent); }

/* 徽章正文字（main.css 原本固定给 -300 浅色阶，假设外面永远深色） */
[data-theme] .panel-dark .text-red-600, [data-theme] .panel-dark .text-red-700,
[data-theme] .panel-dark .text-red-800, [data-theme] .panel-dark .text-red-900 { color: var(--qc-badge-red); }
[data-theme] .panel-dark .text-orange-600, [data-theme] .panel-dark .text-orange-700,
[data-theme] .panel-dark .text-orange-800, [data-theme] .panel-dark .text-orange-900 { color: var(--qc-badge-orange); }
[data-theme] .panel-dark .text-yellow-600, [data-theme] .panel-dark .text-yellow-700,
[data-theme] .panel-dark .text-yellow-800, [data-theme] .panel-dark .text-yellow-900 { color: var(--qc-badge-amber); }
[data-theme] .panel-dark .text-green-600, [data-theme] .panel-dark .text-green-700,
[data-theme] .panel-dark .text-green-800, [data-theme] .panel-dark .text-green-900 { color: var(--qc-badge-green); }
[data-theme] .panel-dark .text-blue-600, [data-theme] .panel-dark .text-blue-700,
[data-theme] .panel-dark .text-blue-800, [data-theme] .panel-dark .text-blue-900 { color: var(--qc-badge-blue); }
[data-theme] .panel-dark .text-purple-600, [data-theme] .panel-dark .text-purple-700,
[data-theme] .panel-dark .text-purple-800, [data-theme] .panel-dark .text-purple-900 { color: var(--qc-badge-purple); }
[data-theme] .panel-dark .text-indigo-600, [data-theme] .panel-dark .text-indigo-700,
[data-theme] .panel-dark .text-indigo-800, [data-theme] .panel-dark .text-indigo-900 { color: var(--qc-badge-indigo); }
[data-theme] .panel-dark .text-amber-600, [data-theme] .panel-dark .text-amber-700,
[data-theme] .panel-dark .text-amber-800, [data-theme] .panel-dark .text-amber-900 { color: var(--qc-badge-amber); }
[data-theme] .panel-dark .text-emerald-600, [data-theme] .panel-dark .text-emerald-700,
[data-theme] .panel-dark .text-emerald-800, [data-theme] .panel-dark .text-emerald-900 { color: var(--qc-badge-emerald); }
[data-theme] .panel-dark .hover\:text-blue-600:hover, [data-theme] .panel-dark .hover\:text-blue-700:hover,
[data-theme] .panel-dark .hover\:text-blue-800:hover { color: var(--qc-badge-blue); }
[data-theme] .panel-dark .hover\:text-emerald-600:hover { color: var(--qc-badge-emerald); }
[data-theme] .panel-dark .hover\:text-red-600:hover, [data-theme] .panel-dark .hover\:text-red-700:hover,
[data-theme] .panel-dark .hover\:text-red-800:hover { color: var(--qc-badge-red); }
[data-theme] .panel-dark .hover\:text-gray-600:hover { color: color-mix(in srgb, var(--qc-fg) 70%, transparent); }
[data-theme] .panel-dark .hover\:text-gray-800:hover { color: var(--qc-fg); }
[data-theme] .panel-dark .group:hover .group-hover\:text-blue-600 { color: var(--qc-badge-blue); }
[data-theme] .panel-dark .group:hover .group-hover\:text-red-700 { color: var(--qc-badge-red); }

/* 灰阶尾巴（main.css 359-370 行区间之外单独列的几条） */
[data-theme] .panel-dark .bg-gray-200 { background-color: color-mix(in srgb, var(--qc-fg) 10%, transparent); }
[data-theme] .panel-dark .text-gray-300 { color: color-mix(in srgb, var(--qc-fg) 30%, transparent); }
[data-theme] .panel-dark .border-gray-300 { border-color: color-mix(in srgb, var(--qc-fg) 15%, transparent); }
[data-theme] .panel-dark .hover\:border-gray-300:hover { border-color: color-mix(in srgb, var(--qc-fg) 15%, transparent); }

/* 低透明度徽章底/连接线/hover 底色（bg-{color}-50/100、from-/to-/via-、悬浮态）：跟
   ink/paper 系统的"chip"分类同理，翻译成半透明色块两种主题下都读得出来，不需要跟着
   反色——main.css 里那批 rgb(.../0.15) 之类的规则原样保留，不在这里重复声明。 */

/* Phase 5 review R9：seo/kb 长尾页大量用 bg-{color}-50/100 或
   from-/to-{color}-50/100 渐变做「内容盒」底色（不是 chip 徽章），盒子内部的
   标题/正文走的是 .qc-paper 会翻转的 text-gray-* 类——深色主题下文字翻成白色，
   容器底色却还停在原来的浅色 tint，白字压浅底。用 scripts/scan_lightbg_flip.py
   区分过「内容盒」（容器内有翻转文字类）和「chip」（只有固定色阶徽章文字，
   自洽，不在这里处理）——这里只映射前者，62 个 bg-/from-/to-{color}-50/100
   组合，1114 处使用点，101 个文件（同一个 combo 在很多页面反复用）。
   深色下的值选择：保色相、降亮度（color-mix 混合该色系 500 号色相到
   --qc-surface-1 上，10%/16% 两档对应原来 -50/-100 的相对轻重），不是
   统一成同一个中性灰——这批内容盒在设计上就是用颜色区分不同功能分类
   （比如同一个页面里紫色卡片讲一个模型、蓝色卡片讲另一个），统一成灰会丢失
   这层设计意图；两个方案的对比截图见 REPORTS/shots/phase-5/r9-surface-comparison/。
   gray 本身是中性色，直接对应 --qc-surface-1/2，不用 color-mix 调色。 */
[data-theme] .qc-paper .bg-amber-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #f59e0b 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-blue-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #3b82f6 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-cyan-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #06b6d4 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-emerald-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #10b981 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-gray-50:not(.qc-keep):not(.qc-keep *) { background-color: var(--qc-surface-1); }
[data-theme] .qc-paper .bg-gray-100:not(.qc-keep):not(.qc-keep *) { background-color: var(--qc-surface-2); }
[data-theme] .qc-paper .bg-green-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #22c55e 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-indigo-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #6366f1 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-orange-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #f97316 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-purple-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #a855f7 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-red-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #ef4444 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-teal-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #14b8a6 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-violet-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #8b5cf6 10%, var(--qc-surface-1)); }
[data-theme] .qc-paper .bg-yellow-50:not(.qc-keep):not(.qc-keep *) { background-color: color-mix(in srgb, #eab308 10%, var(--qc-surface-1)); }

[data-theme] .qc-paper .from-amber-50 { --tw-gradient-from: color-mix(in srgb, #f59e0b 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-blue-50 { --tw-gradient-from: color-mix(in srgb, #3b82f6 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-cyan-50 { --tw-gradient-from: color-mix(in srgb, #06b6d4 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-emerald-50 { --tw-gradient-from: color-mix(in srgb, #10b981 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-fuchsia-50 { --tw-gradient-from: color-mix(in srgb, #d946ef 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-gray-50 { --tw-gradient-from: var(--qc-surface-1) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-green-50 { --tw-gradient-from: color-mix(in srgb, #22c55e 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-indigo-50 { --tw-gradient-from: color-mix(in srgb, #6366f1 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-orange-50 { --tw-gradient-from: color-mix(in srgb, #f97316 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-purple-50 { --tw-gradient-from: color-mix(in srgb, #a855f7 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-red-50 { --tw-gradient-from: color-mix(in srgb, #ef4444 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-rose-50 { --tw-gradient-from: color-mix(in srgb, #f43f5e 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-sky-50 { --tw-gradient-from: color-mix(in srgb, #0ea5e9 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-teal-50 { --tw-gradient-from: color-mix(in srgb, #14b8a6 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-violet-50 { --tw-gradient-from: color-mix(in srgb, #8b5cf6 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }
[data-theme] .qc-paper .from-yellow-50 { --tw-gradient-from: color-mix(in srgb, #eab308 10%, var(--qc-surface-1)) var(--tw-gradient-from-position); }

[data-theme] .qc-paper .to-amber-50 { --tw-gradient-to: color-mix(in srgb, #f59e0b 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-amber-100 { --tw-gradient-to: color-mix(in srgb, #f59e0b 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-blue-50 { --tw-gradient-to: color-mix(in srgb, #3b82f6 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-blue-100 { --tw-gradient-to: color-mix(in srgb, #3b82f6 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-cyan-50 { --tw-gradient-to: color-mix(in srgb, #06b6d4 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-cyan-100 { --tw-gradient-to: color-mix(in srgb, #06b6d4 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-emerald-50 { --tw-gradient-to: color-mix(in srgb, #10b981 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-emerald-100 { --tw-gradient-to: color-mix(in srgb, #10b981 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-fuchsia-50 { --tw-gradient-to: color-mix(in srgb, #d946ef 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-fuchsia-100 { --tw-gradient-to: color-mix(in srgb, #d946ef 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-gray-50 { --tw-gradient-to: var(--qc-surface-1) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-green-50 { --tw-gradient-to: color-mix(in srgb, #22c55e 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-green-100 { --tw-gradient-to: color-mix(in srgb, #22c55e 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-indigo-50 { --tw-gradient-to: color-mix(in srgb, #6366f1 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-indigo-100 { --tw-gradient-to: color-mix(in srgb, #6366f1 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-lime-50 { --tw-gradient-to: color-mix(in srgb, #84cc16 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-orange-50 { --tw-gradient-to: color-mix(in srgb, #f97316 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-orange-100 { --tw-gradient-to: color-mix(in srgb, #f97316 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-pink-50 { --tw-gradient-to: color-mix(in srgb, #ec4899 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-purple-50 { --tw-gradient-to: color-mix(in srgb, #a855f7 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-purple-100 { --tw-gradient-to: color-mix(in srgb, #a855f7 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-red-50 { --tw-gradient-to: color-mix(in srgb, #ef4444 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-red-100 { --tw-gradient-to: color-mix(in srgb, #ef4444 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-rose-100 { --tw-gradient-to: color-mix(in srgb, #f43f5e 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-sky-50 { --tw-gradient-to: color-mix(in srgb, #0ea5e9 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-sky-100 { --tw-gradient-to: color-mix(in srgb, #0ea5e9 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-teal-50 { --tw-gradient-to: color-mix(in srgb, #14b8a6 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-teal-100 { --tw-gradient-to: color-mix(in srgb, #14b8a6 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-violet-50 { --tw-gradient-to: color-mix(in srgb, #8b5cf6 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-violet-100 { --tw-gradient-to: color-mix(in srgb, #8b5cf6 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-yellow-50 { --tw-gradient-to: color-mix(in srgb, #eab308 10%, var(--qc-surface-1)) var(--tw-gradient-to-position); }
[data-theme] .qc-paper .to-yellow-100 { --tw-gradient-to: color-mix(in srgb, #eab308 16%, var(--qc-surface-1)) var(--tw-gradient-to-position); }

/* ================= pv-* 价值表达组件（pricing-value-presentation, 2026-08-08 Phase 2 收敛版） =================
   main.css 里的 pv-* 基准值是深色字面量（无 JS/老浏览器 = 今天的深色样子）；这里按主题翻转变量化。
   与上方既有覆盖层同架构：挂 [data-theme] .qc-ink，color-mix 从 --qc-fg 派生梯度。 */

/* accent 橙文字：浅色主题换深一号（品牌 #d97757 白底实测 ≈3.15:1，不达 4.5；
   #b04a2e 白底实测 ≈5.4:1）。深色维持品牌色（ink-950 上 ≈6.3:1）。 */
html[data-theme="dark"] .qc-ink .pv-accent { color: var(--qc-brand-text); }
html[data-theme="light"] .qc-ink .pv-accent { color: var(--qc-brand-text); } /* == #B04A2E，brand-color-system 起单源 */

/* 费率标尺 */
[data-theme] .qc-ink .pv-meter-track { background: color-mix(in srgb, var(--qc-fg) 8%, transparent); }
[data-theme] .qc-ink .pv-meter-dot { border-color: var(--qc-surface-0); }
[data-theme] .qc-ink .pv-meter-dot--official { background: color-mix(in srgb, var(--qc-fg) 45%, transparent); }
[data-theme] .qc-ink .pv-meter-dot--base { background: var(--qc-fg); }
[data-theme] .qc-ink .pv-meter-dot--yours { background: #d97757; }
[data-theme] .qc-ink .pv-meter-leader { background: color-mix(in srgb, var(--qc-fg) 25%, transparent); }
[data-theme] .qc-ink .pv-meter-leader--yours { background: color-mix(in srgb, #d97757 60%, transparent); }
[data-theme] .qc-ink .pv-meter-gap {
  background: var(--qc-surface-1);
  border-color: color-mix(in srgb, #d97757 45%, transparent);
}
html[data-theme="dark"] .qc-ink .pv-meter-gap { color: #eda07e; }
html[data-theme="light"] .qc-ink .pv-meter-gap { color: #b04a2e; }

/* 套餐卡价值块：橙 tint 底两主题通用（与既有 bg-qcode-primary/10 同思路），
   只有分隔虚线/hover 等中性色需要翻转 */
[data-theme] .qc-ink .pv-card-l2 { border-top-color: color-mix(in srgb, var(--qc-fg) 12%, transparent); }

/* 划线官方锚点：弱化档文字，两主题都从 --qc-fg 派生（45% 档——纯弱化装饰性锚点，
   语义由相邻实付价与换算徽章承担；实付价与徽章正文 ≥4.5 由本文件其他规则保证） */
[data-theme] .qc-ink .pv-strike { color: color-mix(in srgb, var(--qc-fg) 55%, transparent); }

/* 换算器 */
[data-theme] .qc-ink .pv-quick-chip {
  background: color-mix(in srgb, var(--qc-fg) 5%, transparent);
  border-color: color-mix(in srgb, var(--qc-fg) 15%, transparent);
  color: color-mix(in srgb, var(--qc-fg) 75%, transparent);
}
[data-theme] .qc-ink .pv-quick-chip:hover { border-color: color-mix(in srgb, #d97757 60%, transparent); }
[data-theme] .qc-ink .pv-quick-chip.pv-active { background: #b04a2e; border-color: #b04a2e; color: #fff; }
[data-theme] .qc-ink .pv-calc-row + .pv-calc-row { border-top-color: color-mix(in srgb, var(--qc-fg) 8%, transparent); }
/* 「立省」绿色：与徽章文字同套变量（深色 green-300 / 浅色 green-700） */
[data-theme] .qc-ink .pv-saved { color: var(--qc-badge-green); }

/* 瀑布 */
[data-theme] .qc-ink .pv-wf-arrow { color: color-mix(in srgb, var(--qc-fg) 55%, transparent); }

/* ================= 浅色 Apple 质感精修（jobs-2026-08-09-light-theme-apple-polish） =================
   全部规则挂在 html[data-theme="light"] 下，深色主题零影响（深色像素 diff 回归判据保护）。
   机制：① 可见表面上发闷的 color-mix 中灰 → Apple 实色阶变量；② bg-white/5~30 灰罩 →
   近不可见中性纱或「纯白卡片+阴影」；③ 灰边框 → 发丝线变量；④ 导航毛玻璃。 */

/* ---- ① 文字实色阶（qc-ink；qc-keep 排除语义与上方既有规则一致） ---- */
html[data-theme="light"] .qc-ink .text-white\/80:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .text-white\/70:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-body); }
html[data-theme="light"] .qc-ink .text-white\/60:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .text-white\/50:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-secondary); }
/* /30、/20 只用于装饰性/非关键文字（实测原有值对比度仅 1.9~2.7:1），实色化到 tertiary
   是提升而非降级；若后续发现语义性文字用这两档，应改类而非放松此档 */
html[data-theme="light"] .qc-ink .text-white\/30:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .text-white\/20:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-tertiary); }
html[data-theme="light"] .qc-ink .text-gray-200:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-body); }
html[data-theme="light"] .qc-ink .text-gray-300:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .text-gray-400:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .text-ink-muted:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-secondary); }
html[data-theme="light"] .qc-ink .placeholder-white\/40::placeholder { color: var(--qc-fg-tertiary); }
/* auth-status 片段（老 main.css 规则的浅色接管，同既有架构） */
html[data-theme="light"] .qc-ink .nav-auth-dark > div > a:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .nav-auth-dark > div > span:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .nav-auth-dark > div > button:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .nav-auth-dark > div > div > button:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-body); }
html[data-theme="light"] .qc-ink .nav-auth-dark > div > a:hover:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg); }
/* qc-paper / panel-dark 的同类中灰同步实色化（同一套 Apple 变量，深浅对称不变） */
html[data-theme="light"] .qc-paper .text-gray-700:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-paper .text-gray-600:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-body); }
html[data-theme="light"] .qc-paper .text-gray-500:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-secondary); }
html[data-theme="light"] .panel-dark .text-gray-700,
html[data-theme="light"] .panel-dark .text-gray-600 { color: var(--qc-fg-body); }
html[data-theme="light"] .panel-dark .text-gray-500,
html[data-theme="light"] .panel-dark .text-gray-400 { color: var(--qc-fg-secondary); }
html[data-theme="light"] .panel-dark .hover\:text-gray-600:hover { color: var(--qc-fg-body); }
html[data-theme="light"] .panel-dark input::placeholder,
html[data-theme="light"] .panel-dark textarea::placeholder { color: var(--qc-fg-tertiary); }

/* ---- ②a 灰罩清理：bg-white/5~30 的 color-mix(fg) 映射 → 近不可见中性纱。
   逐类核实后的归属：chips/徽章底/表体斑马/hover 态走这里（≤0.08 视觉近不可见）；
   「卡片」语义的不走这里，见 ②b 纯白卡片规则（选择器更具体且位置在后，稳赢）。
   qc-keep 排除：品牌实底（橙渐变卡头等）上的白纱是设计本身（两主题不变），
   深色主题下 fg=白让旧规则碰巧等价，浅色下不排除会把白纱翻成黑纱（home 趋势图
   卡头 tokens/requests 切换钮实测 1.57→1.14 就是这么抓到的） ---- */
html[data-theme="light"] .qc-ink .bg-white\/5:not(.qc-keep):not(.qc-keep *) { background-color: rgba(0, 0, 0, .03); }
html[data-theme="light"] .qc-ink .bg-white\/10:not(.qc-keep):not(.qc-keep *) { background-color: rgba(0, 0, 0, .04); }
html[data-theme="light"] .qc-ink .bg-white\/15:not(.qc-keep):not(.qc-keep *) { background-color: rgba(0, 0, 0, .05); }
html[data-theme="light"] .qc-ink .bg-white\/20:not(.qc-keep):not(.qc-keep *) { background-color: rgba(0, 0, 0, .06); }
html[data-theme="light"] .qc-ink .bg-white\/30:not(.qc-keep):not(.qc-keep *) { background-color: rgba(0, 0, 0, .08); }

/* ---- ②b 纯白卡片+柔和阴影：浅色分层的核心机制（替代深色靠边框分层）。
   卡的判定 = 承载面类(bg-ink-950/900 或 bg-white/5~10) + 卡片级圆角(rounded-lg~3xl)
   + 全边框(border-white/10~20)；rounded-full 的 chips/pills、无圆角的分隔带、
   表单控件（有专属规则③b）均不命中。backdrop-blur 不排除：hero_user_bar 等
   真毛玻璃元素没有 border-white 类、天然不命中本规则；带 border 的 backdrop-blur
   卡（home 好评卡）要的正是白卡效果。 ---- */
html[data-theme="light"] .qc-ink :is(.bg-ink-950, .bg-ink-900, .bg-white\/5, .bg-white\/10):is(.rounded-lg, .rounded-xl, .rounded-2xl, .rounded-3xl):is(.border-white\/10, .border-white\/15, .border-white\/20):not(input):not(select):not(textarea):not(.qc-keep):not(.qc-keep *) {
  background-color: #ffffff;
  border-color: var(--qc-hairline);
  box-shadow: var(--qc-shadow-rest);
  transition: box-shadow .2s ease;
}
/* 悬浮加深一档（仅本来就是可点的 a/button 卡） */
html[data-theme="light"] .qc-ink a:is(.bg-ink-950, .bg-ink-900, .bg-white\/5, .bg-white\/10):is(.rounded-lg, .rounded-xl, .rounded-2xl, .rounded-3xl):hover,
html[data-theme="light"] .qc-ink button:is(.bg-ink-950, .bg-ink-900, .bg-white\/5, .bg-white\/10):is(.rounded-lg, .rounded-xl, .rounded-2xl, .rounded-3xl):hover {
  box-shadow: var(--qc-shadow-hover);
}

/* ---- ③a 边框发丝线化：中性灰边框收敛到发丝线刻度 ---- */
html[data-theme="light"] .qc-ink .border-white\/10:not(.qc-keep):not(.qc-keep *) { border-color: var(--qc-hairline); }
/* 同元素复合形（footer 本身同时带 .qc-ink 和 .border-white/N，后代选择器覆盖不到——
   与 job3 bug1 的 .qc-ink.text-white 同族缺口；上面 base 面规则已有 .qc-ink.bg-ink-950
   复合先例，边框补齐同形） */
html[data-theme="light"] .qc-ink.border-white\/10,
html[data-theme="light"] .qc-ink.border-white\/15 { border-color: var(--qc-hairline); }
html[data-theme="light"] .qc-ink .border-white\/15:not(.qc-keep):not(.qc-keep *) { border-color: rgba(0, 0, 0, .10); }
html[data-theme="light"] .qc-ink .border-white\/20:not(.qc-keep):not(.qc-keep *) { border-color: rgba(0, 0, 0, .12); }
html[data-theme="light"] .qc-ink .border-white\/30:not(.qc-keep):not(.qc-keep *) { border-color: rgba(0, 0, 0, .14); }
html[data-theme="light"] .qc-ink .border-white\/40:not(.qc-keep):not(.qc-keep *) { border-color: rgba(0, 0, 0, .16); }
html[data-theme="light"] .qc-ink .divide-white\/5 > :not([hidden]) ~ :not([hidden]):not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] .qc-ink .divide-white\/10 > :not([hidden]) ~ :not([hidden]):not(.qc-keep):not(.qc-keep *) { border-color: var(--qc-hairline); }
/* qc-paper / panel-dark 的灰边框同步发丝线化（原 fg 12%/20%/10% mix 略重） */
html[data-theme="light"] .qc-paper .border-gray-200:not(.qc-keep):not(.qc-keep *) { border-color: var(--qc-hairline); }
html[data-theme="light"] .qc-paper .border-gray-300:not(.qc-keep):not(.qc-keep *) { border-color: rgba(0, 0, 0, .12); }
html[data-theme="light"] .panel-dark .border-gray-200,
html[data-theme="light"] .panel-dark .border-gray-100,
html[data-theme="light"] .panel-dark .divide-gray-200 > * + *,
html[data-theme="light"] .panel-dark .divide-gray-100 > * + * { border-color: var(--qc-hairline); }
html[data-theme="light"] .panel-dark .border-gray-300,
html[data-theme="light"] .panel-dark .hover\:border-gray-300:hover { border-color: rgba(0, 0, 0, .12); }

/* ---- ③b 表单控件：白底+略强的发丝线（输入可发现性），不跟卡片阴影 ---- */
html[data-theme="light"] .qc-ink input:is(.bg-white\/5, .bg-white\/10, .bg-white\/15, .bg-white\/20),
html[data-theme="light"] .qc-ink select:is(.bg-white\/5, .bg-white\/10, .bg-white\/15, .bg-white\/20),
html[data-theme="light"] .qc-ink textarea:is(.bg-white\/5, .bg-white\/10, .bg-white\/15, .bg-white\/20) {
  background-color: #ffffff;
  border-color: rgba(0, 0, 0, .12);
}

/* ---- ④ 导航毛玻璃（apple.com 式）：scrolled 态 bg-black/80 在浅色下改白纱+模糊；
   不支持 backdrop-filter 时降级纯白+发丝线（border-b border-white/10 已被③a发丝线化） ---- */
html[data-theme="light"] .qc-ink .bg-black\/80 {
  background-color: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
}
@supports (not (backdrop-filter: blur(1px))) and (not (-webkit-backdrop-filter: blur(1px))) {
  html[data-theme="light"] .qc-ink .bg-black\/80 { background-color: #ffffff; }
}

/* ---- pv 弱化锚点/瀑布箭头实色化：fg 55%/45% mix 随 --qc-fg 变浅（#1D1D1F 比 #0A0A0B 亮）
   跌到 3.8，改次要实色（≈5.46:1）。语义不变：仍是弱化档，只是不再用混色梯度 ---- */
html[data-theme="light"] .qc-ink .pv-strike { color: var(--qc-fg-secondary); }
html[data-theme="light"] .qc-ink .pv-wf-arrow,
html[data-theme="light"] .qc-ink .pv-wf-arrow-note { color: var(--qc-fg-secondary); }

/* ---- qc-paper 纯装饰性分隔符（gray-300）：35% mix 变浅后 2.14，提为 tertiary（3.54，
   仍只准装饰用途，与上方「纯装饰性分隔符不担对比度」注释语义一致） ---- */
html[data-theme="light"] .qc-paper .text-gray-300:not(.qc-keep):not(.qc-keep *) { color: var(--qc-fg-tertiary); }

/* ---- 蒙层订正（Phase 2 实测）：bg-ink-950/60 全站只有 2 处用例，都是 hero 图上的
   整体罩层（models.html:43、partner_program.html:139），不是弹窗蒙层——真正的弹窗蒙层
   用的是 bg-black/50 等 tailwind 原值（不随主题变，两主题恒暗）。浅色下 hero 罩层维持
   surface-0 60% 白纱（Phase 1 曾误改为黑纱导致 hero 变暗，Phase 2 铺开时实测纠正回来）。
   弹窗面板分层走下面的 modal 阴影档。 ---- */

/* ---- 模态面板阴影档落地（Phase 2）：fixed 浮层 scrim 内的卡片面板升到 modal 档。
   选择器与 ②b 卡片规则同族同权重、位置在后 → 浮层面板覆盖 rest 档拿到 modal 档。
   蒙层本身（bg-black/50 等 tailwind 原值）两主题恒暗，不随主题变，本 job 不动 ---- */
html[data-theme="light"] .qc-ink .fixed.inset-0 :is(.bg-ink-950, .bg-ink-900, .bg-white\/5, .bg-white\/10):is(.rounded-lg, .rounded-xl, .rounded-2xl, .rounded-3xl):is(.border-white\/10, .border-white\/15, .border-white\/20):not(input):not(select):not(textarea):not(.qc-keep):not(.qc-keep *) {
  box-shadow: var(--qc-shadow-modal);
}

/* ---- pv-* 价值组件浅色谐调（Phase 2 铺开）：fg 派生混色 → 发丝线/实色阶 ---- */
html[data-theme="light"] .qc-ink .pv-quick-chip {
  background: rgba(0, 0, 0, .03);
  border-color: var(--qc-hairline);
  color: var(--qc-fg-body);
}
html[data-theme="light"] .qc-ink .pv-card-l2 { border-top-color: var(--qc-hairline); }
html[data-theme="light"] .qc-ink .pv-calc-row + .pv-calc-row { border-top-color: var(--qc-hairline); }
html[data-theme="light"] .qc-ink .pv-meter-track { background: rgba(0, 0, 0, .06); }
html[data-theme="light"] .qc-ink .pv-meter-leader { background: rgba(0, 0, 0, .15); }
html[data-theme="light"] .qc-ink .pv-meter-dot--official { background: var(--qc-fg-tertiary); }

/* ================= 品牌橙归一规则（brand-color-system Phase 2，V3 拍板） =================
   裸 bg-qcode-primary（未标 qc-keep 的 34+ 处）全部归入 fill 档；qc-keep 已标用例由
   main.css 恒定规则落在同值 #a35941，殊途同归。panel-dark 入作用域：usage_stats 等
   HTMX 注入内容里的品牌钮同规（注入内容不在静态样张渲染内，本规则对样张零像素影响，
   选择器级覆盖）。白字保白：浅色下 text-white 翻转规则
   会把钮上白字翻深，这里压回去（深色下本来就白，规则两主题同写零差异）。
   两主题都动（本 job 无深色冻结），变化点=本色→fill 一档加深。 */

/* 填充归一（含同元素复合形与后代形） */
[data-theme] :where(.qc-ink, .qc-paper, .panel-dark) .bg-qcode-primary:not(.qc-keep):not(.qc-keep *),
[data-theme] :where(.qc-ink, .qc-paper, .panel-dark).bg-qcode-primary:not(.qc-keep) { background-color: var(--qc-brand-fill); }
/* 白字保白（只浅色需要；深色 fg=白规则恒等） */
html[data-theme="light"] :where(.qc-ink, .qc-paper, .panel-dark) .bg-qcode-primary.text-white:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] :where(.qc-ink, .qc-paper, .panel-dark) .bg-qcode-primary:not(.qc-keep):not(.qc-keep *) .text-white { color: #ffffff; }
/* fill hover 对（R-p3：交互态同过门槛且悬停更深） */
[data-theme] :where(.qc-ink, .qc-paper, .panel-dark) .hover\:bg-qcode-primary-hover:hover:not(.qc-keep):not(.qc-keep *) { background-color: var(--qc-brand-fill-hover); }

/* 文字档：浅色 #B04A2E / 深色本色（深色与 tailwind 原值逐位相同） */
[data-theme] :where(.qc-ink, .qc-paper, .panel-dark) .text-qcode-primary:not(.qc-keep):not(.qc-keep *) { color: var(--qc-brand-text); }
[data-theme] :where(.qc-ink, .qc-paper, .panel-dark) .text-qcode-primary\/90:not(.qc-keep):not(.qc-keep *) { color: var(--qc-brand-text); }
[data-theme] :where(.qc-ink, .qc-paper, .panel-dark) .hover\:text-qcode-primary:hover:not(.qc-keep):not(.qc-keep *) { color: var(--qc-brand-text-hover); }
/* 大字豁免回本色（V3 尺寸分档：≥18.66px bold/≥24px 用 --qc-brand） */
html[data-theme="light"] :where(.qc-ink, .qc-paper, .panel-dark) .text-qcode-primary:is(.text-2xl, .text-3xl, .text-4xl, .text-5xl, .text-8xl):not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] :where(.qc-ink, .qc-paper, .panel-dark) :is(h1, h2) .text-qcode-primary:not(.qc-keep):not(.qc-keep *),
html[data-theme="light"] :where(.qc-ink, .qc-paper, .panel-dark) .probe-rate { color: var(--qc-brand); }

} /* @supports (color: color-mix(...)) 结束 */

/* ── P7：浅色主题下 JS 弹窗的配色修正（2026-08-16）────────────────────
   触发面：dashboard 系页面（body 恒带 .bg-ink-950 页面家族标记）+ data-theme="light"。
   main.css 的弹窗深色覆盖组已收窄为深色主题专用（:where(html[data-theme="dark"] .bg-ink-950)），
   浅色下弹窗显示其注入样式 / 工具类的原生浅色配色。本块只修浅色下不达标的项；
   深色主题全部由 main.css 覆盖组原样接管（check-modal-theme.js --compare 逐值锁定，零回归）。
   ① theme.css 的 .qc-ink .text-white → var(--qc-fg) 翻转，会把彩色 chip/按钮上的白字
      翻成深色（浅色 --qc-fg=#1A1613）撞出「彩底深字」—— 仅对「白色足够可读」的彩色底
      把 text-white 钉回白色；橙/绿中调底上白字反而不足 4.5，那些保留翻转后的深字。
   ② renew 弹窗注入样式的原生浅色值 ×/绿字余额/蓝底确认键 不达标，各降一档色阶。
   ③ 弹窗里 text-green-500 / text-orange-600 在浅底上不足 4.5，降为 -700 色阶。 */
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .bg-gray-800 .text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .bg-blue-600 .text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .bg-purple-600.text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .bg-purple-600 .text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .bg-slate-600.text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .bg-slate-600 .text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black [style*="linear-gradient(135deg, #4f46e5"].text-white,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black [style*="linear-gradient(135deg, #2563eb"].text-white {
  color: #fff;
}
/* upgradeTip 步骤圈 3 的绿色渐变上白/深字均不足 4.5，浅色下把渐变降到 emerald-700 档并钉白字 */
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black [style*="linear-gradient(135deg, #059669"] {
  background: linear-gradient(135deg, #047857, #059669) !important;
}
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black [style*="linear-gradient(135deg, #059669"],
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black [style*="linear-gradient(135deg, #047857"] {
  color: #fff;
}
/* ② renew 注入样式原生浅色修正 */
html[data-theme="light"] .bg-ink-950 #renew-modal-js .rm-close { color: var(--qc-fg-muted); }
html[data-theme="light"] .bg-ink-950 #renew-modal-js .rm-row .value.green { color: #15803d; }
html[data-theme="light"] .bg-ink-950 #renew-modal-js .rm-btn-confirm { background: #2563eb; }
/* ③ 浅底上的语义色文字降档 */
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .text-green-500 { color: #15803d; }
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .text-orange-600 { color: #c2410c; }

/* ── P7-b：验收补漏（2026-08-16，Claude 在 prod 公网实测 132 个真实 class 组合后补）
   来源：从线上 dashboard.js 抓全部带色 class，在真实弹窗语境（.bg-ink-950 > 遮罩 > 白底盒）
   下逐个量 computed color 与「逐级向上第一个非透明底」的对比。判据分档：
   正文/小字 4.5、≥24px bold 大字 3.0、svg 图形对象 3.0（WCAG 1.4.3 / 1.4.11）。
   Kimi 的 ③ 块降了 text-green-500 / text-orange-600，下面 4 类是同族漏网：
   ① text-green-600 —— booster-success-message(text-sm on bg-green-50)=3.1、
      返利状态 span(on 白)=3.3   ② text-red-600 —— booster-error-message(text-sm)
      与 booster-balance-warning(text-xs) on bg-red-50 均=4.4（差 0.1）
   ③ text-green-400 svg(on 白)=1.7  ④ text-blue-400 svg(on 白)=2.5（图标档 3.0 也不过）
   降档后：#15803d on 白=5.0 / on green-50=4.8；#b91c1c on 白=6.5 / on red-50=6.0；
   #2563eb on 白=5.1。作用域与 ③ 块逐字一致，深色主题不受影响（选择器带 light）。 */
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .text-green-600,
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .text-green-400 { color: #15803d; }
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .text-red-600   { color: #b91c1c; }
html[data-theme="light"] .bg-ink-950 .fixed.inset-0.bg-black .text-blue-400  { color: #2563eb; }
