import type { ReactNode } from "react";
import { cn } from "@/lib/utils";
import { Container } from "@/components/layout/Container";
import { Folio } from "@/components/layout/Folio";
import { GRID } from "@/components/layout/Section";
import { Lines } from "@/components/motion/Lines";
import { Reveal } from "@/components/motion/Reveal";
import type { Cta, FactItem, Headline } from "@/content/home";
import { Button } from "@/components/ui/Button";
import { Facts } from "@/components/ui/Facts";
import { Portrait } from "@/components/ui/Portrait";
/** The slice of `coaching` / `trainings` / `keynotes` the hero needs (structural). */
export interface ServiceHeroContent {
/** „01“ / „02“ / „03“ – mono, cols 1–2. */
numeral: string;
masthead: { center: string };
eyebrow: string;
h1: Headline;
/** The italic word may also carry `.gold-text` (keynotes – the page's one gradient word). */
h1GoldEm?: boolean;
/** Fließtext unter der Headline. Ohne Angabe trägt die Headline den Hero allein. */
subline?: string;
/** Haupt-Knopf. Ohne Angabe trägt der Hero nur Headline und Subline. */
cta?: Cta;
/** Fakten-Stapel oben rechts. Ohne Angabe (und ohne Foto) entfällt die Spalte. */
facts?: readonly FactItem[];
/** No fraction here – the page's own section counter is the only counter (see ). */
folio: { next?: { label: string; href: string } };
/** Photo alt / caption (keynote stage photo). */
alt?: string;
caption?: string;
}
export interface ServiceHeroProps {
content: ServiceHeroContent;
/** Stage photo (keynotes) – `null`/undefined = no photo. */
photo?: string | null;
/**
* Steht in derselben Spalte direkt unter Headline, Subline und Knopf.
* Auf der Messeseite hängt hier der Gutschein: Wer den Code gescannt hat,
* soll den Nachlass sehen, ohne erst an einer Sektionsüberschrift vorbei
* zu scrollen.
*/
children?: ReactNode;
/**
* Steht als letztes Zeichen in der H1, hinter dem Schlusspunkt. Auf der Messeseite
* hängt hier das Monogramm – die Begrüßung endet mit der Marke, zu der sie gehört.
*/
h1Mark?: ReactNode;
className?: string;
}
/**
* Service-page hero (ink, ≥ 60svh): mono numeral, H1 with one italic word,
* subline, the page's primary CTA, facts stack top-right, folio with the next
* section. Header monogram only – no hero draw.
*
* Ohne `subline` steht die Headline allein: sie erbt dann den Platz, den der
* Fließtext gehalten hat – eine Stufe größer und über die Spalten 3–11 statt
* 3–9. So trägt die Messeseite ihren Hero mit einem einzigen Satz.
*/
export function ServiceHero({ content, photo, children, h1Mark, className }: ServiceHeroProps) {
/* `masthead` und `eyebrow` stehen weiter in den Inhaltsdateien, werden aber seit
dem 06.09.2026 nicht mehr gerendert (Kundenwunsch): die Kopfzeile trug dieselben
Angaben doppelt, und über der H1 stand faktisch die Überschrift ein zweites Mal. */
const { numeral, masthead, h1, h1GoldEm, subline, cta, facts, folio, alt, caption } = content;
const hasPhoto = Boolean(photo);
/* Die Messeseite trägt weder Fakten noch Foto – dann gibt es die rechte Spalte
nicht, statt eine leere Reveal-Hülle in die Spalten 10–12 zu stellen. */
const hasAside = hasPhoto || Boolean(facts?.length);
/* Ohne Fließtext steht die Headline allein im Hero – dann bekommt sie dessen
Platz, statt dass der Hero um die fehlende Zeile zusammenfällt. Der Slot
darunter ändert daran nichts: Auf der Messeseite ist die große Begrüßung
ausdrücklich gewollt, der Gutschein hängt sich unter sie. */
const solo = !subline;
return (
{numeral}
{h1.before}
{h1.em && {h1.em}}
{h1.after}
{h1Mark && (
/* Auf der Grundlinie, hinter dem Punkt, 0,783 em hoch: Das ist die
Oberlänge der Playfair Display (im Browser an „h“ und „b“ gemessen;
die Versalhöhe liegt bei 0,719 em) – die Marke wird damit genau so
hoch, wie die Schrift dieser Zeile maximal wird, und keinen Punkt
höher. Die viewBox der Marke sitzt eng auf der Zeichnung, deshalb
ist Kastenhöhe gleich sichtbare Höhe.
Zwischen Punkt und Marke steht KEIN Leerzeichen im Markup – der
Abstand kommt aus `ml`, damit an dieser Stelle keine Umbruchstelle
entsteht und die Marke nicht allein in eine letzte Zeile rutscht.
Dekorativ (`aria-hidden`): Die Marke steht im Kopf schon mit Namen.
In der Überschrift stünde er ein zweites Mal – und zwar mitten im
Satz, den ein Screenreader vorliest. */
{h1Mark}
)}
{subline && (
{subline}
)}
{cta && (
)}
{children && (
{children}
)}