feat(home): redesign homepage with refined visuals and improved layout flow

- Enhanced hero section with updated typography, animations, and gradient backgrounds.
- Replaced single featured project with dynamic multi-project filtering.
- Improved section transitions and added cohesive hover effects for interactivity.
- Updated CSS variables for softer background colors and unified design language.
- Added responsive refinements for better experience across devices.
This commit is contained in:
zguiyang
2026-03-14 11:17:02 +08:00
parent a85e9f57ba
commit 9c6b7fd698
3 changed files with 399 additions and 311 deletions

View File

@@ -14,7 +14,7 @@ const pageTitle = t("site.title");
const prefix = lang === "zh" ? "/zh" : "";
const localizedServices = services[lang];
const featuredProject = projects[lang].find((project) => project.featured) ?? projects[lang][0];
const featuredProjects = projects[lang].filter((project) => project.featured);
const careerMilestones = [
{
@@ -44,58 +44,78 @@ const keyFacts = [
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen pb-20">
<section class="relative flex min-h-[88vh] items-center overflow-hidden py-20 lg:py-24">
<div class="page-hero-overlay"></div>
<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>
<Container className="relative z-10">
<div class="space-y-10">
<div class="page-content-narrow text-center">
<div class="space-y-5">
<p class="text-xs font-medium uppercase tracking-[0.22em] text-primary/80">{t("home.hero.eyebrow")}</p>
<h1 class="text-5xl font-semibold tracking-tight sm:text-6xl lg:text-7xl">{personalInfo.name}</h1>
<p class="text-xl text-foreground/85 sm:text-2xl">{personalInfo.position[lang]}</p>
<p class="mx-auto max-w-3xl text-lg leading-relaxed text-muted-foreground">{t("home.hero.summary")}</p>
<div class="mx-auto max-w-5xl space-y-16">
<div class="space-y-8 text-center">
<div class="space-y-4">
<h1 class="text-5xl font-bold tracking-tight sm:text-7xl lg:text-8xl">
<span class="bg-gradient-to-b from-foreground to-foreground/70 bg-clip-text text-transparent">{personalInfo.name}</span>
</h1>
<p class="text-2xl font-medium text-foreground/80 sm:text-3xl">{personalInfo.position[lang]}</p>
</div>
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
<a href={`${prefix}/about`} class="inline-flex h-11 items-center justify-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90">
<p class="mx-auto max-w-2xl text-lg leading-relaxed text-muted-foreground/90 sm:text-xl">{t("home.hero.summary")}</p>
<div class="flex flex-wrap items-center justify-center gap-4">
<a href={`${prefix}/about`} class="inline-flex h-12 items-center justify-center rounded-full bg-primary px-8 text-sm font-semibold text-primary-foreground shadow-lg shadow-primary/20 transition-all hover:translate-y-[-2px] hover:bg-primary/90 hover:shadow-xl hover:shadow-primary/30">
{t("home.hero.ctaPrimary")}
</a>
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center justify-center rounded-lg border border-border bg-background px-6 text-sm font-medium text-foreground hover:bg-muted">
<a href={`${prefix}/hire`} class="inline-flex h-12 items-center justify-center rounded-full border border-border bg-background/50 px-8 text-sm font-semibold text-foreground backdrop-blur-sm transition-all hover:translate-y-[-2px] hover:bg-muted">
{t("home.hero.ctaSecondary")}
</a>
</div>
<div class="mt-6 flex flex-wrap items-center justify-center gap-2 text-sm text-muted-foreground">
<div class="flex flex-wrap items-center justify-center gap-3 text-sm">
{keyFacts.map((item) => (
<span class="inline-flex items-center rounded-full border border-border/60 bg-card/60 px-3 py-1">
<span class="inline-flex items-center rounded-full border border-primary/10 bg-primary/5 px-4 py-1.5 font-medium text-primary/80 backdrop-blur-sm">
<span class="mr-2 h-1 w-1 rounded-full bg-primary/50"></span>
{item}
</span>
))}
</div>
</div>
<div class="page-content-main">
<div class="page-surface overflow-hidden rounded-2xl border">
<div class="flex items-center justify-between border-b border-border/70 bg-card/70 px-4 py-3">
<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="flex items-center gap-2">
<span class="h-2.5 w-2.5 rounded-full bg-red-400"></span>
<span class="h-2.5 w-2.5 rounded-full bg-yellow-400"></span>
<span class="h-2.5 w-2.5 rounded-full bg-green-400"></span>
<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>
<span class="h-3 w-3 rounded-full bg-green-400/80 shadow-[0_0_8px_rgba(74,222,128,0.4)]"></span>
</div>
<span class="font-mono text-xs font-medium text-muted-foreground/70 tracking-tight">{personalInfo.terminal.username}</span>
</div>
<div class="space-y-3 p-6 font-mono text-sm leading-relaxed text-foreground/90">
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">whoami</span> {personalInfo.name}</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">role</span> {personalInfo.position[lang]}</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">stack</span> TypeScript, React, Node.js, Astro</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">status</span> {t("home.hero.terminalStatus")}</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">contact</span> {personalInfo.github}</p>
</div>
<span class="font-mono text-xs text-muted-foreground">{personalInfo.terminal.username}</span>
</div>
<div class="space-y-2 p-5 font-mono text-xs leading-6 text-foreground/85 sm:text-sm">
<p><span class="text-primary">$</span> whoami</p>
<p class="pl-4 text-primary/90">{personalInfo.name}</p>
<p><span class="text-primary">$</span> role</p>
<p class="pl-4">{personalInfo.position[lang]}</p>
<p><span class="text-primary">$</span> stack</p>
<p class="pl-4">TypeScript, React, Node.js, Astro</p>
<p><span class="text-primary">$</span> status</p>
<p class="pl-4">{t("home.hero.terminalStatus")}</p>
<p><span class="text-primary">$</span> contact</p>
<p class="pl-4 text-primary/90">{personalInfo.github}</p>
</div>
</div>
</div>
@@ -103,33 +123,36 @@ const keyFacts = [
</Container>
</section>
<section class="py-16">
<div class="space-y-40 pb-40">
<section class="relative pt-16 lg:pt-24">
<Container>
<div class="mb-10 flex items-end justify-between gap-4">
<div class="space-y-2">
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.services.eyebrow")}</p>
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.services.title")}</h2>
<p class="text-muted-foreground">{t("home.services.description")}</p>
<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="hidden text-sm font-medium text-primary hover:text-primary/80 sm:inline-flex">{t("services.viewAll")}</a>
<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-6 md:grid-cols-2">
<div class="grid gap-10 md:grid-cols-2">
{localizedServices.map((service) => (
<article class="page-surface rounded-2xl border p-6 sm:p-8">
<div class="mb-5 flex items-center gap-4">
<div class={`flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-br ${service.icon.gradient} text-white`}>
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<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>
<h3 class="text-xl font-semibold tracking-tight">{service.title}</h3>
<h3 class="text-2xl font-bold tracking-tight">{service.title}</h3>
</div>
<ul class="space-y-2 text-sm text-muted-foreground">
<ul class="space-y-4">
{service.items.slice(0, 3).map((item) => (
<li class="flex gap-2">
<span class="mt-1 h-1.5 w-1.5 shrink-0 rounded-full bg-primary/70"></span>
<span>{item}</span>
<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>
@@ -139,97 +162,118 @@ const keyFacts = [
</Container>
</section>
<section class="py-16 page-section-soft">
<section class="relative">
<Container>
<div class="mb-10 space-y-2">
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.career.eyebrow")}</p>
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.career.title")}</h2>
<p class="text-muted-foreground">{t("home.career.description")}</p>
<div class="mb-16 space-y-3">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.career.title")}</h2>
<p class="max-w-xl text-lg text-muted-foreground">{t("home.career.description")}</p>
</div>
<div class="page-content-main relative ml-2 border-l border-border/70 pl-6 sm:ml-4 sm:pl-8">
{careerMilestones.map((item) => (
<div class="relative mb-6 last:mb-0">
<span class="absolute -left-[2.1rem] top-2 h-3.5 w-3.5 rounded-full border-2 border-primary/40 bg-background sm:-left-[2.65rem]"></span>
<article class="page-surface rounded-xl border p-5">
<p class="text-xs font-medium uppercase tracking-[0.14em] text-primary/80">{item.period}</p>
<h3 class="mt-3 text-base font-semibold leading-6">{item.title}</h3>
<p class="mt-3 text-sm leading-6 text-muted-foreground">{item.outcome}</p>
<div class="relative mx-auto max-w-4xl">
<div class="absolute left-0 top-0 h-full w-px bg-gradient-to-b from-primary/50 via-primary/10 to-transparent sm:left-1/2"></div>
<div class="space-y-12">
{careerMilestones.map((item, index) => (
<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">
<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>
</article>
</div>
</div>
))}
</div>
</div>
<div class="mt-8">
<a href={`${prefix}/about`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
<div class="mt-16 text-center">
<a href={`${prefix}/about`} class="inline-flex h-12 items-center rounded-full border border-border bg-background px-8 text-sm font-semibold transition-all hover:bg-muted">
{t("home.career.cta")}
</a>
</div>
</Container>
</section>
<section class="py-16">
<section class="relative">
<Container>
<div class="mb-8 space-y-2">
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.featured.eyebrow")}</p>
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.featured.title")}</h2>
<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>
<article class="page-surface rounded-2xl border p-6 sm:p-8">
<div class="flex flex-wrap items-center gap-3">
<span class="rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs font-medium text-primary">{t("project.featured")}</span>
<h3 class="text-2xl font-semibold">{featuredProject.title}</h3>
<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="mt-6 grid gap-6 lg:grid-cols-3">
<div>
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.challenge")}</p>
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.impact}</p>
</div>
<div>
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.approach")}</p>
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[0]}</p>
</div>
<div>
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.outcome")}</p>
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[1]}</p>
<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-6 flex flex-wrap gap-2">
{featuredProject.tech.slice(0, 4).map((tech) => (
<span class="rounded-md border border-border/70 bg-muted/50 px-2.5 py-1 text-xs text-muted-foreground">{tech}</span>
{/* 内容区域 */}
<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 flex-wrap gap-3">
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center rounded-md bg-primary px-5 text-sm font-medium text-primary-foreground hover:bg-primary/90">
{/* 操作按钮 */}
<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>
<a href={`${prefix}/hire`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
{t("home.featured.ctaSecondary")}
{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>
</article>
))}
</div>
</Container>
</section>
<section class="py-16">
<section class="relative">
<Container>
<div class="page-surface rounded-2xl border px-6 py-10 text-center sm:px-10">
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.final.title")}</h2>
<p class="mx-auto mt-4 max-w-2xl text-muted-foreground">{t("home.final.description")}</p>
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
<a href={`${prefix}/about`} class="inline-flex h-11 items-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground hover:bg-primary/90">
<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 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>
<div class="flex flex-wrap items-center justify-center gap-4 pt-4">
<a href={`${prefix}/about`} class="inline-flex h-14 items-center rounded-full bg-white px-10 text-sm font-bold text-slate-950 transition-all hover:bg-white/90 dark:bg-primary dark:text-primary-foreground">
{t("home.final.ctaPrimary")}
</a>
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center rounded-lg border border-border bg-background px-6 text-sm font-medium hover:bg-muted">
<a href={`${prefix}/hire`} class="inline-flex h-14 items-center rounded-full border border-white/20 bg-transparent px-10 text-sm font-bold text-white transition-all hover:bg-white/10 dark:border-primary/20 dark:text-foreground">
{t("home.final.ctaSecondary")}
</a>
</div>
</div>
</div>
</Container>
</section>
</div>
</div>
</main>
<Footer lang={lang} client:only="react" />

View File

@@ -14,7 +14,7 @@ const pageTitle = t("site.title");
const prefix = lang === "zh" ? "/zh" : "";
const localizedServices = services[lang];
const featuredProject = projects[lang].find((project) => project.featured) ?? projects[lang][0];
const featuredProjects = projects[lang].filter((project) => project.featured);
const careerMilestones = [
{
@@ -44,58 +44,78 @@ const keyFacts = [
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen pb-20">
<section class="relative flex min-h-[88vh] items-center overflow-hidden py-20 lg:py-24">
<div class="page-hero-overlay"></div>
<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>
<Container className="relative z-10">
<div class="space-y-10">
<div class="page-content-narrow text-center">
<div class="space-y-5">
<p class="text-xs font-medium uppercase tracking-[0.22em] text-primary/80">{t("home.hero.eyebrow")}</p>
<h1 class="text-5xl font-semibold tracking-tight sm:text-6xl lg:text-7xl">{personalInfo.name}</h1>
<p class="text-xl text-foreground/85 sm:text-2xl">{personalInfo.position[lang]}</p>
<p class="mx-auto max-w-3xl text-lg leading-relaxed text-muted-foreground">{t("home.hero.summary")}</p>
<div class="mx-auto max-w-5xl space-y-16">
<div class="space-y-8 text-center">
<div class="space-y-4">
<h1 class="text-5xl font-bold tracking-tight sm:text-7xl lg:text-8xl">
<span class="bg-gradient-to-b from-foreground to-foreground/70 bg-clip-text text-transparent">{personalInfo.name}</span>
</h1>
<p class="text-2xl font-medium text-foreground/80 sm:text-3xl">{personalInfo.position[lang]}</p>
</div>
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
<a href={`${prefix}/about`} class="inline-flex h-11 items-center justify-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90">
<p class="mx-auto max-w-2xl text-lg leading-relaxed text-muted-foreground/90 sm:text-xl">{t("home.hero.summary")}</p>
<div class="flex flex-wrap items-center justify-center gap-4">
<a href={`${prefix}/about`} class="inline-flex h-12 items-center justify-center rounded-full bg-primary px-8 text-sm font-semibold text-primary-foreground shadow-lg shadow-primary/20 transition-all hover:translate-y-[-2px] hover:bg-primary/90 hover:shadow-xl hover:shadow-primary/30">
{t("home.hero.ctaPrimary")}
</a>
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center justify-center rounded-lg border border-border bg-background px-6 text-sm font-medium text-foreground hover:bg-muted">
<a href={`${prefix}/hire`} class="inline-flex h-12 items-center justify-center rounded-full border border-border bg-background/50 px-8 text-sm font-semibold text-foreground backdrop-blur-sm transition-all hover:translate-y-[-2px] hover:bg-muted">
{t("home.hero.ctaSecondary")}
</a>
</div>
<div class="mt-6 flex flex-wrap items-center justify-center gap-2 text-sm text-muted-foreground">
<div class="flex flex-wrap items-center justify-center gap-3 text-sm">
{keyFacts.map((item) => (
<span class="inline-flex items-center rounded-full border border-border/60 bg-card/60 px-3 py-1">
<span class="inline-flex items-center rounded-full border border-primary/10 bg-primary/5 px-4 py-1.5 font-medium text-primary/80 backdrop-blur-sm">
<span class="mr-2 h-1 w-1 rounded-full bg-primary/50"></span>
{item}
</span>
))}
</div>
</div>
<div class="page-content-main">
<div class="page-surface overflow-hidden rounded-2xl border">
<div class="flex items-center justify-between border-b border-border/70 bg-card/70 px-4 py-3">
<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="flex items-center gap-2">
<span class="h-2.5 w-2.5 rounded-full bg-red-400"></span>
<span class="h-2.5 w-2.5 rounded-full bg-yellow-400"></span>
<span class="h-2.5 w-2.5 rounded-full bg-green-400"></span>
<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>
<span class="h-3 w-3 rounded-full bg-green-400/80 shadow-[0_0_8px_rgba(74,222,128,0.4)]"></span>
</div>
<span class="font-mono text-xs font-medium text-muted-foreground/70 tracking-tight">{personalInfo.terminal.username}</span>
</div>
<div class="space-y-3 p-6 font-mono text-sm leading-relaxed text-foreground/90">
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">whoami</span> {personalInfo.name}</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">role</span> {personalInfo.position[lang]}</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">stack</span> TypeScript, React, Node.js, Astro</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">status</span> {t("home.hero.terminalStatus")}</p>
</div>
<div class="flex gap-3">
<span class="text-primary font-bold">~</span>
<p><span class="text-primary/70">contact</span> {personalInfo.github}</p>
</div>
<span class="font-mono text-xs text-muted-foreground">{personalInfo.terminal.username}</span>
</div>
<div class="space-y-2 p-5 font-mono text-xs leading-6 text-foreground/85 sm:text-sm">
<p><span class="text-primary">$</span> whoami</p>
<p class="pl-4 text-primary/90">{personalInfo.name}</p>
<p><span class="text-primary">$</span> role</p>
<p class="pl-4">{personalInfo.position[lang]}</p>
<p><span class="text-primary">$</span> stack</p>
<p class="pl-4">TypeScript, React, Node.js, Astro</p>
<p><span class="text-primary">$</span> status</p>
<p class="pl-4">{t("home.hero.terminalStatus")}</p>
<p><span class="text-primary">$</span> contact</p>
<p class="pl-4 text-primary/90">{personalInfo.github}</p>
</div>
</div>
</div>
@@ -103,33 +123,36 @@ const keyFacts = [
</Container>
</section>
<section class="py-16">
<div class="space-y-40 pb-40">
<section class="relative pt-16 lg:pt-24">
<Container>
<div class="mb-10 flex items-end justify-between gap-4">
<div class="space-y-2">
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.services.eyebrow")}</p>
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.services.title")}</h2>
<p class="text-muted-foreground">{t("home.services.description")}</p>
<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="hidden text-sm font-medium text-primary hover:text-primary/80 sm:inline-flex">{t("services.viewAll")}</a>
<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-6 md:grid-cols-2">
<div class="grid gap-10 md:grid-cols-2">
{localizedServices.map((service) => (
<article class="page-surface rounded-2xl border p-6 sm:p-8">
<div class="mb-5 flex items-center gap-4">
<div class={`flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-br ${service.icon.gradient} text-white`}>
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<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>
<h3 class="text-xl font-semibold tracking-tight">{service.title}</h3>
<h3 class="text-2xl font-bold tracking-tight">{service.title}</h3>
</div>
<ul class="space-y-2 text-sm text-muted-foreground">
<ul class="space-y-4">
{service.items.slice(0, 3).map((item) => (
<li class="flex gap-2">
<span class="mt-1 h-1.5 w-1.5 shrink-0 rounded-full bg-primary/70"></span>
<span>{item}</span>
<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>
@@ -139,97 +162,118 @@ const keyFacts = [
</Container>
</section>
<section class="py-16 page-section-soft">
<section class="relative">
<Container>
<div class="mb-10 space-y-2">
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.career.eyebrow")}</p>
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.career.title")}</h2>
<p class="text-muted-foreground">{t("home.career.description")}</p>
<div class="mb-16 space-y-3">
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.career.title")}</h2>
<p class="max-w-xl text-lg text-muted-foreground">{t("home.career.description")}</p>
</div>
<div class="page-content-main relative ml-2 border-l border-border/70 pl-6 sm:ml-4 sm:pl-8">
{careerMilestones.map((item) => (
<div class="relative mb-6 last:mb-0">
<span class="absolute -left-[2.1rem] top-2 h-3.5 w-3.5 rounded-full border-2 border-primary/40 bg-background sm:-left-[2.65rem]"></span>
<article class="page-surface rounded-xl border p-5">
<p class="text-xs font-medium uppercase tracking-[0.14em] text-primary/80">{item.period}</p>
<h3 class="mt-3 text-base font-semibold leading-6">{item.title}</h3>
<p class="mt-3 text-sm leading-6 text-muted-foreground">{item.outcome}</p>
<div class="relative mx-auto max-w-4xl">
<div class="absolute left-0 top-0 h-full w-px bg-gradient-to-b from-primary/50 via-primary/10 to-transparent sm:left-1/2"></div>
<div class="space-y-12">
{careerMilestones.map((item, index) => (
<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">
<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>
</article>
</div>
</div>
))}
</div>
</div>
<div class="mt-8">
<a href={`${prefix}/about`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
<div class="mt-16 text-center">
<a href={`${prefix}/about`} class="inline-flex h-12 items-center rounded-full border border-border bg-background px-8 text-sm font-semibold transition-all hover:bg-muted">
{t("home.career.cta")}
</a>
</div>
</Container>
</section>
<section class="py-16">
<section class="relative">
<Container>
<div class="mb-8 space-y-2">
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.featured.eyebrow")}</p>
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.featured.title")}</h2>
<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>
<article class="page-surface rounded-2xl border p-6 sm:p-8">
<div class="flex flex-wrap items-center gap-3">
<span class="rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs font-medium text-primary">{t("project.featured")}</span>
<h3 class="text-2xl font-semibold">{featuredProject.title}</h3>
<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="mt-6 grid gap-6 lg:grid-cols-3">
<div>
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.challenge")}</p>
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.impact}</p>
</div>
<div>
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.approach")}</p>
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[0]}</p>
</div>
<div>
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.outcome")}</p>
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[1]}</p>
<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-6 flex flex-wrap gap-2">
{featuredProject.tech.slice(0, 4).map((tech) => (
<span class="rounded-md border border-border/70 bg-muted/50 px-2.5 py-1 text-xs text-muted-foreground">{tech}</span>
{/* 内容区域 */}
<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 flex-wrap gap-3">
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center rounded-md bg-primary px-5 text-sm font-medium text-primary-foreground hover:bg-primary/90">
{/* 操作按钮 */}
<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>
<a href={`${prefix}/hire`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
{t("home.featured.ctaSecondary")}
{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>
</article>
))}
</div>
</Container>
</section>
<section class="py-16">
<section class="relative">
<Container>
<div class="page-surface rounded-2xl border px-6 py-10 text-center sm:px-10">
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.final.title")}</h2>
<p class="mx-auto mt-4 max-w-2xl text-muted-foreground">{t("home.final.description")}</p>
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
<a href={`${prefix}/about`} class="inline-flex h-11 items-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground hover:bg-primary/90">
<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 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>
<div class="flex flex-wrap items-center justify-center gap-4 pt-4">
<a href={`${prefix}/about`} class="inline-flex h-14 items-center rounded-full bg-white px-10 text-sm font-bold text-slate-950 transition-all hover:bg-white/90 dark:bg-primary dark:text-primary-foreground">
{t("home.final.ctaPrimary")}
</a>
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center rounded-lg border border-border bg-background px-6 text-sm font-medium hover:bg-muted">
<a href={`${prefix}/hire`} class="inline-flex h-14 items-center rounded-full border border-white/20 bg-transparent px-10 text-sm font-bold text-white transition-all hover:bg-white/10 dark:border-primary/20 dark:text-foreground">
{t("home.final.ctaSecondary")}
</a>
</div>
</div>
</div>
</Container>
</section>
</div>
</div>
</main>
<Footer lang={lang} client:only="react" />

View File

@@ -44,7 +44,7 @@
:root {
--radius: 0.75rem;
--background: #F8FAFC;
--background: #F1F5F9; /* 更柔和的蓝灰色,不再是纯白或过于扎眼的浅色 */
--foreground: #1E293B;
--card: #FFFFFF;
--card-foreground: #1E293B;