MVp
This commit is contained in:
31
app/(routes)/about/page.tsx
Normal file
31
app/(routes)/about/page.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { cookies, headers } from 'next/headers'
|
||||
import { getDictionary, getInitialLocale } from '@/lib/i18n'
|
||||
export default async function AboutPage() {
|
||||
const cookieStore = cookies()
|
||||
const hdrs = headers()
|
||||
const locale = getInitialLocale(cookieStore, hdrs)
|
||||
const dict = await getDictionary(locale)
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<h1 className="h1">Über Michael Peskov</h1>
|
||||
<div className="grid grid--2 mt-4">
|
||||
<div className="card">
|
||||
<h3 className="h3">Michael Peskov – Deutschlands jüngster Profi‑Zauberkünstler & Taschendieb</h3>
|
||||
<p>
|
||||
Aus Solingen stammend, ist Michael bereits eines der bekanntesten magischen Talente Deutschlands – gezeigt in Formaten von SAT.1, WDR, ZDF und Amazon Prime Video. Schon mit sechs Jahren von der Magie gepackt, verzaubert er heute mit tänzerischer Leichtigkeit und jugendlicher Dynamik Kunden verschiedenster Events.
|
||||
</p>
|
||||
<p>
|
||||
Interaktiv, witzig, verändernd – sein Ziel: Langweile eliminieren, Gespräche entfachen und unvergessliche Momente schaffen. Ob hautnah bei kleinen Gruppen oder groß inszeniert auf der Bühne – Michael passt sich jeder Veranstaltung flexibel an und bringt nicht nur Magie, sondern echte Emotion. Profi‑Organisation, offene Kommunikation und maximale Zuverlässigkeit inklusive.
|
||||
</p>
|
||||
</div>
|
||||
<aside className="card">
|
||||
<div className="badge">5 von 5 Sternen • 100% Weiterempfehlung</div>
|
||||
<div className="badge">42699 Solingen • Aktionsradius > 1000 km</div>
|
||||
<div className="badge">SAT.1 • WDR • ZDF • Amazon Prime Video</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
141
app/(routes)/contact/page.tsx
Normal file
141
app/(routes)/contact/page.tsx
Normal file
@@ -0,0 +1,141 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Kontakt – Michael Peskov | Zauberer Solingen & NRW – Magier buchen für Hochzeit & Firmenfeier',
|
||||
description:
|
||||
'Planen Sie Ihr Event mit Michael Peskov: Close-up Magie, Taschendieb‑Show, Walking Act & Bühnenzauber. 5/5 Sterne (12), 100% Empfehlung. Solingen, Düsseldorf, Köln, NRW – europaweit (>1000 km). Antwort innerhalb von 24h.'
|
||||
}
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
{/* 1. Headline with main keyword */}
|
||||
<header className="mb-6">
|
||||
<h1 className="h1">Zauberer Solingen – Kontakt & Angebot</h1>
|
||||
{/* 2. Intro paragraph (USP + 24h response, natural keywords) */}
|
||||
<p>
|
||||
Magier buchen leicht gemacht: Innerhalb von 24 Stunden erhalten Sie ein maßgeschneidertes Konzept –
|
||||
unverbindlich und passgenau für Ihren Anlass. Ob <strong>Close‑up Magie</strong> als <strong>Walking Act</strong>,
|
||||
interaktiver <strong>Bühnenzauber</strong> oder eine verblüffende <strong>Taschendieb‑Show</strong> –
|
||||
Michael Peskov ist Ihr <strong>Zauberer in Solingen</strong> und <strong>Zauberkünstler NRW</strong> für
|
||||
<strong> Firmenfeier</strong>, <strong>Hochzeit</strong> und private Feiern. Profitieren Sie von moderner Präsentation,
|
||||
klarer Kommunikation und einer reibungslosen Organisation – damit Ihre Gäste noch lange über Ihr Event sprechen.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div className="grid grid--2">
|
||||
{/* 3. Booking form section (conversational labels) */}
|
||||
<div className="card" id="booking">
|
||||
<h2 className="h2">Anfrage – in 60 Sekunden</h2>
|
||||
<form className="bookingForm" style={{ marginTop: 16 }}>
|
||||
<div className="grid" style={{ display:'grid', gridTemplateColumns:'repeat(2, minmax(0,1fr))', gap:'16px' }}>
|
||||
<label className="label">Wann findet Ihr Event statt?
|
||||
<input className="input" placeholder="TT.MM.JJJJ" type="date" required />
|
||||
</label>
|
||||
<label className="label">Wo findet es statt?
|
||||
<input className="input" placeholder="Stadt / Location" required />
|
||||
</label>
|
||||
<label className="label">Wie viele Gäste werden erwartet?
|
||||
<input className="input" type="number" min={1} placeholder="z. B. 120" required />
|
||||
</label>
|
||||
<label className="label">Anlass
|
||||
<select className="select" defaultValue="Firmenfeier">
|
||||
<option>Firmenfeier</option>
|
||||
<option>Hochzeit</option>
|
||||
<option>Geburtstag</option>
|
||||
<option>Gala</option>
|
||||
<option>Messe</option>
|
||||
<option>Sonstiges</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<label className="label" style={{ display:'block', marginTop: 12 }}>Erzählen Sie kurz Details (Timing, Location, Wünsche)
|
||||
<textarea className="textarea" placeholder="z. B. Dinner 19:00, Outdoor‑Bühne, zweisprachige Moderation" />
|
||||
</label>
|
||||
{/* 4. Outcome-driven CTA buttons */}
|
||||
<div className="h-stack mt-4">
|
||||
<button className="btn btn--primary" type="submit">Termin prüfen</button>
|
||||
<button className="btn btn--ghost" type="button">Event‑Plan anfordern</button>
|
||||
<button className="btn btn--ghost" type="button">Datum reservieren</button>
|
||||
</div>
|
||||
{/* 7. Privacy reassurance microcopy */}
|
||||
<p className="muted mt-2">Kein Spam – Ihre Angaben nutzen wir ausschließlich zur Planung Ihres Events.</p>
|
||||
|
||||
{/* 5. Alternative contact options (clickable) */}
|
||||
<div className="h-stack mt-6" style={{ flexWrap:'wrap' as const }}>
|
||||
<a className="btn btn--ghost" href="tel:+491234567890" aria-label="Anrufen">📞 Anruf: +49 XXX XXX XXXX</a>
|
||||
<a className="btn btn--ghost" href="https://wa.me/491234567890" target="_blank" rel="noopener">💬 WhatsApp: Jetzt chatten</a>
|
||||
<a className="btn btn--ghost" href="mailto:booking@michaelpeskov.de">📧 E‑Mail: booking@michaelpeskov.de</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/* 6. Trust & speed elements + photo */}
|
||||
<aside>
|
||||
<div className="sparkle ratio-4x5" style={{ marginBottom: 16 }}>
|
||||
<Image
|
||||
src="https://images.eventpeppers.com/sites/default/files/imagecache/lightbox/images/13234/michael-peskov-magier-taschendieb-450252.jpeg"
|
||||
alt="Michael Peskov – Close‑Up Magie mit Gästen"
|
||||
width={1200}
|
||||
height={1500}
|
||||
className="cover"
|
||||
sizes="(max-width: 960px) 100vw, 50vw"
|
||||
/>
|
||||
</div>
|
||||
<ul className="stack" style={{ listStyle:'none', padding:0, margin:0 }}>
|
||||
<li className="badge">✅ Antwort innerhalb von 24 Stunden</li>
|
||||
<li className="badge">📍 Solingen (NRW) • europaweit buchbar (>1000 km Aktionsradius)</li>
|
||||
<li className="badge">⭐ 5/5 Sterne (12), 100% Empfehlung – Eventpeppers</li>
|
||||
<li className="badge badge--accent">Verfügbar in: DE, AT, CH, EU</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
{/* 6. Service area list for local SEO */}
|
||||
<section className="mt-6">
|
||||
<h2 className="h3">Einsatzgebiete & lokale Keywords</h2>
|
||||
<p>
|
||||
Michael ist als <strong>Magier NRW</strong> in <strong>Solingen</strong>, <strong>Zauberer Düsseldorf</strong>,
|
||||
<strong> Zauberer Köln</strong> und ganz NRW unterwegs – ebenso deutschland‑ und europaweit. Ideal für
|
||||
<strong> Zauberer Firmenfeier</strong>, <strong>Zauberer für Hochzeit</strong>, private Feiern und
|
||||
<strong> Event Entertainment</strong>. Buchen Sie moderne <strong>Close‑up Magie</strong>,
|
||||
eine verblüffende <strong>Taschendieb‑Show</strong> oder interaktiven <strong>Bühnenzauber</strong> –
|
||||
auf Wunsch als flexibler <strong>Walking Act</strong>.
|
||||
</p>
|
||||
<ul className="grid grid--3 mt-4" style={{ listStyle:'none', padding:0, margin:0 }}>
|
||||
<li className="badge">Solingen</li>
|
||||
<li className="badge">Düsseldorf</li>
|
||||
<li className="badge">Köln</li>
|
||||
<li className="badge">Wuppertal</li>
|
||||
<li className="badge">Essen</li>
|
||||
<li className="badge">Dortmund</li>
|
||||
<li className="badge">Bonn</li>
|
||||
<li className="badge">Bochum</li>
|
||||
<li className="badge">NRW & Ruhrgebiet</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{/* 8. Closing CTA with internal links */}
|
||||
<section className="cta mt-6">
|
||||
<div>
|
||||
<h2 className="h2">Jetzt Verfügbarkeit prüfen – sichern Sie Ihren Wunschtermin</h2>
|
||||
<p>
|
||||
Buchen Sie <strong>Close‑Up Magie</strong>, <strong>Walking Act</strong>, <strong>Bühnenzauber</strong> oder die
|
||||
<strong> Taschendieb‑Show</strong> von Michael Peskov. Schauen Sie sich auch die{' '}
|
||||
<Link href="/services">Leistungen</Link> und das <Link href="/showreel">Showreel</Link> an.
|
||||
</p>
|
||||
</div>
|
||||
<div className="h-stack">
|
||||
<a className="btn btn--primary" href="#booking">Termin anfragen</a>
|
||||
<Link className="btn btn--ghost" href="/services">Zu den Leistungen</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p className="muted mt-2"><em>P.S.</em> Beliebte Termine sind schnell vergeben – frühe Anfrage erhöht die Chance auf Ihren Wunschslot.</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
8
app/(routes)/legal/page.tsx
Normal file
8
app/(routes)/legal/page.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export default function LegalPage() {
|
||||
return (
|
||||
<section className="container" style={{ paddingBlock: '64px' }}>
|
||||
<h1>Impressum / Datenschutz</h1>
|
||||
<p style={{ color: 'var(--muted)' }}>Legal content placeholder.</p>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
41
app/(routes)/services/page.tsx
Normal file
41
app/(routes)/services/page.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { cookies, headers } from 'next/headers'
|
||||
import { getDictionary, getInitialLocale } from '@/lib/i18n'
|
||||
export default async function ServicesPage() {
|
||||
const cookieStore = cookies()
|
||||
const hdrs = headers()
|
||||
const locale = getInitialLocale(cookieStore, hdrs)
|
||||
const dict = await getDictionary(locale)
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<h1 className="h1">Leistungen</h1>
|
||||
<div className="grid grid--2 mt-4">
|
||||
<article className="card">
|
||||
<h3 className="h3">1. Close-Up & Tischzauberei (Walking Act)</h3>
|
||||
<p>
|
||||
„Perfekt für Hochzeiten, Firmen‑ und Familienfeiern. Michael bewegt sich von Tisch zu Tisch und verzaubert die Gäste hautnah mit Gabeln, die sich verbiegen, Gegenständen, die verschwinden oder erscheinen, und spektakulären Pickpocket‑Tricks.“
|
||||
</p>
|
||||
</article>
|
||||
<article className="card">
|
||||
<h3 className="h3">2. Bühnenshow (interaktiv & humorvoll)</h3>
|
||||
<p>
|
||||
„Eine energiegeladene, interaktive Show, bei der Gäste aktiver Teil der Magie werden. Mit Auszeichnungen, z. B. „punkthöchste Darbietung“ bei der Aufnahmeprüfung im Magischen Zirkel Deutschlands.“
|
||||
</p>
|
||||
</article>
|
||||
<article className="card">
|
||||
<h3 className="h3">3. Taschendieb‑Darbietung (Pickpocketing)</h3>
|
||||
<p>
|
||||
„Spontane Besitzübertragung mit Stil – Handy, Portemonnaie oder Armbanduhr werden mit Witz und Präzision ‘gestohlen’ und danach … natürlich zurückgegeben. Kann auch als Lerneffekt gegen echte Taschendiebe genutzt werden.“
|
||||
</p>
|
||||
</article>
|
||||
<article className="card">
|
||||
<h3 className="h3">4. Gabelbieger (Signature Act)</h3>
|
||||
<p>
|
||||
„Steinhartes Metall wird in Sekundenschnelle verformt – unnachahmlich, selbst im Vergleich mit Uri Geller. Ein bleibendes Souvenir für Gäste und der magische Höhepunkt jeder Veranstaltung.“
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
21
app/(routes)/showreel/page.tsx
Normal file
21
app/(routes)/showreel/page.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { cookies, headers } from 'next/headers'
|
||||
import { getDictionary, getInitialLocale } from '@/lib/i18n'
|
||||
export default async function ShowreelPage() {
|
||||
const cookieStore = cookies()
|
||||
const hdrs = headers()
|
||||
const locale = getInitialLocale(cookieStore, hdrs)
|
||||
const dict = await getDictionary(locale)
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<h1 className="h1">Showreel</h1>
|
||||
<p className="muted">WDR Lokalzeit Düsseldorf, Showreel – Michael Peskov, Promo Video, Zauberkunst – Vielfalt & Stimmung in Clips.</p>
|
||||
<div className="card mt-4">
|
||||
<div className="ratio-16x9 sparkle">
|
||||
<iframe title="WDR Lokalzeit Düsseldorf - Michael Peskov" src="https://www.youtube-nocookie.com/embed/BGAXMeIzu3Q" loading="lazy" width="100%" height="100%" allow="autoplay; encrypted-media; picture-in-picture" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
39
app/(routes)/testimonials/page.tsx
Normal file
39
app/(routes)/testimonials/page.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { cookies, headers } from 'next/headers'
|
||||
import { getDictionary, getInitialLocale } from '@/lib/i18n'
|
||||
export default async function TestimonialsPage() {
|
||||
const cookieStore = cookies()
|
||||
const hdrs = headers()
|
||||
const locale = getInitialLocale(cookieStore, hdrs)
|
||||
const dict = await getDictionary(locale)
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<h1 className="h1">Stimmen</h1>
|
||||
<div className="grid grid--2 mt-4">
|
||||
<blockquote className="testimonial">
|
||||
<p className="testimonial__quote"><strong>„Ein absolut perfekt gelungenes Zauber Event – jeder unserer Gäste war fasziniert … professionell … absolut weiterzuempfehlen!“</strong></p>
|
||||
<div className="testimonial__meta">
|
||||
<div className="avatar" aria-hidden="true" />
|
||||
<div>
|
||||
<div className="muted">Familienfeier, Februar 2023 — Solingen</div>
|
||||
<div className="badge">5 von 5 Sternen • 100% Weiterempfehlung</div>
|
||||
</div>
|
||||
</div>
|
||||
</blockquote>
|
||||
<blockquote className="testimonial">
|
||||
<p className="testimonial__quote"><strong>„Seine Shows sind genial! Seine Energie und Leidenschaft … unvergleichlich. Ich würde jederzeit wiederkommen!“</strong></p>
|
||||
<div className="testimonial__meta">
|
||||
<div className="avatar" aria-hidden="true" />
|
||||
<div>
|
||||
<div className="muted">Bewertung bei ProvenExpert (11/2024)</div>
|
||||
<div className="badge">5 von 5 Sternen</div>
|
||||
</div>
|
||||
</div>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div className="hr" />
|
||||
<p className="muted">Durchschnitt: 5 von 5 Sternen • 100% Weiterempfehlung</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
50
app/globals.css
Normal file
50
app/globals.css
Normal file
@@ -0,0 +1,50 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
}
|
||||
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(15, 23, 42, 0.5);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(59, 130, 246, 0.3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(59, 130, 246, 0.5);
|
||||
}
|
||||
|
||||
/* Reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
}
|
||||
60
app/layout.tsx
Normal file
60
app/layout.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import './globals.css'
|
||||
import '@/styles/premium.css'
|
||||
import type { Metadata, Viewport } from 'next'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Michael Peskov Magic – Moderne Magie für Events | Zauberer NRW',
|
||||
description: 'Bekannt aus SAT.1, WDR, ZDF & Amazon Prime Video. 5★ Zauberer für Corporate Events, Hochzeiten & private Feiern. Deutschlandweit buchbar.',
|
||||
metadataBase: new URL('http://localhost:3000'),
|
||||
openGraph: {
|
||||
title: 'Michael Peskov Magic – Moderne Magie für Events',
|
||||
description: 'Bekannt aus SAT.1, WDR, ZDF & Amazon Prime Video. 5★ Zauberer für Corporate Events, Hochzeiten & private Feiern.',
|
||||
url: '/',
|
||||
siteName: 'Michael Peskov Magic',
|
||||
images: [{
|
||||
url: '/michael-peskov-magier-taschendieb-453624.jpeg',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'Michael Peskov performing magic'
|
||||
}]
|
||||
},
|
||||
keywords: [
|
||||
'Zauberer NRW',
|
||||
'Magier Solingen',
|
||||
'Corporate Entertainment',
|
||||
'Hochzeitszauberer',
|
||||
'Close-up Magic',
|
||||
'Taschendieb Act',
|
||||
'Firmenfeier Entertainment'
|
||||
]
|
||||
}
|
||||
|
||||
export const viewport: Viewport = {
|
||||
themeColor: '#0F1220',
|
||||
colorScheme: 'dark'
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="de" suppressHydrationWarning>
|
||||
<head>
|
||||
<link rel="icon" href="/icon.png" type="image/png" />
|
||||
<link rel="shortcut icon" href="/icon.png" type="image/png" />
|
||||
<link rel="apple-touch-icon" href="/icon.png" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
|
||||
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" media="print" onLoad="this.media='all'" />
|
||||
<noscript>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" />
|
||||
</noscript>
|
||||
</head>
|
||||
<body className="font-sans antialiased">
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
797
app/page.tsx
Normal file
797
app/page.tsx
Normal file
@@ -0,0 +1,797 @@
|
||||
'use client'
|
||||
import React, { useEffect, useMemo, useState } from "react"
|
||||
import { motion } from "framer-motion"
|
||||
import { Check, Star, BadgeCheck, Sparkles, Play, Mail, Phone, Calendar, Building2, ShieldCheck, Clock4, Users2, Zap, Award, Heart } from "lucide-react"
|
||||
import Image from 'next/image'
|
||||
import {
|
||||
FadeUp,
|
||||
StaggerContainer,
|
||||
StaggerItem,
|
||||
ScaleIn,
|
||||
SlideInLeft,
|
||||
SlideInRight,
|
||||
HoverCard,
|
||||
MagneticButton,
|
||||
CountUp,
|
||||
ParallaxElement
|
||||
} from '@/components/ScrollAnimations'
|
||||
import { AnimatedFAQ } from '@/components/AnimatedFAQ'
|
||||
import { VideoPlayer } from '@/components/VideoPlayer'
|
||||
|
||||
// ---- Main Component ----
|
||||
export default function MagicianLandingPage() {
|
||||
const [active, setActive] = useState("home")
|
||||
|
||||
// Simple scroll function
|
||||
const scrollToSection = (sectionId: string) => {
|
||||
console.log('Scrolling to:', sectionId) // Debug log
|
||||
const element = document.getElementById(sectionId)
|
||||
if (element) {
|
||||
const headerOffset = 100
|
||||
const elementPosition = element.getBoundingClientRect().top
|
||||
const offsetPosition = elementPosition + window.pageYOffset - headerOffset
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetPosition,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
} else {
|
||||
console.log('Element not found:', sectionId) // Debug log
|
||||
}
|
||||
}
|
||||
|
||||
// Observe sections to highlight active link
|
||||
useEffect(() => {
|
||||
const ids = ["home", "proof", "showreel", "acts", "usecases", "testimonials", "about", "faq", "contact"]
|
||||
const obs = new IntersectionObserver(
|
||||
(entries) => {
|
||||
const visible = entries
|
||||
.filter((e) => e.isIntersecting)
|
||||
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0]
|
||||
if (visible) setActive(visible.target.id)
|
||||
},
|
||||
{ rootMargin: "-50% 0px -45% 0px", threshold: [0.15, 0.35, 0.6] }
|
||||
)
|
||||
|
||||
ids.forEach((id) => {
|
||||
const el = document.getElementById(id)
|
||||
if (el) obs.observe(el)
|
||||
})
|
||||
|
||||
return () => obs.disconnect()
|
||||
}, [])
|
||||
|
||||
// Data
|
||||
const proof = useMemo(
|
||||
() => ({
|
||||
rating: 5,
|
||||
reviews: 12,
|
||||
bookings: 20,
|
||||
travel: ">1000 km",
|
||||
logos: ["SAT.1", "WDR", "ZDF", "Amazon Prime Video"],
|
||||
clients: [
|
||||
"Mercedes-Benz AG",
|
||||
"Materna TMT",
|
||||
"VIVA Cruises",
|
||||
"AMADA",
|
||||
"IHK",
|
||||
"Lexus",
|
||||
],
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const acts = [
|
||||
{
|
||||
title: "Close-up Magic (Walking)",
|
||||
desc: "Hautnah am Tisch – perfekter Eisbrecher & Gesprächszünder für Empfänge und Dinner.",
|
||||
points: ["Interaktiv mit Gästen", "Flexibel zwischen den Gängen", "Keine Technik nötig"],
|
||||
icon: <Sparkles className="w-8 h-8 text-blue-300" />,
|
||||
gradient: "from-blue-500/20 to-purple-500/20"
|
||||
},
|
||||
{
|
||||
title: "Bühnenshow",
|
||||
desc: "Humorvoll, modern und gemeinschaftsstiftend – ideal für Kickoffs, Galas & Weihnachtsfeiern.",
|
||||
points: ["20–40 Minuten", "Publikumsbeteiligung", "Skalierbar für kleine & große Bühnen"],
|
||||
icon: <Zap className="w-8 h-8 text-yellow-300" />,
|
||||
gradient: "from-yellow-500/20 to-orange-500/20"
|
||||
},
|
||||
{
|
||||
title: "Taschendieb-Act",
|
||||
desc: "Respektvoll, sicher und spektakulär: scheinbarer Diebstahl von Uhr, Krawatte oder Handy – mit Lerneffekt.",
|
||||
points: ["Publikum lacht & lernt", "Immer mit Einverständnis", "Sofortige Wow-Momente"],
|
||||
icon: <Award className="w-8 h-8 text-green-300" />,
|
||||
gradient: "from-green-500/20 to-emerald-500/20"
|
||||
},
|
||||
{
|
||||
title: "Signature: Gabelbiegen",
|
||||
desc: "Metall wird zur Erinnerung – bleibende Souvenirs für Ihre Gäste.",
|
||||
points: ["Starkes visuelles Finale", "Mitnahme-Souvenir", "Perfekt für Fotos"],
|
||||
icon: <Heart className="w-8 h-8 text-pink-300" />,
|
||||
gradient: "from-pink-500/20 to-rose-500/20"
|
||||
},
|
||||
]
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
name: "Corporate Event",
|
||||
quote: "Perfekter Eisbrecher, professionell und absolut verblüffend – unsere Gäste sprechen heute noch davon.",
|
||||
avatar: "🏢"
|
||||
},
|
||||
{
|
||||
name: "Hochzeit",
|
||||
quote: "Familienfreundlich, charmant und mega eindrucksvoll. Die Fotos vom Gabelbiegen lieben wir!",
|
||||
avatar: "💒"
|
||||
},
|
||||
{
|
||||
name: "Weihnachtsfeier",
|
||||
quote: "Zero Cringe, 100% Wow. Super zuverlässig, großartige Kommunikation und pünktlich auf die Minute.",
|
||||
avatar: "🎄"
|
||||
},
|
||||
]
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
q: "Welche Programmlängen sind möglich?",
|
||||
a: "Close-up 60–90 Minuten (walking/tischweise) je nach Gästezahl; Bühne 20–40 Minuten – wir planen es passend zur Agenda.",
|
||||
},
|
||||
{ q: "Welche Technik wird benötigt?", a: "Close-up: keine. Bühne: Licht/PA nach Raumgröße – kann organisiert werden." },
|
||||
{ q: "Wo trittst du auf?", a: "NRW, deutschlandweit und international – Reise >1000 km möglich." },
|
||||
{ q: "Ist der Taschendieb-Act sicher?", a: "Ja – immer respektvoll, nur mit Einverständnis, haftpflichtversichert." },
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<div className="site-bg" aria-hidden="true" />
|
||||
|
||||
{/* NAVBAR */}
|
||||
<nav className="onepage-nav">
|
||||
<div className="onepage-nav-row">
|
||||
<motion.button
|
||||
onClick={() => scrollToSection("home")}
|
||||
className="onepage-brand"
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer' }}
|
||||
>
|
||||
<motion.div
|
||||
className="onepage-brand-logo"
|
||||
whileHover={{ rotate: 360 }}
|
||||
transition={{ duration: 0.8, ease: "easeInOut" }}
|
||||
>
|
||||
<Image src="/icon.png" alt="Michael Peskov Magic Logo" width={20} height={20} />
|
||||
</motion.div>
|
||||
<span>Michael Peskov Magic</span>
|
||||
</motion.button>
|
||||
|
||||
<div className="onepage-nav-links">
|
||||
{[
|
||||
["Proof", "proof"],
|
||||
["Showreel", "showreel"],
|
||||
["Acts", "acts"],
|
||||
["Use Cases", "usecases"],
|
||||
["Testimonials", "testimonials"],
|
||||
["About", "about"],
|
||||
["FAQ", "faq"],
|
||||
].map(([label, id]) => (
|
||||
<motion.button
|
||||
key={id}
|
||||
onClick={() => {
|
||||
const element = document.getElementById(id)
|
||||
if (element) {
|
||||
const y = element.getBoundingClientRect().top + window.scrollY - 88
|
||||
window.scrollTo({ top: y, behavior: "smooth" })
|
||||
}
|
||||
}}
|
||||
className={`onepage-link ${active === id ? "active" : ""}`}
|
||||
whileHover={{ y: -2 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
style={{
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
color: 'inherit',
|
||||
font: 'inherit',
|
||||
padding: '8px 16px'
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</motion.button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="onepage-nav-cta">
|
||||
<MagneticButton>
|
||||
<button
|
||||
onClick={() => {
|
||||
const element = document.getElementById('contact')
|
||||
if (element) {
|
||||
const y = element.getBoundingClientRect().top + window.scrollY - 88
|
||||
window.scrollTo({ top: y, behavior: "smooth" })
|
||||
}
|
||||
}}
|
||||
className="onepage-btn onepage-btn--primary"
|
||||
style={{
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
color: 'inherit',
|
||||
font: 'inherit'
|
||||
}}
|
||||
>
|
||||
Verfügbarkeit prüfen
|
||||
</button>
|
||||
</MagneticButton>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* HERO */}
|
||||
<section id="home" className="onepage-hero">
|
||||
<ParallaxElement speed={0.3} className="spotlight" />
|
||||
<div className="onepage-container">
|
||||
<div className="onepage-hero-grid">
|
||||
<div>
|
||||
<motion.div
|
||||
initial={{opacity:0,y:50}}
|
||||
animate={{opacity:1,y:0}}
|
||||
transition={{duration:0.8, ease: "easeOut"}}
|
||||
>
|
||||
<motion.span
|
||||
className="onepage-eyebrow"
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.2, duration: 0.5 }}
|
||||
>
|
||||
Premium • Modern • Live
|
||||
</motion.span>
|
||||
<motion.h1
|
||||
className="onepage-h1"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.4, duration: 0.8 }}
|
||||
>
|
||||
Moderne Magie, die Menschen verbindet.
|
||||
</motion.h1>
|
||||
<motion.p
|
||||
className="onepage-lead"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.6, duration: 0.6 }}
|
||||
>
|
||||
Bekannt aus {proof.logos.join(" • ")}. <CountUp end={proof.rating} />★ bewertet, <CountUp end={proof.bookings} />+ erfolgreiche Buchungen. Europaweit im Einsatz.
|
||||
</motion.p>
|
||||
<motion.div
|
||||
className="onepage-flex onepage-flex-wrap onepage-gap-3 onepage-mt-6"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.8, duration: 0.6 }}
|
||||
>
|
||||
<MagneticButton>
|
||||
<button
|
||||
onClick={() => scrollToSection("contact")}
|
||||
className="onepage-btn onepage-btn--primary"
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'inherit', font: 'inherit' }}
|
||||
>
|
||||
Verfügbarkeit prüfen
|
||||
</button>
|
||||
</MagneticButton>
|
||||
<MagneticButton>
|
||||
<button
|
||||
onClick={() => scrollToSection("showreel")}
|
||||
className="onepage-btn onepage-btn--ghost"
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'inherit', font: 'inherit', display: 'flex', alignItems: 'center', gap: '8px' }}
|
||||
>
|
||||
<Play className="w-4 h-4"/> Showreel ansehen
|
||||
</button>
|
||||
</MagneticButton>
|
||||
</motion.div>
|
||||
<StaggerContainer className="onepage-flex onepage-flex-wrap onepage-gap-2 onepage-mt-6" staggerDelay={0.1}>
|
||||
{proof.clients.map((c) => (
|
||||
<StaggerItem key={c}>
|
||||
<motion.span
|
||||
className="onepage-badge"
|
||||
whileHover={{ scale: 1.1, y: -2 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Building2 className="w-3 h-3"/> {c}
|
||||
</motion.span>
|
||||
</StaggerItem>
|
||||
))}
|
||||
</StaggerContainer>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<SlideInRight delay={0.4}>
|
||||
<HoverCard className="onepage-card">
|
||||
<VideoPlayer
|
||||
posterImage="/michael-peskov-magier-taschendieb-453624.jpeg"
|
||||
videoUrl="https://www.youtube-nocookie.com/embed/BGAXMeIzu3Q?autoplay=1"
|
||||
title="SAT.1 Showreel"
|
||||
/>
|
||||
<motion.div
|
||||
className="onepage-flex onepage-gap-2 onepage-mt-4 onepage-text"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 1, duration: 0.5 }}
|
||||
>
|
||||
<Star className="w-4 h-4 text-yellow-300"/>
|
||||
<span><CountUp end={proof.rating} />.0 / 5 · <CountUp end={proof.reviews} />+ Bewertungen · <CountUp end={proof.bookings} />+ Buchungen</span>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="onepage-flex onepage-gap-2 onepage-mt-4 onepage-text"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 1.2, duration: 0.5 }}
|
||||
>
|
||||
<ShieldCheck className="w-4 h-4"/> <span>Haftpflicht · Vertrag · Pünktlich</span>
|
||||
</motion.div>
|
||||
</HoverCard>
|
||||
</SlideInRight>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* PROOF */}
|
||||
<section id="proof" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">As seen on & trusted by</span>
|
||||
<h2 className="onepage-h2">TV & Marken, die Vertrauen schaffen</h2>
|
||||
</FadeUp>
|
||||
<StaggerContainer className="onepage-grid onepage-grid--3" staggerDelay={0.1}>
|
||||
{proof.logos.map((l) => (
|
||||
<StaggerItem key={l}>
|
||||
<HoverCard className="onepage-card onepage-text-center">
|
||||
<div className="onepage-h3">{l}</div>
|
||||
</HoverCard>
|
||||
</StaggerItem>
|
||||
))}
|
||||
{proof.clients.map((l) => (
|
||||
<StaggerItem key={l}>
|
||||
<HoverCard className="onepage-card onepage-text-center">
|
||||
<div className="onepage-h3">{l}</div>
|
||||
</HoverCard>
|
||||
</StaggerItem>
|
||||
))}
|
||||
</StaggerContainer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* SHOWREEL */}
|
||||
<section id="showreel" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">Erleben</span>
|
||||
<h2 className="onepage-h2">Showreel & Momente des Staunens</h2>
|
||||
</FadeUp>
|
||||
<ScaleIn delay={0.2}>
|
||||
<HoverCard className="onepage-card">
|
||||
<VideoPlayer
|
||||
posterImage="/michael-peskov-magier-taschendieb-453624.jpeg"
|
||||
videoUrl="https://www.youtube-nocookie.com/embed/BGAXMeIzu3Q?autoplay=1"
|
||||
title="SAT.1 Showreel"
|
||||
/>
|
||||
</HoverCard>
|
||||
</ScaleIn>
|
||||
<StaggerContainer className="onepage-grid onepage-grid--3 onepage-mt-4" staggerDelay={0.1}>
|
||||
<StaggerItem>
|
||||
<motion.div
|
||||
className="onepage-flex onepage-gap-3 onepage-text"
|
||||
whileHover={{ x: 5 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<BadgeCheck className="w-5 h-5 text-blue-300"/> Eisbrecher für Gespräche
|
||||
</motion.div>
|
||||
</StaggerItem>
|
||||
<StaggerItem>
|
||||
<motion.div
|
||||
className="onepage-flex onepage-gap-3 onepage-text"
|
||||
whileHover={{ x: 5 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<BadgeCheck className="w-5 h-5 text-blue-300"/> Null Fremdscham, 100% Wow
|
||||
</motion.div>
|
||||
</StaggerItem>
|
||||
<StaggerItem>
|
||||
<motion.div
|
||||
className="onepage-flex onepage-gap-3 onepage-text"
|
||||
whileHover={{ x: 5 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<BadgeCheck className="w-5 h-5 text-blue-300"/> Planbar & professionell
|
||||
</motion.div>
|
||||
</StaggerItem>
|
||||
</StaggerContainer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ACTS / PACKAGES */}
|
||||
<section id="acts" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">Programme</span>
|
||||
<h2 className="onepage-h2">Acts & Pakete</h2>
|
||||
</FadeUp>
|
||||
<StaggerContainer className="onepage-grid onepage-grid--4" staggerDelay={0.15}>
|
||||
{acts.map((a, index) => (
|
||||
<StaggerItem key={a.title}>
|
||||
<HoverCard className={`onepage-card onepage-card-hover bg-gradient-to-br ${a.gradient}`}>
|
||||
<motion.div
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ delay: 0.5 + index * 0.1, duration: 0.5, type: "spring" }}
|
||||
className="onepage-mb-4"
|
||||
>
|
||||
{a.icon}
|
||||
</motion.div>
|
||||
<h3 className="onepage-h3">{a.title}</h3>
|
||||
<p className="onepage-text onepage-mb-4">{a.desc}</p>
|
||||
<ul className="onepage-mb-6" style={{listStyle: 'none', padding: 0}}>
|
||||
{a.points.map((p, i) => (
|
||||
<motion.li
|
||||
key={p}
|
||||
className="onepage-flex onepage-gap-2 onepage-text"
|
||||
style={{marginBottom: '8px'}}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.8 + index * 0.1 + i * 0.1 }}
|
||||
>
|
||||
<Check className="w-4 h-4 text-blue-300 flex-shrink-0" style={{marginTop: '2px'}}/> {p}
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
<MagneticButton
|
||||
className="onepage-btn onepage-btn--ghost"
|
||||
style={{width: '100%', justifyContent: 'center'}}
|
||||
>
|
||||
<button
|
||||
onClick={() => scrollToSection("contact")}
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'inherit', font: 'inherit' }}
|
||||
>
|
||||
Termin anfragen
|
||||
</button>
|
||||
</MagneticButton>
|
||||
</HoverCard>
|
||||
</StaggerItem>
|
||||
))}
|
||||
</StaggerContainer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* USE CASES */}
|
||||
<section id="usecases" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">Für welche Anlässe?</span>
|
||||
<h2 className="onepage-h2">Corporate · Hochzeit · Private Feiern</h2>
|
||||
</FadeUp>
|
||||
<StaggerContainer className="onepage-grid onepage-grid--3" staggerDelay={0.2}>
|
||||
{[{
|
||||
title: "Corporate Events",
|
||||
points: ["Kickoff, Gala, Kunden-Dinner", "Bühne + Close-up kombinierbar", "Seriös, vertraglich & pünktlich"],
|
||||
emoji: "🏢"
|
||||
}, {
|
||||
title: "Hochzeiten",
|
||||
points: ["Sektempfang & zwischen den Gängen", "Foto-Momente für das Paar", "Familienfreundlich"],
|
||||
emoji: "💒"
|
||||
}, {
|
||||
title: "Private Feiern",
|
||||
points: ["30./40./50. Geburtstag", "Packages & WhatsApp-Kontakt", "Schnelle Antwort <24h"],
|
||||
emoji: "🎉"
|
||||
}].map((u) => (
|
||||
<StaggerItem key={u.title}>
|
||||
<HoverCard className="onepage-card">
|
||||
<motion.div
|
||||
className="text-4xl onepage-mb-4"
|
||||
animate={{ rotate: [0, 10, -10, 0] }}
|
||||
transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}
|
||||
>
|
||||
{u.emoji}
|
||||
</motion.div>
|
||||
<h3 className="onepage-h3">{u.title}</h3>
|
||||
<ul style={{listStyle: 'none', padding: 0}}>
|
||||
{u.points.map((p) => (
|
||||
<motion.li
|
||||
key={p}
|
||||
className="onepage-flex onepage-gap-2 onepage-text"
|
||||
style={{marginBottom: '8px'}}
|
||||
whileHover={{ x: 5 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Check className="w-4 h-4 text-blue-300 flex-shrink-0" style={{marginTop: '2px'}}/> {p}
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</HoverCard>
|
||||
</StaggerItem>
|
||||
))}
|
||||
</StaggerContainer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* TESTIMONIALS */}
|
||||
<section id="testimonials" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">Bewertungen</span>
|
||||
<h2 className="onepage-h2">Vertrauen, das man lesen kann</h2>
|
||||
</FadeUp>
|
||||
<StaggerContainer className="onepage-grid onepage-grid--3" staggerDelay={0.2}>
|
||||
{testimonials.map((t, i) => (
|
||||
<StaggerItem key={i}>
|
||||
<HoverCard className="onepage-testimonial">
|
||||
<div className="quote">"</div>
|
||||
<motion.div
|
||||
className="text-4xl onepage-mb-4"
|
||||
animate={{ scale: [1, 1.1, 1] }}
|
||||
transition={{ duration: 2, repeat: Infinity, delay: i * 0.5 }}
|
||||
>
|
||||
{t.avatar}
|
||||
</motion.div>
|
||||
<div className="onepage-flex onepage-gap-1 onepage-mb-4">
|
||||
{Array.from({length:5}).map((_,j)=>(
|
||||
<motion.div
|
||||
key={j}
|
||||
initial={{ opacity: 0, scale: 0 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.5 + j * 0.1 }}
|
||||
>
|
||||
<Star className="w-4 h-4 onepage-stars" fill="currentColor"/>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
<p className="onepage-text" style={{fontStyle: 'italic'}}>"{t.quote}"</p>
|
||||
<div className="onepage-mt-4 onepage-text" style={{fontWeight: '600'}}>— {t.name}</div>
|
||||
</HoverCard>
|
||||
</StaggerItem>
|
||||
))}
|
||||
</StaggerContainer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ABOUT */}
|
||||
<section id="about" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">Über Michael</span>
|
||||
<h2 className="onepage-h2">Jung, modern, TV-bekannt</h2>
|
||||
</FadeUp>
|
||||
<div className="onepage-grid onepage-grid--2">
|
||||
<SlideInLeft delay={0.2}>
|
||||
<p className="onepage-text" style={{lineHeight: '1.7'}}>
|
||||
Michael Peskov gehört zu den jüngsten professionellen Magiern Deutschlands. Seine Auftritte verbinden modernes
|
||||
Entertainment mit interaktiver Zauberei und einem einzigartigen Taschendieb-Act – immer respektvoll und sicher.
|
||||
Er ist europaweit im Einsatz ({proof.travel}) und wurde u. a. bei {proof.logos.join(", ")} gezeigt.
|
||||
</p>
|
||||
</SlideInLeft>
|
||||
<SlideInRight delay={0.4}>
|
||||
<HoverCard className="onepage-card">
|
||||
<ul style={{listStyle: 'none', padding: 0}}>
|
||||
{[
|
||||
{ icon: <ShieldCheck className="w-4 h-4 flex-shrink-0" />, text: "Vertrag & Haftpflicht inklusive" },
|
||||
{ icon: <Clock4 className="w-4 h-4 flex-shrink-0" />, text: "Pünktlich, sauberer Ablauf" },
|
||||
{ icon: <Users2 className="w-4 h-4 flex-shrink-0" />, text: "Kleine & große Events" }
|
||||
].map((item, i) => (
|
||||
<motion.li
|
||||
key={i}
|
||||
className="onepage-flex onepage-gap-2 onepage-text"
|
||||
style={{marginBottom: '12px'}}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.6 + i * 0.2 }}
|
||||
whileHover={{ x: 5, color: 'var(--primary-400)' }}
|
||||
>
|
||||
<motion.div style={{marginTop: '2px'}} whileHover={{ scale: 1.2 }}>
|
||||
{item.icon}
|
||||
</motion.div>
|
||||
{item.text}
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</HoverCard>
|
||||
</SlideInRight>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ */}
|
||||
<section id="faq" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">FAQ</span>
|
||||
<h2 className="onepage-h2">Häufige Fragen</h2>
|
||||
</FadeUp>
|
||||
<FadeUp delay={0.2}>
|
||||
<AnimatedFAQ faqs={faqs} />
|
||||
</FadeUp>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CONTACT / CTA */}
|
||||
<section id="contact" className="onepage-section">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<span className="onepage-eyebrow">Jetzt anfragen</span>
|
||||
<h2 className="onepage-h2">Verfügbarkeit & Angebot</h2>
|
||||
</FadeUp>
|
||||
<ScaleIn delay={0.3}>
|
||||
<HoverCard className="onepage-card">
|
||||
<form className="onepage-grid onepage-grid--2" onSubmit={(e)=>{e.preventDefault(); alert("Danke! Wir melden uns i. d. R. innerhalb von 24 Stunden.");}}>
|
||||
<StaggerContainer className="contents" staggerDelay={0.1}>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Datum</label>
|
||||
<motion.input
|
||||
required
|
||||
type="date"
|
||||
className="onepage-input"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
/>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Ort</label>
|
||||
<motion.input
|
||||
required
|
||||
placeholder="Stadt / Location"
|
||||
className="onepage-input"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
/>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Anlass</label>
|
||||
<motion.select
|
||||
className="onepage-select"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
>
|
||||
<option>Corporate Event</option>
|
||||
<option>Hochzeit</option>
|
||||
<option>Private Feier</option>
|
||||
</motion.select>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Gästezahl</label>
|
||||
<motion.input
|
||||
type="number"
|
||||
min={1}
|
||||
placeholder="z. B. 120"
|
||||
className="onepage-input"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
/>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group" style={{gridColumn: '1 / -1'}}>
|
||||
<label className="onepage-label">Programm</label>
|
||||
<div className="onepage-grid onepage-grid--2">
|
||||
{acts.map((a)=> (
|
||||
<motion.label
|
||||
key={a.title}
|
||||
className="onepage-flex onepage-gap-2"
|
||||
style={{padding: '12px', background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: '12px', cursor: 'pointer'}}
|
||||
whileHover={{ scale: 1.02, backgroundColor: 'rgba(255,255,255,0.08)' }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
<input type="checkbox" className="onepage-checkbox"/> <span className="onepage-text">{a.title}</span>
|
||||
</motion.label>
|
||||
))}
|
||||
</div>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Budget (Richtwert)</label>
|
||||
<motion.select
|
||||
className="onepage-select"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
>
|
||||
<option>auf Anfrage</option>
|
||||
<option>bis 1.000 €</option>
|
||||
<option>1.000 – 2.000 €</option>
|
||||
<option>2.000 – 4.000 €</option>
|
||||
<option>4.000 € +</option>
|
||||
</motion.select>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Firma (optional)</label>
|
||||
<motion.input
|
||||
placeholder="Firmenname"
|
||||
className="onepage-input"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
/>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">E-Mail</label>
|
||||
<motion.input
|
||||
required
|
||||
type="email"
|
||||
placeholder="name@firma.de"
|
||||
className="onepage-input"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
/>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-form-group">
|
||||
<label className="onepage-label">Telefon / WhatsApp</label>
|
||||
<motion.input
|
||||
placeholder="+49 …"
|
||||
className="onepage-input"
|
||||
whileFocus={{ scale: 1.02, borderColor: 'var(--primary-400)' }}
|
||||
/>
|
||||
</StaggerItem>
|
||||
<StaggerItem style={{gridColumn: '1 / -1'}}>
|
||||
<motion.label
|
||||
className="onepage-flex onepage-gap-2 onepage-text"
|
||||
whileHover={{ x: 5 }}
|
||||
>
|
||||
<input type="checkbox" className="onepage-checkbox"/> Rückruf per WhatsApp gewünscht
|
||||
</motion.label>
|
||||
</StaggerItem>
|
||||
<StaggerItem className="onepage-flex onepage-flex-wrap onepage-gap-3" style={{gridColumn: '1 / -1'}}>
|
||||
<MagneticButton>
|
||||
<button type="submit" className="onepage-btn onepage-btn--primary onepage-flex onepage-gap-2" style={{border: 'none', background: 'none', color: 'inherit'}}>
|
||||
<Calendar className="w-4 h-4"/> Anfrage senden
|
||||
</button>
|
||||
</MagneticButton>
|
||||
<MagneticButton>
|
||||
<a href="mailto:booking@michaelpeskov.de" className="onepage-btn onepage-btn--ghost onepage-flex onepage-gap-2">
|
||||
<Mail className="w-4 h-4"/> booking@michaelpeskov.de
|
||||
</a>
|
||||
</MagneticButton>
|
||||
<MagneticButton>
|
||||
<a href="tel:+491234567890" className="onepage-btn onepage-btn--ghost onepage-flex onepage-gap-2">
|
||||
<Phone className="w-4 h-4"/> +49 123 456 7890
|
||||
</a>
|
||||
</MagneticButton>
|
||||
</StaggerItem>
|
||||
</StaggerContainer>
|
||||
</form>
|
||||
</HoverCard>
|
||||
</ScaleIn>
|
||||
<FadeUp delay={0.5}>
|
||||
<p className="onepage-text" style={{fontSize: '0.75rem', marginTop: '12px', opacity: 0.7}}>
|
||||
Antwort in der Regel innerhalb von 24 Stunden. Ihre Daten werden nur zur Bearbeitung der Anfrage verwendet.
|
||||
</p>
|
||||
</FadeUp>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FOOTER */}
|
||||
<footer className="onepage-footer">
|
||||
<div className="onepage-container">
|
||||
<FadeUp>
|
||||
<div className="onepage-footer-content">
|
||||
<motion.div
|
||||
className="onepage-flex onepage-gap-2"
|
||||
whileHover={{ scale: 1.05 }}
|
||||
>
|
||||
<motion.div
|
||||
whileHover={{ rotate: 360 }}
|
||||
transition={{ duration: 0.8, ease: "easeInOut" }}
|
||||
>
|
||||
<Image src="/icon.png" alt="Michael Peskov Magic Logo" width={16} height={16} />
|
||||
</motion.div>
|
||||
<span>Michael Peskov Magic</span>
|
||||
</motion.div>
|
||||
<div className="onepage-footer-text">© {new Date().getFullYear()} – All rights reserved.</div>
|
||||
</div>
|
||||
</FadeUp>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* JSON-LD */}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "Michael Peskov Magic",
|
||||
url: "https://michaelpeskov.de",
|
||||
sameAs: ["https://instagram.com/", "https://www.youtube.com/"],
|
||||
aggregateRating: {
|
||||
"@type": "AggregateRating",
|
||||
ratingValue: proof.rating,
|
||||
reviewCount: proof.reviews,
|
||||
},
|
||||
areaServed: "Europe",
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
33
app/providers/ScrollProvider.tsx
Normal file
33
app/providers/ScrollProvider.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
'use client'
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
// Dynamic imports to avoid SSR issues
|
||||
let gsap: any
|
||||
let ScrollTrigger: any
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
gsap = require('gsap').gsap
|
||||
ScrollTrigger = require('gsap/ScrollTrigger').ScrollTrigger
|
||||
gsap.registerPlugin(ScrollTrigger)
|
||||
}
|
||||
|
||||
export function ScrollProvider({ children }: { children: React.ReactNode }) {
|
||||
useEffect(() => {
|
||||
// Check if GSAP is available
|
||||
if (!gsap || !ScrollTrigger) return
|
||||
|
||||
// Just refresh ScrollTrigger on resize - no smooth scrolling
|
||||
const handleResize = () => {
|
||||
ScrollTrigger.refresh()
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
ScrollTrigger.killAll()
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <>{children}</>
|
||||
}
|
||||
Reference in New Issue
Block a user