refactor(theme): 营销页 bg-white token 化(暗黑模式 Phase 2 · marketing 批次)

问题:Tailwind 原生 bg-white 是硬编码值,深色主题下不翻转,
导致整页/整 section 恒为纯白,与转深色的页头页脚割裂。
(globals.css:--color-bg-primary-rgb 浅色 255 255 255 → 深色 10 14 20)

改动:10 文件 67 处 bg-white → 项目 token,按语义二分类
- bg-bg-primary  (33 处):页面/大块骨架(min-h-screen 容器、<section>、<main>)
- bg-bg-elevated (34 处):浮起层(带 border 的卡片、表单输入、图标盒、grid 单元格)
  --color-bg-elevated 浅色 #FFFFFF → 深色 #151B23,同样翻转。

浅色主题下 bg-white / bg-bg-primary / bg-bg-elevated 三者同值(纯白),
故本次改动在浅色主题下零像素差异,只修复深色主题。

新增审计工具:
- scripts/audit/hardcoded-color-audit.mjs:硬编码颜色分级盘点
  (含 alpha 误报修正:bg-white/NN 半透明叠加两主题均成立,判 INFO 非 P0)
- scripts/audit/darkmode-bg-verify.mjs:直接验证背景随主题翻转
  (浅色应纯白、深色应 rgb(10,14,20) 且无残留纯白块)

审计结果:marketing P0 67 → 0;全站 P0 97 → 30
(剩余 components 16 / other 8 / layout 3 / ui-kit 3 为第二批;admin 本就为 0)

门禁:
- tsc 0 error
- eslint 0 error(50 warnings 全为既有,改动文件未新增)
- jest 129/130 套件通过,1548 通过 / 2 跳过 / **0 断言失败**
  唯一失败 src/lib/admin-api.test.ts 为**沙箱环境限制非代码问题**:
  CODEBUDDY_BROKER_DENY 拦截 readFileSync,单独复验同样失败,
  与本次改动零交集(改动仅限 src/app/(marketing)/ 下 10 个页面组件)
- 暗黑模式背景验证 18/18 PASS(9 路由 × 浅深双版)
This commit is contained in:
2026-09-04 13:46:29 +08:00
parent 8f4a860180
commit 846585af1f
13 changed files with 339 additions and 67 deletions
@@ -40,7 +40,7 @@ function DetailHero({ solution }: DetailHeroProps) {
const industryIcon = INDUSTRY_ICONS[solution.industry] || <Factory className="w-8 h-8" />;
return (
<section className="relative min-h-[80vh] flex items-center overflow-hidden bg-white pt-24">
<section className="relative min-h-[80vh] flex items-center overflow-hidden bg-bg-primary pt-24">
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10 w-full py-20 sm:py-24 md:py-28 lg:py-32">
<motion.div
initial={{ opacity: 0, y: 30 }}
@@ -122,7 +122,7 @@ function ChallengesSection({ challenges }: ChallengesSectionProps) {
{challenges.map((challenge, idx) => (
<div
key={idx}
className="group relative p-8 bg-white hover:bg-bg-secondary transition-all duration-150"
className="group relative p-8 bg-bg-elevated hover:bg-bg-secondary transition-all duration-150"
>
<div className="absolute left-0 top-0 bottom-0 w-1 bg-brand scale-y-0 group-hover:scale-y-100 transition-transform duration-150 origin-top" />
<div className="flex items-start gap-6">
@@ -147,7 +147,7 @@ interface SolutionsSectionProps {
function SolutionsSection({ solutions }: SolutionsSectionProps) {
return (
<section className="relative py-20 sm:py-28 md:py-32 lg:py-40 overflow-hidden bg-white">
<section className="relative py-20 sm:py-28 md:py-32 lg:py-40 overflow-hidden bg-bg-primary">
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10">
<ScrollReveal className="text-center max-w-3xl mx-auto mb-16 sm:mb-20 md:mb-20">
<SectionLabel className="justify-center">
@@ -169,7 +169,7 @@ function SolutionsSection({ solutions }: SolutionsSectionProps) {
{solutions.map((solution, idx) => (
<div
key={idx}
className="group relative p-10 bg-white hover:bg-bg-secondary transition-all duration-150"
className="group relative p-10 bg-bg-elevated hover:bg-bg-secondary transition-all duration-150"
>
<div className="absolute top-0 left-0 right-0 h-1 bg-brand scale-x-0 group-hover:scale-x-100 transition-transform duration-150 origin-left" />
@@ -226,7 +226,7 @@ function ValuePropositionSection({ valueProposition }: ValuePropositionProps) {
return (
<div
key={idx}
className="group relative p-10 text-center bg-white hover:bg-bg-secondary transition-all duration-150"
className="group relative p-10 text-center bg-bg-elevated hover:bg-bg-secondary transition-all duration-150"
>
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-1/3 h-1 bg-brand scale-x-0 group-hover:scale-x-100 transition-transform duration-150 origin-center" />
@@ -257,7 +257,7 @@ function SuiteCombinationSection({ suiteCombination, products }: SuiteCombinatio
.filter(Boolean);
return (
<section className="relative py-20 sm:py-28 md:py-32 lg:py-40 overflow-hidden bg-white">
<section className="relative py-20 sm:py-28 md:py-32 lg:py-40 overflow-hidden bg-bg-primary">
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10">
<ScrollReveal className="text-center max-w-3xl mx-auto mb-16 sm:mb-20 md:mb-20">
<SectionLabel className="justify-center">
@@ -279,7 +279,7 @@ function SuiteCombinationSection({ suiteCombination, products }: SuiteCombinatio
{primaryProducts.map((product) => product && (
<div
key={product.id}
className="group relative p-8 bg-white hover:bg-bg-secondary transition-all duration-150 text-center lg:col-span-2"
className="group relative p-8 bg-bg-elevated hover:bg-bg-secondary transition-all duration-150 text-center lg:col-span-2"
>
<div className="absolute top-0 left-0 right-0 h-1 bg-brand scale-x-0 group-hover:scale-x-100 transition-transform duration-150 origin-left" />
@@ -296,7 +296,7 @@ function SuiteCombinationSection({ suiteCombination, products }: SuiteCombinatio
))}
</StaggerReveal>
<ScrollReveal delay={0.2} className="flex items-center justify-center lg:col-span-1 bg-white">
<ScrollReveal delay={0.2} className="flex items-center justify-center lg:col-span-1 bg-bg-elevated">
<div className="w-20 h-20 rounded-full bg-brand-soft/30 border-2 border-brand/30 flex items-center justify-center text-brand font-bold text-xl">
+
</div>