为 html[data-theme='dark'] 添加完整 CSS 变量覆盖块,建立暗黑模式基石。
--color-ink 收窄为'文字/描边跟随主题'语义,深色 UI 元素(卡片/按钮/遮罩/
代码块/页脚)迁到 --color-dark-bg / --color-overlay 独立 token,避免 ink
反色为浅色文字时连带把深色区块变浅(双语义冲突)。
【基础设施】
- globals.css:
* html/body 顶部硬编码 #FFFFFF !important 改 var() 化(保留 !important)
* :root 新增 --color-overlay / --color-overlay-rgb(遮罩/深色叠加层,
永不反色)
* 新增 html[data-theme='dark'] 覆盖块:墨色反色为浅色文字,bg/text/
border 层级反色,link 反色;保留 --color-dark-* / --color-brand-section
* pre 背景 var(--color-ink) → var(--color-dark-bg)
- tailwind.config.js:注册 overlay 色(rgb() 形式,支持 /50 /60 修饰符)
- layout.tsx:head 内联防 FOUC 同步脚本,读 localStorage['novalon-theme']
设置 data-theme(当前无切换 UI,仅作未来挂载点)
【首页试点 + 布局组件】(浅色值完全等价 → 浅色零视觉差异)
- home-content-v15.tsx:7 处 bg-white → bg-bg-primary(narrative/insights/
cases sections 与卡片),2 处 bg-ink → bg-dark-bg(案例卡 bg-dark-bg 不
随反色,保留深色画布)
- header.tsx / mega-dropdown.tsx:bg-white → bg-bg-primary(导航栏/移动
端菜单/下拉面板)
- footer.tsx:bg-[#0A0E14] → bg-dark-bg(语义统一,视觉零差异)
【全局 UI 组件】(深色区块语义统一 + 遮罩固定深色)
- button.tsx:secondary 'bg-ink hover:bg-ink-light' → bg-dark-bg / hover:bg-dark-bg-secondary;
outline 'hover:bg-ink hover:border-ink' → hover:bg-dark-bg / border-dark-bg
- stats-showcase / milestone-timeline:isDark 分支 bg-ink → bg-dark-bg
- metric-card:isDark 分支 bg-ink/50 → bg-overlay/50,hover:bg-ink → hover:bg-overlay
- dialog / alert-dialog:遮罩 bg-ink/60 → bg-overlay/60(永不反色)
- button.test.tsx:断言 bg-ink → bg-dark-bg,注释同步
【验证】
- type-check 0 errors
- lint 0 errors(127 warnings 既有,非本次引入)
- jest 128 suites / 1623 passed(button 断言同步通过)
- 视觉回归先非 update:21 passed(浅色安全门零 diff)+ 1 failed
(仅 theme-dark-main,dark 快照从浅色名义变真正深色 = 语义修复预期)
- update-snapshots:22 passed,仅 theme-dark-main 基线重写
- computed-style 权威验证(一次性脚本,已删除):
dark 7 项断言全过(html/body/hero/导航栏/案例卡→深色 #0A0E14;
body 文字→浅色 #F8FAFC;footer/overlay→保持深色);light 4 项零回归
【未在 Phase 1 范围】(已识别,留待 Phase 2/3 决策)
- service-detail-content-v4.tsx 等营销页 bg-white:Phase 2 批量 token 化
- admin 页面 bg-white + RichTextEditor:admin 边界决策 + Phase 3
- 品牌红 #C41E3A 在深色底对比度复检:Phase 3
1436 lines
38 KiB
CSS
1436 lines
38 KiB
CSS
@tailwind base;
|
||
@tailwind components;
|
||
@tailwind utilities;
|
||
|
||
html {
|
||
background-color: var(--color-bg-primary) !important;
|
||
}
|
||
|
||
body {
|
||
background-color: var(--color-bg-primary) !important;
|
||
color: var(--color-text-primary) !important;
|
||
}
|
||
|
||
:root {
|
||
/* === 咨询专业 · 色彩体系(浅色模式) === */
|
||
/* 墨色核心 */
|
||
--color-ink: #0A0E14;
|
||
--color-ink-light: #0F1419;
|
||
--color-ink-lighter: #151B23;
|
||
--color-ink-rgb: 10 14 20;
|
||
|
||
/* 品牌信号色:朱砂红 — Committed 色彩策略(Bain 式自信表达) */
|
||
--color-brand: #C41E3A;
|
||
--color-brand-hover: #A01830;
|
||
--color-brand-light: #E04A68;
|
||
--color-brand-soft: rgba(196, 30, 58, 0.12);
|
||
--color-brand-bg: #FEF2F4;
|
||
--color-brand-rgb: 196 30 58;
|
||
/* 品牌色深色区块(Bain 式深红背景) */
|
||
--color-brand-section: #8B1530;
|
||
--color-brand-section-text: #F8FAFC;
|
||
--color-brand-section-muted: rgba(248, 250, 252, 0.7);
|
||
|
||
/* 辅助色:服务/行业编码 */
|
||
--color-accent-blue: #3B82F6;
|
||
--color-accent-blue-soft: rgba(59, 130, 246, 0.12);
|
||
--color-accent-blue-rgb: 59 130 246;
|
||
|
||
--color-accent-teal: #14B8A6;
|
||
--color-accent-teal-soft: rgba(20, 184, 166, 0.12);
|
||
--color-accent-teal-rgb: 20 184 166;
|
||
|
||
--color-accent-amber: #F59E0B;
|
||
--color-accent-amber-soft: rgba(245, 158, 11, 0.12);
|
||
--color-accent-amber-rgb: 245 158 11;
|
||
|
||
--color-accent-purple: #8B5CF6;
|
||
--color-accent-purple-soft: rgba(139, 92, 246, 0.12);
|
||
--color-accent-purple-rgb: 139 92 246;
|
||
--color-accent-cyan: #06B6D4;
|
||
--color-accent-cyan-soft: rgba(6, 182, 212, 0.12);
|
||
--color-accent-cyan-rgb: 6 182 212;
|
||
|
||
/* 背景色层级 */
|
||
--color-bg-primary: #FFFFFF;
|
||
--color-bg-secondary: #F8FAFC;
|
||
--color-bg-secondary-rgb: 248 250 252;
|
||
--color-bg-tertiary: #F1F5F9;
|
||
--color-bg-section: #F8FAFC;
|
||
--color-bg-hover: #F1F5F9;
|
||
--color-bg-elevated: #FFFFFF;
|
||
--color-bg-primary-rgb: 255 255 255;
|
||
|
||
/* 文字色层级 */
|
||
--color-text-primary: #0A0E14;
|
||
--color-text-secondary: #334155;
|
||
--color-text-secondary-rgb: 51 65 85;
|
||
--color-text-tertiary: #475569;
|
||
--color-text-muted: #64748B;
|
||
--color-text-muted-rgb: 100 116 139;
|
||
--color-text-subtle: #64748B;
|
||
--color-text-placeholder: #64748B;
|
||
/* 仅用于 ≥24px 大号装饰性文本(如章节序号),对白底 3.41:1,满足 AA 大字 3:1。
|
||
正文、占位符、提示文案请改用 --color-text-placeholder(4.76:1)或更深的令牌。 */
|
||
--color-text-hint: #7C8CA5;
|
||
--color-text-inverse: #FFFFFF;
|
||
|
||
/* 边框色层级 —— 中度软化:--color-border-primary 从 #E2E8F0 调整为 #EEF2F7(更淡),
|
||
让 20 处 gap-px bg-border-primary 网格线与所有卡片边框都自动弱化(约 50%),
|
||
与增强的卡片阴影呼应,视觉从"靠硬边分界"转为"靠阴影分层"。 */
|
||
--color-border-primary: #EEF2F7;
|
||
--color-border-primary-rgb: 238 242 247;
|
||
--color-border-secondary: #CBD5E1;
|
||
--color-border-secondary-rgb: 203 213 225;
|
||
--color-border-accent: #0A0E14;
|
||
--color-border-accent-rgb: 10 14 20;
|
||
--color-border-light: #F1F5F9;
|
||
--color-border-light-rgb: 241 245 249;
|
||
--color-border-dark: #334155;
|
||
--color-border-dark-rgb: 51 65 85;
|
||
--color-border-brand: #C41E3A;
|
||
--color-border-brand-rgb: 196 30 58;
|
||
|
||
/* 链接色 */
|
||
--color-link: #0A0E14;
|
||
--color-link-hover: #C41E3A;
|
||
|
||
/* 功能色 */
|
||
--color-success: #16A34A;
|
||
--color-success-hover: #15803D;
|
||
--color-success-bg: #F0FDF4;
|
||
--color-success-rgb: 22 163 74;
|
||
/* 文字专用:--color-success 仅 3.30:1,作正文色不达 AA;本值 5.02:1(于 success-bg 上 4.79:1) */
|
||
--color-success-text: #15803D;
|
||
|
||
--color-warning: #D97706;
|
||
--color-warning-hover: #B45309;
|
||
--color-warning-bg: #FFFBEB;
|
||
--color-warning-rgb: 217 119 6;
|
||
/* 文字专用:--color-warning 仅 3.19:1,作正文色不达 AA;本值 5.02:1(于 warning-bg 上 4.84:1) */
|
||
--color-warning-text: #B45309;
|
||
|
||
--color-error: #C41E3A;
|
||
--color-error-hover: #A01830;
|
||
--color-error-bg: #FEF2F4;
|
||
--color-error-rgb: 196 30 58;
|
||
|
||
--color-info: #3B82F6;
|
||
--color-info-rgb: 59 130 246;
|
||
--color-info-bg: #EFF6FF;
|
||
/* 文字专用:--color-info 仅 3.68:1,作正文色不达 AA;本值 6.70:1(于 info-bg 上 6.16:1) */
|
||
--color-info-text: #1D4ED8;
|
||
|
||
/* 深色调性区域 */
|
||
--color-dark-bg: #0A0E14;
|
||
--color-dark-bg-secondary: #0F1419;
|
||
--color-dark-bg-tertiary: #151B23;
|
||
--color-dark-text-primary: #F8FAFC;
|
||
--color-dark-text-secondary: #CBD5E1;
|
||
--color-dark-text-muted: #94A3B8;
|
||
--color-dark-border: #1E293B;
|
||
|
||
/* 遮罩 / 深色叠加层(dialog 背板、metric-card 深色半透明底):
|
||
语义上"永远是深色覆盖",不随暗黑模式反色 —— 故用独立 token。 */
|
||
--color-overlay: #0A0E14;
|
||
--color-overlay-rgb: 10 14 20;
|
||
|
||
/* 阴影系统(按层级 + 用途分类) */
|
||
/* 基础层级:几乎看不见,用于微妙的边界定义 */
|
||
--shadow-xs: 0 1px 1px rgba(10, 14, 20, 0.03);
|
||
/* 轻量:卡片默认状态、输入框 */
|
||
--shadow-sm: 0 1px 3px rgba(10, 14, 20, 0.04), 0 1px 2px rgba(10, 14, 20, 0.02);
|
||
/* 中等:悬浮状态、下拉菜单 */
|
||
--shadow-md: 0 4px 12px rgba(10, 14, 20, 0.06), 0 2px 4px rgba(10, 14, 20, 0.03);
|
||
/* 大型:模态框、悬浮卡片 */
|
||
--shadow-lg: 0 12px 28px rgba(10, 14, 20, 0.08), 0 4px 8px rgba(10, 14, 20, 0.04);
|
||
/* 超大:全屏弹窗、重要浮层 */
|
||
--shadow-xl: 0 24px 56px rgba(10, 14, 20, 0.1), 0 8px 16px rgba(10, 14, 20, 0.06);
|
||
/* 品牌阴影:CTA 按钮、品牌强调元素 */
|
||
--shadow-brand: 0 6px 24px rgba(196, 30, 58, 0.22);
|
||
--shadow-brand-hover: 0 8px 32px rgba(196, 30, 58, 0.32);
|
||
/* 内阴影:凹陷效果、输入框聚焦 */
|
||
--shadow-inset: inset 0 2px 4px rgba(10, 14, 20, 0.04);
|
||
/* 光晕阴影:发光效果(慎用) */
|
||
--shadow-glow: 0 0 40px rgba(196, 30, 58, 0.15);
|
||
|
||
/* 字体系统
|
||
字族按「逐字符」回退:拉丁字母命中 Geist(无 CJK 字形),
|
||
中文自动落到后面的 PingFang SC / 微软雅黑。
|
||
var() 必须给回退值,否则 next/font 变量缺失时整条声明会失效。 */
|
||
--font-sans: var(--font-geist-sans, ui-sans-serif), "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
--font-display: var(--font-geist-sans, ui-sans-serif), "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
--font-mono: var(--font-geist-mono, ui-monospace), SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
||
--font-brand: "STKaiti", "KaiTi", "楷体", "SimKai", serif;
|
||
--font-calligraphy-system: "STKaiti", "KaiTi", "楷体", "SimKai", serif;
|
||
--font-serif: "Songti SC", "STSongti-SC", "Noto Serif CJK SC", "SimSun", "STSong", serif;
|
||
|
||
/* 字号系统(12级排版尺度)—— Mobile First,默认移动端 */
|
||
--font-size-caption: 0.6875rem;
|
||
--font-size-xs: 0.75rem;
|
||
--font-size-sm: 0.875rem;
|
||
--font-size-base: 1rem;
|
||
--font-size-lg: 1.0625rem;
|
||
--font-size-xl: 1.1875rem;
|
||
--font-size-2xl: 1.25rem;
|
||
--font-size-3xl: 1.5rem;
|
||
--font-size-4xl: 1.875rem;
|
||
--font-size-5xl: 2.25rem;
|
||
--font-size-6xl: 3rem;
|
||
--font-size-7xl: 3.5rem;
|
||
--font-size-display: 4.5rem;
|
||
|
||
/* 行高系统(与字号对应) */
|
||
--line-height-caption: 1.4;
|
||
--line-height-tight: 1.15;
|
||
--line-height-snug: 1.35;
|
||
--line-height-normal: 1.65;
|
||
--line-height-relaxed: 1.85;
|
||
|
||
/* 字间距系统(按使用场景分层) */
|
||
--letter-spacing-tighter: -0.03em; /* 展示标题,不低于 -0.04em 地板 */
|
||
--letter-spacing-tight: -0.02em;
|
||
--letter-spacing-normal: 0;
|
||
--letter-spacing-wide: 0.03em;
|
||
--letter-spacing-wider: 0.06em;
|
||
--letter-spacing-widest: 0.12em;
|
||
--letter-spacing-eyebrow: 0.12em; /* 减小,避免过宽追踪 */
|
||
|
||
/* 段落间距 */
|
||
--paragraph-spacing: 1.25em;
|
||
--paragraph-spacing-loose: 1.75em;
|
||
|
||
/* 间距系统 */
|
||
--spacing-xs: 0.25rem;
|
||
--spacing-sm: 0.5rem;
|
||
--spacing-md: 1rem;
|
||
--spacing-lg: 1.5rem;
|
||
--spacing-xl: 2rem;
|
||
--spacing-2xl: 3rem;
|
||
--spacing-3xl: 4rem;
|
||
--spacing-4xl: 6rem;
|
||
--spacing-5xl: 8rem;
|
||
--spacing-6xl: 12rem;
|
||
|
||
/* 圆角系统(按用途分类)—— 中度软化:4→6/6→8/10→12/14→18,
|
||
让"硬边"卡片语言变为"柔边",与增强的卡片阴影呼应。
|
||
注意:SM/MD/LG 同步联动大量 Tailwind 圆角类,全局生效。 */
|
||
--radius-xs: 3px; /* 极小:标签、徽章 */
|
||
--radius-sm: 6px; /* 小:按钮、输入框 */
|
||
--radius-md: 8px; /* 中:卡片、弹窗 */
|
||
--radius-lg: 12px; /* 大:大型卡片、容器 */
|
||
--radius-xl: 18px; /* 特大:英雄卡片、特色模块 */
|
||
--radius-2xl: 24px; /* 超大:全屏弹窗、大型容器 */
|
||
--radius-3xl: 32px; /* 巨大:展示卡片 */
|
||
--radius-full: 9999px; /* 圆形:头像、圆形按钮 */
|
||
|
||
/* 过渡系统(按时长分级) */
|
||
--transition-instant: 100ms;
|
||
--transition-fast: 180ms;
|
||
--transition-normal: 280ms;
|
||
--transition-slow: 450ms;
|
||
--transition-slower: 700ms;
|
||
--transition-gentle: 1000ms;
|
||
|
||
/* 缓动曲线(按性格分类) */
|
||
/* 标准:通用入场、状态变化(最常用) */
|
||
--ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
|
||
/* 减速:元素入场(快速开始,轻柔结束) */
|
||
--ease-decelerate: cubic-bezier(0, 0, 0.2, 1);
|
||
/* 加速:元素退场(轻柔开始,快速结束) */
|
||
--ease-accelerate: cubic-bezier(0.4, 0, 1, 1);
|
||
/* 弹性:有生命感的交互(按钮按压、卡片回弹) */
|
||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
--ease-spring-soft: cubic-bezier(0.34, 1.2, 0.64, 1);
|
||
/* 锐利:精确、专业的感觉(数据变化、指标跳动) */
|
||
--ease-sharp: cubic-bezier(0.65, 0, 0.35, 1);
|
||
/* 水墨:柔和、有呼吸感(背景过渡、光晕变化) */
|
||
--ease-ink: cubic-bezier(0.22, 1, 0.36, 1);
|
||
/* ease-out 别名:默认使用水墨曲线(Porsche 风格:快速开始,缓慢结束) */
|
||
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
||
|
||
/* 动效延迟序列(错落动效用) */
|
||
--stagger-xs: 30ms;
|
||
--stagger-sm: 60ms;
|
||
--stagger-md: 100ms;
|
||
--stagger-lg: 150ms;
|
||
--stagger-xl: 200ms;
|
||
|
||
/* 容器宽度 */
|
||
--container-max: 1360px;
|
||
--container-padding: 1rem;
|
||
|
||
/* === 组件令牌层(Component Tokens)=== */
|
||
/* 按钮 */
|
||
--btn-height-sm: 2.25rem;
|
||
--btn-height-md: 2.75rem;
|
||
--btn-height-lg: 3.25rem;
|
||
--btn-padding-x: 1.5rem;
|
||
--btn-font-size: 0.875rem;
|
||
|
||
/* 卡片 —— 中度软化:阴影加深(透明度 0.06→0.08),新增 y 偏移的 hover 抬升过渡。
|
||
让卡片从"靠 1px 硬边分界"变为"靠柔和阴影分层",与增大圆角呼应。 */
|
||
--card-padding: 1.5rem;
|
||
--card-padding-lg: 2.5rem;
|
||
--card-gap: 1.5rem;
|
||
--card-border-radius: var(--radius-lg);
|
||
--card-shadow: 0 1px 2px rgba(10, 14, 20, 0.04), 0 2px 8px rgba(10, 14, 20, 0.08);
|
||
--card-shadow-hover: 0 4px 12px rgba(10, 14, 20, 0.06), 0 12px 32px rgba(10, 14, 20, 0.12);
|
||
--card-border: 1px solid var(--color-border-light);
|
||
--card-transition: transform var(--transition-normal) var(--ease-out),
|
||
box-shadow var(--transition-normal) var(--ease-out),
|
||
border-color var(--transition-normal) var(--ease-out);
|
||
|
||
/* 输入框 */
|
||
--input-height: 2.75rem;
|
||
--input-padding-x: 1rem;
|
||
--input-border-radius: var(--radius-sm);
|
||
|
||
/* Section 间距 —— Mobile First,默认移动端 —— 中度软化:节奏更舒展 */
|
||
--section-gap: var(--spacing-4xl);
|
||
--section-gap-sm: var(--spacing-3xl);
|
||
--section-padding-y: var(--spacing-4xl);
|
||
|
||
/* === 组件令牌层(Component Tokens)=== */
|
||
|
||
/* Badge 标签 */
|
||
--badge-height-sm: 1.25rem;
|
||
--badge-height-md: 1.5rem;
|
||
--badge-padding-x: 0.625rem;
|
||
--badge-font-size: 0.6875rem;
|
||
--badge-radius: var(--radius-full);
|
||
|
||
/* Tabs 标签页 */
|
||
--tab-height: 2.5rem;
|
||
--tab-padding-x: 1rem;
|
||
--tab-font-size: 0.875rem;
|
||
--tab-indicator-height: 2px;
|
||
|
||
/* Modal / Dialog 弹窗 */
|
||
--modal-padding: 2rem;
|
||
--modal-radius: var(--radius-xl);
|
||
--modal-max-width-sm: 420px;
|
||
--modal-max-width-md: 560px;
|
||
--modal-max-width-lg: 720px;
|
||
|
||
/* Tooltip 提示 */
|
||
--tooltip-padding: 0.5rem 0.75rem;
|
||
--tooltip-radius: var(--radius-sm);
|
||
--tooltip-font-size: 0.75rem;
|
||
|
||
/* Form 表单 */
|
||
--label-font-size: 0.875rem;
|
||
--label-margin-bottom: 0.5rem;
|
||
--form-group-gap: 1.25rem;
|
||
|
||
/* Avatar 头像 */
|
||
--avatar-size-sm: 2rem;
|
||
--avatar-size-md: 2.5rem;
|
||
--avatar-size-lg: 3rem;
|
||
--avatar-radius: var(--radius-full);
|
||
|
||
/* Table 表格 */
|
||
--table-header-bg: var(--color-bg-secondary);
|
||
--table-header-font-size: 0.75rem;
|
||
--table-cell-padding-y: 0.75rem;
|
||
--table-cell-padding-x: 1rem;
|
||
--table-border-color: var(--color-border-primary);
|
||
|
||
/* Breadcrumb 面包屑 */
|
||
--breadcrumb-font-size: 0.875rem;
|
||
--breadcrumb-separator-margin: 0.5rem;
|
||
|
||
/* Menu / Dropdown 菜单 */
|
||
--menu-item-height: 2.5rem;
|
||
--menu-padding-y: 0.5rem;
|
||
--menu-min-width: 180px;
|
||
|
||
/* Accordion 手风琴 */
|
||
--accordion-item-gap: 0.5rem;
|
||
--accordion-trigger-height: 3rem;
|
||
--accordion-trigger-padding-x: 1rem;
|
||
|
||
/* Skeleton 骨架屏 */
|
||
--skeleton-radius: var(--radius-sm);
|
||
--skeleton-bg: var(--color-bg-tertiary);
|
||
|
||
/* Stats Bar 数据条 */
|
||
--stats-bar-gap: var(--spacing-2xl);
|
||
--stats-number-size: var(--font-size-4xl);
|
||
--stats-label-size: var(--font-size-xs);
|
||
|
||
/* === 12 列网格系统(Grid System)=== */
|
||
--grid-columns: 12;
|
||
--grid-gap-xs: 0.5rem;
|
||
--grid-gap-sm: 1rem;
|
||
--grid-gap-md: 1.5rem;
|
||
--grid-gap-lg: 2rem;
|
||
--grid-gap-xl: 2.5rem;
|
||
--grid-gap-2xl: 3rem;
|
||
}
|
||
|
||
/* === 暗黑模式(html[data-theme='dark'])===
|
||
策略:仅覆盖 CSS 变量,组件无需逐元素反色。
|
||
- 文字墨色 --color-ink 反色为浅色(其语义收窄为"文字/描边跟随主题")
|
||
- 页面底色 --color-bg-* 反色为深色
|
||
- 深色区块(--color-dark-* / --color-brand-section / --color-overlay / footer)
|
||
使用独立 token,不随反色 —— 由组件显式引用(如 bg-dark-bg) */
|
||
html[data-theme='dark'] {
|
||
/* 墨色反色 → 文字浅色 */
|
||
--color-ink: #F8FAFC;
|
||
--color-ink-light: #E2E8F0;
|
||
--color-ink-lighter: #CBD5E1;
|
||
--color-ink-rgb: 248 250 252;
|
||
|
||
/* 页面底色反色 */
|
||
--color-bg-primary: #0A0E14;
|
||
--color-bg-primary-rgb: 10 14 20;
|
||
--color-bg-secondary: #0F1419;
|
||
--color-bg-secondary-rgb: 15 20 25;
|
||
--color-bg-tertiary: #151B23;
|
||
--color-bg-section: #0F1419;
|
||
--color-bg-hover: #151B23;
|
||
--color-bg-elevated: #151B23;
|
||
|
||
/* 文字层级反色 */
|
||
--color-text-primary: #F8FAFC;
|
||
--color-text-secondary: #CBD5E1;
|
||
--color-text-secondary-rgb: 203 213 225;
|
||
--color-text-tertiary: #94A3B8;
|
||
--color-text-muted: #94A3B8;
|
||
--color-text-muted-rgb: 148 163 184;
|
||
--color-text-subtle: #94A3B8;
|
||
--color-text-placeholder: #94A3B8;
|
||
--color-text-hint: #94A3B8;
|
||
--color-text-inverse: #0A0E14;
|
||
|
||
/* 边框层级反色 */
|
||
--color-border-primary: #1E293B;
|
||
--color-border-primary-rgb: 30 41 59;
|
||
--color-border-secondary: #334155;
|
||
--color-border-secondary-rgb: 51 65 85;
|
||
--color-border-accent: #F8FAFC;
|
||
--color-border-accent-rgb: 248 250 252;
|
||
--color-border-light: #1E293B;
|
||
--color-border-light-rgb: 30 41 59;
|
||
--color-border-dark: #CBD5E1;
|
||
--color-border-dark-rgb: 203 213 225;
|
||
|
||
/* 链接反色 */
|
||
--color-link: #F8FAFC;
|
||
--color-link-hover: #E04A68;
|
||
}
|
||
|
||
/* html/body 背景跟随主题 token(覆盖顶部 !important 硬编码) */
|
||
html[data-theme='dark'],
|
||
html[data-theme='dark'] body {
|
||
background-color: var(--color-bg-primary) !important;
|
||
color: var(--color-text-primary) !important;
|
||
}
|
||
|
||
@layer base {
|
||
* {
|
||
@apply antialiased;
|
||
border-color: var(--color-border-primary);
|
||
}
|
||
|
||
html {
|
||
scroll-behavior: smooth;
|
||
/* 桌面端字号分级(mobile-first 16 → tablet 17 → desktop 18):
|
||
桌面端 18px 根字号使所有 rem 单位放大 12.5%,标题与留白更舒展,
|
||
与增强的圆角+阴影形成"软化"语言。
|
||
权衡:会覆盖用户浏览器字号缩放设置 —— 经 design review 决定保留视觉一致性。 */
|
||
font-size: 16px;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
text-rendering: optimizeLegibility;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
@media (min-width: 640px) {
|
||
html {
|
||
font-size: 17px;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 1024px) {
|
||
html {
|
||
font-size: 18px;
|
||
}
|
||
}
|
||
|
||
body {
|
||
background-color: var(--color-bg-primary);
|
||
color: var(--color-text-primary);
|
||
font-family: var(--font-sans);
|
||
line-height: var(--line-height-normal);
|
||
letter-spacing: var(--letter-spacing-normal);
|
||
position: relative;
|
||
overflow-x: hidden;
|
||
width: 100%;
|
||
transition: background-color var(--transition-normal) var(--ease-out),
|
||
color var(--transition-normal) var(--ease-out);
|
||
}
|
||
|
||
body::before {
|
||
content: '';
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
pointer-events: none;
|
||
z-index: -1;
|
||
}
|
||
|
||
h1, h2, h3, h4, h5, h6 {
|
||
font-weight: 700;
|
||
line-height: var(--line-height-tight);
|
||
letter-spacing: var(--letter-spacing-tight);
|
||
color: var(--color-text-primary);
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
}
|
||
|
||
h1 {
|
||
font-size: var(--font-size-5xl);
|
||
letter-spacing: var(--letter-spacing-tighter);
|
||
font-weight: 800;
|
||
}
|
||
h2 {
|
||
font-size: var(--font-size-4xl);
|
||
letter-spacing: var(--letter-spacing-tight);
|
||
font-weight: 700;
|
||
}
|
||
h3 {
|
||
font-size: var(--font-size-2xl);
|
||
letter-spacing: var(--letter-spacing-tight);
|
||
font-weight: 700;
|
||
}
|
||
h4 {
|
||
font-size: var(--font-size-xl);
|
||
letter-spacing: var(--letter-spacing-normal);
|
||
font-weight: 600;
|
||
}
|
||
h5 {
|
||
font-size: var(--font-size-lg);
|
||
letter-spacing: var(--letter-spacing-normal);
|
||
font-weight: 600;
|
||
}
|
||
h6 {
|
||
font-size: var(--font-size-base);
|
||
letter-spacing: var(--letter-spacing-wide);
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
p {
|
||
color: var(--color-text-secondary);
|
||
line-height: var(--line-height-relaxed);
|
||
margin-bottom: var(--paragraph-spacing);
|
||
}
|
||
|
||
p:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
/* 列表样式优化 */
|
||
ul, ol {
|
||
color: var(--color-text-secondary);
|
||
line-height: var(--line-height-relaxed);
|
||
margin-bottom: var(--paragraph-spacing);
|
||
padding-left: 1.5em;
|
||
}
|
||
|
||
li {
|
||
margin-bottom: 0.5em;
|
||
}
|
||
|
||
li:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
ul {
|
||
list-style-type: none;
|
||
}
|
||
|
||
ul li::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0.75em;
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 1px;
|
||
background: var(--color-brand);
|
||
transform: rotate(45deg);
|
||
}
|
||
|
||
ul li {
|
||
position: relative;
|
||
padding-left: 0.5em;
|
||
}
|
||
|
||
/* 引用样式 */
|
||
blockquote {
|
||
border-left: 3px solid var(--color-brand);
|
||
padding-left: 1.5em;
|
||
margin: 2em 0;
|
||
font-size: var(--font-size-lg);
|
||
color: var(--color-text-primary);
|
||
font-style: normal;
|
||
line-height: var(--line-height-relaxed);
|
||
background: var(--color-bg-secondary);
|
||
padding: 1.5em 2em;
|
||
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
||
}
|
||
|
||
/* 强调文本 */
|
||
strong {
|
||
font-weight: 600;
|
||
color: var(--color-text-primary);
|
||
}
|
||
|
||
/* 代码样式 */
|
||
code {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.9em;
|
||
background: var(--color-bg-tertiary);
|
||
padding: 0.15em 0.4em;
|
||
border-radius: var(--radius-sm);
|
||
color: var(--color-brand);
|
||
}
|
||
|
||
pre {
|
||
font-family: var(--font-mono);
|
||
font-size: var(--font-size-sm);
|
||
line-height: var(--line-height-snug);
|
||
background: var(--color-dark-bg);
|
||
color: var(--color-dark-text-primary);
|
||
padding: 1.5em;
|
||
border-radius: var(--radius-lg);
|
||
overflow-x: auto;
|
||
margin: 2em 0;
|
||
}
|
||
|
||
pre code {
|
||
background: transparent;
|
||
padding: 0;
|
||
color: inherit;
|
||
font-size: inherit;
|
||
}
|
||
|
||
/* 水平分隔线 */
|
||
hr {
|
||
border: none;
|
||
height: 1px;
|
||
background: var(--color-border-primary);
|
||
margin: 3em 0;
|
||
}
|
||
|
||
/* 数字和符号的字体优化 */
|
||
.tabular-nums {
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.oldstyle-nums {
|
||
font-variant-numeric: oldstyle-nums;
|
||
}
|
||
|
||
/* 小字说明文字 */
|
||
.caption {
|
||
font-size: var(--font-size-caption);
|
||
line-height: var(--line-height-caption);
|
||
color: var(--color-text-muted);
|
||
letter-spacing: var(--letter-spacing-wide);
|
||
}
|
||
|
||
/* 眉毛标签(Eyebrow Label) */
|
||
.eyebrow {
|
||
font-size: var(--font-size-xs);
|
||
font-weight: 600;
|
||
letter-spacing: var(--letter-spacing-eyebrow);
|
||
text-transform: uppercase;
|
||
color: var(--color-brand);
|
||
}
|
||
|
||
a {
|
||
color: var(--color-link);
|
||
text-decoration: none;
|
||
transition: color var(--transition-fast) var(--ease-out);
|
||
}
|
||
|
||
a:hover {
|
||
color: var(--color-link-hover);
|
||
}
|
||
|
||
a:focus-visible,
|
||
button:focus-visible,
|
||
input:focus-visible,
|
||
textarea:focus-visible,
|
||
select:focus-visible,
|
||
[tabindex]:focus-visible {
|
||
outline: 2px solid var(--color-brand);
|
||
outline-offset: 2px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
button:focus:not(:focus-visible),
|
||
a:focus:not(:focus-visible),
|
||
input:focus:not(:focus-visible),
|
||
textarea:focus:not(:focus-visible) {
|
||
outline: none;
|
||
}
|
||
|
||
button {
|
||
font-family: inherit;
|
||
cursor: pointer;
|
||
}
|
||
|
||
input, textarea {
|
||
font-family: inherit;
|
||
outline: none;
|
||
}
|
||
|
||
input:focus, textarea:focus {
|
||
outline: none;
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
animation-duration: 0.01ms !important;
|
||
animation-iteration-count: 1 !important;
|
||
transition-duration: 0.01ms !important;
|
||
scroll-behavior: auto !important;
|
||
}
|
||
}
|
||
|
||
@media (prefers-contrast: more) {
|
||
:root {
|
||
--color-text-primary: #000000;
|
||
--color-text-secondary: #1a1a1a;
|
||
--color-border-primary: #000000;
|
||
/* Tailwind border-* 工具类消费 rgb 通道,需同步覆写,否则高对比度模式下边框静默失效 */
|
||
--color-border-primary-rgb: 0 0 0;
|
||
}
|
||
}
|
||
|
||
.font-brand {
|
||
font-family: var(--font-brand), "STKaiti", "KaiTi", serif !important;
|
||
font-weight: normal;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
text-rendering: optimizeLegibility;
|
||
}
|
||
|
||
::selection {
|
||
background-color: var(--color-brand);
|
||
color: white;
|
||
}
|
||
}
|
||
|
||
@layer utilities {
|
||
.container-x {
|
||
width: 100%;
|
||
max-width: var(--container-max);
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
padding-left: var(--container-padding);
|
||
padding-right: var(--container-padding);
|
||
}
|
||
|
||
@media (min-width: 768px) {
|
||
.container-x {
|
||
--container-padding: 2.5rem;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 1024px) {
|
||
.container-x {
|
||
--container-padding: 3rem;
|
||
}
|
||
}
|
||
|
||
.section-padding {
|
||
padding-top: var(--section-padding-y);
|
||
padding-bottom: var(--section-padding-y);
|
||
}
|
||
|
||
.text-balance {
|
||
text-wrap: balance;
|
||
}
|
||
|
||
|
||
.bg-dots {
|
||
background-image: radial-gradient(circle, var(--color-border-primary) 1px, transparent 1px);
|
||
background-size: 24px 24px;
|
||
}
|
||
|
||
.bg-grain {
|
||
position: relative;
|
||
}
|
||
.bg-grain::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
opacity: 0.04;
|
||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
||
background-repeat: repeat;
|
||
background-size: 128px 128px;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
|
||
.bg-glow-brand {
|
||
background: radial-gradient(ellipse at 50% 0%, rgba(var(--color-brand-rgb), 0.08) 0%, transparent 60%);
|
||
}
|
||
|
||
/* Bain 式干净卡片(替代旧墨韵光晕卡片) */
|
||
.bain-card {
|
||
background: var(--color-bg-primary);
|
||
border: var(--card-border);
|
||
border-radius: var(--card-border-radius);
|
||
box-shadow: var(--card-shadow);
|
||
transition: transform var(--transition-fast) var(--ease-out),
|
||
box-shadow var(--transition-fast) var(--ease-out);
|
||
}
|
||
.bain-card:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: var(--card-shadow-hover);
|
||
}
|
||
|
||
/* === Bain 式不对称布局系统 === */
|
||
/* 宽窄列:左宽右窄(65/35) */
|
||
.asymmetric-wide-narrow {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: var(--spacing-2xl);
|
||
}
|
||
@media (min-width: 1024px) {
|
||
.asymmetric-wide-narrow {
|
||
grid-template-columns: 5fr 3fr;
|
||
gap: var(--spacing-4xl);
|
||
}
|
||
}
|
||
|
||
/* 宽窄列:左窄右宽(35/65) */
|
||
.asymmetric-narrow-wide {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: var(--spacing-2xl);
|
||
}
|
||
@media (min-width: 1024px) {
|
||
.asymmetric-narrow-wide {
|
||
grid-template-columns: 3fr 5fr;
|
||
gap: var(--spacing-4xl);
|
||
}
|
||
}
|
||
|
||
/* 不对称三列:左宽 + 中窄 + 右窄(50/25/25) */
|
||
.asymmetric-three {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: var(--spacing-2xl);
|
||
}
|
||
@media (min-width: 1024px) {
|
||
.asymmetric-three {
|
||
grid-template-columns: 2fr 1fr 1fr;
|
||
gap: var(--spacing-3xl);
|
||
}
|
||
}
|
||
|
||
/* 大留白区块:用于 Hero 下方过渡 */
|
||
.section-breathing {
|
||
padding-top: var(--spacing-5xl);
|
||
padding-bottom: var(--spacing-5xl);
|
||
}
|
||
@media (min-width: 768px) {
|
||
.section-breathing {
|
||
padding-top: var(--spacing-6xl);
|
||
padding-bottom: var(--spacing-6xl);
|
||
}
|
||
}
|
||
|
||
/* 紧致区块:用于数据密集区 */
|
||
.section-compact {
|
||
padding-top: var(--spacing-2xl);
|
||
padding-bottom: var(--spacing-2xl);
|
||
}
|
||
@media (min-width: 768px) {
|
||
.section-compact {
|
||
padding-top: var(--spacing-3xl);
|
||
padding-bottom: var(--spacing-3xl);
|
||
}
|
||
}
|
||
|
||
/* 品牌色深色区块(Bain 式 Hero/CTA 深红背景) */
|
||
.bg-brand-section {
|
||
background-color: var(--color-brand-section);
|
||
color: var(--color-brand-section-text);
|
||
}
|
||
|
||
.bg-glow-hero {
|
||
background:
|
||
radial-gradient(ellipse at 20% 30%, rgba(var(--color-brand-rgb), 0.1) 0%, transparent 50%),
|
||
radial-gradient(ellipse at 80% 70%, rgba(var(--color-accent-blue-rgb), 0.06) 0%, transparent 50%);
|
||
}
|
||
|
||
/* 斜切装饰(Accenture 风格) */
|
||
.clip-slant-right {
|
||
clip-path: polygon(0 0, 100% 0, 92% 100%, 0 100%);
|
||
}
|
||
|
||
.clip-slant-left {
|
||
clip-path: polygon(8% 0, 100% 0, 100% 100%, 0 100%);
|
||
}
|
||
|
||
/* 渐变分隔线 */
|
||
.divider-gradient {
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent, var(--color-border-secondary), transparent);
|
||
}
|
||
|
||
/* L 形角框 */
|
||
.corner-frame {
|
||
position: relative;
|
||
}
|
||
.corner-frame::before,
|
||
.corner-frame::after {
|
||
content: '';
|
||
position: absolute;
|
||
width: 16px;
|
||
height: 16px;
|
||
border-color: var(--color-brand);
|
||
border-style: solid;
|
||
transition: all var(--transition-normal) var(--ease-out);
|
||
}
|
||
.corner-frame::before {
|
||
top: 0;
|
||
left: 0;
|
||
border-width: 2px 0 0 2px;
|
||
}
|
||
.corner-frame::after {
|
||
bottom: 0;
|
||
right: 0;
|
||
border-width: 0 2px 2px 0;
|
||
}
|
||
|
||
/* 编号样式(超大背景编号) */
|
||
.bg-number {
|
||
font-size: clamp(6rem, 20vw, 16rem);
|
||
font-weight: 900;
|
||
line-height: 0.8;
|
||
color: transparent;
|
||
-webkit-text-stroke: 1px var(--color-border-primary);
|
||
user-select: none;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* === 12 列网格系统 === */
|
||
.grid-12 {
|
||
display: grid;
|
||
grid-template-columns: repeat(12, 1fr);
|
||
}
|
||
|
||
.grid-gap-xs { gap: var(--grid-gap-xs); }
|
||
.grid-gap-sm { gap: var(--grid-gap-sm); }
|
||
.grid-gap-md { gap: var(--grid-gap-md); }
|
||
.grid-gap-lg { gap: var(--grid-gap-lg); }
|
||
.grid-gap-xl { gap: var(--grid-gap-xl); }
|
||
.grid-gap-2xl { gap: var(--grid-gap-2xl); }
|
||
|
||
/* 列跨越(1-12) */
|
||
.col-span-1 { grid-column: span 1 / span 1; }
|
||
.col-span-2 { grid-column: span 2 / span 2; }
|
||
.col-span-3 { grid-column: span 3 / span 3; }
|
||
.col-span-4 { grid-column: span 4 / span 4; }
|
||
.col-span-5 { grid-column: span 5 / span 5; }
|
||
.col-span-6 { grid-column: span 6 / span 6; }
|
||
.col-span-7 { grid-column: span 7 / span 7; }
|
||
.col-span-8 { grid-column: span 8 / span 8; }
|
||
.col-span-9 { grid-column: span 9 / span 9; }
|
||
.col-span-10 { grid-column: span 10 / span 10; }
|
||
.col-span-11 { grid-column: span 11 / span 11; }
|
||
.col-span-12 { grid-column: span 12 / span 12; }
|
||
|
||
/* 响应式列跨越 */
|
||
@media (min-width: 640px) {
|
||
.sm\:col-span-1 { grid-column: span 1 / span 1; }
|
||
.sm\:col-span-2 { grid-column: span 2 / span 2; }
|
||
.sm\:col-span-3 { grid-column: span 3 / span 3; }
|
||
.sm\:col-span-4 { grid-column: span 4 / span 4; }
|
||
.sm\:col-span-5 { grid-column: span 5 / span 5; }
|
||
.sm\:col-span-6 { grid-column: span 6 / span 6; }
|
||
.sm\:col-span-7 { grid-column: span 7 / span 7; }
|
||
.sm\:col-span-8 { grid-column: span 8 / span 8; }
|
||
.sm\:col-span-9 { grid-column: span 9 / span 9; }
|
||
.sm\:col-span-10 { grid-column: span 10 / span 10; }
|
||
.sm\:col-span-11 { grid-column: span 11 / span 11; }
|
||
.sm\:col-span-12 { grid-column: span 12 / span 12; }
|
||
}
|
||
|
||
@media (min-width: 768px) {
|
||
.md\:col-span-1 { grid-column: span 1 / span 1; }
|
||
.md\:col-span-2 { grid-column: span 2 / span 2; }
|
||
.md\:col-span-3 { grid-column: span 3 / span 3; }
|
||
.md\:col-span-4 { grid-column: span 4 / span 4; }
|
||
.md\:col-span-5 { grid-column: span 5 / span 5; }
|
||
.md\:col-span-6 { grid-column: span 6 / span 6; }
|
||
.md\:col-span-7 { grid-column: span 7 / span 7; }
|
||
.md\:col-span-8 { grid-column: span 8 / span 8; }
|
||
.md\:col-span-9 { grid-column: span 9 / span 9; }
|
||
.md\:col-span-10 { grid-column: span 10 / span 10; }
|
||
.md\:col-span-11 { grid-column: span 11 / span 11; }
|
||
.md\:col-span-12 { grid-column: span 12 / span 12; }
|
||
}
|
||
|
||
@media (min-width: 1024px) {
|
||
.lg\:col-span-1 { grid-column: span 1 / span 1; }
|
||
.lg\:col-span-2 { grid-column: span 2 / span 2; }
|
||
.lg\:col-span-3 { grid-column: span 3 / span 3; }
|
||
.lg\:col-span-4 { grid-column: span 4 / span 4; }
|
||
.lg\:col-span-5 { grid-column: span 5 / span 5; }
|
||
.lg\:col-span-6 { grid-column: span 6 / span 6; }
|
||
.lg\:col-span-7 { grid-column: span 7 / span 7; }
|
||
.lg\:col-span-8 { grid-column: span 8 / span 8; }
|
||
.lg\:col-span-9 { grid-column: span 9 / span 9; }
|
||
.lg\:col-span-10 { grid-column: span 10 / span 10; }
|
||
.lg\:col-span-11 { grid-column: span 11 / span 11; }
|
||
.lg\:col-span-12 { grid-column: span 12 / span 12; }
|
||
}
|
||
|
||
/* 网格行跨越 */
|
||
.row-span-1 { grid-row: span 1 / span 1; }
|
||
.row-span-2 { grid-row: span 2 / span 2; }
|
||
.row-span-3 { grid-row: span 3 / span 3; }
|
||
}
|
||
|
||
/* ===== 动画关键帧 ===== */
|
||
@keyframes fadeInUp {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(24px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
@keyframes fadeInDown {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-24px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
@keyframes slideInLeft {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateX(-32px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
|
||
@keyframes slideInRight {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateX(32px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
|
||
@keyframes scaleIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: scale(0.95);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
@keyframes pulse-soft {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.6; }
|
||
}
|
||
|
||
@keyframes shimmer {
|
||
0% {
|
||
background-position: -200% 0;
|
||
}
|
||
100% {
|
||
background-position: 200% 0;
|
||
}
|
||
}
|
||
|
||
@keyframes float {
|
||
0%, 100% {
|
||
transform: translateY(0);
|
||
}
|
||
50% {
|
||
transform: translateY(-8px);
|
||
}
|
||
}
|
||
|
||
@keyframes ripple {
|
||
0% {
|
||
transform: scale(0);
|
||
opacity: 0.5;
|
||
}
|
||
100% {
|
||
transform: scale(4);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
@keyframes skeletonPulse {
|
||
0%, 100% {
|
||
opacity: 1;
|
||
}
|
||
50% {
|
||
opacity: 0.7;
|
||
}
|
||
}
|
||
|
||
@keyframes growWidth {
|
||
from { transform: scaleX(0); }
|
||
to { transform: scaleX(1); }
|
||
}
|
||
|
||
@keyframes spinSlow {
|
||
from { transform: rotate(0deg); }
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
.animate-fade-in-up {
|
||
animation: fadeInUp var(--transition-slower) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-fade-in-down {
|
||
animation: fadeInDown var(--transition-slower) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-fade-in {
|
||
animation: fadeIn var(--transition-normal) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-slide-in-left {
|
||
animation: slideInLeft var(--transition-slow) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-slide-in-right {
|
||
animation: slideInRight var(--transition-slow) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-scale-in {
|
||
animation: scaleIn var(--transition-normal) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-pulse-soft {
|
||
animation: pulse-soft 2s ease-in-out infinite;
|
||
}
|
||
|
||
.animate-float {
|
||
animation: float 3s ease-in-out infinite;
|
||
}
|
||
|
||
.animate-ripple {
|
||
animation: ripple var(--transition-normal) var(--ease-out) forwards;
|
||
}
|
||
|
||
.animate-grow-width {
|
||
animation: growWidth var(--transition-slow) var(--ease-out) forwards;
|
||
transform-origin: left center;
|
||
}
|
||
|
||
.animate-spin-slow {
|
||
animation: spinSlow 8s linear infinite;
|
||
}
|
||
|
||
.skeleton-pulse {
|
||
animation: skeletonPulse 2s ease-in-out infinite;
|
||
}
|
||
|
||
.skeleton-shimmer {
|
||
background: linear-gradient(
|
||
90deg,
|
||
var(--color-bg-tertiary) 25%,
|
||
var(--color-bg-secondary) 50%,
|
||
var(--color-bg-tertiary) 75%
|
||
);
|
||
background-size: 200% 100%;
|
||
animation: shimmer 1.5s ease-in-out infinite;
|
||
}
|
||
|
||
.animation-delay-100 { animation-delay: 100ms; }
|
||
.animation-delay-200 { animation-delay: 200ms; }
|
||
.animation-delay-300 { animation-delay: 300ms; }
|
||
.animation-delay-400 { animation-delay: 400ms; }
|
||
.animation-delay-500 { animation-delay: 500ms; }
|
||
.animation-delay-600 { animation-delay: 600ms; }
|
||
.animation-delay-700 { animation-delay: 700ms; }
|
||
.animation-delay-800 { animation-delay: 800ms; }
|
||
|
||
/* ===== 滚动条样式 ===== */
|
||
::-webkit-scrollbar {
|
||
width: 6px;
|
||
height: 6px;
|
||
}
|
||
|
||
::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb {
|
||
background: var(--color-border-secondary);
|
||
border-radius: 3px;
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb:hover {
|
||
background: var(--color-text-muted);
|
||
}
|
||
|
||
|
||
/* ===== 响应式调整(Mobile First) ===== */
|
||
|
||
body {
|
||
padding-bottom: 64px;
|
||
}
|
||
|
||
p, li, span {
|
||
overflow-wrap: break-word;
|
||
word-wrap: break-word;
|
||
}
|
||
|
||
/* WCAG 2.5.5 (AAA): 44×44px 触控目标仅作用于移动端导航/页眉/页脚交互元素。
|
||
原全局选择器会撑大正文行内链接,破坏排版节奏与组件自有的尺寸控制。 */
|
||
@media (max-width: 768px) {
|
||
nav a,
|
||
nav button,
|
||
header a,
|
||
header button,
|
||
footer a,
|
||
footer button,
|
||
[role="menu"] a,
|
||
[role="menu"] button,
|
||
[data-mobile-menu] a,
|
||
[data-mobile-menu] button {
|
||
min-height: 44px;
|
||
min-width: 44px;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 640px) {
|
||
:root {
|
||
--container-padding: 1.5rem;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 768px) {
|
||
:root {
|
||
--font-size-lg: 1.125rem;
|
||
--font-size-xl: 1.25rem;
|
||
--font-size-2xl: 1.5rem;
|
||
--font-size-3xl: 1.875rem;
|
||
--font-size-4xl: 2.25rem;
|
||
--font-size-5xl: 3rem;
|
||
--font-size-6xl: 3.75rem;
|
||
--font-size-7xl: 4.5rem;
|
||
--font-size-display: 6rem;
|
||
--section-gap: var(--spacing-4xl);
|
||
--section-gap-sm: var(--spacing-3xl);
|
||
--section-padding-y: var(--spacing-4xl);
|
||
}
|
||
|
||
body {
|
||
padding-bottom: 0;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 1024px) {
|
||
:root {
|
||
--font-size-2xl: 1.5rem;
|
||
--font-size-3xl: 2rem;
|
||
--font-size-4xl: 2.5rem;
|
||
--font-size-5xl: 3.5rem;
|
||
--font-size-6xl: 4.5rem;
|
||
--font-size-7xl: 6rem;
|
||
--font-size-display: 8rem;
|
||
--container-padding: 3rem;
|
||
--section-gap: var(--spacing-5xl);
|
||
--section-padding-y: var(--spacing-5xl);
|
||
}
|
||
}
|
||
|
||
/* ===== 安全区域 ===== */
|
||
.safe-area-inset-bottom {
|
||
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||
}
|
||
|
||
/* ===== 页面过渡加载条 ===== */
|
||
.page-transition-loader {
|
||
width: 120px;
|
||
height: 3px;
|
||
background: var(--color-bg-tertiary);
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.page-transition-loader__bar {
|
||
width: 40%;
|
||
height: 100%;
|
||
background: var(--color-brand);
|
||
border-radius: 2px;
|
||
animation: page-loader-slide 1.2s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes page-loader-slide {
|
||
0% { transform: translateX(-100%); }
|
||
50% { transform: translateX(200%); }
|
||
100% { transform: translateX(-100%); }
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.page-transition-loader__bar {
|
||
animation: none;
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
/* ===== 渐变边框动画 ===== */
|
||
@property --border-angle {
|
||
syntax: '<angle>';
|
||
initial-value: 0deg;
|
||
inherits: false;
|
||
}
|
||
|
||
@keyframes rotateBorder {
|
||
from { --border-angle: 0deg; }
|
||
to { --border-angle: 360deg; }
|
||
}
|
||
|
||
.glow-border {
|
||
position: relative;
|
||
animation: rotateBorder 6s linear infinite paused;
|
||
}
|
||
|
||
.glow-border::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: -1px;
|
||
border-radius: inherit;
|
||
padding: 1px;
|
||
background: conic-gradient(from var(--border-angle),
|
||
var(--color-text-muted),
|
||
var(--color-border-primary),
|
||
var(--color-text-muted));
|
||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||
-webkit-mask-composite: xor;
|
||
mask-composite: exclude;
|
||
opacity: 0;
|
||
transition: opacity 0.6s var(--ease-out);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.glow-border:hover::before {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.glow-border:hover {
|
||
animation-play-state: running;
|
||
}
|
||
|
||
/* === CMS RichTextEditor (TipTap) 样式 === */
|
||
/* 仅用于 CMS Studio 暗色主题,选择器限定在 .rich-text-editor-content */
|
||
.rich-text-editor-content {
|
||
min-height: 120px;
|
||
padding: 0.75rem;
|
||
color: white;
|
||
font-size: 0.875rem;
|
||
line-height: 1.6;
|
||
outline: none;
|
||
}
|
||
|
||
.rich-text-editor-content:empty::before {
|
||
content: attr(data-placeholder);
|
||
color: rgba(255, 255, 255, 0.3);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.rich-text-editor-content h2 {
|
||
font-size: 1.125rem;
|
||
font-weight: 600;
|
||
margin: 0.75rem 0 0.5rem;
|
||
color: white;
|
||
}
|
||
|
||
.rich-text-editor-content h3 {
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
margin: 0.5rem 0 0.375rem;
|
||
color: white;
|
||
}
|
||
|
||
.rich-text-editor-content p {
|
||
margin: 0.375rem 0;
|
||
}
|
||
|
||
.rich-text-editor-content ul,
|
||
.rich-text-editor-content ol {
|
||
padding-left: 1.25rem;
|
||
margin: 0.5rem 0;
|
||
}
|
||
|
||
.rich-text-editor-content ul {
|
||
list-style: disc;
|
||
}
|
||
|
||
.rich-text-editor-content ol {
|
||
list-style: decimal;
|
||
}
|
||
|
||
.rich-text-editor-content li {
|
||
margin: 0.25rem 0;
|
||
}
|
||
|
||
.rich-text-editor-content blockquote {
|
||
border-left: 3px solid var(--color-brand);
|
||
padding-left: 0.75rem;
|
||
margin: 0.5rem 0;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
font-style: italic;
|
||
}
|
||
|
||
.rich-text-editor-content a {
|
||
color: var(--color-brand);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.rich-text-editor-content strong {
|
||
font-weight: 600;
|
||
color: white;
|
||
}
|
||
|
||
.rich-text-editor-content em {
|
||
font-style: italic;
|
||
}
|