// Design System Constants — L3 Detail Pages // Color tokens reference global CSS variables for dark-mode support. // Layout / spacing / animation / easing remain as JS constants. // // ⚠️ COMPLIANCE TRAP(Task #16 残留,刻意保留待用): // 本文件动画令牌与 CONTEXT.md 动效约束冲突(见下方各 ⚠️ 行),且 // design-system.test.ts 用 `// @ts-nocheck` 断言了这些「错误值」。 // 它是零生产消费者的死代码,仅作历史参考。请勿照抄带 ⚠️ 的令牌; // 新代码请直接用 ScrollReveal 默认(duration 0.3 / stagger 0.05 / // easing ease-ink [0.22, 1, 0.36, 1])。要修正须同步改测试,否则必挂。 export const DESIGN_SYSTEM = Object.freeze({ animation: { duration: { fast: '0.2s', normal: '0.4s', // ⚠️ 超目标:CONTEXT.md 入场目标 200-300ms,0.4s=400ms 超时 slow: '0.6s', // ⚠️ P1:>300ms 目标(仍 ≤700ms 硬上限) slower: '0.8s', // ⚠️ P0:>700ms 硬上限违规(最严重) countUp: '2s', }, easing: { smooth: 'cubic-bezier(0.4, 0, 0.2, 1)', // ⚠️ 非 ease-ink [0.22,1,0.36,1] bounce: 'cubic-bezier(0.34, 1.56, 0.64, 1)', // ⚠️ 弹性缓动,违反「禁 spring 内容入场」 easeOut: 'cubic-bezier(0, 0, 0.2, 1)', easeInOut: 'cubic-bezier(0.4, 0, 0.6, 1)', }, delay: { stagger: 0.08, // ⚠️ P2:>60ms(应为 ≤0.06,对齐 ScrollReveal 0.05) section: 0.15, }, }, spacing: { section: { py: 'py-20 lg:py-28', pyCompact: 'py-16 lg:py-20', }, container: { default: 'max-w-7xl mx-auto px-4 sm:px-6 lg:px-8', narrow: 'max-w-5xl mx-auto px-4 sm:px-6 lg:px-8', wide: 'max-w-[1400px] mx-auto px-4 sm:px-6 lg:px-8', }, grid: { gap: 'gap-6 lg:gap-8', gapSmall: 'gap-4 lg:gap-6', }, }, // Typography classes reference CSS variables for theme-aware sizing typography: { hero: { title: 'text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight text-[var(--color-text-primary)]', subtitle: 'text-lg md:text-xl leading-relaxed text-[var(--color-text-secondary)]', description: 'text-base mt-4 max-w-2xl text-[var(--color-text-muted)]', }, section: { title: 'text-3xl md:text-4xl font-bold tracking-tight text-[var(--color-text-primary)]', subtitle: 'text-lg mt-2 text-[var(--color-text-secondary)]', body: 'text-base leading-relaxed text-[var(--color-text-secondary)]', }, card: { title: 'text-lg font-semibold text-[var(--color-text-primary)]', description: 'text-sm leading-relaxed text-[var(--color-text-muted)]', }, }, effects: { inkGlow: { border: 'conic-gradient(from var(--angle), transparent 0%, var(--color-brand) 10%, transparent 20%)', glow: 'radial-gradient(circle at var(--mouse-x) var(--mouse-y), rgba(var(--color-brand-rgb), 0.15) 0%, transparent 50%)', speed: '3s', }, hover: { translateY: '-4px', shadow: 'shadow-xl', transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', }, scroll: { fadeInUp: { initial: { opacity: 0, y: 24 }, animate: { opacity: 1, y: 0 }, viewport: { once: true, margin: '-80px' }, transition: { duration: 0.6, ease: [0.16, 1, 0.3, 1] as const }, // ⚠️ P1:0.6s 超 300ms 目标 }, staggerChildren: { delay: 0.08, }, }, }, // Color references map to CSS custom properties defined in globals.css // These are used for inline styles where Tailwind classes aren't feasible colors: { brand: { primary: 'var(--color-brand)', light: 'var(--color-brand-bg)', lighter: 'rgba(var(--color-brand-rgb), 0.04)', gradient: 'linear-gradient(135deg, var(--color-brand) 0%, #99182d 100%)', }, neutral: { 50: 'var(--color-bg-primary)', 100: 'var(--color-bg-section)', 200: 'var(--color-border-primary)', 300: 'var(--color-text-hint)', 400: 'var(--color-text-subtle)', 500: 'var(--color-text-muted)', 600: 'var(--color-text-secondary)', 700: 'var(--color-text-primary)', 800: 'var(--color-text-primary)', 900: 'var(--color-text-primary)', }, ink: { light: 'rgba(0, 0, 0, 0.03)', medium: 'rgba(0, 0, 0, 0.06)', texture: 'repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(0,0,0,.02) 10px, rgba(0,0,0,.02) 11px)', }, }, components: { card: { base: 'rounded-2xl border border-[var(--color-border-primary)] overflow-hidden transition-all duration-300 bg-[var(--color-bg-primary)]', hover: 'hover:border-[rgba(var(--color-brand-rgb),0.2)] hover:shadow-lg hover:-translate-y-1', padding: 'p-6 lg:p-8', }, badge: { base: 'inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium', variants: { primary: 'bg-[var(--color-brand-bg)] text-[var(--color-brand)]', secondary: 'bg-[var(--color-bg-tertiary)] text-[var(--color-text-secondary)]', success: 'bg-green-50 text-green-700', warning: 'bg-yellow-50 text-yellow-700', }, }, button: { primary: 'inline-flex items-center gap-2 px-6 py-3 text-white font-semibold rounded-lg shadow-md transition-all duration-200 bg-[var(--color-brand)] hover:brightness-110 hover:shadow-lg', secondary: 'inline-flex items-center gap-2 px-6 py-3 font-semibold rounded-lg border transition-all duration-200 bg-[var(--color-bg-primary)] text-[var(--color-text-secondary)] border-[var(--color-border-primary)] hover:border-[var(--color-text-hint)] hover:shadow-sm', ghost: 'inline-flex items-center gap-2 px-4 py-2 font-medium rounded-lg transition-colors duration-200 text-[var(--color-brand)] hover:bg-[var(--color-brand-bg)]', }, metric: { container: 'text-center p-6 rounded-xl border bg-[var(--color-bg-section)] border-[var(--color-border-primary)]', value: 'text-3xl md:text-4xl font-bold mb-1 text-[var(--color-text-primary)]', label: 'text-sm text-[var(--color-text-subtle)]', description: 'text-xs mt-1 text-[var(--color-text-hint)]', }, }, }); export type DesignSystem = typeof DESIGN_SYSTEM;