/* 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: #ffffff;              /* 深色主题前景色（等价于现有 text-white） */
  --qc-surface-0: #0A0A0B;       /* == ink-950，今天的样子 */
  --qc-surface-1: #141416;       /* == ink-900 */
  --qc-surface-2: #1D1D1F;       /* == ink-800 */
  --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 */
}

html[data-theme="light"] {
  color-scheme: light;
  --qc-fg: #0A0A0B;              /* 与 ink-950 同色，浅色主题下的强对比文字 */
  --qc-surface-0: #ffffff;
  --qc-surface-1: #F6F6F7;
  --qc-surface-2: #ECECEE;
  --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 *) { 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: color-mix(in srgb, var(--qc-fg) 40%, transparent); }
html[data-theme="light"] .qc-ink .text-white\/40:not(.qc-keep):not(.qc-keep *) { color: color-mix(in srgb, var(--qc-fg) 60%, transparent); }
[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); }

/* 半透明玻璃拟态卡片/按钮背景 + 边框 + 分隔线 + 输入框占位符，同一套不透明度梯度 */
[data-theme] .qc-ink .bg-white\/5 { background-color: color-mix(in srgb, var(--qc-fg) 5%, transparent); }
[data-theme] .qc-ink .bg-white\/10 { background-color: color-mix(in srgb, var(--qc-fg) 10%, transparent); }
[data-theme] .qc-ink .bg-white\/20 { background-color: color-mix(in srgb, var(--qc-fg) 20%, transparent); }
[data-theme] .qc-ink .bg-white\/30 { background-color: color-mix(in srgb, var(--qc-fg) 30%, transparent); }
[data-theme] .qc-ink .bg-white\/15 { background-color: color-mix(in srgb, var(--qc-fg) 15%, transparent); }

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

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