feat: scroll-animierte Zick-Zack Timeline für alle 8 Wochen

- WeekTimeline Client-Component mit IntersectionObserver
- Woche 1,3,5,7 erscheint von links — Woche 2,4,6,8 von rechts
- Vertikale Gradient-Linie in der Mitte (indigo → violet)
- Nummerierter Dot auf der Linie pro Woche
- Modul-Divider (1/2/3) als animierte Trennelemente
- CSS-Transitionen: opacity + translateX, 0.6s ease
- Expert-Badges auf den Karten (Can, Stefan & Philipp, Manuela)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Athena 2026-04-30 22:06:50 +02:00
parent 8c48fb51d8
commit a5b0e4c9a6
3 changed files with 264 additions and 100 deletions

View file

@ -0,0 +1,247 @@
"use client";
import { useEffect, useRef } from "react";
interface Week {
week: string;
expert?: string;
title: string;
body: string;
vorlagen: string;
result: string;
}
interface Module {
label: string;
headline: string;
weeks: Week[];
}
const MODULES: Module[] = [
{
label: "Modul 1 — Wochen 1 & 2",
headline: "Wunschkunde, Angebot, Positionierung",
weeks: [
{
week: "Woche 1",
title: "Dein Wunschkunde + dein Markt",
body: "Du schaust konkret hin: Wer ist dein Wunschkunde wirklich? Welches Problem hat er — und was hat er schon alles versucht? Was kostet ihn dieses Problem jeden Monat? Du machst einen ehrlichen Marketing-Audit: Was läuft, was nicht — und warum.",
vorlagen: "Marketing-Audit-Vorlage · Wunschkunden-Persona-Vorlage",
result: "Klarheit über deinen Wunschkunden — konkret, nicht allgemein.",
},
{
week: "Woche 2",
title: "Dein unwiderstehliches Angebot + deine Positionierung",
body: "Du legst dein Angebot auf den Tisch: Was bietest du genau an? Welches Problem löst du? Dann entwickelst du deine Positionierungsformel — für wen, welches Problem, was macht dich anders. In einem Satz. Du übst ihn live in der Gruppe.",
vorlagen: "Positionierungsformel-Vorlage · Kurztext für Website, Instagram und LinkedIn",
result: "Dein Angebot klar auf den Punkt — erklärt in einem Satz.",
},
],
},
{
label: "Modul 2 — Wochen 3 & 4",
headline: "Dein System steht.",
weeks: [
{
week: "Woche 3",
title: "Deine Verkaufsseite",
body: "Du lernst wie eine Verkaufsseite aufgebaut sein muss — die 7 Pflicht-Elemente, ihre Reihenfolge, die Psychologie dahinter. Du bekommst die komplette Vorlage. Du setzt es direkt auf deiner Seite um — Katja gibt Feedback.",
vorlagen: "Verkaufsseiten-Vorlage + alle Textelemente · 7-Elemente-Checkliste",
result: "Vollständige Struktur für deine Verkaufsseite — fertig zum Umsetzen.",
},
{
week: "Woche 4",
title: "Deine Kanal-Strategie + 90-Tage-Marketingplan",
body: "Welche 2 Kanäle fokussierst du — auf Basis deiner Zielgruppe, nicht dem was gerade alle machen. Du baust deine Marketing-Systemkarte und startest deinen 90-Tage-Plan.",
vorlagen: "Kanal-Entscheidungsmatrix · Marketing-Systemkarte · 90-Tage-Marketingplan",
result: "Gewusst welche 2 Kanäle du fokussierst — und 90-Tage-Plan begonnen.",
},
],
},
{
label: "Modul 3 — Wochen 58",
headline: "Sichtbarkeit. Anfragen. Und du weißt wie es weitergeht.",
weeks: [
{
week: "Woche 5",
expert: "Can Turkdogan · Social Media",
title: "Dein Content-System",
body: "Deine 34 Content-Themen die zeigen wofür du stehst. Du erstellst live deinen 4-Wochen-Redaktionsplan, schreibst deinen ersten Hook und weißt ab dieser Woche genau: was du postest, wann, und warum.",
vorlagen: "Content-Säulen-Template · 4-Wochen-Redaktionsplan · 10 bewährte Hook-Formeln",
result: "Content-Plan für 4 Wochen — weißt genau was und wie du postest.",
},
{
week: "Woche 6",
expert: "Stefan & Philipp · Onlinewerbevideo",
title: "Social Media Verkauf + Video-Setup",
body: "Du lernst wie du dein Angebot aktiv über Social Media verkaufst — mit Strategie, nicht mit Druck. Die Video-Experten zeigen live: professionelle Videos mit dem Handy.",
vorlagen: "Launch-Checkliste · Equipment-Checkliste · Filming-Guide",
result: "Plan für Social Media Verkauf + professionell auf Video.",
},
{
week: "Woche 7",
expert: "Manuela Ludewig · Vertrieb",
title: "Verkauf + Direktansprache",
body: "Dein persönliches Verkaufsskript für die Direktansprache — angepasst auf deine Positionierung. Du übst es live in der Gruppe mit konkretem Plan für deine nächsten Kontakte.",
vorlagen: "Persönliches Verkaufsskript · Follow-up-Template · Event-Recherche-Guide",
result: "Dein Verkaufsskript für die Direktansprache — einmal geübt.",
},
{
week: "Woche 8",
expert: "Katja Pestereva · Market Compass",
title: "Sichtbarkeit auf Google + Abschluss",
body: "Du optimierst dein Google Business Profil Schritt für Schritt in der Gruppe. Du bringst deine Website auf die Grundlagen die Google belohnt. Abschlussrunde: Was hat sich in 8 Wochen verändert?",
vorlagen: "SEO-Checkliste · Keyword-Recherche-Vorlage · Website-Leitfaden",
result: "Google Business vollständig optimiert + Seite für dein Haupt-Keyword.",
},
],
},
];
/* Running week counter so odd/even alternates across all modules */
let globalWeekIndex = 0;
function WeekCard({ week, isLeft }: { week: Week; isLeft: boolean }) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const obs = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
el.classList.add("tl-visible");
obs.disconnect();
}
},
{ threshold: 0.15 }
);
obs.observe(el);
return () => obs.disconnect();
}, []);
return (
<div
ref={ref}
className={`tl-card ${isLeft ? "tl-from-left" : "tl-from-right"} w-full md:w-[46%] ${
isLeft ? "md:mr-auto md:pr-10" : "md:ml-auto md:pl-10"
}`}
>
<div className="mc-card p-6 space-y-3 hover:shadow-lg hover:shadow-indigo-100 transition-shadow">
{/* Header */}
<div className="flex flex-wrap items-center gap-2">
<span className="bg-gradient-to-r from-indigo-500 to-violet-500 text-white text-xs font-bold px-3 py-1 rounded-full uppercase tracking-wide">
{week.week}
</span>
{week.expert && (
<span className="bg-indigo-50 text-indigo-700 text-xs font-medium px-3 py-1 rounded-full border border-indigo-100">
{week.expert}
</span>
)}
</div>
{/* Title */}
<h4 className="font-extrabold text-slate-900 text-base leading-snug">{week.title}</h4>
{/* Body */}
<p className="text-slate-500 text-sm leading-relaxed">{week.body}</p>
{/* Vorlagen */}
<p className="text-xs text-indigo-600 italic border-t border-slate-100 pt-3">
📋 {week.vorlagen}
</p>
{/* Result */}
<p className="text-sm font-semibold text-emerald-600"> {week.result}</p>
</div>
</div>
);
}
export default function WeekTimeline() {
/* Reset global counter each render (SSR-safe: only matters client-side) */
globalWeekIndex = 0;
return (
<section className="py-20">
<div className="max-w-5xl mx-auto px-6">
{/* Section header */}
<div className="text-center mb-16">
<span className="inline-flex items-center gap-2 bg-indigo-50 text-indigo-700 text-xs font-bold uppercase tracking-widest rounded-full px-4 py-2 border border-indigo-100">
<span className="w-2 h-2 rounded-full bg-indigo-500 animate-pulse" />
8 Wochen · Schritt für Schritt
</span>
<h2 className="mt-4 text-3xl md:text-4xl font-extrabold text-slate-900">
Dein Programm Woche für Woche
</h2>
<p className="mt-3 text-slate-500 max-w-xl mx-auto">
Jede Woche baut auf der nächsten auf. Am Ende hast du kein Zertifikat sondern ein fertiges System.
</p>
</div>
{MODULES.map((mod) => (
<div key={mod.label} className="mb-6">
{/* Module divider */}
<ModuleDivider label={mod.label} headline={mod.headline} />
{/* Weeks */}
<div className="relative">
{/* Vertical timeline line */}
<div className="hidden md:block absolute left-1/2 top-0 bottom-0 w-0.5 bg-gradient-to-b from-indigo-300 via-violet-300 to-indigo-200 -translate-x-1/2" />
<div className="flex flex-col gap-10 py-6">
{mod.weeks.map((week) => {
const isLeft = globalWeekIndex % 2 === 0;
globalWeekIndex++;
return (
<div key={week.week} className="relative flex items-start">
{/* Timeline dot — centered */}
<div className="hidden md:flex absolute left-1/2 -translate-x-1/2 top-7 w-8 h-8 rounded-full bg-gradient-to-br from-indigo-500 to-violet-500 items-center justify-center shadow-lg shadow-indigo-200 z-10 flex-shrink-0">
<span className="text-white text-xs font-bold">
{week.week.replace("Woche ", "")}
</span>
</div>
<WeekCard week={week} isLeft={isLeft} />
</div>
);
})}
</div>
</div>
</div>
))}
</div>
</section>
);
}
function ModuleDivider({ label, headline }: { label: string; headline: string }) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const obs = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
el.classList.add("tl-visible");
obs.disconnect();
}
},
{ threshold: 0.2 }
);
obs.observe(el);
return () => obs.disconnect();
}, []);
return (
<div
ref={ref}
className="tl-card tl-from-bottom text-center py-8 mb-2"
>
<div className="inline-flex items-center gap-3">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-indigo-300" />
<span className="bg-gradient-to-r from-indigo-600 to-violet-600 bg-clip-text text-transparent text-xs font-extrabold uppercase tracking-widest">
{label}
</span>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-indigo-300" />
</div>
<h3 className="mt-2 text-xl md:text-2xl font-extrabold text-slate-900">{headline}</h3>
</div>
);
}

View file

@ -58,3 +58,18 @@ body {
} }
details summary::-webkit-details-marker { display: none; } details summary::-webkit-details-marker { display: none; }
/* ── Timeline scroll animations ── */
.tl-card {
opacity: 0;
transition: opacity 0.6s ease, transform 0.6s ease;
}
.tl-from-left { transform: translateX(-56px); }
.tl-from-right { transform: translateX(56px); }
.tl-from-bottom{ transform: translateY(40px); }
.tl-card.tl-visible {
opacity: 1;
transform: translateX(0) translateY(0);
}

View file

@ -1,4 +1,5 @@
import Image from "next/image"; import Image from "next/image";
import WeekTimeline from "./components/WeekTimeline";
const CTA_HREF = "#platz-sichern"; const CTA_HREF = "#platz-sichern";
@ -35,39 +36,6 @@ function IconCard({ icon, title, sub }: { icon: string; title: string; sub: stri
); );
} }
function ModuleCard({ week, expert, title, body, vorlagen, result }: {
week: string; expert?: string; title: string; body: string; vorlagen: string; result: string;
}) {
return (
<div className="mc-card overflow-hidden flex flex-col">
{/* Thumbnail */}
<div className="relative w-full aspect-video bg-slate-100 flex items-center justify-center border-b border-slate-100">
<div className="absolute inset-0 bg-gradient-to-br from-indigo-50 to-violet-50" />
<div className="relative flex flex-col items-center gap-2 text-slate-400">
<svg className="w-10 h-10 opacity-30" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15 10l4.553-2.069A1 1 0 0121 8.869v6.262a1 1 0 01-1.447.894L15 14M4 8h11a2 2 0 012 2v4a2 2 0 01-2 2H4a2 2 0 01-2-2v-4a2 2 0 012-2z" />
</svg>
<span className="text-xs uppercase tracking-widest opacity-50">Video</span>
</div>
<span className="absolute top-3 left-3 bg-gradient-to-r from-indigo-500 to-violet-500 text-white text-xs font-bold px-2 py-1 rounded-md uppercase tracking-wide">
{week}
</span>
{expert && (
<span className="absolute top-3 right-3 bg-white/80 text-indigo-700 text-xs font-semibold px-2 py-1 rounded-md border border-indigo-100">
{expert}
</span>
)}
</div>
{/* Content */}
<div className="p-5 flex flex-col gap-3 flex-1">
<h4 className="font-bold text-slate-900 text-sm leading-snug">{title}</h4>
<p className="text-slate-500 text-xs leading-relaxed flex-1">{body}</p>
<p className="text-xs text-indigo-600 italic border-t border-slate-100 pt-3">{vorlagen}</p>
<p className="text-xs font-semibold text-emerald-600"> {result}</p>
</div>
</div>
);
}
export default function Home() { export default function Home() {
return ( return (
@ -255,73 +223,7 @@ export default function Home() {
</div> </div>
</section> </section>
{/* <WeekTimeline />
MODUL 1 Thumbnail Cards
*/}
<section className="py-20 bg-white">
<div className="max-w-5xl mx-auto px-6 space-y-5">
<Pill>Modul 1 Wochen 1 &amp; 2</Pill>
<h2 className="text-3xl md:text-4xl font-extrabold text-slate-900">Wunschkunde, Angebot, Positionierung alles klar auf den Punkt.</h2>
<div className="grid md:grid-cols-2 gap-6 pt-4">
<ModuleCard week="Woche 1" title="Dein Wunschkunde + dein Markt"
body="Du schaust konkret hin: Wer ist dein Wunschkunde wirklich? Welches Problem hat er — und was hat er schon alles versucht? Was kostet ihn dieses Problem jeden Monat? Du machst einen ehrlichen Marketing-Audit: Was läuft, was nicht — und warum."
vorlagen="Marketing-Audit-Vorlage · Wunschkunden-Persona-Vorlage"
result="Klarheit über deinen Wunschkunden — konkret, nicht allgemein." />
<ModuleCard week="Woche 2" title="Dein unwiderstehliches Angebot + deine Positionierung"
body="Du legst dein Angebot auf den Tisch: Was bietest du genau an? Welches Problem löst du? Dann entwickelst du deine Positionierungsformel — für wen, welches Problem, was macht dich anders. In einem Satz. Du übst ihn live in der Gruppe."
vorlagen="Positionierungsformel-Vorlage · Kurztext für Website, Instagram-Profil und LinkedIn"
result="Dein Angebot klar auf den Punkt — erklärt in einem Satz." />
</div>
</div>
</section>
{/*
MODUL 2
*/}
<section className="py-20">
<div className="max-w-5xl mx-auto px-6 space-y-5">
<Pill>Modul 2 Wochen 3 &amp; 4</Pill>
<h2 className="text-3xl md:text-4xl font-extrabold text-slate-900">Dein System steht.</h2>
<div className="grid md:grid-cols-2 gap-6 pt-4">
<ModuleCard week="Woche 3" title="Deine Verkaufsseite"
body="Du lernst wie eine Verkaufsseite aufgebaut sein muss — die 7 Pflicht-Elemente, ihre Reihenfolge, die Psychologie dahinter. Du bekommst die komplette Vorlage. Du setzt es direkt auf deiner Seite um — Katja gibt Feedback."
vorlagen="Verkaufsseiten-Vorlage + alle Textelemente · 7-Elemente-Checkliste"
result="Vollständige Struktur für deine Verkaufsseite — fertig zum Umsetzen." />
<ModuleCard week="Woche 4" title="Deine Kanal-Strategie + 90-Tage-Marketingplan"
body="Welche 2 Kanäle fokussierst du — auf Basis deiner Zielgruppe, nicht dem was gerade alle machen. Du baust deine Marketing-Systemkarte und startest deinen 90-Tage-Plan."
vorlagen="Kanal-Entscheidungsmatrix · Marketing-Systemkarte · 90-Tage-Marketingplan"
result="Gewusst welche 2 Kanäle du fokussierst — und 90-Tage-Plan begonnen." />
</div>
</div>
</section>
{/*
MODUL 3
*/}
<section className="py-20 bg-white">
<div className="max-w-5xl mx-auto px-6 space-y-5">
<Pill>Modul 3 Wochen 58</Pill>
<h2 className="text-3xl md:text-4xl font-extrabold text-slate-900">Sichtbarkeit. Anfragen. Und du weißt wie es weitergeht.</h2>
<div className="grid md:grid-cols-2 gap-6 pt-4">
<ModuleCard week="Woche 5" expert="Can Turkdogan" title="Dein Content-System"
body="Deine 34 Content-Themen — die zeigen wofür du stehst. Du erstellst live deinen 4-Wochen-Redaktionsplan, schreibst deinen ersten Hook und weißt ab dieser Woche genau: was du postest, wann, und warum."
vorlagen="Content-Säulen-Template · 4-Wochen-Redaktionsplan · 10 bewährte Hook-Formeln"
result="Content-Plan für 4 Wochen — weißt genau was und wie du postest." />
<ModuleCard week="Woche 6" expert="Stefan & Philipp · OWV" title="Social Media Verkauf + Video-Setup"
body="Du lernst wie du dein Angebot aktiv über Social Media verkaufst — mit Strategie, nicht mit Druck. Die Video-Experten zeigen live: professionelle Videos mit dem Handy."
vorlagen="Launch-Checkliste · Equipment-Checkliste · Filming-Guide"
result="Plan für Social Media Verkauf + professionell auf Video." />
<ModuleCard week="Woche 7" expert="Manuela Ludewig" title="Verkauf + Direktansprache"
body="Dein persönliches Verkaufsskript für die Direktansprache — angepasst auf deine Positionierung. Du übst es live in der Gruppe mit konkretem Plan für deine nächsten Kontakte."
vorlagen="Persönliches Verkaufsskript · Follow-up-Template · Event-Recherche-Guide"
result="Dein Verkaufsskript für die Direktansprache — einmal geübt." />
<ModuleCard week="Woche 8" expert="Katja Pestereva" title="Sichtbarkeit auf Google + Abschluss"
body="Du optimierst dein Google Business Profil Schritt für Schritt in der Gruppe. Du bringst deine Website auf die Grundlagen die Google belohnt. Abschlussrunde: Was hat sich in 8 Wochen verändert?"
vorlagen="SEO-Checkliste · Keyword-Recherche-Vorlage · Website-Leitfaden"
result="Google Business vollständig optimiert + Seite für dein Haupt-Keyword." />
</div>
</div>
</section>
{/* {/*
VORHER / NACHHER VORHER / NACHHER