redesign(homepage): elegant editorial redesign with scroll animations

- HeroSection: full-viewport split layout with staggered entrance animations,
  editorial typography, tech stack tags, animated scroll indicator
- WorksSection: refined header with section label, scroll-reveal on entry
- ProjectCard: per-card IntersectionObserver reveal, numbered projects,
  enhanced hover states (scale + brightness), improved CTA
- FeatureSection: card grid with border/glass treatment and staggered reveals
- AboutSection: animated timeline progress line, scroll-triggered card entrances
- FeatureColumn: icon container with hover treatment
- globals.css: fadeUp/lineGrow/arrowBounce keyframes, .reveal utility,
  prefers-reduced-motion support, brand-accent color token
- lib/useReveal.ts: IntersectionObserver hook for scroll reveals

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 08:39:54 +02:00
parent b717abb7de
commit 87efea3cc1
9 changed files with 600 additions and 178 deletions
+51 -2
View File
@@ -3,11 +3,60 @@
@theme {
--color-brand-brown: #2C1E16;
--color-brand-beige: #F5F4F0;
--font-sans: var(--font-inter);
--color-brand-accent: #8B7355;
--font-sans: var(--font-inter);
--font-serif: var(--font-playfair);
}
@keyframes fadeUp {
from { opacity: 0; transform: translateY(28px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes lineGrow {
from { width: 0%; }
to { width: 95%; }
}
@keyframes arrowBounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(6px); }
}
@keyframes underlineSlide {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.reveal {
opacity: 0;
transform: translateY(28px);
transition: opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.reveal {
opacity: 1;
transform: none;
transition: none;
}
.animate-arrow-bounce {
animation: none !important;
}
}
:root {
--background: #ffffff;
--foreground: #171717;
+6 -4
View File
@@ -16,11 +16,13 @@ export default async function Home({ params }: props) {
const projects = getAllProjects().filter((item) => item.ready);
return (
<main className=" bg-brand-beige text-brand-black flex flex-col items-center justify-center">
<main className="bg-brand-beige text-brand-brown flex flex-col">
<HeroSection />
<WorksSection projects={projects} locale={locale} />
<FeatureSection />
<TimelineSection />
<div className="px-8 md:px-14 lg:px-20">
<WorksSection projects={projects} locale={locale} />
<FeatureSection />
<TimelineSection />
</div>
</main>
);
}