pages
Some checks failed
Build & Deploy Mintel Blog / build-and-deploy (push) Failing after 1m26s

This commit is contained in:
2026-01-31 10:09:12 +01:00
parent 03fa2ea4a9
commit cd2d267e48
15 changed files with 745 additions and 789 deletions

View File

@@ -10,28 +10,24 @@ import {
ConceptSystem, ConceptSystem,
ConceptTarget, ConceptTarget,
ContactIllustration, ContactIllustration,
ConnectorBranch,
ConnectorStart,
ConnectorEnd,
ConnectorSplit,
HeroLines, HeroLines,
ParticleNetwork, ParticleNetwork,
GridLines GridLines
} from '../../src/components/Landing'; } from '../../src/components/Landing';
import { Check, ArrowRight } from 'lucide-react'; import { Check } from 'lucide-react';
import { H3, H4, LeadText, BodyText, Label, MonoLabel } from '../../src/components/Typography';
import { BackgroundGrid, Card, Container } from '../../src/components/Layout';
import { Button } from '../../src/components/Button';
export default function AboutPage() { export default function AboutPage() {
return ( return (
<div className="flex flex-col bg-white overflow-hidden relative"> <div className="flex flex-col bg-white overflow-hidden relative">
{/* Background Elements */} {/* Background Elements */}
<ParticleNetwork className="opacity-20" /> <ParticleNetwork className="opacity-20" />
<div className="fixed inset-0 pointer-events-none -z-20 opacity-[0.015]" style={{ <BackgroundGrid />
backgroundImage: 'linear-gradient(#0f172a 1px, transparent 1px), linear-gradient(90deg, #0f172a 1px, transparent 1px)',
backgroundSize: '80px 80px'
}} />
{/* Hero Section */} {/* Hero Section */}
<section className="relative pt-40 pb-32 overflow-hidden border-b border-slate-50"> <section className="relative pt-32 pb-24 overflow-hidden border-b border-slate-50">
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-full opacity-10 pointer-events-none"> <div className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-full opacity-10 pointer-events-none">
<HeroLines className="w-full h-full" /> <HeroLines className="w-full h-full" />
</div> </div>
@@ -39,41 +35,42 @@ export default function AboutPage() {
<GridLines /> <GridLines />
</div> </div>
<div className="narrow-container relative z-10"> <Container variant="narrow" className="relative z-10">
<div className="flex flex-col items-center text-center space-y-12"> <div className="flex flex-col items-center text-center space-y-12">
<Reveal> <Reveal>
<div className="relative"> <div className="relative">
{/* Structural rings around avatar */} {/* Structural rings around avatar */}
<div className="absolute inset-0 -m-8 border border-slate-100 rounded-full animate-[spin_20s_linear_infinite] opacity-50" /> <div className="absolute inset-0 -m-8 border border-slate-100 rounded-full animate-[spin_30s_linear_infinite] opacity-50" />
<div className="absolute inset-0 -m-4 border border-slate-200 rounded-full animate-[spin_15s_linear_infinite_reverse] opacity-30" /> <div className="absolute inset-0 -m-4 border border-slate-200 rounded-full animate-[spin_20s_linear_infinite_reverse] opacity-30" />
<div className="relative w-32 h-32 md:w-40 md:h-40 rounded-full overflow-hidden border border-slate-200 shadow-2xl shadow-slate-200/50 bg-white p-1"> <div className="relative w-32 h-32 md:w-40 md:h-40 rounded-full overflow-hidden border border-slate-200 shadow-xl bg-white p-1 group">
<div className="w-full h-full rounded-full overflow-hidden"> <div className="w-full h-full rounded-full overflow-hidden">
<img <img
src="/header.webp" src="/header.webp"
alt="Marc Mintel" alt="Marc Mintel"
className="w-full h-full object-cover grayscale transition-all duration-1000 ease-in-out scale-110 hover:scale-100" className="w-full h-full object-cover grayscale transition-all duration-1000 ease-in-out scale-110 group-hover:scale-100 group-hover:grayscale-0"
/> />
</div> </div>
</div> </div>
</div> </div>
</Reveal> </Reveal>
<div className="space-y-6 max-w-2xl"> <div className="space-y-6 max-w-3xl">
<Reveal delay={0.1}> <Reveal delay={0.1}>
<div className="flex items-center justify-center gap-3 mb-4"> <div className="flex items-center justify-center gap-4 mb-4">
<div className="h-px w-8 bg-slate-900"></div> <div className="h-px w-8 bg-slate-900"></div>
<span className="text-[10px] font-bold uppercase tracking-[0.4em] text-slate-900">Digital Architect</span> <MonoLabel className="text-slate-900">Digital Architect</MonoLabel>
<div className="h-px w-8 bg-slate-900"></div> <div className="h-px w-8 bg-slate-900"></div>
</div> </div>
</Reveal> </Reveal>
<PageHeader <PageHeader
title={<>Über <span className="text-slate-300">mich.</span></>} title={<>Über <span className="text-slate-200">mich.</span></>}
description="(oder: Warum das hier kein Agentur-Zirkus ist)" description="Warum ich tue, was ich tue und wie Sie davon profitieren."
className="pt-0 md:pt-0"
/> />
</div> </div>
</div> </div>
</div> </Container>
{/* Connector to first section */} {/* Connector to first section */}
<div className="absolute bottom-0 left-1/2 -translate-x-1/2 w-px h-16 bg-gradient-to-b from-transparent to-slate-200" /> <div className="absolute bottom-0 left-1/2 -translate-x-1/2 w-px h-16 bg-gradient-to-b from-transparent to-slate-200" />
@@ -84,48 +81,47 @@ export default function AboutPage() {
number="01" number="01"
title="Erfahrung" title="Erfahrung"
borderTop borderTop
connector={<ConnectorStart className="h-full" />} illustration={<ExperienceIllustration className="w-24 h-24" />}
illustration={<ExperienceIllustration className="w-32 h-32" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Ich baue Websites und Systeme seit über 15 Jahren. <br /> 15 Jahre Web-Entwicklung. <br />
<span className="text-slate-300">Weil ich es hasse, wenn Dinge nicht funktionieren.</span> <span className="text-slate-200">Vom Designer zum Architekten.</span>
</h3> </H3>
</Reveal> </Reveal>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-12">
<Reveal delay={0.1}> <Reveal delay={0.1}>
<div className="space-y-6"> <div className="space-y-8">
<p className="text-xl text-slate-600 font-serif italic"> <LeadText className="text-xl md:text-2xl text-slate-400">
In diesen 15 Jahren habe ich Agenturen von innen gesehen, Konzerne erlebt und Startups aufgebaut. Ich habe Agenturen, Konzerne und Startups von innen gesehen. Dabei habe ich gelernt, what really counts: <span className="text-slate-900">Ergebnisse, nicht Prozesse.</span>
</p> </LeadText>
<ul className="space-y-4"> <ul className="space-y-4">
{[ {[
'Marketingversprechen zerlegt', 'Komplexe Systeme vereinfacht',
'Systeme repariert, die „fertig“ waren', 'Performance-Probleme gelöst',
'Gelernt, wie man Dinge baut, die einfach laufen' 'Nachhaltige Software-Architekturen gebaut'
].map((item, i) => ( ].map((item, i) => (
<li key={i} className="flex items-center gap-3 text-slate-500"> <li key={i} className="flex items-center gap-4 group">
<div className="w-1.5 h-1.5 bg-slate-300 rounded-full shrink-0" /> <div className="w-1.5 h-1.5 bg-slate-900 rounded-full group-hover:scale-150 transition-transform" />
{item} <BodyText className="text-lg">{item}</BodyText>
</li> </li>
))} ))}
</ul> </ul>
</div> </div>
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<div className="p-8 bg-slate-50 rounded-3xl border border-slate-100"> <Card variant="gray" hover={false} padding="normal" className="group">
<p className="text-slate-900 font-bold text-lg mb-4">Heute mache ich das ohne Agentur-Zwischenschichten.</p> <H4 className="text-2xl mb-6">Mein Fokus heute: Direkte Zusammenarbeit ohne Reibungsverluste.</H4>
<div className="flex flex-wrap gap-4"> <div className="flex flex-wrap gap-3">
{['Direkt', 'Sauber', 'Verantwortlich'].map((tag, i) => ( {['Effizient', 'Pragmatisch', 'Verlässlich'].map((tag, i) => (
<span key={i} className="px-4 py-2 bg-white border border-slate-200 rounded-full text-xs font-bold uppercase tracking-widest text-slate-400"> <span key={i} className="px-4 py-2 bg-white border border-slate-200 rounded-full shadow-sm">
{tag} <Label className="text-slate-900">{tag}</Label>
</span> </span>
))} ))}
</div> </div>
</div> </Card>
</Reveal> </Reveal>
</div> </div>
</div> </div>
@@ -137,31 +133,30 @@ export default function AboutPage() {
title="Verantwortung" title="Verantwortung"
variant="gray" variant="gray"
borderTop borderTop
connector={<ConnectorBranch className="h-full" />} illustration={<ResponsibilityIllustration className="w-24 h-24" />}
illustration={<ResponsibilityIllustration className="w-32 h-32" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Ich habe fast alle Fehler schon für Sie gemacht. <br /> Ich stehe für meine <br />
<span className="text-slate-300">(Damit Sie sie nicht machen müssen)</span> <span className="text-slate-200">Arbeit gerade.</span>
</h3> </H3>
</Reveal> </Reveal>
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 items-center"> <div className="grid grid-cols-1 md:grid-cols-12 gap-12 items-center">
<div className="md:col-span-7 space-y-8"> <div className="md:col-span-8 space-y-8">
<Reveal delay={0.1}> <Reveal delay={0.1}>
<p className="text-xl text-slate-600 font-serif italic"> <LeadText className="text-xl md:text-2xl text-slate-400">
Ich habe als Designer angefangen, bin dann Entwickler geworden, und habe irgendwann gemerkt: Das Problem ist selten Technik. Es ist immer Zuständigkeit. In der klassischen Agenturwelt verschwindet Verantwortung oft hinter Hierarchien. Bei mir gibt es nur <span className="text-slate-900">einen Ansprechpartner:</span> Mich.
</p> </LeadText>
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<div className="flex items-start gap-6 p-6 bg-white rounded-2xl border border-slate-100 shadow-sm"> <Card variant="white" padding="normal" className="flex flex-row items-start gap-6 group">
<div className="w-12 h-12 bg-slate-900 text-white rounded-xl flex items-center justify-center shrink-0 font-bold">!</div> <div className="w-12 h-12 bg-slate-900 text-white rounded-xl flex items-center justify-center shrink-0 font-bold text-xl group-hover:rotate-12 transition-transform duration-500">!</div>
<p className="text-slate-900 font-medium"> <BodyText className="text-slate-900 font-medium text-lg md:text-xl leading-relaxed">
Wenn keiner verantwortlich ist, passiert nichts. Also habe ich mir angewöhnt, Verantwortung zu übernehmen. Ich übernehme die volle Verantwortung für die technische Umsetzung und Qualität Ihres Projekts. Ohne Ausreden.
</p> </BodyText>
</div> </Card>
</Reveal> </Reveal>
</div> </div>
</div> </div>
@@ -173,129 +168,94 @@ export default function AboutPage() {
number="03" number="03"
title="Philosophie" title="Philosophie"
borderTop borderTop
connector={<ConnectorSplit className="h-full" />} illustration={<ConceptSystem className="w-24 h-24" />}
illustration={<ConceptSystem className="w-32 h-32" />}
> >
<div className="space-y-16"> <div className="space-y-16">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Warum ich Websites wie Systeme baue. Nachhaltigkeit durch <br />
</h3> <span className="text-slate-200">sauberen Code.</span>
</H3>
</Reveal> </Reveal>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12"> <div className="grid grid-cols-1 md:grid-cols-2 gap-12">
<div className="space-y-8"> <div className="space-y-8">
<Reveal delay={0.1}> <Reveal delay={0.1}>
<p className="text-slate-500 font-serif italic text-lg"> <LeadText className="text-xl text-slate-400">
Ich war viele Jahre Senior Developer in Firmen, in denen Millionenumsätze dranhingen, Fehler teuer waren und Performance nicht optional war. Ich baue keine Wegwerf-Produkte. Meine Systeme sind so konzipiert, dass sie mit Ihrem Unternehmen <span className="text-slate-900">wachsen können.</span>
</p> </LeadText>
</Reveal> </Reveal>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
{['Schnell', 'Stabil', 'Boring', 'Erweiterbar', 'Wartungsarm', 'Unabhängig'].map((item, i) => ( {['Skalierbar', 'Wartbar', 'Performant', 'Sicher', 'Unabhängig', 'Zukunftssicher'].map((item, i) => (
<Reveal key={i} delay={0.2 + i * 0.05}> <Reveal key={i} delay={0.2 + i * 0.05}>
<div className="flex items-center gap-2 text-slate-900 font-bold text-sm uppercase tracking-widest"> <div className="flex items-center gap-3 group">
<Check className="w-4 h-4 text-slate-400" /> <div className="w-5 h-5 rounded-full bg-slate-50 flex items-center justify-center group-hover:bg-slate-900 transition-colors duration-500">
{item} <Check className="w-2.5 h-2.5 text-slate-400 group-hover:text-white" />
</div>
<Label className="text-slate-900">{item}</Label>
</div> </div>
</Reveal> </Reveal>
))} ))}
</div> </div>
</div> </div>
<Reveal delay={0.3}> <Reveal delay={0.3}>
<div className="relative p-10 bg-slate-900 text-white rounded-3xl overflow-hidden group"> <Card variant="dark" padding="normal" className="relative rounded-2xl overflow-hidden group">
<div className="absolute top-0 right-0 w-32 h-32 bg-white/5 -translate-y-16 translate-x-16 rounded-full blur-3xl group-hover:bg-white/10 transition-colors" /> <div className="absolute top-0 right-0 w-48 h-48 bg-white/5 -translate-y-24 translate-x-24 rounded-full blur-3xl group-hover:bg-white/10 transition-colors duration-1000" />
<h4 className="text-2xl font-bold mb-6 relative z-10">Das prägt.</h4> <H4 className="text-white text-2xl mb-6 relative z-10">Kein Vendor Lock-in.</H4>
<p className="text-slate-400 font-serif italic text-lg relative z-10"> <LeadText className="text-slate-400 text-lg relative z-10 leading-relaxed">
Meine Websites sind nicht abhängig von Plugins oder Agenturen. Sie sind gebaut, um zu bleiben. Sie behalten die volle Kontrolle über Ihren Code und Ihre Daten. Keine Abhängigkeit von proprietären Systemen.
</p> </LeadText>
</div> </Card>
</Reveal> </Reveal>
</div> </div>
</div> </div>
</Section> </Section>
{/* Section 04: Roles */} {/* Section 04: Result */}
<Section <Section
number="04" number="04"
title="Perspektive"
variant="gray"
borderTop
connector={<ConnectorBranch className="h-full" />}
illustration={<ConceptTarget className="w-32 h-32" />}
>
<div className="space-y-12">
<Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl">
Ich habe beide Seiten gesehen.
</h3>
</Reveal>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{[
'Webdesigner', 'Entwickler', 'Marketing', 'Vertrieb',
'Agentur', 'Inhouse', 'Dienstleister', 'Unternehmer'
].map((role, i) => (
<Reveal key={i} delay={i * 0.05}>
<div className="p-4 bg-white border border-slate-100 rounded-xl text-center hover:border-slate-300 transition-colors group">
<span className="text-xs font-bold uppercase tracking-widest text-slate-400 group-hover:text-slate-900 transition-colors">{role}</span>
</div>
</Reveal>
))}
</div>
<Reveal delay={0.4}>
<p className="text-2xl text-slate-600 font-serif italic max-w-2xl">
Ich weiß, was Unternehmen brauchen und was sie nicht brauchen. (Meetings, Tickets, Workshops, PowerPoint.)
</p>
</Reveal>
</div>
</Section>
{/* Section 05: Result */}
<Section
number="05"
title="Ergebnis" title="Ergebnis"
borderTop borderTop
connector={<ConnectorBranch className="h-full" />} illustration={<ResultIllustration className="w-24 h-24" />}
illustration={<ResultIllustration className="w-32 h-32" />}
> >
<div className="space-y-16"> <div className="space-y-16">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Was Kunden davon haben. Was Sie von mir <br />
</h3> <span className="text-slate-200">erwarten können.</span>
</H3>
</Reveal> </Reveal>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12"> <div className="grid grid-cols-1 md:grid-cols-2 gap-16">
<div className="space-y-8"> <div className="space-y-8">
<div className="space-y-4"> <div className="space-y-6">
<span className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Sie bekommen kein:</span> <Label>Kein:</Label>
<div className="flex flex-wrap gap-3"> <div className="flex flex-wrap gap-3">
{['Projektmanager', 'Prozess', 'Team', 'Ticket', 'CMS-Drama'].map((item, i) => ( {['Agentur-Zirkus', 'Meeting-Marathon', 'Ticket-Wahnsinn', 'CMS-Frust'].map((item, i) => (
<span key={i} className="px-4 py-2 border border-slate-100 rounded-full text-slate-400 line-through text-sm italic font-serif"> <span key={i} className="px-4 py-2 border border-slate-100 rounded-full bg-slate-50/50">
{item} <BodyText className="text-slate-400 line-through text-base mb-0">{item}</BodyText>
</span> </span>
))} ))}
</div> </div>
</div> </div>
</div> </div>
<div className="space-y-8"> <div className="space-y-8">
<div className="space-y-4"> <div className="space-y-6">
<span className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-900">Sie bekommen:</span> <Label className="text-slate-900">Sondern:</Label>
<div className="space-y-4"> <div className="space-y-8">
{[ {[
{ label: 'Eine Person', desc: 'Direkter Kontakt, keine Stille Post.' }, { label: 'Direkte Kommunikation', desc: 'Kurze Wege, schnelle Entscheidungen.' },
{ label: 'Eine Verantwortung', desc: 'Ich stehe für das Ergebnis gerade.' }, { label: 'Echte Expertise', desc: 'Fundiertes Wissen aus 15 Jahren Praxis.' },
{ label: 'Ein Ergebnis', desc: 'Funktionierende Systeme, keine Ausreden.' } { label: 'Messbare Qualität', desc: 'Code, der hält, was er verspricht.' }
].map((item, i) => ( ].map((item, i) => (
<Reveal key={i} delay={0.2 + i * 0.1}> <Reveal key={i} delay={0.2 + i * 0.1}>
<div className="flex gap-4 items-start"> <div className="flex gap-6 items-start group">
<div className="w-6 h-6 rounded-full bg-slate-900 flex items-center justify-center shrink-0 mt-1"> <div className="w-8 h-8 rounded-full bg-slate-900 flex items-center justify-center shrink-0 mt-1 group-hover:scale-110 transition-transform">
<Check className="w-3 h-3 text-white" /> <Check className="w-4 h-4 text-white" />
</div> </div>
<div> <div className="space-y-1">
<div className="font-bold text-slate-900">{item.label}</div> <H4 className="text-xl">{item.label}</H4>
<div className="text-slate-500 text-sm font-serif italic">{item.desc}</div> <BodyText className="text-base text-slate-400">{item.desc}</BodyText>
</div> </div>
</div> </div>
</Reveal> </Reveal>
@@ -307,41 +267,37 @@ export default function AboutPage() {
</div> </div>
</Section> </Section>
{/* Section 06: Today */} {/* Section 05: Today */}
<Section <Section
number="06" number="05"
title="Heute" title="Kontakt"
variant="gray" variant="gray"
borderTop borderTop
connector={<ConnectorEnd className="h-full" />} illustration={<ContactIllustration className="w-24 h-24" />}
illustration={<ContactIllustration className="w-32 h-32" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Heute baue ich Websites für Unternehmen, die keine Lust mehr auf Chaos haben. Bereit für eine <br />
</h3> <span className="text-slate-200">Zusammenarbeit?</span>
</H3>
</Reveal> </Reveal>
<div className="p-12 bg-white rounded-[3rem] border border-slate-100 shadow-2xl shadow-slate-200/50 relative overflow-hidden group"> <Card variant="white" hover={false} padding="large" className="rounded-3xl shadow-xl relative overflow-hidden group">
<div className="absolute top-0 right-0 w-64 h-64 bg-slate-50 -translate-y-32 translate-x-32 rounded-full blur-3xl group-hover:bg-slate-100 transition-colors" /> <div className="absolute top-0 right-0 w-96 h-96 bg-slate-50 -translate-y-1/2 translate-x-1/2 rounded-full blur-[80px] group-hover:bg-slate-100 transition-colors duration-1000" />
<div className="relative z-10 space-y-8"> <div className="relative z-10 space-y-8">
<p className="text-2xl text-slate-600 font-serif italic leading-relaxed max-w-2xl"> <LeadText className="text-2xl md:text-4xl leading-tight max-w-2xl text-slate-400">
Ich übernehme das Thema komplett damit es für Sie kein Thema mehr ist. Lassen Sie uns gemeinsam etwas bauen, das <span className="text-slate-900">wirklich funktioniert.</span>
</p> </LeadText>
<div className="pt-8"> <div className="pt-4">
<a <Button href="/contact">
href="/contact"
className="inline-flex items-center gap-4 px-10 py-5 bg-slate-900 text-white rounded-full font-bold text-sm uppercase tracking-widest hover:bg-slate-800 transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] hover:-translate-y-1 hover:shadow-2xl hover:shadow-slate-900/20 group"
>
Projekt anfragen Projekt anfragen
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" /> </Button>
</a>
</div> </div>
</div> </div>
</div> </Card>
</div> </div>
</Section> </Section>
</div> </div>

View File

@@ -10,28 +10,28 @@
body { body {
@apply bg-white text-slate-800 font-serif antialiased selection:bg-slate-900 selection:text-white; @apply bg-white text-slate-800 font-serif antialiased selection:bg-slate-900 selection:text-white;
line-height: 1.8; line-height: 1.6;
} }
/* Typography */ /* Typography */
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
@apply font-sans font-bold text-slate-900; @apply font-sans font-bold text-slate-900 tracking-tighter;
} }
h1 { h1 {
@apply text-4xl md:text-5xl leading-[1.1] mb-8 tracking-tight; @apply text-6xl md:text-8xl leading-[0.95] mb-12;
} }
h2 { h2 {
@apply text-3xl md:text-4xl leading-[1.2] mb-6 mt-12 tracking-tight; @apply text-4xl md:text-6xl leading-tight mb-8 mt-16;
} }
h3 { h3 {
@apply text-2xl md:text-3xl leading-[1.3] mb-4 mt-8 tracking-tight; @apply text-3xl md:text-5xl leading-tight mb-6 mt-12;
} }
h4 { h4 {
@apply text-xl md:text-2xl leading-[1.4] mb-3 mt-6 tracking-tight; @apply text-2xl md:text-3xl leading-tight mb-4 mt-8;
} }
p { p {

View File

@@ -1,6 +1,4 @@
import { ArrowRight } from 'lucide-react';
import { import {
CirclePattern,
ComparisonRow, ComparisonRow,
ConceptAutomation, ConceptAutomation,
ConceptCode, ConceptCode,
@@ -10,80 +8,61 @@ import {
ConceptPrototyping, ConceptPrototyping,
ConceptSystem, ConceptSystem,
ConceptWebsite, ConceptWebsite,
ConnectorBranch,
ConnectorEnd,
ConnectorSplit,
ConnectorStart,
ContactIllustration,
DifferenceIllustration, DifferenceIllustration,
FlowLines,
GridLines,
HeroArchitecture, HeroArchitecture,
HeroMainIllustration, HeroMainIllustration
ServicesFlow
} from '../src/components/Landing'; } from '../src/components/Landing';
import { Reveal } from '../src/components/Reveal'; import { Reveal } from '../src/components/Reveal';
import { Section } from '../src/components/Section'; import { Section } from '../src/components/Section';
import { H1, H3, LeadText, BodyText, MonoLabel, Label } from '../src/components/Typography';
import { BackgroundGrid, Card, Container } from '../src/components/Layout';
import { Button } from '../src/components/Button';
export default function LandingPage() { export default function LandingPage() {
return ( return (
<div className="flex flex-col bg-white overflow-hidden relative"> <div className="flex flex-col bg-white overflow-hidden relative">
{/* Subtle Grid Pattern Overlay */} <BackgroundGrid />
<div className="fixed inset-0 pointer-events-none -z-20 opacity-[0.015]" style={{
backgroundImage: 'linear-gradient(#0f172a 1px, transparent 1px), linear-gradient(90deg, #0f172a 1px, transparent 1px)',
backgroundSize: '80px 80px'
}} />
{/* Hero Section - Split Layout */} {/* Hero Section */}
<section className="relative min-h-[80vh] flex items-center pt-12 md:pt-0 pb-24 md:pb-0"> <section className="relative min-h-[80vh] flex items-center pt-24 md:pt-0">
<div className="narrow-container w-full relative"> <Container variant="narrow" className="relative">
{/* Connector Start for Hero */} <div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-24 items-center">
<div className="absolute left-[2.5rem] top-32 bottom-0 w-24 hidden md:block -z-10 pointer-events-none"> {/* Left Column */}
<ConnectorStart className="h-full" /> <div className="md:col-span-6 relative z-10">
</div>
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-16 items-center min-h-[600px]">
{/* Left Column: Brand & Number */}
<div className="md:col-span-4 relative z-10 bg-white/50 backdrop-blur-[2px]">
<Reveal> <Reveal>
<div className="space-y-8"> <div className="space-y-8">
<div className="flex items-center gap-3 text-slate-400 font-mono text-[10px] uppercase tracking-[0.3em]"> <div className="flex items-center gap-4">
<span className="w-6 h-px bg-slate-900"></span> <div className="w-8 h-px bg-slate-900"></div>
Digital Architect <MonoLabel className="text-slate-900">Digital Architect</MonoLabel>
</div> </div>
<h1 className="text-6xl md:text-8xl font-bold text-slate-900 tracking-tighter leading-[0.9]"> <H1 className="text-6xl md:text-8xl">
Websites <br /> Websites <br />
<span className="text-slate-300">ohne <br />Overhead.</span> <span className="text-slate-200">ohne Overhead.</span>
</h1> </H1>
<div className="pt-8"> <div className="pt-4">
<a <Button href="#contact" variant="outline">
href="#contact"
className="inline-flex items-center gap-4 px-8 py-4 border border-slate-200 bg-white text-slate-900 rounded-full font-bold text-sm uppercase tracking-widest hover:border-slate-400 hover:bg-slate-50 transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] hover:-translate-y-0.5 hover:shadow-xl hover:shadow-slate-100 group"
>
Projekt anfragen Projekt anfragen
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" /> </Button>
</a>
</div> </div>
</div> </div>
</Reveal> </Reveal>
</div> </div>
{/* Right Column: Visual & Context */} {/* Right Column */}
<div className="md:col-span-8 relative h-[600px] md:h-[900px] flex items-center justify-center"> <div className="md:col-span-6 relative h-[400px] md:h-[600px] flex items-center justify-center">
{/* Hero Architecture Illustration - Background Layer */} <div className="absolute inset-0 -z-10 opacity-[0.03] pointer-events-none flex items-center justify-center scale-150">
<div className="absolute inset-0 -z-10 opacity-5 pointer-events-none flex items-center justify-center scale-[2]">
<HeroArchitecture className="w-full h-full" /> <HeroArchitecture className="w-full h-full" />
</div> </div>
<Reveal delay={0.2} className="w-full h-full flex items-center justify-center"> <Reveal delay={0.2} className="w-full h-full flex items-center justify-center">
<div className="relative w-full h-full flex items-center justify-center pointer-events-none"> <div className="relative w-full h-full flex items-center justify-center pointer-events-none">
<HeroMainIllustration className="w-full h-full scale-150 md:scale-[1.6] translate-x-12 md:translate-x-16 origin-center" /> <HeroMainIllustration className="w-full h-full scale-110 md:scale-125 origin-center" />
</div> </div>
</Reveal> </Reveal>
</div> </div>
</div> </div>
</div> </Container>
</section> </section>
{/* Section 02: The Promise */} {/* Section 02: The Promise */}
@@ -91,41 +70,33 @@ export default function LandingPage() {
number="02" number="02"
title="Das Versprechen" title="Das Versprechen"
borderTop borderTop
connector={<ConnectorBranch className="h-full" />}
> >
<div className="space-y-16 relative"> <div className="space-y-16 relative">
<div className="absolute right-0 top-0 w-64 h-64 -z-10 opacity-30 pointer-events-none">
<GridLines />
</div>
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="max-w-3xl">
Schluss mit aufgeblähten Prozessen. <br /> Schluss mit aufgeblähten Prozessen. <br />
<span className="text-slate-300">Ich reduziere auf das Wesentliche.</span> <span className="text-slate-200">Ich reduziere auf das Wesentliche.</span>
</h3> </H3>
</Reveal> </Reveal>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 relative z-10"> <div className="grid grid-cols-1 md:grid-cols-2 gap-16 relative z-10">
<Reveal delay={0.1}> <Reveal delay={0.1}>
<div className="space-y-8"> <div className="space-y-8">
<div className="flex items-center gap-4 text-slate-900 font-bold text-lg"> <div className="flex items-center gap-4">
<div className="w-12 h-12 rounded-xl bg-slate-50 flex items-center justify-center border border-slate-100"> <Label className="text-slate-900">Was ich biete</Label>
<ConceptCode className="w-8 h-8" />
</div>
Was ich biete
</div> </div>
<ul className="space-y-8"> <ul className="space-y-6">
{[ {[
{ text: 'Direkte Kommunikation ohne Account Manager', icon: <ConceptCommunication className="w-16 h-16" /> }, { text: 'Direkte Kommunikation ohne Umwege', icon: <ConceptCommunication className="w-12 h-12" /> },
{ text: 'Schnelle Prototypen statt langer Konzepte', icon: <ConceptPrototyping className="w-16 h-16" /> }, { text: 'Schnelle Prototypen statt langer Konzepte', icon: <ConceptPrototyping className="w-12 h-12" /> },
{ text: 'Sauberer Code, der auch morgen noch läuft', icon: <ConceptCode className="w-16 h-16" /> }, { text: 'Sauberer Code, der auch morgen noch läuft', icon: <ConceptCode className="w-12 h-12" /> },
{ text: 'Fixpreise für klare Budgetsicherheit', icon: <ConceptPrice className="w-16 h-16" /> } { text: 'Fixpreise für volle Budgetsicherheit', icon: <ConceptPrice className="w-12 h-12" /> }
].map((item, i) => ( ].map((item, i) => (
<li key={i} className="flex items-center gap-6 text-slate-600 font-serif italic text-lg group"> <li key={i} className="flex items-center gap-6 group">
<div className="shrink-0 opacity-100 transition-all duration-500 group-hover:scale-110"> <div className="shrink-0 transition-transform duration-500 group-hover:scale-110">
{item.icon} {item.icon}
</div> </div>
{item.text} <LeadText className="text-xl">{item.text}</LeadText>
</li> </li>
))} ))}
</ul> </ul>
@@ -133,12 +104,9 @@ export default function LandingPage() {
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<div className="space-y-8 opacity-50 hover:opacity-100 transition-opacity duration-500"> <div className="space-y-8 opacity-40 hover:opacity-100 transition-opacity duration-700">
<div className="flex items-center gap-4 text-slate-400 font-bold text-lg"> <div className="flex items-center gap-4">
<div className="w-12 h-12 rounded-xl bg-slate-50 flex items-center justify-center border border-slate-100 grayscale"> <Label>Was ich nicht mache</Label>
<ConceptMessy className="w-8 h-8" />
</div>
Was ich nicht mache
</div> </div>
<ul className="space-y-4"> <ul className="space-y-4">
{[ {[
@@ -147,9 +115,9 @@ export default function LandingPage() {
'Outsourcing an Billig-Anbieter', 'Outsourcing an Billig-Anbieter',
'Wartungsverträge mit versteckten Kosten' 'Wartungsverträge mit versteckten Kosten'
].map((item, i) => ( ].map((item, i) => (
<li key={i} className="flex items-start gap-3 text-slate-400 font-serif italic text-lg decoration-slate-400 line-through"> <li key={i} className="flex items-start gap-3 decoration-slate-200 line-through">
<span className="w-1.5 h-1.5 bg-slate-300 rounded-full mt-2.5 shrink-0"></span> <span className="w-1.5 h-1.5 bg-slate-200 rounded-full mt-2.5 shrink-0"></span>
{item} <LeadText className="text-slate-400 text-lg">{item}</LeadText>
</li> </li>
))} ))}
</ul> </ul>
@@ -165,43 +133,37 @@ export default function LandingPage() {
title="Der Unterschied" title="Der Unterschied"
variant="white" variant="white"
borderTop borderTop
connector={<ConnectorStart className="h-full" />}
> >
<div className="space-y-12 relative"> <div className="space-y-16 relative">
<div className="flex flex-col md:flex-row gap-12 items-center"> <div className="flex flex-col md:flex-row gap-12 items-center">
<Reveal className="flex-1"> <Reveal className="flex-1">
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl relative z-10"> <LeadText className="text-2xl md:text-3xl leading-tight max-w-2xl relative z-10 text-slate-400">
Der klassische Agentur-Weg ist oft langsam und teuer. Mein Ansatz ist radikal anders: Ich baue zuerst, dann reden wir über Details. Ich arbeite nicht gegen die Zeit, sondern <span className="text-slate-900">für das Ergebnis.</span> Mein Fokus liegt auf der Umsetzung, nicht auf der Verwaltung von Prozessen.
</p> </LeadText>
</Reveal> </Reveal>
<Reveal delay={0.2} className="w-full md:w-80 shrink-0"> <Reveal delay={0.2} className="w-full md:w-72 shrink-0">
<DifferenceIllustration className="w-full h-auto" /> <div className="p-6 bg-slate-50 rounded-2xl border border-slate-100">
<DifferenceIllustration className="w-full h-auto grayscale opacity-50" />
</div>
</Reveal> </Reveal>
</div> </div>
<div className="grid grid-cols-1 gap-6 relative z-20"> <div className="grid grid-cols-1 gap-8 relative z-20">
<ComparisonRow <ComparisonRow
negativeLabel="Agentur" negativeLabel="Klassisch"
negativeText="Konzeptcalls, Meetings, Slides, Warten auf das Angebot." negativeText="Lange Planungsphasen und abstrakte Konzepte."
positiveLabel="Ich" positiveLabel="Mein Weg"
positiveText="Ich baue einen Prototypen. Sie sehen sofort, was Sie bekommen." positiveText="Schnelle Prototypen. Sie sehen Fortschritt in Tagen."
delay={0.1} delay={0.1}
/> />
<ComparisonRow <ComparisonRow
negativeLabel="Agentur" negativeLabel="Klassisch"
negativeText="Stundensätze, Nachberechnungen, Budget-Überraschungen." negativeText="Komplexe Preisstrukturen und versteckte Kosten."
positiveLabel="Ich" positiveLabel="Mein Weg"
positiveText="Fixpreise. Ein Preis, ein Ergebnis. Keine Diskussionen." positiveText="Klare Fixpreise. Volle Kostentransparenz."
reverse reverse
delay={0.2} delay={0.2}
/> />
<ComparisonRow
negativeLabel="Agentur"
negativeText="Wechselnde Ansprechpartner, Stille Post."
positiveLabel="Ich"
positiveText="Ein Ansprechpartner. Ich setze um, was wir besprechen."
delay={0.3}
/>
</div> </div>
</div> </div>
</Section> </Section>
@@ -211,103 +173,97 @@ export default function LandingPage() {
number="04" number="04"
title="Zielgruppe" title="Zielgruppe"
borderTop borderTop
connector={<ConnectorSplit className="h-full" />}
> >
<div className="relative"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 relative z-10">
<div className="absolute left-0 top-0 w-full h-full -z-10 opacity-30 pointer-events-none"> <Reveal>
<CirclePattern /> <Card variant="dark" padding="normal" className="group">
</div> <div className="space-y-6 relative overflow-hidden">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 relative z-10"> <div className="w-16 h-16 bg-white/5 rounded-xl flex items-center justify-center border border-white/10">
<Reveal> <ConceptPrice className="w-8 h-8" />
<div className="p-10 bg-slate-900 text-white rounded-3xl h-full flex flex-col justify-between group hover:scale-[1.02] transition-transform duration-500 shadow-2xl shadow-slate-900/20">
<div className="space-y-6 relative overflow-hidden">
<div className="w-16 h-16 bg-white/10 rounded-2xl flex items-center justify-center">
<ConceptPrice className="w-10 h-10" />
</div>
<h3 className="text-3xl font-bold tracking-tight text-white">Unternehmer & <br/>Geschäftsführer</h3>
<p className="text-slate-300 font-serif italic text-lg leading-relaxed">
"Ich brauche eine Lösung, die funktioniert. Ich habe keine Zeit für technische Details oder lange Meetings."
</p>
</div>
<div className="pt-8 border-t border-white/10 mt-8">
<span className="text-xs font-bold uppercase tracking-widest text-slate-400 group-hover:text-white transition-colors">Perfekt für Sie</span>
</div> </div>
<H3 className="text-white text-3xl">Unternehmer & <br/>Geschäftsführer</H3>
<LeadText className="text-slate-400 text-lg">
"Ich brauche eine Lösung, die funktioniert. Ich habe keine Zeit für technische Details."
</LeadText>
</div> </div>
</Reveal> <div className="pt-8 border-t border-white/5 mt-8">
<Reveal delay={0.2}> <Label className="group-hover:text-white transition-colors">Perfekt für Sie</Label>
<div className="p-10 bg-white border border-slate-100 rounded-3xl h-full flex flex-col justify-between group hover:border-slate-300 transition-colors duration-500 shadow-xl shadow-slate-100/50">
<div className="space-y-6 relative overflow-hidden">
<div className="w-16 h-16 bg-slate-50 border border-slate-200 rounded-2xl flex items-center justify-center">
<ConceptWebsite className="w-10 h-10" />
</div>
<h3 className="text-3xl font-bold tracking-tight text-slate-900">Marketing & <br/>Vertrieb</h3>
<p className="text-slate-600 font-serif italic text-lg leading-relaxed">
"Wir brauchen Landingpages, Tools und Automatisierungen, um unsere Ziele zu erreichen. Schnell und zuverlässig."
</p>
</div>
<div className="pt-8 border-t border-slate-200 mt-8">
<span className="text-xs font-bold uppercase tracking-widest text-slate-400 group-hover:text-slate-900 transition-colors">Perfekt für Sie</span>
</div>
</div> </div>
</Reveal> </Card>
</div> </Reveal>
<Reveal delay={0.2}>
<Card variant="white" padding="normal" className="group">
<div className="space-y-6 relative overflow-hidden">
<div className="w-16 h-16 bg-slate-50 border border-slate-100 rounded-xl flex items-center justify-center">
<ConceptWebsite className="w-8 h-8" />
</div>
<H3 className="text-3xl">Marketing & <br/>Vertrieb</H3>
<LeadText className="text-slate-400 text-lg">
"Wir brauchen Landingpages und Tools, um unsere Ziele zu erreichen. Schnell und zuverlässig."
</LeadText>
</div>
<div className="pt-8 border-t border-slate-50 mt-8">
<Label className="group-hover:text-slate-900 transition-colors">Perfekt für Sie</Label>
</div>
</Card>
</Reveal>
</div> </div>
</Section> </Section>
{/* Section 05: Services - Visual Flow */} {/* Section 05: Services */}
<Section <Section
number="05" number="05"
title="Leistungen" title="Leistungen"
variant="gray" variant="gray"
borderTop borderTop
connector={<ConnectorBranch className="h-full" />}
> >
<div className="relative py-12"> <div className="grid grid-cols-1 md:grid-cols-3 gap-8 relative z-20">
{/* Connecting Line Illustration */} <Reveal delay={0.1}>
<div className="absolute top-1/2 left-0 w-full -translate-y-1/2 hidden md:block"> <Card variant="white" padding="small" className="group">
<ServicesFlow /> <div className="w-16 h-16 bg-slate-50 rounded-xl flex items-center justify-center mb-8 group-hover:scale-110 transition-transform duration-500">
</div> <ConceptWebsite className="w-8 h-8" />
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 relative z-20"> <div className="space-y-4">
<Reveal delay={0.1}> <H3 className="text-2xl">Websites</H3>
<div className="bg-white p-8 rounded-2xl border border-slate-100 shadow-lg hover:shadow-xl transition-all duration-300 group h-full relative overflow-hidden"> <BodyText>
<div className="w-20 h-20 bg-slate-50 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500"> High-Performance Websites. Maßgeschneiderte Architektur statt Baukasten.
<ConceptWebsite className="w-12 h-12" /> </BodyText>
</div> <div className="pt-4">
<h3 className="text-2xl font-bold text-slate-900 mb-4">Websites</h3> <a href="/websites" className="text-[10px] font-bold uppercase tracking-[0.4em] text-slate-900 border-b border-slate-100 pb-1 hover:border-slate-900 transition-all">
<p className="text-slate-500 font-serif italic mb-6"> Details
High-Performance Websites. Kein Baukasten, sondern maßgeschneiderte Architektur.
</p>
<a href="/websites" className="text-xs font-bold uppercase tracking-widest text-slate-900 border-b border-slate-200 pb-1 hover:border-slate-900 transition-colors">
Preise ansehen
</a> </a>
</div>
</div> </div>
</Reveal> </Card>
</Reveal>
<Reveal delay={0.3}> <Reveal delay={0.3}>
<div className="bg-white p-8 rounded-2xl border border-slate-100 shadow-lg hover:shadow-xl transition-all duration-300 group h-full mt-8 md:mt-0 relative overflow-hidden"> <Card variant="white" padding="small" className="group mt-8 md:mt-0">
<div className="w-20 h-20 bg-slate-50 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500"> <div className="w-16 h-16 bg-slate-50 rounded-xl flex items-center justify-center mb-8 group-hover:scale-110 transition-transform duration-500">
<ConceptSystem className="w-12 h-12" /> <ConceptSystem className="w-8 h-8" />
</div>
<h3 className="text-2xl font-bold text-slate-900 mb-4">Systeme</h3>
<p className="text-slate-500 font-serif italic">
Web-Applikationen, Kundenportale, interne Tools. Wenn Standard-Software an ihre Grenzen stößt.
</p>
</div> </div>
</Reveal> <div className="space-y-4">
<H3 className="text-2xl">Systeme</H3>
<BodyText>
Web-Applikationen, Portale, interne Tools. Wenn Standard an Grenzen stößt.
</BodyText>
</div>
</Card>
</Reveal>
<Reveal delay={0.5}> <Reveal delay={0.5}>
<div className="bg-white p-8 rounded-2xl border border-slate-100 shadow-lg hover:shadow-xl transition-all duration-300 group h-full relative overflow-hidden"> <Card variant="white" padding="small" className="group">
<div className="w-20 h-20 bg-slate-50 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500"> <div className="w-16 h-16 bg-slate-50 rounded-xl flex items-center justify-center mb-8 group-hover:scale-110 transition-transform duration-500">
<ConceptAutomation className="w-12 h-12" /> <ConceptAutomation className="w-8 h-8" />
</div>
<h3 className="text-2xl font-bold text-slate-900 mb-4">Automatisierung</h3>
<p className="text-slate-500 font-serif italic">
Verbindung von Tools, automatische PDF-Erstellung, Daten-Synchronisation.
</p>
</div> </div>
</Reveal> <div className="space-y-4">
</div> <H3 className="text-2xl">Automatisierung</H3>
<BodyText>
Verbindung von Tools, automatische Prozesse, Daten-Synchronisation.
</BodyText>
</div>
</Card>
</Reveal>
</div> </div>
</Section> </Section>
@@ -316,43 +272,38 @@ export default function LandingPage() {
number="06" number="06"
title="Kontakt" title="Kontakt"
borderTop borderTop
connector={<ConnectorEnd className="h-full" />}
> >
<div className="relative py-12" id="contact"> <div className="relative py-12" id="contact">
<div className="absolute right-0 top-1/2 -translate-y-1/2 w-[400px] h-[200px] -z-10 opacity-40 pointer-events-none">
<FlowLines />
</div>
<div className="absolute left-1/2 top-0 -translate-x-1/2 w-32 h-32 opacity-10 -z-10">
<ContactIllustration />
</div>
<Reveal> <Reveal>
<div className="space-y-12"> <div className="space-y-16">
<h2 className="text-5xl md:text-7xl font-bold text-slate-900 tracking-tighter leading-[0.9]"> <H1 className="text-6xl md:text-8xl">
Lassen Sie uns <br /> Lassen Sie uns <br />
<span className="text-slate-300">starten.</span> <span className="text-slate-200">starten.</span>
</h2> </H1>
<div className="flex flex-col md:flex-row gap-12 items-start relative z-10"> <div className="flex flex-col md:flex-row gap-16 items-start relative z-10">
<div className="space-y-6 flex-1"> <div className="space-y-8 flex-1">
<p className="text-xl text-slate-600 font-serif italic"> <LeadText className="text-2xl md:text-3xl text-slate-400">
Schreiben Sie mir kurz, worum es geht. Ich melde mich innerhalb von 24 Stunden mit einer ersten Einschätzung. Schreiben Sie mir kurz, worum es geht. Ich melde mich innerhalb von <span className="text-slate-900">24 Stunden</span>.
</p> </LeadText>
<a <div className="pt-4">
href="/contact" <a
className="inline-block text-3xl md:text-4xl font-bold text-slate-900 hover:text-slate-600 transition-colors border-b-2 border-slate-900 hover:border-slate-600 pb-2" href="/contact"
> className="inline-block text-3xl md:text-5xl font-bold text-slate-900 hover:text-slate-400 transition-all duration-700 border-b-2 border-slate-900 hover:border-slate-200 pb-2"
Projekt anfragen >
</a> Projekt anfragen
</a>
</div>
</div> </div>
<div className="flex-1 space-y-4"> <div className="w-full md:w-72 space-y-6 p-6 bg-slate-50 rounded-2xl border border-slate-100">
<div className="flex items-center gap-4 text-sm font-bold uppercase tracking-widest text-slate-400"> <div className="flex items-center gap-3">
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div> <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
Verfügbar für neue Projekte <Label className="text-slate-900">Verfügbarkeit</Label>
</div> </div>
<p className="text-slate-500 text-sm"> <BodyText className="text-base leading-snug">
Aktuell nehme ich Projekte für Q2 2026 an. Aktuell nehme ich Projekte für <span className="font-bold text-slate-900">Q2 2026</span> an.
</p> </BodyText>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,5 @@
'use client'; 'use client';
import { Info, Check, Zap, Shield, Code, MessageSquare, RefreshCw, Layout, ArrowRight } from 'lucide-react';
import { PageHeader } from '../../src/components/PageHeader'; import { PageHeader } from '../../src/components/PageHeader';
import { Reveal } from '../../src/components/Reveal'; import { Reveal } from '../../src/components/Reveal';
import { Section } from '../../src/components/Section'; import { Section } from '../../src/components/Section';
@@ -10,23 +9,28 @@ import {
SolidFoundation, SolidFoundation,
LayerSeparation, LayerSeparation,
DirectService, DirectService,
AgencyChaos, TaskDone,
TaskDone ConceptAutomation,
} from '../../src/components/Landing/Illustrations/WebsitesDescriptive'; ConceptCode,
import { motion } from 'framer-motion'; ConceptCommunication,
ConceptPrototyping,
ConceptSystem,
ConceptTarget
} from '../../src/components/Landing';
import { Check } from 'lucide-react';
import { H2, H3, H4, LeadText, BodyText, Label } from '../../src/components/Typography';
import { BackgroundGrid, Card } from '../../src/components/Layout';
import { MotionButton } from '../../src/components/Button';
export default function WebsitesPage() { export default function WebsitesPage() {
return ( return (
<div className="flex flex-col bg-white overflow-hidden relative"> <div className="flex flex-col bg-white overflow-hidden relative">
{/* Subtle Grid Pattern Overlay */}
<div className="fixed inset-0 pointer-events-none -z-20 opacity-[0.015]" style={{ <BackgroundGrid />
backgroundImage: 'linear-gradient(#0f172a 1px, transparent 1px), linear-gradient(90deg, #0f172a 1px, transparent 1px)',
backgroundSize: '80px 80px'
}} />
<PageHeader <PageHeader
title={<>Websites, die <br /><span className="text-slate-300">einfach funktionieren.</span></>} title={<>Websites, die <br /><span className="text-slate-200">einfach funktionieren.</span></>}
description="Die meisten Websites funktionieren. Bis jemand sie anfasst. Ich baue Websites so, dass das alles egal ist." description="Keine Baukästen, keine Plugins, kein Overhead. Nur sauberer Code und maximale Performance."
backLink={{ href: '/', label: 'Zurück' }} backLink={{ href: '/', label: 'Zurück' }}
backgroundSymbol="W" backgroundSymbol="W"
/> />
@@ -36,32 +40,34 @@ export default function WebsitesPage() {
number="01" number="01"
title="Der Ansatz" title="Der Ansatz"
borderTop borderTop
illustration={<SystemArchitecture className="w-32 h-32" />} illustration={<SystemArchitecture className="w-24 h-24" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Ich baue Websites wie Systeme <br /> Ich baue Websites wie Systeme <br />
<span className="text-slate-300">nicht wie Broschüren.</span> <span className="text-slate-200">nicht wie Broschüren.</span>
</h3> </H3>
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl"> <LeadText className="text-xl md:text-2xl max-w-2xl text-slate-400">
Eine Website ist kein Flyer. Sie ist ein System, das jeden Tag arbeitet. Eine Website ist kein Flyer. Sie ist ein <span className="text-slate-900">Werkzeug</span>, das jeden Tag arbeitet.
Deshalb baue ich sie stabil, schnell und vorhersehbar. Deshalb baue ich sie stabil, schnell und wartungsfrei.
</p> </LeadText>
</Reveal> </Reveal>
<Reveal delay={0.4}> <Reveal delay={0.4}>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 pt-8"> <div className="grid grid-cols-2 md:grid-cols-4 gap-8 pt-8">
{[ {[
{ label: 'Stabil', icon: Shield }, { label: 'Stabil', icon: ConceptSystem },
{ label: 'Schnell', icon: Zap }, { label: 'Schnell', icon: ConceptAutomation },
{ label: 'Vorhersehbar', icon: Layout }, { label: 'Wartungsfrei', icon: ConceptCode },
{ label: 'Sicher', icon: Info }, { label: 'Sicher', icon: ConceptTarget },
].map((item, i) => ( ].map((item, i) => (
<div key={i} className="flex flex-col gap-3"> <div key={i} className="flex flex-col gap-3 group">
<item.icon className="w-5 h-5 text-slate-300" /> <div className="w-12 h-12 rounded-xl bg-slate-50 flex items-center justify-center border border-slate-100 group-hover:scale-110 transition-transform duration-500">
<span className="text-[10px] font-bold uppercase tracking-widest text-slate-900">{item.label}</span> <item.icon className="w-6 h-6" />
</div>
<Label className="text-slate-900">{item.label}</Label>
</div> </div>
))} ))}
</div> </div>
@@ -74,42 +80,47 @@ export default function WebsitesPage() {
number="02" number="02"
title="Performance" title="Performance"
borderTop borderTop
illustration={<SpeedPerformance className="w-32 h-32" />} variant="gray"
illustration={<SpeedPerformance className="w-24 h-24" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Geschwindigkeit ist <br /> Geschwindigkeit ist <br />
<span className="text-slate-300">kein Extra. Sie ist Standard.</span> <span className="text-slate-200">kein Extra. Sie ist Standard.</span>
</h3> </H3>
</Reveal> </Reveal>
<Reveal delay={0.2}> <div className="grid grid-cols-1 md:grid-cols-12 gap-12 items-center">
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl"> <div className="md:col-span-7 space-y-8">
Viele Websites sind langsam, weil sie zusammengeklickt sind. Meine sind schnell, weil sie gebaut sind. <Reveal delay={0.2}>
</p> <LeadText className="text-xl text-slate-400">
</Reveal> Viele Websites sind langsam, weil sie zusammengeklickt sind. Meine sind schnell, weil sie <span className="text-slate-900">von Grund auf</span> entwickelt wurden.
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 pt-8"> </LeadText>
<Reveal delay={0.4}> </Reveal>
<ul className="space-y-6"> <Reveal delay={0.4}>
{[ <ul className="space-y-4">
'Seiten laden sofort', {[
'Google mag sie (SEO)', 'Seiten laden ohne Verzögerung',
'Besucher bleiben länger', 'Optimiert für Suchmaschinen (SEO)',
'Bessere Sichtbarkeit', 'Bessere Nutzererfahrung',
].map((item, i) => ( 'Höhere Conversion-Rates',
<li key={i} className="flex items-center gap-4 text-lg text-slate-600 font-serif italic"> ].map((item, i) => (
<div className="w-1.5 h-1.5 bg-slate-900 rounded-full" /> <li key={i} className="flex items-center gap-4 group">
{item} <div className="w-1.5 h-1.5 bg-slate-900 rounded-full group-hover:scale-150 transition-transform" />
</li> <LeadText className="text-lg md:text-xl">{item}</LeadText>
))} </li>
</ul> ))}
</Reveal> </ul>
<Reveal delay={0.6}> </Reveal>
<div className="p-10 bg-slate-50 rounded-3xl border border-slate-100 flex flex-col justify-center items-center text-center group"> </div>
<div className="text-7xl md:text-9xl font-bold text-slate-900 tracking-tighter group-hover:scale-110 transition-transform duration-500">90+</div> <div className="md:col-span-5">
<div className="text-slate-400 font-serif italic text-lg mt-4">Pagespeed Normalzustand</div> <Reveal delay={0.6}>
</div> <Card variant="white" padding="normal" className="text-center group">
</Reveal> <div className="text-7xl md:text-8xl font-bold text-slate-900 tracking-tighter group-hover:scale-110 transition-transform duration-700">90+</div>
<Label className="mt-4">Pagespeed Score</Label>
</Card>
</Reveal>
</div>
</div> </div>
</div> </div>
</Section> </Section>
@@ -117,33 +128,39 @@ export default function WebsitesPage() {
{/* No Maintenance */} {/* No Maintenance */}
<Section <Section
number="03" number="03"
title="Wartungsfrei" title="Technik"
borderTop borderTop
illustration={<SolidFoundation className="w-32 h-32" />} illustration={<SolidFoundation className="w-24 h-24" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Keine Plugins. <br /> Keine Plugins. <br />
<span className="text-slate-300">Keine Wartungshölle.</span> <span className="text-slate-200">Keine Abhängigkeiten.</span>
</h3> </H3>
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl"> <LeadText className="text-xl md:text-2xl max-w-2xl text-slate-400">
Ich nutze keine Baukästen oder Plugin-Sammlungen, die sich selbst zerstören. Ich nutze keine Baukästen, die sich selbst zerstören.
Ihre Website besteht aus sauberem Code und einer klaren Struktur. Ihre Website besteht aus <span className="text-slate-900">sauberem Code</span>, der Ihnen gehört.
</p> </LeadText>
</Reveal> </Reveal>
<Reveal delay={0.4}> <Reveal delay={0.4}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 pt-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 pt-8">
<div className="p-8 bg-white border border-slate-100 rounded-2xl shadow-sm hover:border-slate-300 transition-colors"> <Card variant="white" padding="normal" className="group">
<div className="font-bold text-slate-900 mb-2 uppercase tracking-widest text-[10px]">Technik</div> <div className="space-y-4">
<p className="text-slate-500 font-serif italic">Sauberer Code & feste Bausteine.</p> <Label className="text-slate-900 mb-2">Code Qualität</Label>
</div> <H4 className="text-2xl">Langlebigkeit</H4>
<div className="p-8 bg-white border border-slate-100 rounded-2xl shadow-sm hover:border-slate-300 transition-colors"> <BodyText>Modernste Web-Technologien für maximale Performance und Wartbarkeit.</BodyText>
<div className="font-bold text-slate-900 mb-2 uppercase tracking-widest text-[10px]">Sicherheit</div> </div>
<p className="text-slate-500 font-serif italic">Wenn etwas geändert wird, geht nichts kaputt.</p> </Card>
</div> <Card variant="white" padding="normal" className="group">
<div className="space-y-4">
<Label className="text-slate-900 mb-2">Sicherheit</Label>
<H4 className="text-2xl">Resilienz</H4>
<BodyText>Minimale Angriffsfläche durch Verzicht auf unnötige Drittanbieter-Software.</BodyText>
</div>
</Card>
</div> </div>
</Reveal> </Reveal>
</div> </div>
@@ -154,40 +171,48 @@ export default function WebsitesPage() {
number="04" number="04"
title="Inhalte" title="Inhalte"
borderTop borderTop
illustration={<LayerSeparation className="w-32 h-32" />} variant="gray"
illustration={<LayerSeparation className="w-24 h-24" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Inhalte & Technik <br /> Inhalte pflegen <br />
<span className="text-slate-300">sind getrennt. Absichtlich.</span> <span className="text-slate-200">ohne Angst.</span>
</h3> </H3>
</Reveal> </Reveal>
<Reveal delay={0.2}> <div className="grid grid-cols-1 md:grid-cols-12 gap-12 items-start">
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl"> <div className="md:col-span-7">
Sie können Inhalte selbst pflegen, ohne das Design oder die Technik zu gefährden. <Reveal delay={0.2}>
Sie können nichts kaputt machen. Ich verspreche es. <LeadText className="text-xl md:text-2xl text-slate-400">
</p> Sie können Texte und Bilder selbst anpassen, ohne das Design oder die Technik zu gefährden.
</Reveal> Ein <span className="text-slate-900">intuitives System</span> sorgt dafür, dass alles an seinem Platz bleibt.
<Reveal delay={0.4}> </LeadText>
<div className="flex flex-wrap gap-12 pt-8"> </Reveal>
<div className="space-y-4">
<div className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Was Sie tun</div>
<div className="flex items-center gap-3 text-xl font-bold text-slate-900">
<Check className="w-5 h-5" />
Inhalte pflegen
</div>
</div>
<div className="space-y-4 opacity-30">
<div className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Was Sie ignorieren</div>
<div className="flex flex-col gap-2">
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">Design</div>
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">Struktur</div>
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">Technik</div>
</div>
</div>
</div> </div>
</Reveal> <div className="md:col-span-5">
<Reveal delay={0.4}>
<Card variant="white" padding="normal" className="space-y-8">
<div className="space-y-4">
<Label>Ihre Freiheit</Label>
<div className="flex items-center gap-3 text-xl font-bold text-slate-900">
<div className="w-8 h-8 rounded-full bg-slate-900 flex items-center justify-center">
<Check className="w-3 h-3 text-white" />
</div>
Inhalte flexibel verwalten
</div>
</div>
<div className="space-y-4 opacity-30">
<Label>Mein Schutz</Label>
<div className="space-y-2">
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">Design-Chaos</div>
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">Technische Fehler</div>
</div>
</div>
</Card>
</Reveal>
</div>
</div>
</div> </div>
</Section> </Section>
@@ -196,87 +221,69 @@ export default function WebsitesPage() {
number="05" number="05"
title="Service" title="Service"
borderTop borderTop
illustration={<DirectService className="w-32 h-32" />} illustration={<DirectService className="w-24 h-24" />}
> >
<div className="space-y-12"> <div className="space-y-12">
<Reveal> <Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl"> <H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
Änderungen sind <br /> Änderungen sind <br />
<span className="text-slate-300">einfach. Wirklich.</span> <span className="text-slate-200">Teil des Konzepts.</span>
</h3> </H3>
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl"> <LeadText className="text-xl md:text-2xl max-w-2xl text-slate-400">
Neue Seite? Neue Funktion? Neue Idee? <br /> Ihr Business entwickelt sich weiter, Ihre Website auch. <br />
Kein Ticket. Kein Formular. Kein Projektplan. Keine komplizierten Prozesse, sondern <span className="text-slate-900">direkte Umsetzung</span> Ihrer Ideen.
</p> </LeadText>
</Reveal> </Reveal>
<Reveal delay={0.4}> <Reveal delay={0.4}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 pt-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 pt-8">
<div className="p-10 bg-white border border-slate-100 rounded-3xl hover:border-slate-900 transition-all duration-500 group"> <Card variant="white" padding="normal" className="group hover:border-slate-900">
<MessageSquare className="w-10 h-10 text-slate-200 group-hover:text-slate-900 transition-colors mb-6" /> <ConceptCommunication className="w-12 h-12 mb-8 group-hover:scale-110 transition-all duration-700" />
<h4 className="text-2xl font-bold text-slate-900 mb-2">Kurze Wege</h4> <div className="space-y-2">
<p className="text-slate-500 font-serif italic">Sie schreiben mir, was Sie brauchen.</p> <H4 className="text-2xl">Direkter Draht</H4>
</div> <BodyText>Sie sprechen direkt mit dem Entwickler. Keine Stille Post.</BodyText>
<div className="p-10 bg-white border border-slate-100 rounded-3xl hover:border-slate-900 transition-all duration-500 group"> </div>
<RefreshCw className="w-10 h-10 text-slate-200 group-hover:text-slate-900 transition-colors mb-6" /> </Card>
<h4 className="text-2xl font-bold text-slate-900 mb-2">Schnelle Umsetzung</h4> <Card variant="white" padding="normal" className="group hover:border-slate-900">
<p className="text-slate-500 font-serif italic">Ich setze es um. Fertig.</p> <ConceptPrototyping className="w-12 h-12 mb-8 group-hover:scale-110 transition-all duration-700" />
</div> <div className="space-y-2">
<H4 className="text-2xl">Agile Anpassung</H4>
<BodyText>Schnelle Iterationen statt langer Wartezeiten.</BodyText>
</div>
</Card>
</div> </div>
</Reveal> </Reveal>
</div> </div>
</Section> </Section>
{/* Why */}
<Section
number="06"
title="Warum"
borderTop
illustration={<AgencyChaos className="w-32 h-32" />}
>
<div className="space-y-12">
<Reveal>
<h3 className="text-3xl md:text-5xl font-bold text-slate-900 leading-tight tracking-tight max-w-3xl">
15 Jahre Agenturen <br />
<span className="text-slate-300">waren genug.</span>
</h3>
</Reveal>
<Reveal delay={0.2}>
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl">
Zu viele Meetings. Zu viele Konzepte. Zu viele Übergaben. Zu viele eigentlich müsste man mal.
Meine Websites sind dafür gebaut, dass Dinge einfach passieren.
</p>
</Reveal>
</div>
</Section>
{/* Result */} {/* Result */}
<Section <Section
number="07" number="06"
title="Ergebnis" title="Ergebnis"
borderTop borderTop
variant="gray" variant="gray"
illustration={<TaskDone className="w-32 h-32" />} illustration={<TaskDone className="w-24 h-24" />}
> >
<div className="space-y-16"> <div className="space-y-16">
<Reveal> <Reveal>
<h2 className="text-5xl md:text-8xl font-bold text-slate-900 tracking-tighter leading-[0.9]"> <H3 className="text-4xl md:text-6xl tracking-tighter">
Eine Website, die sich wie eine <br /> Eine Website, die <br />
<span className="text-slate-300">erledigte Aufgabe</span> anfühlt. <span className="text-slate-200">einfach läuft.</span>
</h2> </H3>
</Reveal> </Reveal>
<div className="grid grid-cols-1 md:grid-cols-3 gap-12"> <div className="grid grid-cols-1 md:grid-cols-3 gap-12">
{[ {[
{ title: 'Kein Stress', desc: 'Keine Wartungspflicht, keine Überraschungen.' }, { title: 'Kein Overhead', desc: 'Fokus auf das, was Ihre Kunden wirklich brauchen.' },
{ title: 'Keine Abhängigkeit', desc: 'Sauberer Code, der Ihnen gehört.' }, { title: 'Volle Kontrolle', desc: 'Der Code gehört Ihnen, ohne Vendor Lock-in.' },
{ title: 'Keine Agentur', desc: 'Direkter Kontakt, schnelle Ergebnisse.' }, { title: 'Echte Performance', desc: 'Messbare Geschwindigkeit für bessere Ergebnisse.' },
].map((item, i) => ( ].map((item, i) => (
<Reveal key={i} delay={i * 0.1}> <Reveal key={i} delay={i * 0.1}>
<div className="space-y-4"> <div className="space-y-4 group">
<div className="text-2xl font-bold tracking-tight text-slate-900">{item.title}</div> <div className="w-8 h-px bg-slate-200 group-hover:w-full transition-all duration-1000" />
<p className="text-slate-500 font-serif italic text-lg">{item.desc}</p> <H4 className="text-2xl">{item.title}</H4>
<LeadText className="text-lg text-slate-400">{item.desc}</LeadText>
</div> </div>
</Reveal> </Reveal>
))} ))}
@@ -285,20 +292,14 @@ export default function WebsitesPage() {
<Reveal delay={0.4}> <Reveal delay={0.4}>
<div className="pt-16 border-t border-slate-200 flex flex-col md:flex-row justify-between items-start md:items-center gap-8"> <div className="pt-16 border-t border-slate-200 flex flex-col md:flex-row justify-between items-start md:items-center gap-8">
<div className="space-y-2"> <div className="space-y-2">
<div className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Technik</div> <Label>Bereit für mehr?</Label>
<p className="text-slate-500 font-serif italic text-lg"> <LeadText className="text-2xl">
Modern, sicher, schnell. Aber das ist mein Problem, nicht Ihres. Lassen Sie uns über Ihr nächstes Projekt sprechen.
</p> </LeadText>
</div> </div>
<motion.a <MotionButton href="/contact">
href="/contact"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="inline-flex items-center gap-4 px-12 py-6 bg-slate-900 text-white rounded-full font-bold uppercase tracking-widest text-xs hover:bg-slate-800 transition-colors group"
>
Projekt anfragen Projekt anfragen
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" /> </MotionButton>
</motion.a>
</div> </div>
</Reveal> </Reveal>
</div> </div>

21
package-lock.json generated
View File

@@ -15,6 +15,7 @@
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vercel/og": "^0.8.6", "@vercel/og": "^0.8.6",
"canvas-confetti": "^1.9.4", "canvas-confetti": "^1.9.4",
"clsx": "^2.1.1",
"framer-motion": "^12.29.2", "framer-motion": "^12.29.2",
"ioredis": "^5.9.1", "ioredis": "^5.9.1",
"lucide-react": "^0.468.0", "lucide-react": "^0.468.0",
@@ -25,6 +26,7 @@
"react": "^19.2.3", "react": "^19.2.3",
"react-dom": "^19.2.3", "react-dom": "^19.2.3",
"shiki": "^1.24.2", "shiki": "^1.24.2",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^3.4.0" "tailwindcss": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {
@@ -1889,6 +1891,15 @@
"node": ">=0.8" "node": ">=0.8"
} }
}, },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/cluster-key-slot": { "node_modules/cluster-key-slot": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
@@ -4575,6 +4586,16 @@
"integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==", "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/tailwind-merge": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
"integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "3.4.19", "version": "3.4.19",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",

View File

@@ -21,6 +21,7 @@
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vercel/og": "^0.8.6", "@vercel/og": "^0.8.6",
"canvas-confetti": "^1.9.4", "canvas-confetti": "^1.9.4",
"clsx": "^2.1.1",
"framer-motion": "^12.29.2", "framer-motion": "^12.29.2",
"ioredis": "^5.9.1", "ioredis": "^5.9.1",
"lucide-react": "^0.468.0", "lucide-react": "^0.468.0",
@@ -31,6 +32,7 @@
"react": "^19.2.3", "react": "^19.2.3",
"react-dom": "^19.2.3", "react-dom": "^19.2.3",
"shiki": "^1.24.2", "shiki": "^1.24.2",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^3.4.0" "tailwindcss": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {

67
src/components/Button.tsx Normal file
View File

@@ -0,0 +1,67 @@
import * as React from 'react';
import { ArrowRight } from 'lucide-react';
import { motion } from 'framer-motion';
import Link from 'next/link';
interface ButtonProps {
href: string;
children: React.ReactNode;
variant?: 'primary' | 'outline';
className?: string;
showArrow?: boolean;
}
export const Button: React.FC<ButtonProps> = ({
href,
children,
variant = 'primary',
className = "",
showArrow = true
}) => {
const baseStyles = "inline-flex items-center gap-4 rounded-full font-bold uppercase tracking-widest transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] group";
const variants = {
primary: "px-10 py-5 bg-slate-900 text-white hover:bg-slate-800 hover:-translate-y-1 hover:shadow-2xl hover:shadow-slate-900/20 text-sm",
outline: "px-8 py-4 border border-slate-200 bg-white text-slate-900 hover:border-slate-400 hover:bg-slate-50 hover:-translate-y-0.5 hover:shadow-xl hover:shadow-slate-100 text-sm"
};
const content = (
<>
{children}
{showArrow && <ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />}
</>
);
if (href.startsWith('#')) {
return (
<a href={href} className={`${baseStyles} ${variants[variant]} ${className}`}>
{content}
</a>
);
}
return (
<Link href={href} className={`${baseStyles} ${variants[variant]} ${className}`}>
{content}
</Link>
);
};
export const MotionButton: React.FC<ButtonProps> = ({
href,
children,
variant = 'primary',
className = "",
showArrow = true
}) => {
return (
<motion.div
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
<Button href={href} variant={variant} className={className} showArrow={showArrow}>
{children}
</Button>
</motion.div>
);
};

View File

@@ -8,7 +8,6 @@ interface LineProps {
delay?: number; delay?: number;
} }
// ... existing components ...
export const HeroLines: React.FC<LineProps> = ({ className = "", delay = 0 }) => { export const HeroLines: React.FC<LineProps> = ({ className = "", delay = 0 }) => {
return ( return (
<svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 800 600" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 800 600" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -216,150 +215,7 @@ export const ComparisonLines: React.FC<LineProps> = ({ className = "", delay = 0
) )
} }
// --- New Connector Components --- export const ConnectorStart: React.FC<LineProps> = ({ className = "", delay = 0 }) => null;
export const ConnectorBranch: React.FC<LineProps> = ({ className = "", delay = 0 }) => null;
export const ConnectorStart: React.FC<LineProps> = ({ className = "", delay = 0 }) => { export const ConnectorSplit: React.FC<LineProps> = ({ className = "", delay = 0 }) => null;
return ( export const ConnectorEnd: React.FC<LineProps> = ({ className = "", delay = 0 }) => null;
<svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 100 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<motion.path
d="M 50 0 V 400"
stroke="currentColor"
strokeWidth="3"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay }}
/>
<circle cx="50" cy="10" r="8" className="fill-slate-900" />
{/* Multiple Pulses */}
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="4s"
repeatCount="indefinite"
path="M 50 0 V 400"
/>
</motion.circle>
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="4s"
begin="2s"
repeatCount="indefinite"
path="M 50 0 V 400"
/>
</motion.circle>
</svg>
);
};
export const ConnectorBranch: React.FC<LineProps> = ({ className = "", delay = 0 }) => {
return (
<svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 200 400" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* Main vertical line */}
<motion.path
d="M 50 0 V 400"
stroke="currentColor"
strokeWidth="3"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay }}
/>
{/* Branch */}
<motion.path
d="M 50 100 C 50 150, 100 150, 150 150 H 200"
stroke="currentColor"
strokeWidth="3"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay + 0.5 }}
/>
{/* Pulses */}
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="4s"
repeatCount="indefinite"
path="M 50 0 V 400"
/>
</motion.circle>
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="3s"
repeatCount="indefinite"
path="M 50 100 C 50 150, 100 150, 150 150 H 200"
/>
</motion.circle>
</svg>
);
};
export const ConnectorSplit: React.FC<LineProps> = ({ className = "", delay = 0 }) => {
return (
<svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 200 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<motion.path
d="M 50 0 V 50 C 50 100, 100 100, 150 100 H 200"
stroke="currentColor"
strokeWidth="3"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay }}
/>
<motion.path
d="M 50 50 V 400"
stroke="currentColor"
strokeWidth="3"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay }}
/>
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="4s"
repeatCount="indefinite"
path="M 50 0 V 400"
/>
</motion.circle>
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="3s"
repeatCount="indefinite"
path="M 50 0 V 50 C 50 100, 100 100, 150 100 H 200"
/>
</motion.circle>
</svg>
);
};
export const ConnectorEnd: React.FC<LineProps> = ({ className = "", delay = 0 }) => {
return (
<svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 100 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<motion.path
d="M 50 0 V 200"
stroke="currentColor"
strokeWidth="3"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay }}
/>
<circle cx="50" cy="200" r="8" className="fill-slate-900" />
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="2s"
repeatCount="indefinite"
path="M 50 0 V 200"
/>
</motion.circle>
</svg>
);
};

View File

@@ -1,6 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { ArrowRight } from 'lucide-react'; import { ArrowRight } from 'lucide-react';
import { Reveal } from '../Reveal'; import { Reveal } from '../Reveal';
import { Label, H3, LeadText } from '../Typography';
interface ComparisonRowProps { interface ComparisonRowProps {
negativeLabel: string; negativeLabel: string;
@@ -23,12 +24,12 @@ export const ComparisonRow: React.FC<ComparisonRowProps> = ({
<Reveal delay={delay}> <Reveal delay={delay}>
<div className={`flex flex-col ${reverse ? 'md:flex-row-reverse' : 'md:flex-row'} gap-8 md:gap-12 items-center`}> <div className={`flex flex-col ${reverse ? 'md:flex-row-reverse' : 'md:flex-row'} gap-8 md:gap-12 items-center`}>
<div className="flex-1 p-8 md:p-10 bg-slate-50/50 rounded-2xl text-slate-400 border border-transparent w-full"> <div className="flex-1 p-8 md:p-10 bg-slate-50/50 rounded-2xl text-slate-400 border border-transparent w-full">
<div className="text-[10px] font-bold uppercase tracking-[0.2em] mb-4 line-through decoration-slate-200"> <Label className="mb-4 line-through decoration-slate-200">
{negativeLabel} {negativeLabel}
</div> </Label>
<div className="text-lg md:text-xl font-serif italic line-through decoration-slate-200 leading-snug"> <LeadText className="line-through decoration-slate-200 leading-snug">
{negativeText} {negativeText}
</div> </LeadText>
</div> </div>
<div className="shrink-0"> <div className="shrink-0">
@@ -36,12 +37,12 @@ export const ComparisonRow: React.FC<ComparisonRowProps> = ({
</div> </div>
<div className="flex-1 p-8 md:p-10 border border-slate-100 rounded-2xl bg-white hover:border-slate-200 transition-all duration-500 hover:shadow-xl hover:shadow-slate-100/50 w-full"> <div className="flex-1 p-8 md:p-10 border border-slate-100 rounded-2xl bg-white hover:border-slate-200 transition-all duration-500 hover:shadow-xl hover:shadow-slate-100/50 w-full">
<div className="text-[10px] font-bold uppercase tracking-[0.2em] text-slate-900 mb-4"> <Label className="text-slate-900 mb-4">
{positiveLabel} {positiveLabel}
</div> </Label>
<div className="text-2xl md:text-3xl font-bold text-slate-900 leading-tight tracking-tight"> <H3 className="text-2xl md:text-3xl">
{positiveText} {positiveText}
</div> </H3>
</div> </div>
</div> </div>
</Reveal> </Reveal>

View File

@@ -13,3 +13,4 @@ export * from './HeroMainIllustration';
export * from './ExperienceIllustration'; export * from './ExperienceIllustration';
export * from './ResponsibilityIllustration'; export * from './ResponsibilityIllustration';
export * from './ResultIllustration'; export * from './ResultIllustration';
export * from './WebsitesDescriptive';

68
src/components/Layout.tsx Normal file
View File

@@ -0,0 +1,68 @@
import * as React from 'react';
import { cn } from '../utils/cn';
export const BackgroundGrid: React.FC = () => (
<div className="fixed inset-0 pointer-events-none -z-20 opacity-[0.01]" style={{
backgroundImage: 'linear-gradient(#0f172a 1px, transparent 1px), linear-gradient(90deg, #0f172a 1px, transparent 1px)',
backgroundSize: '60px 60px'
}} />
);
interface CardProps {
children: React.ReactNode;
className?: string;
variant?: 'white' | 'dark' | 'gray';
hover?: boolean;
padding?: 'none' | 'small' | 'normal' | 'large';
}
export const Card: React.FC<CardProps> = ({
children,
className = "",
variant = 'white',
hover = true,
padding = 'normal'
}) => {
const variants = {
white: 'bg-white border-slate-100 text-slate-900 shadow-sm',
dark: 'bg-slate-900 border-white/5 text-white shadow-xl',
gray: 'bg-slate-50/50 border-slate-100 text-slate-900'
};
const paddings = {
none: 'p-0',
small: 'p-6 md:p-8',
normal: 'p-8 md:p-10',
large: 'p-10 md:p-12'
};
return (
<div className={cn(
"rounded-2xl border h-full flex flex-col justify-between transition-all duration-500 ease-out",
variants[variant],
paddings[padding],
hover ? 'hover:border-slate-200 hover:shadow-md' : '',
className
)}>
{children}
</div>
);
};
export const Container: React.FC<{ children: React.ReactNode; className?: string; variant?: 'narrow' | 'normal' | 'wide' }> = ({
children,
className = "",
variant = 'normal'
}) => {
const variants = {
narrow: 'max-w-4xl',
normal: 'max-w-6xl',
wide: 'max-w-7xl'
};
return (
<div className={cn("mx-auto px-6 w-full", variants[variant], className)}>
{children}
</div>
);
};

View File

@@ -2,6 +2,8 @@ import * as React from 'react';
import { ArrowLeft } from 'lucide-react'; import { ArrowLeft } from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
import { Reveal } from './Reveal'; import { Reveal } from './Reveal';
import { H1, LeadText } from './Typography';
import { cn } from '../utils/cn';
interface PageHeaderProps { interface PageHeaderProps {
title: React.ReactNode; title: React.ReactNode;
@@ -11,18 +13,20 @@ interface PageHeaderProps {
label: string; label: string;
}; };
backgroundSymbol?: string; backgroundSymbol?: string;
className?: string;
} }
export const PageHeader: React.FC<PageHeaderProps> = ({ export const PageHeader: React.FC<PageHeaderProps> = ({
title, title,
description, description,
backLink, backLink,
backgroundSymbol backgroundSymbol,
className = ""
}) => { }) => {
return ( return (
<section className="narrow-container relative"> <section className={cn("narrow-container relative pt-24 pb-16 md:pt-40 md:pb-24", className)}>
{backgroundSymbol && ( {backgroundSymbol && (
<div className="absolute -left-24 -top-24 text-[20rem] font-bold text-slate-50 select-none -z-10 opacity-50"> <div className="absolute -left-24 -top-12 text-[20rem] md:text-[24rem] font-bold text-slate-50 select-none -z-10 opacity-40 tracking-tighter leading-none">
{backgroundSymbol} {backgroundSymbol}
</div> </div>
)} )}
@@ -30,24 +34,24 @@ export const PageHeader: React.FC<PageHeaderProps> = ({
{backLink && ( {backLink && (
<Link <Link
href={backLink.href} href={backLink.href}
className="inline-flex items-center gap-3 px-4 py-2 border border-slate-200 rounded-full text-slate-400 hover:text-slate-900 hover:border-slate-400 hover:bg-slate-50 mb-12 transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] hover:-translate-y-0.5 hover:shadow-lg hover:shadow-slate-100 font-bold text-[10px] uppercase tracking-[0.3em] group" className="inline-flex items-center gap-2 text-slate-400 hover:text-slate-900 mb-12 transition-colors font-bold text-[10px] uppercase tracking-[0.4em] group"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> {backLink.label} <ArrowLeft className="w-3 h-3 group-hover:-translate-x-1 transition-transform" /> {backLink.label}
</Link> </Link>
)} )}
<div className="space-y-16"> <div className="space-y-8 relative">
<Reveal> <Reveal>
<h1 className="text-6xl md:text-8xl font-bold text-slate-900 tracking-tighter leading-[0.95]"> <H1 className="max-w-4xl">
{title} {title}
</h1> </H1>
</Reveal> </Reveal>
{description && ( {description && (
<Reveal delay={0.2}> <Reveal delay={0.2}>
<p className="text-2xl md:text-3xl text-slate-500 font-serif italic leading-snug max-w-3xl"> <LeadText className="text-xl md:text-2xl text-slate-400 leading-relaxed max-w-2xl font-serif italic">
{description} {description}
</p> </LeadText>
</Reveal> </Reveal>
)} )}
</div> </div>

View File

@@ -1,5 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { Reveal } from './Reveal'; import { Reveal } from './Reveal';
import { Label } from './Typography';
import { cn } from '../utils/cn';
interface SectionProps { interface SectionProps {
number?: string; number?: string;
@@ -9,7 +11,7 @@ interface SectionProps {
delay?: number; delay?: number;
variant?: 'white' | 'gray'; variant?: 'white' | 'gray';
borderTop?: boolean; borderTop?: boolean;
connector?: React.ReactNode; borderBottom?: boolean;
containerVariant?: 'narrow' | 'normal' | 'wide'; containerVariant?: 'narrow' | 'normal' | 'wide';
illustration?: React.ReactNode; illustration?: React.ReactNode;
} }
@@ -22,93 +24,59 @@ export const Section: React.FC<SectionProps> = ({
delay = 0, delay = 0,
variant = 'white', variant = 'white',
borderTop = false, borderTop = false,
connector, borderBottom = false,
containerVariant = 'narrow', containerVariant = 'narrow',
illustration, illustration,
}) => { }) => {
const bgClass = variant === 'gray' ? 'bg-slate-50' : 'bg-white'; const bgClass = variant === 'gray' ? 'bg-slate-50/50' : 'bg-white';
const borderClass = borderTop ? 'border-t border-slate-100' : ''; const borderTopClass = borderTop ? 'border-t border-slate-100' : '';
const borderBottomClass = borderBottom ? 'border-b border-slate-100' : '';
const containerClass = containerVariant === 'wide' ? 'wide-container' : containerVariant === 'normal' ? 'container' : 'narrow-container'; const containerClass = containerVariant === 'wide' ? 'wide-container' : containerVariant === 'normal' ? 'container' : 'narrow-container';
// If no number and title, or if we want to force a simple layout, we could add a prop.
// But let's make it smart: if it's wide, maybe we want the title on top anyway?
// The user specifically asked to move it above for the configurator.
const isTopTitle = containerVariant === 'wide';
return ( return (
<section className={`relative py-24 md:py-32 group ${bgClass} ${borderClass} ${className}`}> <section className={cn(
<div className={containerClass}> "relative py-24 md:py-40 group overflow-hidden",
{isTopTitle ? ( bgClass,
<div className="space-y-16"> borderTopClass,
{(number || title) && ( borderBottomClass,
<div className="flex flex-col md:flex-row md:items-end gap-6 md:gap-12"> className
{number && ( )}>
<Reveal delay={delay}> <div className={cn("relative z-10", containerClass)}>
<span className="block text-6xl md:text-8xl font-bold text-slate-100 leading-none select-none"> <div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-24">
{number} {/* Sidebar: Number & Title */}
</span> <div className="md:col-span-3">
</Reveal> <div className="md:sticky md:top-40 space-y-8">
)} {number && (
{title && ( <Reveal delay={delay}>
<Reveal delay={delay + 0.1}> <span className="block text-7xl md:text-8xl font-bold text-slate-100 leading-none select-none tracking-tighter">
<div className="flex items-center gap-3 mb-2 md:mb-4"> {number}
<div className="h-px w-6 bg-slate-900"></div> </span>
<h2 className="text-xs font-bold uppercase tracking-[0.3em] text-slate-900"> </Reveal>
{title} )}
</h2> {title && (
</div> <Reveal delay={delay + 0.1}>
</Reveal> <div className="flex items-center gap-4">
)} <Label className="text-slate-900 text-[10px] tracking-[0.4em]">
</div> {title}
)} </Label>
<div>{children}</div> </div>
</div> </Reveal>
) : ( )}
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-16"> {illustration && (
{/* Sidebar: Number & Title */} <Reveal delay={delay + 0.2}>
<div className="md:col-span-3 relative"> <div className="pt-8 opacity-100 group-hover:scale-105 transition-transform duration-1000 ease-out origin-left grayscale hover:grayscale-0">
{/* Connector Line */} {illustration}
{connector && ( </div>
<div className="absolute left-[2.5rem] top-0 bottom-0 w-24 hidden md:block -z-10 pointer-events-none"> </Reveal>
{connector}
</div>
)} )}
<div className="md:sticky md:top-32 space-y-6">
{number && (
<Reveal delay={delay}>
<span className="block text-6xl md:text-8xl font-bold text-slate-100 leading-none select-none relative bg-white/0 backdrop-blur-[2px]">
{number}
</span>
</Reveal>
)}
{title && (
<Reveal delay={delay + 0.1}>
<div className="flex items-center gap-3">
<div className="h-px w-6 bg-slate-900"></div>
<h2 className="text-xs font-bold uppercase tracking-[0.3em] text-slate-900">
{title}
</h2>
</div>
</Reveal>
)}
{illustration && (
<Reveal delay={delay + 0.2}>
<div className="pt-12 opacity-100 group-hover:scale-110 transition-transform duration-700 origin-left">
{illustration}
</div>
</Reveal>
)}
</div>
</div>
{/* Main Content */}
<div className="md:col-span-9">
{children}
</div> </div>
</div> </div>
)}
{/* Main Content */}
<div className="md:col-span-9">
{children}
</div>
</div>
</div> </div>
</section> </section>
); );

View File

@@ -0,0 +1,54 @@
import * as React from 'react';
interface TypographyProps {
children: React.ReactNode;
className?: string;
}
export const H1: React.FC<TypographyProps> = ({ children, className = "" }) => (
<h1 className={`text-5xl md:text-7xl font-bold text-slate-900 tracking-tighter leading-[1.1] ${className}`}>
{children}
</h1>
);
export const H2: React.FC<TypographyProps> = ({ children, className = "" }) => (
<h2 className={`text-3xl md:text-5xl font-bold text-slate-900 tracking-tighter leading-tight ${className}`}>
{children}
</h2>
);
export const H3: React.FC<TypographyProps> = ({ children, className = "" }) => (
<h3 className={`text-2xl md:text-4xl font-bold text-slate-900 tracking-tight leading-tight ${className}`}>
{children}
</h3>
);
export const H4: React.FC<TypographyProps> = ({ children, className = "" }) => (
<h4 className={`text-xl md:text-2xl font-bold text-slate-900 tracking-tight ${className}`}>
{children}
</h4>
);
export const LeadText: React.FC<TypographyProps> = ({ children, className = "" }) => (
<p className={`text-lg md:text-xl font-serif italic text-slate-500 leading-relaxed ${className}`}>
{children}
</p>
);
export const BodyText: React.FC<TypographyProps> = ({ children, className = "" }) => (
<p className={`text-base text-slate-500 leading-relaxed ${className}`}>
{children}
</p>
);
export const Label: React.FC<TypographyProps> = ({ children, className = "" }) => (
<span className={`text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400 block ${className}`}>
{children}
</span>
);
export const MonoLabel: React.FC<TypographyProps> = ({ children, className = "" }) => (
<span className={`text-[10px] font-mono uppercase tracking-[0.2em] text-slate-400 block ${className}`}>
{children}
</span>
);

6
src/utils/cn.ts Normal file
View File

@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}