- Reduced section spacing and adjusted minimum height for improved visual balance. - Updated card designs, headlines, and typography for better readability and flow. - Simplified styles and reorganized structure for enhanced maintainability. - Refined call-to-action area with improved button styling and responsiveness.
240 lines
12 KiB
Plaintext
240 lines
12 KiB
Plaintext
---
|
|
import Layout from "@/layouts/Layout.astro";
|
|
import GlassHeader from "@/components/GlassHeader";
|
|
import Footer from "@/components/Footer";
|
|
import Container from "@/components/ui/Container.astro";
|
|
import ProjectCard from "@/components/ProjectCard.astro";
|
|
import { useTranslations } from "@/i18n/utils";
|
|
import type { Lang } from "@/types/i18n";
|
|
import { defaultLang } from "@/i18n/ui";
|
|
import { personalInfo, services, projects } from "@/lib/data/index";
|
|
|
|
const lang = (Astro.currentLocale as Lang) || defaultLang;
|
|
const t = useTranslations(lang);
|
|
const pageTitle = t("site.title");
|
|
const prefix = lang === "zh" ? "/zh" : "";
|
|
|
|
const localizedServices = services[lang];
|
|
const featuredProjects = projects[lang].filter((project) => project.featured);
|
|
|
|
const careerMilestones = [
|
|
{
|
|
period: t("home.career.card1.period"),
|
|
title: t("home.career.card1.title"),
|
|
outcome: t("home.career.card1.outcome"),
|
|
},
|
|
{
|
|
period: t("home.career.card2.period"),
|
|
title: t("home.career.card2.title"),
|
|
outcome: t("home.career.card2.outcome"),
|
|
},
|
|
{
|
|
period: t("home.career.card3.period"),
|
|
title: t("home.career.card3.title"),
|
|
outcome: t("home.career.card3.outcome"),
|
|
},
|
|
];
|
|
|
|
const keyFacts = [
|
|
t("home.trust.item1"),
|
|
t("home.trust.item3"),
|
|
t("home.trust.item4"),
|
|
];
|
|
---
|
|
|
|
<Layout title={pageTitle}>
|
|
<GlassHeader client:load transition:persist="header" lang={lang} />
|
|
|
|
<main class="min-h-screen">
|
|
<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-[80vh] items-center py-20 lg:py-28">
|
|
<Container className="relative z-10">
|
|
<div class="mx-auto max-w-5xl space-y-12">
|
|
<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>
|
|
|
|
<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-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>
|
|
|
|
<div class="mx-auto max-w-3xl space-y-8">
|
|
<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-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 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/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>
|
|
<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>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Container>
|
|
</section>
|
|
|
|
<div class="space-y-24 pb-24">
|
|
<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>
|
|
|
|
<div class="grid gap-10 md:grid-cols-2">
|
|
{localizedServices.map((service) => (
|
|
<article class="group relative rounded-2xl 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>
|
|
<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">
|
|
<Container>
|
|
<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="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="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>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<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="relative">
|
|
<div class="py-24 lg:py-32">
|
|
<Container>
|
|
<div class="mb-12 space-y-3">
|
|
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl">{t("home.featured.title")}</h2>
|
|
</div>
|
|
|
|
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
{featuredProjects.map((project) => (
|
|
<ProjectCard project={project} lang={lang} />
|
|
))}
|
|
</div>
|
|
</Container>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="relative">
|
|
<Container>
|
|
<div class="flex flex-col items-center text-center">
|
|
<h2 class="text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl mb-6">{t("home.final.title")}</h2>
|
|
<p class="text-lg leading-relaxed text-muted-foreground/90 sm:text-xl max-w-2xl mb-10">{t("home.final.description")}</p>
|
|
<div class="flex flex-wrap 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 transition-all hover:translate-y-[-2px] hover:bg-primary/90">
|
|
{t("home.final.ctaPrimary")}
|
|
</a>
|
|
<a href={`${prefix}/hire`} class="inline-flex h-12 items-center justify-center rounded-full border border-border px-8 text-sm font-semibold text-foreground transition-all hover:translate-y-[-2px] hover:bg-muted">
|
|
{t("home.final.ctaSecondary")}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</Container>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<Footer lang={lang} client:only="react" />
|
|
</Layout>
|