'use client'; /** * L3SignalsSlot — L3 信任层「替代信号」槽 * * 设计意图: * - 真实数据(客户案例 / 资质认证 / 数据佐证 / 证言)需获得客户授权后才能公开; * 在那之前,详情页 L3 必须有可验证的兜底内容(避免 L3 整段消失 = 信任真空)。 * - 四类替代信号(方法论透明度 / 团队资历 / 里程碑 / 服务承诺)均为站点内 * 可访问的真实路由(/methodology · /team · /about/brand · /contact), * 不存在编造。 * * 接入位置:详情页 L3 区块(案例 / 认证 / 数据)之前,由 L3EmptyFallback 在三者 * 全空时统一包裹渲染;任一非空时本组件不渲染,让真实 section 自行展示。 * * 设计约束(CLAUDE.md / CONTEXT.md): * - 品牌红 ≥3 处触达点(eyebrow 短线 + Icon 容器 + 卡片 hover 边) * - 动效 ≤700ms ease-ink(ScrollReveal/StaggerReveal 默认 400ms,符合"动效四原则 fast") * - WCAG AA:text-secondary 在 bg-primary 4.5:1+;hover 状态焦点环保留 * * @see /Users/zhangxiang/Codes/Novalon/novalon-website/.workbuddy/memory/MEMORY.md * "内容真实性约束"(零编造前提下的 L3 替代信号) */ import Link from 'next/link'; import { ArrowUpRight, Compass, Milestone, ShieldCheck, Users, } from 'lucide-react'; import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal'; import { SectionLabel } from '@/components/ui/page-decoration'; import { cn } from '@/lib/utils'; interface L3Signal { href: string; eyebrow: string; title: string; desc: string; Icon: React.ComponentType<{ className?: string }>; /** * 服务承诺卡:文案散落 5 处但无可复用 L3 section, * 待业务确认后才有具体承诺条款。当前显示「待业务确认」占位(无 href 跳转)。 */ disabled?: boolean; } const SIGNALS: readonly L3Signal[] = [ { href: '/methodology', eyebrow: '方法论', title: '交付方法论', desc: '从诊断评估到持续优化,四阶段可量化路径;不依赖案例也能证明过程可控。', Icon: Compass, }, { href: '/team', eyebrow: '团队', title: '团队资历', desc: '创始团队与核心成员的背景、承诺宣言与协作方式。', Icon: Users, }, { href: '/about/brand', eyebrow: '历程', title: '发展历程', desc: '2026 年 1 月成立至今的关键节点与里程碑。', Icon: Milestone, }, { href: '/contact', eyebrow: '承诺', title: '服务承诺', desc: '具体承诺条款待业务确认后公开;当前阶段以共创协议为准,欢迎垂询。', Icon: ShieldCheck, disabled: true, }, ] as const; export function L3SignalsSlot({ heading = '在数据之外,我们用透明度建立信任', description = '客户案例与资质认证需获得授权后才能公开;在那之前,以下四个锚点是我们可验证的承诺。', }: { heading?: string; description?: string; }) { return (
信任锚点

{heading}

{description}

{/* grid 类直接挂在 StaggerReveal 上:StaggerReveal 会为每个子项包一层 motion.div, 若把 grid 放在外层容器,包装层会成为 grid 的唯一子项,卡片将堆成单列 */} {SIGNALS.map((s) => ( ))}
); } function SignalCard({ signal }: { signal: L3Signal }) { const { href, eyebrow, title, desc, Icon, disabled } = signal; const cardBody = (
{eyebrow}

{title} {!disabled && (

{desc}

{disabled && (

待业务确认

)}
); if (disabled) { return (
{cardBody}
); } return ( {cardBody} ); }