"use client";
import Image from "next/image";
import Link from "next/link";
import type { ComponentType, ReactNode } from "react";
import {
ArrowRight,
Building2,
CalendarDays,
CalendarX2,
Check,
CreditCard,
DoorOpen,
Globe,
Link2,
MessageCircle,
Settings2,
Ticket,
UploadCloud,
UserPlus,
Wallet,
} from "lucide-react";
import {
Counter,
MaskedWords,
Reveal,
RevealItem,
ScrollTracking,
Tilt,
} from "./motion";
import { BrowserFrame, ParallaxLayer } from "./mockup";
import { BrandButton, Eyebrow, Faq, GhostLink, WaitlistForm } from "./ui";
import { Logo } from "./logo";
import { FAQ_ENTRIES } from "../lib/faq";
import { CONTACT_EMAIL } from "../lib/site";
/* ------------------------------------------------------------------ *
* Shared section scaffolding
* ------------------------------------------------------------------ */
function Section({
id,
children,
className = "",
}: {
id?: string;
children: ReactNode;
className?: string;
}) {
return (
{children}
);
}
function SectionHead({
eyebrow,
titleLines,
lead,
wash = "amber",
align = "left",
}: {
eyebrow: string;
/** Each entry is one visual line, split into words for the masked reveal. */
titleLines: ReactNode[][];
lead?: string;
wash?: "amber" | "sky" | "mint" | "peach";
align?: "left" | "center";
}) {
const centered = align === "center";
return (
{eyebrow}
{/* Tracking tightens as the heading scrolls toward centre — the type
settles into its final, compressed form. */}
{titleLines.map((line, index) => (
))}
{lead ? (
{lead}
) : null}
);
}
type Item = {
title: string;
body: string;
Icon: ComponentType<{ className?: string; strokeWidth?: number }>;
};
/* ------------------------------------------------------------------ *
* Problem
* ------------------------------------------------------------------ */
const PROBLEMS: Item[] = [
{
title: "Buchungen kommen per DM",
body: "Instagram, WhatsApp, Telefon, zwischen zwei Kursen. Die Teilnehmerliste führst du im Kopf oder in einer Tabelle.",
Icon: MessageCircle,
},
{
title: "Wer hat eigentlich bezahlt?",
body: "Bar, Überweisung, „bring ich nächstes Mal mit“. Nachfassen kostet dich jede Woche Stunden — und manchmal den Betrag.",
Icon: Wallet,
},
{
title: "Raum doppelt belegt",
body: "Zwei Kurse, ein Raum, eine Trainerin. Auffallen tut es oft erst am Kurstag — vor wartenden Kunden.",
Icon: Building2,
},
{
title: "Abgesagt heißt leer",
body: "Kurzfristige Stornos bleiben unbesetzt, obwohl drei Leute gewartet hätten. Bezahlt hat am Ende niemand.",
Icon: CalendarX2,
},
];
export function Problem() {
return (
leider
,
"auch.",
],
]}
lead="Du bist Trainerin, nicht Sachbearbeiterin. Trotzdem geht jede Woche ein halber Arbeitstag für Koordination drauf."
/>
{PROBLEMS.map(({ title, body, Icon }, index) => (
{title}
{body}
))}
);
}
/* ------------------------------------------------------------------ *
* Solution
* ------------------------------------------------------------------ */
const FEATURES: Item[] = [
{
title: "Kurse & Serientermine",
body: "Einzeltermin oder Dauerauftrag in wenigen Klicks. Level, Preis, Teilnehmerzahl, Raum und Trainer gehören direkt dazu.",
Icon: CalendarDays,
},
{
title: "Öffentliche Buchungsseite",
body: "Deine eigene Seite mit Kalender, Kursfiltern und deinem Logo. Gastbuchung ohne Account — kein Abbruch an der Registrierung.",
Icon: Globe,
},
{
title: "Zahlung läuft über Stripe",
body: "Bezahlt wird beim Buchen, nicht beim Nachfragen. Du siehst jeden Eingang in Echtzeit, Rechnungen sind GoBD-konform und als ZIP exportierbar.",
Icon: CreditCard,
},
{
title: "Warteliste, die nachrückt",
body: "Sagt jemand ab, rückt der nächste automatisch auf den Platz. Der Kurs bleibt voll, ohne dass du eine Nachricht schreibst.",
Icon: UserPlus,
},
{
title: "Räume & Trainer",
body: "Wer unterrichtet wo, mit welchen Rechten. Doppelbelegungen fallen beim Anlegen auf — nicht am Kurstag.",
Icon: DoorOpen,
},
{
title: "Rabattcodes & Stornoregeln",
body: "Prozentual oder als Fixbetrag, mit Nutzungslimit und Gültigkeitszeitraum. Stornofristen legst du einmal fest, danach gelten sie automatisch.",
Icon: Ticket,
},
];
export function Solution() {
return (
einer
,
"Tabelle.",
],
]}
lead="Alles, was ein Kursbetrieb wirklich braucht — und nichts, wofür du eine Schulung brauchst."
/>
{FEATURES.map(({ title, body, Icon }, index) => (
{title}
{body}
))}
);
}
/* ------------------------------------------------------------------ *
* Showcase — alternating sticky-ish parallax rows
* ------------------------------------------------------------------ */
const SHOTS = [
{
src: "/booking-page.png",
url: "since3.kumasy.de",
eyebrow: "Für deine Kundinnen",
title: "Die Seite, die dein Kunde sieht",
body: "Kalender, Kursfilter, Preis, freie Plätze — und ein Button. Buchen ohne Account möglich, damit niemand an der Registrierung abspringt.",
alt: "Öffentliche Buchungsseite mit Monatskalender, Kursfiltern und zwei buchbaren Kursen",
depth: 70,
},
{
src: "/courses.png",
url: "app.kumasy.de/kurse",
eyebrow: "Dein Kursplan",
title: "Kurse im Griff",
body: "Nach Tag sortiert, mit Belegung, Level, Raum und Status. Entwürfe veröffentlichst du gesammelt statt einzeln.",
alt: "Kursübersicht mit nach Datum gruppierten Kurskarten, Belegung und Veröffentlichungsstatus",
depth: 50,
},
{
src: "/payments.png",
url: "app.kumasy.de/zahlungen",
eyebrow: "Deine Zahlen",
title: "Geld, nachvollziehbar",
body: "Umsatz, offene Posten, Stornos und Teilerstattungen auf einer Seite. Alle Rechnungen auf einmal als ZIP.",
alt: "Zahlungsübersicht mit Monatsumsatz, offenen Posten und einer Tabelle aller Transaktionen",
depth: 70,
},
];
export function Showcase() {
return (
innen
,
"aus.",
],
]}
lead="Keine Render-Bilder — das ist die Oberfläche, mit der unser Pilotstudio heute arbeitet."
/>
Zugang sichern
{SHOTS.map((shot, index) => (
{/* Copy sits above the shot so the screenshot gets the full
column width — at half-width the UI text was unreadable. */}
{shot.eyebrow}
{shot.title}
{shot.body}
{/* Tinted stage: the screenshot rests on colour rather than
floating on the flat page. */}
))}
);
}
/* ------------------------------------------------------------------ *
* Steps
* ------------------------------------------------------------------ */
const STEPS: Item[] = [
{
title: "Daten übernehmen",
body: "Unser Migrationstool zieht Kurse, Kundinnen und Termine aus deinem bisherigen System in Kumasy. Du tippst nichts ab.",
Icon: UploadCloud,
},
{
title: "Einmal einrichten",
body: "Räume, Trainer, Preise, Stornoregeln und dein Branding. Danach legst du nur noch Termine an.",
Icon: Settings2,
},
{
title: "Link teilen",
body: "Deine Buchungsseite kommt in Instagram-Bio, Website und Newsletter. Ab da buchen und bezahlen deine Kundinnen selbst.",
Icon: Link2,
},
];
export function Steps() {
return (
ersten
,
"Buchung.",
],
]}
/>
{STEPS.map(({ title, body, Icon }, index) => (
{index + 1}
{title}
{body}
))}
);
}
/* ------------------------------------------------------------------ *
* Pricing
* ------------------------------------------------------------------ */
const INCLUDED = [
"Öffentliche Buchungsseite inklusive Gastbuchung, Warteliste und Rabattcodes",
"Zahlungen über Stripe, GoBD-konforme Rechnungen, Sammelexport",
"Migration deiner bestehenden Daten mit unserem Migrationstool",
"Support von echten Menschen, erreichbar und ansprechbar — kein KI-Chatbot",
"Keine Einrichtungsgebühr, keine Umsatzbeteiligung, keine Preisstufen",
];
export function Pricing() {
return (
Provision.
,
],
]}
lead="Du sollst am Monatsende wissen, was Kumasy kostet — ohne Taschenrechner."
/>
pro Monat
Alle Funktionen. Unbegrenzt Kurse, Trainer und Kundinnen.
{INCLUDED.map((item) => (
{item}
))}
Platz auf der Warteliste sichern
Monatlich abrechenbar. Die Konditionen zu Laufzeit und
Kündigung stehen in den{" "}
AGB
.
+ 0,50 €
pro Buchung
Trägt deine Kundin beim Checkout, nicht du. Für dich bleibt die
monatliche Rechnung planbar bei 150 €.
Transparenz-Hinweis
Zusätzlich fallen die Transaktionsgebühren von Stripe bzw.
PayPal nach deren jeweils gültiger Preisliste an. Diese rechnen
die Zahlungsdienstleister direkt ab — sie laufen nicht über uns,
und wir verdienen nichts daran.
);
}
/* ------------------------------------------------------------------ *
* Objections
* ------------------------------------------------------------------ */
const OBJECTIONS = [
{
eyebrow: null,
title: "„Ich bin zu klein dafür.“",
body: "Es gibt keine Mindestgröße und keine Staffelpreise. Wenn du regelmäßig Kurse gibst, rechnet sich das System ab den ersten Stunden, die du nicht mehr mit Buchungs- und Zahlungs-Nachverfolgung verbringst.",
},
{
eyebrow: null,
title: "„Ich bin schon woanders.“",
body: "Unser Migrationstool übernimmt deine bestehenden Daten automatisch — der Umzug ist kein Wochenendprojekt. Kumasy ist günstiger und aufgeräumter, komplett in Deutschland entwickelt, und im Support sitzt ein Mensch mit Namen statt eines KI-Chatbots.",
},
{
eyebrow: "Auf der Roadmap",
title: "„Und was kommt danach?“",
body: "Wir arbeiten daran, wiederkehrende Abläufe im Studioalltag weitgehend per KI zu automatisieren. Wer jetzt auf der Warteliste steht, bekommt das zuerst zu sehen.",
},
];
export function Objections() {
return (
{OBJECTIONS.map((item, index) => (
{item.eyebrow ? (
{item.eyebrow}
) : null}
{item.title}
{item.body}
))}
);
}
/* ------------------------------------------------------------------ *
* Pilot studio
* ------------------------------------------------------------------ */
const TECH = [
"Zahlungsabwicklung über Stripe",
"Hosting über Vercel, Region Frankfurt",
"DSGVO-konform, Daten bleiben in der EU",
"GoBD-konforme Rechnungsstellung",
];
export function Pilot() {
return (
Pilotstudio
Kumasy läuft im Alltag bei 120gradStudio.
Wir testen jede Funktion zuerst dort, bevor sie in die
Warteliste-Freigabe geht — an echten Kursen, echten Buchungen
und echten Zahlungen.
{/* Das Testimonial folgt, sobald 120gradStudio ein freigegebenes
Zitat geliefert hat. Bis dahin steht hier die belegbare
Aussage statt eines erfundenen Zitats — und im Markup kein
Review-Schema, das Google als Manipulation werten würde. */}
Seit dem Start laufen dort Kursplanung, Buchungen und Zahlungen
vollständig über Kumasy — im laufenden Betrieb, nicht in einer
Testumgebung.