Files
2026-08-01 16:07:57 +02:00

139 lines
5.0 KiB
TypeScript

"use client";
import { motion } from "framer-motion";
import { ArrowRight } from "lucide-react";
import GlowButton from "@/components/ui/GlowButton";
import { fadeUp, stagger } from "@/lib/animations";
import type { Dictionary, Locale } from "@/lib/dictionaries";
interface HeroProps {
locale: Locale;
dict: Dictionary;
}
export default function Hero({ locale, dict }: HeroProps) {
const stats = [
{ value: "13+", label: dict.hero.stats.projects },
{ value: "4", label: dict.hero.stats.clients },
{ value: "10", label: dict.hero.stats.infra },
{ value: "<24h", label: dict.hero.stats.response },
];
return (
<section className="relative isolate flex min-h-[100svh] items-center overflow-hidden pt-24">
{/* Grid background */}
<div className="pointer-events-none absolute inset-0 grid-bg [mask-image:radial-gradient(ellipse_at_center,#000_30%,transparent_70%)] opacity-50" />
{/* Floating orbs */}
<motion.div
className="pointer-events-none absolute left-[10%] top-[10%] h-[700px] w-[700px] rounded-full"
style={{
background:
"radial-gradient(circle, rgba(139, 92, 246, 0.55) 0%, transparent 70%)",
filter: "blur(60px)",
}}
animate={{
x: [0, 40, -20, 0],
y: [0, -30, 20, 0],
scale: [1, 1.1, 0.95, 1],
}}
transition={{ duration: 18, repeat: Infinity, ease: "easeInOut" }}
/>
<motion.div
className="pointer-events-none absolute right-[5%] top-[30%] h-[600px] w-[600px] rounded-full"
style={{
background:
"radial-gradient(circle, rgba(167, 139, 250, 0.35) 0%, transparent 70%)",
filter: "blur(70px)",
}}
animate={{
x: [0, -50, 30, 0],
y: [0, 40, -25, 0],
scale: [1, 0.9, 1.1, 1],
}}
transition={{ duration: 22, repeat: Infinity, ease: "easeInOut" }}
/>
{/* Top accent line */}
<div className="pointer-events-none absolute inset-x-0 top-0 mx-auto h-px max-w-3xl bg-gradient-to-r from-transparent via-purple-400/50 to-transparent" />
{/* Content */}
<div className="relative mx-auto w-full max-w-7xl px-6 lg:px-8">
<motion.div
variants={stagger(0.1)}
initial="hidden"
animate="visible"
className="mx-auto max-w-4xl text-center"
>
{/* Badge */}
<motion.div variants={fadeUp} className="mb-8 flex justify-center">
<span className="inline-flex items-center gap-2 rounded-full border border-emerald-500/30 bg-emerald-500/10 px-3.5 py-1.5 font-mono text-xs tracking-tight text-emerald-300 backdrop-blur-md">
<span className="relative flex h-1.5 w-1.5">
<span className="absolute inset-0 animate-ping rounded-full bg-emerald-400 opacity-75" />
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-emerald-400" />
</span>
{dict.hero.badge}
</span>
</motion.div>
{/* Heading */}
<motion.h1
variants={fadeUp}
className="font-display text-display-2xl font-medium tracking-tight"
>
<span className="text-gradient-fade">{dict.hero.titleLine1}</span>
<br />
<span className="text-gradient-purple">{dict.hero.titleLine2}</span>
</motion.h1>
{/* Subtitle */}
<motion.p
variants={fadeUp}
className="mx-auto mt-8 max-w-2xl text-lg leading-relaxed text-text-secondary sm:text-xl"
>
{dict.hero.subtitle}
</motion.p>
{/* CTAs */}
<motion.div
variants={fadeUp}
className="mt-12 flex flex-wrap items-center justify-center gap-4"
>
<GlowButton
href={`/${locale}/contact`}
variant="primary"
size="lg"
icon={<ArrowRight className="h-4 w-4" />}
>
{dict.hero.cta}
</GlowButton>
</motion.div>
{/* Stats */}
<motion.div
variants={fadeUp}
className="mt-20 grid grid-cols-2 gap-px overflow-hidden rounded-2xl border border-border/60 bg-border/40 sm:grid-cols-4"
>
{stats.map((stat) => (
<div
key={stat.label}
className="bg-background/60 px-6 py-6 backdrop-blur-sm"
>
<div className="font-display text-3xl font-medium tracking-tight text-text-primary sm:text-4xl">
{stat.value}
</div>
<div className="mt-1 font-mono text-[11px] uppercase tracking-widest text-text-secondary">
{stat.label}
</div>
</div>
))}
</motion.div>
</motion.div>
</div>
{/* Bottom fade */}
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent" />
</section>
);
}