Kumasy-Marketing/app/components/sections.tsx
2026-09-20 01:52:28 +02:00

814 lines
28 KiB
TypeScript

"use client";
import Image from "next/image";
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";
/* ------------------------------------------------------------------ *
* Shared section scaffolding
* ------------------------------------------------------------------ */
function Section({
id,
children,
className = "",
}: {
id?: string;
children: ReactNode;
className?: string;
}) {
return (
<section id={id} className={`px-4 py-20 sm:py-[80px] ${className}`}>
<div className="mx-auto max-w-[1200px]">{children}</div>
</section>
);
}
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 (
<div className={centered ? "mx-auto max-w-[760px] text-center" : "max-w-[760px]"}>
<Reveal>
<Eyebrow wash={wash}>{eyebrow}</Eyebrow>
</Reveal>
{/* Tracking tightens as the heading scrolls toward centre — the type
settles into its final, compressed form. */}
<ScrollTracking from={0.02} to={-0.032}>
<h2 className="mt-5 font-display text-[clamp(2rem,4.8vw,2.9rem)] font-semibold leading-[1.06] text-ink">
{titleLines.map((line, index) => (
<MaskedWords
key={index}
className="block"
words={line}
delay={index * 0.08}
/>
))}
</h2>
</ScrollTracking>
{lead ? (
<Reveal delay={0.18}>
<p
className={`mt-5 text-body-lg text-slate-body ${centered ? "mx-auto max-w-[560px]" : "max-w-[560px]"}`}
>
{lead}
</p>
</Reveal>
) : null}
</div>
);
}
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 (
<Section id="problem">
<SectionHead
eyebrow="Das Problem"
wash="peach"
titleLines={[
["Der", "Kurs", "ist", "ausgebucht."],
[
"Dein",
"Kopf",
<em key="leider" className="brand-text italic">
leider
</em>,
"auch.",
],
]}
lead="Du bist Trainerin, nicht Sachbearbeiterin. Trotzdem geht jede Woche ein halber Arbeitstag für Koordination drauf."
/>
<ul className="mt-14 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
{PROBLEMS.map(({ title, body, Icon }, index) => (
<RevealItem key={title} delay={index * 0.08}>
<div className="h-full glass glass-rim rounded-cards p-5 transition-transform duration-500 ease-[var(--ease-out-soft)] hover:-translate-y-1">
<span className="flex size-9 items-center justify-center rounded-full bg-peach-wash text-peach-ink">
<Icon className="size-[18px]" strokeWidth={1.7} />
</span>
<h3 className="mt-4 text-body-lg font-semibold leading-snug text-ink">
{title}
</h3>
<p className="mt-2 text-body text-slate-body">{body}</p>
</div>
</RevealItem>
))}
</ul>
</Section>
);
}
/* ------------------------------------------------------------------ *
* 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 (
<Section id="funktionen">
<SectionHead
eyebrow="Die Lösung"
wash="mint"
titleLines={[
["Ein", "System", "statt", "drei", "Tools"],
[
"und",
<em key="einer" className="brand-text italic">
einer
</em>,
"Tabelle.",
],
]}
lead="Alles, was ein Kursbetrieb wirklich braucht — und nichts, wofür du eine Schulung brauchst."
/>
<ul className="mt-14 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{FEATURES.map(({ title, body, Icon }, index) => (
<RevealItem key={title} delay={(index % 3) * 0.08}>
<div className="h-full glass glass-rim rounded-cards p-6 transition-transform duration-500 ease-[var(--ease-out-soft)] hover:-translate-y-1">
<span className="flex size-10 items-center justify-center rounded-full bg-amber-soft text-[#8a6d00]">
<Icon className="size-5" strokeWidth={1.6} />
</span>
<h3 className="mt-5 text-subheading font-semibold tracking-[-0.26px] text-ink">
{title}
</h3>
<p className="mt-2.5 text-body text-slate-body">{body}</p>
</div>
</RevealItem>
))}
</ul>
</Section>
);
}
/* ------------------------------------------------------------------ *
* 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 (
<Section id="einblick">
<div className="flex flex-col gap-6 md:flex-row md:items-end md:justify-between">
<SectionHead
eyebrow="Einblick"
titleLines={[
["So", "sieht", "dein", "Studio"],
[
"von",
<em key="innen" className="brand-text italic">
innen
</em>,
"aus.",
],
]}
lead="Keine Render-Bilder — das ist die Oberfläche, mit der unser Pilotstudio heute arbeitet."
/>
<Reveal delay={0.2}>
<BrandButton href="#warteliste">
Zugang sichern
<ArrowRight className="size-4" strokeWidth={2} />
</BrandButton>
</Reveal>
</div>
<div className="mt-20 flex flex-col gap-20 lg:gap-28">
{SHOTS.map((shot, index) => (
<div key={shot.src}>
{/* Copy sits above the shot so the screenshot gets the full
column width — at half-width the UI text was unreadable. */}
<Reveal className="mx-auto max-w-[620px] text-center">
<Eyebrow wash={index % 2 === 1 ? "peach" : "sky"}>
{shot.eyebrow}
</Eyebrow>
<h3 className="mt-5 font-display text-heading-sm font-semibold tracking-[-0.4px] text-ink">
{shot.title}
</h3>
<p className="mx-auto mt-4 max-w-[540px] text-body-lg text-slate-body">
{shot.body}
</p>
</Reveal>
{/* Tinted stage: the screenshot rests on colour rather than
floating on the flat page. */}
<div className="relative mt-10 overflow-hidden rounded-[32px] px-4 pb-0 pt-10 sm:px-10 sm:pt-14">
<div aria-hidden className="absolute inset-0 -z-10">
<div className="aurora absolute inset-0 opacity-80" />
<div
className="absolute inset-x-0 bottom-0 h-1/3"
style={{
background:
"linear-gradient(to top, rgba(249,250,251,0.9), transparent)",
}}
/>
</div>
<ParallaxLayer depth={shot.depth}>
<Tilt max={3}>
<BrowserFrame url={shot.url} className="mx-auto max-w-[980px]">
<Image
src={shot.src}
alt={shot.alt}
width={1918}
height={911}
sizes="(max-width: 1024px) 94vw, 980px"
className="h-auto w-full"
/>
</BrowserFrame>
</Tilt>
</ParallaxLayer>
</div>
</div>
))}
</div>
</Section>
);
}
/* ------------------------------------------------------------------ *
* 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 (
<Section>
<SectionHead
eyebrow="In drei Schritten"
wash="mint"
align="center"
titleLines={[
["Vom", "ersten", "Login"],
[
"bis",
"zur",
<em key="ersten" className="brand-text italic">
ersten
</em>,
"Buchung.",
],
]}
/>
<ol className="mt-14 grid gap-4 md:grid-cols-3">
{STEPS.map(({ title, body, Icon }, index) => (
<RevealItem key={title} delay={index * 0.11}>
<div className="h-full glass glass-rim rounded-cards p-6">
<div className="flex items-center justify-between">
<span className="flex size-10 items-center justify-center rounded-full bg-mint-wash text-mint-ink">
<Icon className="size-5" strokeWidth={1.6} />
</span>
<span
aria-hidden
className="font-display text-heading-sm font-semibold leading-none"
style={{
background: "var(--gradient-amber)",
WebkitBackgroundClip: "text",
backgroundClip: "text",
color: "transparent",
}}
>
{index + 1}
</span>
</div>
<h3 className="mt-5 text-subheading font-semibold tracking-[-0.26px] text-ink">
{title}
</h3>
<p className="mt-2.5 text-body text-slate-body">{body}</p>
</div>
</RevealItem>
))}
</ol>
</Section>
);
}
/* ------------------------------------------------------------------ *
* 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 (
<Section id="preis">
<SectionHead
eyebrow="Preis"
align="center"
titleLines={[
["Ein", "Preis.", "Keine", "Staffelung."],
[
"Keine",
<em key="provision" className="brand-text italic">
Provision.
</em>,
],
]}
lead="Du sollst am Monatsende wissen, was Kumasy kostet — ohne Taschenrechner."
/>
<div className="mt-14 grid gap-4 lg:grid-cols-[1.15fr_1fr]">
<Reveal>
<div className="flex h-full flex-col glass-xl glass-rim rounded-cards p-8">
<p className="flex items-baseline gap-2">
<Counter
to={150}
suffix=" €"
className="font-display text-heading font-semibold tracking-[-1.15px] text-ink"
/>
<span className="text-body text-slate-helper">pro Monat</span>
</p>
<p className="mt-2 text-body-lg text-slate-body">
Alle Funktionen. Unbegrenzt Kurse, Trainer und Kundinnen.
</p>
<ul className="mt-7 flex flex-col gap-3.5">
{INCLUDED.map((item) => (
<li key={item} className="flex gap-3 text-body text-slate-body">
<Check
className="mt-1 size-4 shrink-0 text-mint-ink"
strokeWidth={2.4}
/>
{item}
</li>
))}
</ul>
<div className="mt-8 flex flex-col items-start gap-3">
<BrandButton href="#warteliste">
Platz auf der Warteliste sichern
</BrandButton>
<p className="text-[13px] text-slate-helper">
[Mindestlaufzeit und Kündigungsfrist hier ergänzen]
</p>
</div>
</div>
</Reveal>
<div className="flex flex-col gap-4">
<Reveal delay={0.09}>
<div className="rounded-cards glass glass-rim bg-sky-wash/50 p-7">
<p className="flex items-baseline gap-2">
<span className="font-display text-heading-sm font-semibold tracking-[-0.4px] text-ink">
+ 0,50 €
</span>
<span className="text-body text-sky-ink">pro Buchung</span>
</p>
<p className="mt-3 text-body text-slate-body">
Trägt deine Kundin beim Checkout, nicht du. Für dich bleibt die
monatliche Rechnung planbar bei 150 €.
</p>
</div>
</Reveal>
<Reveal delay={0.16}>
<div className="rounded-cards glass glass-rim bg-peach-wash/50 p-7">
<Eyebrow wash="peach" className="!bg-white/70">
Transparenz-Hinweis
</Eyebrow>
<p className="mt-3 text-body text-slate-body">
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.
</p>
</div>
</Reveal>
</div>
</div>
</Section>
);
}
/* ------------------------------------------------------------------ *
* 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 (
<Section>
<SectionHead
eyebrow="Ehrlich gesagt"
wash="peach"
align="center"
titleLines={[["Was", "du", "jetzt"], ["wahrscheinlich", "denkst."]]}
/>
<ul className="mt-14 grid gap-4 md:grid-cols-3">
{OBJECTIONS.map((item, index) => (
<RevealItem key={item.title} delay={index * 0.1}>
<div className="h-full glass glass-rim rounded-cards p-6">
{item.eyebrow ? (
<Eyebrow wash="mint" className="mb-3">
{item.eyebrow}
</Eyebrow>
) : null}
<h3 className="text-subheading font-semibold tracking-[-0.26px] text-ink">
{item.title}
</h3>
<p className="mt-3 text-body text-slate-body">{item.body}</p>
</div>
</RevealItem>
))}
</ul>
</Section>
);
}
/* ------------------------------------------------------------------ *
* 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 (
<Section>
<div className="grid gap-4 lg:grid-cols-[1.35fr_1fr]">
<Reveal>
<div className="flex h-full flex-col justify-between glass glass-rim rounded-cards p-8">
<div>
<Eyebrow wash="mint">Pilotstudio</Eyebrow>
<h2 className="mt-5 font-display text-[clamp(1.75rem,3.4vw,2.25rem)] font-semibold leading-[1.08] tracking-[-0.026em] text-ink">
Kumasy läuft im Alltag bei 120gradStudio.
</h2>
<p className="mt-4 max-w-[520px] text-body-lg text-slate-body">
Wir testen jede Funktion zuerst dort, bevor sie in die
Warteliste-Freigabe geht — an echten Kursen, echten Buchungen
und echten Zahlungen.
</p>
</div>
<blockquote className="mt-8 border-l-2 border-hairline pl-5">
<p className="text-body-lg italic text-ink">
„[Hier das Zitat von 120gradStudio einsetzen — ein bis zwei
Sätze, am besten mit konkreter Zahl.]“
</p>
<footer className="mt-3 text-body text-slate-helper">
[Name], 120gradStudio
</footer>
</blockquote>
</div>
</Reveal>
<Reveal delay={0.1}>
<div className="glass-ink glass-rim h-full rounded-cards p-8">
<Eyebrow wash="amber" className="!border-white/25 !bg-white/15 !text-amber">
Technik & Recht
</Eyebrow>
<ul className="mt-6 flex flex-col gap-4">
{TECH.map((item) => (
<li key={item} className="flex gap-3 text-body text-white/85">
<Check
className="mt-1 size-4 shrink-0 text-amber"
strokeWidth={2.2}
/>
{item}
</li>
))}
</ul>
</div>
</Reveal>
</div>
</Section>
);
}
/* ------------------------------------------------------------------ *
* FAQ
* ------------------------------------------------------------------ */
export function FaqSection() {
return (
<Section id="faq">
<div className="grid gap-10 lg:grid-cols-[0.8fr_1.2fr]">
<div>
<Reveal>
<Eyebrow>FAQ</Eyebrow>
</Reveal>
<h2 className="mt-5 font-display text-[clamp(2rem,4.6vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.032em] text-ink">
<MaskedWords words={["Häufige", "Fragen"]} />
</h2>
<Reveal delay={0.15}>
<p className="mt-4 text-body text-slate-body">
Deine Frage ist nicht dabei? Schreib uns — es antwortet ein
Mensch.
</p>
</Reveal>
<Reveal delay={0.2}>
<GhostLink href="mailto:info@kumasy.de" className="mt-3">
info@kumasy.de
<ArrowRight className="size-4" strokeWidth={2} />
</GhostLink>
</Reveal>
</div>
<Reveal delay={0.1}>
<div className="border-t border-hairline">
<Faq question="Brauchen meine Kundinnen einen Account?">
Nein. Gastbuchung ohne Registrierung ist Standard — genau da
springen sonst die meisten ab. Wer will, legt sich trotzdem ein
Konto an und sieht seine Buchungshistorie.
</Faq>
<Faq question="Was passiert mit meinen bestehenden Daten?">
Unser Migrationstool pflegt Kurse, Kundinnen und Termine aus
deinem alten System automatisch in Kumasy ein. Du musst nichts
abtippen und kannst vorher prüfen, was übernommen wird.
</Faq>
<Faq question="Wer zahlt die 0,50 € pro Buchung?">
Deine Kundin, beim Checkout. Dein monatlicher Betrag bleibt bei
150 € — unabhängig davon, ob du 20 oder 2.000 Buchungen im Monat
hast. Dazu kommen nur die Transaktionsgebühren von Stripe bzw.
PayPal.
</Faq>
<Faq question="Ist Kumasy DSGVO-konform?">
Ja. Gehostet wird über Vercel in der Region Frankfurt, Zahlungen
laufen über Stripe, Rechnungen werden GoBD-konform erstellt.
[Auftragsverarbeitungsvertrag und Datenschutzerklärung hier
verlinken.]
</Faq>
<Faq question="Wann kann ich starten?">
Wir sind in der Pilotphase und geben nach und nach Zugänge frei.
Du bekommst eine E-Mail, sobald du dran bist.
</Faq>
</div>
</Reveal>
</div>
</Section>
);
}
/* ------------------------------------------------------------------ *
* Closing CTA
* ------------------------------------------------------------------ */
export function ClosingCta() {
return (
<Section className="pb-28">
<Reveal>
<div className="relative isolate overflow-hidden glass-xl glass-rim rounded-cards px-6 py-16 text-center sm:px-12">
<div
aria-hidden
className="pointer-events-none absolute inset-x-0 top-0 h-[3px]"
style={{ background: "var(--gradient-amber)" }}
/>
<div
aria-hidden
className="blob pointer-events-none absolute left-1/2 top-full size-[520px] -translate-x-1/2 -translate-y-1/2 rounded-full opacity-25"
style={{
background:
"radial-gradient(circle, rgba(38,192,255,0.55) 0%, transparent 68%)",
filter: "blur(70px)",
}}
/>
<Eyebrow>Pilotphase · Warteliste</Eyebrow>
<h2 className="mx-auto mt-6 max-w-[620px] font-display text-[clamp(2rem,5vw,3.0625rem)] font-semibold leading-[1.04] tracking-[-0.04em] text-ink">
<MaskedWords
words={[
"Sei",
"dabei,",
"bevor",
"wir",
<em key="oeffnen" className="brand-text italic">
öffnen
</em>,
]}
/>
</h2>
<Reveal delay={0.25}>
<p className="mx-auto mt-5 max-w-[460px] text-body-lg text-slate-body">
Trag dich ein und wir melden uns, sobald dein Zugang bereit ist.
Keine Zahlungsdaten, keine Verpflichtung.
</p>
</Reveal>
<Reveal delay={0.32}>
<div className="mx-auto mt-9 max-w-[520px] text-left">
<WaitlistForm compact />
</div>
</Reveal>
</div>
</Reveal>
</Section>
);
}
/* ------------------------------------------------------------------ *
* Footer
* ------------------------------------------------------------------ */
export function Footer() {
return (
<footer className="border-t border-hairline px-4 py-10">
<div className="mx-auto flex max-w-[1200px] flex-col gap-6 sm:flex-row sm:items-center sm:justify-between">
<Logo />
<nav aria-label="Rechtliches">
<ul className="flex flex-wrap items-center gap-x-6 gap-y-2 text-body text-slate-helper">
<li>
<a href="mailto:info@kumasy.de" className="hover:text-ink">
info@kumasy.de
</a>
</li>
<li>
<a href="/impressum" className="hover:text-ink">
Impressum
</a>
</li>
<li>
<a href="/datenschutz" className="hover:text-ink">
Datenschutz
</a>
</li>
<li>
<a href="/agb" className="hover:text-ink">
AGB
</a>
</li>
</ul>
</nav>
</div>
</footer>
);
}