feat(home): enhance visual design and layout improvements

- Improved hero section with dynamic gradient and overlay enhancements.
- Updated background styles, component surfaces, and hover effects for a cohesive look.
- Enhanced section spacing, responsiveness, and typography for better flow.
- Refined service and project showcases with modernized card styling and interactivity.
This commit is contained in:
zguiyang
2026-03-14 11:30:33 +08:00
parent 9c6b7fd698
commit 32954cf69a
3 changed files with 199 additions and 186 deletions

View File

@@ -24,7 +24,7 @@ const t = useTranslations(lang);
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<meta name="description" content={description} />
<title>{title}{t('site.title') ? ` | ${t('site.title')}` : ''}</title>
<title>{title} | {t("site.title")}</title>
<!-- View Transitions for smooth page transitions -->
<meta name="view-transition" content="same-origin" />
{
@@ -37,8 +37,11 @@ const t = useTranslations(lang);
class="min-h-screen bg-background font-sans antialiased selection:bg-primary/20 selection:text-primary"
>
<div
class="fixed inset-0 -z-10 h-full w-full bg-background bg-[radial-gradient(ellipse_80%_80%_at_50%_-20%,rgba(37,99,235,0.15),rgba(255,255,255,0))]"
class="fixed inset-0 -z-10 h-full w-full bg-background"
>
<div class="absolute inset-0 bg-[radial-gradient(ellipse_80%_80%_at_50%_-20%,rgba(37,99,235,0.12),rgba(255,255,255,0))]"></div>
<div class="absolute inset-0 bg-[radial-gradient(circle_at_80%_20%,rgba(139,92,246,0.08),transparent_40%)]"></div>
<div class="absolute inset-0 bg-[radial-gradient(circle_at_20%_80%,rgba(249,115,22,0.05),transparent_40%)]"></div>
</div>
<slot />
<BackToTop client:load />

View File

@@ -45,12 +45,13 @@ const keyFacts = [
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen">
<div class="relative">
{/* 统一的页面背景装饰 */}
<div class="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_var(--tw-gradient-from)_0%,_transparent_25%)] from-primary/5 to-transparent"></div>
<section class="relative flex min-h-[90vh] items-center overflow-hidden py-24 lg:py-32">
<div class="page-hero-overlay opacity-50"></div>
<div class="relative overflow-hidden">
<div class="absolute inset-0 -z-10">
<div class="absolute left-1/2 top-0 h-[600px] w-[800px] -translate-x-1/2 -translate-y-1/2 bg-primary/10 blur-[120px]"></div>
<div class="absolute right-0 top-1/4 h-[400px] w-[400px] bg-purple-500/5 blur-[100px]"></div>
<div class="absolute left-0 top-1/2 h-[400px] w-[400px] bg-orange-500/5 blur-[100px]"></div>
</div>
<section class="relative flex min-h-[90vh] items-center py-24 lg:py-32">
<Container className="relative z-10">
<div class="mx-auto max-w-5xl space-y-16">
<div class="space-y-8 text-center">
@@ -85,8 +86,8 @@ const keyFacts = [
<div class="mx-auto max-w-3xl">
<div class="group relative">
<div class="absolute -inset-1 rounded-2xl bg-gradient-to-r from-primary/20 to-purple-500/20 opacity-50 blur transition duration-1000 group-hover:opacity-100 group-hover:duration-200"></div>
<div class="page-surface relative overflow-hidden rounded-2xl border bg-card/80 backdrop-blur-md">
<div class="flex items-center justify-between border-b border-border/50 bg-muted/30 px-5 py-3">
<div class="page-surface relative overflow-hidden rounded-2xl border bg-card/40 backdrop-blur-md">
<div class="flex items-center justify-between border-b border-border/50 bg-muted/20 px-5 py-3">
<div class="flex items-center gap-2">
<span class="h-3 w-3 rounded-full bg-red-400/80 shadow-[0_0_8px_rgba(248,113,113,0.4)]"></span>
<span class="h-3 w-3 rounded-full bg-yellow-400/80 shadow-[0_0_8px_rgba(250,204,21,0.4)]"></span>
@@ -124,42 +125,44 @@ const keyFacts = [
</section>
<div class="space-y-40 pb-40">
<section class="relative pt-16 lg:pt-24">
<Container>
<div class="mb-16 flex flex-col gap-6 md:flex-row md:items-end md:justify-between">
<div class="space-y-4">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">{t("home.services.title")}</h2>
<p class="max-w-2xl text-lg leading-relaxed text-muted-foreground/90">{t("home.services.description")}</p>
<section class="relative">
<div class="py-24 lg:py-32">
<Container>
<div class="mb-16 flex flex-col gap-6 md:flex-row md:items-end md:justify-between">
<div class="space-y-4">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">{t("home.services.title")}</h2>
<p class="max-w-2xl text-lg leading-relaxed text-muted-foreground/90">{t("home.services.description")}</p>
</div>
<a href={`${prefix}/services`} class="inline-flex items-center text-sm font-bold text-primary transition-colors hover:text-primary/70">
{t("services.viewAll")}
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg>
</a>
</div>
<a href={`${prefix}/services`} class="inline-flex items-center text-sm font-bold text-primary transition-colors hover:text-primary/70">
{t("services.viewAll")}
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg>
</a>
</div>
<div class="grid gap-10 md:grid-cols-2">
{localizedServices.map((service) => (
<article class="group relative p-4 transition-all duration-500 hover:-translate-y-1">
<div class="mb-8 flex items-center gap-6">
<div class={`flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br ${service.icon.gradient} text-white shadow-lg transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3`}>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<Fragment set:html={service.icon.svg} />
</svg>
<div class="grid gap-10 md:grid-cols-2">
{localizedServices.map((service) => (
<article class="group relative rounded-3xl p-6 transition-all duration-500 hover:bg-card/50 hover:shadow-xl hover:shadow-primary/5">
<div class="mb-8 flex items-center gap-6">
<div class={`flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br ${service.icon.gradient} text-white shadow-lg transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3`}>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<Fragment set:html={service.icon.svg} />
</svg>
</div>
<h3 class="text-2xl font-bold tracking-tight">{service.title}</h3>
</div>
<h3 class="text-2xl font-bold tracking-tight">{service.title}</h3>
</div>
<ul class="space-y-4">
{service.items.slice(0, 3).map((item) => (
<li class="flex items-start gap-3 text-muted-foreground group-hover:text-foreground/90 transition-colors">
<span class="mt-2.5 h-1 w-1 shrink-0 rounded-full bg-primary/30 group-hover:bg-primary transition-all"></span>
<span class="text-base leading-relaxed">{item}</span>
</li>
))}
</ul>
</article>
))}
</div>
</Container>
<ul class="space-y-4">
{service.items.slice(0, 3).map((item) => (
<li class="flex items-start gap-3 text-muted-foreground group-hover:text-foreground/90 transition-colors">
<span class="mt-2.5 h-1 w-1 shrink-0 rounded-full bg-primary/30 group-hover:bg-primary transition-all"></span>
<span class="text-base leading-relaxed">{item}</span>
</li>
))}
</ul>
</article>
))}
</div>
</Container>
</div>
</section>
<section class="relative">
@@ -177,7 +180,7 @@ const keyFacts = [
<div class={`relative flex flex-col sm:flex-row ${index % 2 === 0 ? 'sm:flex-row-reverse' : ''}`}>
<div class="absolute -left-1.5 top-2 h-3 w-3 rounded-full border-2 border-primary bg-background sm:left-1/2 sm:-ml-1.5"></div>
<div class="w-full pl-8 sm:w-1/2 sm:px-12">
<article class="p-2 transition-all">
<article class="rounded-2xl p-4 transition-all hover:bg-card/40">
<span class="text-xs font-bold uppercase tracking-wider text-primary/60">{item.period}</span>
<h3 class="mt-2 text-xl font-bold leading-tight">{item.title}</h3>
<p class="mt-3 text-sm leading-relaxed text-muted-foreground/90">{item.outcome}</p>
@@ -197,66 +200,68 @@ const keyFacts = [
</section>
<section class="relative">
<Container>
<div class="mb-12 space-y-3 text-center">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.featured.title")}</h2>
</div>
<div class="py-24 lg:py-32">
<Container>
<div class="mb-12 space-y-3 text-center">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.featured.title")}</h2>
</div>
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{featuredProjects.map((project) => (
<article class="group flex flex-col overflow-hidden rounded-3xl border border-border/50 bg-card/50 backdrop-blur-sm transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/5">
{/* 顶部封面图区域 */}
<div class="relative aspect-video overflow-hidden">
<div class={`absolute inset-0 bg-gradient-to-br ${project.image?.bg || 'from-primary/20 to-purple-500/20'} transition-transform duration-700 group-hover:scale-110`}></div>
<div class="absolute inset-0 flex items-center justify-center">
<span class="text-6xl transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3">{project.icon}</span>
</div>
<div class="absolute top-4 right-4">
<span class="rounded-full bg-background/80 px-3 py-1 text-[10px] font-bold uppercase tracking-wider text-foreground backdrop-blur-md">
{project.type}
</span>
</div>
</div>
{/* 内容区域 */}
<div class="flex flex-1 flex-col p-6 lg:p-8">
<div class="flex-1 space-y-4">
<h3 class="text-2xl font-bold tracking-tight">{project.title}</h3>
<p class="line-clamp-2 text-sm leading-relaxed text-muted-foreground">
{project.impact}
</p>
<div class="flex flex-wrap gap-2">
{project.tech.map((tech) => (
<span class="rounded-md bg-primary/5 px-2 py-1 text-[10px] font-medium text-primary/80">
{tech}
</span>
))}
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{featuredProjects.map((project) => (
<article class="group flex flex-col overflow-hidden rounded-3xl border border-border/50 bg-card/50 backdrop-blur-sm transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/5">
{/* 顶部封面图区域 */}
<div class="relative aspect-video overflow-hidden">
<div class={`absolute inset-0 bg-gradient-to-br ${project.image?.bg || 'from-primary/20 to-purple-500/20'} transition-transform duration-700 group-hover:scale-110`}></div>
<div class="absolute inset-0 flex items-center justify-center">
<span class="text-6xl transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3">{project.icon}</span>
</div>
<div class="absolute top-4 right-4">
<span class="rounded-full bg-background/80 px-3 py-1 text-[10px] font-bold uppercase tracking-wider text-foreground backdrop-blur-md">
{project.type}
</span>
</div>
</div>
{/* 操作按钮 */}
<div class="mt-8 flex items-center justify-between gap-4">
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center justify-center rounded-full bg-primary px-6 text-xs font-bold text-primary-foreground transition-all hover:bg-primary/90">
{t("home.featured.ctaPrimary")}
</a>
{project.links?.github && (
<a href={project.links.github} target="_blank" rel="noopener noreferrer" class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background/50 text-muted-foreground transition-all hover:bg-muted hover:text-foreground">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 4.125 9.642 9.807 11.53 0.6.111 0.799-0.26 0.799-0.577 0-0.285-0.011-1.04-0.017-2.042-3.338 0.727-4.042-1.61-4.042-1.61-0.546-1.387-1.333-1.756-1.333-1.756-1.089-0.745 0.083-0.729 0.083-0.729 1.205 0.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492 0.997 0.107-0.775 0.418-1.305 0.762-1.604-2.665-0.305-5.467-1.334-5.467-5.931 0-1.311 0.469-2.381 1.236-3.221-0.124-0.303-0.535-1.524 0.117-3.176 0 0 1.008-0.322 3.301 1.23 0.96-0.267 1.98-0.399 3-0.405 1.02 0.006 2.04 0.138 3 0.405 2.28-1.552 3.285-1.23 3.285-1.23 0.654 1.653 0.242 2.874 0.118 3.176 0.77 0.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921 0.43 0.372 0.823 1.102 0.823 2.222 0 1.606-0.014 2.898-0.014 3.293 0 0.319 0.192 0.694 0.801 0.576 5.687-1.889 9.812-6.228 9.812-11.53 0-6.627-5.373-12-12-12z"/></svg>
{/* 内容区域 */}
<div class="flex flex-1 flex-col p-6 lg:p-8">
<div class="flex-1 space-y-4">
<h3 class="text-2xl font-bold tracking-tight">{project.title}</h3>
<p class="line-clamp-2 text-sm leading-relaxed text-muted-foreground">
{project.impact}
</p>
<div class="flex flex-wrap gap-2">
{project.tech.map((tech) => (
<span class="rounded-md bg-primary/5 px-2 py-1 text-[10px] font-medium text-primary/80">
{tech}
</span>
))}
</div>
</div>
{/* 操作按钮 */}
<div class="mt-8 flex items-center justify-between gap-4">
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center justify-center rounded-full bg-primary px-6 text-xs font-bold text-primary-foreground transition-all hover:bg-primary/90">
{t("home.featured.ctaPrimary")}
</a>
)}
{project.links?.github && (
<a href={project.links.github} target="_blank" rel="noopener noreferrer" class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background/50 text-muted-foreground transition-all hover:bg-muted hover:text-foreground">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 4.125 9.642 9.807 11.53 0.6.111 0.799-0.26 0.799-0.577 0-0.285-0.011-1.04-0.017-2.042-3.338 0.727-4.042-1.61-4.042-1.61-0.546-1.387-1.333-1.756-1.333-1.756-1.089-0.745 0.083-0.729 0.083-0.729 1.205 0.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492 0.997 0.107-0.775 0.418-1.305 0.762-1.604-2.665-0.305-5.467-1.334-5.467-5.931 0-1.311 0.469-2.381 1.236-3.221-0.124-0.303-0.535-1.524 0.117-3.176 0 0 1.008-0.322 3.301 1.23 0.96-0.267 1.98-0.399 3-0.405 1.02 0.006 2.04 0.138 3 0.405 2.28-1.552 3.285-1.23 3.285-1.23 0.654 1.653 0.242 2.874 0.118 3.176 0.77 0.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921 0.43 0.372 0.823 1.102 0.823 2.222 0 1.606-0.014 2.898-0.014 3.293 0 0.319 0.192 0.694 0.801 0.576 5.687-1.889 9.812-6.228 9.812-11.53 0-6.627-5.373-12-12-12z"/></svg>
</a>
)}
</div>
</div>
</div>
</article>
))}
</div>
</Container>
</article>
))}
</div>
</Container>
</div>
</section>
<section class="relative">
<Container>
<div class="relative overflow-hidden rounded-[2.5rem] bg-slate-950 px-8 py-16 text-center text-white sm:px-16 sm:py-24 dark:bg-primary/10 dark:text-foreground">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_center,_var(--tw-gradient-from)_0%,_transparent_70%)] from-primary/20 to-transparent"></div>
<div class="relative overflow-hidden rounded-[2.5rem] bg-gradient-to-br from-slate-900 to-slate-950 px-8 py-16 text-center text-white sm:px-16 sm:py-24 dark:from-primary/20 dark:to-primary/5 dark:text-foreground">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_center,_var(--tw-gradient-from)_0%,_transparent_70%)] from-primary/10 to-transparent opacity-50"></div>
<div class="relative z-10 mx-auto max-w-3xl space-y-8">
<h2 class="text-4xl font-bold tracking-tight sm:text-6xl">{t("home.final.title")}</h2>
<p class="text-lg text-white/70 sm:text-xl dark:text-muted-foreground">{t("home.final.description")}</p>

View File

@@ -45,12 +45,13 @@ const keyFacts = [
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen">
<div class="relative">
{/* 统一的页面背景装饰 */}
<div class="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_var(--tw-gradient-from)_0%,_transparent_25%)] from-primary/5 to-transparent"></div>
<section class="relative flex min-h-[90vh] items-center overflow-hidden py-24 lg:py-32">
<div class="page-hero-overlay opacity-50"></div>
<div class="relative overflow-hidden">
<div class="absolute inset-0 -z-10">
<div class="absolute left-1/2 top-0 h-[600px] w-[800px] -translate-x-1/2 -translate-y-1/2 bg-primary/10 blur-[120px]"></div>
<div class="absolute right-0 top-1/4 h-[400px] w-[400px] bg-purple-500/5 blur-[100px]"></div>
<div class="absolute left-0 top-1/2 h-[400px] w-[400px] bg-orange-500/5 blur-[100px]"></div>
</div>
<section class="relative flex min-h-[90vh] items-center py-24 lg:py-32">
<Container className="relative z-10">
<div class="mx-auto max-w-5xl space-y-16">
<div class="space-y-8 text-center">
@@ -85,8 +86,8 @@ const keyFacts = [
<div class="mx-auto max-w-3xl">
<div class="group relative">
<div class="absolute -inset-1 rounded-2xl bg-gradient-to-r from-primary/20 to-purple-500/20 opacity-50 blur transition duration-1000 group-hover:opacity-100 group-hover:duration-200"></div>
<div class="page-surface relative overflow-hidden rounded-2xl border bg-card/80 backdrop-blur-md">
<div class="flex items-center justify-between border-b border-border/50 bg-muted/30 px-5 py-3">
<div class="page-surface relative overflow-hidden rounded-2xl border bg-card/40 backdrop-blur-md">
<div class="flex items-center justify-between border-b border-border/50 bg-muted/20 px-5 py-3">
<div class="flex items-center gap-2">
<span class="h-3 w-3 rounded-full bg-red-400/80 shadow-[0_0_8px_rgba(248,113,113,0.4)]"></span>
<span class="h-3 w-3 rounded-full bg-yellow-400/80 shadow-[0_0_8px_rgba(250,204,21,0.4)]"></span>
@@ -124,42 +125,44 @@ const keyFacts = [
</section>
<div class="space-y-40 pb-40">
<section class="relative pt-16 lg:pt-24">
<Container>
<div class="mb-16 flex flex-col gap-6 md:flex-row md:items-end md:justify-between">
<div class="space-y-4">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">{t("home.services.title")}</h2>
<p class="max-w-2xl text-lg leading-relaxed text-muted-foreground/90">{t("home.services.description")}</p>
<section class="relative">
<div class="py-24 lg:py-32">
<Container>
<div class="mb-16 flex flex-col gap-6 md:flex-row md:items-end md:justify-between">
<div class="space-y-4">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">{t("home.services.title")}</h2>
<p class="max-w-2xl text-lg leading-relaxed text-muted-foreground/90">{t("home.services.description")}</p>
</div>
<a href={`${prefix}/services`} class="inline-flex items-center text-sm font-bold text-primary transition-colors hover:text-primary/70">
{t("services.viewAll")}
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg>
</a>
</div>
<a href={`${prefix}/services`} class="inline-flex items-center text-sm font-bold text-primary transition-colors hover:text-primary/70">
{t("services.viewAll")}
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg>
</a>
</div>
<div class="grid gap-10 md:grid-cols-2">
{localizedServices.map((service) => (
<article class="group relative p-4 transition-all duration-500 hover:-translate-y-1">
<div class="mb-8 flex items-center gap-6">
<div class={`flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br ${service.icon.gradient} text-white shadow-lg transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3`}>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<Fragment set:html={service.icon.svg} />
</svg>
<div class="grid gap-10 md:grid-cols-2">
{localizedServices.map((service) => (
<article class="group relative rounded-3xl p-6 transition-all duration-500 hover:bg-card/50 hover:shadow-xl hover:shadow-primary/5">
<div class="mb-8 flex items-center gap-6">
<div class={`flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br ${service.icon.gradient} text-white shadow-lg transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3`}>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<Fragment set:html={service.icon.svg} />
</svg>
</div>
<h3 class="text-2xl font-bold tracking-tight">{service.title}</h3>
</div>
<h3 class="text-2xl font-bold tracking-tight">{service.title}</h3>
</div>
<ul class="space-y-4">
{service.items.slice(0, 3).map((item) => (
<li class="flex items-start gap-3 text-muted-foreground group-hover:text-foreground/90 transition-colors">
<span class="mt-2.5 h-1 w-1 shrink-0 rounded-full bg-primary/30 group-hover:bg-primary transition-all"></span>
<span class="text-base leading-relaxed">{item}</span>
</li>
))}
</ul>
</article>
))}
</div>
</Container>
<ul class="space-y-4">
{service.items.slice(0, 3).map((item) => (
<li class="flex items-start gap-3 text-muted-foreground group-hover:text-foreground/90 transition-colors">
<span class="mt-2.5 h-1 w-1 shrink-0 rounded-full bg-primary/30 group-hover:bg-primary transition-all"></span>
<span class="text-base leading-relaxed">{item}</span>
</li>
))}
</ul>
</article>
))}
</div>
</Container>
</div>
</section>
<section class="relative">
@@ -177,7 +180,7 @@ const keyFacts = [
<div class={`relative flex flex-col sm:flex-row ${index % 2 === 0 ? 'sm:flex-row-reverse' : ''}`}>
<div class="absolute -left-1.5 top-2 h-3 w-3 rounded-full border-2 border-primary bg-background sm:left-1/2 sm:-ml-1.5"></div>
<div class="w-full pl-8 sm:w-1/2 sm:px-12">
<article class="p-2 transition-all">
<article class="rounded-2xl p-4 transition-all hover:bg-card/40">
<span class="text-xs font-bold uppercase tracking-wider text-primary/60">{item.period}</span>
<h3 class="mt-2 text-xl font-bold leading-tight">{item.title}</h3>
<p class="mt-3 text-sm leading-relaxed text-muted-foreground/90">{item.outcome}</p>
@@ -197,66 +200,68 @@ const keyFacts = [
</section>
<section class="relative">
<Container>
<div class="mb-12 space-y-3 text-center">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.featured.title")}</h2>
</div>
<div class="py-24 lg:py-32">
<Container>
<div class="mb-12 space-y-3 text-center">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.featured.title")}</h2>
</div>
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{featuredProjects.map((project) => (
<article class="group flex flex-col overflow-hidden rounded-3xl border border-border/50 bg-card/50 backdrop-blur-sm transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/5">
{/* 顶部封面图区域 */}
<div class="relative aspect-video overflow-hidden">
<div class={`absolute inset-0 bg-gradient-to-br ${project.image?.bg || 'from-primary/20 to-purple-500/20'} transition-transform duration-700 group-hover:scale-110`}></div>
<div class="absolute inset-0 flex items-center justify-center">
<span class="text-6xl transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3">{project.icon}</span>
</div>
<div class="absolute top-4 right-4">
<span class="rounded-full bg-background/80 px-3 py-1 text-[10px] font-bold uppercase tracking-wider text-foreground backdrop-blur-md">
{project.type}
</span>
</div>
</div>
{/* 内容区域 */}
<div class="flex flex-1 flex-col p-6 lg:p-8">
<div class="flex-1 space-y-4">
<h3 class="text-2xl font-bold tracking-tight">{project.title}</h3>
<p class="line-clamp-2 text-sm leading-relaxed text-muted-foreground">
{project.impact}
</p>
<div class="flex flex-wrap gap-2">
{project.tech.map((tech) => (
<span class="rounded-md bg-primary/5 px-2 py-1 text-[10px] font-medium text-primary/80">
{tech}
</span>
))}
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{featuredProjects.map((project) => (
<article class="group flex flex-col overflow-hidden rounded-3xl border border-border/50 bg-card/50 backdrop-blur-sm transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/5">
{/* 顶部封面图区域 */}
<div class="relative aspect-video overflow-hidden">
<div class={`absolute inset-0 bg-gradient-to-br ${project.image?.bg || 'from-primary/20 to-purple-500/20'} transition-transform duration-700 group-hover:scale-110`}></div>
<div class="absolute inset-0 flex items-center justify-center">
<span class="text-6xl transition-transform duration-500 group-hover:scale-110 group-hover:rotate-3">{project.icon}</span>
</div>
<div class="absolute top-4 right-4">
<span class="rounded-full bg-background/80 px-3 py-1 text-[10px] font-bold uppercase tracking-wider text-foreground backdrop-blur-md">
{project.type}
</span>
</div>
</div>
{/* 操作按钮 */}
<div class="mt-8 flex items-center justify-between gap-4">
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center justify-center rounded-full bg-primary px-6 text-xs font-bold text-primary-foreground transition-all hover:bg-primary/90">
{t("home.featured.ctaPrimary")}
</a>
{project.links?.github && (
<a href={project.links.github} target="_blank" rel="noopener noreferrer" class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background/50 text-muted-foreground transition-all hover:bg-muted hover:text-foreground">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 4.125 9.642 9.807 11.53 0.6.111 0.799-0.26 0.799-0.577 0-0.285-0.011-1.04-0.017-2.042-3.338 0.727-4.042-1.61-4.042-1.61-0.546-1.387-1.333-1.756-1.333-1.756-1.089-0.745 0.083-0.729 0.083-0.729 1.205 0.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492 0.997 0.107-0.775 0.418-1.305 0.762-1.604-2.665-0.305-5.467-1.334-5.467-5.931 0-1.311 0.469-2.381 1.236-3.221-0.124-0.303-0.535-1.524 0.117-3.176 0 0 1.008-0.322 3.301 1.23 0.96-0.267 1.98-0.399 3-0.405 1.02 0.006 2.04 0.138 3 0.405 2.28-1.552 3.285-1.23 3.285-1.23 0.654 1.653 0.242 2.874 0.118 3.176 0.77 0.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921 0.43 0.372 0.823 1.102 0.823 2.222 0 1.606-0.014 2.898-0.014 3.293 0 0.319 0.192 0.694 0.801 0.576 5.687-1.889 9.812-6.228 9.812-11.53 0-6.627-5.373-12-12-12z"/></svg>
{/* 内容区域 */}
<div class="flex flex-1 flex-col p-6 lg:p-8">
<div class="flex-1 space-y-4">
<h3 class="text-2xl font-bold tracking-tight">{project.title}</h3>
<p class="line-clamp-2 text-sm leading-relaxed text-muted-foreground">
{project.impact}
</p>
<div class="flex flex-wrap gap-2">
{project.tech.map((tech) => (
<span class="rounded-md bg-primary/5 px-2 py-1 text-[10px] font-medium text-primary/80">
{tech}
</span>
))}
</div>
</div>
{/* 操作按钮 */}
<div class="mt-8 flex items-center justify-between gap-4">
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center justify-center rounded-full bg-primary px-6 text-xs font-bold text-primary-foreground transition-all hover:bg-primary/90">
{t("home.featured.ctaPrimary")}
</a>
)}
{project.links?.github && (
<a href={project.links.github} target="_blank" rel="noopener noreferrer" class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background/50 text-muted-foreground transition-all hover:bg-muted hover:text-foreground">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 4.125 9.642 9.807 11.53 0.6.111 0.799-0.26 0.799-0.577 0-0.285-0.011-1.04-0.017-2.042-3.338 0.727-4.042-1.61-4.042-1.61-0.546-1.387-1.333-1.756-1.333-1.756-1.089-0.745 0.083-0.729 0.083-0.729 1.205 0.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492 0.997 0.107-0.775 0.418-1.305 0.762-1.604-2.665-0.305-5.467-1.334-5.467-5.931 0-1.311 0.469-2.381 1.236-3.221-0.124-0.303-0.535-1.524 0.117-3.176 0 0 1.008-0.322 3.301 1.23 0.96-0.267 1.98-0.399 3-0.405 1.02 0.006 2.04 0.138 3 0.405 2.28-1.552 3.285-1.23 3.285-1.23 0.654 1.653 0.242 2.874 0.118 3.176 0.77 0.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921 0.43 0.372 0.823 1.102 0.823 2.222 0 1.606-0.014 2.898-0.014 3.293 0 0.319 0.192 0.694 0.801 0.576 5.687-1.889 9.812-6.228 9.812-11.53 0-6.627-5.373-12-12-12z"/></svg>
</a>
)}
</div>
</div>
</div>
</article>
))}
</div>
</Container>
</article>
))}
</div>
</Container>
</div>
</section>
<section class="relative">
<Container>
<div class="relative overflow-hidden rounded-[2.5rem] bg-slate-950 px-8 py-16 text-center text-white sm:px-16 sm:py-24 dark:bg-primary/10 dark:text-foreground">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_center,_var(--tw-gradient-from)_0%,_transparent_70%)] from-primary/20 to-transparent"></div>
<div class="relative overflow-hidden rounded-[2.5rem] bg-gradient-to-br from-slate-900 to-slate-950 px-8 py-16 text-center text-white sm:px-16 sm:py-24 dark:from-primary/20 dark:to-primary/5 dark:text-foreground">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_center,_var(--tw-gradient-from)_0%,_transparent_70%)] from-primary/10 to-transparent opacity-50"></div>
<div class="relative z-10 mx-auto max-w-3xl space-y-8">
<h2 class="text-4xl font-bold tracking-tight sm:text-6xl">{t("home.final.title")}</h2>
<p class="text-lg text-white/70 sm:text-xl dark:text-muted-foreground">{t("home.final.description")}</p>