Compare commits

...

1 Commits

Author SHA1 Message Date
Yolando
c6922c5bea feat: implement base design tokens, global styles, and hero section component 2026-04-11 02:31:36 +07:00
3 changed files with 53 additions and 36 deletions

View File

@@ -22,8 +22,10 @@ export default async function HomePage() {
<HeroSection />
{/* Hero → Experience */}
<ExperienceSection />
<EducationSection />
<div className="section-warm-bg">
<ExperienceSection />
<EducationSection />
</div>
{/* Experience → TechStack (white/dark → muted tint) */}
<div className="bg-background">

View File

@@ -41,6 +41,10 @@
/* Section padding */
--section-py: 6rem;
/* Light mode section tints */
--hero-bg: linear-gradient(135deg, #fafafa 0%, #f0edff 40%, #ede9fe 60%, #f5f3ff 100%);
--section-warm: linear-gradient(180deg, #fafafa 0%, #f8f7ff 50%, #fafafa 100%);
}
.dark {
@@ -64,6 +68,9 @@
--glass-border: rgba(255,255,255,0.08);
--gradient-subtle: linear-gradient(135deg, rgba(99,102,241,0.12) 0%, rgba(168,85,247,0.12) 100%);
--hero-bg: none;
--section-warm: none;
}
/* ========== BASE STYLES ========== */
@@ -134,14 +141,30 @@ body {
z-index: 0;
}
/* Grid pattern background */
/* Grid pattern background - softer dot pattern for light mode */
.grid-pattern {
background-image:
radial-gradient(circle, var(--border) 1px, transparent 1px);
background-size: 32px 32px;
}
.dark .grid-pattern {
background-image:
linear-gradient(var(--border) 1px, transparent 1px),
linear-gradient(90deg, var(--border) 1px, transparent 1px);
background-size: 60px 60px;
}
/* Hero section background */
.hero-gradient-bg {
background: var(--hero-bg);
}
/* Section warm tint for light mode */
.section-warm-bg {
background: var(--section-warm);
}
/* Animated gradient orbs */
@keyframes float {
0%, 100% { transform: translateY(0px) rotate(0deg); }

View File

@@ -2,7 +2,7 @@
import { useState } from "react";
import { motion, PanInfo } from "framer-motion";
import { ArrowDown, FileText, Download, Plus } from "lucide-react";
import { ArrowDown, Download } from "lucide-react";
import { useTranslations } from "next-intl";
const PROFILE_IMAGES = [
@@ -72,17 +72,28 @@ export function HeroSection() {
return (
<section
id="hero"
className="relative min-h-screen flex items-center justify-center overflow-hidden pt-20"
className="relative min-h-screen flex items-center justify-center overflow-hidden pt-20 hero-gradient-bg"
>
<div className="absolute inset-0 grid-pattern opacity-30" />
{/* Decorative Blur Backgrounds */}
<div className="absolute top-1/4 -left-32 w-96 h-96 rounded-full bg-accent/20 blur-[120px] animate-pulse-glow pointer-events-none" />
<div
className="absolute bottom-1/4 -right-32 w-96 h-96 rounded-full bg-purple-500/15 blur-[120px] animate-pulse-glow pointer-events-none"
style={{ animationDelay: "2s" }}
/>
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] rounded-full bg-indigo-500/5 blur-[100px] pointer-events-none" />
{/* Subtle ambient light blobs - organic, not grid lines */}
<div className="absolute top-0 left-0 right-0 bottom-0 pointer-events-none overflow-hidden">
<motion.div
animate={{
x: [0, 30, -20, 0],
y: [0, -40, 20, 0],
}}
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
className="absolute top-[10%] left-[5%] w-[500px] h-[500px] rounded-full bg-accent/[0.07] dark:bg-accent/[0.15] blur-[100px]"
/>
<motion.div
animate={{
x: [0, -25, 15, 0],
y: [0, 30, -25, 0],
}}
transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
className="absolute bottom-[10%] right-[5%] w-[450px] h-[450px] rounded-full bg-purple-500/[0.05] dark:bg-purple-500/[0.12] blur-[100px]"
/>
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] rounded-full bg-indigo-400/[0.03] dark:bg-indigo-500/[0.05] blur-[120px]" />
</div>
<div className="relative z-10 w-full max-w-6xl mx-auto px-6">
<div className="grid lg:grid-cols-[1.1fr_0.9fr] gap-12 lg:gap-8 items-center">
@@ -203,27 +214,8 @@ export function HeroSection() {
transition={{ duration: 0.8, delay: 0.4 }}
className="order-1 lg:order-2 flex justify-center lg:justify-end relative w-full perspective-1000 h-[380px] sm:h-[450px]"
>
{/* Decorative elements behind card deck */}
<div className="absolute -bottom-10 -left-10 w-64 h-64 rounded-full bg-purple-600/30 blur-[80px] animate-pulse-glow pointer-events-none" />
<div className="absolute -top-6 -right-6 w-40 h-40 rounded-full bg-indigo-500/20 blur-[60px] animate-pulse-glow pointer-events-none" style={{ animationDelay: "1.5s" }} />
{/* Plus icon decoration */}
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, delay: 0.9 }}
className="absolute -top-2 right-4 sm:right-0 z-20 text-accent pointer-events-none"
>
<Plus size={24} strokeWidth={2.5} />
</motion.div>
{/* Circle decoration */}
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 0.5, scale: 1 }}
transition={{ duration: 0.5, delay: 1.1 }}
className="absolute top-16 -right-2 sm:right-[-12px] w-8 h-8 rounded-full border-2 border-accent/50 pointer-events-none z-20"
/>
{/* Soft glow behind card deck */}
<div className="absolute -bottom-10 left-1/2 -translate-x-1/2 w-72 h-48 rounded-full bg-accent/[0.08] dark:bg-accent/[0.15] blur-[80px] pointer-events-none" />
<div className="relative w-full max-w-[280px] sm:max-w-[320px] h-full mx-auto lg:mx-0 lg:mr-8 xl:mr-16">
{cards.map((imgUrl, index) => {
@@ -232,7 +224,7 @@ export function HeroSection() {
return (
<motion.div
key={imgUrl}
className="absolute inset-0 rounded-3xl overflow-hidden shadow-2xl border border-white/10 glass cursor-grab active:cursor-grabbing bg-card"
className="absolute inset-0 rounded-3xl overflow-hidden shadow-2xl border border-white/10 dark:border-white/10 border-black/[0.04] glass cursor-grab active:cursor-grabbing bg-card"
style={{
transformOrigin: "bottom center",
zIndex: cards.length - index,