This commit is contained in:
2026-01-29 22:20:50 +01:00
parent 802d707487
commit 936a997f03
4 changed files with 346 additions and 51 deletions

View File

@@ -1,8 +1,8 @@
import * as React from 'react'; import * as React from 'react';
import { Zap, Shield, MousePointer2, Sparkles, ArrowRight, Check, X } from 'lucide-react'; import { Zap, Shield, MousePointer2, Sparkles, ArrowRight, Check, X, Layout, Database, Workflow } from 'lucide-react';
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 { HeroItem, FeatureCard, ComparisonRow, ServiceCard, HeroLines, GridLines, FlowLines, CirclePattern } from '../src/components/Landing'; import { HeroItem, FeatureCard, ComparisonRow, ServiceCard, HeroLines, GridLines, FlowLines, CirclePattern, ServicesFlow, ComparisonLines, ConnectorStart, ConnectorBranch, ConnectorSplit, ConnectorEnd } from '../src/components/Landing';
export default function LandingPage() { export default function LandingPage() {
return ( return (
@@ -14,8 +14,13 @@ export default function LandingPage() {
}} /> }} />
{/* Hero Section - Split Layout */} {/* Hero Section - Split Layout */}
<section className="relative min-h-[90vh] flex items-center pt-24 pb-24 md:pb-0"> <section className="relative min-h-[80vh] flex items-center pt-12 md:pt-0 pb-24 md:pb-0">
<div className="narrow-container w-full"> <div className="narrow-container w-full relative">
{/* Connector Start for Hero */}
<div className="absolute left-[2.5rem] top-32 bottom-0 w-24 hidden md:block -z-10 pointer-events-none">
<ConnectorStart className="h-full" />
</div>
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-16 items-center"> <div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-16 items-center">
{/* Left Column: Brand & Number */} {/* Left Column: Brand & Number */}
<div className="md:col-span-5 relative z-10"> <div className="md:col-span-5 relative z-10">
@@ -44,7 +49,7 @@ export default function LandingPage() {
</div> </div>
{/* Right Column: Visual & Context */} {/* Right Column: Visual & Context */}
<div className="md:col-span-7 relative h-[500px] md:h-[800px] flex items-center justify-center"> <div className="md:col-span-7 relative h-[400px] md:h-[600px] flex items-center justify-center">
{/* Abstract Lines Illustration */} {/* Abstract Lines Illustration */}
<div className="absolute inset-0 -z-10 opacity-80 pointer-events-none"> <div className="absolute inset-0 -z-10 opacity-80 pointer-events-none">
<HeroLines className="w-full h-full" /> <HeroLines className="w-full h-full" />
@@ -53,15 +58,14 @@ export default function LandingPage() {
<Reveal delay={0.2}> <Reveal delay={0.2}>
<div className="relative bg-white/80 backdrop-blur-sm p-8 md:p-12 border border-slate-100 rounded-2xl shadow-2xl shadow-slate-100/50 max-w-md mx-auto"> <div className="relative bg-white/80 backdrop-blur-sm p-8 md:p-12 border border-slate-100 rounded-2xl shadow-2xl shadow-slate-100/50 max-w-md mx-auto">
<div className="absolute -top-6 -left-6 w-12 h-12 bg-slate-900 text-white flex items-center justify-center rounded-full font-bold text-xl"> <div className="absolute -top-6 -left-6 w-12 h-12 bg-slate-900 text-white flex items-center justify-center rounded-full font-bold text-xl">
00 01
</div> </div>
<p className="text-xl md:text-2xl font-serif italic text-slate-600 leading-relaxed"> <p className="text-xl md:text-2xl font-serif italic text-slate-600 leading-relaxed">
"Ich baue digitale Systeme für Unternehmen, die Ergebnisse wollen ohne Agentur-Zirkus, ohne Overhead, ohne Tech-Blabla." "Ich baue digitale Systeme für Unternehmen, die Ergebnisse wollen ohne Agentur-Zirkus, ohne Overhead, ohne Tech-Blabla."
</p> </p>
<div className="mt-6 flex items-center gap-4"> <div className="mt-6 flex items-center gap-4">
<div className="w-10 h-10 bg-slate-100 rounded-full overflow-hidden"> <div className="w-10 h-10 bg-slate-100 rounded-full overflow-hidden flex items-center justify-center text-slate-400 font-bold">
{/* Placeholder for avatar if needed, or just a symbol */} M
<div className="w-full h-full flex items-center justify-center text-slate-400 font-bold">M</div>
</div> </div>
<div className="text-xs font-bold uppercase tracking-widest text-slate-900"> <div className="text-xs font-bold uppercase tracking-widest text-slate-900">
Marc Mintel Marc Mintel
@@ -74,8 +78,8 @@ export default function LandingPage() {
</div> </div>
</section> </section>
{/* Section 01: The Promise */} {/* Section 02: The Promise */}
<Section number="01" title="Das Versprechen" borderTop> <Section number="02" title="Das Versprechen" 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"> <div className="absolute right-0 top-0 w-64 h-64 -z-10 opacity-30 pointer-events-none">
<GridLines /> <GridLines />
@@ -136,16 +140,21 @@ export default function LandingPage() {
</div> </div>
</Section> </Section>
{/* Section 02: The Difference */} {/* Section 03: The Difference */}
<Section number="02" title="Der Unterschied" variant="gray" borderTop> <Section number="03" title="Der Unterschied" variant="white" borderTop connector={<ConnectorStart className="h-full" />}>
<div className="space-y-12"> <div className="space-y-12 relative">
{/* Animated Vertical Line */}
<div className="absolute left-1/2 top-24 bottom-0 -translate-x-1/2 hidden md:block w-24 h-full pointer-events-none z-0">
<ComparisonLines className="w-full h-full" />
</div>
<Reveal> <Reveal>
<p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl"> <p className="text-xl md:text-2xl font-serif italic text-slate-600 max-w-2xl relative z-10">
Der klassische Agentur-Weg ist oft langsam und teuer. Mein Ansatz ist radikal anders: Ich baue zuerst, dann reden wir über Details. Der klassische Agentur-Weg ist oft langsam und teuer. Mein Ansatz ist radikal anders: Ich baue zuerst, dann reden wir über Details.
</p> </p>
</Reveal> </Reveal>
<div className="grid grid-cols-1 gap-6"> <div className="grid grid-cols-1 gap-6 relative z-10">
<ComparisonRow <ComparisonRow
negativeLabel="Agentur" negativeLabel="Agentur"
negativeText="Konzeptcalls, Meetings, Slides, Warten auf das Angebot." negativeText="Konzeptcalls, Meetings, Slides, Warten auf das Angebot."
@@ -172,33 +181,33 @@ export default function LandingPage() {
</div> </div>
</Section> </Section>
{/* Section 03: Target Group */} {/* Section 04: Target Group */}
<Section number="03" title="Zielgruppe" borderTop> <Section number="04" title="Zielgruppe" borderTop connector={<ConnectorSplit className="h-full" />}>
<div className="relative"> <div className="relative">
<div className="absolute left-0 top-0 w-full h-full -z-10 opacity-30 pointer-events-none"> <div className="absolute left-0 top-0 w-full h-full -z-10 opacity-30 pointer-events-none">
<CirclePattern /> <CirclePattern />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<Reveal> <Reveal>
<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"> <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"> <div className="space-y-6">
<div className="w-12 h-12 bg-white/10 rounded-xl flex items-center justify-center"> <div className="w-12 h-12 bg-white/10 rounded-xl flex items-center justify-center">
<Zap className="w-6 h-6 text-white" /> <Zap className="w-6 h-6 text-white" />
</div> </div>
<h3 className="text-3xl font-bold tracking-tight">Unternehmer & <br/>Geschäftsführer</h3> <h3 className="text-3xl font-bold tracking-tight text-white">Unternehmer & <br/>Geschäftsführer</h3>
<p className="text-slate-400 font-serif italic text-lg leading-relaxed"> <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." "Ich brauche eine Lösung, die funktioniert. Ich habe keine Zeit für technische Details oder lange Meetings."
</p> </p>
</div> </div>
<div className="pt-8 border-t border-white/10 mt-8"> <div className="pt-8 border-t border-white/10 mt-8">
<span className="text-xs font-bold uppercase tracking-widest text-slate-500 group-hover:text-white transition-colors">Perfekt für Sie</span> <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>
</div> </div>
</Reveal> </Reveal>
<Reveal delay={0.2}> <Reveal delay={0.2}>
<div className="p-10 bg-slate-50 border border-slate-100 rounded-3xl h-full flex flex-col justify-between group hover:border-slate-300 transition-colors duration-500"> <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"> <div className="space-y-6">
<div className="w-12 h-12 bg-white border border-slate-200 rounded-xl flex items-center justify-center"> <div className="w-12 h-12 bg-slate-50 border border-slate-200 rounded-xl flex items-center justify-center">
<Shield className="w-6 h-6 text-slate-900" /> <Shield className="w-6 h-6 text-slate-900" />
</div> </div>
<h3 className="text-3xl font-bold tracking-tight text-slate-900">Marketing & <br/>Vertrieb</h3> <h3 className="text-3xl font-bold tracking-tight text-slate-900">Marketing & <br/>Vertrieb</h3>
@@ -215,31 +224,59 @@ export default function LandingPage() {
</div> </div>
</Section> </Section>
{/* Section 04: Services */} {/* Section 05: Services - Visual Flow */}
<Section number="04" title="Leistungen" variant="gray" borderTop> <Section number="05" title="Leistungen" variant="gray" borderTop connector={<ConnectorBranch className="h-full" />}>
<div className="grid grid-cols-1 gap-8"> <div className="relative py-12">
<ServiceCard {/* Connecting Line Illustration */}
title="Websites" <div className="absolute top-1/2 left-0 w-full -translate-y-1/2 hidden md:block">
description="High-Performance Websites. Kein Baukasten, sondern maßgeschneiderte Architektur für maximale Geschwindigkeit und SEO." <ServicesFlow />
linkHref="/websites" </div>
linkLabel="Preise ansehen"
delay={0.1} <div className="grid grid-cols-1 md:grid-cols-3 gap-8 relative z-10">
/> <Reveal delay={0.1}>
<ServiceCard <div className="bg-white p-8 rounded-2xl border border-slate-100 shadow-lg hover:shadow-xl transition-all duration-300 group h-full">
title="Systeme" <div className="w-16 h-16 bg-slate-50 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500">
description="Web-Applikationen, Kundenportale, interne Tools. Wenn Standard-Software an ihre Grenzen stößt." <Layout className="w-8 h-8 text-slate-900" />
delay={0.2} </div>
/> <h3 className="text-2xl font-bold text-slate-900 mb-4">Websites</h3>
<ServiceCard <p className="text-slate-500 font-serif italic mb-6">
title="Automatisierung" High-Performance Websites. Kein Baukasten, sondern maßgeschneiderte Architektur.
description="Verbindung von Tools, automatische PDF-Erstellung, Daten-Synchronisation. Sparen Sie manuelle Arbeit." </p>
delay={0.3} <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>
</div>
</Reveal>
<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">
<div className="w-16 h-16 bg-slate-50 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500">
<Database className="w-8 h-8 text-slate-900" />
</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>
</Reveal>
<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">
<div className="w-16 h-16 bg-slate-50 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500">
<Workflow className="w-8 h-8 text-slate-900" />
</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>
</Reveal>
</div>
</div> </div>
</Section> </Section>
{/* Section 05: Contact */} {/* Section 06: Contact */}
<Section number="05" title="Kontakt" borderTop> <Section number="06" title="Kontakt" 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"> <div className="absolute right-0 top-1/2 -translate-y-1/2 w-[400px] h-[200px] -z-10 opacity-40 pointer-events-none">
<FlowLines /> <FlowLines />
@@ -257,10 +294,10 @@ export default function LandingPage() {
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 24 Stunden mit einer ersten Einschätzung.
</p> </p>
<a <a
href="mailto:hello@mintel.me" href="/contact"
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" 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"
> >
hello@mintel.me Projekt anfragen
</a> </a>
</div> </div>

View File

@@ -4,7 +4,7 @@ export const Footer: React.FC = () => {
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
return ( return (
<footer className="py-16 mt-24 border-t border-slate-100"> <footer className="py-16 mt-24 border-t border-slate-100 bg-white relative z-10">
<div className="narrow-container"> <div className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 items-end"> <div className="grid grid-cols-1 md:grid-cols-2 gap-12 items-end">
<div className="space-y-8"> <div className="space-y-8">
@@ -22,7 +22,7 @@ export const Footer: React.FC = () => {
<div className="flex flex-col md:items-end gap-4 text-sm font-mono text-slate-300 uppercase tracking-widest"> <div className="flex flex-col md:items-end gap-4 text-sm font-mono text-slate-300 uppercase tracking-widest">
<span>© {currentYear}</span> <span>© {currentYear}</span>
<div className="flex gap-8"> <div className="flex gap-8">
<a href="mailto:marc@mintel.me" className="hover:text-slate-900 transition-colors no-underline">Email</a> <a href="/contact" className="hover:text-slate-900 transition-colors no-underline">Kontakt</a>
<a href="https://github.com/marcmintel" className="hover:text-slate-900 transition-colors no-underline">GitHub</a> <a href="https://github.com/marcmintel" className="hover:text-slate-900 transition-colors no-underline">GitHub</a>
</div> </div>
</div> </div>

View File

@@ -8,6 +8,7 @@ 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">
@@ -31,6 +32,23 @@ export const HeroLines: React.FC<LineProps> = ({ className = "", delay = 0 }) =>
animate={{ pathLength: 1, opacity: 1 }} animate={{ pathLength: 1, opacity: 1 }}
transition={{ duration: 2.5, delay: delay + 0.2, ease: "easeInOut" }} transition={{ duration: 2.5, delay: delay + 0.2, ease: "easeInOut" }}
/> />
{/* Animated Pulses */}
<motion.circle r="3" fill="currentColor" className="text-slate-300">
<animateMotion
dur="6s"
repeatCount="indefinite"
path="M-100 300 C 100 300, 200 100, 400 100 C 600 100, 700 500, 900 500"
/>
</motion.circle>
<motion.circle r="3" fill="currentColor" className="text-slate-200">
<animateMotion
dur="8s"
repeatCount="indefinite"
path="M-100 350 C 100 350, 200 150, 400 150 C 600 150, 700 550, 900 550"
/>
</motion.circle>
{/* Nodes */} {/* Nodes */}
<motion.circle cx="400" cy="100" r="4" className="fill-slate-200" <motion.circle cx="400" cy="100" r="4" className="fill-slate-200"
initial={{ scale: 0 }} animate={{ scale: 1 }} transition={{ delay: delay + 1, duration: 0.5 }} /> initial={{ scale: 0 }} animate={{ scale: 1 }} transition={{ delay: delay + 1, duration: 0.5 }} />
@@ -63,6 +81,13 @@ export const GridLines: React.FC<LineProps> = ({ className = "", delay = 0 }) =>
viewport={{ once: true }} viewport={{ once: true }}
transition={{ duration: 1.5, delay: delay }} transition={{ duration: 1.5, delay: delay }}
/> />
{/* Active Cells */}
<motion.rect x="120" y="40" width="40" height="40" className="fill-slate-50"
initial={{ opacity: 0 }} animate={{ opacity: [0, 0.5, 0] }} transition={{ duration: 3, repeat: Infinity, repeatDelay: 2 }} />
<motion.rect x="160" y="80" width="40" height="40" className="fill-slate-50"
initial={{ opacity: 0 }} animate={{ opacity: [0, 0.5, 0] }} transition={{ duration: 4, repeat: Infinity, repeatDelay: 1 }} />
<motion.circle cx="200" cy="120" r="3" className="fill-slate-400" <motion.circle cx="200" cy="120" r="3" className="fill-slate-400"
initial={{ scale: 0 }} whileInView={{ scale: 1 }} viewport={{ once: true }} transition={{ delay: delay + 1.5 }} /> initial={{ scale: 0 }} whileInView={{ scale: 1 }} viewport={{ once: true }} transition={{ delay: delay + 1.5 }} />
</svg> </svg>
@@ -93,6 +118,15 @@ export const FlowLines: React.FC<LineProps> = ({ className = "", delay = 0 }) =>
transition={{ duration: 1.5, delay: delay + 0.2 }} transition={{ duration: 1.5, delay: delay + 0.2 }}
/> />
{/* Pulse */}
<motion.circle r="2" fill="currentColor" className="text-slate-400">
<animateMotion
dur="4s"
repeatCount="indefinite"
path="M 0 100 H 100 C 150 100, 150 50, 200 50 H 300"
/>
</motion.circle>
<motion.rect x="300" y="30" width="80" height="40" rx="8" className="stroke-slate-300 fill-white" strokeWidth="1" <motion.rect x="300" y="30" width="80" height="40" rx="8" className="stroke-slate-300 fill-white" strokeWidth="1"
initial={{ opacity: 0, x: 280 }} whileInView={{ opacity: 1, x: 300 }} viewport={{ once: true }} transition={{ delay: delay + 1 }} /> initial={{ opacity: 0, x: 280 }} whileInView={{ opacity: 1, x: 300 }} viewport={{ once: true }} transition={{ delay: delay + 1 }} />
@@ -111,6 +145,221 @@ export const CirclePattern: React.FC<LineProps> = ({ className = "", delay = 0 }
initial={{ scale: 0.8, opacity: 0 }} whileInView={{ scale: 1, opacity: 1 }} viewport={{ once: true }} transition={{ duration: 1, delay: delay + 0.2 }} /> initial={{ scale: 0.8, opacity: 0 }} whileInView={{ scale: 1, opacity: 1 }} viewport={{ once: true }} transition={{ duration: 1, delay: delay + 0.2 }} />
<motion.circle cx="200" cy="200" r="50" stroke="currentColor" strokeWidth="1" className="text-slate-200" <motion.circle cx="200" cy="200" r="50" stroke="currentColor" strokeWidth="1" className="text-slate-200"
initial={{ scale: 0.8, opacity: 0 }} whileInView={{ scale: 1, opacity: 1 }} viewport={{ once: true }} transition={{ duration: 1, delay: delay + 0.4 }} /> initial={{ scale: 0.8, opacity: 0 }} whileInView={{ scale: 1, opacity: 1 }} viewport={{ once: true }} transition={{ duration: 1, delay: delay + 0.4 }} />
{/* Rotating Ring */}
<motion.circle cx="200" cy="200" r="120" stroke="currentColor" strokeWidth="1" strokeDasharray="10 10" className="text-slate-200"
animate={{ rotate: 360 }} transition={{ duration: 20, repeat: Infinity, ease: "linear" }} />
</svg> </svg>
) )
} }
export const ServicesFlow: React.FC<LineProps> = ({ className = "", delay = 0 }) => {
return (
<svg className={`absolute pointer-events-none ${className}`} viewBox="0 0 1000 200" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* Path connecting the 3 steps */}
<motion.path
d="M 100 100 L 900 100"
stroke="currentColor"
strokeWidth="3"
strokeDasharray="8 8"
className="text-slate-300"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 2, delay: delay }}
/>
{/* Animated pulse moving along the line */}
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="3s"
repeatCount="indefinite"
path="M 100 100 L 900 100"
/>
</motion.circle>
{/* Second pulse with delay */}
<motion.circle r="5" fill="currentColor" className="text-slate-900">
<animateMotion
dur="3s"
begin="1.5s"
repeatCount="indefinite"
path="M 100 100 L 900 100"
/>
</motion.circle>
</svg>
);
};
export const ComparisonLines: 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 400"
stroke="currentColor"
strokeWidth="3"
strokeDasharray="4 4"
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>
</svg>
)
}
// --- New Connector Components ---
export const ConnectorStart: 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 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

@@ -9,6 +9,7 @@ interface SectionProps {
delay?: number; delay?: number;
variant?: 'white' | 'gray'; variant?: 'white' | 'gray';
borderTop?: boolean; borderTop?: boolean;
connector?: React.ReactNode;
} }
export const Section: React.FC<SectionProps> = ({ export const Section: React.FC<SectionProps> = ({
@@ -19,6 +20,7 @@ export const Section: React.FC<SectionProps> = ({
delay = 0, delay = 0,
variant = 'white', variant = 'white',
borderTop = false, borderTop = false,
connector,
}) => { }) => {
const bgClass = variant === 'gray' ? 'bg-slate-50' : 'bg-white'; const bgClass = variant === 'gray' ? 'bg-slate-50' : 'bg-white';
const borderClass = borderTop ? 'border-t border-slate-100' : ''; const borderClass = borderTop ? 'border-t border-slate-100' : '';
@@ -29,10 +31,17 @@ export const Section: React.FC<SectionProps> = ({
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-16"> <div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-16">
{/* Sidebar: Number & Title */} {/* Sidebar: Number & Title */}
<div className="md:col-span-3 relative"> <div className="md:col-span-3 relative">
{/* Connector Line */}
{connector && (
<div className="absolute left-[2.5rem] top-0 bottom-0 w-24 hidden md:block -z-10 pointer-events-none">
{connector}
</div>
)}
<div className="md:sticky md:top-32 space-y-6"> <div className="md:sticky md:top-32 space-y-6">
{number && ( {number && (
<Reveal delay={delay}> <Reveal delay={delay}>
<span className="block text-6xl md:text-8xl font-bold text-slate-100 leading-none select-none"> <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} {number}
</span> </span>
</Reveal> </Reveal>