/**
 * zo-theme.css — Theme-Stylesheet (Interaktion, Komponenten, Sektionen, Seiten).
 *
 * Basis-Design-Tokens (Farben, Spacing 10–90, Typografie, Radius, Shadow) leben KANONISCH
 * in theme.json und werden zur Laufzeit als --wp--preset--* / --wp--custom--* bereitgestellt
 * (auch im Block-Editor). Diese Datei KONSUMIERT sie; sie definiert keine zweite Token-Quelle.
 * Der :root-Block unten hält NUR lokale Konstanten, für die (noch) kein theme.json-Token
 * existiert — Kandidaten fürs theme.json (markiert TODO).
 *
 * Reihenfolge (ITCSS-nah, unlayered): tokens → base → components → sections → pages → integrations.
 * Bewusst KEIN @layer: theme.json/WP geben Global-Styles unlayered aus; @layer-Regeln würden
 * dagegen verlieren (empirisch belegt). Kaskade wird über Reihenfolge + Scope gesteuert.
 * Konvention: neue Komponenten in den passenden Abschnitt; Werte immer über theme.json-Tokens
 * bzw. die :root-Konstanten oben referenzieren, nie hartkodieren.
 */

/* ===================================================================== *
 *  TOKENS — lokale Konstanten ohne theme.json-Entsprechung               *
 * ===================================================================== */
:root {
	--zo-grid-line: #E5E0F5;          /* Lernhero-Hintergrundgitter — TODO theme.json? */
	--zo-action-hover: var(--wp--custom--color--violet-link); /* dunklerer Primary-Hover (add-to-cart), Ton = Link-Token (#31) */
	--zo-overline: #C0ABFF;           /* Entdecken-Overline auf dunklem Bild — TODO theme.json? */

	/* RemixIcon arrow-right-line als Mask-Quelle (currentColor, kein Inline-SVG im Content).
	   Dritte Verwendung (Teaser-Universal-CTA, Text-Bild-Button, Action-Link, #188) →
	   extrahiert; --zo-tu-icon-arrow ist jetzt Alias hierauf. */
	--zo-icon-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z'/%3E%3C/svg%3E");

	/* PDP-Vertikalrhythmus (#153, revalidiert #289 am Frame 6761:84794 "XL", 2026-09-16).
	   --zo-pdph-pad = Innenrand des PDP-Heros oben/unten: "PDP Header .base" traegt jetzt
	                   48/48 (Box 668 = 48 + 572 + 48; die aeltere 40er-Fassung 5076:34309
	                   ist ueberholt). Alle Abstaende ZWISCHEN den Sektions-Boxen (Hero ->
	                   Sprungnav -> Sektionen -> Footer) kommen aus var(--zo-module-gap):
	                   itemSpacing des Seiten-Frames ist an die Modul-Reihe 40/56/64/96
	                   gebunden (VariableID 5033:24673, module-gap.md). Die fruehere
	                   Best-Guess-Konstante --zo-pdp-nav-gap (80, Frame 4573-37150) entfaellt
	                   damit (Registry pdp-sprungnav-abstand aufgeloest). */
	--zo-pdph-pad: 48px;

	/* Rail = LEGACY-ALIAS auf die Grid-Foundation (Phase 1 #128, 2026-08-03). Die #99-Rail
	   (1360 / Inset 16-24-40) war eine Drift-Lesart und ist auf die kanonischen Grid-Tokens
	   gemappt: Cap 1328, Inset 16/24/32 (Werte: docs/knowledge/content-rail.md). Bestands-
	   Konsumenten (width: --zo-rail-w bzw. padding-inline: --zo-rail-bleed) liegen damit auf
	   der Figma-Kante; Phase 2 zieht sie modulweise auf .zo-container/.zo-grid, Phase 3
	   entfernt die Aliase (kein neuer Konsument mehr!).
	   Zwei Ausprägungen, gleiche Kante:
	   • boxed:  width: var(--zo-rail-w); margin-inline: auto;         (gecappter, zentrierter Block)
	   • bleed:  padding-inline: var(--zo-rail-bleed);                 (Full-Bleed-Track/Grid) */
	--zo-rail-max: var(--zo-content-max);
	--zo-rail-inset: var(--zo-grid-margin);
	--zo-rail-w: min(var(--zo-rail-max), 100% - 2 * var(--zo-rail-inset));
	--zo-rail-bleed: max(var(--zo-rail-inset), calc((100% - var(--zo-rail-max)) / 2));
}

/* Kanonisches Layout-Grid (Figma Foundations 4407:30657, via layoutGrids gemessen).
   EINE Token-Quelle; ersetzt schrittweise die erfundene Rail (#99). Fest & konsistent:
   Spalten 4/8/12 · Gutter 16 · Rand 16/24/32. Content-Cap 1328 (= 12×96 + 11×16).
   DQ1 ENTSCHIEDEN (Olaf, #128 2026-08-03): Content-Max final 1328, ab 1440 hart zentriert.
   Nutzung: .zo-container (Schiene) + .zo-grid
   (Spalten) + .zo-col(-md/-lg)-* (Spans). Doku/Migration:
   docs/superpowers/specs/2026-08-01-grid-system-design.md */
:root {
	--zo-grid-gutter: var(--wp--custom--grid--gutter, 16px);
	--zo-content-max: var(--wp--custom--grid--content-max, 1328px);
	--zo-grid-margin: 16px;   /* SM <640 — MD/LG via @media unten */
	--zo-grid-columns: 4;     /* SM <640 — MD/LG via @media unten */
	/* Abstand zwischen Seiten-Modulen und Content→Footer (#174). Figma: itemSpacing der
	   Seiten-Frames 5568:40005, variablengebunden 5033:24672/24678/24677/24673 — Spec
	   docs/figma-specs/module-gap.md. Kein theme.json-Preset: 56/96 fehlen in der Skala,
	   Presets sind viewport-fix. */
	--zo-module-gap: 40px;    /* SM <640 — MD/LG/XL via @media unten */
}
@media (min-width: 640px)  { :root { --zo-grid-margin: 24px; --zo-grid-columns: 8;  --zo-module-gap: 56px; } }   /* MD */
@media (min-width: 1024px) { :root { --zo-grid-margin: 32px; --zo-grid-columns: 12; --zo-module-gap: 64px; } }   /* LG */
@media (min-width: 1440px) { :root { --zo-module-gap: 96px; } }   /* XL */

/* Text scale for headings and running copy (#372). Figma "Heading" 4926:24144 (H1-H6 per
   viewport, Spacing=Yes paddingBottom = gap to the following text) and "Paragraph"
   5529:39784 (Body Copy 16/22 from LG, 14/20 below) — spec docs/figma-specs/paragraph.md.
   theme.json styles.elements.h1-h6 point here, so every heading without its own component
   size follows the steps. Line heights are unitless ratios: a heading or paragraph with an
   editorial preset size (has-*-font-size) keeps a proportional line height.
   --zo-type-h{n}-* = the visual step of Figma type Hn; --zo-h{n}-* = what an <hn> uses.
   Both are equal everywhere (the article remap from #372 was dropped in #402).
   --zo-text-gap: text block -> next heading (group itemSpacing 24, all viewports). */
:root {
	--zo-type-h1-fs: var(--wp--custom--font-size--24); --zo-type-h1-lh: calc(32 / 24); --zo-type-h1-pb: 16px;
	--zo-type-h2-fs: var(--wp--custom--font-size--20); --zo-type-h2-lh: calc(26 / 20); --zo-type-h2-pb: 12px;
	--zo-type-h3-fs: var(--wp--custom--font-size--18); --zo-type-h3-lh: calc(24 / 18); --zo-type-h3-pb: 8px;
	--zo-type-h4-fs: 16px; --zo-type-h4-lh: calc(22 / 16); --zo-type-h4-pb: 8px;
	--zo-type-h5-fs: 16px; --zo-type-h5-lh: calc(22 / 16); --zo-type-h5-pb: 8px;
	--zo-type-h6-fs: 16px; --zo-type-h6-lh: calc(22 / 16); --zo-type-h6-pb: 8px;
	--zo-copy-fs: 14px; --zo-copy-lh: calc(20 / 14); --zo-copy-gap: 20px;
	--zo-text-gap: var(--wp--preset--spacing--40); /* 24 */
}
@media (min-width: 640px) { :root {   /* MD */
	--zo-type-h1-fs: var(--wp--custom--font-size--32); --zo-type-h1-lh: calc(42 / 32); --zo-type-h1-pb: 24px;
	--zo-type-h2-fs: var(--wp--custom--font-size--24); --zo-type-h2-lh: calc(32 / 24); --zo-type-h2-pb: 16px;
	--zo-type-h3-fs: var(--wp--custom--font-size--20); --zo-type-h3-lh: calc(26 / 20); --zo-type-h3-pb: 12px;
	--zo-type-h4-fs: var(--wp--custom--font-size--18); --zo-type-h4-lh: calc(24 / 18); --zo-type-h4-pb: 12px;
	--zo-type-h5-pb: 12px;
	--zo-type-h6-pb: 12px;
} }
@media (min-width: 1024px) { :root {  /* LG+ */
	--zo-type-h1-fs: var(--wp--custom--font-size--48); --zo-type-h1-lh: calc(62 / 48); --zo-type-h1-pb: 32px;
	--zo-type-h2-fs: var(--wp--custom--font-size--40); --zo-type-h2-lh: calc(52 / 40); --zo-type-h2-pb: 24px;
	--zo-type-h3-fs: var(--wp--custom--font-size--24); --zo-type-h3-lh: calc(32 / 24); --zo-type-h3-pb: 16px;
	--zo-type-h4-fs: var(--wp--custom--font-size--20); --zo-type-h4-lh: calc(26 / 20);
	--zo-type-h5-fs: var(--wp--custom--font-size--18); --zo-type-h5-lh: calc(24 / 18);
	--zo-copy-fs: 16px; --zo-copy-lh: calc(22 / 16); --zo-copy-gap: 22px;
} }

/* Tag -> step mapping (default: <hn> looks like Hn). */
:root {
	--zo-h1-fs: var(--zo-type-h1-fs); --zo-h1-lh: var(--zo-type-h1-lh); --zo-h1-pb: var(--zo-type-h1-pb);
	--zo-h2-fs: var(--zo-type-h2-fs); --zo-h2-lh: var(--zo-type-h2-lh); --zo-h2-pb: var(--zo-type-h2-pb);
	--zo-h3-fs: var(--zo-type-h3-fs); --zo-h3-lh: var(--zo-type-h3-lh); --zo-h3-pb: var(--zo-type-h3-pb);
	--zo-h4-fs: var(--zo-type-h4-fs); --zo-h4-lh: var(--zo-type-h4-lh); --zo-h4-pb: var(--zo-type-h4-pb);
	--zo-h5-fs: var(--zo-type-h5-fs); --zo-h5-lh: var(--zo-type-h5-lh); --zo-h5-pb: var(--zo-type-h5-pb);
	--zo-h6-fs: var(--zo-type-h6-fs); --zo-h6-lh: var(--zo-type-h6-lh); --zo-h6-pb: var(--zo-type-h6-pb);
}

/* Die EINE Content-Schiene: max 1328, zentriert, responsive Ränder. Ersetzt --zo-rail-w. */
.zo-container {
	width: min(100% - 2 * var(--zo-grid-margin), var(--zo-content-max));
	margin-inline: auto;
}
/* Responsives Spalten-Raster. Module werden DIREKTE Kinder und spannen via .zo-col-*.
   Keine eigene max-width hier — die Breite kommt allein von .zo-container. */
.zo-grid {
	display: grid;
	grid-template-columns: repeat(var(--zo-grid-columns), 1fr);
	column-gap: var(--zo-grid-gutter);
}
/* Span-Utilities — explizit je Breakpoint (mobile-first). SM ≤4, MD ≤8, LG+ ≤12 Spalten. */
.zo-col-1 { grid-column: span 1; } .zo-col-2 { grid-column: span 2; }
.zo-col-3 { grid-column: span 3; } .zo-col-4 { grid-column: span 4; }
@media (min-width: 640px) {
	.zo-col-md-1 { grid-column: span 1; } .zo-col-md-2 { grid-column: span 2; }
	.zo-col-md-3 { grid-column: span 3; } .zo-col-md-4 { grid-column: span 4; }
	.zo-col-md-5 { grid-column: span 5; } .zo-col-md-6 { grid-column: span 6; }
	.zo-col-md-7 { grid-column: span 7; } .zo-col-md-8 { grid-column: span 8; }
}
@media (min-width: 1024px) {
	.zo-col-lg-1  { grid-column: span 1;  } .zo-col-lg-2  { grid-column: span 2;  }
	.zo-col-lg-3  { grid-column: span 3;  } .zo-col-lg-4  { grid-column: span 4;  }
	.zo-col-lg-5  { grid-column: span 5;  } .zo-col-lg-6  { grid-column: span 6;  }
	.zo-col-lg-7  { grid-column: span 7;  } .zo-col-lg-8  { grid-column: span 8;  }
	.zo-col-lg-9  { grid-column: span 9;  } .zo-col-lg-10 { grid-column: span 10; }
	.zo-col-lg-11 { grid-column: span 11; } .zo-col-lg-12 { grid-column: span 12; }
}

/* ===================================================================== *
 *  BASE — Reset/Grundlagen (box-sizing, Transitions, Bild-Grundregeln, Flow-Gap)
 * ===================================================================== */

/* Page-section flow (#254): stepped module gap between top-level page modules.
   Designer confirmed the 40/56/64/96 series as the general page-section rule
   (module-gap.md); templates opt in via className on post-content — replaces the
   viewport-fixed root blockGap (24px) there. Same pattern as .zo-article (#238).
   :root prefix: the editor canvas injects WP layout styles after theme CSS (same
   specificity, later order) — without it the flow gap loses there. Front end unaffected. */
:root .zo-module-flow > * { margin-block: 0; }
:root .zo-module-flow > * + * { margin-block-start: var(--zo-module-gap); }
/* The series is a SECTION gap: freely typed text blocks (heading + paragraphs directly
   in post-content, e.g. /uebers-lab/) keep the editorial 24px rhythm between each other —
   precedent: the article content stream has its own smaller rhythm, not the module series.
   A section next to a text block still gets the series (rule above). */
:root .zo-module-flow > :is(p, h1, h2, h3, h4, h5, h6, ul, ol, blockquote, figure, table, pre)
  + :is(p, h1, h2, h3, h4, h5, h6, ul, ol, blockquote, figure, table, pre) {
	margin-block-start: var(--wp--preset--spacing--40); /* 24 = previous root blockGap */
}
/* Trailing empty paragraphs (editor artifact) would add a phantom module gap before
   the footer — hide them. */
:root .zo-module-flow > p:empty { display: none; }
/* On flow pages the topic-grid section keeps no own padding-block: its 80er padding
   (COMPONENTS §Themen-Grid) is editorial safety spacing without Figma source and would
   double the flow gap here. */
:root .zo-module-flow > .zo-topics { padding-block: 0; }

/* Text rhythm inside both content flows — page flow and article stream (#372, Figma
   "Paragraph" 5529:39784 + "Heading" 4926:24144, spec docs/figma-specs/paragraph.md §3).
   Only plain text blocks: a paragraph with an editorial preset size (has-*-font-size or a
   custom inline size) keeps it. Heading -> text = the heading's pb step, paragraph ->
   paragraph = one copy line (Figma separates paragraphs by a blank line), text -> next
   heading = 24. Text <-> module keeps the module gap of the respective flow. */
:root :is(.zo-module-flow, .zo-article .zo-article__content) > :is(p, ul, ol):not([class*="-font-size"], [style*="font-size"]) {
	font-size: var(--zo-copy-fs);
	line-height: var(--zo-copy-lh);
	letter-spacing: 0.01em;
}
:root :is(.zo-module-flow, .zo-article .zo-article__content) > :is(p, ul, ol) + :is(p, ul, ol) { margin-block-start: var(--zo-copy-gap); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > :is(p, ul, ol) + :is(h1, h2, h3, h4, h5, h6) { margin-block-start: var(--zo-text-gap); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > h1 + :is(p, ul, ol, h2, h3, h4, h5, h6) { margin-block-start: var(--zo-h1-pb); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > h2 + :is(p, ul, ol, h3, h4, h5, h6) { margin-block-start: var(--zo-h2-pb); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > h3 + :is(p, ul, ol, h4, h5, h6) { margin-block-start: var(--zo-h3-pb); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > h4 + :is(p, ul, ol, h5, h6) { margin-block-start: var(--zo-h4-pb); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > h5 + :is(p, ul, ol, h6) { margin-block-start: var(--zo-h5-pb); }
:root :is(.zo-module-flow, .zo-article .zo-article__content) > h6 + :is(p, ul, ol) { margin-block-start: var(--zo-h6-pb); }

/* GT Haptik: Normalformen statt Alternate-Glyphen (#244, Philipp: alle vier).
   Die woff2 tragen die Alternates (0 mit Punkt, R mit Schraegstrich, eckige C/G) als
   Default-Glyphen; ss01 tauscht C/G/R und 0 auf die Normalformen der Figma-Referenz
   (Node 4507-34294), ss04 haelt die 0 zusaetzlich explizit fest. Vererbt sich von body
   ueberallhin; Figtree hat keine ss-Features im GSUB -> Fliesstext unveraendert. */
body {
	font-feature-settings: "ss01" 1, "ss04" 1;
}

/* Bilder in Karten: volle Breite, kein Eigenabstand oben */
.zo-section .wp-block-column > .wp-block-group.has-white-background-color > .wp-block-image {
	margin: 0;
}

.wp-block-image img {
	display: block;
	width: 100%;
}

/* <picture>-Wrapper aus zo_picture() (#107): kein eigenes Layout-Box — das <img> verhält
   sich exakt wie zuvor (Selektoren/Positionierung greifen unverändert am <img>). */
.zo-picture { display: contents; }

/* Inline-Text-Highlighting <mark> (#141 Spec-Default, #303 B1a: einziger Stil): das eigene
   Editor-Format zo/highlight (inc/text-highlight.php) schreibt nacktes <mark>, core/text-color
   ist abgemeldet — diese Regel IST die Hervorhebung. Figma 5930-33927: Fläche = Inline-Content-Box
   (24px bei 18/26-Text), kein Padding. Token lilac #E0D6FF; color:inherit neutralisiert das
   UA-Schwarz — Textfarbe bleibt die des Absatzes. */
mark {
	background-color: var(--wp--custom--color--lilac);
	color: inherit;
}

/* Form-Controls-Basis (#170, Figma „Input field" 5551:21846 + „Dropdown button" 5308:910,
   Abruf/Sampling 2026-08-10 — Spec: docs/figma-specs/form-controls.md).
   Native Felder überall (WP, WooCommerce, LearnDash, FluentForms) erben den EINEN Standard:
   4px-Unterkante statt Kasten, transparent auf dem jeweiligen Grund, Feldhöhe 48.
   States: default · hover (violet-dark) · focus (Input: primary-Unterkante = Figma „Selected",
   bewusst kein Ring; Select: 4px-Ring foreground außen wie Button-Basis #169) · error
   ([aria-invalid="true"] → red-500 + Icon; Woo-/FluentForms-Markup s. u.) · disabled/readonly
   (grey-light) · active/open: n/a (nativ nicht adressierbar, Spec §Fallen).
   Breakpoints: n/a — die Sets haben keine Size-Achse, EINE Größe auf allen Viewports.
   Checkbox/Radio/Range/File sind nicht Teil der Figma-Sets → der :where()-Wächter lässt sie aus. */
input:where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="button"], [type="submit"], [type="reset"], [type="image"], [type="hidden"])),
textarea,
select {
	box-sizing: border-box;
	margin: 0;
	border: 0;
	border-bottom: 4px solid var(--wp--preset--color--foreground);
	border-radius: 0;
	background-color: transparent;
	padding: 13px 0 9px; /* 13 + lh22 + 9 + 4 Unterkante = 48 border-box (Spec §Soll-Maße) */
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
	line-height: 22px;
	letter-spacing: 0.16px;
	color: var(--wp--preset--color--foreground);
	transition: border-color 0.2s ease, color 0.2s ease;
}
input:where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="button"], [type="submit"], [type="reset"], [type="image"], [type="hidden"])) {
	height: 48px;
}
/* Placeholder ist ink, nicht grau (gesampelt #1A1A1A); opacity gegen Firefox-Dimmen. */
input::placeholder,
textarea::placeholder {
	color: var(--wp--preset--color--foreground);
	opacity: 1;
}
input:hover:not(:disabled, [readonly]),
textarea:hover:not(:disabled, [readonly]),
select:hover:not(:disabled) {
	border-bottom-color: var(--wp--custom--color--violet-dark);
}
/* Fokus = Figma „Selected" (Caret + primary-Unterkante). Der UA-Ring weicht bewusst:
   die Unterkante ist der Indikator (Spec §Fallen — die „Focused"-Variante rendert ohne Ring). */
input:focus:not([readonly]),
textarea:focus:not([readonly]) {
	outline: 0;
	border-bottom-color: var(--wp--preset--color--primary);
}
/* Select: eigener Pfeil (arrow-down-s-line 18×18 rechtsbündig), Text 16/700.
   fill-Hex in den data-URIs = Token-Werte (foreground/violet-dark/grey-mid), dort nicht
   per var() referenzierbar — jede Farbe am Referenz-PNG gesampelt (Spec §Zustandsfarben). */
select:not([multiple]) {
	height: 48px;
	appearance: none;
	-webkit-appearance: none;
	font-weight: 700;
	padding-right: 26px; /* Arrow 18 + Gap 8 (Spec §Soll-Maße) */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%231A1A1A' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right center;
	background-size: 18px 18px;
	cursor: pointer;
}
select:not([multiple]):hover:not(:disabled) {
	color: var(--wp--custom--color--violet-dark);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%236842DB' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
}
select:focus-visible {
	outline: 4px solid var(--wp--preset--color--foreground); /* Ring außen wie Button-Basis (#169) */
	outline-offset: 0;
}
/* Fehlerzustand: aria-invalid ist der Standard-Haken (FluentForms setzt ihn selbst);
   .woocommerce-invalid ist Woos Checkout-Markup (Klasse sitzt auf der Feld-Zeile). */
input[aria-invalid="true"],
textarea[aria-invalid="true"],
select[aria-invalid="true"],
.woocommerce-invalid :where(input, textarea, select) {
	border-bottom-color: var(--wp--custom--color--red-500);
}
/* Alert-Icon (Figma alert-2-line, 24×24 rechtsbündig, fill = red-500 gesampelt) nur auf
   Texteingaben — Selects behalten ihren Pfeil. */
input[aria-invalid="true"]:where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="button"], [type="submit"], [type="reset"], [type="image"], [type="hidden"])),
textarea[aria-invalid="true"] {
	padding-right: 24px; /* Textreserve = Icon-Breite (Spec §Soll-Maße) */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23FE4141' d='M15.936 2.5L21.5 8.067V15.937L15.936 21.5H8.066L2.5 15.936V8.066L8.066 2.5H15.936ZM15.107 4.5H8.894L4.501 8.895V15.108L8.894 19.502H15.107L19.501 15.108V8.894L15.107 4.501V4.5ZM11 15H13V17H11V15ZM11 7H13V13H11V7Z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right center;
	background-size: 24px 24px;
}
/* Disabled schlägt Error (ein gesperrtes Feld meldet nichts); readonly behält Ink-Text. */
input:disabled,
input[readonly],
textarea:disabled,
textarea[readonly],
select:disabled {
	border-bottom-color: var(--wp--preset--color--grey-light);
}
input:disabled,
textarea:disabled,
select:disabled {
	color: var(--wp--preset--color--grey-mid);
	cursor: default;
	opacity: 1; /* Chromium dimmt disabled Selects per UA-opacity .7 — grey-light/grey-mid SIND schon der gedimmte Look */
}
input:disabled::placeholder,
textarea:disabled::placeholder {
	color: var(--wp--preset--color--grey-mid);
}
select:not([multiple]):disabled {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23C2C2C2' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
}
/* Woo block checkout select (#314): Woo's `background: none` SHORTHAND (0,2,0 in
   wc-block-library-style.css) beats the base rule above (0,1,1) but loses to the hover rule
   (0,3,1), which only swaps background-image — repeat/position/size then fall back to the UA
   defaults (`repeat`/`auto`) and the arrow tiles across the field. Pin the full background
   longhand at (0,2,1) so exactly one theme arrow (Figma arrow-down-s-line 18px, spec
   form-controls.md) renders in every state; the generic hover/disabled rules above keep
   swapping only the fill color. Woo's own 24px `__expand` chevron (absolute, right 12) is
   redundant then and gets hidden; the arrow takes its slot (box has 9px side padding, unlike
   the padding-less base fields). Box look (border, floating label) stays Woo — consistent
   with the neighboring checkout text inputs. */
.wc-blocks-components-select select.wc-blocks-components-select__select {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%231A1A1A' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	background-size: 18px 18px;
	padding-right: 38px; /* arrow 18 + edge 12 + gap 8 (form-controls.md text reserve) */
}
.wc-blocks-components-select select.wc-blocks-components-select__select:focus {
	padding-right: 38px; /* Woo's :focus rule (0,3,0) resets its 16px 8.5px 0 shorthand */
}
.wc-blocks-components-select select.wc-blocks-components-select__select:disabled {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23C2C2C2' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
}
.wc-blocks-components-select .wc-blocks-components-select__expand {
	display: none;
}
/* Feld-Label: 12/500 grey, sitzt bündig auf der Feld-Oberkante (Gap 0). Nur Typo — Layout
   (display, Abstände) gehört dem jeweiligen Formular. Hover-Label #343232 aus dem Dropdown-Set
   ist keine Token-Farbe → ausgelassen (Spec §Fallen, der Designerin gemeldet). */
label {
	font-size: var(--wp--custom--font-size--12);
	font-weight: 500;
	line-height: 16px;
	letter-spacing: 0.12px;
	color: var(--wp--preset--color--grey);
}
/* Hint- und Fehlertext unterm Feld: 12/500 grey, 8px Abstand — auch der FEHLERtext ist laut
   Set grau (Fehler spricht über Unterkante + Icon), .ff-el-is-error .error ist FluentForms'
   eigenes Fehlertext-Element (sonst Plugin-rot). */
.zo-field-hint,
.zo-field-error,
.ff-el-is-error .error {
	display: block;
	margin: 8px 0 0;
	font-size: var(--wp--custom--font-size--12);
	font-weight: 500;
	line-height: 16px;
	letter-spacing: 0.12px;
	color: var(--wp--preset--color--grey);
}

/* Top-Level-Regionen bündig: theme.json setzt blockGap 24 → WP legt einen 24px-Vertikal-Margin
   ZWISCHEN Header, main und Footer; in diesem Gap scheint der weiße Root-BG als Naht durch (#99,
   Philipp-Review). Vertikal-Margin der drei Regionen auf 0 → Weiß(Header) → Papier → Weiß(Footer)
   ohne Naht. Root-BG bleibt weiß (Header/Footer). */
.wp-site-blocks > * {
	margin-block: 0;
}
.wp-site-blocks > main {
	/* Content-Bereich in Papier (#99, Designerin); Header + Footer bleiben weiß (eigener BG,
	   liegen außerhalb von <main>). Sektionen mit eigenem BG/Karten sitzen darauf. */
	background-color: var(--wp--preset--color--paper);
}

/* Print without backgrounds (#369): no page, section, card or flag fill on paper, even
   when the browser's "print backgrounds" option is on (the paper grey used to cover every
   page). Elements only — ::before/::after keep their fill because icons and list bullets
   are painted as mask + background-color there. !important: component rules and inline
   block styles out-specify any element selector; WP preset classes
   (.has-*-background-color, 0-1-0) even carry !important — `body [class]` (0-1-1) beats them. */
@media print {
	body, body *, body [class] { background-color: transparent !important; background-image: none !important; }
	/* Light text presets only ever sit on a dark fill — with the fill gone they turn ink.
	   !important + body prefix: the preset classes carry !important (0-1-0) themselves. */
	body .has-white-color, body .has-paper-color, body .has-grey-light-color { color: var(--wp--preset--color--foreground) !important; }
}

/* ===================================================================== *
 *  COMPONENTS — wiederverwendbare Bausteine (Header, Nav, Footer, Karten, Flags, Buttons, Teaser, Listen, Icons)
 * ===================================================================== */

/* Sanfte Übergänge */
.wp-element-button,
.zo-section .wp-block-column > .wp-block-group,
a {
	transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

/* Karten: weiße Karten bekommen Tiefe + Haarlinie; Bild läuft bündig in den Radius */
.zo-section .wp-block-column > .wp-block-group.has-white-background-color {
	box-shadow: var(--wp--preset--shadow--card);
	border: var(--wp--custom--border--hairline) solid var(--wp--preset--color--grey-light);
	overflow: hidden;
}

/* Hover-Lift für alle Karten mit Hintergrund (Themen, Kurse, Termine, Zielgruppen) */
.zo-section .wp-block-column > .wp-block-group.has-background:hover {
	transform: translateY(-4px);
	box-shadow: var(--wp--preset--shadow--card-hover);
}

/* Artikel-/Experten-Karten ohne Flächen-BG: Bild leicht anheben beim Hover */
.zo-section .wp-block-column:hover > .wp-block-group:not(.has-background) > .wp-block-group:first-child {
	box-shadow: var(--wp--preset--shadow--card-hover);
}

/* Button-Hover: dezent skaliert statt nur Farbe */
.wp-element-button:hover {
	transform: translateY(-1px);
}

/* Navigation: aktive/hover-Links in Primärfarbe */
.wp-block-navigation a:hover {
	color: var(--wp--preset--color--primary);
}

/* ============================================================
   Component: Section-Heading  (.zo-section-heading)  — Issue #152
   Die EINE Skala der Sektions-Überschriften. Quelle: Figma Component-Set „Heading"
   4926:24144, Type=H2 (Abruf 2026-08-06, 36 Varianten ausgelesen):
       SM  <640   20 / 26        MD  ≥640   24 / 32        LG+ ≥1024   40 / 52
   durchgängig weight 700, letterSpacing 0, GT Haptik, foreground.
   Konsumenten: jede Sektions-H2 trägt `.zo-section-heading` zusätzlich zu ihrer
   Komponenten-Klasse (expert-/testimonial-/author-carousel, faq, einstiegskurs,
   pdp-section). Die Komponenten-Klasse regelt danach nur noch ihren Abstand nach unten —
   die Typo steht hier, genau einmal.
   WARUM @media UND NICHT @container: Die Stufung ist in Figma eine Viewport-Variante
   (Achse `Viewport = SM | MD | LG+`), keine Container-Eigenschaft. Dieselbe Komponente
   steht auf der PDP in der Rail (Container = Viewport − 2×Rand → 960 bei Viewport 1024)
   und auf anderen Seiten full-width (Container ≈ Viewport). EINE Container-Schwelle kann
   nur einen der beiden Fälle treffen — belegt: vor #152 sprang die 40er-Stufe auf der PDP
   erst bei Viewport 1088 statt 1024. Der Karten-/Spalten-Reflow bleibt Container-Query,
   der Type-Scale wird Viewport-Query.
   States: n/a (nicht interaktiv). Breakpoints: 640 / 1024 (Viewport).
   ============================================================ */
.zo-section-heading {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--20);
	line-height: 26px;
	font-weight: 700;
	letter-spacing: 0;                 /* Figma H2: ls 0 — schlägt die globale heading-Regel (0.01em) */
	color: var(--wp--preset--color--foreground);
}
@media (min-width: 640px) {
	.zo-section-heading { font-size: var(--wp--custom--font-size--24); line-height: 32px; }
}
@media (min-width: 1024px) {
	.zo-section-heading { font-size: var(--wp--custom--font-size--40); line-height: 52px; }
}

/* Section intro (#396): short description below a section H2 - the typo of the optional
   heads of content-list (#279 pattern), product-grid (#279) and card-carousel (#396),
   extracted on its third use. Values unchanged from .zo-content-list__intro:
   small 500 20/0.01em, medium 22 from 1024 (viewport stage like .zo-section-heading).
   The component class keeps only its spacing. */
.zo-section-intro {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 20px;
	letter-spacing: 0.01em;
	color: var(--wp--preset--color--foreground);
}
@media (min-width: 1024px) {
	.zo-section-intro { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
}

/* ============================================================
   Component: Main-Menu  (.zo-mainnav)  — Issue #92
   Figma 5512:16659 (Bar/4 Viewports) · 5512:20334 (States/Badges) ·
   5516:30835 (Mega) · 5690:8374 (Mobile-Drawer). Spec: docs/figma-specs/
   main-menu-topbar.md + main-menu-mega-mobile.md. Abruf 2026-07-30.
   States: :hover/:focus-visible/active · Badge leer|Zahl|Häkchen.
   Breakpoints: XL >=1280 · LG <=1279 · MD <=1023 (Nav->Burger, #333) · SM <=479.
   ============================================================ */
/* Header trägt keine Global-Padding — die Bar setzt ihren Inset selbst (56/32/24/16).
   padding-block:0 killt zusätzlich WPs Default `.wp-block-group.has-background{padding:1.25em}`
   → sonst 25px weißer Streifen über/unter der Nav (#99, Philipp-Review „weiße Abstände unter Nav").
   Height = spacer: the nav is fixed (out of flow, #328) — the header keeps its slot in the page. */
.site-header { padding: 0; height: calc(80px + var(--wp--custom--border--hairline)); }
@media (max-width: 1023px) { .site-header { height: calc(64px + var(--wp--custom--border--hairline)); } }

/* Pinned reveal/hide header (#328, node 5690-8363): fixed at the viewport top so it can come
   back on upscroll mid-page. Was position:sticky inside the short <header> — it could only
   stick within those 80px and scrolled away, so the reveal never showed mid-page (#92 note). */
.zo-mainnav {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 100;
	background: var(--wp--preset--color--white);
	border-bottom: var(--wp--custom--border--hairline) solid var(--wp--preset--color--grey-light);
	transition: transform 0.3s ease;
}
.zo-mainnav.is-hidden { transform: translateY(-100%); }
/* Logged-in views: sit below the WP admin bar instead of underneath it. */
body.admin-bar .zo-mainnav { top: 32px; }
@media (max-width: 782px) { body.admin-bar .zo-mainnav { top: 46px; } }

.zo-mainnav__bar {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	width: var(--zo-rail-w);          /* Rail = Grid-Alias (#128): Cap 1328, Rand 16/24/32, ab 1440 zentriert */
	margin-inline: auto;
	height: 80px;
}

/* Logo-Lockup */
.zo-mainnav__logo {
	display: inline-flex;
	align-items: center;
	gap: 17px;
	flex: 0 0 auto;
	text-decoration: none;
}
.zo-mainnav__mark { width: 36px; height: 36px; flex: 0 0 auto; display: block; }
.zo-mainnav__mark path:first-child { fill: var(--wp--preset--color--primary); }
.zo-mainnav__mark path:last-child { fill: var(--wp--preset--color--foreground); }
.zo-mainnav__wordmark {
	font-weight: 700;
	font-size: 1.425rem;
	line-height: 1;
	white-space: nowrap;
}
.zo-mainnav__wordmark-a { color: var(--wp--preset--color--foreground); }
.zo-mainnav__wordmark-b { color: var(--wp--preset--color--primary); }

/* Textnav: zentriert im Restraum zwischen Logo und Icon-Gruppe */
.zo-mainnav__textnav { flex: 1 1 auto; align-self: stretch; display: flex; justify-content: center; min-width: 0; }
.zo-mainnav__menu {
	display: flex;
	align-items: stretch; /* items span the full bar height so the panel docks at the header line (#332) */
	gap: 32px;
	list-style: none;
	margin: 0;
	padding: 0;
}
.zo-mainnav__item { position: relative; }
/* Desktop only (drawer keeps its block layout): full-height item = hover path down
   to the panel never leaves the item, and top:100% on .zo-mega = header bottom (#332). */
.zo-mainnav__textnav .zo-mainnav__item { display: flex; align-items: center; }
.zo-mainnav__link {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--10); /* 4 — Label↔Chevron (Frame 5512:16659) */
	padding-block: var(--wp--preset--spacing--20); /* 8 oben/unten (Frame 5512:16659) */
	font-size: var(--wp--custom--font-size--18);
	font-weight: 700;
	line-height: 1.4;
	color: var(--wp--preset--color--foreground);
	text-decoration: none;
	white-space: nowrap;
}
.zo-mainnav__link:hover,
.zo-mainnav__item:focus-within > .zo-mainnav__link { color: var(--wp--preset--color--primary); }
.zo-mainnav__chev { display: inline-flex; line-height: 0; }
.zo-mainnav__chev svg { width: 20px; height: 20px; }
/* Bar-Nav zeigt keinen Chevron (Figma 5512:16659) — nur der Drawer klappt auf. */
.zo-mainnav__textnav .zo-mainnav__chev { display: none; }

/* Icon-Gruppe */
.zo-mainnav__icons { display: flex; align-items: center; gap: 32px; flex: 0 0 auto; }
.zo-mainnav__iconbtn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	color: var(--wp--preset--color--foreground);
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
	text-decoration: none;
}
.zo-mainnav__iconbtn:hover,
.zo-mainnav__iconbtn:focus-visible { color: var(--wp--preset--color--primary); }
.zo-mainnav__ico { line-height: 0; }
.zo-mainnav__ico svg { display: block; width: 24px; height: 24px; }
.zo-mainnav__badge {
	position: absolute;
	top: 2px;
	right: 2px;
	box-sizing: border-box;
	min-width: 14px;
	height: 14px;
	padding: 0 2px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--custom--font-size--12);
	font-weight: 700;
	line-height: 1;
	border-radius: 4px;
}
.zo-mainnav__badge--check svg { width: 10px; height: 10px; }

.zo-mainnav__burger,
.zo-mainnav__close,
.zo-mainnav__drawer { display: none; }

/* Mega-Panel — belegte Werte aus Spec main-menu-mega-mobile.md (5516:30835).
   Item-States belegt via Frame 5516:26841 (Hover #6842DB · Pressed #8359FF · Focus-Ring).
   Panel-BG paper (#F4F4F4), Flag schwarz (#1A1A1A). */
.zo-mega {
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translateX(-50%); /* flush with the header line: item is bar-height, no offset (5551:3112, #332) */
	background: var(--wp--preset--color--paper);
	box-shadow: var(--wp--preset--shadow--card);
	padding: var(--wp--preset--spacing--40);
	opacity: 0;
	visibility: hidden;
	/* Close-Delay (Hover-Intent): schliesst erst nach 0.2s, oeffnet sofort (#92). */
	transition: opacity 0.15s ease 0.2s, visibility 0s linear 0.35s;
	z-index: 90;
}
/* The former 8px hover bridge (.zo-mega::before, #92) is obsolete: the panel now
   touches the full-height item, so there is no gap to cross (#332). */
/* Verbindungs-Dreieck (Node 5516:30921): 34x22, paper, Spitze nach oben,
   zeigt auf den aktiven Hauptmenuepunkt (folgt der Panel-Zentrierung). */
.zo-mega::after {
	content: '';
	position: absolute;
	top: -16px;
	left: 50%;
	transform: translateX(-50%);
	width: 0;
	height: 0;
	border-left: 17px solid transparent;
	border-right: 17px solid transparent;
	border-bottom: 22px solid var(--wp--preset--color--paper);
}
.zo-mainnav__item.has-mega:hover > .zo-mega,
.zo-mainnav__item.has-mega:focus-within > .zo-mega {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.15s ease 0s, visibility 0s linear 0s;
}
.zo-mega__list,
.zo-mega__group-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.zo-mega__list { grid-template-columns: 309px; } /* 1-Spalte (Frame 5516:30835) */
.mega-cols-2 .zo-mega__list { grid-template-columns: 317px 317px; column-gap: var(--wp--preset--spacing--40); } /* 2-Spalten je 317 (Frame 5516:32481) */
.mega-cols-3 .zo-mega__list { grid-template-columns: repeat(3, 309px); column-gap: var(--wp--preset--spacing--40); } /* 3-Spalten je 309, Gap 24 (Frames 5516:34008 + 5551:5572, #182) */
/* Topicline 12/700 ink, Höhe 16, Gap 0 zu den Items (Frames 5516:30835 + 5551:5572; #92-Abweichung in #182 korrigiert) */
.zo-mega__group-title {
	display: block;
	font-size: 0.75rem;
	font-weight: 700;
	line-height: 1.333;
	color: var(--wp--preset--color--foreground);
	margin-bottom: 0;
}
/* Item height is content-driven (#282): 12 + title 20 + [4 + desc n*16] + 12
   → 2-line desc 80 (Frame 5516:30835), 1-line 64, no desc 44 (Frame 5516:34008). */
.zo-mega__link {
	display: grid;
	grid-template-columns: 16px 1fr;
	column-gap: var(--wp--preset--spacing--20);
	align-items: start;
	padding: 12px var(--wp--preset--spacing--20); /* 12 vert / 8 horiz (Frame 5516:32481) */
	text-decoration: none;
	color: var(--wp--preset--color--foreground);
}
.zo-mega__icon { line-height: 0; padding-top: 2px; }
.zo-mega__icon svg { width: 16px; height: 16px; } /* 16x16 in both render contexts: desktop textnav and mobile drawer (#286, Frame 5690:8374) */
.zo-mega__body { display: block; }
.zo-mega__title { font-size: 0.875rem; font-weight: 700; line-height: 1.4286; display: flex; align-items: center; gap: var(--wp--preset--spacing--20); } /* Höhe 20 (Frame 5516:30835) */
.zo-mega__desc { display: block; color: var(--wp--preset--color--grey); font-size: 0.75rem; font-weight: 500; line-height: 1.333; margin-top: 4px; } /* gap 4 above desc, 2 lines = 32 (Frame 5516:30835 itemSpacing) */
/* Item-States (Frame 5516:26841): Hover Titel violet-dark, Pressed Titel primary,
   Subline bleibt grau, kein BG. Focus nur Ring (Titel bleibt ink). */
.zo-mega__link:hover .zo-mega__title { color: var(--wp--custom--color--violet-dark); }
.zo-mega__link:active .zo-mega__title { color: var(--wp--preset--color--primary); }
.zo-mega__link:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: -2px; }
.zo-mega__flag {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--10); /* 4 (Frame 5516:32481) */
	background: var(--wp--preset--color--foreground);
	color: var(--wp--preset--color--white);
	font-size: 0.75rem;
	font-weight: 500; /* Frame 5516:32481 */
	line-height: 1.4;
	padding: 2px 6px; /* 2 vert (Frame 5516:32481) */
	white-space: nowrap;
}
.zo-mega__flag svg { fill: currentColor; }

/* LG (<=1279): kleinere Nav, Inset 32, Icon-Gap 12 */
@media (max-width: 1279px) {
	/* Bar-Breite via kanonischer Rail (#99) — kein eigener Cap mehr. */
	.zo-mainnav__link { font-size: var(--wp--preset--font-size--medium); }
	.zo-mainnav__menu { gap: 24px; }
	.zo-mainnav__logo { gap: 14px; }
	.zo-mainnav__wordmark { font-size: 1.172rem; }
	.zo-mainnav__mark { width: 30px; height: 30px; }
	.zo-mainnav__icons { gap: 12px; }
}

/* MD (<=1023): Textnav -> Burger, Bar 64, Inset 24/12. Threshold was 781 — at ~800px
   the text menu overlapped the logo; Figma has no textnav variant below LG/1024 (#333). */
@media (max-width: 1023px) {
	/* Burger-Layout: full-bleed mit asymmetrischem Inset (Logo links / Burger rechts eng) — nicht die Rail. */
	.zo-mainnav__bar { width: 100%; height: 64px; padding-left: 24px; padding-right: 12px; justify-content: space-between; }
	.zo-mainnav__textnav { display: none; }
	.zo-mainnav__logo { gap: 15px; }
	.zo-mainnav__wordmark { font-size: 1.25rem; }
	.zo-mainnav__mark { width: 32px; height: 32px; }
	.zo-mainnav__icons { gap: 12px; }
	.zo-mainnav__burger { display: inline-flex; }

	/* Mobile-Drawer */
	.zo-mainnav__drawer {
		display: block;
		position: fixed;
		inset: 0;
		z-index: 200;
		background: var(--wp--preset--color--white);
		overflow-y: auto;
	}
	.zo-mainnav__drawer[hidden] { display: none; }
	.zo-mainnav__drawer-head {
		box-sizing: border-box;
		display: flex;
		align-items: center;
		justify-content: space-between;
		height: 64px;
		padding-inline: 24px;
		border-bottom: var(--wp--custom--border--hairline) solid var(--wp--preset--color--grey-light);
	}
	.zo-mainnav__close { display: inline-flex; }
	.zo-mainnav__drawer-body .zo-mainnav__menu { display: block; }
	.zo-mainnav__drawer-body .zo-mainnav__item { border-bottom: var(--wp--custom--border--hairline) solid var(--wp--preset--color--grey-light); }
	.zo-mainnav__drawer-body .zo-mainnav__link {
		justify-content: space-between;
		width: 100%;
		box-sizing: border-box;
		padding: 23px 24px; /* row height 72 = 23 + 26 + 23 (Frame 5690:8374) */
		font-size: var(--wp--custom--font-size--18);
		line-height: 1.4445; /* 26px at 18px */
	}
	/* Open accordion row: paper BG, primary text + chevron, chevron flips up (Frame 5690:8374) */
	.zo-mainnav__drawer-body .zo-mainnav__item.is-open > .zo-mainnav__link {
		background: var(--wp--preset--color--paper);
		color: var(--wp--preset--color--primary);
	}
	.zo-mainnav__drawer-body .zo-mainnav__item.is-open > .zo-mainnav__link .zo-mainnav__chev svg { transform: rotate(180deg); }
	.zo-mainnav__drawer-body .zo-mega {
		position: static;
		transform: none;
		opacity: 1;
		visibility: visible;
		border: 0;
		box-shadow: none;
		display: none;
		background: var(--wp--preset--color--paper); /* #F4F4F4 like the open row, not grey-light (Frame 5690:8374) */
		padding-top: 0; /* topicline starts flush below the open row, bottom keeps 24 (Frame 5690:8374, re-sync 2026-09-16) */
	}
	/* Mobile drawer: topicline gap 12; description wraps, no truncation (Frame 5690:8374 textAutoResize HEIGHT, #357) */
	.zo-mainnav__drawer-body .zo-mega__group-title { margin-bottom: 12px; }
	.zo-mainnav__drawer-body .zo-mega::before,
	.zo-mainnav__drawer-body .zo-mega::after { content: none; }
	.zo-mainnav__drawer-body .zo-mainnav__item.is-open > .zo-mega { display: block; }
	/* Every panel is one full-width column in the drawer, incl. the 1-col desktop track 309px (#357) */
	.zo-mainnav__drawer-body .zo-mega__list { grid-template-columns: minmax(0, 1fr); }
	html.zo-drawer-lock { overflow: hidden; }
}

/* SM (<=479): Inset 16/4, Icon-Gap 0, Wortmarke umbricht (Figma: 3 Zeilen ~54px) */
@media (max-width: 479px) {
	.zo-mainnav__bar { padding-left: 16px; padding-right: 4px; }
	.zo-mainnav__drawer-head { padding-left: 16px; padding-right: 4px; }
	/* SM drawer inset 16 for rows and open panel, matching the head (Frame 5690:8374) */
	.zo-mainnav__drawer-body .zo-mainnav__link { padding-left: 16px; padding-right: 16px; }
	.zo-mainnav__drawer-body .zo-mega { padding-left: 16px; padding-right: 16px; }
	.zo-mainnav__icons { gap: 0; }
	.zo-mainnav__logo { gap: 10px; }
	.zo-mainnav__mark { width: 35px; height: 35px; }
	.zo-mainnav__wordmark {
		white-space: normal;
		max-width: 56px;
		font-size: 0.8125rem;
		line-height: 1.15;
		overflow-wrap: anywhere;
	}
}

.zo-logo-mark {
	width: 2rem;
	height: 2rem;
	flex: 0 0 auto;
	display: block;
}

.zo-logo-mark__a {
	fill: var(--wp--preset--color--primary);
}

.zo-logo-mark__b {
	fill: var(--wp--preset--color--foreground);
}

/* ------------------------------------------------------------------ *
 *  Footer (#93) — Node 5641:32270 · Spec docs/figma-specs/footer.md
 *  Newsletter (visuell) · Logo · 3 Link-Spalten (Menü) · Kontakt · Legal.
 *  States: :hover/:focus-visible · Accordion (SM) aria-expanded · disabled n/a.
 *  Breakpoints (Container-Query am .zo-footer): SM <640 / LG ≥640 / MD ≥1024 / XL ≥1440.
 * ------------------------------------------------------------------ */
.zo-footer {
	container-type: inline-size;
	/* Content→Footer = Modul-Abstand (#174, module-gap.md). Die Lücke zeigt den
	   Seitenhintergrund (global paper, theme.json) — der EINE Mechanismus auf allen Seiten. */
	margin-block-start: var(--zo-module-gap);
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--foreground);
}
.zo-footer *,
.zo-footer *::before,
.zo-footer *::after { box-sizing: border-box; }

.zo-footer__nl-inner,
.zo-footer__body-inner {
	width: var(--zo-rail-w);          /* Rail = Grid-Alias (#128): Cap 1328, Rand 16/24/32, ab 1440 zentriert */
	margin-inline: auto;
}

/* --- Newsletter (BG lilac) --- */
.zo-footer__newsletter { background: var(--wp--preset--color--accent-lilac); }
.zo-footer__nl-inner {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--40); /* 24 — Intro→Form (SM stacked) */
	padding-block: var(--wp--preset--spacing--60); /* 40 SM */
}
.zo-footer__nl-intro { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--20); } /* 8 SM */
.zo-footer__nl-title {
	margin: 0;
	font-family: var(--wp--preset--font-family--display, inherit);
	font-size: var(--wp--custom--font-size--24);
	font-weight: 700;
	line-height: 1.3;
	color: var(--wp--preset--color--foreground);
}
.zo-footer__nl-sub {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 1.4;
	color: var(--wp--preset--color--foreground);
}
.zo-footer__nl-form { display: flex; flex-direction: column; gap: 16px; } /* SM/LG button→consent 16 */
.zo-footer__nl-row { display: flex; flex-direction: column; gap: 16px; margin: 0; } /* SM input→button 16; das FF-Fieldset bringt beides aus INTEGRATIONS §FluentForms mit */
.zo-footer__field,
.zo-footer .zo-footer__nl-form .ff-el-group { flex: 1 1 auto; }
/* Field look (4px underline, h48, typography, states) comes from the form-controls base
   (#170, Figma "Input field" 5551:21846). The footer's former 2px deviation (footer.md)
   was dropped per #337 — input fields follow the one component everywhere. */
.zo-footer__input,
.zo-footer .zo-footer__nl-form .ff-el-form-control { width: 100%; }
/* Knopf: Maße/Farben kommen aus .zo-btn--md (COMPONENTS, Figma 4510:32604 — deckungsgleich
   mit footer.md: h48, 14/500 weiß auf primary, scharfkantig). Eigen bleibt hier die Breite
   und der Hover-/Fokus-Ton: der Newsletter-Knopf folgt dem Action-Hover der Fußzeile
   (violet-link, wie die Social-Kreise daneben) statt dem Button-Hover (violet-dark) —
   footer.md nennt keinen Hover-Zustand, die Abweichung ist Bestand, kein Beleg (#214). */
.zo-footer__nl-btn,
.zo-footer .zo-footer__nl-form .ff-btn-submit { width: 100%; } /* SM full */
.zo-footer__nl-btn:hover,
.zo-footer .zo-footer__nl-form .ff-btn-submit:hover { background: var(--zo-action-hover); }
.zo-footer__nl-btn:focus-visible,
.zo-footer .zo-footer__nl-form .ff-btn-submit:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }
.zo-footer__consent {
	margin: 0;
	font-size: var(--wp--custom--font-size--12);
	font-weight: 500;
	line-height: 1.35;
	color: var(--wp--preset--color--grey);
}
.zo-footer__consent a { color: inherit; text-decoration: underline; }

/* FluentForms embed (#184): only layout stays footer-specific — label visually hidden,
   field and button side by side. Field look follows the form-controls base since #337;
   group gaps, success text and button come from the central layer (#214). */
.zo-footer .zo-footer__nl-form .ff_submit_btn_wrapper { flex: 0 0 auto; }
/* Label nur für Screenreader — sichtbares Design ist der Placeholder (Figma). */
.zo-footer .zo-footer__nl-form .ff-el-input--label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* Bestätigung nach Absenden sitzt bündig im Formular-Slot (zentral: 24px Abstand). */
.zo-footer .ff-message-success { margin: 0; }

/* --- Body (BG white) --- */
.zo-footer__body-inner {
	padding-block: var(--wp--preset--spacing--70) var(--wp--preset--spacing--40); /* 48 top SM / 24 bottom */
	display: flex;
	flex-direction: column;
}
.zo-footer__logo {
	display: inline-flex;
	align-items: flex-start; /* wordmark sits above centre in Figma — offset via margin-top */
	gap: 21px; /* Figma Logo 5641:30893: wordmark x 66 − mark 45 */
	text-decoration: none;
	color: var(--wp--preset--color--foreground);
	margin-bottom: var(--wp--preset--spacing--60); /* 40 logo→cols */
}
.zo-footer__mark { width: 45px; height: 45px; flex: none; } /* SM */
.zo-footer__mark path:first-child { fill: var(--wp--preset--color--primary); }
.zo-footer__mark path:last-child { fill: var(--wp--preset--color--foreground); }
.zo-footer__wordmark { width: 222px; height: auto; flex: none; margin-top: 10px; } /* SM — Figma vector 222×20 @ y10 (#356) */
.zo-footer__wordmark-a { fill: var(--wp--preset--color--foreground); }
.zo-footer__wordmark-b { fill: var(--wp--preset--color--primary); }

/* Spalten */
.zo-footer__cols { display: flex; flex-direction: column; }
.zo-footer__col { display: flex; flex-direction: column; }
.zo-footer__col-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
	text-align: left;
	color: var(--wp--preset--color--foreground);
}
.zo-footer__col-title { font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 1.43; }
.zo-footer__col-plus { display: inline-flex; color: var(--wp--preset--color--primary); }
.zo-footer__col-panel { overflow: hidden; }
.zo-footer__menu {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 12px; /* 32 stride − 20 line */
}
.zo-footer__menu li { margin: 0; line-height: 20px; }
.zo-footer__menu a {
	display: block;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 20px;
	color: var(--wp--preset--color--foreground);
	text-decoration: underline;
	text-underline-offset: 2px;
}
.zo-footer__menu a:hover { color: var(--wp--preset--color--primary); }

/* SM: Spalten sind Accordion (kollabiert), Haarlinie je Item, Panel zu */
@container (max-width: 639.98px) {
	.zo-footer__col { border-top: 1px solid var(--wp--preset--color--grey-light); }
	.zo-footer__col-head { min-height: 79px; } /* item h80 = 1 hairline + 79 head (Figma 6770:97744, #349) */
	.zo-footer__col-panel { display: none; padding-bottom: var(--wp--preset--spacing--40); }
	.zo-footer__col-head[aria-expanded="true"] + .zo-footer__col-panel { display: block; }
	.zo-footer__col-plus { transition: transform 0.15s ease; }
	.zo-footer__col-head[aria-expanded="true"] .zo-footer__col-plus { transform: rotate(45deg); }
	/* Contact is no accordion; its inherited top hairline closes the accordion list
	   below the last item (Figma 6770:97744: every item has a bottom stroke, #349) */
	.zo-footer__col--contact { padding-top: var(--wp--preset--spacing--60); }
	.zo-footer__col--contact .zo-footer__col-plus { display: none; }
}

/* Kontakt-Spalte */
.zo-footer__col--contact { gap: var(--wp--preset--spacing--40); } /* 24 heading→info & info→social (SM/LG) */
.zo-footer__contact { display: flex; flex-direction: column; gap: 12px; }
.zo-footer__contact-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	line-height: 1.43;
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}
.zo-footer__contact-link:hover { text-decoration: underline; }
.zo-footer__contact-icon { display: inline-flex; flex: none; }
.zo-footer__contact-icon .zo-icon { width: 16px; height: 16px; }
.zo-footer__social { display: flex; gap: 12px; }
.zo-footer__social-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border-radius: 50%; /* bewusste Ausnahme (wie Avatare), sonst Marke scharfkantig */
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--white);
}
.zo-footer__social-btn:hover { background: var(--zo-action-hover); }
.zo-footer__social-btn:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }
.zo-footer__social-ico .zo-icon { width: 18px; height: 18px; }

/* Legal-Zeile */
.zo-footer__legal {
	margin-top: var(--wp--preset--spacing--60); /* 40 cols→sep */
	padding-top: var(--wp--preset--spacing--40); /* 24 sep→links (SM/LG) */
	border-top: 1px solid var(--wp--preset--color--grey-light);
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--50); /* 32 links→copyright (SM) */
}
.zo-footer__legal-menu {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 24px;
}
.zo-footer__legal-menu li { margin: 0; line-height: 20px; }
.zo-footer__legal-menu a {
	display: block;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 20px;
	color: var(--wp--preset--color--foreground);
	text-decoration: underline;
	text-underline-offset: 2px;
}
.zo-footer__legal-menu a:hover { color: var(--wp--preset--color--primary); }
.zo-footer__copyright {
	margin: 0;
	font-size: var(--wp--preset--font-size--small); /* SM */
	font-weight: 500;
	line-height: 1.43;
	color: var(--wp--preset--color--grey);
}

/* --- LG ≥640 --- */
@container (min-width: 640px) {
	.zo-footer__nl-inner {
		flex-direction: row;
		align-items: flex-start;
		gap: var(--wp--preset--spacing--50); /* 32 — Intro | Form (Figma 640) */
		padding-block: var(--wp--preset--spacing--40); /* 24 */
	}
	.zo-footer__nl-intro { flex: 0 0 246px; gap: var(--wp--preset--spacing--30); } /* 16 */
	.zo-footer__nl-form { flex: 0 0 314px; gap: var(--wp--preset--spacing--30); } /* 16 button→consent, Figma 640 */
	.zo-footer__nl-row,
	.zo-footer .zo-footer__nl-form .frm-fluent-form fieldset { gap: 12px; } /* LG input→button 12 */
	.zo-footer__nl-btn,
	.zo-footer .zo-footer__nl-form .ff-btn-submit { width: auto; align-self: flex-start; } /* auto-Breite links */

	.zo-footer__body-inner { padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40); } /* 32 top / 24 bottom (top via mark below) */
	.zo-footer__mark { width: 62px; height: 62px; }
	.zo-footer__wordmark { width: 308px; margin-top: 14px; } /* Figma 5641:30430: 308×28 @ y14 */
	.zo-footer__logo { gap: 30px; margin-bottom: var(--wp--preset--spacing--50); } /* 30 mark→wordmark (x 92 − 62) · 32 */

	/* 3 Link-Spalten in einer Reihe; Kontakt fällt in eigene Zeile darunter */
	.zo-footer__cols { flex-direction: row; flex-wrap: wrap; column-gap: 40px; row-gap: var(--wp--preset--spacing--50); }
	.zo-footer__col { flex: 1 1 0; border-top: 0; } /* 3 Link-Spalten füllen die Reihe; Kontakt wrappt (100%) */
	.zo-footer__col-head { min-height: 0; cursor: default; pointer-events: none; }
	.zo-footer__col-plus { display: none; }
	.zo-footer__col-panel { display: block; margin-top: var(--wp--preset--spacing--30); } /* 16 heading→list */
	.zo-footer__col--contact {
		flex: 1 1 100%;
		flex-direction: column;
		padding-top: 0;
	}
	/* Kontakt-Zeile: Info links, Social rechts */
	.zo-footer__col--contact { display: grid; grid-template-columns: auto auto; grid-auto-rows: min-content; column-gap: var(--wp--preset--spacing--70); align-items: center; }
	.zo-footer__col--contact .zo-footer__col-title { grid-column: 1 / -1; margin-bottom: var(--wp--preset--spacing--40); }
	.zo-footer__col--contact .zo-footer__contact { grid-column: 1; }
	.zo-footer__col--contact .zo-footer__social { grid-column: 2; }

	.zo-footer__legal { margin-top: var(--wp--preset--spacing--50); } /* 32 */
	.zo-footer__legal {
		flex-direction: row;
		flex-wrap: wrap;
		justify-content: space-between;
		align-items: baseline;
		gap: 16px 24px;
	}
	.zo-footer__legal-nav { flex: 1 1 auto; }
	.zo-footer__copyright { font-size: var(--wp--custom--font-size--12); text-align: right; }
}

/* --- MD ≥1024: 4 Spalten (inkl. Kontakt), Newsletter inline --- */
@container (min-width: 1024px) {
	.zo-footer__nl-inner { gap: 96px; padding-block: 48px; }
	.zo-footer__nl-intro { flex: 0 0 344px; gap: var(--wp--preset--spacing--30); }
	.zo-footer__nl-title { font-size: var(--wp--custom--font-size--32); }
	.zo-footer__nl-sub { font-size: var(--wp--preset--font-size--medium); }
	.zo-footer__nl-form { flex: 0 0 470px; gap: var(--wp--preset--spacing--40); } /* 24 */
	.zo-footer__nl-row,
	.zo-footer .zo-footer__nl-form .frm-fluent-form fieldset { flex-direction: row; align-items: center; gap: 12px; }
	.zo-footer__nl-btn,
	.zo-footer .zo-footer__nl-form .ff-btn-submit { flex: none; width: 132px; }

	.zo-footer__body-inner { padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--60); } /* 40/40 */
	.zo-footer__mark { width: 87px; height: 87px; }
	.zo-footer__wordmark { width: 432px; margin-top: 20px; } /* Figma 5641:30146: 432×39 @ y20 */
	.zo-footer__logo { gap: 41px; margin-bottom: var(--wp--preset--spacing--60); } /* 41 mark→wordmark (x 128 − 87) · 40 */

	.zo-footer__cols { flex-wrap: nowrap; column-gap: 40px; }
	.zo-footer__col { flex: 1 1 0; }
	.zo-footer__col--contact { display: flex; flex: 1 1 0; gap: 0; align-items: flex-start; }
	.zo-footer__col--contact .zo-footer__col-title { margin-bottom: var(--wp--preset--spacing--30); } /* 16 */
	.zo-footer__col--contact .zo-footer__contact { margin-bottom: var(--wp--preset--spacing--40); } /* 24 info→social */

	.zo-footer__legal { margin-top: var(--wp--preset--spacing--60); padding-top: var(--wp--preset--spacing--60); } /* 40/40 */
}

/* XL (≥1440): Inset via Rail (= Grid-Alias #128) — Content bleibt 1328 zentriert. */
/* Icon-Liste (Häkchen statt Bullet) */
.zo-icon-list { list-style: none; padding-left: 0; }

.zo-icon-list li { position: relative; padding-left: 1.75em; }

.zo-icon-list li::before {
	content: "✓";
	position: absolute;
	left: 0;
	color: var(--wp--preset--color--primary);
	font-weight: 700;
}

/* Details/Accordion: Summary klickbar hervorheben */
.wp-block-details summary {
	cursor: pointer;
	font-weight: 600;
}

.wp-block-details[open] summary {
	margin-bottom: var(--wp--preset--spacing--20);
}

/* === PDP: Inline-Icons (RemixIcon) === */
.zo-icon { display: inline-block; flex: 0 0 auto; vertical-align: middle; line-height: 0; }
/* ============================================================
   Component: Button  (.zo-btn)
   Figma Component-Set „Button" 4510:32604 (File sw9mSXf2WMaODrUS4Skv7H).
   Spec: docs/figma-specs/buttons.md  ·  Sync 2026-07-27 (#87)
   Achsen: Size {XL = Basis, --md} × Hierarchy {Primary = Basis, --secondary, --tertiary}
           × Icon {None/Leading/Trailing = DOM-Reihenfolge, --icon = Only, rund}.
   States: :hover (violet-dark) · :focus-visible (Ring foreground, außen, 4px / Tertiary 2px) ·
           disabled (:disabled / [aria-disabled] / .is-disabled → grey-mid).
           active/pressed = Default (Figma-Set ohne eigene Pressed-Optik, #87) → n/a.
   Breakpoints: n/a (Größe über --md-Modifier, nicht viewport-abhängig).
   ============================================================ */
.zo-btn, .zo-btn *, .ff-btn-submit { box-sizing: border-box; }

/* Adopter: Plugin-generierte Buttons, die kein .zo-btn tragen können, übernehmen die
   Komponente statt eigene Regeln (#86, CLAUDE.md: keine Redundanz — eine Button-Quelle).
   FluentForms-Submit = MD/Primary — seit #214 für JEDES Formular (Kontakt, Newsletter,
   Warteliste, Reflexion), nicht mehr je Einbauort kopiert; LD-Mark-Complete = XL/Primary.
   Adopter-Selektoren stehen bewusst in dieser Komponente (nicht in INTEGRATIONS), damit
   Mechanik + States an EINER Stelle liegen.
   Konto-Abmelden (#173) = XL/Secondary; Layout/Platzierung in INTEGRATIONS §Konto-Subnav.
   Text-Bild-CTA (#188) = Core-Button im Pattern zo/section-text-image: XL/Primary, unter
   1024 stuft die Komponente auf die MD-Maße (Figma-Achse Viewport, s. .zo-text-image). */
.zo-btn,
.ff-btn-submit,
.zo-lesson__nav-complete .learndash_mark_complete_button,
.zo-lesson__nav-complete input[type="submit"],
.zo-text-image .wp-block-button__link,
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a {
	display: inline-flex; align-items: center; justify-content: center; gap: 12px;
	height: 64px; padding: 0 24px; border: 0; border-radius: 0;
	font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 22px;
	text-decoration: none; cursor: pointer;
	background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); }

.zo-btn .zo-icon { width: 18px; height: 18px; color: currentColor; }

/* Size MD (48h) — FluentForms-Submits laufen als MD */
.zo-btn--md,
.ff-btn-submit { height: 48px; padding: 0 16px; gap: 8px; font-size: var(--wp--preset--font-size--small); line-height: 20px; }
.zo-btn--md .zo-icon { width: 16px; height: 16px; }

/* Hierarchy Secondary — 4px-Rahmen inside via inset-Shadow (Layout/Breite bleiben exakt) */
.zo-btn--secondary,
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a {
	background: transparent; color: var(--wp--preset--color--primary);
	box-shadow: inset 0 0 0 4px var(--wp--preset--color--primary); }

/* Hierarchy Tertiary — nur Text */
.zo-btn--tertiary { background: transparent; color: var(--wp--preset--color--primary); }

/* Icon-Only — quadratisch, rund (Radius 100, bewusste Ausnahme zur Scharfkantigkeit) */
.zo-btn--icon { width: 64px; padding: 0; gap: 0; border-radius: 100px; }
.zo-btn--icon .zo-icon { width: 24px; height: 24px; }
.zo-btn--md.zo-btn--icon { width: 48px; }
.zo-btn--md.zo-btn--icon .zo-icon { width: 18px; height: 18px; }

/* Hover — violet-dark */
.zo-btn:hover,
.ff-btn-submit:hover,
.zo-lesson__nav-complete .learndash_mark_complete_button:hover,
.zo-lesson__nav-complete input[type="submit"]:hover,
.zo-text-image .wp-block-button__link:hover { background: var(--wp--custom--color--violet-dark); }
.zo-btn--secondary:hover,
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a:hover {
	background: transparent; color: var(--wp--custom--color--violet-dark);
	box-shadow: inset 0 0 0 4px var(--wp--custom--color--violet-dark); }
.zo-btn--tertiary:hover { background: transparent; color: var(--wp--custom--color--violet-dark); }

/* Focus — Ring außen (foreground), 4px, Tertiary 2px */
.zo-btn:focus-visible,
.ff-btn-submit:focus-visible,
.zo-lesson__nav-complete .learndash_mark_complete_button:focus-visible,
.zo-lesson__nav-complete input[type="submit"]:focus-visible,
.zo-text-image .wp-block-button__link:focus-visible,
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a:focus-visible { outline: 4px solid var(--wp--preset--color--foreground); outline-offset: 0; }
.zo-btn--tertiary:focus-visible { outline-width: 2px; }

/* Disabled — grey-mid, keine Interaktion */
.zo-btn:disabled, .zo-btn[aria-disabled="true"], .zo-btn.is-disabled {
	cursor: not-allowed; pointer-events: none;
	background: var(--wp--preset--color--grey-mid); color: var(--wp--preset--color--white); }
.zo-btn--secondary:disabled, .zo-btn--secondary[aria-disabled="true"], .zo-btn--secondary.is-disabled {
	background: transparent; color: var(--wp--preset--color--grey-mid);
	box-shadow: inset 0 0 0 4px var(--wp--preset--color--grey-mid); }
.zo-btn--tertiary:disabled, .zo-btn--tertiary[aria-disabled="true"], .zo-btn--tertiary.is-disabled {
	background: transparent; color: var(--wp--preset--color--grey-mid); box-shadow: none; }

/* Demo-Frame der Button-Komponente (Gerüst der Demoseite, gehört zur Komponente) */
.zo-buttons-demo__h { margin: 24px 0 12px; font-size: var(--wp--preset--font-size--small); font-weight: 700; }
.zo-buttons-demo__row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }

/* ============================================================
   Component: Startseiten-Header  (.zo-homeheader)
   Figma Component-Set 6802:30020 („Header Home", Viewport=SM/MD/LG/XL, READY_FOR_DEV);
   Erstauslegung gegen Frame 6557:8578 (#234).
   Spec: docs/figma-specs/header-home.md  ·  Sync 2026-09-16 (#283)
   Aufbau: SM/MD randlos gestapelt (Bildzone fix 300 hoch, kein Karo), ab LG Karo-Band mit
   der Rail aus Bildfläche (Foto + 20 % Abdunklung, Text unten verankert) und lila
   Themen-Kasten (400). Die Bandhöhe ist inhaltsgetrieben — XL 512 = 56 + 400 + 56, wobei
   die 400 aus dem Kasteninhalt kommen (32+24+24+288+32).
   States: :hover/:focus-visible an den Themen-Knöpfen. Sie überschreiben die Standard-States
           der .zo-btn-Komponente, weil `violet-dark` auf dem lila Kasten unsichtbar wäre
           (im Figma-Set trägt der Frame nur `State = Default`, Spec §8 — abgeleitet).
           active = Default (wie .zo-btn, #87). disabled/leer/laden: n/a (Knöpfe sind Links).
   Breakpoints: SM Basis · MD 640 · LG 1024 · XL 1440 (Container-Queries am Band; nur das
                Karo am Wurzel-Element läuft über @media, weil ein Container sich nicht
                selbst abfragen kann — das Band ist alignfull, Viewport = Container).
                Seit #283 sind alle vier Stufen Figma-belegt (Set 6802:30020); der
                Best-Guess-Eintrag `home-header-reflow` in config/unvalidiert.json ist erledigt.
   ============================================================ */
.zo-homeheader, .zo-homeheader * { box-sizing: border-box; }

.zo-homeheader {
	container-type: inline-size;
	background-color: var(--wp--preset--color--paper);
}

/* Karo erst ab LG — SM/MD stehen randlos ohne Band-Rahmen (Set 6802:30020, Spec §7).
   Karo unten verankert (Bandunterkante = Linie, Pitch 32) — Team-Regel aus dem Review
   (Philipp, #234, 2026-08-21), gleiche Mechanik wie .zo-pgh--events.has-karo (#224).
   Bewusste Abweichung vom Frame-Render (dort oben verankert, Spec §6): der sichere
   Linien-Abschluss unten schlägt den Einzel-Frame. Nicht „zurückfixen". */
@media (min-width: 1024px) {
	.zo-homeheader {
		background-image:
			linear-gradient(var(--wp--preset--color--primary) 1px, transparent 1px),
			linear-gradient(90deg, var(--wp--preset--color--primary) 1px, transparent 1px);
		background-size: 32px 32px;
		background-position: 0 calc(100% - 1px), 0 0;
	}
}

/* Rail + Spalten: ab LG kommt die Breite allein von .zo-container (Grid-Foundation #128),
   die beiden Spalten stoßen ohne Lücke aneinander (Frame: 928 + 400 = 1328). Unter LG ist
   der Header randlos (SM-/MD-Frames 320/640 = volle Viewport-Breite, Spec §7) — die
   Rail-Breite wird dafür scoped aufgehoben, kein eigenes Rail-System (§1.4a). */
.zo-homeheader__inner { display: flex; flex-direction: column; }
@container (max-width: 1023.98px) {
	.zo-homeheader__inner { width: 100%; }
}

/* --- Bildfläche (SM/MD: fix 300 hoch, wächst nur, wenn der Inhalt höher ist) --- */
.zo-homeheader__media {
	position: relative; isolation: isolate; overflow: hidden;
	display: flex; align-items: flex-end;
	min-height: 300px;
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30); /* 24 / 16 */
	background-color: var(--wp--preset--color--grey-dark); /* trägt den weißen Text, solange kein Bild gewählt ist */
}
.zo-homeheader__img { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* Zweiter Fill des Frames: Schwarz 20 % über dem Foto — ohne ihn steht der weiße Text auf
   hellen Bildern nicht (Spec §4, Render-schlägt-JSON-Falle 2). */
.zo-homeheader__media:not(.has-no-image)::after { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.7) 100%); } /* replaces Figma's flat black 20% fill so light photos stay readable (#284, B1a) */
.zo-homeheader__body { position: relative; z-index: 2; width: 100%; min-width: 0; color: var(--wp--preset--color--white); }

.zo-homeheader__title { margin: 0; font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: var(--wp--custom--font-size--24); line-height: 32px; color: inherit; }
.zo-homeheader__lead-in { display: block; }
/* Wechselwort: alle Wörter liegen als Grid-Stapel übereinander (grid-area 1/1). Dadurch
   bestimmt das LÄNGSTE Wort die Zeilenhöhe und beim Wechsel springt nichts (Spec §8).
   Die Dauer der Überblendung setzt das view-Script aus dem Server-Wert. */
.zo-homeheader__rotator { display: grid; }
.zo-homeheader__word { grid-area: 1 / 1; color: var(--wp--preset--color--primary); opacity: 0; transition: opacity var(--zo-homeheader-fade, 500ms) ease-in-out; }
.zo-homeheader__word.is-active { opacity: 1; }

.zo-homeheader__lead { margin: var(--wp--preset--spacing--20) 0 0; font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; letter-spacing: 0.01em; color: inherit; }

/* --- Themen-Kasten (SM: Pad 16, Gap 12; Knöpfe als Reihe mit Umbruch, Gap 12 — Spec §7) --- */
.zo-homeheader__topics { display: flex; flex-direction: column; gap: 12px; padding: var(--wp--preset--spacing--30); background-color: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); }
.zo-homeheader__topics-heading { margin: 0; font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: var(--wp--preset--font-size--medium); line-height: 22px; color: inherit; }
.zo-homeheader__list { display: flex; flex-flow: row wrap; align-items: flex-start; gap: 12px; }

/* Knopf-Optik = .zo-btn (Size MD). Auf Lila kippen nur die Farben — Secondary weiß umrandet,
   der hervorgehobene Knopf weiß gefüllt mit lila Schrift (Spec §5.2, gesampelt). */
.zo-homeheader__topic.zo-btn--secondary { color: var(--wp--preset--color--white); box-shadow: inset 0 0 0 var(--wp--custom--border--emphasis) var(--wp--preset--color--white); }
.zo-homeheader__topic--primary { background: var(--wp--preset--color--white); color: var(--wp--preset--color--primary); }
.zo-homeheader__topic.zo-btn--secondary:hover { background: var(--wp--preset--color--white); color: var(--wp--preset--color--primary); box-shadow: inset 0 0 0 var(--wp--custom--border--emphasis) var(--wp--preset--color--white); }
.zo-homeheader__topic--primary:hover { background: var(--wp--preset--color--accent-lilac); color: var(--wp--preset--color--primary); }
.zo-homeheader__topic:focus-visible { outline: var(--wp--custom--border--emphasis) solid var(--wp--preset--color--white); outline-offset: 0; }

/* ---------- MD (>=640): größere Pads + Schriftstufe (Viewport=MD, 640) ---------- */
@container (min-width: 640px) {
	.zo-homeheader__media { padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40); } /* 32 / 24 */
	.zo-homeheader__topics { padding: var(--wp--preset--spacing--40); gap: var(--wp--preset--spacing--30); } /* 24 / 16 */
	.zo-homeheader__title { font-size: var(--wp--custom--font-size--32); line-height: 42px; }
	.zo-homeheader__lead { margin-top: 12px; font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
}

/* ---------- LG (>=1024): zweispaltig, Kasten fix 400, Bild nimmt den Rest der Rail ---------- */
@container (min-width: 1024px) {
	.zo-homeheader__inner { flex-direction: row; align-items: stretch; padding-block: 56px; }
	.zo-homeheader__media { flex: 1 1 auto; min-width: 0; min-height: 0; padding: var(--wp--preset--spacing--60); padding-right: var(--wp--preset--spacing--70); } /* 40, rechts 64 */
	.zo-homeheader__topics { flex: 0 0 400px; padding: var(--wp--preset--spacing--50); gap: var(--wp--preset--spacing--40); } /* 32 / 24 */
	.zo-homeheader__topics-heading { font-size: var(--wp--custom--font-size--18); line-height: 24px; }
	.zo-homeheader__list { flex-flow: column nowrap; }
	.zo-homeheader__title { font-size: var(--wp--custom--font-size--64); line-height: 76px; }
	.zo-homeheader__lead { margin-top: var(--wp--preset--spacing--40); font-size: var(--wp--custom--font-size--18); line-height: 26px; }
}

/* ---------- XL (>=1440): Rail 1328 = 928 + 400 (Viewport=XL, deckungsgleich 6557:8578) ---------- */
@container (min-width: 1440px) {
	.zo-homeheader__media { padding-right: calc(2 * var(--wp--preset--spacing--60)); } /* 80 — Frame setzt den Text von der Kasten-Kante ab */
}

/* Bewegung reduzieren: kein Wechsel (das view-Script startet gar nicht erst), das erste Wort
   steht — es ist zugleich das Wort für Vorlesesoftware und Suchmaschinen. */
@media (prefers-reduced-motion: reduce) {
	.zo-homeheader__word { transition: none; }
}

/* ============================================================
   Component: Progress-Bar  (.zo-progress)
   Aus .zo-course-progress (#70) promotet → wiederverwendbar über Kurs/Lektion (#87).
   Werte belegt gegen Kurs-Frame 5266:16509 (Track 4px, grey-mid/primary). Kontext-Spacing
   (margin) trägt der Konsument (z. B. .zo-course__progress in PAGES), nicht die Komponente.
   States: n/a (statische Anzeige). Breakpoints: n/a.
   ============================================================ */
.zo-progress__track { height: 4px; background: var(--wp--preset--color--grey-mid); overflow: hidden; }
.zo-progress__fill { display: block; height: 100%; background: var(--wp--preset--color--primary); }
.zo-progress__label { margin: 4px 0 0; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; color: var(--wp--preset--color--foreground); }

/* ============================================================
   Component: Reflexions-Box  (.zo-reflection)  ·  Pattern zo/reflection
   Figma „Card-Text / Reflektionsfrage" in Node 4507-34294 (#85). Peach Card mit Eyebrow,
   Frage und Hinweiszeile — hält als erstes Konzept das FluentForms-Reflexionsformular
   (@artr3y #85): FluentForms-Felder darin werden auf zo-Optik getrimmt (Radius 0, primary).
   Spec: docs/figma-specs/lesson-single.md.
   States: :hover/:focus-visible an FluentForms-Feldern/Submit (definiert). Leer/Fehler:
           FluentForms-eigene Meldungen. Breakpoints: Padding 40→24 unter 600px.
   ============================================================ */
.zo-reflection { background: var(--wp--preset--color--accent-orange); color: var(--wp--preset--color--foreground); padding: 40px; }
.zo-reflection, .zo-reflection * { box-sizing: border-box; }
.zo-reflection__eyebrow { margin: 0; font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; color: var(--wp--preset--color--primary); }
.zo-reflection__question { margin: 24px 0 0; font-size: var(--wp--custom--font-size--24); font-weight: 700; line-height: 32px; color: var(--wp--preset--color--foreground); }
.zo-reflection__hint { margin: 32px 0 0; display: flex; align-items: center; gap: 6px; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; color: var(--wp--preset--color--foreground); }
.zo-reflection__hint .zo-icon { width: 16px; height: 16px; flex: 0 0 auto; color: currentColor; }

/* FluentForms im Reflexionsformular: Feld-Optik kommt seit #170 aus der Form-Controls-Basis
   (BASE, Figma 5551:21846), Formular-Layout und Knopf seit #214 aus der zentralen Schicht
   (INTEGRATIONS §FluentForms bzw. .zo-btn). Hier bleibt nur, was die Box selbst bestimmt:
   ihr Abstand zum Formular und die Höhe des Mehrzeilen-Felds. */
.zo-reflection .fluentform { margin-top: 24px; }
.zo-reflection textarea.ff-el-form-control { min-height: 120px; }

/* ============================================================
   Component: Teaser Double Image  (zo/teaser-double)
   Figma 4510-31348 (Component-Sets 4750:9834/9987, File sw9mSXf2WMaODrUS4Skv7H).
   Spec: docs/figma-specs/teaser-double.md  ·  Sync 2026-07-31 (#96)
   Zwei Full-Bleed-Bildkarten, ohne Gap aneinanderstoßend; Bild + Scrim-Verlauf, Inhalt
   bottom-anchored (Eyebrow → H3 → Body 3-zeilig geklemmt → CTA). CTA adoptiert .zo-btn.
   States: :hover/:focus-visible am CTA (via .zo-btn-Komponente). active/disabled/leer: n/a
           (statischer redaktioneller Teaser). Breakpoints (Container-Query): 640/1024/1440 —
           Ratio 1:1 (<1024) → 4:3 (≥1024); gestapelt (<640) → 2-up (≥640).
   ============================================================ */
.zo-teaser-double, .zo-teaser-double * { box-sizing: border-box; }

.zo-teaser-double { container-type: inline-size; }

.zo-teaser-double__grid { display: grid; grid-template-columns: 1fr; gap: 0; padding-inline: var(--zo-rail-bleed); } /* kanonische Rail (#99) */

/* Karte: Flex-Column, Inhalt unten. aspect-ratio gibt die Mindesthöhe und weicht bei zu
   langem Inhalt (min-content) — Karte wächst dann, statt zu clippen. */
.zo-teaser-double__card {
	position: relative; overflow: hidden; isolation: isolate;
	display: flex; flex-direction: column; justify-content: flex-end;
	aspect-ratio: 1 / 1;                                  /* SM/MD: quadratisch */
	padding: 24px 16px;                                  /* SM: 24 v / 16 h */
	color: var(--wp--preset--color--white);
}

/* Bild füllt die Karte (object-fit), Quellmaße beeinflussen das Layout nie. */
.zo-teaser-double__img { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; max-width: none; margin: 0; object-fit: cover; }

/* Scrim: dunkler Verlauf top→bottom für Lesbarkeit (Node 4750:9988 GRADIENT_LINEAR). */
.zo-teaser-double__card::after { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(180deg, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.8) 100%); }

.zo-teaser-double__content { position: relative; z-index: 2; display: flex; flex-direction: column; }
.zo-teaser-double__content > :first-child { margin-top: 0; }

.zo-teaser-double__eyebrow { margin: 0; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; color: var(--wp--preset--color--accent-lilac); }

.zo-teaser-double__title { margin: 4px 0 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 24px; color: var(--wp--preset--color--white); }

.zo-teaser-double__body { margin: 8px 0 0; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; color: var(--wp--preset--color--white);
	display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.zo-teaser-double__cta { margin-top: 24px; align-self: flex-start; }

/* MD (≥640): 2-up, quadratisch, Padding 24, H3 20/26, H3→Body 12. */
@container (min-width: 640px) {
	.zo-teaser-double__grid { grid-template-columns: repeat(2, 1fr); }
	.zo-teaser-double__card { padding: 24px; }
	.zo-teaser-double__title { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-teaser-double__body { margin-top: 12px; }
}

/* LG (≥1024): 4:3, Inset 32, Padding 32, H3 24/32, größere Gaps, CTA auf 64h. */
@container (min-width: 1024px) {
	.zo-teaser-double__card { aspect-ratio: 4 / 3; padding: 32px; }
	.zo-teaser-double__title { margin-top: 6px; font-size: var(--wp--custom--font-size--24); line-height: 32px; }
	.zo-teaser-double__body { margin-top: 16px; font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-teaser-double__cta { margin-top: 32px; }
	.zo-teaser-double .zo-teaser-double__cta.zo-btn { height: 64px; padding: 0 24px; gap: 12px; font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-teaser-double__cta.zo-btn .zo-icon { width: 18px; height: 18px; }
}

/* XL (≥1440): Padding 48, Eyebrow→H3 8. Inset via kanonischer Rail (#99). */
@container (min-width: 1440px) {
	.zo-teaser-double__card { padding: 48px; }
	.zo-teaser-double__title { margin-top: 8px; }
}

/* ============================================================
   Component: Alert Box  (zentrales Modul, Block zo/alert-box, #278)
   Figma Component-Set „Alert Box" 4750:18950 (READY_FOR_DEV):
   XL 1440×206 · LG 1024×206 · MD 640×208 · SM 320×272.
   Spec: docs/figma-specs/alert-box.md  ·  Sync 2026-09-15
   States: :hover am Link (definiert). focus-visible: Browser-Default;
           active/disabled/laden/fehler: n/a. Leer/Inaktiv: Block rendert
           nichts (kein Wrapper — Modul-Abstand haengt am owl-Selektor).
   Breakpoints (Media-Query): < 640 SM (Rand 16, Titel 18/24) ·
           640–1023 MD (ohne Bild, Titel 20/26) · >= 1024 LG/XL
           (Bild 316×158 links, Titel 24/32). Bild optional: ohne Bild
           fuellt der Text die Breite (Spalte entfaellt im Markup).
   ============================================================ */
.zo-angebot, .zo-angebot * { box-sizing: border-box; }

/* No own width: the section is always alignfull (hardcoded in the render, #278).
   Inside constrained parents WP's `.has-global-padding > .alignfull` negative
   margins stretch it to full bleed; a fixed `width: 100%` on top of that shifted
   the box left by the root padding (over-constrained: width + both margins). */

/* Rail-boxed Inner (#99/#128): Cap 1328, zentriert. Hoehe content-getrieben:
   XL/LG Bild 158 + 2×24 Padding = 206 lt. Set (kein fixes height). */
.zo-angebot__inner { width: var(--zo-rail-w); margin: 0 auto;
	display: flex; align-items: flex-start; gap: 40px; padding: 24px;
	background: var(--wp--preset--color--accent-lilac); }

.zo-angebot__media { flex: 0 0 316px; width: 316px; height: 158px; }

.zo-angebot__media img { width: 100%; height: 100%; max-width: none; margin: 0; object-fit: cover; display: block; }

/* Flex-Column statt Inline-Flow: das inline-flex-Flag erzeugte sonst 2px Zeilenbox-Rest
   unter sich (Descent) — als Flex-Item sind die Gaps exakt die Margins. */
.zo-angebot__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; }

.zo-angebot__flag { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 4px 8px 4px 6px;
	background: var(--wp--preset--color--foreground); color: var(--wp--preset--color--white);
	font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; }

.zo-angebot__flag .zo-icon { width: 16px; height: 16px; }

.zo-angebot__title { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--24); font-weight: 700;
	line-height: 32px; margin: 8px 0 0; color: var(--wp--preset--color--foreground); }

/* Body lt. Set foreground #1A1A1A — der Altbau (4482:39337) nutzte grey-dark. */
.zo-angebot__text { margin: 4px 0 0; font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 22px;
	color: var(--wp--preset--color--foreground); }

.zo-angebot__link { display: inline-flex; align-items: center; gap: 6px; margin-top: 24px;
	font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px;
	color: var(--wp--preset--color--primary); text-decoration: none; }

.zo-angebot__link:hover { opacity: .85; }

.zo-angebot__link .zo-icon { width: 18px; height: 18px; }

/* MD/SM-Varianten (< 1024): ohne Bild, kleinere Flag/Typo/Icons. */
@media (max-width: 1023px) {
	.zo-angebot__media { display: none; }
	.zo-angebot__flag { height: 20px; padding: 2px 6px; gap: 4px; }
	.zo-angebot__flag .zo-icon { width: 12px; height: 12px; }
	.zo-angebot__title { margin-top: 6px; font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-angebot__text { font-size: var(--wp--preset--font-size--small); line-height: 20px; }
	.zo-angebot__link { gap: 4px; }
	.zo-angebot__link .zo-icon { width: 16px; height: 16px; }
}

/* SM (< 640): schmalere Raender, Titel 18/24, Flag→Titel-Gap 8. */
@media (max-width: 639px) {
	.zo-angebot__inner { padding: 24px 16px; }
	.zo-angebot__title { margin-top: 8px; font-size: var(--wp--custom--font-size--18); line-height: 24px; }
}

/* ============================================================
   Component: Teaser universal  (Kachel, wählbare BG-Farbe)
   Figma Component-Set „Teaser-universal" (File sw9mSXf2WMaODrUS4Skv7H):
   XL 4909-78066 · LG 4909-78134 · MD 4909-78201 · SM 4909-78268.
   Spec: docs/figma-specs/teaser-universal.md  ·  Sync 2026-07-06
   States: :hover, :focus-visible am CTA-Button (definiert).
           active/disabled/leer/laden/fehler: n/a (statischer Pattern-CTA).
   Breakpoints (Container-Query): < 640px vertikal (Bild oben);
           >= 640px horizontal (Bild rechts, Quadrat = Kachelhöhe).
   ============================================================ */
.zo-teaser-uni, .zo-teaser-uni * { box-sizing: border-box; }

/* Container + BG-Indirektion: der Block-Style setzt --zo-tile-bg an EINER Stelle,
   und DERSELBE Group (die äußerste .zo-teaser-uni, die man beim Klick auf die Kachel
   selektiert) trägt Style-Klasse UND Hintergrund — so schaltet die Farbwahl direkt an
   der Kachel, die man auswählt. Spätere brand-semantische Token-Namen = Edit hier,
   ohne Content-Migration. */
.zo-teaser-uni { container-type: inline-size; --zo-tile-bg: var(--wp--preset--color--white);
	background: var(--zo-tile-bg);
	color: var(--wp--preset--color--foreground);
	border-radius: 0;                                    /* Marke scharfkantig */
	overflow: hidden;
	--zo-tu-icon-cal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 1V3H15V1H17V3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H7V1H9ZM20 11H4V19H20V11ZM7 5H4V9H20V5H17V7H15V5H9V7H7V5Z'/%3E%3C/svg%3E");
	--zo-tu-icon-arrow: var(--zo-icon-arrow-right); }

.zo-teaser-uni.is-style-zo-tile-white     { --zo-tile-bg: var(--wp--preset--color--white); }

.zo-teaser-uni.is-style-zo-tile-orange    { --zo-tile-bg: var(--wp--preset--color--accent-orange); }

.zo-teaser-uni.is-style-zo-tile-yellow    { --zo-tile-bg: var(--wp--preset--color--accent-yellow); }

.zo-teaser-uni.is-style-zo-tile-turquoise { --zo-tile-bg: var(--wp--preset--color--accent-turquoise); }

.zo-teaser-uni.is-style-zo-tile-lilac     { --zo-tile-bg: var(--wp--preset--color--accent-lilac); }

.zo-teaser-uni.is-style-zo-tile-grey      { --zo-tile-bg: var(--wp--preset--color--grey-light); }

/* Vertikal (mobile-first, MD/SM). Die Größen-Locals liegen am __inner (Descendant),
   damit die Container-Query sie überschreiben kann — der Container selbst kann sich
   nicht per @container stylen. */
.zo-teaser-uni__inner {
	--zo-tu-pad: var(--wp--preset--spacing--40);        /* 24 */
	--zo-tu-title: 24px;
	--zo-tu-sub: 16px;
	--zo-tu-body: 14px;                                 /* Absatz/Labels/Button MD/SM (kein 14px-Token) */
	--zo-tu-gap-title: var(--wp--preset--spacing--30);  /* 16 */
	--zo-tu-gap-sub: 6px;
	--zo-tu-gap-body: 12px;
	--zo-tu-list-gap: var(--wp--preset--spacing--10);   /* 4  (List-Icon itemSpacing MD/SM) */
	--zo-tu-icon-gap: 6px;                              /* 6  (List Item itemSpacing MD/SM) */
	--zo-tu-body-gap: var(--wp--preset--spacing--40);   /* 24 Textblock->Button (Frame522 gap MD/SM) */
	--zo-tu-icon-size: 16px;                            /* Icon+Pfeil MD/SM */
	--zo-tu-btn-h: 48px;
	--zo-tu-btn-padh: var(--wp--preset--spacing--30);   /* 16 */
	--zo-tu-btn-gap: var(--wp--preset--spacing--20);    /* 8 */
	display: flex; flex-direction: column;
}

/* Bild-Box hat IMMER eine feste Geometrie (aspect-ratio bzw. stretch-Quadrat).
   Das <img> liegt absolut darin und füllt sie per object-fit — die Quellbild-
   Maße (zu groß/zu klein) beeinflussen das Layout dadurch nie. */
.zo-teaser-uni__media { order: -1; position: relative; aspect-ratio: 16 / 9; width: 100%; margin: 0; overflow: hidden; background: var(--wp--preset--color--white); }

.zo-teaser-uni__media img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; max-width: none; object-fit: cover; border-radius: 0; }

.zo-teaser-uni__body { display: flex; flex-direction: column; gap: var(--zo-tu-body-gap); padding: var(--zo-tu-pad); }

.zo-teaser-uni__text { display: flex; flex-direction: column; }

.zo-teaser-uni__title    { margin: 0 0 var(--zo-tu-gap-title); font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: var(--zo-tu-title); line-height: 1.25; color: var(--wp--preset--color--foreground); }

.zo-teaser-uni__subtitle { margin: 0 0 var(--zo-tu-gap-sub);   font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: var(--zo-tu-sub);   line-height: 1.3;  color: var(--wp--preset--color--foreground); }

.zo-teaser-uni__lead     { margin: 0 0 var(--zo-tu-gap-body);  font-family: var(--wp--preset--font-family--body);    font-weight: 500; font-size: var(--zo-tu-body); line-height: 1.4; color: var(--wp--preset--color--foreground); }

/* Icon-Liste: Kalender-Icon per mask (currentColor) — kein Inline-SVG im Content. */
.zo-teaser-uni__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--zo-tu-list-gap); }

.zo-teaser-uni__list li {
	position: relative; margin: 0; padding-left: calc(var(--zo-tu-icon-size) + var(--zo-tu-icon-gap));
	font-family: var(--wp--preset--font-family--body); font-weight: 500; font-size: var(--zo-tu-body);
	line-height: 1.375; color: var(--wp--preset--color--foreground);
}

.zo-teaser-uni__list li::before {
	content: ""; position: absolute; left: 0; top: 0.1em; width: var(--zo-tu-icon-size); height: var(--zo-tu-icon-size); flex: 0 0 auto;
	background-color: currentColor;
	-webkit-mask: var(--zo-tu-icon-cal) center / contain no-repeat;
	        mask: var(--zo-tu-icon-cal) center / contain no-repeat;
}

/* CTA-Button (Core-Button, scharfkantig, Pfeil per mask). */
.zo-teaser-uni__cta { margin: 0; }

.zo-teaser-uni__cta .wp-block-button__link {
	display: inline-flex; align-items: center; gap: var(--zo-tu-btn-gap);
	min-height: var(--zo-tu-btn-h); padding: 0 var(--zo-tu-btn-padh);
	border-radius: 0;
	background-color: var(--wp--preset--color--primary); color: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--body); font-weight: 500; font-size: var(--zo-tu-body); line-height: 1;
	transition: filter .15s ease;
}

.zo-teaser-uni__cta .wp-block-button__link::after {
	content: ""; width: var(--zo-tu-icon-size); height: var(--zo-tu-icon-size); flex: 0 0 auto; background-color: currentColor;
	-webkit-mask: var(--zo-tu-icon-arrow) center / contain no-repeat;
	        mask: var(--zo-tu-icon-arrow) center / contain no-repeat;
}

.zo-teaser-uni__cta .wp-block-button__link:hover { filter: brightness(1.08); }

.zo-teaser-uni__cta .wp-block-button__link:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }

/* Horizontal ab 640px = LG-Regime (LG-Frame 4909-78134). Werte, die XL und LG teilen
   (Padding 40, Titel 32, Untertitel 18, Body 16, title->sub 24, list-gap 6, icon-gap 8,
   Button 64, Icon/Pfeil 18), stehen hier; die zwei Gaps, in denen XL abweicht
   (sub->para, para->list), werden im XL-Tier unten überschrieben. */
@container (min-width: 640px) {
	.zo-teaser-uni__inner {
		--zo-tu-pad: var(--wp--preset--spacing--60);        /* 40 */
		--zo-tu-title: 32px;
		--zo-tu-sub: 18px;
		--zo-tu-body: 16px;                                 /* Absatz/Labels/Button XL/LG (kein 16px-Token) */
		--zo-tu-gap-title: var(--wp--preset--spacing--40);  /* 24 */
		--zo-tu-gap-sub: 6px;                               /* LG sub->para (XL-Tier: 8) */
		--zo-tu-gap-body: 12px;                             /* LG para->list (XL-Tier: 16) */
		--zo-tu-list-gap: 6px;                              /* List-Icon itemSpacing XL/LG */
		--zo-tu-icon-gap: var(--wp--preset--spacing--20);   /* 8  (List Item itemSpacing XL/LG) */
		--zo-tu-icon-size: 18px;                            /* Icon+Pfeil XL/LG */
		--zo-tu-btn-h: 64px;
		--zo-tu-btn-padh: var(--wp--preset--spacing--40);   /* 24 */
		--zo-tu-btn-gap: 12px;
		display: grid; grid-template-columns: 1fr auto; align-items: stretch;
	}
	/* Bild rechts = Quadrat mit Seitenlänge = Kachelhöhe (XL 448, LG 490). Grid-Track
	   `auto` + align-self:stretch gibt der Media-Zelle die Zeilenhöhe (= Body-/Kachelhöhe),
	   aspect-ratio:1 leitet die Breite daraus ab. Im Grid resolved das robust (in Flex
	   kollabiert die Breite aus stretch+aspect-ratio auf 0 — Kachel-Bild-Falle, gemessen). */
	.zo-teaser-uni__media { order: 0; aspect-ratio: 1 / 1; width: auto; height: auto; align-self: stretch; }
	.zo-teaser-uni__body { justify-content: space-between; }
}

/* XL-Regime (XL-Frame 4909-78066): breite Kachel. Nur die zwei Gaps, in denen XL
   von LG abweicht. Schwelle 1180px liegt zwischen LG-Kachel (980) und XL-Kachel (1384),
   damit jede Stufe ihre exakten Figma-Gaps trifft (±2px ohne Näherung). */
@container (min-width: 1180px) {
	.zo-teaser-uni__inner {
		--zo-tu-gap-sub: var(--wp--preset--spacing--20);    /* 8  XL sub->para */
		--zo-tu-gap-body: var(--wp--preset--spacing--30);   /* 16 XL para->list */
	}
}

/* --- Themen-Karte (Card Topic) + Themen-Grid — Figma 4602:33566 + 5961:35357, Sync 2026-08-10 (#166).
   Blöcke zo/topic-grid (Eltern-Container) + zo/topic-card (inc/topic-card-block.php), Pattern
   zo/grid-topic; Raster auf der Grid-Foundation (.zo-container/.zo-grid im Block-Render,
   Karten span 4 → span 6 ab LG).
   States: default + :hover/:focus-visible (Pfeil-Button invertiert); Leer: 0-Zähler-Chip entfällt,
   ohne Zielseite Hinweistext (__empty), Raster ohne Karten rendert nicht. n/a: active/disabled/laden.
   Breakpoints (@media, Foundation-konform): SM <640 · MD 640–1023 · LG+ ≥1024 (XL erbt LG+). */
/* Sektion liegt in main UND entry-content (beide has-global-padding) — der WP-alignfull-Ausbruch
   hebt nur EINE Ebene auf → viewport-relativ ausbrechen (content-rail.md §align:full, wie event-list).
   Die Rail kommt innen von .zo-container (100% = 100vw → exakt 56/1328 @1440).
   Sektions-Padding 80 lebt hier (nicht im Markup) — Redakteure können es nicht wegklicken. */
.zo-topics { box-sizing: border-box; width: 100vw; margin-inline: calc(50% - 50vw); padding-block: var(--wp--preset--spacing--80); }

.zo-topics * { box-sizing: border-box; }

.zo-topics .zo-topics__inner { row-gap: var(--zo-grid-gutter); align-items: stretch; }

/* WP-Flow-Gap (24px margin-block-start der Gruppe) neutralisieren — §1.6-Gotcha; im Grid
   würde er Row-Stretch und Zeilen-Gap verfälschen (gemessen: +24 an Karte 2). */
.zo-topics .zo-topics__inner > * { margin: 0; }

.zo-topics .wp-block-zo-topic-card { grid-column: span 4; display: flex; }

.zo-topics .wp-block-zo-topic-card > .zo-card-topic,
.zo-topics .zo-card-topic { width: 100%; }

@media (min-width: 1024px) {
	.zo-topics .wp-block-zo-topic-card { grid-column: span 6; }
}

.zo-card-topic { position: relative; /* anchor for the stretched button link (#352) */ display: flex; flex-direction: column; background: var(--wp--preset--color--white);
	box-shadow: var(--wp--preset--shadow--card);
	border: var(--wp--custom--border--hairline) solid var(--wp--preset--color--grey-light); }

.zo-card-topic__media { width: 100%; }

.zo-card-topic__media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }

/* Intro: Min-Höhe je Breakpoint (Figma-Kontrollsumme 200/240/278); Footer unten gepinnt. */
.zo-card-topic__body { display: flex; flex-direction: column; flex: 1 1 auto; padding: 16px; min-height: 200px; }

.zo-card-topic__head { display: flex; align-items: center; gap: 6px; }

.zo-card-topic__icon { display: inline-flex; color: var(--wp--preset--color--foreground); }

.zo-card-topic__icon svg { width: 18px; height: 18px; }

.zo-card-topic__title { margin: 0; font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 24px; color: var(--wp--preset--color--foreground); }

.zo-card-topic__text { margin: 8px 0 0; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px;
	color: var(--wp--preset--color--foreground); }

/* margin-top:auto pinnt den Footer unten, padding-top ist der Min-Gap (Figma itemSpacing 16/24/24). */
.zo-card-topic__footer { display: flex; align-items: flex-end; justify-content: space-between;
	gap: 16px; margin-top: auto; padding-top: 16px; }

.zo-card-topic__flags { display: flex; flex-direction: column; gap: 6px; }

.zo-card-topic__flag { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px;
	font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; white-space: nowrap;
	color: var(--wp--preset--color--foreground); align-self: flex-start; }

.zo-card-topic__flag svg { width: 12px; height: 12px; flex: 0 0 auto; }

.zo-card-topic__flag--turquoise { background: var(--wp--preset--color--accent-turquoise); }

.zo-card-topic__flag--orange { background: var(--wp--preset--color--accent-orange); }

.zo-card-topic__button { display: inline-flex; align-items: center; justify-content: center;
	flex: 0 0 auto; width: 48px; height: 48px; border-radius: 9999px;
	border: 4px solid var(--wp--preset--color--primary); color: var(--wp--preset--color--primary);
	background: transparent; text-decoration: none; }

.zo-card-topic__button::after { content: ""; position: absolute; inset: 0; } /* whole card clickable (#352 B1a), like Card Expert */
.zo-card-topic__button svg { width: 18px; height: 18px; }

.zo-card-topic__button:hover,
.zo-card-topic__button:focus-visible { background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); }

.zo-card-topic__empty { margin: 0; padding: 16px; font-size: var(--wp--custom--font-size--12);
	color: var(--wp--preset--color--foreground); }

/* MD 640–1023 — Metriken (Figma Viewport=MD): Pad 24, Icon 24, Titel 20/26, Body 14/20, Min 240. */
@media (min-width: 640px) {
	.zo-card-topic__body { padding: 24px; min-height: 240px; }
	.zo-card-topic__icon svg { width: 24px; height: 24px; }
	.zo-card-topic__title { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-card-topic__text { font-size: 14px; line-height: 20px; } /* kein 14er-Token, Figma 4602:33566 MD */
	.zo-card-topic__footer { padding-top: 24px; }
}

/* LG+ ≥1024 (deckt XL): Pad 32, Icon 32, Titel 24/32, Body 16/22, Min 278, Flags horizontal H24. */
@media (min-width: 1024px) {
	.zo-card-topic__body { padding: 32px; min-height: 278px; }
	.zo-card-topic__head { gap: 12px; }
	.zo-card-topic__icon svg { width: 32px; height: 32px; }
	.zo-card-topic__title { font-size: var(--wp--custom--font-size--24); line-height: 32px; }
	.zo-card-topic__text { margin-top: 12px; font-size: 16px; line-height: 22px; } /* kein 16er-Token, Figma 4602:33566 LG+ */
	.zo-card-topic__flags { flex-direction: row; flex-wrap: wrap; gap: 12px; }
	.zo-card-topic__flag { gap: 6px; padding: 4px 8px 4px 6px; }
	.zo-card-topic__flag svg { width: 16px; height: 16px; }
}

/* ============================================================
   Component: Card-Text  (Text-Karte / LD-Lektionskachel)
   Figma COMPONENT_SET „Card-Text" 4509:30862  ·  Spec: docs/figma-specs/card-text.md
   Sync 2026-07-22 (#55). Varianten: lesson (peach) · begriff/methode (white+border)
   · reflection (peach, doppelbreit inline). Kein Divider (Line-16 rendert nicht).
   ============================================================ */
.zo-card-text, .zo-card-text * { box-sizing: border-box; }
.zo-card-text { display: flex; }
.zo-card-text__inner {
	display: flex; flex-direction: column; width: 100%;
	padding: var(--wp--preset--spacing--40); /* 24 */
	color: var(--wp--preset--color--foreground);
	text-decoration: none;
}
.zo-card-text__eyebrow {
	margin: 0; font-size: var(--wp--preset--font-size--small); font-weight: 700; /* Presets sind fluid (clamp) → px, wie Card-Topic */
	line-height: 20px; letter-spacing: 0.14px; color: var(--wp--preset--color--primary);
}
.zo-card-text__title {
	margin: var(--wp--preset--spacing--40) 0 0; /* eyebrow->title 24 */
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--24); font-weight: 700; line-height: 32px; /* kein 24er-Token */
	color: var(--wp--preset--color--foreground);
	overflow-wrap: break-word; hyphens: auto; /* lange Komposita brechen, statt Kachel-Border zu überschreiten (#70) */
}
.zo-card-text__text {
	margin: 12px 0 0; /* title->body 12 */
	font-size: var(--wp--preset--font-size--medium); font-weight: 500; /* Preset medium ist fluid (clamp) → px */
	line-height: 22px; letter-spacing: 0.16px;
}
.zo-card-text__footer {
	display: flex; flex-wrap: wrap; align-items: center;
	gap: var(--wp--preset--spacing--60); /* item-gap 40 */
	margin-top: var(--wp--preset--spacing--50); /* body->footer min 32; bei lesson via auto gepinnt */
}
.zo-card-text__meta-item { display: inline-flex; align-items: center; gap: 6px;
	font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; }
.zo-card-text__meta-icon { flex: 0 0 auto; }

/* Variante Lektion — Peach, feste Mindesthoehe 280, Footer unten gepinnt */
.zo-card-text--lesson { background: var(--wp--preset--color--accent-orange); }
.zo-card-text--lesson .zo-card-text__inner { min-height: 280px; }
.zo-card-text--lesson .zo-card-text__footer { margin-top: auto; }

/* Varianten Begriff/Methode — White + Haarlinie, hug height, kein Footer */
.zo-card-text--begriff,
.zo-card-text--methode { background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--grey-mid); }

/* Variante Reflektionsfrage — Peach, doppelbreit inline, Padding 40 */
.zo-card-text--reflection { background: var(--wp--preset--color--accent-orange); }
.zo-card-text--reflection .zo-card-text__inner { padding: var(--wp--preset--spacing--60); } /* 40 */
.zo-card-text--reflection .zo-card-text__title { line-height: 32px; }
.zo-card-text--reflection .zo-card-text__footer { margin-top: var(--wp--preset--spacing--50); }

/* Ganze Karte klickbar: Hover/Focus hebt dezent, wie andere Flaechen-Karten */
a.zo-card-text__inner { transition: transform .15s ease, box-shadow .15s ease; }
a.zo-card-text__inner:hover,
a.zo-card-text__inner:focus-visible { transform: translateY(-2px);
	box-shadow: 0 6px 20px rgba(0,0,0,.08); }

/* Grid der Text-Karten: 460 fix (kein Stretch), so viele Spalten wie passen (Reflow-Annahme #55).
   minmax(min(100%,460px),460px): fixe 460 solange sie passen, sonst fluid auf Containerbreite
   (kein Overflow, robust gegen Container-Padding — ohne px-Breakpoint). */
.zo-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 460px), 460px));
	justify-content: start; gap: var(--wp--preset--spacing--40); }

/* ============================================================
   Component: Account-Kurse  (Mein Konto → Endpoint /courses/, #156)
   Kein Figma-Frame — Zusammenbau aus vorhandenen Bausteinen (Entscheide artr3y
   07.08. + Philipp 18.08.): drei Sektionen mit .zo-section-heading (#152).
   „Deine Kurse" = Katalog-Kachel-Variante (.zo-kat-card, Card-Product-Optik) mit
   .zo-progress + Kurs-CTA aus #90 als Action-Link-Zeile (Review Philipp 18.08.:
   Progress oben, darunter Links statt zo-btn) statt Preis/Termin-Fuß; zwei
   Link-Ziele statt Flächen-Link (Bild/Titel → Kursseite, CTA → nächster Schritt),
   verschachtelte <a> wären invalides HTML. „Weitere kostenlose Kurse" = dieselbe
   Kachel als --free-Variante (kein Progress, ein „Kurs starten"-Action-Link →
   Kursseite, Philipp 18.08. 22:00). „Verfügbare Kurse" = zo_render_product_card 1:1.
   States: Titel-Link :hover/:focus-visible = primary (Nav-Konvention); Karten-
   Shadow-Hover kommt von .zo-kat-card; CTA-States über .is-style-zo-action-link.
   disabled/leer/laden: Leerfall eigener Block, sonst n/a.
   Breakpoints: Grid = Katalog-Foundation (span 4 → 3/2/1 Karten je 12/8/4 Spalten),
   kein H-Overflow (375/768/1440 gemessen, #156); Heading stuft über .zo-section-heading.
   ============================================================ */
/* Grid = Katalog-Foundation statt eigener auto-fit-Rail (§1.4a — auto-fit dehnte die
   Karten auf 484 bzw. seitenbreite 992 statt 432, Review Philipp 18.08.). Die Konto-
   Content-Spalte ist span 9 der Foundation (INTEGRATIONS §Konto-Subnav) → ein
   9-Spalten-Subgrid mit demselben Gutter reproduziert die Foundation-Spalten exakt,
   span-4-Karten (.zo-kat-grid-Default) messen genau Card-Product (XL 432). <1024 ist
   die Content-Spalte die volle Rail → Foundation-Spaltenzahl (8/4) wie im Katalog. */
.zo-account-courses__section .zo-kat-grid { margin-top: 0; } /* Heading-Margin liefert die 24 */
@media (min-width: 1024px) {
	.zo-account-courses__section .zo-kat-grid { grid-template-columns: repeat(9, 1fr); }
}
/* WC-Reset-Gegenregel (Muster Katalog-Archiv, INTEGRATIONS): woocommerce-layout.css
   setzt auf body.woocommerce-page `img { height: auto }` (0-1-1) und schlägt
   .zo-kat-card__img (0-1-0) — das Bild fiele auf seine intrinsische Höhe und übermalte
   den Karten-Body (Titel/Progress unsichtbar, Review Philipp 18.08.). */
.zo-account-courses__section .zo-kat-card__img { height: 100%; }
/* Sektions-Rhythmus: Heading->Grid 24 (Heading-Margin), Sektion->Sektion 64 */
.zo-account-courses__section + .zo-account-courses__section { margin-top: var(--wp--preset--spacing--70); }
.zo-account-courses__heading { margin: 0 0 var(--wp--preset--spacing--40); }
/* Kurs-Karte: Body wächst mit, bleibt aber mindestens auf Card-Product-Höhe (254, #94/#197)
   und füllt die Karte — Konto- und Katalog-Kacheln einer Reihe fluchten. */
.zo-account-course .zo-kat-card__body { height: auto; min-height: 254px; flex: 1 1 auto; }
.zo-account-course__media-link { position: absolute; inset: 0; display: block; }
.zo-account-course__link { color: inherit; text-decoration: none; }
.zo-account-course__link:hover,
.zo-account-course__link:focus-visible { color: var(--wp--preset--color--primary); }
/* Fuß (Review Philipp 18.08.): Progress unten gepinnt (padding-top hält min. 12 zum
   Titel), Action-Link-Zeile 12 darunter. Gratis-Variante (--free, Sektion „Weitere
   kostenlose Kurse", #156): kein Progress — die Action-Zeile selbst pinnt unten. */
.zo-account-course__progress { margin: auto 0 0; padding-top: 12px; }
.zo-account-course .zo-course__actions { margin-top: 12px; }
.zo-account-course--free .zo-course__actions { margin-top: auto; padding-top: 12px; }
/* Leerfall: Hinweis + Link aufs Lernangebot */
.zo-account-courses__empty-text { margin: 0 0 var(--wp--preset--spacing--40); }

/* Demo-Frames (Pattern demo-card-text, #55): Varianten in nativer Breite */
.zo-cards-demo__frame { flex: 0 0 auto; }
.zo-cards-demo__frame--card { width: 460px; max-width: none; }
.zo-cards-demo__frame--wide { width: 936px; max-width: none; }

/* --- Demo-Frames (Pattern demo-page-header): jeder Breakpoint in nativer Breite --- */
.zo-pgh-demo__frame { flex: 0 0 auto; }
.zo-pgh-demo__frame--xl { width: 1440px; max-width: none; }
.zo-pgh-demo__frame--lg { width: 1024px; max-width: none; }
.zo-pgh-demo__frame--md { width: 640px; max-width: none; }
.zo-pgh-demo__frame--sm { width: 320px; max-width: none; }

/* --- Demo-Frames (Pattern demo-testimonial-carousel, #60): native Breite je Breakpoint --- */
.zo-tc-demo__frame { flex: 0 0 auto; }
.zo-tc-demo__frame--xl { width: 1440px; max-width: none; }
.zo-tc-demo__frame--lg { width: 1024px; max-width: none; }
.zo-tc-demo__frame--md { width: 640px; max-width: none; }
.zo-tc-demo__frame--sm { width: 320px; max-width: none; }

/* Demo-Frames für das FAQ-Akkordeon entfernt (#127): seit dem Grid-Umzug stuft das Modul am
   VIEWPORT — vier Fixed-Width-Frames in EINEM Viewport zeigen dann alle denselben Breakpoint.
   Die Demo-Seite hält jetzt eine Instanz in natürlicher Breite, gemessen wird an vier echten
   Viewports (tools/figma/measure-faq-accordion.js). */

/* --- Demo-Frames (Pattern demo-content-box, #64): native Breite je Breakpoint --- */
.zo-cbox-demo__frame { flex: 0 0 auto; }
.zo-cbox-demo__frame--xl { width: 1440px; max-width: none; }
.zo-cbox-demo__frame--lg { width: 1024px; max-width: none; }
.zo-cbox-demo__frame--md { width: 640px; max-width: none; }
.zo-cbox-demo__frame--sm { width: 320px; max-width: none; }

/* --- Demo-Frames (Pattern demo-teaser-double, #96): native Breite je Breakpoint --- */
.zo-tdbl-demo__frame { flex: 0 0 auto; }
.zo-tdbl-demo__frame--xl { width: 1440px; max-width: none; }
.zo-tdbl-demo__frame--lg { width: 1024px; max-width: none; }
.zo-tdbl-demo__frame--md { width: 640px; max-width: none; }
.zo-tdbl-demo__frame--sm { width: 320px; max-width: none; }

/* --- Demo-Frames (Pattern demo-image-carousel, #79): native Breite je Breakpoint --- */
.zo-imgc-demo__frame { flex: 0 0 auto; }
.zo-imgc-demo__frame--xl { width: 1440px; max-width: none; }
.zo-imgc-demo__frame--lg { width: 1024px; max-width: none; }
.zo-imgc-demo__frame--md { width: 640px; max-width: none; }
.zo-imgc-demo__frame--sm { width: 320px; max-width: none; }

/* --- Demo-Frames (Pattern demo-text-columns, #80): native Breite je Breakpoint --- */
.zo-txtcol-demo__frame { flex: 0 0 auto; }
.zo-txtcol-demo__frame--xl { width: 1440px; max-width: none; }
.zo-txtcol-demo__frame--lg { width: 1024px; max-width: none; }
.zo-txtcol-demo__frame--md { width: 640px; max-width: none; }
.zo-txtcol-demo__frame--sm { width: 320px; max-width: none; }

/* --- Demo-Frames (Pattern demo-einstiegskurs, #65): native Breite je Breakpoint --- */
.zo-ek-demo__frame { flex: 0 0 auto; }
.zo-ek-demo__frame--xl { width: 1440px; max-width: none; }
.zo-ek-demo__frame--lg { width: 1024px; max-width: none; }
.zo-ek-demo__frame--md { width: 640px; max-width: none; }
.zo-ek-demo__frame--sm { width: 320px; max-width: none; }

/* ============================================================
   Component: Content Box  (zo/content-box + zo/content-box-item)
   Figma 5210-61195 (COMPONENT_SET Type×Viewport).
   Spec: docs/figma-specs/content-box.md  ·  Sync 2026-07-23 (#64)
   Reflow per Container-Query auf dem Block: 1 / 2 / 4 Spalten (SM / MD / LG+XL),
   Gap 16, Item-Padding 24; Inline-Padding 16/24/32/56 (SM/MD/LG/XL) = Figma-.base-Inset.
   Type färbt den Item-Hintergrund (Default neutral = weiß).
   States: n/a (redaktionell, kein Hover/Focus/Leer-Zustand — Inhalt via InnerBlocks).
   Breakpoints: Container 640 / 1024 / 1440.
   ============================================================ */
.zo-content-box, .zo-content-box * { box-sizing: border-box; }
/* container-type misst die Content-Box → der Wrapper bleibt grid-/padding-frei, sonst könnte er
   sich nicht von seiner EIGENEN @container-Query stylen und die Schwellen verschöben sich um den
   Innenrand. Grid + Inline-Padding liegen auf __grid (Muster analog .zo-faq). */
.zo-content-box { container-type: inline-size; }
.zo-content-box__grid { display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--30); /* 16 */
	padding-inline: var(--zo-rail-bleed); /* kanonische Rail (#99) */ }
.zo-content-box__item { display: flex; flex-direction: column; gap: 12px;
	padding: var(--wp--preset--spacing--40);             /* 24 */ border-radius: 0; }
.zo-content-box__headline { display: flex; align-items: flex-start; gap: var(--wp--preset--spacing--20); /* 8 */ }
.zo-content-box__icon { flex: 0 0 auto; margin-top: 1px; color: var(--wp--preset--color--foreground);
	display: inline-flex; }
.zo-content-box__icon svg { width: 24px; height: 24px; display: block; }
/* letter-spacing explizit 0: der Titel darf ein <div> ODER ein Heading sein (Lernziele auf der PDP,
   #152). Ohne die Zeile bekäme nur die Heading-Variante die globale heading-Regel (0.01em) und
   beide Ausprägungen liefen optisch auseinander. Figma führt den Titel mit ls 0. */
.zo-content-box__title { margin: 0; font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 26px; letter-spacing: 0;
	color: var(--wp--preset--color--foreground); }
.zo-content-box__body { margin: 0; font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 22px;
	color: var(--wp--preset--color--foreground); }
/* Type → Item-Hintergrund (Figma-Fills = Theme-Token, exakt). */
.zo-content-box--neutral   .zo-content-box__item { background: var(--wp--preset--color--white); }
.zo-content-box--webinar   .zo-content-box__item { background: var(--wp--preset--color--accent-turquoise); }
.zo-content-box--kurse     .zo-content-box__item { background: var(--wp--preset--color--accent-orange); }
.zo-content-box--bundles   .zo-content-box__item { background: var(--wp--preset--color--accent-yellow); }
.zo-content-box--promotion .zo-content-box__item { background: var(--wp--preset--color--accent-lilac); }
@container (min-width: 640px) {
	.zo-content-box__grid { grid-template-columns: repeat(2, 1fr); }
}
@container (min-width: 1024px) {
	.zo-content-box__grid { grid-template-columns: repeat(4, 1fr); }
	.zo-content-box__item { gap: var(--wp--preset--spacing--30); /* 16 */ }
}

/* ============================================================
   Component: Number Counter  (zo/number-counter + zo/number-counter-item)
   Figma 4510-31385 (COMPONENT_SET Viewport=XL/LG/MD/SM · Item Style=Airy/Dense).
   Spec: docs/figma-specs/number-counter.md  ·  Sync 2026-08-10 (#162)
   Eine Zeile gleich breiter Zahl-Boxen (variable Anzahl → 1fr je Item), unter Container 640
   zwei pro Zeile. Trenner überall exakt 1px: Grid-Gap 1px auf grauem Grund + 1px-Außenrahmen
   (das Referenz-PNG kollabiert die Item-Strokes, naive Item-Borders ergäben 2px).
   Zeile = --zo-rail-w (Grid-Foundation #128, keine eigene Rail).
   States: n/a (redaktionell, kein Hover/Focus/Leer-Zustand — Inhalt via InnerBlocks).
   Breakpoints: Container 640 (2 Spalten → eine Zeile) / 1024 (Dense → Airy).
   ============================================================ */
.zo-number-counter, .zo-number-counter * { box-sizing: border-box; }
/* container-type misst den Block → Grid + Rail liegen auf __grid (Muster .zo-content-box). */
.zo-number-counter { container-type: inline-size; }
.zo-number-counter__grid { width: var(--zo-rail-w); margin-inline: auto;
	display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
	background: var(--wp--preset--color--grey-mid);
	border: 1px solid var(--wp--preset--color--grey-mid); }
.zo-number-counter__item { display: flex; flex-direction: column; align-items: center; justify-content: center;
	gap: var(--wp--preset--spacing--10); /* 4 */ text-align: center;
	background: var(--wp--preset--color--white); border-radius: 0;
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30); /* Dense 24/16 */ }
/* Ungerade Anzahl im 2-Spalten-Fall: letzte Box über beide Spalten, sonst schiene der graue
   Grund als leere Zelle durch (Figma zeigt nur den 4er-Fall — Annahme, Spec §Annahmen). */
.zo-number-counter__item:nth-child(odd):last-child { grid-column: 1 / -1; }
.zo-number-counter__number { margin: 0; font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--24); font-weight: 700; line-height: 32px; letter-spacing: 0;
	color: var(--wp--preset--color--primary); }
.zo-number-counter__label { margin: 0; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; letter-spacing: 0.01em;
	color: var(--wp--preset--color--grey); }
@container (min-width: 640px) {
	.zo-number-counter__grid { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 1fr; }
	.zo-number-counter__item:nth-child(odd):last-child { grid-column: auto; }
}
@container (min-width: 1024px) {
	.zo-number-counter__item { padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40); } /* Airy 40/24 */
	/* custom--32 statt preset large: large ist fluid (clamp) und faellt bei 1024 auf 27.5px. */
	.zo-number-counter__number { font-size: var(--wp--custom--font-size--32); line-height: 42px; }
	.zo-number-counter__label { font-size: var(--wp--preset--font-size--small); /* 14 */ line-height: 20px; }
}

/* ============================================================
   Component: Text Columns  (zo/text-columns)
   Figma 4573-37221 (PDP-Textblock, Container 1360 im 1440-Artboard).
   Spec: docs/figma-specs/text-columns.md  ·  Sync 2026-07-24 (#80)
   Validated #366 against approved Figma 6503:97080 "Text Combo" (6770:89516 XL / 6770:89578 LG /
   6770:98676 MD): Lernziele column fixed 432, Freitext fills, column gap 80 (XL 816/80/432,
   LG 448/80/432); below 1024 stacked (Freitext on top), stack gap 32. Content-Cap = wideSize 1328 (Grid #128), Seiten-Inset via Rail-Alias (16/24/32).
   States: n/a (redaktionell, kein Hover/Focus/Leer-Zustand — Inhalt via RichText/InnerBlocks).
   Breakpoints: Container 1024 (Reflow).
   ============================================================ */
.zo-text-columns, .zo-text-columns * { box-sizing: border-box; }
/* container-type misst den (full-width) Block → Reflow-Schwelle 1024 am Viewport;
   Breiten-Cap + Grid liegen auf __row (analog .zo-content-box__grid). */
.zo-text-columns { container-type: inline-size; }
.zo-text-columns__row { width: var(--zo-rail-w);
	margin-inline: auto; display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--50); /* 32 stack gap (Figma 6770:98676, #366) */ }
.zo-text-columns__body { font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium); font-weight: 500;
	line-height: 22px; color: var(--wp--preset--color--foreground); }
.zo-text-columns__body > :first-child { margin-top: 0; }
.zo-text-columns__body > :last-child { margin-bottom: 0; }
.zo-text-columns__aside { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--30); /* heading -> list 16 (Heading pad-bottom, Figma 6770:89516, #366) */ }
.zo-text-columns__heading { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--24);
	font-weight: 700; line-height: 32px; /* Figma 6770:89516, #366 */ color: var(--wp--preset--color--foreground); }
/* Bullet-Liste (Core-list): scharfkantiger 3×3-Marker, Text-Inset 11, Item-Gap 8 (Figma 4573-37221). */
.zo-text-columns__list ul { list-style: none; margin: 0; padding: 0;
	display: flex; flex-direction: column; gap: var(--wp--preset--spacing--20); /* 8 */ }
.zo-text-columns__list li { position: relative; margin: 0; padding-left: 11px;
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 22px;
	color: var(--wp--preset--color--foreground); }
.zo-text-columns__list li::before { content: ""; position: absolute; left: 0; top: 9px;
	width: 3px; height: 3px; background: var(--wp--preset--color--foreground); border-radius: 0; }
@container (min-width: 1024px) {
	/* Zwei-Spalten-Raster nur MIT Lernziele-Spalte (Aside). Ohne Aside bleibt die __row
	   einspaltig und der Freitext läuft über die volle Zeilenbreite statt schmal+linksbündig
	   in der 787er-Spalte zu hängen (Philipp #88). Generisch für alle .zo-text-columns. */
	.zo-text-columns__row:has(.zo-text-columns__aside) { grid-template-columns: minmax(0, 1fr) 432px; gap: 80px; /* Figma 6770:89516 (#366) */
		align-items: start; }
}

/* ============================================================
   Component: Einstiegskurs  (zo/section-einstiegskurs, Pattern)
   Figma 4573-37273 (Feature-Block im PDP-Frame 4573-37150).
   Spec: docs/figma-specs/einstiegskurs.md  ·  Sync 2026-07-24 (#65)
   XL: zwei Spalten flush, Bild fest 432, Karte füllt (Figma 6503:97080 "Teaser universal"
   6761:86002 XL 896/432, 6770:89581 LG 528/432 — #366; vorher 917fr/443fr), unter 1024 einspaltig
   gestapelt (Karte oben / Bild unten). Content-Cap = wideSize 1328 (Grid #128), Seiten-Inset via Rail-Alias (16/24/32).
   Render-Falle: Content→Button-Gap = 60 (absolute Position), NICHT itemSpacing 80.
   States: Button :hover / :focus-visible (definiert); sonst n/a (redaktioneller Content).
   Breakpoints: Container 1024 (Reflow).
   ============================================================ */
.zo-einstiegskurs, .zo-einstiegskurs * { box-sizing: border-box; }
/* container-type misst den (full-width) Block → Reflow-Schwelle 1024 am Viewport;
   Breiten-Cap + Grid liegen auf __row (analog .zo-content-box__grid / .zo-text-columns__row). */
.zo-einstiegskurs { container-type: inline-size;
	--zo-ek-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.9999 15.1709L19.1928 5.97705L20.6071 7.39126L9.9999 17.9993L3.63599 11.6354L5.0502 10.2212L9.9999 15.1709Z'/%3E%3C/svg%3E"); }
/* WP-Flow-Margins innerhalb neutralisieren — Abstände kommen ausschließlich aus flex-gap. */
.zo-einstiegskurs__card, .zo-einstiegskurs__content, .zo-einstiegskurs__intro, .zo-einstiegskurs__lead,
.zo-einstiegskurs__heading, .zo-einstiegskurs__subhead, .zo-einstiegskurs__body, .zo-einstiegskurs__list,
.zo-einstiegskurs__cta, .zo-einstiegskurs__media { margin: 0; }
/* Breite/Zentrierung kommen aus .zo-container im Markup (Phase-2-Umzug #131, vorher eigener
   --zo-rail-w-Cap — gleiche Formel, aber Rail-Alias statt Foundation, content-rail.md §Offen). */
.zo-einstiegskurs__row { display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--60); /* 40 (Stapel-Gap) */ }
/* Peach-Karte: Content oben, Button unten (Gap 60 = absolute Figma-Position). */
.zo-einstiegskurs__card { display: flex; flex-direction: column; gap: 60px; /* Content→Button, Figma-Render */
	background: var(--wp--preset--color--accent-orange); border-radius: 0;
	padding: var(--wp--preset--spacing--60); /* 40 (mobil symmetrisch) */ }
.zo-einstiegskurs__content { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--50); /* 32 */ }
.zo-einstiegskurs__intro { display: flex; flex-direction: column; gap: 12px; /* Textgruppe → Liste (Figma 4573-37273) */ }
.zo-einstiegskurs__lead { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--20); /* 8 */ }
/* Typo der H2 kommt aus .zo-section-heading (#152) — hier bewusst keine zweite Skala. */
.zo-einstiegskurs__subhead { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--18);
	font-weight: 700; line-height: 21.6px; color: var(--wp--preset--color--foreground); }
.zo-einstiegskurs__body { font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium);
	font-weight: 500; line-height: 22.4px; color: var(--wp--preset--color--foreground); }
/* Check-Liste (Core-list): check-line-Marker per mask, Text-Inset 26 (Icon 18 + Gap 8), Item-Gap 6. */
.zo-einstiegskurs__list { list-style: none; padding: 0;
	display: flex; flex-direction: column; gap: 6px; /* Item→Item (Figma 4573-37273) */ }
.zo-einstiegskurs__list li { position: relative; margin: 0; padding-left: 26px;
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 22px;
	color: var(--wp--preset--color--foreground); }
.zo-einstiegskurs__list li::before { content: ""; position: absolute; left: 0; top: 3px;
	width: 18px; height: 18px; background: var(--wp--preset--color--foreground);
	-webkit-mask: var(--zo-ek-check) center / contain no-repeat; mask: var(--zo-ek-check) center / contain no-repeat; }
/* CTA-Button (Core-Button, scharfkantig, feste Höhe 64 = Figma FIXED). */
.zo-einstiegskurs__cta .wp-block-button__link { display: inline-flex; align-items: center;
	min-height: 64px; padding: 0 var(--wp--preset--spacing--40); /* 24 */ border-radius: 0;
	background-color: var(--wp--preset--color--primary); color: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--body); font-weight: 500; font-size: var(--wp--preset--font-size--medium); line-height: 1;
	transition: filter .15s ease; }
.zo-einstiegskurs__cta .wp-block-button__link:hover { filter: brightness(1.08); }
.zo-einstiegskurs__cta .wp-block-button__link:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }
/* Bild: gestapelt 3/2 (mobil), ab 1024 über volle Kartenhöhe. */
.zo-einstiegskurs__media { overflow: hidden; aspect-ratio: 3 / 2; }
.zo-einstiegskurs__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
@container (min-width: 1024px) {
	.zo-einstiegskurs__row { grid-template-columns: minmax(0, 1fr) 432px; gap: 0; align-items: stretch; /* Bild bündig, volle Höhe */ }
	.zo-einstiegskurs__card { padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--80) var(--wp--preset--spacing--60) var(--wp--preset--spacing--60); /* T40 R100 B40 L40 */ }
	.zo-einstiegskurs__media { aspect-ratio: auto; height: 100%; }
}

/* Kombipreis banner of a webinar series (#395, inc/webinar-series.php): same Figma component
   "Teaser universal" 6761:86002 as the Einstiegskurs banner, so it reuses the classes above.
   Card colour = Bundles yellow (Content Box spec, #FFEFA0). The date selects copy the PDP
   header select ("Termin finden": 48 high, primary border, calendar left, chevron right). */
.zo-series .zo-einstiegskurs__card { background: var(--wp--preset--color--accent-yellow); }
.zo-einstiegskurs__row--solo { grid-template-columns: 1fr; }
.zo-series {
	--zo-series-icon-cal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 1V3H15V1H17V3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H7V1H9ZM20 11H4V19H20V11ZM7 5H4V9H20V5H17V7H15V5H9V7H7V5Z'/%3E%3C/svg%3E");
	--zo-series-icon-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
}
.zo-series__modules { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--30); /* 16 */ margin: 0; }
.zo-series__module { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--20); /* 8 */ }
.zo-series__label { font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small);
	font-weight: 700; line-height: 20px; color: var(--wp--preset--color--foreground); }
.zo-series__select { position: relative; }
.zo-series__select select { appearance: none; -webkit-appearance: none; -moz-appearance: none;
	display: block; width: 100%; height: 48px; margin: 0; padding: 0 44px; border-radius: 0;
	/* !important: a WC Blocks rule paints a second chevron as background-image (same fix as the PDP header select). */
	background-color: var(--wp--preset--color--white); background-image: none !important;
	border: 1px solid var(--wp--preset--color--primary); color: var(--wp--preset--color--primary);
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); line-height: 20px; font-weight: 500; cursor: pointer; }
.zo-series__select select:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }
.zo-series__select::before, .zo-series__select::after { content: ""; position: absolute; top: 50%; transform: translateY(-50%);
	width: 16px; height: 16px; pointer-events: none; background-color: var(--wp--preset--color--primary); }
.zo-series__select::before { left: 16px; -webkit-mask: var(--zo-series-icon-cal) center / contain no-repeat; mask: var(--zo-series-icon-cal) center / contain no-repeat; }
.zo-series__select::after { right: 15px; width: 18px; height: 18px;
	-webkit-mask: var(--zo-series-icon-chev) center / contain no-repeat; mask: var(--zo-series-icon-chev) center / contain no-repeat; }
.zo-series .zo-einstiegskurs__cta .wp-block-button__link { border: 0; cursor: pointer; }

/* ============================================================
   Component: Card Article  (Magazin-Teaser, PDP „Mehr zum Thema")
   Figma COMPONENT_SET „Card Article" 4948-16636 (2026-09-24, #351): LG+ 432x466,49
   (Body 250) · SM+ 288x348,33 (Body 204). Link = Action Link Lila Trailing (4512-33753,
   MD on LG+, SM on SM+). Scharfkantig (Marke).
   States: :hover (link violet-dark, no underline) / :focus-visible am ganzen Karten-Link.
           leer/laden/fehler: n/a (datengetriebene Karte, leere Felder entfallen).
   Breakpoints (@media): SM+ <1024 · LG+ ≥1024 (viewport, like Card Product #334).
   ============================================================ */
.zo-card-article, .zo-card-article * { box-sizing: border-box; }
.zo-card-article { display: flex; flex-direction: column; background: var(--wp--preset--color--white);
	color: inherit; text-decoration: none; }
.zo-card-article__media { position: relative; aspect-ratio: 2 / 1; overflow: hidden; background: var(--wp--preset--color--paper); }
/* Media holds its 2:1 hard: img absolute so image attributes (intrinsic ratio) can never
   stretch the wrapper height — same pattern as .zo-kat-card__media (#293). */
.zo-card-article__media img, .zo-card-article__img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
/* flex: 1 + space-between: in stretched grid rows the link sits on the bottom edge like
   the Figma body (FIXED, SPACE_BETWEEN); min-height = Figma body, content may grow it. */
.zo-card-article__body { flex: 1 0 auto; display: flex; flex-direction: column; justify-content: space-between; gap: 24px; padding: 24px; min-height: 250px; /* Frame 1171280507 */ }
.zo-card-article__text { display: flex; flex-direction: column; gap: 12px; /* Flag -> Text (Frame 1171280504) */ }
.zo-card-article__flags { display: flex; flex-wrap: wrap; gap: 8px; }
.zo-card-article__lines { display: flex; flex-direction: column; gap: 8px; /* Titel -> Text (Frame 1171280508) */ }
.zo-card-article__title { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--20); line-height: 1.3; font-weight: 700; }
.zo-card-article__excerpt { margin: 0; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); line-height: 1.4286; font-weight: 500; letter-spacing: 0.01em; }
/* Link = Action Link component (look + SM fallback from the shared rule, #359); MD stage
   from 1024 below. The card <a> carries hover/focus. */
.zo-card-article__link { align-self: flex-start; }
.zo-card-article:hover .zo-card-article__link { color: var(--wp--custom--color--violet-dark); }
/* Variant SM+ below viewport 1024 (4948-17479): pad 16, gaps 16/6, title 16/22,
   excerpt 12/16, link = Action Link SM (14/20, gap 4, icon 16 — the component fallback).
   Flags 20/12 come from the shared .zo-kat-flag SM rule. */
@media (max-width: 1023.98px) {
	.zo-card-article__body { gap: 16px; padding: 16px; min-height: 204px; }
	.zo-card-article__lines { gap: 6px; }
	.zo-card-article__title { font-size: var(--wp--preset--font-size--medium); line-height: 1.375; }
	.zo-card-article__excerpt { font-size: var(--wp--custom--font-size--12); line-height: 1.3333; }
}
@media (min-width: 1024px) {
	/* Action Link MD trailing: 16/22 · icon 18 · gap 6 */
	.zo-card-article__link { --zo-action-link-font-size: var(--wp--preset--font-size--medium); --zo-action-link-line-height: 22px; --zo-action-link-icon: 18px; --zo-action-link-gap: 6px; }
}
.zo-card-article:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }
/* 3-up Grid (Frame 1171280513: 3x432, gap 15), Reflow per Container-Query. */
.zo-cards-article { display: grid; grid-template-columns: 1fr; gap: 15px; container-type: inline-size; }
@container (min-width: 700px) { .zo-cards-article { grid-template-columns: repeat(2, 1fr); } }
@container (min-width: 1000px) { .zo-cards-article { grid-template-columns: repeat(3, 1fr); } }

/* ============================================================
   Component: Card Expert  (Dozent:innen-Kachel)
   Figma COMPONENT_SET „Card Expert" 4007:10300 (dev-ready) — GENAU ZWEI Varianten,
   Umschaltpunkt LG (1024). Abruf/Sync 2026-08-07 (#153):
     Viewport=SM+  288 x 322 · Media 288x144 · Body-Pad 16 · Gap 24 (SPACE_BETWEEN)
                   Name 16/700/22 · Rolle 12/500/16 · Bio 12/500/16 · Link 14/700/20 · Icon 16
     Viewport=LG+  432 x 432 · Media 432x216 · Body-Pad 24 · Gap 40 (SPACE_BETWEEN)
                   Name 20/700/26 · Rolle 12/500/16 · Bio 14/500/20 · Link 16/700/22 · Icon 18
   Die Karte ist in Figma HOEHEN-FIX (beide Frames FIXED) und verteilt den Rest per
   SPACE_BETWEEN — darum height + justify-content hier, nicht inhaltsgetrieben.
   Der frueher hier verbaute Zwischenwert 309 existiert in Figma NICHT (#153).
   Container fuer die Variante ist der jeweilige Rahmen (.zo-card-carousel bzw.
   .zo-card-carousel-block / .zo-product-grid--experts, alle container-type);
   ohne Container greift die SM+-Variante.
   Photo since #344: round 189x189, centered (Figma Viewport3 7176:63272), text left.
   Spec: docs/figma-specs/expert-carousel.md
   States: :hover / :focus-visible am Profil-Link (definiert).
           leer/laden/fehler: n/a (datengetriebene Karte, leere Felder entfallen).
   ============================================================ */
.zo-card-expert, .zo-card-expert * { box-sizing: border-box; }
.zo-card-expert { display: flex; flex-direction: column; min-height: 336px; /* SM+ 288x336 (Figma 2564:3535, 2026-09-16) —
	min instead of fixed height: on wider mobile cards the 2:1 photo grows and a fixed
	height clipped the body/link (#290); content may extend the card, SPACE_BETWEEN fills the rest. */
	background: var(--wp--preset--color--white);
	border-radius: 0;                                    /* Marke scharfkantig */
	position: relative; overflow: hidden; }
/* Round centered photo (#344, Figma Card Expert Viewport3 7176:63272, 2026-09-24): 189x189 circle,
   top offset = card padding (16 SM+ / 24 LG+), same fixed size in every card width (B1a);
   card widths/grid unchanged, text stays left-aligned below. */
.zo-card-expert__media { flex: 0 0 auto; align-self: center; width: 189px; height: 189px;
	margin-top: var(--wp--preset--spacing--30);          /* 16 */
	border-radius: 50%;
	background: var(--wp--preset--color--paper); overflow: hidden; }
.zo-card-expert__media img,
.zo-card-expert__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.zo-card-expert__body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
	justify-content: space-between;                      /* Figma primaryAxisAlignItems SPACE_BETWEEN */
	gap: var(--wp--preset--spacing--30);                 /* 16 (Figma itemSpacing SM+, 2026-09-16) */
	padding: var(--wp--preset--spacing--30);             /* 16 */ }
.zo-card-expert__text { display: flex; flex-direction: column; gap: 12px; }
.zo-card-expert__names { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--10); /* 4 */ }
.zo-card-expert__name { margin: 0; font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 22px; color: var(--wp--preset--color--foreground);
	display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; /* Figma maxLines 2 */ }
.zo-card-expert__role { margin: 0; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px;
	color: var(--wp--preset--color--grey);
	display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; /* Figma maxLines 1 */ }
/* feste Figma-Größen, NICHT die fluiden theme.json-Presets (small=14, medium=16 sind fix). */
.zo-card-expert__bio { margin: 0; font-size: var(--wp--custom--font-size--12);
	font-weight: 500; line-height: 16px; color: var(--wp--preset--color--foreground);
	display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; /* Figma maxLines 3 (SM+, 2026-09-16) */ }
.zo-card-expert__link { display: inline-flex; align-items: center; gap: var(--wp--preset--spacing--20); /* 8 */
	font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px;
	color: var(--wp--preset--color--primary); text-decoration: none; }
.zo-card-expert__link::after { content: ""; position: absolute; inset: 0; }  /* ganze Karte klickbar */
.zo-card-expert__link svg { width: 16px; height: 16px; flex: 0 0 auto; }
.zo-card-expert:hover .zo-card-expert__link { color: var(--wp--custom--color--violet-dark); }  /* Action Link hover (#351) */
.zo-card-expert:focus-within { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.zo-card-expert__link:focus-visible { outline: none; }
/* Variante „Viewport=LG+" (Figma 4007:10300). Container = Rahmen der Karte (s. o.). */
@container (min-width: 1024px) {
	.zo-card-expert { min-height: 432px; }
	.zo-card-expert__media { margin-top: var(--wp--preset--spacing--40); }   /* 24 */
	.zo-card-expert__body { gap: var(--wp--preset--spacing--40);   /* 24 (Figma itemSpacing LG+, 2026-09-16) */
		padding: var(--wp--preset--spacing--40); }                 /* 24 */
	.zo-card-expert__name { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-card-expert__bio { font-size: var(--wp--preset--font-size--small); line-height: 20px;
		-webkit-line-clamp: 2; /* Figma maxLines 2 on LG+ */ }
	.zo-card-expert__link { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-card-expert__link svg { width: 18px; height: 18px; }
}

/* ============================================================
   Component: Carousel-Arrows  (geteilte Pfeil-Buttons aller Karussells)
   Figma Arrow-Control 48x48 (Card-Carousel-Shells, z. B. 5301-15652).
   Markup: zo_carousel_arrow() (inc/carousel-shared.php); genutzt von card-,
   testimonial- und image-carousel. Bis #222 lag der Abschnitt im Expert-Carousel
   (zo/expert-carousel, #59) — der Block ist abgeschafft, die Pfeile bleiben.
   States: :hover / :focus-visible / :disabled (Scroll-Enden, via view.js).
   ============================================================ */
.zo-carousel-arrow { display: inline-flex; align-items: center; justify-content: center;
	width: 48px; height: 48px; padding: 0; border: 4px solid var(--wp--preset--color--primary);
	border-radius: 100%; background: transparent; color: var(--wp--preset--color--primary);
	cursor: pointer; }
.zo-carousel-arrow svg { width: 18px; height: 18px; }
.zo-carousel-arrow--prev { border-color: var(--wp--preset--color--grey-mid); color: var(--wp--preset--color--grey-mid); }
.zo-carousel-arrow:hover { background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); border-color: var(--wp--preset--color--primary); }
.zo-carousel-arrow:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.zo-carousel-arrow:disabled { border-color: var(--wp--preset--color--grey-mid); color: var(--wp--preset--color--grey-mid);
	background: transparent; cursor: default; }

/* ============================================================
   Component: Card Testimonial  (Teilnehmer-Stimme, randlos)
   Figma „Testimonial Section .item" 5065-19315.
   Spec: docs/figma-specs/testimonial-carousel.md  ·  Sync 2026-07-21 (#60)
   States: n/a (statische, datengetriebene Karte; leere Felder entfallen).
   1:1-Grenze: Höhe inhaltsabhängig (auto); Figma zeigt fixes Lorem.
   Fonts als feste px (nicht die fluiden theme.json-Presets), damit die Messung sitzt.
   ============================================================ */
.zo-card-testimonial, .zo-card-testimonial * { box-sizing: border-box; }
.zo-card-testimonial { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--50); /* 32 (item-Gap XL/LG) */
	padding-top: var(--wp--preset--spacing--30);         /* 16 (XL/LG) */
	padding-right: var(--wp--preset--spacing--60);       /* 40 (XL/LG) */ }
.zo-card-testimonial__quote { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--40); /* 24 (XL/LG) */ }
.zo-card-testimonial__quote-icon { display: block; color: var(--wp--preset--color--primary); }
.zo-card-testimonial__quote-icon svg { display: block; width: 24px; height: 24px; }
.zo-card-testimonial__text { margin: 0; font-style: italic; font-weight: 500;
	font-size: var(--wp--custom--font-size--24); line-height: 32px; color: var(--wp--preset--color--foreground); }
.zo-card-testimonial__author { display: flex; align-items: center; gap: 6px; margin: 0; }
.zo-card-testimonial__avatar { display: block; flex: 0 0 auto; width: 48px; height: 48px;
	border-radius: 50%; overflow: hidden; background: var(--wp--preset--color--grey-light);
	box-shadow: 0 0 0 2px var(--wp--preset--color--white); }
.zo-card-testimonial__avatar img,
.zo-card-testimonial__avatar-img { display: block; width: 100%; height: 100%; object-fit: cover; }
.zo-card-testimonial__meta { display: flex; flex-direction: column; }
.zo-card-testimonial__name { font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 22px;
	color: var(--wp--preset--color--foreground); }
.zo-card-testimonial__org { font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px;
	color: var(--wp--preset--color--grey); }

/* ============================================================
   Component: Testimonial-Carousel  (Teilnehmer-Stimmen, horizontal scrollbar)
   Figma Component-Set 5065-19315 (Viewports XL/LG/MD/SM). Shell-Mechanik =
   zo/expert-carousel (Arrows teilen .zo-carousel-arrow).
   Spec: docs/figma-specs/testimonial-carousel.md  ·  Sync 2026-07-21 (#60)
   States: Arrows :hover / :focus-visible / disabled (Scroll-Enden, via view.js).
   Breakpoints (Container-Query): <640 SM (Card 250, ohne Arrows) · >=640 MD (500, ohne Arrows) ·
           >=1024 LG (420, Arrows) · >=1360 XL (600, Arrows).
   Die H2 stuft NICHT mehr hier, sondern über .zo-section-heading am Viewport (#152).
   ============================================================ */
.zo-testimonial-carousel, .zo-testimonial-carousel * { box-sizing: border-box; }
/* container-type misst die Content-Box → Wrapper bleibt padding-frei (Rand auf head+track). */
.zo-testimonial-carousel { container-type: inline-size; }
.zo-testimonial-carousel__head { display: flex; align-items: flex-start; justify-content: space-between;
	gap: 16px; margin-bottom: 16px; padding-inline: var(--zo-rail-bleed); /* kanonische Rail (#99) */ }
/* Typo der H2 kommt aus .zo-section-heading (#152). */
.zo-testimonial-carousel__controls { display: none; flex: 0 0 auto; gap: 12px; }
.zo-testimonial-carousel__track { display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x mandatory;
	scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-inline: var(--zo-rail-bleed); /* kanonische Rail (#99) */
	/* scroll-padding = Rand, sonst zieht mandatory-Snap die erste Karte bündig an die
	   Wrapper-Kante und frisst die Einrückung → Karte fluchtet dann nicht mit der Heading. */
	scroll-padding-inline: var(--zo-rail-bleed); }
.zo-testimonial-carousel__track::-webkit-scrollbar { display: none; }
.zo-testimonial-carousel__track > .zo-card-testimonial { flex: 0 0 250px; scroll-snap-align: start; }
.zo-testimonial-carousel__empty { margin: 0; color: var(--wp--preset--color--grey); }
/* SM/MD-Karte: kleinere Fonts + engere Gaps + kein Top-Pad (Node 5065-19315 Frame ...755). */
.zo-testimonial-carousel__track > .zo-card-testimonial { gap: var(--wp--preset--spacing--40); /* 24 */
	padding-top: 0; padding-right: var(--wp--preset--spacing--40); /* 24 */ }
.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__quote { gap: var(--wp--preset--spacing--30); /* 16 */ }
.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__quote-icon svg { width: 18px; height: 18px; }
.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__text { font-size: var(--wp--custom--font-size--18); line-height: 24px; }
.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__name { font-size: var(--wp--preset--font-size--small); line-height: 20px; }

@container (min-width: 640px) {
	.zo-testimonial-carousel__head { margin-bottom: 24px; }
	.zo-testimonial-carousel__track { gap: 16px; }
	.zo-testimonial-carousel__track > .zo-card-testimonial { flex-basis: 500px; }
}
@container (min-width: 1024px) {
	.zo-testimonial-carousel__head { margin-bottom: 32px; }
	.zo-testimonial-carousel.is-scrollable .zo-testimonial-carousel__controls { display: flex; }
	/* LG/XL-Karte: größere Fonts + weitere Gaps + Top-Pad 16 / Rechts-Pad 40 (Frame ...754). */
	.zo-testimonial-carousel__track > .zo-card-testimonial { flex-basis: 420px;
		gap: var(--wp--preset--spacing--50); /* 32 */
		padding-top: var(--wp--preset--spacing--30);     /* 16 */
		padding-right: var(--wp--preset--spacing--60); /* 40 */ }
	.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__quote { gap: var(--wp--preset--spacing--40); /* 24 */ }
	.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__quote-icon svg { width: 24px; height: 24px; }
	.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__text { font-size: var(--wp--custom--font-size--24); line-height: 32px; }
	.zo-testimonial-carousel__track > .zo-card-testimonial .zo-card-testimonial__name { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
}
/* XL-Schwelle bewusst 1360 statt 1440: der Container ist der full-bleed Sektions-Block, der bei
   klassischer Scrollbar ~15px unter der Fensterbreite bleibt. Beleg, dass die Schwelle erreichbar
   ist (#153, gemessen 2026-08-07 gegen zo-worker): Container-Breite = 1440 auf der PDP bei
   Viewport 1440, 1440 im Demo-Frame .zo-tc-demo__frame--xl. Karte 600 = Figma 5065-19315 XL. */
@container (min-width: 1360px) {
	.zo-testimonial-carousel__track > .zo-card-testimonial { flex-basis: 600px; }
}

/* ============================================================
   Component: Card-Carousel  (.zo-card-carousel — Karten-Karussell)
   Figma-Komponente „Card Carousel standard/colored". Instanzen: Profilseite 5301-15694 (#77)
   sowie Artikel-Abschluss 5860-66513 „Passende Angebote" / 5860-66514 „Weiterlesen" (#150).
   Head (H2 + arrows 2x48, gap 12) · track gap 16 · card widths staged per viewport
   (4969-20570, 2026-09-16): SM/MD 250 · LG/XL 3 per rail = 309,33@1024 - 432@1440.
   Karten-Höhen kommen aus den Karten-Komponenten, nicht aus dem Karussell:
   Card Product 470 (COMPONENT_SET 5050-19905, Media 216 + Body 254 — seit #197; bis dahin
   482) · Card Article 466,49 (COMPONENT_SET 4948-16636, Media 216,49 + Body 250). Bis #150
   stand hier für beide 482 — die Zahl der Produkt-Karte war beim Bau der Profilseite auf die
   Artikel-Karte mitübernommen worden.
   Shell-Mechanik = zo/expert-carousel (zo-carousel-view.js, Arrows .zo-carousel-arrow);
   Hülle rendert zo_card_carousel() (inc/carousel-shared.php). Farbe/Padding der Sektion liegt
   am Sektions-Scope (.zo-author-section--kurse/--beitraege, .zo-article-outro--*, PAGES).
   Spec: docs/figma-specs/expert-profile.md · docs/figma-specs/article-outro.md.
   States: Arrows :hover / :focus-visible / :disabled (Scroll-Enden, via view.js).
   Breakpoints (container query on the named container zo-card-carousel): arrows >=1024;
   H2 steps via .zo-section-heading at the viewport (#152). Card sizes: base 250, >=1024
   fluid 3-per-rail (#293; the former fixed 432 came from the XL-only design state).
   Card internals follow the VIEWPORT STAGE, not the card width (4969-20570 LG shows the
   LG+ layout on a 309px card): >=1024 the track card drops its own containment so its
   width<432 query measures the carousel and the SM+ block stops applying.
   Spec: docs/figma-specs/card-carousel.md §Responsive Karten-Staffel.
   ============================================================ */
.zo-card-carousel, .zo-card-carousel * { box-sizing: border-box; }
/* container-type misst die Content-Box → Wrapper bleibt padding-frei (Rand auf head+track). */
.zo-card-carousel { container-type: inline-size; container-name: zo-card-carousel; }
.zo-card-carousel__head { display: flex; align-items: flex-start; justify-content: space-between;
	gap: 16px; margin-bottom: 16px; padding-inline: var(--zo-rail-bleed); /* kanonische Rail (#99) */ }
/* Scroll shell only (grid variant keeps 16/24, measured #200): head->track 12/16/24 (4969-20570). */
.zo-card-carousel > .zo-card-carousel__head { margin-bottom: 12px; }
/* Typo der H2 kommt aus .zo-section-heading (#152). */
/* Optional short description (#396): H2 + intro as one column next to the arrows.
   Cap 960 and H2->intro 12/16/24 (viewport) mirror the optional heads of
   content-list/product-grid (#279); head->cards keeps the carousel's own spacing. */
.zo-card-carousel__titles { flex: 0 1 960px; min-width: 0; }
.zo-card-carousel__titles > * { margin: 0; }
.zo-card-carousel__titles > .zo-section-heading { margin-bottom: 12px; }
@media (min-width: 640px) {
	.zo-card-carousel__titles > .zo-section-heading { margin-bottom: 16px; }
}
@media (min-width: 1024px) {
	.zo-card-carousel__titles > .zo-section-heading { margin-bottom: 24px; }
}
.zo-card-carousel__controls { display: none; flex: 0 0 auto; gap: 12px; }
.zo-card-carousel__track { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory;
	scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-inline: var(--zo-rail-bleed); /* kanonische Rail (#99) */
	scroll-padding-inline: var(--zo-rail-bleed); }
.zo-card-carousel__track::-webkit-scrollbar { display: none; }
/* Room for the card hover shadow (#352): overflow-x:auto clips vertically too; padding is
   cancelled by the same negative margin, so no card or section moves. Top 12 = smallest
   head gap (scroll shell), so the controls above are never covered. */
.zo-card-carousel__track { padding-block: 12px 32px; margin-block: -12px -32px; }
/* Card heights are content-driven since #293: media 2:1 + fixed/min body height per card
   (Card Product body 220 SM+ / 254 LG+ -> 345/408,67/470 · Card Article body min 204,33/250). */
/* min-width: 0 — flex min-width:auto let unbreakable content push a card past its basis
   (hidden before #293 because the 432px basis fit everything). */
.zo-card-carousel__track > * { flex: 0 0 250px; min-width: 0; scroll-snap-align: start; } /* 4969-20570 SM/MD: Karte 250 */
/* Card Article in the track: fixed body height like the Figma frames (SM+ 204,33 / LG+ 250)
   with clamped lines (title 3/excerpt 2 on SM+, 2/2 on LG+ — 4948-16636), mirroring how
   .zo-kat-card fits its fixed body. Grid contexts (.zo-cards-article) stay content-driven. */
.zo-card-carousel__track > .zo-card-article .zo-card-article__body { height: 204.33px; overflow: hidden; }
.zo-card-carousel__track > .zo-card-article .zo-card-article__title { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.zo-card-carousel__track > .zo-card-article .zo-card-article__excerpt { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Card Expert kennt GENAU ZWEI Varianten (4007:10300, #153): SM+ 288×322 · LG+ 432×432 —
   die Breite schaltet deshalb mit der Container-Schwelle 1024 mit (bis #222 Regel des
   abgeschafften zo/expert-carousel; sonst staende eine 432er-Breite auf der 322er-SM-Karte). */
.zo-card-carousel__track > .zo-card-expert { flex-basis: 288px; }

@container (min-width: 640px) {
	.zo-card-carousel__head { margin-bottom: 24px; }
	.zo-card-carousel > .zo-card-carousel__head { margin-bottom: 16px; /* 4969-20570 MD */ }
}
@container (min-width: 1024px) {
	.zo-card-carousel__head { margin-bottom: 24px; /* 5301-15652: Kopf 76 = 52 + 24 */ }
	.zo-card-carousel > .zo-card-carousel__head { margin-bottom: 24px; /* 4969-20570 LG/XL */ }
	.zo-card-carousel.is-scrollable .zo-card-carousel__controls { display: flex; }
	/* 3 per rail, fluid: (rail - 2 gaps) / 3 = 309,33@1024 -> 432@1440 (4969-20570 LG/XL).
	   100% resolves against the track content box = rail (padding-inline is the bleed). */
	.zo-card-carousel__track > * { flex-basis: calc((100% - 32px) / 3); }
	/* Card Product needs no per-track override since #334: its variant switches on the
	   viewport (media query in §Card Product), so 309-432px cards keep LG+ here anyway. */
	/* Card Article LG+: fixed body 250 replaces the former fixed 466.49 card height —
	   total = width/2 + 250 = 466,49 at 432 (4948-16636), fluid below. Title 2 lines. */
	.zo-card-carousel__track > .zo-card-article .zo-card-article__body { height: 250px; }
	.zo-card-carousel__track > .zo-card-article .zo-card-article__title { -webkit-line-clamp: 2; }
	.zo-card-carousel__track > .zo-card-expert { flex-basis: 432px; }
}

/* Block-Wrapper zo/card-carousel (#164, Figma 4994-20269 „colored"): base + farbige Fläche.
   Farbe über die Tile-Indirektion --zo-tile-bg (Werte = theme.json-Palette, eine Farb-Quelle
   mit den zo-tile-*-Styles); horizontale Rail liegt in der Hülle (--zo-rail-bleed), der
   Wrapper trägt nur Fläche + vertikales Padding. Wrapper ist eigener Container, damit die
   Padding-Stufen an der realen Blockbreite schalten (alignfull = Viewport; Editor-Canvas
   entsprechend schmaler). Ohne Farbwahl (standard-Variante) kein Padding.
   Raster-Layout (#200): .zo-card-carousel-grid s. u. — Farbfläche/Padding gelten identisch.
   States: n/a (Wrapper ohne Interaktion; Arrows/Track s. Hülle oben).
   Breakpoints (Container-Query): 640 (MD) / 1024 (LG) / 1360 (XL, Muster Testimonial-XL). */
.zo-card-carousel-block { container-type: inline-size; }
.zo-card-carousel-block__inner--colored { background: var(--zo-tile-bg); padding-block: 24px; /* SM: 468 − 420 = 2×24 */ }
.zo-card-carousel-block--turquoise { --zo-tile-bg: var(--wp--preset--color--accent-turquoise); } /* Webinare #B8F7F3 */
.zo-card-carousel-block--orange    { --zo-tile-bg: var(--wp--preset--color--accent-orange); }    /* Kurse #FFD4B8 */
.zo-card-carousel-block--yellow    { --zo-tile-bg: var(--wp--preset--color--accent-yellow); }    /* Bundles #FFEFA0 */
.zo-card-carousel-block--lilac     { --zo-tile-bg: var(--wp--preset--color--accent-lilac); }     /* Angebote/Promotion #E0D6FF */
.zo-card-carousel-block__empty { padding-inline: var(--zo-rail-bleed); margin: 0; }

/* Raster-Layout des Blocks (#200, Schalter wie partner-grid): dieselben Karten im
   Katalog-Raster statt im Scroll-Track. Kopf = .zo-card-carousel__head (Rail + 16/24er
   Abstand aus der Hülle, ohne Pfeile); das Raster trägt die kanonische Rail selbst
   (padding-inline statt des 40er-Katalog-margin-top) und spannt jede Karte über 4
   Foundation-Spalten — 3/2/1 pro Reihe wie .zo-kat-grid im Katalog (XL 432 · LG 309 · MD/SM 288).
   States: n/a (Karten bringen ihre eigenen mit). Breakpoints: Foundation (--zo-grid-columns). */
.zo-card-carousel-grid .zo-kat-grid { margin-top: 0; padding-inline: var(--zo-rail-bleed); }
.zo-card-carousel-grid .zo-kat-grid > * { grid-column: span 4; }

@container (min-width: 640px) {
	.zo-card-carousel-block__inner--colored { padding-block: 32px; /* MD: 468 − 404 = 2×32 */ }
}
@container (min-width: 1024px) {
	.zo-card-carousel-block__inner--colored { padding-block: 40px; /* LG: 582,5 − 502,5 = 2×40 */ }
}
@container (min-width: 1360px) {
	.zo-card-carousel-block__inner--colored { padding-block: 56px; /* XL: 658 − 546 = 2×56 */ }
}

/* ============================================================
   Component: Bild-Carousel  (zo/image-carousel)
   Figma Component-Set 5806:630, No-Reihe (#226; Erstbau 4969-13612 #79, Hover-Arrows #190).
   Freie Bilder (InnerBlocks core/image), Overlay-Arrows nur LG/XL, Deko-Dots + Caption-Zeile.
   Track, Caption und Dots liegen auf der Grid-Foundation und clippen an BEIDEN Rasterkanten
   (Philipp #226 — ersetzt den #128-Anschnitt nach rechts). Rail-Padding auf __viewport/__footer,
   nicht auf dem Wrapper, damit @container die volle Blockbreite misst. Shell-Mechanik
   (Track-Scroll, Arrow-Step, disabled an den Enden) geteilt via assets/js/zo-carousel-view.js —
   Arrows teilen die Basisklasse .zo-carousel-arrow (Markup), aber eigene Optik (gefüllt).
   Spec: docs/figma-specs/image-carousel.md.
   States: :focus-visible/:disabled auf Arrows · Arrows nur bei Hover/Fokus sichtbar
   (Annotation 5806:630, #190) · Dots n/a (nicht interaktiv).
   Breakpoints (Container-Query): 640 (MD) / 1024 (LG, Arrows) / 1360 (XL).
   ============================================================ */
.zo-image-carousel, .zo-image-carousel * { box-sizing: border-box; }
.zo-image-carousel { container-type: inline-size; }
/* Rail auf dem Viewport: der Track (Scroll-Container) misst genau die Content-Breite und
   clippt die Karten an beiden Rasterkanten (#226). */
.zo-image-carousel__viewport { position: relative; padding-inline: var(--zo-rail-bleed); }
.zo-image-carousel__track { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory;
	scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.zo-image-carousel__track::-webkit-scrollbar { display: none; }
.zo-image-carousel__track > .wp-block-image { flex: 0 0 212px; margin: 0; scroll-snap-align: start;
	aspect-ratio: 4 / 3; overflow: hidden; border-radius: 0; }
.zo-image-carousel__track > .wp-block-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Pro-Karte-Caption von core/image ausblenden — sie wird zentral in der Caption-Zeile gespiegelt (#79). */
.zo-image-carousel__track > .wp-block-image figcaption { display: none; }

/* Overlay-Arrows (erst ab LG sichtbar, unten): Kreis primary (aktiv) / grey-mid (disabled),
   Icon in beiden States weiß (Set 5806:630 — kein transluzentes Overlay mehr wie in #79). */
.zo-image-carousel__arrow { display: none; position: absolute; top: 50%; transform: translateY(-50%);
	width: 48px; height: 48px; padding: 0; border: 0; border-radius: 100%;
	background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); cursor: pointer; }
.zo-image-carousel__arrow svg { width: 18px; height: 18px; }
.zo-image-carousel__arrow:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
/* color explizit: die geteilte .zo-carousel-arrow:disabled setzt sonst grey-mid → grau auf grau. */
.zo-image-carousel__arrow:disabled { background: var(--wp--preset--color--grey-mid);
	color: var(--wp--preset--color--white); cursor: default; }

/* Footer (Caption-Zeile + Dots) unter dem Track, auf der Rail. SM: Spalte — Caption linksbündig
   über zentrierten Dots. Ab MD: eine Zeile — Caption links, Dots rechtsbündig (Set 5806:630). */
.zo-image-carousel__footer { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--30); /* 16 */
	padding-inline: var(--zo-rail-bleed); margin-top: 12px; /* Strip→Bottom-Bar, Set-Gap SM/MD (kein Preset) */ }
/* Caption der aktiven Karte. Feste min-height (1 Zeile) gegen Layout-Sprung; leere Caption → leer.
   Wechsel per Fade (JS toggelt `.is-fading`). Typo Set: SM/MD 12/16, LG/XL 14/20, Figtree 500. */
.zo-image-carousel__caption { margin: 0; text-align: left; min-height: 16px;
	font-weight: 500; font-size: var(--wp--custom--font-size--12); line-height: 16px;
	color: var(--wp--preset--color--grey); transition: opacity .18s ease; }
.zo-image-carousel__caption.is-fading { opacity: 0; }

/* Scroll-Indikator-Dots: fix 5, iOS-Tapering 4/8/8/8/4, Gap 12. Aktiver Dot (JS: folgt dem
   Scroll-Fortschritt, #79) wird primary + volle Größe, sanft animiert. Ruhe-Farbe grey-mid. */
.zo-image-carousel__dots { display: flex; justify-content: center; align-items: center; gap: 12px; }
.zo-image-carousel__dot { width: 8px; height: 8px; border-radius: 100%;
	background: var(--wp--preset--color--grey-mid);
	transition: width .25s ease, height .25s ease, background-color .25s ease; }
.zo-image-carousel__dot:nth-child(1), .zo-image-carousel__dot:nth-child(5) { width: 4px; height: 4px; }
.zo-image-carousel__dot.is-active { width: 8px; height: 8px; background: var(--wp--preset--color--primary); }

@container (min-width: 640px) {
	.zo-image-carousel__track > .wp-block-image { flex-basis: 440px; }
	/* Footer wird zur Zeile: Caption links, Dots rechts auf der Rasterkante (Set: ab MD-Reihe). */
	.zo-image-carousel__footer { flex-direction: row; align-items: center; justify-content: space-between;
		gap: var(--wp--preset--spacing--40); /* 24 = Minimum, Luft macht space-between */ }
	.zo-image-carousel__caption { flex: 1 1 auto; }
	.zo-image-carousel__dots { flex: 0 0 auto; }
}
@container (min-width: 1024px) {
	.zo-image-carousel__track > .wp-block-image { flex-basis: 391px; }
	.zo-image-carousel__footer { margin-top: 16px; /* Strip→Bottom-Bar, Set-Gap LG/XL */ }
	.zo-image-carousel__caption { font-size: var(--wp--preset--font-size--small); line-height: 20px;
		min-height: 20px; }
	/* Arrows nur bei Hover/Fokus sichtbar (Annotation 5806:630, #190). Verstecken über opacity,
	   nicht visibility/display — sonst fielen die Buttons aus der Tab-Reihenfolge und
	   :focus-within könnte nie greifen (Karussell wäre per Tastatur unbedienbar). */
	.zo-image-carousel.is-scrollable .zo-image-carousel__arrow { display: inline-flex; opacity: 0;
		transition: opacity .18s ease; }
	.zo-image-carousel__viewport:hover .zo-image-carousel__arrow,
	.zo-image-carousel__viewport:focus-within .zo-image-carousel__arrow { opacity: 1; }
	/* Arrow-x aus der No-Reihe des Sets: prev 24 innerhalb der linken Rasterkante, next bündig
	   an der rechten (LG 56/992 · XL 80/1384 — Asymmetrie ist Set-Wahrheit, Spec §Arrows). */
	.zo-image-carousel__arrow.zo-carousel-arrow--prev { left: calc(var(--zo-rail-bleed) + 24px); }
	.zo-image-carousel__arrow.zo-carousel-arrow--next { right: var(--zo-rail-bleed); }
}
/* XL-Schwelle 1360 statt 1440 — s. Begruendung am Testimonial-Karussell (#153). */
@container (min-width: 1360px) {
	.zo-image-carousel__track > .wp-block-image { flex-basis: 544px; }
}

/* ============================================================
   Component: Partner-Karten  (zo/partner-grid + zo/partner-card)  — Issue #192
   Figma 6264-77967 (Karten) + Card-Grids-Canvas + 6462-87404 (Carousel), Update 18.08.:
   Card „Profile" 6265:78842 (LG+ 320×350: Logo 2:1 + Box 190 pad 24 · SM+ 288×314:
   Box 170 pad 16, Name 18/24) · Card „Teaser" 6379:81975 (quadratisch, nur Logo,
   Overlay-Pad 24/16/12 an LG+/MD/SM, Name 20/26 bzw. 16/22) · Grid Profile 6468:3531
   (XL 4 / LG 3 / MD 2 / SM 1 Spalten = span 3 bzw. 4 der 12er-Foundation) ·
   Grid Teaser 6462:86136 (XL 5 / LG 4 / MD 3 / SM 2 — komponenten-eigenes Raster,
   nicht 12-teilbar, XL: 5×252.8+4×16 = 1328) · Carousel 6382:708 (nur kompakt,
   Karten 240/224/180 an LG+/MD/SM, Arrows 48 grey-mid Overlay nur LG/XL bei
   Hover/Fokus, Dots wie zo/image-carousel). Spec: docs/figma-specs/partner-card.md.
   States: Overlay per :hover (hover-fähige Geräte) + .is-open (JS-Toggle)
   + :has(:focus-visible) — EINE lila Fläche (__panel/__content) statt Box + zweitem
   Overlay (#192-Review: Meta nur 1× im DOM, bewegt sich beim Öffnen nicht; Fläche
   fährt per transform hoch, Beschreibung klappt per grid-template-rows aus) ·
   :focus-visible auf __toggle/__close/__tap/Action-Link ·
   :disabled auf Arrows · Leer-Hinweis __empty · active n/a (kein Figma-State).
   Breakpoints: Viewport-MQ 640/1024/1440 — das Modul sitzt auf der Grid-Foundation
   (--zo-grid-columns/--zo-grid-margin stufen am Viewport, Begründung s. FAQ/#127);
   alle Spaltenstufen seit dem 18.08. Figma-belegt (Grid-Sets, ersetzt die Ableitung).
   ============================================================ */
.zo-partners, .zo-partners * { box-sizing: border-box; }

/* Raster: Spalten- UND Zeilen-Gap 16 (Figma: beide 16). */
.zo-partners__grid { display: grid; gap: var(--zo-grid-gutter); }
/* Ausgeklappt liegt auf der Foundation (Grid-Set 6468:3531): span 4 = SM 1 / MD 2 /
   LG 3 Karten je Zeile (4er-/8er-/12er-Grid), ab 1440 span 3 = 4 Karten (3×96+2×16 = 320).
   Team (#371) uses the same 4-column set (Figma 7176:67066 = instance of 6468:2848 XL:
   4×320 + 3×16 = 1328, row gap 16).
   Tracks are minmax(0, 1fr): plain 1fr = minmax(auto, 1fr) let an oversized card
   minimum widen the columns past the container (horizontal scrollbar, #371). */
.zo-partners__grid--expanded,
.zo-partners__grid--team { grid-template-columns: repeat(var(--zo-grid-columns), minmax(0, 1fr)); }
.zo-partners__grid--expanded > *,
.zo-partners__grid--team > * { grid-column: span 4; }
@media (min-width: 1440px) {
	.zo-partners__grid--expanded > *,
	.zo-partners__grid--team > * { grid-column: span 3; }
}
/* Kompakt: komponenten-eigenes Raster (Grid-Set 6462:86136 — SM 2 / MD 3 / LG 4 / XL 5,
   LG: 4×228+3×16 = 960 ✓). */
.zo-partners__grid--compact { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 640px) {
	.zo-partners__grid--compact { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
	.zo-partners__grid--compact { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1440px) {
	.zo-partners__grid--compact { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* --- Team (#371, Philipp B1a): Card Expert "Viewport3" (Figma 7176:63272, 2026-09-27)
   in every grid width — the only variant drawn for this grid (the set varies only the
   column count). Card 320 x HUG (425 with a 3-line text): padding 24, photo circle 189
   centred, gap 24 photo -> text -> link, name 20/26, role 12/16, text 14/20, link 16/22
   + icon 18. Figma sets no maxLines on the Viewport3 texts -> no clamping here.
   Height hugs the content (no 336/432 minimum); grid rows stretch, so the cards of a
   row are equally tall and the link sits at the bottom (SPACE_BETWEEN).
   States: :hover/:focus-visible from the expert card when linked; without link the
   card is static (no shadow, not clickable). Empty = __empty hint.
   Breakpoints: columns only (Foundation 4/8/12 at 640/1024, span 3 from 1440).
   Scoped on the card modifier, so grid and carousel (zo-partners--team) share it. --- */
.zo-card-expert.zo-card-expert--team { min-height: 0; }
.zo-card-expert--team .zo-card-expert__media { margin-top: var(--wp--preset--spacing--40); } /* 24 */
.zo-card-expert--team .zo-card-expert__body { gap: var(--wp--preset--spacing--40); /* 24 */
	padding: var(--wp--preset--spacing--40); }                                                      /* 24 */
.zo-card-expert--team .zo-card-expert__name { font-size: var(--wp--custom--font-size--20); line-height: 26px;
	display: block; overflow: visible; }
.zo-card-expert--team .zo-card-expert__role { display: block; overflow: visible; }
.zo-card-expert--team .zo-card-expert__bio { font-size: var(--wp--preset--font-size--small); line-height: 20px;
	display: block; overflow: visible; white-space: pre-line; }
.zo-card-expert--team .zo-card-expert__link { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
.zo-card-expert--team .zo-card-expert__link svg { width: 18px; height: 18px; }
.zo-card-expert--team.zo-card-expert--static:hover { box-shadow: none; }

/* --- Karte (beide Varianten) --- */
.zo-card-partner { position: relative; display: flex; flex-direction: column; }
.zo-card-partner__empty { margin: 0; padding: var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--white); color: var(--wp--preset--color--grey);
	font-size: var(--wp--preset--font-size--small); line-height: 20px; }
/* Vollflächen-Schicht: unsichtbarer Toggle-Button auf JEDER Karte — Klick/Tap schaltet
   das Overlay um (Philipp, #192 zweiter Review-Durchgang: kein stretched link mehr,
   der Link wandert als Action-Link ins Overlay; alle Karten verhalten sich gleich). */
.zo-card-partner__tap { position: absolute; inset: 0; z-index: 2;
	margin: 0; padding: 0; border: 0; background: transparent; cursor: pointer; }
.zo-card-partner__tap:focus-visible,
.zo-card-partner__toggle:focus-visible, .zo-card-partner__close:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.zo-card-partner__logo { display: flex; align-items: center; justify-content: center;
	background: var(--wp--preset--color--white); }
.zo-card-partner__img { max-width: 100%; max-height: 100%; width: auto; height: auto;
	object-fit: contain; }
/* Meta-Gap: Profile 4 (alle Größen), Teaser 6 SM/MD → 8 LG+ (Figma-Sets, Update 18.08.). */
.zo-card-partner__meta { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--10); /* 4 */ }
.zo-card-partner--compact .zo-card-partner__meta { gap: 6px; /* Teaser SM/MD — kein Token, Figma 6462:86710 */ }
/* Karten-Typo stuft seit dem 18.08. am Viewport (Figma-Sets): Profile 18/24 → 20/26 @1024,
   Teaser 16/22 → 20/26 @1024; ls 0.14px = 0.01em (Presets small/medium sind fix, s. Card-Expert). */
.zo-card-partner__name { margin: 0; font-family: var(--wp--preset--font-family--display);
	font-weight: 700; letter-spacing: 0; color: var(--wp--preset--color--foreground); }
.zo-card-partner--expanded .zo-card-partner__name { font-size: var(--wp--custom--font-size--18); line-height: 24px; }
.zo-card-partner--compact .zo-card-partner__name { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
/* Rolle: Profile 14/20 in allen Größen, Teaser 12/16 SM/MD → 14/20 LG+. */
.zo-card-partner__role { margin: 0; font-size: var(--wp--preset--font-size--small);
	font-weight: 500; line-height: 20px; letter-spacing: 0.01em;
	color: var(--wp--preset--color--grey); }
.zo-card-partner--compact .zo-card-partner__role { font-size: var(--wp--custom--font-size--12); line-height: 16px; }

/* Ausgeklappt: Logo-Fläche fluid 2:1 (Grid-Set 6468:3531 — XL 320×160, LG 309.3×154.7,
   MD/SM 288×144; pad 24 in allen Größen) + lila Fläche fix 170 (SM+) bzw. 190 (LG+, @1024).
   Karten-Höhe = Logo (aspect-ratio) + padding-bottom in Box-Höhe — die lila Fläche liegt
   absolut, damit sie beim Öffnen wachsen kann, ohne die Grid-Zeile zu reflowen (#192-Review). */
.zo-card-partner--expanded { padding-bottom: 170px; }
/* min-height: 0 — ohne das behält die Flex-Box ihr Content-Minimum (min-height: auto) und ein
   Logo höher als 2:1 streckt die Box über das aspect-ratio hinaus (das max-height: 100% des img
   ist im Minimum zirkulär und zählt als none); __surface bleibt bei 2:1 und deckt die Box im
   Hover dann nicht mehr ab (#206, BMWi 300×186 / Ibykus 300×212). */
.zo-card-partner--expanded .zo-card-partner__logo { aspect-ratio: 2 / 1; min-height: 0;
	padding: var(--wp--preset--spacing--40); }

/* --- Die EINE lila Fläche (#192-Review: Meta nur 1× im DOM, springt nicht mehr). ---
   __content trägt Meta + Beschreibung + Toggle; ausgeklappt bottom-verankert mit
   min-height = geschlossene Box (170 SM+ / 190 LG+). Öffnen: __surface (Deko-Schicht,
   2:1 = Logo-Höhe) fährt per transform über die Logo-Fläche hoch, die Beschreibung
   klappt per grid-template-rows 0fr→1fr aus. Passt sie in den Restraum unter Meta,
   bleibt Meta exakt an der Closed-Position; nur bei Überlauf wächst __content
   bottom-verankert nach oben (Meta rückt hoch — Philipps Vorgabe; deshalb behält das
   Overlay auch das Closed-Padding statt Figmas Hover-Pad 24 @SM+, Spec §Abweichung).
   pointer-events bleibt an der Fläche aus, damit Klicks den __tap darunter treffen
   (Issue-Entscheid); nur __toggle/__close/__action fangen. */
.zo-card-partner__surface { position: absolute; top: 0; left: 0; right: 0; aspect-ratio: 2 / 1;
	z-index: 1; background: var(--wp--preset--color--accent-lilac); pointer-events: none;
	transform: translateY(100%); transition: transform .25s ease; }
.zo-card-partner__content { display: flex; flex-direction: column;
	background: var(--wp--preset--color--accent-lilac); pointer-events: none; }
.zo-card-partner--expanded .zo-card-partner__content { position: absolute; left: 0; right: 0;
	bottom: 0; z-index: 3; min-height: 170px; max-height: 100%;
	padding: var(--wp--preset--spacing--30); /* 16 SM+ — 24 LG+ (@1024 unten) */ }
/* Aufklappender Teil: zu, bis JS/Hover öffnet (0fr→1fr, animierbar); Gap Meta→Beschreibung 16.
   __more ist das EINE Grid-Kind (mehrere Kinder bekämen implizite Rows und brächen die
   0fr-Animation) und stapelt Beschreibung + Action-Link mit Gap 16. */
.zo-card-partner__body { display: grid; grid-template-rows: 0fr;
	margin-top: var(--wp--preset--spacing--30); /* 16 */
	transition: grid-template-rows .25s ease; }
.zo-card-partner__more { display: flex; flex-direction: column; min-height: 0; overflow: hidden;
	gap: var(--wp--preset--spacing--30); /* 16 */ }
/* Beschreibung: SM+ 12/16, max 6 Zeilen = 96px (Figma Body Copy 240×96) —
   LG+ 14/20, max 8 Zeilen = 160px (272×160, @1024 unten). */
.zo-card-partner__description { margin: 0; min-height: 0; font-size: var(--wp--custom--font-size--12);
	font-weight: 500; line-height: 16px; letter-spacing: 0.01em;
	color: var(--wp--preset--color--foreground);
	display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
/* Toggle unten rechts mit 8px Kanten-Abstand (Figma-Wrapper 64×64 pad 8); nur Icon sichtbar
   (Button-Fläche im Mock transparent — am PNG belegt, Spec §Fallen). Offen blendet er aus
   (im Figma-Open-State ersetzt ihn der Close-Button). */
.zo-card-partner__toggle { position: absolute; right: 8px; bottom: 8px;
	display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px;
	padding: 0; border: 0; border-radius: 100%; background: transparent;
	color: var(--wp--preset--color--primary); cursor: pointer; pointer-events: auto;
	transition: opacity .25s ease; }
.zo-card-partner__toggle svg, .zo-card-partner__close svg { width: 18px; height: 18px; }
.zo-card-partner__close { position: absolute; top: 0; right: 0; z-index: 4;
	display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px;
	padding: 0; border: 0; border-radius: 100%; background: transparent;
	color: var(--wp--preset--color--primary); cursor: pointer;
	opacity: 0; pointer-events: none; transition: opacity .25s ease; }

/* Action-Link im Overlay — seit dem Figma-Update 18.08. offiziell im Design (Active
   Link, Basis 4512:33726, in allen Hover-States): Figtree 700 14/20, Icon 16, Gap 4,
   Farbe primary #8359FF (Philipp 18.08.: „Baue den Link auf Lila um" — ersetzt den
   foreground-Kontrast-Entscheid vom 14.08.). Adopter von .is-style-zo-action-link
   (#188, Markup-Muster content-list); die Farbe kommt jetzt aus dem Basis-Stil, aber
   dessen LG-Stufe (Gap 6 + 16/22 + Icon 18 @1024) gilt hier NICHT — die Karte bleibt
   in allen Viewports auf SM (Gap 4 + 14/20 + 16), deshalb gepinnt (3-Klassen-Selektor
   gewinnt auch gegen die MQ des Basis-Stils). Der Gap-Pin ist seit #212 keine
   Korrektur des Basis-Stils mehr, sondern hält die SM-Stufe über 1024 hinaus.
   pointer-events auto hebt das none der __content-/__panel-Schicht nur am Link auf. */
.zo-card-partner .zo-card-partner__action .wp-block-button__link {
	--zo-action-link-font-size: var(--wp--preset--font-size--small); --zo-action-link-line-height: 20px; --zo-action-link-icon: 16px; --zo-action-link-gap: 4px;
	pointer-events: auto; }
.zo-card-partner--compact .zo-card-partner__action { margin-top: var(--wp--preset--spacing--20); /* +8 = 16 zu Meta */ }

/* Kompakt: die ganze Karte ist die Logo-Fläche (quadratisch, pad 32); die lila Fläche
   slidet von unten ein (gleiche Bewegung wie ausgeklappt — #192-Review, statt Fade),
   __panel clippt sie im geschlossenen Zustand. */
.zo-card-partner--compact { aspect-ratio: 1 / 1;
	min-height: 0; /* aspect-ratio keeps a content-based minimum: a portrait image stretched the card past 1:1 (#371) */ }
.zo-card-partner--compact .zo-card-partner__logo { flex: 1 1 auto; padding: var(--wp--preset--spacing--50); /* 32 */
	min-height: 0; /* same trap one level down (see --expanded, #206) */ }
.zo-card-partner__panel { position: absolute; inset: 0; z-index: 3; overflow: hidden;
	pointer-events: none; }
.zo-card-partner--compact .zo-card-partner__content { position: absolute; inset: 0;
	gap: var(--wp--preset--spacing--20); /* 8 */ justify-content: flex-start;
	padding: 12px; /* Teaser SM (6462:87262) — 16 MD / 24 LG+ (@media unten), kein Token */
	transform: translateY(100%); transition: transform .25s ease; }

/* Offen-Zustand (.is-open per JS, Fokus, hover-fähige Geräte): Fläche hoch, Beschreibung
   auf, Toggle→Close-Wechsel. Buttons bleiben im DOM/Tab-Fluss (#190-Lektion). */
.zo-card-partner.is-open .zo-card-partner__surface,
.zo-card-partner:has(:focus-visible) .zo-card-partner__surface { transform: translateY(0); }
.zo-card-partner.is-open .zo-card-partner__body,
.zo-card-partner:has(:focus-visible) .zo-card-partner__body { grid-template-rows: 1fr; }
.zo-card-partner.is-open .zo-card-partner__toggle,
.zo-card-partner:has(:focus-visible) .zo-card-partner__toggle { opacity: 0; pointer-events: none; }
.zo-card-partner.is-open .zo-card-partner__close,
.zo-card-partner:has(:focus-visible) .zo-card-partner__close { opacity: 1; pointer-events: auto; }
.zo-card-partner--compact.is-open .zo-card-partner__content,
.zo-card-partner--compact:has(:focus-visible) .zo-card-partner__content { transform: translateY(0); }
@media (hover: hover) {
	.zo-card-partner:hover .zo-card-partner__surface { transform: translateY(0); }
	.zo-card-partner:hover .zo-card-partner__body { grid-template-rows: 1fr; }
	.zo-card-partner:hover .zo-card-partner__toggle { opacity: 0; pointer-events: none; }
	.zo-card-partner:hover .zo-card-partner__close { opacity: 1; pointer-events: auto; }
	.zo-card-partner--compact:hover .zo-card-partner__content { transform: translateY(0); }
}

/* Viewport-Stufung der Karten (Figma-Sets, Update 18.08.): Teaser-Overlay-Pad 12→16→24,
   Profile-Box 170→190 (pad 16→24), Typo auf die LG+-Größen ab 1024. */
@media (min-width: 640px) {
	.zo-card-partner--compact .zo-card-partner__content { padding: var(--wp--preset--spacing--30); /* 16 MD */ }
}
@media (min-width: 1024px) {
	.zo-card-partner--expanded { padding-bottom: 190px; }
	.zo-card-partner--expanded .zo-card-partner__content { min-height: 190px;
		padding: var(--wp--preset--spacing--40); /* 24 LG+ */ }
	.zo-card-partner--compact .zo-card-partner__content { padding: var(--wp--preset--spacing--40); /* 24 LG+ */ }
	.zo-card-partner--compact .zo-card-partner__meta { gap: var(--wp--preset--spacing--20); /* 8 LG+ */ }
	.zo-card-partner--expanded .zo-card-partner__name,
	.zo-card-partner--compact .zo-card-partner__name { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-card-partner--compact .zo-card-partner__role { font-size: var(--wp--preset--font-size--small); line-height: 20px; }
	.zo-card-partner__description { font-size: var(--wp--preset--font-size--small); line-height: 20px;
		-webkit-line-clamp: 8; /* 160px = Figma Body Copy 272×160 */ }
}

/* --- Carousel-Hülle: Track full-bleed auf der Rail-Kante, Mechanik zo-carousel-view. --- */
.zo-partners__intro { margin-bottom: var(--wp--preset--spacing--40); /* 24 SM */ }
/* Typo der Intro-H2 kommt aus .zo-section-heading (#152) — hier nur die Abstände
   (Figma Heading pad-b 12/16/24). */
.zo-partners__heading { margin: 0 0 12px; }
.zo-partners__text { margin: 0; font-size: var(--wp--preset--font-size--small);
	font-weight: 500; line-height: 20px; color: var(--wp--preset--color--foreground); }
.zo-partners__viewport { position: relative; }
.zo-partners__track { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory;
	scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-inline: var(--zo-rail-bleed); /* kanonische Rail (#99) */
	scroll-padding-inline: var(--zo-rail-bleed); }
.zo-partners__track::-webkit-scrollbar { display: none; }
/* Carousel-Karten fix 180 (SM) / 224 (MD) / 240 (LG+) — Figma-Set 6382:708, Update 18.08. */
.zo-partners__track > .zo-card-partner { flex: 0 0 180px; scroll-snap-align: start; }
/* Team carousel (#371, Philipp 2026-09-27; no Figma frame): same card as the team grid,
   one item = one grid column (MD 2 / LG 3 / XL 4 per rail = 320 @1440); SM 288 = Card
   Expert SM width, so the next card peeks. `> *` also sizes the editor block wrappers.
   Flex items stretch -> equal card heights, link at the bottom like in the grid.
   Track padding/negative margin = room for the hover shadow (#352 pattern), no shift. */
.zo-partners--team .zo-partners__track { padding-block: 12px 32px; margin-block: -12px -32px; }
.zo-partners--team .zo-partners__track > * { flex: 0 0 288px; min-width: 0; scroll-snap-align: start; }
/* Overlay-Arrows: aktiv Kreis primary, disabled grey-mid, Icon immer weiß (im XL-Frame
   belegt: rechter Arrow #8359FF, linker am Scroll-Anfang = disabled #C2C2C2 — PNG+JSON,
   Spec §Carousel); links Inset 24, rechts 0 — in LG- UND XL-Frame so belegt.
   z-index 5: über den Karten-Schichten __tap (2), __content/__panel (3), __close (4) —
   sonst gewinnt die unsichtbare Klick-Fläche der Karte den Hit-Test gegen den Pfeil
   (#192-Review, per elementFromPoint belegt). */
.zo-partners__arrow { display: none; position: absolute; top: 50%; transform: translateY(-50%);
	z-index: 5;
	border: 0; background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); }
.zo-partners__arrow:hover { background: var(--wp--preset--color--primary); }
.zo-partners__arrow:disabled { background: var(--wp--preset--color--grey-mid);
	color: var(--wp--preset--color--white); border: 0; cursor: default; }
.zo-partners__arrow.zo-carousel-arrow--prev { left: calc(var(--zo-rail-bleed) + 24px); }
.zo-partners__arrow.zo-carousel-arrow--next { right: var(--zo-rail-bleed); }
/* Dots: fix 5, iOS-Tapering 4/8/8/8/4, Gap 12 — identisch zo/image-carousel (#79/#190). */
.zo-partners__footer { display: flex; justify-content: center;
	margin-top: var(--wp--preset--spacing--40); /* 24 SM/MD */ }
.zo-partners__dots { display: flex; justify-content: center; align-items: center; gap: 12px; }
.zo-partners__dot { width: 8px; height: 8px; border-radius: 100%;
	background: var(--wp--preset--color--grey-mid);
	transition: width .25s ease, height .25s ease, background-color .25s ease; }
.zo-partners__dot:nth-child(1), .zo-partners__dot:nth-child(5) { width: 4px; height: 4px; }
.zo-partners__dot.is-active { width: 8px; height: 8px; background: var(--wp--preset--color--primary); }
@media (min-width: 640px) {
	.zo-partners__intro { margin-bottom: var(--wp--preset--spacing--50); /* 32 MD */ }
	.zo-partners__heading { margin-bottom: 16px; }
	.zo-partners__text { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-partners__track > .zo-card-partner { flex-basis: 224px; }
	.zo-partners--team .zo-partners__track > * { flex-basis: calc((100% - 16px) / 2); }
}
@media (min-width: 1024px) {
	.zo-partners__intro { margin-bottom: var(--wp--preset--spacing--60); /* 40 LG/XL */ }
	.zo-partners__heading { margin-bottom: 24px; }
	.zo-partners__text { max-width: 960px; }
	.zo-partners__track > .zo-card-partner { flex-basis: 240px; }
	.zo-partners--team .zo-partners__track > * { flex-basis: calc((100% - 32px) / 3); }
	.zo-partners__footer { margin-top: var(--wp--preset--spacing--50); /* 32 LG/XL */ }
	/* Arrows nur LG/XL und nur bei Hover/Fokus (Annotation; Muster #190: opacity statt
	   display, sonst fielen die Buttons aus der Tab-Reihenfolge). Unsichtbar fangen sie
	   keine Pointer (z-index 5 läge sonst über den __tap-Flächen der Karten — #192-Review). */
	.zo-partners--carousel.is-scrollable .zo-partners__arrow { display: inline-flex; opacity: 0;
		pointer-events: none; transition: opacity .18s ease; }
	.zo-partners__viewport:hover .zo-partners__arrow,
	.zo-partners__viewport:focus-within .zo-partners__arrow { opacity: 1; pointer-events: auto; }
}
@media (min-width: 1440px) {
	.zo-partners--team .zo-partners__track > * { flex-basis: calc((100% - 48px) / 4); } /* 320 */
}

/* ============================================================
   Component: FAQ-Akkordeon  (CPT faq + faq_cat)
   Figma Component-Set 5182-55812 (Viewports XL/LG/MD/SM). Native <details>/<summary>,
   Toggle-Marker „+"→„−" per SVG-Tausch (kein view.js; Minus statt „ד seit #163,
   Philipp: für alle Akkordeons gleich). Kein eigener Hintergrund (Component
   transparent; Section-Kontext liefert paper).
   Spec: docs/figma-specs/faq-accordion.md  ·  Sync 2026-07-21 (#61), Grid-Umzug 2026-08-07 (#127)
   States: summary :hover / :focus-visible · [open] (Minus statt Plus). Leer = __empty.
   Breakpoints (Viewport-MQ, Raster + Rand aus der Grid-Foundation):
       <640 SM (stack, 4 Spalten, Rand 16) · >=640 MD (stack, 8 Spalten, Rand 24) ·
       >=1024 LG (2-Spalt 4/8 = 309/635, Rand 32) · >=1440 XL (2-Spalt 5/7 = 544/768, Content 1328).
   Die H2 stuft NICHT hier, sondern über .zo-section-heading am Viewport (#152).
   ============================================================ */
.zo-faq, .zo-faq * { box-sizing: border-box; }
/* Phase-2-Umzug auf die Grid-Foundation (#127): __inner IST die Schiene UND das Raster
   (`.zo-container .zo-grid` im Markup), __head/__list spannen Figmas Spalten (Component-Set
   5173:52576: LG 310+16+634 = 4/8 von 12 · XL 544+16+768 = 5/7 von 12). Damit faellt die
   modul-eigene Rail ersatzlos weg — inklusive der 100cqw-Notloesung aus #153
   (`--zo-rail-bleed` auf einem Grid-ITEM, content-rail.md §rail-bleed) und der
   Container-Query-Schwelle 1360.
   WARUM VIEWPORT-MQ STATT CONTAINER-QUERY (bewusster Bruch mit der Forward-Regel in
   block-css-fallen.md §Demo): Rand und Spaltenzahl kommen aus --zo-grid-margin/--zo-grid-columns,
   und die stufen im `:root` am Viewport. Ein Modul, das auf der Foundation sitzt, stuft deshalb
   zwangslaeufig mit ihr — eine eigene Container-Schwelle daneben waere das verbotene
   Parallel-System. Konsequenz: kein `container-type` mehr und EINE Demo-Instanz statt vier
   Fixed-Width-Frames (die konnten den Viewport ohnehin nicht simulieren). */
.zo-faq__inner { row-gap: var(--wp--preset--spacing--50); /* 32 Header->Liste im Stack SM/MD */ }

/* Heading-Spalte */
/* Typo der H2 kommt aus .zo-section-heading (#152) — hier nur der Abstand zur Liste. */
.zo-faq__heading { margin: 0 0 16px; }
.zo-faq__intro { margin: 0 0 16px; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; color: var(--wp--preset--color--foreground); }
.zo-faq__contact { display: inline-flex; align-items: center; gap: 10px; margin: 0;
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px;
	color: var(--wp--preset--color--primary); text-decoration: none; }
.zo-faq__contact:hover { text-decoration: underline; }
.zo-faq__contact-icon { display: inline-flex; color: var(--wp--preset--color--primary); }
.zo-faq__contact-icon svg { display: block; width: 18px; height: 18px; }

/* Akkordeon-Liste */
.zo-faq__empty { margin: 0; color: var(--wp--preset--color--grey); }
.zo-faq__item { border-bottom: 1px solid var(--wp--preset--color--grey-mid); }
.zo-faq__summary { display: flex; align-items: center; gap: 24px; /* Frage<->Button SM/MD */
	padding-block: 16px; list-style: none; cursor: pointer; }
.zo-faq__summary::-webkit-details-marker { display: none; }
.zo-faq__summary:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.zo-faq__question { flex: 1 1 auto; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; color: var(--wp--preset--color--foreground); }
.zo-faq__toggle { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
	width: 48px; height: 48px; border: 4px solid var(--wp--preset--color--primary); border-radius: 50%;
	color: var(--wp--preset--color--primary); }
.zo-faq__toggle svg { display: block; width: 18px; height: 18px; }
.zo-faq__toggle svg:last-child { display: none; }              /* Minus erst offen (#163) */
.zo-faq__item[open] .zo-faq__toggle svg:first-child { display: none; }
.zo-faq__item[open] .zo-faq__toggle svg:last-child { display: block; }
.zo-faq__answer { margin: 0; padding: 0 0 16px; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); font-weight: 400; line-height: 22px; color: var(--wp--preset--color--foreground); }
.zo-faq__answer > :first-child { margin-top: 0; }
.zo-faq__answer > :last-child { margin-bottom: 0; }

@media (min-width: 640px) {                              /* MD: stack, 8 Spalten */
	.zo-faq__heading { margin-bottom: 24px; }
}
@media (min-width: 1024px) {                             /* LG: 2-Spalt 4/8 (309,33 + 16 + 634,67) */
	.zo-faq__heading { margin-bottom: 32px; }
	.zo-faq__intro { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-faq__contact { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-faq__summary { gap: 40px; padding-block: 24px; } /* Frage<->Button + pad LG/XL */
	.zo-faq__question { font-size: var(--wp--custom--font-size--18); line-height: 26px; }
	.zo-faq__answer { padding-bottom: 24px; }
}
/* XL: 2-Spalt 5/7 (544 + 16 + 768 = Content 1328). Schwelle jetzt exakt 1440 = der
   XL-Breakpoint der Foundation; die alte 1360 war eine Kruecke gegen die Ungenauigkeit
   des Alignfull-Containers und entfaellt mit dem Viewport-Bezug. Kein `.zo-col-xl-*` in der
   Foundation: der Spannen-Wechsel bei XL ist bisher erst der zweite Fall (nach
   .zo-article --zo-article-cols) — beim dritten wird er als Utility extrahiert. */
@media (min-width: 1440px) {
	.zo-faq__head { grid-column: span 5; }
	.zo-faq__list, .zo-faq__empty { grid-column: span 7; }
}

/* ============================================================
   Component: Akkordeon  (zo/accordion + zo/accordion-item, #163)
   Figma 4510-31650 (Component-Sets Accordion .items / Accordion .list). Native
   <details>/<summary>, Toggle „+"→„−" per SVG-Tausch (kein JS). Läuft in der normalen
   Content-Spalte (keine eigene Rail); Breite = Elternkontext.
   Spec: docs/figma-specs/accordion.md  ·  Sync 2026-08-10 (#163)
   States: summary :hover (Kreis violet-dark) / :focus-visible (outline ink 3/4px, Figma
     OUTSIDE) · [open] (Titel primary, Minus). Pressed = Default (Figma), Leer/Laden/Fehler
     n/a (statisch; Container ohne Einträge rendert leer).
   Breakpoints (Viewport-MQ, Kopplung wie .zo-faq): <1024 Dense (Zeile 80, Titel 14/20) ·
     >=1024 Airy (Zeile 96, Titel 18/26).
   Zeilen-Optik = zweite Verwendung neben .zo-faq (bewusstes Duplikat, CLAUDE.md-Regel:
   Extraktion erst beim dritten Vorkommen).
   ============================================================ */
.zo-accordion, .zo-accordion * { box-sizing: border-box; }
.zo-accordion { border-top: 1px solid var(--wp--preset--color--grey-mid); }
.zo-accordion__item { border-bottom: 1px solid var(--wp--preset--color--grey-mid); }
.zo-accordion__summary { display: flex; align-items: center; gap: 24px; /* Titel<->Button SM/MD */
	padding-block: 16px; list-style: none; cursor: pointer; }
.zo-accordion__summary::-webkit-details-marker { display: none; }
.zo-accordion__summary:focus-visible { outline: 3px solid var(--wp--preset--color--foreground); outline-offset: 0; }
.zo-accordion__title { flex: 1 1 auto; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px;
	color: var(--wp--preset--color--foreground); /* Figma #201E1E -> ink (Philipp #163) */ }
.zo-accordion__item[open] > .zo-accordion__summary .zo-accordion__title { color: var(--wp--preset--color--primary); }
.zo-accordion__toggle { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
	width: 48px; height: 48px; border: 4px solid var(--wp--preset--color--primary); border-radius: 50%;
	color: var(--wp--preset--color--primary); }
.zo-accordion__summary:hover .zo-accordion__toggle { border-color: var(--wp--custom--color--violet-dark);
	color: var(--wp--custom--color--violet-dark); }
.zo-accordion__toggle svg { display: block; width: 18px; height: 18px; }
.zo-accordion__toggle svg:last-child { display: none; }        /* Minus erst offen */
.zo-accordion__item[open] > .zo-accordion__summary .zo-accordion__toggle svg:first-child { display: none; }
.zo-accordion__item[open] > .zo-accordion__summary .zo-accordion__toggle svg:last-child { display: block; }
.zo-accordion__body { padding: 0 0 24px; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px;
	color: var(--wp--preset--color--foreground); }
/* Body block gap = link-list gap 12 (Figma frame 1, itemSpacing 12); also neutralizes the
   WP flow gap. Body links follow the global link style (link color + underline, theme.json) —
   deliberate deviation from the Figma text-link default (plain ink, no underline): #285. */
.zo-accordion__body > * { margin-block: 12px 0; }
.zo-accordion__body > :first-child { margin-top: 0; }
@media (min-width: 1024px) {                             /* LG/XL: Airy */
	.zo-accordion__summary { gap: 40px; padding-block: 24px; }
	.zo-accordion__summary:focus-visible { outline-width: 4px; }
	.zo-accordion__title { font-size: var(--wp--custom--font-size--18); line-height: 26px; }
	.zo-accordion__body { padding-bottom: 40px; font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
}

/* ============================================================
   Component: Sprungmarken-Navigation  (zo/anchor-nav, #68)
   Figma 4893-57137 (Component-Sets .Buttons / Anchor Navigation / .Mini-Drawer-Content).
   Sticky Pill-Leiste (Desktop, Overflow-Pfeile) + Vollbild-Drawer (mobil). Scroll-Spy = view.js.
   Spec: docs/figma-specs/anchor-nav.md  ·  Sync 2026-07-22 (#68)
   States: pill/item :hover / :focus-visible / [aria-current] (Selected) · trigger aria-expanded.
     Leer = Auto-Hide (render_callback ''). Viewport-MQ bewusst (full-width sticky Element,
     Insets + Drawer sind viewport-getrieben, nicht container-scoped).
   Breakpoints: <640 Drawer (inset 16) · >=640 Pills inset 24 · >=1024 inset 32 · >=1440 inset 56.
   Alignment (#304): default left · .zo-anchor-nav--center centers the pill row (Figma 6076-65792),
     identical insets; on overflow it degrades to the left-aligned scroll behavior.
   PDP-Variante: Pill-Reihe liegt seit #153 als .zo-container auf der Grid-Foundation
   (Figma 5191:34970) — keine eigene Rail, kein --zo-pdp-inset mehr.
   ============================================================ */
.zo-anchor-nav, .zo-anchor-nav * { box-sizing: border-box; }
/* Free-page pill bar: sticky top:0. Since #328 this markup only serves the editor preview —
   every frontend page renders the condensed sticky mechanic (see inc/anchor-nav-block.php). */
.zo-anchor-nav { --zo-anchor-inset: var(--zo-rail-bleed); position: sticky; top: 0; z-index: 20; margin: 0; } /* Pills auf die kanonische Rail (#99) */
/* Jump-target offset: header (pinned, reveals on upward jumps, #328) + condensed bar + 8.
   Was 88 (bar only) — upward jumps then landed under the revealed header+bar stack. */
.zo-has-anchor { scroll-margin-top: 168px; }
@media (max-width: 639px) { .zo-has-anchor { scroll-margin-top: 64px; } }
/* Legacy jump target kept inside a renamed section (#395: #dozentinnen -> #expertinnen): sits
   below the section padding, so the offset adds --zo-module-gap to land like the new anchor. */
.zo-anchor-alias { display: block; height: 0; scroll-margin-top: calc(168px + var(--zo-module-gap)); }
@media (max-width: 639px) { .zo-anchor-alias { scroll-margin-top: calc(64px + var(--zo-module-gap)); } }
/* The alias is first child: keep the section content flush like before (no flow block-gap). */
.zo-section > .zo-anchor-alias + * { margin-block-start: 0; }

/* --- Desktop-Leiste (mobile-first: erst ab 640 sichtbar) --- */
.zo-anchor-nav__bar { display: none; }
.zo-anchor-nav__list { display: flex; align-items: center; gap: var(--wp--preset--spacing--20); /* 8 */
	margin: 0; padding: 0; list-style: none;
	overflow-x: auto; scroll-behavior: smooth; scroll-snap-type: x proximity;
	scrollbar-width: none; -ms-overflow-style: none; }
.zo-anchor-nav__list::-webkit-scrollbar { display: none; }
.zo-anchor-nav__pill__li { flex: 0 0 auto; scroll-snap-align: start; }

/* Pill (Figma „Stand Alone" 48h, Radius 100, Border 2px). Default has no fill — outline only
   (Figma 6075-36924: every pill instance fills [], #346); hover/selected stay lilac. */
.zo-anchor-nav__pill { display: inline-flex; align-items: center; gap: var(--wp--preset--spacing--20); /* 8 */
	height: 48px; padding: 12px 24px;
	border: 2px solid var(--wp--preset--color--primary); border-radius: 100px;
	background: transparent; color: var(--wp--preset--color--primary);
	font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 22px;
	text-decoration: none; white-space: nowrap; cursor: pointer;
	transition: background-color .15s ease; }
.zo-anchor-nav__pill:hover { background: var(--wp--preset--color--accent-lilac); }
.zo-anchor-nav__pill:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.zo-anchor-nav__pill[aria-current="true"] { background: var(--wp--preset--color--accent-lilac); }
.zo-anchor-nav__link-icon { display: inline-flex; }
.zo-anchor-nav__pill .zo-anchor-nav__link-icon svg { display: block; width: 16px; height: 16px; }

/* Overflow-Pfeile (runde 48px-Buttons an den Enden, nur bei Overflow via view.js) */
.zo-anchor-nav__arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
	display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; padding: 0;
	border: 0; border-radius: 50%; background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white);
	cursor: pointer; }
.zo-anchor-nav__arrow[hidden] { display: none; }
.zo-anchor-nav__arrow svg { display: block; width: 24px; height: 24px; }
.zo-anchor-nav__arrow--prev { left: var(--zo-anchor-inset); }
.zo-anchor-nav__arrow--next { right: var(--zo-anchor-inset); }

/* --- Mobile-Trigger (<640): rechteckiger Button „Seiteninhalt", Border 4px, scharfkantig --- */
.zo-anchor-nav__trigger { display: inline-flex; align-items: center; justify-content: center;
	gap: var(--wp--preset--spacing--20); /* 8 */ width: calc(100% - 32px); height: 48px; margin: 0 16px;
	padding: 12px 16px; border: 4px solid var(--wp--preset--color--primary); background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--primary); font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; cursor: pointer; }
.zo-anchor-nav__trigger-icon svg { display: block; width: 16px; height: 16px; }

@media (min-width: 640px) {
	/* Ab 640 klappen BEIDE Varianten Trigger/Drawer weg und zeigen die Pill-Leiste (#89,
	   vereinheitlicht mit der PDP-Variante). Gleiche Spezifität wie die Trigger-Basis-Regel
	   oben (0,1,0) — dieser Block muss deshalb NACH ihr stehen (#183). Die spezifischeren
	   PDP-Basis-Regeln (.zo-anchor-nav--pdp …, 0,2,0) überschreibt der PDP-@640-Block unten. */
	.zo-anchor-nav__trigger,
	.zo-anchor-nav__drawer { display: none; }
	.zo-anchor-nav:not(.zo-anchor-nav--pdp) .zo-anchor-nav__bar { position: relative; display: flex; align-items: center; height: 48px;
		padding-inline: var(--zo-anchor-inset); }
}
/* Inset via Rail-Alias (--zo-rail-bleed, #128) — trackt 16/24/32 + Cap 1328 automatisch. */

/* Alignment center (#304, Figma 6076-65792): the list stays its own scroll container and gets
   centered inside the bar while it fits; on overflow it fills the bar and scrolls from the
   left as usual (same insets/arrows as the left variant — verified per breakpoint variant). */
.zo-anchor-nav--center .zo-anchor-nav__bar { justify-content: center; }
/* #328: with the condensed mechanic on all pages the pills live in __incontent — center them
   there the same way (list hugs its content while it fits, degrades to scroll on overflow). */
.zo-anchor-nav--center .zo-anchor-nav__incontent { justify-content: center; }
.zo-anchor-nav--center.zo-anchor-nav--pdp .zo-anchor-nav__incontent .zo-anchor-nav__list { width: auto; max-width: 100%; }

/* --- Mobile-Drawer (Vollbild-Overlay, weiß) --- */
.zo-anchor-nav__drawer { position: fixed; inset: 0; z-index: 1000; }
.zo-anchor-nav__drawer[hidden] { display: none; }
.zo-anchor-nav__drawer-panel { position: absolute; inset: 0; display: flex; flex-direction: column;
	padding: 64px 24px 24px; background: var(--wp--preset--color--white); overflow-y: auto; }
.zo-anchor-nav__close { position: absolute; top: 0; right: 0; display: inline-flex; align-items: center;
	justify-content: center; width: 64px; height: 64px; padding: 0; border: 0; background: transparent;
	color: var(--wp--preset--color--primary); cursor: pointer; }
.zo-anchor-nav__close svg { display: block; width: 24px; height: 24px; }
.zo-anchor-nav__drawer-head { margin-bottom: 16px; }
.zo-anchor-nav__eyebrow { display: block; margin-bottom: 8px; font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; color: var(--wp--preset--color--foreground); }
.zo-anchor-nav__drawer-title { margin: 0; font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 26px; color: var(--wp--preset--color--foreground); }
.zo-anchor-nav__drawer-list { margin: 0; padding: 0; list-style: none; }
.zo-anchor-nav__drawer-item { display: flex; align-items: center; gap: var(--wp--preset--spacing--40); /* 24 */
	height: 64px; border-bottom: 2px solid var(--wp--preset--color--grey-mid);
	color: var(--wp--preset--color--foreground); text-decoration: none;
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; }
.zo-anchor-nav__drawer-item .zo-anchor-nav__drawer-item__label { flex: 1 1 auto; }
.zo-anchor-nav__drawer-item .zo-anchor-nav__link-icon { flex: 0 0 auto; }
.zo-anchor-nav__drawer-item .zo-anchor-nav__link-icon svg { display: block; width: 16px; height: 16px; }
.zo-anchor-nav__drawer-item:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: -2px; }
.zo-anchor-nav__drawer-item[aria-current="true"] { color: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary); }
/* Body-Scroll-Lock bei offenem Drawer */
.zo-anchor-nav-lock, .zo-anchor-nav-lock body { overflow: hidden; }

/* --- Editor-Vorschau: Leiste immer zeigen, nicht sticky --- */
.zo-anchor-nav--editor { position: static; }
.zo-anchor-nav--editor .zo-anchor-nav__bar { display: flex; align-items: center; min-height: 48px;
	flex-wrap: wrap; gap: var(--wp--preset--spacing--20); }
.zo-anchor-nav--editor .zo-anchor-nav__list { flex-wrap: wrap; overflow: visible; }
.zo-anchor-nav--editor .zo-anchor-nav__pill__li { scroll-snap-align: none; }
.zo-anchor-nav__editor-empty { margin: 0; padding: 12px 0; color: var(--wp--preset--color--grey);
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-style: italic; }

/* --- PDP-Variante (#52, neu aufgebaut #89) — Drei-Zustands-Modell.
   Zustand 1  In-Content-Pills (Node 4573-37638): volle Breite, 48h, im normalen Content-Fluss,
     ab MD sichtbar (SM aus). Nummerierung entfällt (Philipp #89) → Pill = Label + arrow-down.
   Zustand 2  Sticky-Kondensat (Node 5128-15063): `Titel | CTA | list-check`, erscheint per Reveal
     sobald die In-Content-Bar über den Header gescrollt ist (view.js), navigiert über den Drawer
     (nicht Pills). Dockt an die Hauptnav (Node 5690-8363): Header sichtbar ⇒ Subnav bei
     top=--zo-header-h, Header ausgeblendet (.zo-mainnav.is-hidden) ⇒ Subnav an top:0.
   Zustand 3  SM (<640): keine In-Content-Pills; Sticky-Kondensat UNTEN fix (CTA + Trigger),
     Reveal nach Hero-Scroll (5239-18162). Bar 80h weiß, 1px grey-mid.
   The blog-post variant (#307, .zo-anchor-nav--article, same node 5239-18162) reuses all
   .zo-anchor-nav--pdp rules unchanged: post title instead of product title, a "Nach oben"
   button (button element, same __cta styling) instead of the buy CTA. --- */
.zo-anchor-nav--pdp { position: static; z-index: auto; margin: 0; transition: none; }
/* #390: after a leading header band the nav sits inside the module flow; the pill row brings
   its own module gap (margin-top below), so the flow must not add a second one. */
:root .zo-module-flow > .zo-anchor-nav { margin-block-start: 0; }

/* Zustand 1 — In-Content-Pills (Base = SM: aus; ab MD in-flow, s. u.) */
.zo-anchor-nav__incontent { display: none; }

/* Zustand 2/3 — Sticky-Kondensat. Base = SM: unten fix, Reveal nach Hero-Scroll. */
.zo-anchor-nav__sticky { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 30;
	padding-bottom: env(safe-area-inset-bottom); transition: opacity 0.2s ease; }
.zo-anchor-nav--pdp:not(.is-revealed) .zo-anchor-nav__sticky { opacity: 0; visibility: hidden; pointer-events: none; }
.zo-anchor-nav--pdp .zo-anchor-nav__bar { display: flex; align-items: center; gap: var(--wp--preset--spacing--30); /* 16 */
	height: 80px; padding-inline: 16px; background: var(--wp--preset--color--white);
	border-top: 1px solid var(--wp--preset--color--grey-mid);
	/* Content shadow (#328, node 6811-13076): bar sits at the bottom on SM, shadow points up. */
	box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.1), 0 0 4px rgba(0, 0, 0, 0.07); }
.zo-anchor-nav--pdp .zo-anchor-nav__product-title { display: none; flex: 1 1 auto; min-width: 0;
	font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 22px;
	color: var(--wp--preset--color--foreground); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.zo-anchor-nav--pdp .zo-anchor-nav__actions { display: flex; align-items: center; gap: var(--wp--preset--spacing--30); /* 16 */
	flex: 1 1 auto; min-width: 0; }
/* CTA = primärer Button (Figma „Button .base", 48h, scharfkantig, 14/500) als Anchor-Jump */
.zo-anchor-nav--pdp .zo-anchor-nav__cta { flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center;
	gap: var(--wp--preset--spacing--20); /* 8 */ height: 48px; padding: 0 16px;
	background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px;
	text-decoration: none; white-space: nowrap; border: 0; cursor: pointer; }
.zo-anchor-nav--pdp .zo-anchor-nav__cta:hover { background: var(--zo-action-hover); }
.zo-anchor-nav--pdp .zo-anchor-nav__cta:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
/* Trigger = ghost (transparent, no border), list-check primary. Icon-only 48×48 below XL;
   from XL it shows icon + "Seiteninhalt" label (#328, node 6811-13076). The condensate always
   navigates via the drawer (pills only live in the in-content state). */
.zo-anchor-nav--pdp .zo-anchor-nav__trigger { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
	gap: var(--wp--preset--spacing--20); /* 8 */ width: 48px; height: 48px; margin: 0; padding: 0;
	border: 0; background: transparent; color: var(--wp--preset--color--primary); cursor: pointer; }
.zo-anchor-nav--pdp .zo-anchor-nav__trigger-icon svg { display: block; width: 18px; height: 18px; }
.zo-anchor-nav--pdp .zo-anchor-nav__trigger-label { display: none; }
.zo-anchor-nav--pdp .zo-anchor-nav__trigger:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: -2px; }

@media (min-width: 640px) {
	/* Zustand 1 sichtbar: In-Content-Pills in flow, 48h. Die Pill-Reihe sitzt als `.zo-container`
	   direkt auf der Grid-Foundation (§1.4a) — Klasse im Markup, s. inc/anchor-nav-block.php.
	   Belegt am dev-ready Component „Anchor Navigation / Example" 5191:34970 (Abruf 2026-08-07):
	   XL 1440 -> x56/w1328 · LG 1100 -> x32/w1036 · MD 860 -> x24/w812 (#153).
	   Vorher stand hier ein flacher Inset von 40px aus dem Playground-Frame 4573-37638; er
	   fluchtete weder mit Hauptmenue noch mit den Sektions-Ueberschriften. Keine eigene Rail mehr.
	   Abstand nach oben: Hero-BOX (inkl. --zo-pdph-pad) -> Nav = Modul-Reihe; das Frame-
	   itemSpacing misst Box zu Box (6761:84794, #289 — ersetzt calc(80 - pad) vom
	   Best-Guess-Frame 4573-37150). */
	.zo-anchor-nav--pdp .zo-anchor-nav__incontent { position: relative; display: flex;
		align-items: center; height: 48px;
		margin-top: var(--zo-module-gap); }
	.zo-anchor-nav--pdp .zo-anchor-nav__incontent .zo-anchor-nav__list { width: 100%; }
	.zo-anchor-nav--pdp .zo-anchor-nav__arrow--prev { left: 0; }
	.zo-anchor-nav--pdp .zo-anchor-nav__arrow--next { right: 0; }

	/* Zustand 2: Sticky-Kondensat oben. Andock-Offset (top) setzt view.js live aus der realen
	   Unterkante der Hauptnav (Node 5690-8363): Header sichtbar ⇒ top=Header-Unterkante,
	   Header weggescrollt ⇒ top:0. CSS-Fallback ohne JS = top:0. */
	.zo-anchor-nav__sticky { top: 0; bottom: auto; padding-bottom: 0; }
	/* Bar content on the canonical rail (#328, node 6811-13076: XL inset 56/w1328 — resolves the
	   old 40px deviation vs. the pill row) + downward content shadow. */
	.zo-anchor-nav--pdp .zo-anchor-nav__bar { justify-content: flex-start; padding-inline: var(--zo-rail-bleed);
		border-top: 0; border-bottom: 1px solid var(--wp--preset--color--grey-mid);
		box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1), 0 0 4px rgba(0, 0, 0, 0.07); }
	.zo-anchor-nav--pdp .zo-anchor-nav__product-title { display: block; flex: 1 1 auto; }
	.zo-anchor-nav--pdp .zo-anchor-nav__actions { flex: 0 0 auto; }
	.zo-anchor-nav--pdp .zo-anchor-nav__cta { flex: 0 0 auto; }
	/* Drawer bleibt auf Desktop nutzbar (allgemeine 640-Regel blendet ihn sonst aus). */
	.zo-anchor-nav--pdp .zo-anchor-nav__drawer:not([hidden]) { display: block; }
}
@media (min-width: 1024px) {
	.zo-anchor-nav--pdp .zo-anchor-nav__product-title { font-size: var(--wp--custom--font-size--18); line-height: 24px; }
}
@media (min-width: 1440px) {
	/* XL (#328, node 6811-13076): trigger shows icon + "Seiteninhalt" label (ghost, hug width),
	   actions gap 24; the drawer becomes a 360px right-hand panel over a 20% scrim instead of
	   the fullscreen overlay. Below XL everything stays as before (Philipp #328). */
	.zo-anchor-nav--pdp .zo-anchor-nav__actions { gap: var(--wp--preset--spacing--40); /* 24 */ }
	.zo-anchor-nav--pdp .zo-anchor-nav__trigger { width: auto; padding: 12px 16px; }
	.zo-anchor-nav--pdp .zo-anchor-nav__trigger-icon svg { width: 16px; height: 16px; }
	.zo-anchor-nav--pdp .zo-anchor-nav__trigger-label { display: inline; }
	.zo-anchor-nav__drawer { background: rgba(0, 0, 0, 0.2); }
	.zo-anchor-nav__drawer-panel { left: auto; width: 360px; }
}

/* Editor-Vorschau der PDP-Bar: In-Content-Pills + Kondensat statisch untereinander zeigen. */
.zo-anchor-nav--pdp.zo-anchor-nav--editor .zo-anchor-nav__sticky { position: static; opacity: 1; visibility: visible; }
.zo-anchor-nav--pdp.zo-anchor-nav--editor .zo-anchor-nav__incontent { display: flex; }

/* ============================================================
   Component: Terminliste (Block zo/event-list) — Figma 5298-40780 (#56) ·
   Responsive Card Calendar 5570-563, Sync 2026-08-10 (#176), Spec eventlist.md ·
   Übersichtsseiten-Rhythmus 5568-40006 + 5603-60212/61907/64539, Sync 2026-08-21 (#230).
   States: :hover/:focus-visible am CTA (LG/XL) bzw. an der Karten-Klickfläche (SM/MD) ·
   empty · disabled n/a. Breakpoints (Container-Query am __list, für H2/Filterleiste am
   Wrapper): SM <592 gestapelte Karte · MD ≥592 Zeile · LG/XL ≥944 Zeile mit Aside
   (944 = 1024 − 2×40, filter-bar.md) · XL-Gaps ≥1328 (= Content-Cap, #230).
   ============================================================ */
.zo-eventlist, .zo-eventlist * { box-sizing: border-box; }

/* Wrapper ist selbst Container: misst durch das Rail-Padding die Content-Breite (288/592/
   960/1328 — gleiche Schwellen wie __list) und trägt so die @container-Stufen für H2 und
   Filterleisten-Abstand, die AUSSERHALB von __list liegen (Self-Styling-Falle: __list kann
   die eigene Query nicht beantworten). Die Row-Queries lösen weiter am näheren __list auf. */
.zo-eventlist { container-type: inline-size; }

/* H2 „Alle Termine" über der Filterleiste (Übersichtsseite 5568:40006, #230). */
.zo-eventlist__main-heading { margin: 0 0 var(--wp--preset--spacing--30); font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 26px; color: var(--wp--preset--color--foreground); } /* SM 20/26, mb 16 */

/* Rail-Wrapper; die Monats-Liste (Flex-Spalte, 80er-Gap) sitzt in __list, damit die
   Filterleiste (#101) darüber nicht im 80er-Gap hängt. container-type misst hier die
   Content-Breite (Rail liegt auf dem alignfull-Wrapper, Muster .zo-content-box). */
.zo-eventlist__list { container-type: inline-size; display: flex; flex-direction: column; gap: var(--zo-module-gap); } /* Monats-Gap = Modul-Reihe 40/56/64/96 (5568:40006 = itemSpacing der Seiten-Frames, module-gap.md, #230) */
/* Block ist align:full (block.json) und liegt geschachtelt in main+entry-content (beide
   has-global-padding) → die alignfull-Margins brechen nur teilweise aus, container-relative
   Rail würde sich doppelt einrücken. Deshalb sauber zum Viewport ausbrechen (50%-50vw) und dann
   per --zo-rail-bleed auf die kanonische Rail einrücken — bündig zu Header/Footer (#99, Philipp-
   Review). Content cappt 1328 (Grid #128), ab 1440 zentriert. */
.zo-eventlist.alignfull {
	width: 100vw;
	max-width: 100vw;
	margin-inline: calc(50% - 50vw);
	/* Viewport-relatives Rail-Bleed: der Token --zo-rail-bleed nutzt 100% (hier = gepaddeter
	   Container, nicht Viewport) → an XL+ falsche Zentrierung. Da der Block auf 100vw ausbricht,
	   das Bleed direkt aus dem Viewport rechnen: Inset bis der Content 1328 cappt, dann zentriert. */
	padding-inline: max(var(--zo-rail-inset), calc(50vw - var(--zo-rail-max) / 2));
}

.zo-eventlist__month-group { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--30); } /* SM/MD 16 — LG/XL 32 unten (#230) */

.zo-eventlist__heading { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 24px; color: var(--wp--preset--color--foreground); } /* SM 18/24 — MD 20/26, LG/XL 32/42 unten (#230) */

.zo-eventlist__rows { display: flex; flex-direction: column; gap: 12px; } /* Karten-Gap 12, alle Breakpoints (5568:40006 &co., kein 12er-Token, #230) */

/* Basis = SM-Karte (<592): Datum-Kasten volle Breite, Body gestapelt, Preis-Fußzeile.
   Ein Grid je Zeile trägt alle drei Layouts — nur Spalten/Areas wechseln je Schwelle. */
.zo-eventlist__row { position: relative; display: grid; grid-template-columns: 100%; grid-template-areas: "date" "body" "aside"; background: var(--wp--preset--color--white); }

.zo-eventlist__date { grid-area: date; height: 144px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; background: var(--wp--preset--color--grey-light); }

.zo-eventlist__day { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--64); font-weight: 700; line-height: 76px; color: var(--wp--preset--color--primary); } /* Display MD 64/76 (Typo-Frame 6216:73445, sync 2026-08-19, #207) */

/* Range „28-31" bleibt im SM 64px; erst ab MD 32px (Figma-Varianten Date Type=Range). */

.zo-eventlist__month { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; color: var(--wp--preset--color--primary); } /* 14 */

.zo-eventlist__body { grid-area: body; min-width: 0; display: flex; flex-direction: column; padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--30) 0; } /* 16, unten übernimmt __aside */

.zo-eventlist__flags { margin-bottom: 12px; }

.zo-eventlist__title { margin: 0 0 var(--wp--preset--spacing--30) 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 22px; color: var(--wp--preset--color--foreground); } /* 16/22, mb 16 */

.zo-eventlist__meta { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }

.zo-eventlist__meta-item { display: inline-flex; align-items: center; gap: 6px; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; color: var(--wp--preset--color--grey); white-space: nowrap; }

.zo-eventlist__meta-item svg { width: 12px; height: 12px; flex: 0 0 auto; }

/* SM/MD: Preis-Fußzeile rechtsbündig im Body-Raster; Padding 16 = Gap Meta→Preis + Kartenrand. */
.zo-eventlist__aside { grid-area: aside; display: flex; align-items: center; justify-content: flex-end; gap: var(--wp--preset--spacing--40); padding: var(--wp--preset--spacing--30); }

.zo-eventlist__price { display: inline-flex; align-items: baseline; gap: 6px; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; color: var(--wp--preset--color--primary); white-space: nowrap; } /* 14/20 */
/* Angebot: regulärer Preis durchgestrichen + gedämpft, Angebotspreis normal (Philipp #63). */
.zo-eventlist__price-old { font-weight: 400; color: var(--wp--preset--color--grey); text-decoration: line-through; }
.zo-eventlist__price-now { color: inherit; }

/* SM/MD: Button ist im Design hidden — der CTA-Anker wird zur unsichtbaren Klickfläche über
   der ganzen Karte (Entscheidung 1a, Philipp #176); URL/target/rel identisch zum LG-Button. */
.zo-eventlist__cta { position: absolute; inset: 0; z-index: 1; }

.zo-eventlist__cta svg { display: none; }

.zo-eventlist__cta:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }

/* --- MD ≥592: Zeile — Datum-Spalte 142 stretcht, Meta horizontal, Preis-Fußzeile bleibt.
   H2/Filterleiste lösen am Wrapper-Container auf, der Rest am __list (gleiche Breite). --- */
@container (min-width: 592px) {
	.zo-eventlist__main-heading { margin-bottom: var(--wp--preset--spacing--40); font-size: var(--wp--custom--font-size--24); line-height: 32px; } /* 24/32, mb 24 */
	.zo-eventlist__heading { font-size: var(--wp--custom--font-size--20); line-height: 26px; } /* 20/26 */
	.zo-eventlist__row { grid-template-columns: 142px minmax(0, 1fr); grid-template-rows: 1fr auto; grid-template-areas: "date body" "date aside"; }
	.zo-eventlist__date { height: auto; }
	.zo-eventlist__day--range { font-size: var(--wp--custom--font-size--32); line-height: 42px; }
	.zo-eventlist__meta { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--wp--preset--spacing--40); } /* 24 */
}

/* --- LG/XL ≥944: Zeile mit Aside rechts (Preis + runder Pfeil-CTA) --- */
@container (min-width: 944px) {
	.zo-eventlist__main-heading { margin-bottom: var(--wp--preset--spacing--50); font-size: var(--wp--custom--font-size--40); line-height: 52px; } /* 40/52, mb 32 */
	.zo-eventlist__heading { font-size: var(--wp--custom--font-size--32); line-height: 42px; } /* 32/42 */
	.zo-eventlist__month-group { gap: var(--wp--preset--spacing--50); } /* 32 */
	.zo-eventlist__row { grid-template-columns: 142px minmax(0, 1fr) auto; grid-template-rows: auto; grid-template-areas: "date body aside"; min-height: 142px; }
	.zo-eventlist__body { padding: var(--wp--preset--spacing--40); } /* 24 rundum */
	.zo-eventlist__title { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-eventlist__meta { gap: var(--wp--preset--spacing--50); } /* 32 */
	.zo-eventlist__meta-item { font-size: var(--wp--preset--font-size--small); line-height: 20px; } /* 14/20 */
	.zo-eventlist__meta-item svg { width: 16px; height: 16px; }
	.zo-eventlist__aside { align-self: center; padding: 0 var(--wp--preset--spacing--40) 0 0; } /* 24 */
	.zo-eventlist__price { font-size: var(--wp--preset--font-size--medium); line-height: 22px; } /* 16/22 */
	/* Runder Icon-CTA 48×48 (Figma 5570-563): bewusste Marken-Ausnahme rund — von Philipp
	   bestätigt (#176, wie Akkordeon), Präzedenz .zo-footer__social-btn. Stroke liegt im
	   Design innen → inset-Shadow statt border. */
	.zo-eventlist__cta { position: static; display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 50%; box-shadow: inset 0 0 0 4px var(--wp--preset--color--primary); background: var(--wp--preset--color--white); color: var(--wp--preset--color--primary); }
	.zo-eventlist__cta::after { content: ""; position: absolute; inset: 0; } /* whole row stays clickable on LG (#352 B1a) */
	.zo-eventlist__cta svg { display: block; width: 18px; height: 18px; flex: 0 0 auto; }
	.zo-eventlist__cta:hover, .zo-eventlist__cta:focus-visible { background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); outline: none; }
}

/* Flags in der Terminliste: 20px-Höhe, 12px-Icon (Design 5298) · Popular = inline dunkles Flag. */
.zo-eventlist .zo-kat-flag { height: 20px; }

.zo-eventlist .zo-kat-flag svg, .zo-eventlist__flag-popular svg { width: 12px; height: 12px; }

.zo-eventlist__flag-popular { display: inline-flex; align-items: center; gap: 6px; height: 20px; padding: 4px 8px 4px 6px; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1; white-space: nowrap; background: var(--wp--preset--color--foreground); color: var(--wp--preset--color--white); }

.zo-eventlist__flag-popular svg { width: 16px; height: 16px; flex: 0 0 auto; }

.zo-eventlist__empty { font-size: var(--wp--preset--font-size--medium); color: var(--wp--preset--color--grey); }

/* Terminliste: Luft der Filterleiste (#101) zur ersten Monatsgruppe jetzt aus der
   Übersichtsseite belegt (5568:40006 &co., #230): 32/40/56/64 — Query löst am
   .zo-eventlist-Wrapper auf (Container-Breite = Content 288/592/960/1328). Gefilterte
   Zeilen/leere Monatsgruppen werden per [hidden] ausgeblendet (schlägt das Flex-display
   der Basis). H2-Abstand zur Filterleiste: XL-Stufe hier, SM/MD/LG in den Blöcken oben. */
.zo-eventlist .zo-filterbar { margin-bottom: var(--wp--preset--spacing--50); } /* SM 32 */
@container (min-width: 592px) {
	.zo-eventlist .zo-filterbar { margin-bottom: var(--wp--preset--spacing--60); } /* MD 40 */
}
@container (min-width: 944px) {
	.zo-eventlist .zo-filterbar { margin-bottom: 56px; } /* LG — kein 56er-Token (wie --zo-module-gap-Reihe) */
}
@container (min-width: 1328px) {
	.zo-eventlist .zo-filterbar { margin-bottom: var(--wp--preset--spacing--70); } /* XL 64 */
	.zo-eventlist__main-heading { margin-bottom: var(--wp--preset--spacing--60); } /* XL mb 40 (fs bleibt 40/52) */
}

.zo-eventlist__row[hidden], .zo-eventlist__month-group[hidden] { display: none; }

/* ============================================================
   Component: Filter-Bar / Custom-Dropdown  (Issue #101, SM-Mini-Drawer #102)
   Figma 5308-29620 (Bar) + 5308-27062 (Dropdown) · Spec docs/figma-specs/filter-bar.md
   Wiederverwendbar: Terminliste jetzt, Produkt-Archiv als Folge-Issue. Client-side
   Filtern + Chips + Zähler via assets/js/zo-filter-bar.js.
   States: Toggle :hover/:focus-visible · .is-open · .is-active (Auswahl) ·
           Option :hover/:focus-visible/.is-selected · Chip-Remove/Reset :hover ·
           Drawer offen/zu via [hidden] + html.zo-filterbar-lock (Scroll-Lock).
           Leer/Fehler: n/a (rein clientseitig).
   Breakpoints (Container-Query am .zo-filterbar, misst die Content-Box; Schwellen =
           Figma-Viewport − 2×Rail, Herleitung in der Spec): <592 SM: EIN „Filter"-
           Button + Fullscreen-Mini-Drawer (#102, Muster wie .zo-anchor-nav__drawer;
           Drawer selbst hängt per JS-Portal an body — außerhalb der Query) ·
           ≥592 MD: Facetten fluid in gleichen Dritteln, Kopf-Gap 40 ·
           ≥944 LG/XL: Facette 256px fixed. Liste = Buttonbreite.
   ============================================================ */
/* Drawer separat listen: er hängt zur Laufzeit per JS-Portal an body, außerhalb von .zo-filterbar. */
.zo-filterbar, .zo-filterbar *, .zo-filterbar__drawer, .zo-filterbar__drawer * { box-sizing: border-box; }

.zo-filterbar { container-type: inline-size; }

.zo-filterbar__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; }

.zo-filterbar__facets { display: flex; flex-wrap: wrap; gap: 16px; }

.zo-filterbar__facet { position: relative; }

.zo-filterbar__toggle { display: inline-flex; align-items: center; gap: 8px; height: 48px; padding: 0; border: 0; border-bottom: 4px solid var(--wp--preset--color--foreground); background: none; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 1; color: var(--wp--preset--color--foreground); cursor: pointer; }

.zo-filterbar__toggle.is-open, .zo-filterbar__toggle.is-active { border-bottom-color: var(--wp--preset--color--primary); }

.zo-filterbar__toggle:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }

.zo-filterbar__label { white-space: nowrap; }

.zo-filterbar__dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--wp--preset--color--primary); flex: 0 0 auto; }

.zo-filterbar__dot[hidden] { display: none; }

.zo-filterbar__chevron { width: 18px; height: 18px; flex: 0 0 auto; transition: transform 0.15s ease; }

.zo-filterbar__toggle.is-open .zo-filterbar__chevron { transform: rotate(180deg); }

.zo-filterbar__list { position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; min-width: 100%; width: max-content; max-width: 320px; max-height: 264px; overflow-y: auto; margin: 0; padding: 0; list-style: none; background: var(--wp--preset--color--white); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.08); }

.zo-filterbar__option { display: flex; align-items: center; justify-content: space-between; gap: 12px; height: 48px; padding: 0 12px; margin-top: -1px; border: 1px solid var(--wp--preset--color--grey-light); font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1; color: var(--wp--preset--color--foreground); cursor: pointer; }

.zo-filterbar__option:first-child { margin-top: 0; }

.zo-filterbar__option:hover { background: var(--wp--preset--color--paper); }

.zo-filterbar__option:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: -2px; }

.zo-filterbar__option.is-selected { color: var(--wp--preset--color--primary); }

.zo-filterbar__check { width: 18px; height: 18px; flex: 0 0 auto; color: var(--wp--preset--color--primary); visibility: hidden; }

.zo-filterbar__option.is-selected .zo-filterbar__check { visibility: visible; }

.zo-filterbar__count { flex: 0 0 auto; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1; color: var(--wp--preset--color--grey); white-space: nowrap; }

.zo-filterbar__active { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 32px; }

.zo-filterbar__active[hidden] { display: none; }

.zo-filterbar__chip { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px; border: 2px solid var(--wp--preset--color--foreground); font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1; color: var(--wp--preset--color--foreground); }

.zo-filterbar__chip-remove { display: inline-flex; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; }

.zo-filterbar__chip-remove svg { width: 16px; height: 16px; }

.zo-filterbar__chip-remove:hover, .zo-filterbar__chip-remove:focus-visible { color: var(--wp--preset--color--primary); }

.zo-filterbar__reset { display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0; background: none; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 1; color: var(--wp--preset--color--primary); cursor: pointer; }

.zo-filterbar__reset[hidden] { display: none; }

.zo-filterbar__reset svg { width: 16px; height: 16px; }

.zo-filterbar__reset:hover, .zo-filterbar__reset:focus-visible { text-decoration: underline; }

/* MD ≥592 (= Figma-Viewport 640 − 2×24 Rail): Facetten füllen die Zeile in gleichen Dritteln,
   Zähler rechtsbündig mit min. 40 Kopf-Gap (Figma MD: 592 − 40 − 65 = 487 FILL). Button-Innen-
   layout space-between: Label bündig links, Punkt+Chevron bündig rechts; Unterstrich volle
   Breite. Offene Liste = exakt Buttonbreite. */
@container (min-width: 592px) {
	.zo-filterbar__head { flex-wrap: nowrap; gap: 40px; }
	.zo-filterbar__facets { flex: 1 1 0; flex-wrap: nowrap; min-width: 0; }
	.zo-filterbar__facet { flex: 1 1 0; }
	.zo-filterbar__toggle { width: 100%; }
	.zo-filterbar__label { margin-right: auto; }
	.zo-filterbar__list { width: 100%; min-width: 0; max-width: none; }
}

/* LG/XL ≥944 (= Figma-Viewport 1024 − 2×40 Rail): Dropdowns 256px fixed statt fluid
   (Figma LG/XL: Facetten-Container 800 = 3×256 + 2×16). */
@container (min-width: 944px) {
	.zo-filterbar__facets { flex: 0 0 auto; }
	.zo-filterbar__facet { flex: 0 0 256px; }
}

/* --- SM <592 (#102, Figma 5308-29620 Viewport=SM): Dropdowns + Chip-Zeile weichen dem einen
   „Filter"-Button (volle Containerbreite, Optik = Desktop-Toggle); Zähler rutscht linksbündig
   darunter (Kopf-Gap 16). Chips leben hier nur im Drawer (der ist portaled, die Query trifft
   ihn nicht — der :not-Schutz gilt dem No-JS-Fall). --- */
.zo-filterbar__drawer-toggle { display: none; }

@container (width < 592px) {
	.zo-filterbar__facets { display: none; }
	.zo-filterbar__active:not(.zo-filterbar__active--drawer) { display: none; }
	.zo-filterbar__drawer-toggle { display: inline-flex; width: 100%; }
	.zo-filterbar__drawer-toggle .zo-filterbar__label { margin-right: auto; }
}

/* --- Mini-Drawer (#102): Fullscreen-Overlay, Muster + Maße wie .zo-anchor-nav__drawer
   (Padding 64/24, Close 64×64 transparent statt Figmas weißem r100-Kreis — auf weißem Grund
   deckungsgleich, Konsistenz vor Einzelfall). Content scrollt (Auslauf 80), X + „Fertig"
   bleiben stehen. --- */
.zo-filterbar__drawer { position: fixed; inset: 0; z-index: 1000; }

.zo-filterbar__drawer[hidden] { display: none; }

.zo-filterbar__drawer-panel { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--wp--preset--color--white); }

.zo-filterbar__drawer-body { flex: 1 1 auto; overflow-y: auto; padding: 64px 24px 80px; }

.zo-filterbar__drawer-close { position: absolute; top: 0; right: 0; z-index: 1; display: inline-flex; align-items: center; justify-content: center; width: 64px; height: 64px; padding: 0; border: 0; background: transparent; color: var(--wp--preset--color--primary); cursor: pointer; }

.zo-filterbar__drawer-close svg { display: block; width: 24px; height: 24px; }

.zo-filterbar__drawer-close:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: -2px; }

.zo-filterbar__drawer-title { margin: 0 0 24px; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 26px; color: var(--wp--preset--color--foreground); }

/* Im Drawer ersetzt der 24er-Abstand das Desktop-margin-top; „Aktive Filter"-Label bricht als
   volle Flex-Zeile vor die Chips (Gap 12 = Chip-Gap). */
.zo-filterbar__active--drawer { margin: 0 0 24px; }

.zo-filterbar__active-title { flex: 0 0 100%; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; color: var(--wp--preset--color--foreground); }

.zo-filterbar__groups { display: flex; flex-direction: column; gap: 40px; }

.zo-filterbar__group-label { display: block; margin-bottom: 12px; font-size: var(--wp--preset--font-size--small); font-weight: 700; line-height: 20px; color: var(--wp--preset--color--foreground); }

/* Gruppen-Liste: nur horizontale Linien (Container oben 1px, Items unten 1px — Figma
   individualStrokeWeights, anders als das Desktop-Popup mit Vollrahmen). */
.zo-filterbar__group-list { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--wp--preset--color--grey-light); background: var(--wp--preset--color--white); }

.zo-filterbar__group-list .zo-filterbar__option { margin-top: 0; border-width: 0 0 1px; }

.zo-filterbar__drawer-foot { position: absolute; right: 0; bottom: 0; left: 0; padding: 24px; pointer-events: none; }

.zo-filterbar__drawer-done { pointer-events: auto; display: flex; align-items: center; justify-content: center; width: 100%; height: 48px; padding: 0 16px; border: 0; background: var(--wp--preset--color--primary); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2), 0 0 4px rgba(0, 0, 0, 0.1); font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1; color: var(--wp--preset--color--white); cursor: pointer; }

.zo-filterbar__drawer-done:hover, .zo-filterbar__drawer-done:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }

/* Body-Scroll-Lock bei offenem Drawer (Muster .zo-anchor-nav-lock). */
.zo-filterbar-lock, .zo-filterbar-lock body { overflow: hidden; }

/* ============================================================
   Block: zo/product-grid  (Redakteurs-Produkt-Grid, Issue #14)
   Nutzt die Lernen-Hub-Kachel-Optik (.zo-kat-*) auf beliebigen Seiten.
   Layout/Karten kommen aus den bestehenden .zo-kat-Regeln; hier nur das,
   was außerhalb der Katalog-Seite (.zo-katalog) zusätzlich nötig ist.
   ============================================================ */
.zo-product-grid,
.zo-product-grid * { box-sizing: border-box; }

/* Rail-Behandlung für den align:full-Default (Regression aus #94, 727f234): der Block bekam
   Default align=full, aber nie die interne Rail — Karten klebten auf freien Seiten (/lernen/)
   bei left:0, weil .zo-kat-grid mit justify-content:start im Full-Bleed liegt. Ab ≤1400px
   maskiert die zentrierende Media-Query den Fehler — Beleg deshalb IMMER bei ≥1440 messen.
   Mechanik identisch zu .zo-eventlist.alignfull (#99): sauber auf 100vw ausbrechen, dann
   viewport-relativ auf die Rail einrücken (Content cappt 1328 — Grid #128, ab 1440 zentriert). */
.zo-product-grid.alignfull {
	width: 100vw;
	max-width: 100vw;
	margin-inline: calc(50% - 50vw);
	padding-inline: max(var(--zo-rail-inset), calc(50vw - var(--zo-rail-max) / 2));
}

/* Optionaler Kopf (#279): H2 + Kurzbeschreibung vor Leiste/Grid, nur gerendert wenn
   ausgefuellt — Masse und Stufung identisch zum Listen-Kopf der Content List
   (.zo-content-list__header: Cap 960, Kopf->Inhalt 32/40/48, H2->Intro 12/16/24,
   Intro small->medium ab 1024). Typo der H2 kommt aus .zo-section-heading (#152). */
.zo-product-grid__header { max-width: 960px; margin: 0 0 32px; }

.zo-product-grid__header > * { margin: 0; }

.zo-product-grid__header > .zo-section-heading { margin-bottom: 12px; }

/* Intro typo: .zo-section-intro (#396). */

@media (min-width: 640px) {
	.zo-product-grid__header { margin-bottom: 40px; }
	.zo-product-grid__header > .zo-section-heading { margin-bottom: 16px; }
}

@media (min-width: 1024px) {
	.zo-product-grid__header { margin-bottom: 48px; }
	.zo-product-grid__header > .zo-section-heading { margin-bottom: 24px; }
}

/* Integrierte Filterleiste (#138): Gap Leiste → Karten wie Terminliste (40, filter-bar.md). */
.zo-product-grid .zo-filterbar { margin-bottom: 40px; }

.zo-product-grid .zo-kat-grid { margin-top: 0; }
/* `display:grid` schlaegt das UA-`[hidden]` — Instant-Filter (#16) blendet ein leeres
   Grid sonst nicht aus. Explizit ueberschreiben, analog `__more[hidden]`. */
.zo-product-grid .zo-kat-grid[hidden] { display: none; }

/* Expert:innen-Achse (#222): nur die Expert-Instanz wird Query-Container, damit die
   Card-Expert-Varianten (SM+/LG+, Schwelle 1024) an der Instanzbreite schalten (Muster
   .zo-card-carousel-block im Raster-Layout #200). container-type misst die CONTENT-Box —
   alignfull traegt die Rail als padding, die LG+-Karte greift also ab Rail-INNENbreite
   1024 (Viewport ~1104). Bewusst nicht .zo-product-grid generell: Bestands-Grids bleiben. */
.zo-product-grid--experts { container-type: inline-size; }

.zo-product-grid__empty { margin: 0; font-size: var(--wp--preset--font-size--medium); font-weight: 500; color: var(--wp--preset--color--grey-dark); }

.zo-product-grid__more[hidden] { display: none; }


/* ============================================================
   Block: zo/page-header  (Seiten-Header, Issues #51 + #50 + #224)
   Figma: Events 4896-72704 (XL/LG/MD/SM, Sync 2026-08-21) · Basic 6036-40451 (Viewport x
   Show Picture, Sync 2026-08-21, ersetzt 4937-26948; Color-Achse bleibt Block-Attribut).
   Reflow per Container-Query (Demo §Phase 6): Schwellen = Frame-Breiten
   (>=1440 XL · 1024 LG · 640 MD · <640 SM stacked). Spec: docs/figma-specs/page-header.md.
   States: :hover/:focus-visible an Breadcrumb-Links, Event-Rows, Teaser-Link. empty (Teaser).
   Breakpoints: XL 1440 / LG 1024 / MD 640 / SM 320.
   ============================================================ */
.zo-pgh, .zo-pgh * { box-sizing: border-box; }

.zo-pgh { container-type: inline-size; }

/* Optionales Karo-Muster (#100): full-width hinter dem Banner, sichtbar in den Band-Rändern,
   32px-Zellen. Diese Regel gilt nur noch für EVENTS; basic zeichnet sein Karo nur LG/XL über
   .zo-pgh__inner::before (s. u.), artikel über die eigene Regel. Linien opak primary — der
   ältere 50 %-Mix (Sampling #77) ist überholt, das Set-Render 4896-72704 (Sync 2026-08-21)
   sampelt 1px opak #8359FF und trägt an XL/LG einen 1px-Bottom-Stroke primary (INSIDE).
   Von UNTEN verankert (100% − 1px): die unterste Karo-Linie liegt exakt an der Band-Unterkante
   und IST der Abschluss-Strich — er endet so bei jeder inhaltsgetriebenen Bandhöhe auf einer
   vollen 32er-Reihe (Olaf #224). Unterhalb LG decken die Panels das Band voll ab (Set: MD/SM
   ohne Karo), das Muster ist dort schlicht unsichtbar. */
.zo-pgh--events.has-karo {
	background-image:
		linear-gradient(var(--wp--preset--color--primary) 1px, transparent 1px),
		linear-gradient(90deg, var(--wp--preset--color--primary) 1px, transparent 1px);
	background-size: 32px 32px;
	background-position: 0 calc(100% - 1px), 0 0;
}

.zo-pgh__inner { margin-inline: auto; display: flex; flex-direction: column; }

/* --- Linke Spalte: Breadcrumb + Heading (beide Layouts) --- */
.zo-pgh__main { display: flex; flex-direction: column; min-width: 0; }

.zo-pgh__crumbs { display: flex; align-items: center; flex-wrap: wrap; gap: var(--wp--preset--spacing--20); } /* 8 */

.zo-pgh__crumb { font-family: var(--wp--preset--font-family--body); font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1; text-decoration: none; color: var(--wp--preset--color--grey); }

a.zo-pgh__crumb:hover, a.zo-pgh__crumb:focus-visible { text-decoration: underline; }

.zo-pgh__crumb--current { color: var(--wp--preset--color--foreground); }

.zo-pgh__crumb-sep { display: inline-flex; align-items: center; }

.zo-pgh__crumb-sep svg { width: 12px; height: 12px; }

.zo-pgh__heading { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--20); } /* 8 (Basic h1->Subline) */

.zo-pgh__title { margin: 0; font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: var(--wp--custom--font-size--24); line-height: 1.15; color: inherit; }

.zo-pgh__lead { margin: 0; color: inherit; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1.4; }

/* ---------- EVENTS-Layout (Node 4896-72704) ---------- */
.zo-pgh--events .zo-pgh__inner { max-width: none; } /* SM: gestapelt, volle Breite */

.zo-pgh--events .zo-pgh__main { background: var(--wp--preset--color--white); color: var(--wp--preset--color--foreground); padding: var(--wp--preset--spacing--30); min-height: 272px; } /* pad 16 */

.zo-pgh--events .zo-pgh__heading { margin-top: 12px; gap: var(--wp--preset--spacing--30); } /* bc->h1 12; h1->intro 16 */

/* Termin-Teaser (rechte / untere Spalte) */
.zo-pgh__teaser { display: flex; flex-direction: column; background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); padding: var(--wp--preset--spacing--30); min-height: 300px; } /* pad 16 */

.zo-pgh__teaser-heading { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 1.3; color: var(--wp--preset--color--white); }

.zo-pgh__events { display: flex; flex-direction: column; gap: 2px; margin-top: var(--wp--preset--spacing--30); } /* item-gap 2; heading->list 16 */

.zo-pgh__event { display: flex; align-items: stretch; height: 52px; background: var(--wp--preset--color--white); text-decoration: none; }

.zo-pgh__event-date { flex: 0 0 45px; width: 45px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; background: var(--wp--preset--color--grey-light); } /* #E2E2E2 */

.zo-pgh__event-day { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 1; color: var(--wp--preset--color--primary); }

.zo-pgh__event-month { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1; color: var(--wp--preset--color--primary); }

.zo-pgh__event-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: var(--wp--preset--spacing--10); padding: 0 12px; } /* zentriert, horizontal-pad 12 */

.zo-pgh__event-title { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 1.3; color: var(--wp--preset--color--foreground); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; }

.zo-pgh__event-time { font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1; color: var(--wp--preset--color--grey); }

.zo-pgh__event-arrow { display: none; flex: 0 0 48px; width: 48px; align-items: center; justify-content: center; background: var(--wp--preset--color--white); color: var(--wp--preset--color--primary); }

.zo-pgh__event-arrow svg { width: 18px; height: 18px; }

.zo-pgh__event:hover .zo-pgh__event-title, .zo-pgh__event:focus-visible .zo-pgh__event-title { text-decoration: underline; }

.zo-pgh__events-empty { margin: 0; font-size: var(--wp--preset--font-size--small); font-weight: 500; color: var(--wp--preset--color--white); }

.zo-pgh__teaser-link { display: inline-flex; align-self: flex-start; align-items: center; gap: var(--wp--preset--spacing--20); margin-top: var(--wp--preset--spacing--30); font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 1; color: var(--wp--preset--color--white); text-decoration: none; } /* gap list->link 16 */

.zo-pgh__teaser-link svg { width: 18px; height: 18px; }

.zo-pgh__teaser-link:hover, .zo-pgh__teaser-link:focus-visible { text-decoration: underline; }

/* ---------- BASIC-Layout (COMPONENT_SET 6036-40451, Viewport x Show Picture — #224) ----------
   Basis = SM (<640): randlos gestapeltes Band (Panel + optional 16:9-Bild darunter), kein
   Karo/Strich. MD (>=640) nur größere Pads/Fonts. Erst LG/XL (>=1024) liegen auf der Rail,
   zweispaltig (Bild fix 420 rechts — zwei Viewports, eine Bildbreite; ersetzt den alten
   33.75 %-Rail-Anteil aus 459/1360), mit Karo + 1px-Abschluss-Strich. */
.zo-pgh--basic { position: relative; isolation: isolate; } /* Anker + Stacking-Scope fürs Karo-::before (LG/XL) */

.zo-pgh--basic .zo-pgh__main { justify-content: flex-start; gap: var(--wp--preset--spacing--60); padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30); } /* SM: gap bc->h1 40, pad 24/16 */

.zo-pgh--basic .zo-pgh__crumb { line-height: 16px; letter-spacing: 0.01em; } /* Set: 12/16, ls 0.12 — das generische lh 1 macht MD/SM-Baender 4px zu flach */

.zo-pgh--basic .zo-pgh__media { position: relative; overflow: hidden; aspect-ratio: 16 / 9; } /* SM 320x180 · MD 640x360, randlos unter dem Panel */

/* Bild absolut, damit die natürliche Bildhöhe die Flex-Zeile nicht aufbläht (percentage-height braucht definite Parent-Höhe). */
.zo-pgh--basic .zo-pgh__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

/* Organisation logo (#275): logos are rarely 16:9 — contain on a white panel with breathing
   room instead of cover, so nothing gets cropped or blown up. */
.zo-pgh--basic.has-logo .zo-pgh__media { background: var(--wp--preset--color--white); }
.zo-pgh--basic.has-logo .zo-pgh__media img { object-fit: contain; padding: var(--wp--preset--spacing--50); /* 32 */ box-sizing: border-box; }

.zo-pgh--basic .zo-pgh__heading { max-width: 680px; } /* Heading-Instanz maxWidth MD/SM (Set 6036-40451, #377) */

.zo-pgh--basic .zo-pgh__title { font-size: var(--wp--custom--font-size--24); line-height: 32px; }

.zo-pgh--basic .zo-pgh__lead { font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 1.2; } /* Subline: nicht im Set 6036, bleibt für Bestand (Profil #77) */

/* Basic band: lila only (#348 removed hell-lila/weiss) */
.zo-pgh--basic.is-color-lila .zo-pgh__main { background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white); }

.zo-pgh--basic.is-color-lila .zo-pgh__crumb { color: var(--wp--preset--color--white); }

/* ---------- MD (>=640): Events zweispaltig ---------- */
@container (min-width: 640px) {
	.zo-pgh--events .zo-pgh__inner { flex-direction: row; align-items: stretch; }
	.zo-pgh--events .zo-pgh__main { flex: 1 1 0; min-height: 300px; padding: var(--wp--preset--spacing--40); } /* pad 24 */
	.zo-pgh--events .zo-pgh__teaser { flex: 1 1 0; padding: var(--wp--preset--spacing--40); }
	.zo-pgh--events .zo-pgh__title { font-size: var(--wp--custom--font-size--24); }
}

/* ---------- LG (>=1024) ---------- */
@container (min-width: 1024px) {
	.zo-pgh--events .zo-pgh__inner { max-width: 960px; padding-block: 56px 0; } /* top 56 (Set-Sync 2026-08-21); no bottom inset without karo (#281 B1a) — karo override below */
	/* Mit Karo: unteres Inset so, dass die Standard-Bandhöhe auf n*32+1 landet (56+360+65 = 481)
	   → beim bottom-verankerten Muster liegt dann auch OBEN eine volle Reihe an der Bandkante.
	   Frame selbst ist 472 (56/56) und verletzt Olafs Reihen-Regel — Regel schlägt Frame,
	   gleiche Entscheidung wie basic 349→353 (#224). */
	.zo-pgh--events.has-karo .zo-pgh__inner { padding-block: 56px 65px; }
	.zo-pgh--events .zo-pgh__main { min-height: 360px; padding: var(--wp--preset--spacing--50); } /* pad 32 */
	.zo-pgh--events .zo-pgh__teaser { min-height: 360px; padding: var(--wp--preset--spacing--50); }
	.zo-pgh--events .zo-pgh__title { font-size: var(--wp--custom--font-size--32); }
	.zo-pgh--events .zo-pgh__lead { font-size: var(--wp--preset--font-size--medium); }
	.zo-pgh--events .zo-pgh__heading { gap: var(--wp--preset--spacing--30); } /* h1->intro 16 */
	.zo-pgh__teaser-heading { font-size: var(--wp--custom--font-size--20); }
	.zo-pgh__events { gap: var(--wp--preset--spacing--10); margin-top: var(--wp--preset--spacing--40); } /* gap 4; heading->list 24 */
	.zo-pgh__event { height: 64px; }
	.zo-pgh__event-date { flex-basis: 57px; width: 57px; }
	.zo-pgh__event-day { font-size: var(--wp--custom--font-size--24); }
	.zo-pgh__event-body { padding: 0 var(--wp--preset--spacing--30); } /* horizontal 16 */
	.zo-pgh__event-title { font-size: var(--wp--custom--font-size--18); }
	.zo-pgh__event-arrow { display: flex; }
	.zo-pgh__teaser-link { margin-top: var(--wp--preset--spacing--40); } /* 24 */
}

/* ---------- XL (>=1440) ---------- */
@container (min-width: 1440px) {
	.zo-pgh--events .zo-pgh__inner { max-width: 1328px; padding-block: 56px 0; } /* no bottom inset without karo (#281 B1a) */
	/* Standard-Bandhöhe mit Karo auf n*32+1: 56+398+59 = 513 (Frame 510, s. LG-Kommentar). */
	.zo-pgh--events.has-karo .zo-pgh__inner { padding-block: 56px 59px; }
	.zo-pgh--events .zo-pgh__main { min-height: 398px; padding: var(--wp--preset--spacing--60); } /* pad 40 */
	.zo-pgh--events .zo-pgh__teaser { min-height: 398px; padding: var(--wp--preset--spacing--60); }
	.zo-pgh--events .zo-pgh__title { font-size: var(--wp--custom--font-size--48); }
	.zo-pgh--events .zo-pgh__heading { gap: var(--wp--preset--spacing--40); } /* h1->intro 24 */
	.zo-pgh__teaser-heading { font-size: var(--wp--custom--font-size--24); }
	.zo-pgh__events { margin-top: var(--wp--preset--spacing--50); } /* heading->list 32 */
	.zo-pgh__teaser-link { margin-top: var(--wp--preset--spacing--50); } /* 32 */
}

/* ---------- Basic · MD (>=640): weiter gestapelt, größere Pads ---------- */
@container (min-width: 640px) {
	.zo-pgh--basic .zo-pgh__main { gap: var(--wp--preset--spacing--70); padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40); } /* gap 64, pad 32/24 */
	.zo-pgh--basic .zo-pgh__title { font-size: var(--wp--custom--font-size--32); line-height: 42px; }
}

/* ---------- Basic · LG (>=1024): zweispaltig auf der Rail, Karo + Abschluss-Strich ---------- */
@container (min-width: 1024px) {
	.zo-pgh--basic .zo-pgh__inner { flex-direction: row; align-items: stretch; width: var(--zo-rail-w); padding-block: 56px 0; } /* Rail = Grid-Alias (#128): 1328/16-24-32 · no bottom inset without karo (#281 B1a), karo override below */
	/* Panel-Breite fix Rail−420 neben dem Bild. Show Picture=No (Set-Update #377, 2026-09-28):
	   ohne Bild ist das Panel das letzte Kind und füllt die ganze Rail (1328/960) — ersetzt
	   den 420er-Spacer aus #224. Heading max 960 (Instanz-maxWidth LG+). */
	.zo-pgh--basic .zo-pgh__main { flex: 0 0 calc(100% - 420px); justify-content: space-between; gap: var(--wp--preset--spacing--60); padding: var(--wp--preset--spacing--60); min-height: 236px; } /* pad 40 */
	.zo-pgh--basic .zo-pgh__main:last-child { flex-basis: 100%; }
	.zo-pgh--basic .zo-pgh__heading { max-width: 960px; }
	.zo-pgh--basic .zo-pgh__media { flex: 0 0 420px; aspect-ratio: auto; min-height: 236px; }
	.zo-pgh--basic .zo-pgh__lead { font-size: var(--wp--custom--font-size--24); }
	/* Karo (opak, 32px-Pitch — natives Set-Render 6036-40451 schlägt den älteren 50 %-Mix #77)
	   nur LG/XL. Von UNTEN verankert (100% − 1px): die unterste Karo-Linie liegt damit exakt
	   an der Band-Unterkante und IST der 1px-Abschluss-Strich (individualStrokeWeights
	   bottom=1 primary, INSIDE) — der Strich endet so bei jeder Bandhöhe auf einer vollen
	   32er-Reihe (Olaf #224). Standardfall 353 hoch = 56 + 236 + 61 → oben liegt ebenfalls
	   eine Linie exakt auf der Bandkante. Als ::before, weil sich .zo-pgh als Container
	   nicht selbst per @container stylen kann (block-css-fallen.md §Self-Styling). */
	.zo-pgh--basic.has-karo .zo-pgh__inner { padding-block: 56px 61px; }
	.zo-pgh--basic.has-karo .zo-pgh__inner::before {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		background-image:
			linear-gradient(var(--wp--preset--color--primary) 1px, transparent 1px),
			linear-gradient(90deg, var(--wp--preset--color--primary) 1px, transparent 1px);
		background-size: 32px 32px;
		background-position: 0 calc(100% - 1px), 0 0;
	}
}

/* ---------- Basic · XL (>=1440): H1 48, Panel rechts stärker abgesetzt ---------- */
@container (min-width: 1440px) {
	.zo-pgh--basic .zo-pgh__main { padding-right: calc(2 * var(--wp--preset--spacing--60)); } /* 80 — Frame setzt den Titel von der Bildkante ab */
	.zo-pgh--basic .zo-pgh__title { font-size: var(--wp--custom--font-size--48); line-height: 62px; }
}

/* ---------- ARTIKEL-Layout (COMPONENT_SET 6031-37168, #146) ----------
   Hell-lila Spalte (Brotkrümel + h1 oben, Autorzeile unten) + optionales Bild. Das Bild ist
   die einzige Stellschraube der Textlaufweite: ab LG belegt es feste 432, die Spalte nimmt
   den Rest der Schiene (XL 1328−432 = 896 · LG 960−432 = 528) — deshalb steht hier NIRGENDS
   eine zweite Breitenzahl. Darunter (MD/SM) wird gestapelt, das Bild läuft randlos 16:9.
   Bandhöhe LG/XL 544 = 56 + 432 + 56; MD/SM inhaltsgetrieben (694/334 · 536/356).
   Spec + Node-ID je Zahl: docs/figma-specs/header-artikel.md.
   States: :hover/:focus-visible an Brotkrümel-Links und an Teilen/Drucken. „Teilen" ohne
   Funktion (Philipp #146, kein Kanal entschieden) — kein disabled, es ist gewollt inert.
   Breakpoints: SM <640 · MD 640 · LG 1024 · XL 1440. Basis = SM. */
.zo-pgh--artikel { background-color: var(--wp--preset--color--paper); }

/* Karo im Artikel-Band: 1px opakes primary auf paper, 32er-Raster — am Set-Render gesampelt
   (Spec §6). Von UNTEN verankert (#224, wie basic/events): die unterste Linie liegt exakt an
   der Band-Unterkante und schließt das Band bei jeder Höhe auf einer Linie ab — vorher endete
   die fixe 544er-Höhe (17*32) 1px VOR der Abschluss-Linie. Bandhöhe bleibt 544 (Frame-treu);
   die oberste Reihe ist dadurch 31px statt 32 — unsichtbar, unten gewinnt Olafs Reihen-Regel. */
.zo-pgh--artikel.has-karo {
	background-image:
		linear-gradient(var(--wp--preset--color--primary) 1px, transparent 1px),
		linear-gradient(90deg, var(--wp--preset--color--primary) 1px, transparent 1px);
	background-size: 32px 32px; /* stand bis #224 in der Band-Regel (jetzt events-only) */
	background-position: 0 calc(100% - 1px), 0 0;
}

.zo-pgh--artikel .zo-pgh__inner { width: 100%; max-width: none; }

.zo-pgh--artikel .zo-pgh__main {
	background: var(--wp--preset--color--accent-lilac);
	color: var(--wp--preset--color--foreground);
	justify-content: space-between;
	gap: var(--wp--preset--spacing--40); /* 24 (SM) */
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30); /* 24 / 16 */
}

.zo-pgh__top { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--30); } /* 16 */

/* Brotkrümel bleibt einzeilig (Frame: eine 16px-Zeile). Echte Beitragstitel würden sonst
   umbrechen und die Bandhöhe sprengen — 1:1-Grenze, Spec §8. */
.zo-pgh--artikel .zo-pgh__crumbs { flex-wrap: nowrap; min-width: 0; }

.zo-pgh--artikel .zo-pgh__crumb {
	line-height: 16px;
	letter-spacing: 0.01em; /* 0.12 bei 12px */
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	min-width: 0;
}

.zo-pgh--artikel .zo-pgh__crumb-sep { flex: 0 0 auto; }

.zo-pgh--artikel .zo-pgh__title { font-size: var(--wp--custom--font-size--24); line-height: 32px; }

/* --- Autorzeile (Frame 1171280954) --- */
.zo-pgh__meta { display: flex; flex-direction: column; align-items: flex-start; gap: var(--wp--preset--spacing--40); } /* SM: zwei Zeilen, 24 */

.zo-pgh__author { display: flex; align-items: center; gap: var(--wp--preset--spacing--20); min-width: 0; } /* 8 */

.zo-pgh__avatar { flex: 0 0 auto; width: 48px; height: 48px; border-radius: 50%; object-fit: cover; display: block; }

.zo-pgh__author-text { display: flex; flex-direction: column; min-width: 0; }

/* Name und Organisation bleiben einzeilig — im Frame ist jede Zeile ein eigener
   FILL-Textknoten fester Höhe (22/16 bzw. 20/16). Eine umbrechende Rolle-·-Firma-Subline
   würde die Autorzeile über 48 hinaus wachsen lassen und bei MD/SM die Bandhöhe verschieben
   (gemessen: 56 statt 48). 1:1-Grenze, Spec §8. */
.zo-pgh__author-name,
.zo-pgh__author-org { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.zo-pgh__author-name {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); /* 14 */
	font-weight: 700;
	line-height: 20px;
	letter-spacing: 0.01em;
	color: var(--wp--preset--color--foreground);
}

.zo-pgh__author-org {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--font-size--12);
	font-weight: 500;
	line-height: 16px;
	letter-spacing: 0.01em;
	color: var(--wp--preset--color--grey);
}

.zo-pgh__actions { display: flex; align-items: flex-end; gap: var(--wp--preset--spacing--40); } /* 24 */

/* Teilen/Drucken = Action Link, Icon LEADING (instances 4512:33752 XL/LG, 4512:33749 SM/MD
   of set 4512:33753). Look and states come from §Component: Action-Link (#355); only the
   leading gap (SM 6 / MD 8) and the container stage live here. */
.zo-pgh__action { --zo-action-link-gap: 6px; }

/* Bild: randlos 16:9 unter der Spalte (SM 320×180 · MD 640×360). */
.zo-pgh--artikel .zo-pgh__media { width: 100%; aspect-ratio: 16 / 9; overflow: hidden; }

.zo-pgh--artikel .zo-pgh__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- Artikel · MD (>=640) ---------- */
@container (min-width: 640px) {
	.zo-pgh--artikel .zo-pgh__main { gap: var(--wp--preset--spacing--70); padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40); } /* 64 · 32/24 */
	.zo-pgh--artikel .zo-pgh__title { font-size: var(--wp--custom--font-size--32); line-height: 42px; }
	/* Autorzeile wird eine Zeile: Avatar-Gruppe links, Aktionen rechts, unten bündig.
	   Der Mindestabstand 40 entspricht dem paddingRight der Avatar-Gruppe im Frame. */
	.zo-pgh__meta { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: var(--wp--preset--spacing--60); }
}

/* ---------- Artikel · LG (>=1024): zweispaltig auf der Schiene ---------- */
@container (min-width: 1024px) {
	.zo-pgh--artikel .zo-pgh__inner { flex-direction: row; align-items: flex-start; width: var(--zo-rail-w); padding-block: 56px 0; } /* Rail = Grid-Alias (#128) · no bottom inset without karo (#281 B1a); artikel is always has-karo (544 via override) */
	/* With karo the band keeps its frame-true 544 height (56 + 432 + 56, see band comment above). */
	.zo-pgh--artikel.has-karo .zo-pgh__inner { padding-block: 56px; }
	.zo-pgh--artikel .zo-pgh__main { flex: 1 1 auto; min-width: 0; min-height: 432px; padding: var(--wp--preset--spacing--60); } /* 40 */
	.zo-pgh--artikel .zo-pgh__media { flex: 0 0 432px; width: 432px; aspect-ratio: 1 / 1; }
	.zo-pgh--artikel .zo-pgh__title { font-size: var(--wp--custom--font-size--48); line-height: 62px; }
	.zo-pgh__actions { gap: var(--wp--preset--spacing--50); } /* 32 */
	/* Action Link MD, leading: 16/22 · icon 18 · gap 8 */
	.zo-pgh__action { --zo-action-link-font-size: var(--wp--preset--font-size--medium); --zo-action-link-line-height: 22px; --zo-action-link-icon: 18px; --zo-action-link-gap: 8px; }
	.zo-pgh__author-name { font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	.zo-pgh__author-text { gap: 2px; }
	/* Mit Bild wird bei LG enger gesetzt: Padding 32 statt 40 und die Titel-Variante
	   „H1 Compact" (32/42) — 6031:37230 gegen 6031:37290. */
	.zo-pgh--artikel.has-media .zo-pgh__main { padding: var(--wp--preset--spacing--50); }
	.zo-pgh--artikel.has-media .zo-pgh__title { font-size: var(--wp--custom--font-size--32); line-height: 42px; }
	.zo-pgh--artikel.has-media .zo-pgh__actions { gap: var(--wp--preset--spacing--40); } /* 24 */
}

/* ---------- Artikel · XL (>=1440) ---------- */
@container (min-width: 1440px) {
	/* Rechts 80 statt 40 — der Frame setzt den Titel von der Bildkante ab (6031:37216/37303). */
	.zo-pgh--artikel .zo-pgh__main,
	.zo-pgh--artikel.has-media .zo-pgh__main {
		padding: var(--wp--preset--spacing--60) calc(2 * var(--wp--preset--spacing--60)) var(--wp--preset--spacing--60) var(--wp--preset--spacing--60);
	}
	.zo-pgh--artikel.has-media .zo-pgh__title { font-size: var(--wp--custom--font-size--48); line-height: 62px; }
	.zo-pgh--artikel.has-media .zo-pgh__actions { gap: var(--wp--preset--spacing--50); } /* 32 */
}

/* ============================================================
   Meta Info — Icon-Text-Paare in einer Zeile (Datum, Lesezeit, Ort, …).
   Figma: 5575:16114 COMPONENT „Meta Info" Style=Dense, Items=2, Direction=Horizontal
   (dev-ready) · Item = 4144:33899 „List Icon .item" · sync 2026-08-06.
   Spec: docs/figma-specs/article-meta.md · Issue #147.
   States: n/a (reine Textausgabe, keine Interaktion).
   Breakpoints: keiner — die Zeile bricht bei Platzmangel um (row-gap 8), damit auf SM 320
   kein horizontaler Overflow entsteht; der Entwurf zeichnet nur den einzeiligen Fall.
   Bestandshinweis: `.zo-eventlist__meta-item` und `.zo-card-text__meta-item` bauen dieselbe
   Form noch selbst — Migration ist als Nachbar-Befund in #147 gemeldet, nicht Teil von #147.
   ============================================================ */
.zo-meta-info { display: flex; flex-wrap: wrap; align-items: center;
	column-gap: var(--wp--preset--spacing--50); /* 32: 5575:16114 itemSpacing */
	row-gap: var(--wp--preset--spacing--20); }  /* 8 — Umbruchfall, s. Header */
.zo-meta-info__item { display: inline-flex; align-items: center;
	gap: 6px; /* 4144:33899 itemSpacing — kein Spacing-Token, wie .zo-eventlist__meta-item */
	font-size: var(--wp--preset--font-size--small); font-weight: 500;
	line-height: 20px; letter-spacing: 0.14px; color: var(--wp--preset--color--grey); }
.zo-meta-info__icon { display: inline-flex; flex: 0 0 auto; }
.zo-meta-info__icon svg { display: block; width: 16px; height: 16px; }

/* ============================================================
   Zitat — Anführungs-Icon, Zitattext, Byline (Avatar · Name · Firma).
   Figma: 5826:50231 COMPONENT_SET „Quote Text – Integrated" (Viewport SM+/LG+) ·
   5826:49991 COMPONENT_SET „Quote Text – Standalone" (Viewport SM/MD/LG/XL) — beide dev-ready,
   sync 2026-08-06. Spec: docs/figma-specs/artikel-bausteine.md §2 · Issue #149.
   Zwei Darstellungen, ein Baustein: ohne `align` läuft er in der Textspalte mit (integriert),
   mit `alignwide` wird er größer und ab 1024 zentriert (standalone). Die Breite selbst kommt
   IMMER aus dem Drei-Spuren-Grid (#145) — hier steht keine.
   States: n/a (reine Textausgabe). Breakpoints: SM <640 · MD 640 · LG 1024.
   ============================================================ */
.zo-quote, .zo-quote * { box-sizing: border-box; }
.zo-quote {
	--zo-quote-icon: 18px;      /* 5826:50241 Icon-Instanz */
	--zo-quote-icon-gap: 8px;   /* 5826:50241 Body Copy paddingTop */
	--zo-quote-fs: var(--wp--custom--font-size--18);
	--zo-quote-lh: 24px;
	--zo-quote-byline-gap: 16px; /* 5826:50241 Body Copy paddingBottom */
	--zo-quote-max: none;
	--zo-quote-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg transform='translate(1 4.5)'%3E%3Cpath d='M11.0341 15L14.9845 0L22 0L16.2786 15L11.0341 15ZM0 15L3.95046 0L10.9659 0L5.24458 15L0 15Z'/%3E%3C/g%3E%3C/svg%3E");
	display: flex; flex-direction: column; align-items: flex-start;
}
.zo-quote::before { content: ""; flex: 0 0 auto;
	width: var(--zo-quote-icon); height: var(--zo-quote-icon);
	background: var(--wp--preset--color--primary);
	-webkit-mask: var(--zo-quote-mark) center / contain no-repeat;
	        mask: var(--zo-quote-mark) center / contain no-repeat; }
/* core/quote bringt Rahmen + Eigenabstände mit — hier trägt nur die Typo. */
.zo-quote .zo-quote__text { width: 100%; max-width: var(--zo-quote-max);
	margin: var(--zo-quote-icon-gap) 0 0; padding: 0; border: 0;
	font-family: var(--wp--preset--font-family--display); font-weight: 700;
	font-size: var(--zo-quote-fs); line-height: var(--zo-quote-lh);
	color: var(--wp--preset--color--foreground); }
.zo-quote .zo-quote__text > * { margin: 0; font: inherit; color: inherit; }
.zo-quote__byline { display: flex; align-items: center;
	gap: 6px; /* 5826:50241 Avatar label group itemSpacing */
	margin: var(--zo-quote-byline-gap) 0 0; }
.zo-quote__avatar { flex: 0 0 auto; width: 48px; height: 48px; margin: 0; }
.zo-quote__avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%;
	border: 2px solid var(--wp--preset--color--white); }
/* Die Labels bleiben linksbündig, auch wenn die Standalone-Fassung zentriert (5826:49694:
   „Maxi Musterfrau" und „Unternehmen XYZ" starten dort beide bei x=693). */
.zo-quote__labels { text-align: left; }
.zo-quote__name { margin: 0; font-size: var(--wp--preset--font-size--small); font-weight: 700;
	line-height: 20px; letter-spacing: 0.14px; color: var(--wp--preset--color--foreground); }
.zo-quote__org { margin: 0; font-size: var(--wp--custom--font-size--12); font-weight: 500;
	line-height: 16px; letter-spacing: 0.12px; color: var(--wp--preset--color--grey); }

/* Standalone bekommt ab MD eine eigene Stufe (5826:49691), integriert erst ab LG. */
@media (min-width: 640px) {
	.zo-quote.alignwide { --zo-quote-icon: 24px; --zo-quote-icon-gap: 12px;
		--zo-quote-fs: var(--wp--custom--font-size--24); --zo-quote-lh: 32px;
		--zo-quote-byline-gap: 24px; }
}
@media (min-width: 1024px) {
	.zo-quote { --zo-quote-icon: 24px; --zo-quote-icon-gap: 12px;
		--zo-quote-fs: var(--wp--custom--font-size--24); --zo-quote-lh: 32px;
		--zo-quote-byline-gap: 24px; }
	/* 5826:49692/49694: ab LG zentriert, Zitattext auf maxWidth 1100 gedeckelt. */
	.zo-quote.alignwide { --zo-quote-icon: 32px; --zo-quote-icon-gap: 24px;
		/* NICHT --wp--preset--font-size--x-large: das Preset ist fluid (clamp 28–40) und
		   löst bei 1024 auf 36,38 auf — Figma nennt feste 40 je Breakpoint. */
		--zo-quote-fs: var(--wp--custom--font-size--40); --zo-quote-lh: 52px;
		--zo-quote-byline-gap: 32px; --zo-quote-max: 1100px;
		align-items: center; text-align: center; }
}

/* ============================================================
   Info-Box „Tipp" — 4-px-Rahmen ohne Fläche, Label mit Glühbirne, Titel, Fließtext.
   Figma: 5826:52338 COMPONENT_SET „Info Box" (Viewport SM+/LG+, dev-ready), abgeleitet von
   „Content Box .item" 5175:13505 · sync 2026-08-06.
   Spec: docs/figma-specs/artikel-bausteine.md §3 · Issue #149.
   Kein „Hervorgehoben": das Set kennt nur Viewport-Varianten (von Philipp bestätigt, #149).
   States: n/a. Breakpoints: SM+ <1024 · LG+ ab 1024 (Schwelle von Philipp bestätigt).
   ============================================================ */
.zo-infobox, .zo-infobox * { box-sizing: border-box; }
.zo-infobox {
	--zo-ib-pad: var(--wp--preset--spacing--30);       /* 16 — 5826:52339 padding */
	--zo-ib-meta-gap: 12px;                            /* 5826:52339 itemSpacing */
	--zo-ib-text-gap: var(--wp--preset--spacing--20);  /* 8 — 5826:52339 Frame 9 itemSpacing */
	--zo-ib-title-fs: var(--wp--preset--font-size--medium);
	--zo-ib-title-lh: 22px;
	--zo-ib-body-fs: var(--wp--preset--font-size--small);
	--zo-ib-body-lh: 20px;
	--zo-ib-body-ls: 0.14px;
	--zo-ib-bulb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg transform='translate(3.99975 2.001) scale(1.5)'%3E%3Cpath d='M3.98214 10.666L4.6668 10.666L4.6668 7.33267L6.00014 7.33267L6.00014 10.666L6.6848 10.666C6.7728 9.86467 7.18147 9.20333 7.8448 8.48133C7.92014 8.4 8.39947 7.90333 8.45614 7.83267C8.92699 7.24442 9.22213 6.53514 9.30755 5.78651C9.39297 5.03789 9.2652 4.28036 8.93897 3.60116C8.61273 2.92196 8.10129 2.34872 7.46354 1.94745C6.82579 1.54618 6.08767 1.3332 5.33419 1.33304C4.5807 1.33288 3.8425 1.54554 3.20458 1.94654C2.56666 2.34754 2.05497 2.92056 1.72844 3.59962C1.40192 4.27868 1.27383 5.03615 1.35893 5.78482C1.44403 6.53348 1.73886 7.24289 2.20947 7.83133C2.2668 7.90267 2.74747 8.4 2.82147 8.48067C3.48547 9.20333 3.89414 9.86467 3.98214 10.666L3.98214 10.666ZM4.00014 11.9993L4.00014 12.666L6.6668 12.666L6.6668 11.9993L4.00014 11.9993ZM1.16947 8.666C0.541597 7.88153 0.148101 6.93565 0.0343122 5.93731C-0.0794768 4.93898 0.0910696 3.9288 0.526305 3.02316C0.961541 2.11752 1.64376 1.35325 2.49437 0.818388C3.34499 0.283528 4.32939 -0.000160828 5.33419 6.84022e-08C6.33899 0.000160965 7.3233 0.284165 8.17375 0.819297C9.02419 1.35443 9.70616 2.11892 10.1411 3.0247C10.5761 3.93048 10.7463 4.94071 10.6322 5.93901C10.5181 6.93731 10.1243 7.88306 9.49613 8.66733C9.0828 9.182 8.00014 9.99933 8.00014 10.9993L8.00014 12.666C8.00014 13.0196 7.85966 13.3588 7.60961 13.6088C7.35956 13.8589 7.02042 13.9993 6.6668 13.9993L4.00014 13.9993C3.64651 13.9993 3.30738 13.8589 3.05733 13.6088C2.80728 13.3588 2.6668 13.0196 2.6668 12.666L2.6668 10.9993C2.6668 9.99933 1.58347 9.182 1.16947 8.666Z'/%3E%3C/g%3E%3C/svg%3E");
	padding: var(--zo-ib-pad);
	/* strokeAlign INSIDE + strokesIncludedInLayout → border-box, Breite bleibt die der Spur. */
	border: var(--wp--custom--border--emphasis) solid var(--wp--preset--color--primary);
	border-radius: 0;
}
.zo-infobox > * { margin: 0; }
.zo-infobox > * + * { margin-block-start: var(--zo-ib-text-gap); }
.zo-infobox > .zo-infobox__label + * { margin-block-start: var(--zo-ib-meta-gap); }
.zo-infobox__label { display: flex; align-items: flex-start;
	gap: 6px; /* 5826:52339 List Icon .item itemSpacing */
	font-size: var(--wp--preset--font-size--small); font-weight: 500;
	line-height: 20px; letter-spacing: 0.14px; color: var(--wp--preset--color--primary); }
.zo-infobox__label::before { content: ""; flex: 0 0 auto; width: 16px; height: 16px;
	margin-top: 2px; /* 5826:52339 Icon-Frame paddingTop */
	background: var(--wp--preset--color--primary);
	-webkit-mask: var(--zo-ib-bulb) center / contain no-repeat;
	        mask: var(--zo-ib-bulb) center / contain no-repeat; }
.zo-infobox__title { font-family: var(--wp--preset--font-family--display); font-weight: 700;
	font-size: var(--zo-ib-title-fs); line-height: var(--zo-ib-title-lh);
	color: var(--wp--preset--color--foreground); }
.zo-infobox__body, .zo-infobox > p:not(.zo-infobox__label) {
	font-size: var(--zo-ib-body-fs); font-weight: 500; line-height: var(--zo-ib-body-lh);
	letter-spacing: var(--zo-ib-body-ls); color: var(--wp--preset--color--foreground); }
@media (min-width: 1024px) {
	.zo-infobox { --zo-ib-pad: var(--wp--preset--spacing--40);      /* 24 — 5826:52337 */
		--zo-ib-meta-gap: var(--wp--preset--spacing--30);           /* 16 */
		--zo-ib-text-gap: 12px;
		--zo-ib-title-fs: var(--wp--custom--font-size--20); --zo-ib-title-lh: 26px;
		--zo-ib-body-fs: var(--wp--preset--font-size--medium); --zo-ib-body-lh: 22px;
		--zo-ib-body-ls: 0.16px; }
}

/* ============================================================
   Takeaways — 4-px-Rahmen, links die Überschrift, rechts die Punkte mit Pfeil-Marker.
   Figma: 5980:52598 COMPONENT_SET „Highlight Box" (Viewport SM/MD/LG/XL, dev-ready),
   sync 2026-08-06. Spec: docs/figma-specs/artikel-bausteine.md §4 · Issue #149.
   Kein „Hervorgehoben": die Box ist per Definition rail-breit (von Philipp bestätigt, #149) —
   das Pattern setzt `alignwide` fest, die Kante selbst kommt aus dem Grid (#145).
   Pfeil-Marker per CSS-mask auf core/list (Präzedenz #65) — die Liste bleibt frei editierbar.
   States: n/a. Breakpoints: SM <640 · MD 640 · LG 1024 · XL 1440.
   ============================================================ */
.zo-takeaways, .zo-takeaways * { box-sizing: border-box; }
.zo-takeaways {
	--zo-tw-pad: var(--wp--preset--spacing--30);   /* 16 — 5980:52594 padding */
	--zo-tw-gap: var(--wp--preset--spacing--30);   /* 16 — Titel → Liste, vertikal */
	/* NICHT --wp--preset--font-size--large: das Preset ist fluid (clamp 20–32) und löst bei
	   320 auf 20 auf — Figma nennt feste 32 (5980:52594). */
	--zo-tw-title-fs: var(--wp--custom--font-size--32);
	--zo-tw-title-lh: 42px;
	--zo-tw-item-gap: 12px;                        /* 5980:52594 .list itemSpacing */
	--zo-tw-icon: 18px;
	--zo-tw-icon-gap: 6px;
	/* Center the arrow on the first text line — deliberate deviation from Figma's
	   top-aligned icon frame (#301 B2a, Philipp 2026-09-21). Resolves per breakpoint
	   via the icon/line-height vars: SM (20-18)/2 = 1px (= old Figma paddingTop),
	   MD (20-32)/2 = -6px, LG (22-48)/2 = -13px. */
	--zo-tw-icon-top: calc((var(--zo-tw-body-lh) - var(--zo-tw-icon)) / 2);
	--zo-tw-body-fs: var(--wp--preset--font-size--small);
	--zo-tw-body-lh: 20px;
	--zo-tw-body-ls: 0.14px;
	--zo-tw-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z'/%3E%3C/svg%3E");
	display: grid; grid-template-columns: 1fr; gap: var(--zo-tw-gap);
	padding: var(--zo-tw-pad);
	border: var(--wp--custom--border--emphasis) solid var(--wp--preset--color--primary);
	border-radius: 0;
}
.zo-takeaways > * { margin: 0; }
/* Editor canvas only (.wp-block exists only there): the editor's block-gap rule outranks
   the reset above and pushed the list 24px below the title (#301, finding 1). */
.zo-takeaways > .wp-block { margin-block-start: 0; }
.zo-takeaways__title { font-family: var(--wp--preset--font-family--display); font-weight: 700;
	font-size: var(--zo-tw-title-fs); line-height: var(--zo-tw-title-lh);
	color: var(--wp--preset--color--primary); }
.zo-takeaways__list { list-style: none; padding: 0;
	display: flex; flex-direction: column; gap: var(--zo-tw-item-gap); }
.zo-takeaways__list li { position: relative; margin: 0;
	padding-left: calc(var(--zo-tw-icon) + var(--zo-tw-icon-gap));
	font-family: var(--wp--preset--font-family--body); font-weight: 500;
	font-size: var(--zo-tw-body-fs); line-height: var(--zo-tw-body-lh);
	letter-spacing: var(--zo-tw-body-ls); color: var(--wp--preset--color--foreground); }
.zo-takeaways__list li::before { content: ""; position: absolute; left: 0;
	top: var(--zo-tw-icon-top); width: var(--zo-tw-icon); height: var(--zo-tw-icon);
	background: var(--wp--preset--color--primary);
	-webkit-mask: var(--zo-tw-arrow) center / contain no-repeat;
	        mask: var(--zo-tw-arrow) center / contain no-repeat; }
@media (min-width: 640px) {
	.zo-takeaways { --zo-tw-pad: var(--wp--preset--spacing--50);   /* 32 — 5980:52595 */
		--zo-tw-gap: var(--wp--preset--spacing--40);               /* 24 */
		--zo-tw-title-fs: var(--wp--custom--font-size--48); --zo-tw-title-lh: 62px;
		--zo-tw-item-gap: var(--wp--preset--spacing--30);          /* 16 */
		--zo-tw-icon: 32px; --zo-tw-icon-gap: 12px; }
}
@media (min-width: 1024px) {
	/* 5980:52596: zwei gleich breite Spalten, Titel links, Liste rechts (960 = 4+40+408+56+408+40+4). */
	.zo-takeaways { --zo-tw-pad: var(--wp--preset--spacing--60);   /* 40 */
		--zo-tw-gap: 56px;
		--zo-tw-title-fs: var(--wp--custom--font-size--80); --zo-tw-title-lh: 96px; /* Display LG 80/96 (6216:73445, sync 2026-08-19, #207) */
		--zo-tw-item-gap: var(--wp--preset--spacing--40);          /* 24 */
		--zo-tw-icon: 48px; --zo-tw-icon-gap: var(--wp--preset--spacing--40);
		--zo-tw-body-fs: var(--wp--preset--font-size--medium); --zo-tw-body-lh: 22px;
		--zo-tw-body-ls: 0.16px;
		grid-template-columns: 1fr 1fr; align-items: start; }
}
@media (min-width: 1440px) {
	.zo-takeaways { --zo-tw-gap: var(--wp--preset--spacing--70); } /* 64 — 5980:52597 */
}

/* ============================================================
   Video-Vorschau — Block-Style „zo-video" auf core/image.
   Figma: 5768:94 COMPONENT_SET „Video" (dev-ready) · sync 2026-08-06.
   Spec: docs/figma-specs/artikel-bausteine.md §1 · Issue #149.
   Figmas Video-Komponente ist die Bild-Komponente plus Play-Knopf — nur der steht hier.
   Der Knopf sitzt auf der Mitte des BILDES, nicht der Figur (die trägt noch die
   Bildunterschrift): `margin-top: 28.125%` = halbe Bildhöhe, weil Prozent-Margins gegen die
   BREITE des Containers auflösen und das Bild 16:9 ist (0,5625 / 2).
   States: der Knopf ist Optik (pointer-events: none) — :hover/:focus-visible liegen am Link,
   den die Redaktion am Bild setzt; active/disabled n/a.
   Breakpoints: Knopf 48 unter 1024, 64 ab 1024 (5768:33 / 5768:73).
   ============================================================ */
.is-style-zo-video { position: relative;
	--zo-video-btn: 48px;
	--zo-video-play: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg transform='translate(8 4.4342)'%3E%3Cpath d='M8.394 7.56574L2 3.30274L2 11.8287L8.394 7.56574ZM11.376 7.98174L0.777 15.0477C0.701706 15.0978 0.61423 15.1266 0.523891 15.1309C0.433553 15.1352 0.343733 15.115 0.263999 15.0723C0.184265 15.0296 0.117604 14.9661 0.0711136 14.8885C0.0246236 14.8109 4.67204e-05 14.7222 0 14.6317L0 0.499742C4.67204e-05 0.4093 0.0246236 0.320564 0.0711136 0.242985C0.117604 0.165406 0.184265 0.10189 0.263999 0.0592012C0.343733 0.0165124 0.433553 -0.00375036 0.523891 0.000571232C0.61423 0.00489283 0.701706 0.0336371 0.777 0.0837421L11.376 7.14974C11.4445 7.1954 11.5006 7.25726 11.5395 7.32983C11.5783 7.4024 11.5986 7.48344 11.5986 7.56574C11.5986 7.64805 11.5783 7.72908 11.5395 7.80165C11.5006 7.87422 11.4445 7.93608 11.376 7.98174Z'/%3E%3C/g%3E%3C/svg%3E");
}
/* 16:9-Ausschnitt trägt der Style selbst, damit der Knopf auch außerhalb des Artikels sitzt
   (im Artikel setzt ihn zusätzlich die Bild-Regel im PAGES-Abschnitt — gleiche Kante). */
.is-style-zo-video img { display: block; width: 100%; height: auto;
	aspect-ratio: 16 / 9; object-fit: cover; }
.is-style-zo-video::before, .is-style-zo-video::after { content: ""; position: absolute;
	top: 0; left: 50%; margin-top: 28.125%; transform: translate(-50%, -50%);
	pointer-events: none; }
.is-style-zo-video::before { width: var(--zo-video-btn); height: var(--zo-video-btn);
	border-radius: 50%; background: var(--wp--preset--color--primary); }
.is-style-zo-video::after { width: 24px; height: 24px;
	background: var(--wp--preset--color--white);
	-webkit-mask: var(--zo-video-play) center / contain no-repeat;
	        mask: var(--zo-video-play) center / contain no-repeat; }
@media (min-width: 1024px) {
	.is-style-zo-video { --zo-video-btn: 64px; } /* 5768:73 Button .base */
}

/* ============================================================
   Component: Table (.zo-table-Skin)  — Issue #179
   Quelle: Figma Component-Set „Table" 6184:3086 (Abruf 2026-08-11,
   Spec docs/figma-specs/table.md). Achsen Viewport=SM+|LG+ × Overflow=false|true.
   EIN Skin, zwei Adopter: figure.wp-block-table table (core/table) und
   .woocommerce table.shop_table (Konto-Bestellungen, künftig Cart/Checkout) —
   Adopter-Muster wie .zo-btn (check-sections AUSNAHMEN). Die Neutralisierung des
   Woo-Smallscreen-Stackings liegt in INTEGRATIONS §Woo-Tabellen.
   Adopters 3+4 (#315): the order-confirmation tables (totals + downloads) on
   /checkout/order-received/. They carry no shop_table class, so they join each
   selector group as wrapper + table.__table — the doubled class yields (0,2,1),
   which beats Woo's block CSS (0,1,1/0,1,2) regardless of load order (Woo prints
   block styles during render, after the theme stylesheet; lesson from #314).
   Their Woo-specific extras (tfoot, cell alignment, address/notice boxes) live
   in INTEGRATIONS §Woo-Bestellbestaetigung.
   WARUM @media UND NICHT @container: Der Wechsel ist im Figma eine
   Viewport-Achse (wie .zo-section-heading #152) — Beleg: die Variante
   Viewport=LG+/Overflow=true hat Container 640 und trotzdem die LG-Maße.
   Overflow: JS (zo-table-scroll.js) wickelt die Tabelle in
   .zo-table-wrap > .zo-table-scroll und toggelt .is-overflowing; der Fade
   sitzt als ::after auf dem NICHT scrollenden Wrap (abspos im Scroller
   scrollte mit). Ohne JS scrollt die core-Figure per Block-Library-Default;
   nur der Fade fehlt (progressive enhancement).
   States: hover/focus/active n/a (Set kennt nur Viewport×Overflow).
   Breakpoints: 1024 (Viewport).
   ============================================================ */
figure.wp-block-table table,
.woocommerce table.shop_table,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table {
	width: 100%;
	margin: 0;
	border: 0;
	border-radius: 0;                  /* Woo rundet shop_table — Marke scharfkantig */
	border-collapse: collapse;         /* Row-Borders liegen am tr */
	background: transparent;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	line-height: 20px;
	letter-spacing: 0.01em;            /* Figma ls 1 % */
	color: var(--wp--preset--color--foreground);
}
figure.wp-block-table table th,
figure.wp-block-table table td,
.woocommerce table.shop_table th,
.woocommerce table.shop_table td,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table th,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table td,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table th,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table td {
	border: 0;                         /* Block-Library gibt td/th 1px-Borders, Woo border-top */
	padding: 12px 16px;                /* Figma Cell SM: 12 block × 16 inline */
	vertical-align: middle;
	background: transparent;
	font-size: inherit;                /* Woo setzt .875em auf td */
	line-height: inherit;
}
figure.wp-block-table table td,
.woocommerce table.shop_table td,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table td,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table td { font-weight: 500; }
figure.wp-block-table table th,
.woocommerce table.shop_table th,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table th,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table th { font-weight: 700; text-align: start; }
/* Kopfzeile: Flieder, ohne Border (Figma: strokes leer; Block-Library: thead 3px bottom) */
figure.wp-block-table table thead,
.woocommerce table.shop_table thead,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table thead,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table thead { border: 0; }
figure.wp-block-table table thead tr,
.woocommerce table.shop_table thead tr,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table thead tr,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table thead tr {
	border: 0;
	background: var(--wp--preset--color--accent-lilac);
}
/* Daten-Zeile 45/55 = Inhalt 44/54 + 1px Border (Figma strokeAlign INSIDE, top 0) */
figure.wp-block-table table tbody,
.woocommerce table.shop_table tbody,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table tbody,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table tbody { border: 0; }
figure.wp-block-table table tbody tr,
.woocommerce table.shop_table tbody tr,
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table tbody tr,
.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table tbody tr {
	border: 1px solid var(--wp--preset--color--grey-mid);
	border-top: 0;
	background: transparent;           /* Row liegt auf dem Seiten-Papier */
}
@media (min-width: 1024px) {
	figure.wp-block-table table,
	.woocommerce table.shop_table,
	.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table,
	.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table {
		font-size: var(--wp--preset--font-size--medium);
		line-height: 22px;
	}
	figure.wp-block-table table th,
	figure.wp-block-table table td,
	.woocommerce table.shop_table th,
	.woocommerce table.shop_table td,
	.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table th,
	.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table td,
	.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table th,
	.wc-block-order-confirmation-downloads table.wc-block-order-confirmation-downloads__table td {
		padding: 16px 24px;            /* Figma Cell LG: 16 block × 24 inline */
	}
}
/* Overflow-Scroll + Fade (JS-Wrapper, s. Header) */
.zo-table-wrap { position: relative; }
.zo-table-scroll { overflow-x: auto; }
figure.wp-block-table:has(> .zo-table-wrap) { overflow-x: visible; } /* Scrollen übernimmt der Wrapper */
.zo-table-wrap::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	width: 48px;                       /* Figma Overflow Indicator 6184:3086 */
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.15s;
	/* Figma-Stops: Paper α0 → α0.85 bei 60 % → α1 (Sampling: #F1F0F5 = 85 % Paper über Lilac) */
	background: linear-gradient(to right,
		transparent,
		color-mix(in srgb, var(--wp--preset--color--paper) 85%, transparent) 60%,
		var(--wp--preset--color--paper));
}
.zo-table-wrap.is-overflowing::after { opacity: 1; }

/* ============================================================
   Component: Text-Bild-Kombination  (.zo-text-image)  — Issue #188
   Figma Component-Set „Text-Image-Combo" 6311:235 (Sync 2026-08-13).
   Spec: docs/figma-specs/text-image-combo.md · Block zo/text-image
   (Server-Render inc/text-image-block.php erzeugt dieses Markup; Überschrift/
   CTA optional = leeres Attribut; Bildposition = Klasse is-style-zo-image-right
   am Media-Figure, Spaltentausch via :has() am Inner; H2-Typo =
   .zo-section-heading, #152. Bestands-Markup des ersetzten Patterns
   zo/section-text-image rendert über dieselben Klassen unverändert weiter).
   Button = .zo-btn-Adopter (eine Button-Quelle, #86): XL-Größe ab 1024,
   darunter MD-Maße (Stufung ist Figma-Viewport-Achse, kein --md-Modifier);
   Pfeil per Mask --zo-icon-arrow-right (kein Inline-SVG im Content).
   Sektion liegt in main UND entry-content (beide has-global-padding) →
   viewport-relativ ausbrechen, Rail innen als .zo-container
   (content-rail.md §align:full, Muster .zo-topics).
   States: Button/Action-Link erben ihre Komponenten-States; Bild/Text nicht
   interaktiv → n/a. Leer/Laden/Fehler: n/a (statisches Element).
   Breakpoints (@media, Foundation): SM <640 · MD 640 · LG 1024 · XL 1440.
   ============================================================ */
.zo-text-image { box-sizing: border-box; width: 100vw; margin-inline: calc(50% - 50vw); }

.zo-text-image * { box-sizing: border-box; }

/* Gestapelt (SM/MD): Bild → Text, Gap 16/24. Grid statt Flex: dieselbe Struktur
   trägt ab LG die 2-Spalten-Teilung. */
.zo-text-image .zo-text-image__inner { display: grid; grid-template-columns: 100%; row-gap: 16px; align-items: start; }

/* WP-Flow-Gap (24px) neutralisieren — §1.6-Gotcha. */
.zo-text-image .zo-text-image__inner > * { margin: 0; }

/* Width is never cropped, height never exceeds 16:9 (#331, deviation from the
   #188 Figma spec's fixed 16:9 crop): wider images show in full at their natural
   height; square/portrait images are capped at 16:9 and cropped top/bottom.
   cqi = media width, hence the inline-size container on the figure. */
.zo-text-image__media { container-type: inline-size; }
.zo-text-image__media img { display: block; width: 100%; height: auto; max-height: calc(100cqi * 9 / 16); object-fit: cover; }

.zo-text-image__content { display: flex; flex-direction: column; align-items: flex-start; }

.zo-text-image__content > * { margin: 0; }

/* Vertikalrhythmus aus dem Set: H2→Body 12/16/24 · Body→Button 24/24/32
   (Figma paddingBottom der Heading-Instanz + itemSpacing des Content-Frames).
   Als margin-bottom, damit gelöschte optionale Blöcke keine Lücken hinterlassen. */
.zo-text-image__content > .zo-section-heading { margin-bottom: 12px; }

/* Body-Absätze: seit dem InnerBlocks-Umbau (#188, 3. Runde) klassenlose core/paragraph
   direkt in __content (Editor identisch) — .zo-text-image__body deckt Alt-Bestand
   (text-Attribut-Fallback + statisches Pattern-Markup) weiter ab. */
.zo-text-image__body,
.zo-text-image__content > p {
	margin-bottom: 24px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 20px;
	letter-spacing: 0.01em;
	color: var(--wp--preset--color--foreground);
}

.zo-text-image__content > :last-child { margin-bottom: 0; }

/* CTA-Pfeil (trailing, currentColor) — Look/States kommen vom .zo-btn-Adopter. */
.zo-text-image .wp-block-button__link::after {
	content: "";
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	background: currentColor;
	-webkit-mask: var(--zo-icon-arrow-right) center / contain no-repeat;
	        mask: var(--zo-icon-arrow-right) center / contain no-repeat;
}

/* Unter 1024: Button in MD-Maßen (= .zo-btn--md; Stufung am Viewport, s. Header). */
@media (max-width: 1023.98px) {
	.zo-text-image .wp-block-button__link { height: 48px; padding: 0 16px; gap: 8px; font-size: var(--wp--preset--font-size--small); line-height: 20px; }
	.zo-text-image .wp-block-button__link::after { width: 16px; height: 16px; }
}

@media (min-width: 640px) {
	.zo-text-image .zo-text-image__inner { row-gap: 24px; }
	.zo-text-image__content > .zo-section-heading { margin-bottom: 16px; }
}

@media (min-width: 1024px) {
	.zo-text-image .zo-text-image__inner { grid-template-columns: 1fr 1fr; column-gap: 64px; }
	.zo-text-image__content > .zo-section-heading { margin-bottom: 24px; }
	.zo-text-image__body,
	.zo-text-image__content > p { margin-bottom: 32px; font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
	/* Bild rechts: LG-Spalten sind symmetrisch — Reihenfolge tauschen genügt. */
	.zo-text-image__inner:has(> .is-style-zo-image-right) > .zo-text-image__media { order: 2; }
}

@media (min-width: 1440px) {
	/* XL: asymmetrische Teilung 544 · Gap 80 · 704 (Rail 1328) — als Proportion,
	   exakt bei gecapptem Container (content-rail.md §Muster für Measure-Solls). */
	.zo-text-image .zo-text-image__inner { grid-template-columns: 544fr 704fr; column-gap: 80px; }
	.zo-text-image__inner:has(> .is-style-zo-image-right) { grid-template-columns: 704fr 544fr; }
}

/* ============================================================
   Component: Action-Link  (.is-style-zo-action-link · .zo-pgh__action)  — #188, #212, #355, #359
   Figma set "Action Link" 4512:33753 (❖ BASE COMPONENTS → Link, dev-ready; named
   "Active Link" until #208 — the WIP set 4498:34321 that #188 guessed from is empty).
   Spec: docs/figma-specs/action-link.md. Re-validated 2026-09-25 (#355): all 60
   variants unchanged since the 2026-08-19 fetch.
   ONE component, two markups (merged in #355; inline-SVG consumers added in #359):
   - Icon TRAILING: .is-style-zo-action-link .wp-block-button__link, arrow via ::after
     (zo/text-image ctaType action-link, content list, partner card, LearnDash CTA,
     account course cards).
   - Icon LEADING: .zo-pgh__action (<button> + inline SVG, article header share/print;
     instances 4512:33752/4512:33749). Sets only its leading gap + container stage.
   - Inline SVG, not focusable (<span>): .zo-card-article__link (trailing; the card <a>
     carries hover/focus) and .zo-course__action-status (leading, static marker in
     foreground — not clickable, so no hover and cursor auto).
   Size stage = bundle of four custom properties, SM is the fallback:
     --zo-action-link-font-size  small 14 | medium 16
     --zo-action-link-line-height 20px     | 22px
     --zo-action-link-icon        16px     | 18px
     --zo-action-link-gap         trailing 4 | 6 · leading 6 | 8
   The stage is an instance choice, not a viewport switch: the base style steps at
   1024 (@media), content list at 640, partner card stays SM, page header steps per
   @container. A consumer switches the whole bundle, never a single value.
   Hover = colour change to #6842DB (violet-dark), NO underline (textDecoration empty
   in all 60 variants). Focus ring = 2px #1A1A1A (foreground), strokeAlign OUTSIDE →
   outline-offset 0. NOT built: Disabled (#C2C2C2, 1.8:1 on white) — no consumer.
   Must stay AFTER .zo-text-image in the cascade (beats the .zo-btn adopter on equal
   specificity by order).
   States: :hover (violet-dark) · :focus-visible (ring 2px foreground, offset 0)
   · disabled n/a.
   Breakpoints: base style @media SM/MD <1024 · LG+ ≥1024.
   ============================================================ */
.is-style-zo-action-link .wp-block-button__link,
.zo-pgh__action,
.zo-card-article__link,
.zo-course__action-status {
	display: inline-flex;
	align-items: center;
	gap: var(--zo-action-link-gap, 4px);
	height: auto;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--zo-action-link-font-size, var(--wp--preset--font-size--small));
	font-weight: 700;
	line-height: var(--zo-action-link-line-height, 20px);
	letter-spacing: 0.01em;
	color: var(--wp--preset--color--primary);
	cursor: pointer;
}

.is-style-zo-action-link .wp-block-button__link::after {
	content: "";
	flex: 0 0 auto;
	width: var(--zo-action-link-icon, 16px);
	height: var(--zo-action-link-icon, 16px);
	background: currentColor;
	-webkit-mask: var(--zo-icon-arrow-right) center / contain no-repeat;
	        mask: var(--zo-icon-arrow-right) center / contain no-repeat;
}

.zo-pgh__action svg,
.zo-card-article__link svg,
.zo-course__action-status svg { flex: 0 0 auto; width: var(--zo-action-link-icon, 16px); height: var(--zo-action-link-icon, 16px); }

.is-style-zo-action-link .wp-block-button__link:hover,
.is-style-zo-action-link .wp-block-button__link:focus-visible { background: none; text-decoration: none; }

/* Hover = colour change (the icon follows via currentColor), no underline. */
.is-style-zo-action-link .wp-block-button__link:hover,
.zo-pgh__action:hover { color: var(--wp--custom--color--violet-dark); }

.is-style-zo-action-link .wp-block-button__link:focus-visible,
.zo-pgh__action:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 0; }

/* Mouse click (:focus without :focus-visible): theme.json sets a global 4px foreground
   outline on the button element's :focus (decided for the buy buttons) via
   `:root :where()` (0-1-0) and would win here otherwise (#206). Keyboard ring stays. */
.is-style-zo-action-link .wp-block-button__link:focus:not(:focus-visible) { outline: none; }

@media (min-width: 1024px) {
	/* MD trailing: 16/22 · icon 18 · gap 6 */
	.is-style-zo-action-link .wp-block-button__link { --zo-action-link-font-size: var(--wp--preset--font-size--medium); --zo-action-link-line-height: 22px; --zo-action-link-icon: 18px; --zo-action-link-gap: 6px; }
}

/* ============================================================
   Component: Content List  (.zo-content-list)  — Issue #189
   Figma Component-Set „Content List" 6317:66823 (Sync 2026-08-13).
   Spec: docs/figma-specs/content-list.md · Blöcke zo/content-list +
   zo/content-list-item (Server-Render inc/content-list-block.php erzeugt
   dieses Markup; Kopf/Zeilen-Überschrift/Link optional = leeres Attribut).
   Zeile: Trennlinie oben (jede, auch die erste) + zwei Layouts über
   `has-image` aus dem Render — mit Bild: Bild links · Text rechts
   (XL 544·80·704), ohne Bild: H3 links · Text rechts (XL 542·80·706,
   Figma-Werte differieren bewusst um 2px je Type). H2-Typo =
   .zo-section-heading (#152); Action-Link = .is-style-zo-action-link (#188),
   hier ab 640 in der großen Stufe (Node-Werte aller MD-Varianten — der
   generische Stil stuft erst bei 1024, deshalb der Scope-Override; muss in
   der Kaskade NACH .is-style-zo-action-link stehen).
   Sektion liegt in main/entry-content (has-global-padding) → viewport-relativ
   ausbrechen, Rail innen als .zo-container (Muster .zo-text-image).
   States: Action-Link erbt seine Komponenten-States; Bild/Text nicht
   interaktiv → n/a. Leer/Laden/Fehler: n/a (statisches Element).
   Breakpoints (@media, Foundation): SM <640 · MD 640 · LG 1024 · XL 1440.
   ============================================================ */
.zo-content-list { box-sizing: border-box; width: 100vw; margin-inline: calc(50% - 50vw); }

.zo-content-list * { box-sizing: border-box; }

/* Listen-Kopf: H2 + Einleitung, ab LG auf 960 gecappt (XL-Cap aus dem Set,
   unterhalb 1024 ist die Rail ohnehin schmaler). Kopf→Items 32/40/48 als
   margin-bottom am Kopf — fehlt der Kopf, entsteht keine Geister-Lücke. */
.zo-content-list__header { max-width: 960px; margin: 0 0 32px; }

.zo-content-list__header > * { margin: 0; }

.zo-content-list__header > .zo-section-heading { margin-bottom: 12px; }

/* Intro typo: .zo-section-intro (#396). */

/* Zeilen-Stapel: Gap 24/32/40. WP-Flow-Gap (24px) neutralisieren — §1.6-Gotcha. */
.zo-content-list__items { display: grid; grid-template-columns: 100%; row-gap: 24px; }

.zo-content-list__items > * { margin: 0; }

/* Zeile: Trennlinie + Padding 16/24; gestapelt (SM/MD), ab LG zwei Spalten.
   row-gap = H3→Content (ohne Bild) 8/12 bzw. Bild→Content (mit Bild) 16/24. */
.zo-content-list__item {
	display: grid;
	grid-template-columns: 100%;
	row-gap: 8px;
	align-items: start;
	border-top: 1px solid var(--wp--preset--color--grey-mid);
	padding-top: 16px;
}

.zo-content-list__item.has-image { row-gap: 16px; }

.zo-content-list__item > * { margin: 0; }

.zo-content-list__media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }

.zo-content-list__heading {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--18);
	font-weight: 700;
	line-height: 24px;
	color: var(--wp--preset--color--foreground);
}

.zo-content-list__content { display: flex; flex-direction: column; align-items: flex-start; }

.zo-content-list__content > * { margin: 0; }

/* Vertikalrhythmus aus dem Set: H3→Body 8/12/16 · Body→Link 16/16/24
   (paddingBottom der Heading-Instanz + itemSpacing des Content-Frames).
   Als margin-bottom, damit fehlende optionale Teile keine Lücken hinterlassen. */
.zo-content-list__content > .zo-content-list__heading { margin-bottom: 8px; }

/* Body-Absätze: seit dem InnerBlocks-Umbau (#188, 3. Runde) klassenlose core/paragraph
   direkt in __content (Editor identisch) — .zo-content-list__body deckt Alt-Bestand
   (text-Attribut-Fallback) weiter ab. */
.zo-content-list__body,
.zo-content-list__content > p {
	margin-bottom: 16px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 20px;
	letter-spacing: 0.01em;
	color: var(--wp--preset--color--foreground);
}

.zo-content-list__content > :last-child { margin-bottom: 0; }

/* Action-Link-Stufung der Content List: klein nur SM, ab 640 groß — der generische
   Stil stuft erst 1024, deshalb wird die MD-Stufe hier vorgezogen (Gap 6 + 16/22 +
   Icon 18 gehören zusammen). Die SM-Werte kommen seit #212 aus dem Basis-Stil. */

@media (min-width: 640px) {
	.zo-content-list__header { margin-bottom: 40px; }
	.zo-content-list__header > .zo-section-heading { margin-bottom: 16px; }
	.zo-content-list__items { row-gap: 32px; }
	.zo-content-list__item { row-gap: 12px; padding-top: 24px; }
	.zo-content-list__item.has-image { row-gap: 24px; }
	.zo-content-list__content > .zo-content-list__heading { margin-bottom: 12px; }
	.zo-content-list__heading { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
	.zo-content-list .is-style-zo-action-link .wp-block-button__link { --zo-action-link-font-size: var(--wp--preset--font-size--medium); --zo-action-link-line-height: 22px; --zo-action-link-icon: 18px; --zo-action-link-gap: 6px; }
}

@media (min-width: 1024px) {
	.zo-content-list__header { margin-bottom: 48px; }
	.zo-content-list__header > .zo-section-heading { margin-bottom: 24px; }
	.zo-content-list__items { row-gap: 40px; }
	/* Zwei Spalten, top-aligned: LG beide Types 391·80·489 (Proportion,
	   exakt bei gecapptem Container — content-rail.md §Muster für Measure-Solls). */
	.zo-content-list__item,
	.zo-content-list__item.has-image { grid-template-columns: 391fr 489fr; column-gap: 80px; row-gap: 0; }
	.zo-content-list__heading { font-size: var(--wp--custom--font-size--24); line-height: 32px; }
	.zo-content-list__content > .zo-content-list__heading { margin-bottom: 16px; }
	.zo-content-list__body,
	.zo-content-list__content > p { margin-bottom: 24px; font-size: var(--wp--preset--font-size--medium); line-height: 22px; }
}

@media (min-width: 1440px) {
	/* XL: Type-eigene Teilungen (Rail 1328) — Text 542·80·706, Bild 544·80·704. */
	.zo-content-list__item { grid-template-columns: 542fr 706fr; }
	.zo-content-list__item.has-image { grid-template-columns: 544fr 704fr; }
}

/* ---------- Warteliste-Modal (#204) ----------
   Natives <dialog> in der PDP Transaction Card: „Informiert bleiben" öffnet das eingebettete
   FluentForm „Warteliste" (Name, E-Mail, verstecktes product_id). Kein eigener Figma-Frame —
   Optik aus bestehenden Bausteinen belegt: weiße Fläche mit 1px grey-mid-Rand (Muster
   Dropdown/Listen-Flächen), scharfkantig (Marke), Felder = Form-Controls-Basis #170
   (sr-only-Label + Placeholder, Muster Footer #184), Submit = Primär-Button (Muster
   Footer-Newsletter). Öffnen/Schließen: assets/js/zo-waitlist.js; Trigger-Button-Optik
   liegt bei den PDP-Kauf-Buttons (PAGES §PDP).
   States: Close/Submit :hover/:focus-visible · ::backdrop dimmt · disabled n/a.
   Breakpoints: n/a — fluide Breite min(480px, 100vw − 32px), keine eigene Media Query. */
.zo-waitlist {
	box-sizing: border-box;
	width: min(480px, calc(100vw - 32px));
	/* Zentrierung über inset/transform statt margin:auto — die Karten-Regel
	   `.zo-pdph__card > * { margin:0 !important }` würde die UA-Dialog-Margins killen. */
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	max-height: calc(100vh - 32px);
	overflow-y: auto;
	border: 1px solid var(--wp--preset--color--grey-mid);
	border-radius: 0;
	padding: 32px;
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--foreground);
}

.zo-waitlist::backdrop { background: rgba(0, 0, 0, 0.5); }

.zo-waitlist__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }

.zo-waitlist__title { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--24); line-height: 32px; font-weight: 700; color: var(--wp--preset--color--foreground); }

.zo-waitlist__close { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin: 0; border: 0; padding: 0; background: transparent; color: var(--wp--preset--color--foreground); cursor: pointer; }

.zo-waitlist__close:hover { color: var(--wp--custom--color--violet-dark); }

.zo-waitlist__close:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }

.zo-waitlist__sub { margin: 16px 0 0; font-size: var(--wp--preset--font-size--medium); line-height: 1.375; color: var(--wp--preset--color--foreground); }

.zo-waitlist__form { margin-top: 24px; }

/* Feld-Optik, Formular-Layout, Knopf und Bestätigungstext kommen seit #214 aus der
   zentralen Schicht (BASE §Form-Controls · INTEGRATIONS §FluentForms · .zo-btn) — die
   frühere Kopie dieser Werte im Modal ist entfallen. Eigen bleibt nur, was das Modal
   selbst bestimmt: Label unsichtbar (Design zeigt Placeholder, Muster Footer #184),
   Abstand über dem Knopf, Knopf über die volle Modal-Breite. */
.zo-waitlist .ff-el-input--label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.zo-waitlist .ff_submit_btn_wrapper { margin-top: 8px; }
.zo-waitlist .ff-btn-submit { width: 100%; }

/* ---------- Druckbild: Rahmenwerk aus (#146) ----------
   Navigation, Fußbereich, Sprungmarken und die Teilen/Drucken-Leiste selbst verschwinden;
   was bleibt, ist der Inhalt. Steht am Ende von COMPONENTS, weil alle Selektoren hier
   Komponenten sind (tools/css/check-sections.js prüft das auch innerhalb von @media);
   der artikel-spezifische Teil sitzt im PAGES-Abschnitt. */
@media print {
	.site-header, .zo-mainnav, .zo-footer, .zo-anchor-nav, .zo-pgh__actions { display: none; }
	/* Reduced print output (#309): teasers, header event panel and carousel arrows are
	   worthless on paper; the FAQ +/- toggle too — zo-print.js opens every <details>
	   before printing (B1a), so the answers are on the page anyway. */
	.zo-pgh__media, .zo-pgh__teaser,
	.zo-teaser-double, .zo-teaser-uni,
	.zo-card-carousel__controls,
	.zo-faq .zo-faq__toggle { display: none; }
	/* Compact page header (#309): on screen the band fills up to 432px via min-height,
	   inset padding and the karo pattern — on page 1 of a printout that is just a big
	   empty block. Collapse it to title + breadcrumb + meta. Selector tiers mirror the
	   screen rules (variant + state classes) so the print values win by file order. */
	.zo-pgh,
	.zo-pgh--artikel.has-karo, .zo-pgh--basic.has-karo, .zo-pgh--events.has-karo { background: none; }
	.zo-pgh .zo-pgh__inner { padding-block: 0; }
	.zo-pgh .zo-pgh__inner::before, .zo-pgh--basic.has-karo .zo-pgh__inner::before { content: none; }
	.zo-pgh .zo-pgh__main,
	.zo-pgh--artikel .zo-pgh__main, .zo-pgh--artikel.has-media .zo-pgh__main,
	.zo-pgh--basic .zo-pgh__main, .zo-pgh--basic.is-color-lila .zo-pgh__main,
	.zo-pgh--events .zo-pgh__main {
		background: none;
		color: var(--wp--preset--color--foreground);
		min-height: 0;
		gap: var(--wp--preset--spacing--40);
		padding: var(--wp--preset--spacing--40) 0;
	}
	/* Homepage header (#309 follow-up): photo, gradient overlay and the topic jump
	   links are navigation/decoration — off in print. Text back to plain print
	   colors: the white-on-photo scheme would print white on white. */
	.zo-homeheader__img, .zo-homeheader__topics { display: none; }
	.zo-homeheader__media:not(.has-no-image)::after { content: none; }
	.zo-homeheader, .zo-homeheader__media { background: none; }
	.zo-homeheader__body, .zo-homeheader__word { color: var(--wp--preset--color--foreground); }
	/* Card carousels ("Jetzt loslegen" etc.) are link navigation — off in print. */
	.zo-card-carousel-block { display: none; }
	/* No fills on paper (#369, BASE print rule): text that was white on a fill turns ink —
	   filled buttons (same selector list as the fill rule, plus core buttons) and the
	   breadcrumb of the lilac basic header go back to the plain header colors. */
	.zo-btn,
	.ff-btn-submit,
	.zo-lesson__nav-complete .learndash_mark_complete_button,
	.zo-lesson__nav-complete input[type="submit"],
	.zo-text-image .wp-block-button__link,
	.wp-element-button.wp-block-button__link { color: var(--wp--preset--color--foreground); }
	.zo-pgh--basic.is-color-lila .zo-pgh__crumb { color: var(--wp--preset--color--grey); }
	.zo-pgh--basic.is-color-lila .zo-pgh__crumb--current { color: var(--wp--preset--color--foreground); }
}

/* ===================================================================== *
 *  SECTIONS — Sektions-Patterns (Lernhero, Angebot, Entdecken, CTA-Bild)
 * ===================================================================== */

/* ============================================================
   Lernen-Hub  (Figma 4482:39337, Desktop 1440)
   Seite „Lernen im Zukunftsorte Lab." (Slug lernangebote)
   ============================================================ */
/* --- Sektion 2: Hero mit Events-Box  (Scope .zo-lernhero) --- */
.zo-lernhero { box-sizing: border-box; width: 100%; padding: 66px 0 67px;
	background-color: var(--wp--preset--color--paper);
	background-image:
		linear-gradient(var(--zo-grid-line) 1px, transparent 1px),
		linear-gradient(90deg, var(--zo-grid-line) 1px, transparent 1px);
	background-size: 40px 40px; }

.zo-lernhero * { box-sizing: border-box; }

.zo-lernhero__inner { width: var(--zo-rail-w); margin: 0 auto; display: flex; }

.zo-lernhero__text { flex: 0 0 50%; width: 50%; min-height: 400px; background: var(--wp--preset--color--white); padding: 40px; } /* 680/1360 = exakt 1/2 der Rail — auf dem 1328-Grid (#128) = 664; fixe 680 liefen 32px ueber */

.zo-lernhero__crumb { display: flex; align-items: center; gap: 6px; font-size: var(--wp--custom--font-size--12); font-weight: 500;
	color: var(--wp--preset--color--grey); }

.zo-lernhero__crumb a { color: var(--wp--preset--color--grey); text-decoration: none; }

.zo-lernhero__crumb a:hover { color: var(--wp--preset--color--primary); }

.zo-lernhero__crumb span[aria-current] { color: var(--wp--preset--color--foreground); }

.zo-lernhero__crumb .zo-icon { color: var(--wp--preset--color--grey-mid); }

.zo-lernhero__title { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--48); font-weight: 700;
	line-height: 1.3; letter-spacing: -0.01em; margin: 11px 0 0; color: var(--wp--preset--color--foreground); }

.zo-lernhero__lead { margin: 24px 0 0; max-width: 560px; font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 1.5;
	color: var(--wp--preset--color--foreground); }

.zo-lernhero__events { flex: 0 0 50%; width: 50%; min-height: 400px; padding: 40px; color: var(--wp--preset--color--white); /* 1/2 der Rail, s. __text */
	background: var(--wp--preset--color--primary); }

.zo-lernhero__events-title { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--24); font-weight: 700;
	line-height: 1.4; margin: 0; color: var(--wp--preset--color--white); }

.zo-lernhero__list { list-style: none; margin: 32px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.zo-lernhero__event-link { display: flex; align-items: center; height: 64px; background: var(--wp--preset--color--white);
	text-decoration: none; color: var(--wp--preset--color--foreground); }

.zo-lernhero__date { flex: 0 0 57px; display: flex; flex-direction: column; align-items: center; justify-content: center;
	border-right: 1px solid var(--wp--preset--color--grey-light); }

.zo-lernhero__day { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--24); font-weight: 700; line-height: 1.3; }

.zo-lernhero__month { font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1.3; }

.zo-lernhero__event-body { flex: 1 1 auto; min-width: 0; padding: 0 16px; display: flex; flex-direction: column; gap: 2px; }

.zo-lernhero__event-title { font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.zo-lernhero__event-time { font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1.3; color: var(--wp--preset--color--grey); }

.zo-lernhero__event-link .zo-icon { flex: 0 0 auto; margin-right: 16px; color: var(--wp--preset--color--foreground); }

.zo-lernhero__more { display: inline-flex; align-items: center; gap: 8px; margin-top: 32px;
	font-size: var(--wp--preset--font-size--medium); font-weight: 700; color: var(--wp--preset--color--white); text-decoration: none; }

.zo-lernhero__more:hover { opacity: .85; }

@media (max-width: 781px) {
	.zo-lernhero__inner { flex-direction: column; }
	.zo-lernhero__text, .zo-lernhero__events { flex-basis: auto; width: 100%; }
}

/* SM (<640): Best Guess — der Lernen-Hub-Frame 4482:39337 hat kein SM-Design (Playground).
   Typo/Padding folgen dem dev-ready Header-Basic-Set 6036-40451 (Titel 24, Panel-Pad 24/16);
   ohne Stufe sprengte die 48er-H1 ("Zukunftsorte") die 208er-Spalte und riss die Seite auf
   sw=345 bei 320 (Grid-Gate #131). Registry: config/unvalidiert.json "lernhero-sm-stufe". */
@media (max-width: 639px) {
	.zo-lernhero__text, .zo-lernhero__events { padding: 24px 16px; }
	.zo-lernhero__title { font-size: var(--wp--custom--font-size--24); }
}

/* Print (#369): the violet events panel loses its fill (BASE print rule) — its white text turns ink. */
@media print {
	.zo-lernhero__events, .zo-lernhero__events-title, .zo-lernhero__more { color: var(--wp--preset--color--foreground); }
}

/* --- Sektion 3: Angebot-Teaser — seit #278 der Block zo/alert-box (COMPONENTS).
   Der bespoke .zo-angebot-Bau (Lernen-Hub-Frame 4482:39337, Bild 262×131, Hoehe 179)
   ist ersetzt; Pattern zo/teaser-angebot rendert das zentral gepflegte Modul aus dem
   dev-ready Component-Set 4750:18950. Seiten-Abstand: s. Seiten-Scope .zo-lernpage unten. --- */

/* --- Sektion 5: Entdecken-Doppelbild — seit #131 der Block zo/teaser-double (COMPONENTS).
   Der bespoke .zo-entdecken-Bau (Lernen-Hub-Frame 4482:39337, nur LG designt; fixer Content
   lief bei 320 ueber) ist entfernt; Pattern zo/teaser-entdecken rendert das dev-ready
   Component-Set 4750:9834. Seiten-Abstand: s. Seiten-Scope .zo-lernpage unten. --- */

/* --- Sektion 6: CTA-Teaser mit Bild  (Scope .zo-ctabild) --- */
.zo-ctabild { box-sizing: border-box; width: 100%; }

.zo-ctabild * { box-sizing: border-box; }

.zo-ctabild__inner { width: var(--zo-rail-w); margin: 0 auto; display: flex;
	background: var(--wp--preset--color--white); min-height: 448px; }

.zo-ctabild__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; padding: 40px; }

.zo-ctabild__title { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--40); font-weight: 700;
	line-height: 1.2; margin: 0; color: var(--wp--preset--color--foreground); }

.zo-ctabild__sub { margin: 32px 0 0; font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 1.3; color: var(--wp--preset--color--foreground); }

.zo-ctabild__text { margin: 8px 0 0; max-width: 772px; font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 1.5; color: var(--wp--preset--color--grey-dark); }

.zo-ctabild__body .zo-btn { margin-top: auto; align-self: flex-start; }

.zo-ctabild__media { flex: 0 0 448px; width: 448px; height: 448px; }

.zo-ctabild__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 781px) {
	.zo-ctabild__inner { flex-direction: column; }
	.zo-ctabild__media { width: 100%; flex-basis: auto; height: auto; aspect-ratio: 1/1; }
}

/* ===================================================================== *
 *  PAGES — seiten-spezifische Scopes (.single-product/PDP, .zo-katalog, .zo-lernpage, .zo-course)
 * ===================================================================== */

.zo-pdph .wp-block-group .zo-icon { margin-block: 0; }

/* === PDP: Marke ist scharfkantig — Buttons & WC-Elemente rechteckig (nur Produktseite) === */
.single-product .wp-block-button__link,
.single-product .wp-element-button,
.single-product .wc-block-components-button,
.single-product button.single_add_to_cart_button,
.single-product .wp-block-woocommerce-product-button .wp-block-button__link { border-radius: 0; }

.single-product .wp-block-woocommerce-product-image img,
.single-product .wc-block-grid__product-image img,
.single-product .attachment-woocommerce_thumbnail { border-radius: 0; }

/* WC add-to-cart: Mengenfeld + Button auf einer Linie, scharf */
.single-product form.cart .quantity input { border-radius: 0; }

/* =======================================================================
   PDP HEADER .base — 1:1 Nachbau (Figma Node 5076:34309, gelesen 2026-07-15).
   Spec: docs/figma-specs/pdp-header.md. Container 1328 (56px-Inset bei 1440),
   left column 828, gutter 80, transaction card 420 — revalidated per breakpoint
   against page 6503:97080 on 2026-09-27 (#370). Werte token-only.
   ======================================================================= */
/* Kopf weiss auf Seiten-BG paper — der BG kommt seit #174 global aus theme.json
   (styles.color.background = paper), die frühere body.single-product-Regel (#53) entfällt. */
.zo-pdph { background-color: var(--wp--preset--color--white); }
/* Innenrand 40/40 = dev-ready Component „PDP Header .base" 5076:34309 (Rahmen 644). */
.single-product .zo-pdph { padding-top: var(--zo-pdph-pad); padding-bottom: var(--zo-pdph-pad); }
/* CTA-Sprungziel = Transaction-Card im Hero (id="zo-pdp-auswahl" bleibt Anker-Ziel im Markup);
   Offset = Bar-Höhe (80) + 16 Abstand. Scope statt ID-Selektor — .zo-pdph__card ist eindeutig. */
.single-product .zo-pdph__card { scroll-margin-top: 96px; }

/* Breite/Zentrierung kommen aus .zo-container im Markup (Phase-2-Umzug #131). Vorher lag hier
   width: --zo-rail-w in einer constrained Section mit Root-Padding 40 → 100% = 1360, Inner
   rechnete 1296/72 statt 1328/56 (Doppel-Padding; der fruehere Kommentar "trifft ... jetzt
   exakt" war falsch, gemessen 2026-08-19). Section ist jetzt layout:default (ohne Root-Padding). */
/* Gutter 80 from LG up (#370, page 6503:97080: XL 828|80|420, LG 460|80|420). */
.single-product .zo-pdph__inner { display: flex; flex-wrap: nowrap; gap: 80px; align-items: flex-start; }

/* --- Left column (828 at XL 1440, 460 at LG 1024) --- */
/* Fluid main: inner 1328 - 80 - 420 = 828 at XL; shrinks down to 460 at 1024.
   No top padding: breadcrumb and card share the top edge (#370, both y48 in all frames). */
.single-product .zo-pdph__main { flex: 1 1 auto; min-width: 0; box-sizing: border-box; display: flex; flex-direction: column; align-self: stretch; }

/* !important: neutralisiert die WP/theme.json-Auto-Margins (unlayered :where) auf Child-Blöcken.
   max-width none: the constrained layout would cap children at contentSize 720 (#370). */
.single-product .zo-pdph__main > * { margin: 0 !important; max-width: none; }

.single-product .zo-pdph .woocommerce-breadcrumb { font-size: var(--wp--custom--font-size--12); line-height: 16px; font-weight: 500; color: var(--wp--preset--color--foreground); margin: 0; }

.single-product .zo-pdph .woocommerce-breadcrumb a { color: var(--wp--preset--color--grey); text-decoration: none; }

.single-product .zo-pdph__title {
	margin-top: 24px !important;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--48); line-height: 1.29; font-weight: 700; letter-spacing: 0;
	color: var(--wp--preset--color--foreground);
}

/* Wrap row, gap 32 both axes (#370): lead fills (XL 657 beside the topic), below 460 + 32 + topic
   the topic wraps under the lead (LG 1024: lead 460, topic 32 below). */
.single-product .zo-pdph__descrow { margin-top: 32px !important; display: flex; flex-wrap: wrap; gap: 32px; align-items: flex-start; }

.single-product .zo-pdph__lead { flex: 1 1 460px; min-width: 0; font-size: var(--wp--preset--font-size--medium); line-height: 1.375; font-weight: 500; color: var(--wp--preset--color--foreground); margin: 0 !important; }

.single-product .zo-pdph__lead a { color: var(--wp--preset--color--foreground); text-decoration: underline; }

.single-product .zo-pdph__topic { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; }

.single-product .zo-pdph__topic-label { font-size: var(--wp--preset--font-size--small); line-height: 1.4; font-weight: 700; color: var(--wp--preset--color--foreground); }

.single-product .zo-pdph__topic-link { display: inline-flex; align-items: center; gap: 6px; font-size: var(--wp--preset--font-size--medium); line-height: 1.375; color: var(--wp--preset--color--foreground); text-decoration: none; }

.single-product .zo-pdph__topic-link svg { width: 18px; height: 18px; flex: 0 0 auto; }

.single-product .zo-pdph__topic-link span { text-decoration: underline; } /* always underlined per issue #305 (deliberate deviation: Figma node 5076:34309 has decoration none) */

/* Experts sit 56 below the lead row (top-aligned, not at the column bottom), wrap gap 32 (#370). */
.single-product .zo-pdph__experts { margin-top: 56px !important; display: flex; flex-wrap: wrap; gap: 32px; }

.single-product .zo-pdph__expert { display: flex; align-items: center; gap: 12px; }

.single-product .zo-pdph__avatar { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; border: 2px solid var(--wp--preset--color--white); box-sizing: border-box; }

.single-product .zo-pdph__expert-txt { display: flex; flex-direction: column; }

.single-product .zo-pdph__expert-name { font-family: var(--wp--preset--font-family--body); font-weight: 700; font-size: var(--wp--custom--font-size--18); line-height: 1.44; color: var(--wp--preset--color--foreground); }

.single-product .zo-pdph__expert-org { font-size: var(--wp--custom--font-size--12); line-height: 16px; color: var(--wp--preset--color--grey); }

/* --- Transaction Card (420, mint) --- */
.single-product .zo-pdph__card { flex: 0 0 420px; max-width: 420px; box-sizing: border-box; padding: 24px; align-self: flex-start; display: flex; flex-direction: column; }

.single-product .zo-pdph__card > * { margin: 0 !important; }

.single-product .zo-pdph__flags { align-self: flex-start; display: flex; flex-wrap: wrap; gap: 8px; }

.single-product .zo-pdph__flag { align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; height: 24px; box-sizing: border-box; padding: 4px 8px 4px 6px; background: var(--wp--preset--color--foreground); color: var(--wp--preset--color--white); font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1; }

.single-product .zo-pdph__flag svg { width: 16px; height: 16px; flex: 0 0 auto; }

.single-product .zo-pdph__head { margin-top: 16px !important; display: flex; flex-direction: column; gap: 4px; }

.single-product .zo-pdph__offer { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--32); line-height: 1.31; font-weight: 700; color: var(--wp--preset--color--foreground); margin: 0; }

.single-product .zo-pdph__duration { font-size: var(--wp--custom--font-size--12); line-height: 1.33; font-weight: 500; color: var(--wp--preset--color--grey); margin: 0; }

.single-product .zo-pdph__price,
.single-product .zo-pdph__price .woocommerce-Price-amount {
	margin-top: 8px !important;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--32); line-height: 1.31; font-weight: 700;
	color: var(--wp--preset--color--primary) !important;
}

.single-product .zo-pdph__price .woocommerce-Price-amount { margin-top: 0 !important; }

.single-product .zo-pdph__price del { display: none; }

/* VAT exemption note under the price (#401): no Figma frame, reuses the duration line style. */
.single-product .zo-pdph__tax-note { margin-top: 4px !important; font-size: var(--wp--custom--font-size--12); line-height: 1.33; font-weight: 500; color: var(--wp--preset--color--grey); }

/* Gap 8 (Figma: 4) and top-aligned icon: multi-line labels must read as one item,
   with item gaps visibly larger than line gaps (#291; Figma only knows single-line items). */
.single-product .zo-pdph__checklist { margin-top: 16px !important; list-style: none; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.single-product .zo-pdph__check { display: flex; align-items: flex-start; gap: 6px; min-height: 20px; font-size: var(--wp--preset--font-size--small); line-height: 20px; font-weight: 500; color: var(--wp--preset--color--foreground); }

/* 2px offset centers the 16px icon on the 20px first text line */
.single-product .zo-pdph__check svg { width: 16px; height: 16px; flex: 0 0 auto; margin-top: 2px; color: var(--wp--preset--color--grey-dark); }

/* Kaufzeile: native Woo variations_form (variables Produkt) aufs Design restylen.
   Struktur: table.variations td.value select = „Termin finden"; darunter die Reihe
   Menge-Stepper (links) + Add-to-Cart „Webinar buchen" (rechts). Menge fehlt im Figma
   (Node 5076:34309) — kompakter Stepper links per Freigabe (#53). Icons per mask (currentColor). */
.single-product .zo-pdph {
	--zo-pdph-icon-cal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 1V3H15V1H17V3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H7V1H9ZM20 11H4V19H20V11ZM7 5H4V9H20V5H17V7H15V5H9V7H7V5Z'/%3E%3C/svg%3E");
	--zo-pdph-icon-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
}

.single-product .zo-pdph__card .wp-block-add-to-cart-form,
.single-product .zo-pdph__card a.zo-pdph__continue,
.single-product .zo-pdph__card button.zo-pdph__waitlist { margin-top: 32px !important; margin-bottom: 0 !important; }

.single-product .zo-pdph__card form.cart { margin: 0 !important; display: flex; flex-direction: column; }

/* Variation-Auswahl = „Termin finden" (Kalender-Icon links, Chevron rechts) */
.single-product .zo-pdph__card table.variations { margin: 0 !important; border: 0; width: 100%; display: block; }

.single-product .zo-pdph__card table.variations tbody,
.single-product .zo-pdph__card table.variations tr { display: block; }

.single-product .zo-pdph__card table.variations th.label { display: none; }

.single-product .zo-pdph__card table.variations td.value { display: block; padding: 0; position: relative; }

.single-product .zo-pdph__card td.value select {
	appearance: none; -webkit-appearance: none; -moz-appearance: none;
	position: relative; z-index: 0;
	width: 100%; height: 48px; box-sizing: border-box; margin: 0;
	padding: 0 44px; border-radius: 0;
	/* WC-Blocks-Inline-Style malt einen zweiten Chevron als background-image (feather) → weg,
	   nur der `::after`-Chevron bleibt. `!important`, weil die Fremd-Regel gleich spezifisch nachlädt. */
	background-color: var(--wp--preset--color--white); background-image: none !important;
	border: 1px solid var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--small); line-height: 20px; font-weight: 500; cursor: pointer;
}

.single-product .zo-pdph__card td.value::before,
.single-product .zo-pdph__card td.value::after {
	content: ""; position: absolute; top: 50%; transform: translateY(-50%);
	width: 16px; height: 16px; z-index: 1; pointer-events: none;
	background-color: var(--wp--preset--color--primary);
}

.single-product .zo-pdph__card td.value::before {
	left: 16px;
	-webkit-mask: var(--zo-pdph-icon-cal) center / contain no-repeat;
	        mask: var(--zo-pdph-icon-cal) center / contain no-repeat;
}

.single-product .zo-pdph__card td.value::after {
	right: 15px; width: 18px; height: 18px;
	-webkit-mask: var(--zo-pdph-icon-chev) center / contain no-repeat;
	        mask: var(--zo-pdph-icon-chev) center / contain no-repeat;
}

/* „Zurücksetzen"-Link — WC-JS blendet ihn nach Auswahl inline ein → `!important`. */
.single-product .zo-pdph__card .reset_variations { display: none !important; }

/* Select → Kaufreihe: 16px (Node 5076:34309). Statt Flex-gap explizit, da WC vor der
   Tabelle ein leeres Wrapper-Element ausgibt, das ein gap fälschlich mitzählen würde. */
.single-product .zo-pdph__card .single_variation_wrap { margin-top: 16px; }

/* Variation-Preis/Verfügbarkeit doppelt den Kopf-Preis → ausblenden (Design zeigt einen Preis).
   `!important`, weil WC-JS die Zeile per inline display:block einblendet. */
.single-product .zo-pdph__card .woocommerce-variation.single_variation { display: none !important; }

/* Menge-Stepper (links) + Add-to-Cart-Button (rechts) in einer Reihe */
.single-product .zo-pdph__card .woocommerce-variation-add-to-cart { display: flex; gap: 8px; align-items: stretch; margin: 0; }

/* Menge nur zeigen, wenn mehrere kaufbar. Bei „Nur einzeln verkaufen" rendert WC (Template 10.1.0)
   `<div class="quantity">` OHNE `.hidden`-Klasse, nur der Input wird `type="hidden"` → der leere
   Primary-Rahmen kollabiert sonst zu einem lila Strich. Beide Fälle ausblenden, Button volle Breite (#53). */
.single-product .zo-pdph__card .quantity.hidden,
.single-product .zo-pdph__card .quantity:has( input.qty[type="hidden"] ) { display: none !important; }

/* Stepper als eine primary-umrandete Einheit (analog zum „Termin finden"-Select), ohne Mint-Lücken.
   `overflow:hidden` klammert die Kinder in den Rahmen; die Trenner sind die Input-Seitenränder. */
.single-product .zo-pdph__card .quantity {
	display: inline-flex; align-items: stretch; flex: 0 0 auto; height: 64px; box-sizing: border-box;
	border: 1px solid var(--wp--preset--color--primary);
	background: var(--wp--preset--color--white); overflow: hidden;
}

.single-product .zo-pdph__card .quantity input.qty {
	/* WC-Blocks setzt Breite/`margin-right:8px` mit höherer Spezifität → hier klar überschreiben,
	   sonst blitzt der Mint-Kartengrund zwischen Input und Plus durch. */
	width: 44px !important; height: 100%; margin: 0 !important; padding: 0;
	border: 0; border-left: 1px solid var(--wp--preset--color--primary); border-right: 1px solid var(--wp--preset--color--primary);
	text-align: center; -moz-appearance: textfield; appearance: textfield;
	background: var(--wp--preset--color--white); color: var(--wp--preset--color--foreground);
	font-size: var(--wp--preset--font-size--medium); line-height: 1;
}

.single-product .zo-pdph__card .quantity input.qty::-webkit-outer-spin-button,
.single-product .zo-pdph__card .quantity input.qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.single-product .zo-pdph__card .zo-qty-btn {
	width: 40px; height: 100%; margin: 0; padding: 0; border: 0; cursor: pointer;
	background: var(--wp--preset--color--white); color: var(--wp--preset--color--primary);
	font-size: var(--wp--custom--font-size--20); line-height: 1; display: inline-flex; align-items: center; justify-content: center;
}

.single-product .zo-pdph__card .zo-qty-btn:hover { background: var(--wp--preset--color--grey-light); }

/* Add-to-Cart „Webinar buchen" — a.zo-pdph__continue („Kurs fortsetzen", #155) und
   button.zo-pdph__waitlist („Informiert bleiben", #204) tragen dieselbe Optik */
.single-product .zo-pdph__card button.single_add_to_cart_button,
.single-product .zo-pdph__card a.zo-pdph__continue,
.single-product .zo-pdph__card button.zo-pdph__waitlist {
	flex: 1 1 auto; height: 64px; box-sizing: border-box; margin: 0;
	background: var(--wp--preset--color--primary); color: var(--wp--preset--color--white);
	border: 0; border-radius: 0; font-weight: 500; font-size: var(--wp--preset--font-size--medium); line-height: 1;
	display: inline-flex; align-items: center; justify-content: center; text-transform: none; letter-spacing: 0; padding: 0;
}

/* #155: Link-Spezifika des „Kurs fortsetzen"-Buttons — Anker statt <button>, volle Kartenbreite,
   Abstand zum Pfeil-Icon. margin-top kommt aus der add-to-cart-Formularregel weiter oben.
   #204: der Wartelisten-Button teilt Vollbreite + Icon-Abstand. */
.single-product .zo-pdph__card a.zo-pdph__continue,
.single-product .zo-pdph__card button.zo-pdph__waitlist { display: flex; width: 100%; gap: 12px; text-decoration: none; cursor: pointer; }

.single-product .zo-pdph__card button.single_add_to_cart_button:hover,
.single-product .zo-pdph__card a.zo-pdph__continue:hover,
.single-product .zo-pdph__card button.zo-pdph__waitlist:hover { background: var(--zo-action-hover); }

.single-product .zo-pdph__card button.single_add_to_cart_button:disabled,
.single-product .zo-pdph__card button.single_add_to_cart_button.disabled { opacity: .5; cursor: not-allowed; }

/* Reflow per page 6503:97080 (#370): LG keeps two columns (card 420, main fluid), MD/SM stack
   one column (card below content) with the SM text styles (Heading/SM 24/32, Copy/SM 14/20).
   The transaction card keeps its desktop look on MD/SM (Figma redesign there is out of scope). */
@media (max-width: 1023px) {
	.single-product .zo-pdph { padding-top: 32px; }
	.single-product .zo-pdph__inner { flex-direction: column; gap: 40px; }
	.single-product .zo-pdph__main { flex: 1 1 auto; max-width: 100%; }
	.single-product .zo-pdph__card { flex: 1 1 auto; max-width: 100%; width: 100%; align-self: stretch; }
	.single-product .zo-pdph__title { font-size: var(--wp--custom--font-size--24); line-height: 32px; }
	.single-product .zo-pdph__descrow { margin-top: 16px !important; flex-direction: column; gap: 24px; }
	.single-product .zo-pdph__lead,
	.single-product .zo-pdph__topic { flex-basis: auto; max-width: 100%; }
	.single-product .zo-pdph__lead { font-size: var(--wp--preset--font-size--small); line-height: 20px; }
	.single-product .zo-pdph__topic-link { gap: 4px; font-size: var(--wp--preset--font-size--small); line-height: 20px; }
	.single-product .zo-pdph__topic-link svg { width: 16px; height: 16px; }
	.single-product .zo-pdph__experts { margin-top: 32px !important; }
	.single-product .zo-pdph__expert { gap: 8px; }
	.single-product .zo-pdph__expert-name { font-size: var(--wp--preset--font-size--small); line-height: 20px; }
}

@media (max-width: 639px) {
	.single-product .zo-pdph { padding-top: 24px; }
}

/* ============================================================
   PDP-Body: dynamische Sektionen  (#88, Frame 4573-37150)
   Template-getriebene, self-gating zo/section-pdp-*-Patterns. Scope .zo-pdp-*.
   Datenbindung: inc/pdp-sections.php. Hier lebt nur noch der vertikale Rhythmus.

   Breiten-Cap NICHT mehr pauschal (#153): bis dahin cappte `.zo-pdp-section > *` jedes
   Kind auf die Rail — die Karussell-/FAQ-Komponenten sind aber full-bleed und raillen sich
   selbst (padding-inline: --zo-rail-bleed). Ergebnis war ein doppelt gerechneter Rand, die
   Ueberschriften von Rezensionen/Dozent:innen/FAQ standen 32px weiter innen als „Lerninhalte",
   und der 1328er-Cap machte die Container-Query-Schwelle 1360 unerreichbar
   (content-rail.md §rail-bleed). Die gecappten Sektionen tragen ihre Schiene jetzt selbst als
   `.zo-container` im Markup (inc/pdp-sections.php), die full-bleed-Sektionen bleiben ungecappt.
   ============================================================ */
.zo-pdp-section, .zo-pdp-section * { box-sizing: border-box; }
/* Sektions-Rhythmus = Modul-Reihe 40/56/64/96 (#289): itemSpacing des Seiten-Frames 6761:84794
   ist an die Modul-Gap-Variable gebunden (5033:24673, module-gap.md) — ersetzt das fruehere
   padding-block spacing|80 (effektiv 200px zwischen Sektionen). Nur padding-block-START: der
   Abstand zum Footer kommt aus dessen eigenem margin-block-start (EIN Mechanismus, #174);
   padding statt margin, damit main-blockGap 0 und WP-Layout-Regeln nicht hineinspielen.
   Gilt auch fuer die erste Sektion nach der Sprungnav (Frame: Nav -> Sektion ebenfalls 96). */
.zo-pdp-section { padding-block-start: var(--zo-module-gap); }
.zo-pdp-lerninhalte__inner, .zo-pdp-artikel__inner, .zo-pdp-vorschau__inner { display: flex; flex-direction: column;
	gap: var(--wp--preset--spacing--60); container-type: inline-size; }
/* Typo der Sektions-H2 kommt aus .zo-section-heading (#152) — keine PDP-eigene Skala mehr. */
/* Lerninhalte: Topic-Cards (Frame 1171280655: 4x328, gap 16; Karte 4573:37209 — Padding 32,
   Titel 20/26/700, Text 16/22/500, Gap 12, #154). BG = Akzent des Produkttyps (zo_format-Term-Meta
   zo_accent, Modifier-Keys aus zo_flag_accents()). Without an accent (e.g. Bereisung,
   MeetUs) the card defaults to white, never transparent (Philipp #345); modifiers below override. */
.zo-pdp-topics { display: grid; grid-template-columns: 1fr; gap: 16px; }
.zo-pdp-topics__card { display: flex; flex-direction: column; gap: 12px; padding: var(--wp--preset--spacing--50); /* 32 */ background: var(--wp--preset--color--white); }
.zo-pdp-topics__card--turquoise { background: var(--wp--preset--color--accent-turquoise); }
.zo-pdp-topics__card--orange    { background: var(--wp--preset--color--accent-orange); }
.zo-pdp-topics__card--yellow    { background: var(--wp--preset--color--accent-yellow); }
.zo-pdp-topics__card--lilac     { background: var(--wp--preset--color--accent-lilac); }
.zo-pdp-topics__title { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--20); line-height: 26px; font-weight: 700; color: var(--wp--preset--color--foreground); }
.zo-pdp-topics__text { margin: 0; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium); line-height: 22px; font-weight: 500; color: var(--wp--preset--color--foreground); }
@container (min-width: 700px) { .zo-pdp-topics { grid-template-columns: repeat(2, 1fr); } }
@container (min-width: 1000px) { .zo-pdp-topics { grid-template-columns: repeat(4, 1fr); } }
/* Lerninhalte: Beschreibung/Lernziele reuse .zo-text-columns — im __inner voll ausnutzen. */
.zo-pdp-lerninhalte__cols { width: 100%; }
.zo-pdp-lerninhalte__cols .zo-text-columns__row { width: 100%; }
/* Reflow-Schwelle hier als @media: die generische @container-1024-Regel der Komponente misst in
   diesem Kontext das rail-gecappte __inner (ohne .zo-text-columns-Wrapper im Markup) — die
   2-Spalten-Stufe spraenge erst bei Viewport 1024+Rand statt 1024 (Figma-Viewport-Achse,
   content-rail.md §Viewport-Stufung; #131). Werte identisch zur Komponente (1fr/432, gap 80, #366). */
@media (min-width: 1024px) {
	.zo-pdp-lerninhalte__cols .zo-text-columns__row:has(.zo-text-columns__aside) { grid-template-columns: minmax(0, 1fr) 432px; gap: 80px; align-items: start; }
}
/* Vorschau: Produktgalerie */
.zo-pdp-preview { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.zo-pdp-preview__item { margin: 0; aspect-ratio: 3 / 2; overflow: hidden; background: var(--wp--preset--color--paper); }
.zo-pdp-preview__img, .zo-pdp-preview__item img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Vorschau: Text links + Video rechts (Figma 6761-87910 "Text-Image-Combo", 1328er-Rail, #289).
   Eigene Sektion über Lerninhalte (#89) → .zo-pdp-vorschau__inner erbt Flex/Container aus der
   Gruppe oben. H2 sitzt IN der Textspalte (Video-Oberkante bündig mit H2-Oberkante); unter 1024
   einspaltig gestapelt, Text (mit H2) oben, Video darunter (DOM-/Lesereihenfolge des Frames). */
.zo-pdp-vorschau__row { display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--60); align-items: start; }
.zo-pdp-vorschau__content { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--40); /* H2→Body 24, Figma 6761-87910 */ }
.zo-pdp-vorschau__text { font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 22px; color: var(--wp--preset--color--foreground); }
.zo-pdp-vorschau__text > :first-child { margin-top: 0; }
.zo-pdp-vorschau__text > :last-child { margin-bottom: 0; }
/* RTE-Formate im Vorschau-Text (#300, B1a): Zwischenueberschrift/Liste folgen Theme-Tokens
   (h3 = Preset "large" wie Theme-Heading-3); Figma 4573-37193 definiert nur Fliesstext. */
.zo-pdp-vorschau__text h3 { margin: 24px 0 8px; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--large); font-weight: 700; line-height: 1.3; }
.zo-pdp-vorschau__text ul { margin: 0 0 1em; padding-left: 24px; }
.zo-pdp-vorschau__text li { margin: 0 0 4px; }
/* 2-spaltig ab Viewport 1024 (Reflow-Regel wie .zo-text-columns). Als @media, nicht @container:
   der naechste Query-Container ist das auf die Rail gecappte __inner (.zo-container) — eine
   Container-Schwelle verschiebt die Stufe um den Rail-Rand (content-rail.md §Viewport-Stufung;
   die fruehere Schwelle 944 war das vw−80-Relikt der alten 40er-Inset-Spalte, #131).
   704+80+544 = 1328: der neue Frame liegt nativ auf der Rail, fr = px-treu bei 1440. */
@media (min-width: 1024px) {
	/* --textonly (Text ohne Video UND ohne Produktbild): gleiche Spaltenteilung, rechte Zelle
	   bleibt leer — der Text laeuft nie ueber die volle Rail (Philipp #289 Folgeauftrag). */
	.zo-pdp-vorschau__row--split, .zo-pdp-vorschau__row--textonly { grid-template-columns: 704fr 544fr; gap: 80px; /* Figma 6761-87910 */ }
}
/* Produktbild als Medium, wenn kein Video gepflegt ist (#289): gleiche 544er-Spalte,
   16:9 wie das Video-Placeholder-Image im Frame (544x306), Cover-Beschnitt. */
.zo-pdp-vorschau__image { margin: 0; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; }
.zo-pdp-vorschau__image img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Video (oEmbed responsiv) */
.zo-pdp-video__frame { position: relative; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; }
.zo-pdp-video__frame iframe, .zo-pdp-video__frame video, .zo-pdp-video__frame embed, .zo-pdp-video__frame object { position: absolute; inset: 0; width: 100%; height: 100%; }
/* Lernziele rendern seit #154 ohne Kasten als .zo-text-columns__aside (Heading + __list,
   Figma 4573:37221; Philipp #144 revidiert die #63-Content-Box) — keine PDP-Sonderregeln mehr. */

/* ============================================================
   Kursübersicht / Content Hub  (Figma 4144:28137, Desktop 1440)
   Scope: .zo-katalog  – pixelgenauer 1:1-Rebuild
   ============================================================ */
.zo-katalog { background: var(--wp--preset--color--paper); }

.zo-katalog * { box-sizing: border-box; }

.zo-kat-main { margin: 0; }

/* --- Main / Wrapper --- */
/* Boden = Footer-Margin (EIN Mechanismus, #174/module-gap.md); oben bleibt 120 (Snapshot 4144:28137). */
.zo-kat-main { padding: 120px 0 0; }

.zo-kat-wrap { width: var(--zo-rail-w); margin: 0 auto; }

.zo-kat-heading { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--40); font-weight: 700; line-height: 1.3; margin: 0; color: var(--wp--preset--color--foreground); }

/* --- Filterleiste --- */
.zo-kat-filters { margin-top: 40px; display: flex; align-items: center; justify-content: space-between; min-height: 48px; flex-wrap: wrap; gap: 16px; } /* Umbruch auf schmalen Breiten (Grid-Gate #128) — analog .zo-product-filter */

.zo-kat-filters__group { display: flex; gap: 12px; flex-wrap: wrap; } /* Umbruch auf schmalen Breiten (Grid-Gate #128) */

.zo-kat-dropdown { width: 199px; height: 48px; border: 1px solid var(--wp--preset--color--grey-mid); background: var(--wp--preset--color--white); display: flex; align-items: center; justify-content: space-between; padding: 0 16px; font-family: var(--wp--preset--font-family--body); font-size: var(--wp--preset--font-size--small); font-weight: 400; color: var(--wp--preset--color--foreground); cursor: pointer; }

.zo-kat-dropdown svg { width: 14px; height: 14px; flex: 0 0 auto; }

.zo-kat-count { font-size: var(--wp--preset--font-size--small); font-weight: 500; color: var(--wp--preset--color--grey-dark); }

/* --- Grid (Figma Card-Grid/Product 4887:19928, Grid-Foundation #128) ---
   Karte = span 4 auf JEDEM Breakpoint (12 Spalten → 3/Reihe · 8 → 2 · 4 → 1); an den
   Figma-Kanten rechnet sich exakt XL 432 · LG 309 · MD/SM 288. Zeilen- wie Spalten-Gap 16. */
.zo-kat-grid { margin-top: 40px; display: grid; grid-template-columns: repeat(var(--zo-grid-columns), 1fr); gap: var(--zo-grid-gutter); align-items: start; } /* start: die hoehere Offer-Card (512) darf die 470er-Produktkarten nicht mitstrecken */

.zo-kat-grid > .zo-kat-card, .zo-kat-grid > .zo-kat-card--offer { grid-column: span 4; }

/* Card-Article im Kat-Grid (Magazin #148, Komponente 4948:16636 LG+ 432×466,49): Body 250 FIXED
   wie die Komponente (Media 2:1 = 216 + 250 = 466); im PDP-Kontext (.zo-cards-article) bleibt die
   Hoehe content-getrieben (#44). Link unten gepinnt, Titel/Anriss geclampt gegen Ueberlauf. */
.zo-kat-grid > .zo-card-article { grid-column: span 4; }

/* Card Expert im Kat-Grid (#222, product-grid Expert:innen-Achse): span 4 wie Produkt-/
   Artikel-Karte; Breite kommt aus der Foundation-Zelle, Hoehe aus der Karten-Variante. */
.zo-kat-grid > .zo-card-expert { grid-column: span 4; }

.zo-kat-grid .zo-card-article__body { height: 250px; overflow: hidden; } /* Body-Frame 4948:16636 FIXED */

.zo-kat-grid .zo-card-article__title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

.zo-kat-grid .zo-card-article__excerpt { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* SM+ body 204 FIXED (4948-17479): title 3 lines 66 + excerpt 2 lines 32 like the carousel. */
@media (max-width: 1023.98px) {
	.zo-kat-grid .zo-card-article__body { height: 204px; }
	.zo-kat-grid .zo-card-article__title { -webkit-line-clamp: 3; }
	.zo-kat-grid .zo-card-article__excerpt { -webkit-line-clamp: 2; }
}

/* --- Card-Product (Figma COMPONENT_SET 5050:19905, #38 · Gleich-Hoehe #94 · fluid #128
   · Figma-Update 20.08. #197) ---
   States: hover (Shadow) · Beliebt-Badge konditional (is_featured) · Zeitzeile konditional.
   Variants (Figma names them Viewport=LG+ / Viewport=SM+): LG+ 432×470 · SM+ 288×364.
   Since #334 the variant switches on the VIEWPORT (media query, LG+ >= 1024) — matching the
   Figma naming — not on the card width: with the old container query, three-up desktop grids
   below 1440 rendered SM+ type (designer report). Width comes from the grid span,
   Hoehe = Media (Aspect 2:1) + fixer Body (SM+ 220 / LG+ 254). Keine Border, radius 0.
   Gleich-Hoehe (#94): Media-Aspect + Titel/Untertitel-Clamps FEST, Fuss per margin-top:auto
   unten gepinnt; Grid-Stretch haelt die Reihe gleich hoch, bild-lose Produkte kollabieren
   nicht (Media-Wrapper haelt den Platz). overflow hidden kappt seltene Ueberlaeufe. */
/* box-sizing gehoert in die Komponente, nicht in den Seiten-Scope: bis #197 kam border-box
   nur ueber `.zo-katalog *` — ausserhalb des Katalogs (Konto-Kurse, WC-Archiv) fiel das Flag
   damit auf content-box zurueck und mass 32 statt 24 (LG+) bzw. 28 statt 20 (SM+). */
.zo-kat-card, .zo-kat-card * { box-sizing: border-box; }

.zo-kat-card { overflow: hidden; background: var(--wp--preset--color--white); display: flex; flex-direction: column; text-decoration: none; color: inherit; }

/* One hover shadow for every clickable card (#352): value of the built Card Product —
   Figma has no hover variant or effect for any card component (checked 2026-09-24). */
.zo-kat-card, .zo-card-article, .zo-card-expert, .zo-card-topic, .zo-eventlist__row { transition: box-shadow 0.2s ease; }

.zo-kat-card:hover, .zo-card-article:hover, .zo-card-expert:hover, .zo-card-topic:hover, .zo-eventlist__row:hover { box-shadow: 0 6px 24px rgba(0,0,0,0.08); }

/* Media haelt sein 2:1 hart: img absolut, damit Bild-Attribute (WC aspect-ratio) die
   Wrapper-Hoehe nie strecken koennen. */
.zo-kat-card__media { position: relative; flex: 0 0 auto; aspect-ratio: 2 / 1; }

.zo-kat-card__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Body-Hoehe fix (Figma LG+ 254): Card-Hoehe = Breite/2 + Body an allen Grid-Breiten.
   flex 0 0 auto + overflow hidden setzt die Flex-Item-Min-Size auf 0 — laengerer Inhalt
   kann die fixe Hoehe nicht mehr aufdruecken (Kinder clampen/shrinken wie bisher, #94). */
.zo-kat-card__body { box-sizing: border-box; padding: 24px; display: flex; flex-direction: column; flex: 0 0 auto; height: 254px; overflow: hidden; }

.zo-kat-card__title { flex: 0 0 auto; margin: 12px 0 0; font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 1.3; height: 52px; color: var(--wp--preset--color--foreground); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

.zo-kat-card__meta { flex: 0 1 auto; min-height: 0; margin: 8px 0 0; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1.4286; height: 40px; color: var(--wp--preset--color--foreground); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Bundle-Liste = Slot „List Icon" (5050:19905): LG+ 3 Zeilen a 20 + Gap 4 = 68 (SM+ 3x16 + 4 = 56).
   PHP rendert bis zu 4 Kinder — die max-height kappt die 4. Zeile ganz, nie halb. */
.zo-kat-card__list { flex: 0 1 auto; min-height: 0; margin: 8px 0 0; max-height: 68px; overflow: hidden; list-style: none; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.zo-kat-card__list li { display: flex; align-items: center; gap: 6px; height: 20px; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1.4286; color: var(--wp--preset--color--foreground); }

.zo-kat-card__list li svg { width: 16px; height: 16px; flex: 0 0 auto; }

.zo-kat-card__foot { flex: 0 0 auto; margin-top: auto; display: flex; align-items: center; justify-content: space-between; }

.zo-kat-card__avail { font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 1.4286; color: var(--wp--preset--color--grey); }

/* Price is Figtree (body font), not the display font — 5050:19905 sets it in Figtree 700
   in both variants (#334, designer report). */
.zo-kat-card__price { font-family: var(--wp--preset--font-family--body); font-size: var(--wp--custom--font-size--18); font-weight: 700; line-height: 1.4444; color: var(--wp--preset--color--primary); }

/* --- Flags --- */
.zo-kat-flags { flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.zo-kat-flag { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 4px 8px 4px 6px; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 1; color: var(--wp--preset--color--foreground); white-space: nowrap; }

.zo-kat-flag svg { width: 16px; height: 16px; flex: 0 0 auto; }

.zo-kat-flag--popular { position: absolute; top: 24px; left: 24px; background: var(--wp--preset--color--foreground); color: var(--wp--preset--color--white); }

.zo-kat-flag--turquoise { background: var(--wp--preset--color--accent-turquoise); }

.zo-kat-flag--orange { background: var(--wp--preset--color--accent-orange); }

.zo-kat-flag--yellow { background: var(--wp--preset--color--accent-yellow); }

.zo-kat-flag--lilac { background: var(--wp--preset--color--accent-lilac); padding: 4px 8px; }

/* Format flags are never white: fallback without accent is grey-200 (Philipp #363 B1a); padding
   like the other format colors. Topic flags keep --plain (#363 B2b). */
.zo-kat-flag--grey { background: var(--wp--custom--color--grey-200); }

.zo-kat-flag--plain { background: transparent; padding: 4px 0; color: var(--wp--preset--color--foreground); }

/* Topic chip hidden on SM/MD viewports (#306, Philipp B1b+B2a): two chips can wrap into a
   second row and, with the fixed-height card body, clip the text below. Format chip stays;
   desktop (>= 1024px viewport) unchanged. Deliberate Figma deviation (SM+ card 5050:19905
   shows both chips). Also applies to the account course card (shared flags source, #156). */
@media (max-width: 1023.98px) {
	.zo-kat-flag--topic { display: none; }
}

/* --- Mehr laden (Pagination Loader, Figma 4896:67433, #335) ---
   Count 14/20 · bar/fill reuse .zo-progress (track 164x4 grey-mid, fill primary) · button
   is the shared Secondary MD (.zo-btn--md.zo-btn--secondary). Figma auto-layout gap is 24
   around 0-height LINE nodes whose 4px stroke centers on the box → 22px visual margins.
   Fill width = loaded share (shown/total, B1a), inline from PHP resp. view.js. */
.zo-kat-loadmore { margin-top: 40px; display: flex; flex-direction: column; align-items: center; }

.zo-kat-loadmore__count { font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; color: var(--wp--preset--color--foreground); }

.zo-kat-loadmore__bar { display: block; margin-top: 22px; width: 164px; }

.zo-kat-loadmore__btn { margin-top: 22px; }
/* --- Variant switch on the VIEWPORT (#334, was a container query on the card width):
   Figma names the variants Viewport=LG+ / Viewport=SM+ — the stage decides, not the card.
   LG+ from viewport 1024 (nav breakpoint, #333), SM+ below. The old width<432 query made
   three-up desktop grids below 1440 (card ~309-426) render SM+ type — the designer's
   report in #334. Column count/wrapping still comes entirely from the grid (span 4). */
@media (max-width: 1023.98px) {
	/* Card Product SM+ (5050:19905, #197): Body 220 fix, Titel 3 Zeilen (22px lh),
	   Anriss 12/16 auf 3 Zeilen (48), Verfuegbarkeit 12/16, Preis 16/22. */
	.zo-kat-card__body { padding: 16px; height: 220px; }
	.zo-kat-card__title { margin-top: 8px; font-size: var(--wp--preset--font-size--medium); line-height: 1.375; height: 66px; -webkit-line-clamp: 3; }
	.zo-kat-card__meta { margin-top: 6px; font-size: var(--wp--custom--font-size--12); line-height: 1.3333; height: 48px; -webkit-line-clamp: 3; }
	.zo-kat-card__list { margin-top: 6px; max-height: 56px; }
	.zo-kat-card__list li { height: 16px; font-size: var(--wp--custom--font-size--12); line-height: 1.3333; }
	.zo-kat-card__list li svg { width: 12px; height: 12px; }
	.zo-kat-card__avail { font-size: var(--wp--custom--font-size--12); line-height: 1.3333; }
	.zo-kat-card__price { font-size: var(--wp--preset--font-size--medium); line-height: 1.375; }
	.zo-kat-flag { height: 20px; }
	.zo-kat-flag svg { width: 12px; height: 12px; }
	.zo-kat-flag--popular { top: 16px; left: 16px; }
}

/* --- Katalog: Angebots-Card (Platz 6, Figma 4482:39337) --- */
.zo-kat-flag--dark { background: var(--wp--preset--color--foreground); color: var(--wp--preset--color--white); }

.zo-kat-card--offer { min-height: 512px; background: var(--wp--preset--color--accent-lilac); /* Breite vom Grid-Span (#128); Basis-Frame 4482:39337 ist nicht dev-ready (Playground) */
	border: 0; padding: 32px; display: flex; flex-direction: column; }

.zo-kat-card--offer .zo-kat-flag { align-self: flex-start; }

.zo-kat-offer__title { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--custom--font-size--32); font-weight: 700;
	line-height: 1.3; margin: 8px 0 0; color: var(--wp--preset--color--foreground); }

.zo-kat-offer__sub { margin: 4px 0 0; font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 1.4; letter-spacing: -0.01em; color: var(--wp--preset--color--grey-dark); }

.zo-kat-offer__list { list-style: none; margin: 30px 0 0; padding: 0; display: flex; flex-direction: column; }

.zo-kat-offer__list li { display: flex; align-items: center; gap: 12px; height: 30px; font-size: var(--wp--preset--font-size--medium); font-weight: 500; color: var(--wp--preset--color--foreground); }

.zo-kat-offer__list li svg { width: 18px; height: 18px; flex: 0 0 auto; }

.zo-kat-offer__link { margin-top: auto; display: inline-flex; align-items: center; gap: 6px; font-size: var(--wp--preset--font-size--medium); font-weight: 700; color: var(--wp--preset--color--primary); text-decoration: none; }

.zo-kat-offer__link:hover { opacity: .85; }

/* --- Page scope "Lernen-Hub": section spacing = module series (#254) ---
   The old fixed 80/128 came from playground frame 4482:39337 (not a valid spacing
   source, lernen-hub.md); the designer confirmed the 40/56/64/96 series as the general
   section rule (module-gap.md). All five sections are direct children. */
.zo-lernpage { background: var(--wp--preset--color--paper); } /* Boden = Footer-Margin (#174) */

/* :root prefix: the editor canvas injects WP layout styles after theme CSS (same
   specificity, later order) — without it the flow gap loses there. Front end unaffected. */
:root .zo-lernpage > * { margin-block: 0; }

:root .zo-lernpage > * + * { margin-block-start: var(--zo-module-gap); }

.zo-lernpage .zo-kat-main { padding: 0; }

/* ============================================================
   WooCommerce-Produktkacheln + Archive  (Issue #10)
   Eine Card-Quelle (zo_render_product_card) für Shop/Kategorie/Archiv,
   /lernangebote/-Grid und PDP-„Ähnliche Angebote". Nutzt die bestehenden
   .zo-kat-card-Styles oben; hier nur Zeitzeile und das Mapping des
   WC-Loops (ul.products) auf das Katalog-Grid.
   ============================================================ */
/* Filterleiste = Custom-Dropdown-Widget .zo-filterbar (COMPONENTS, #101/#102) — seit #103 auch
   hier; die alten nativen <select>-Styles (.zo-kat-filters__select) sind entfallen. */

/* ============================================================
   Page: LearnDash Kurs-Einzelseite  (Scope .zo-course)
   Figma „Kurs - Einstiegsseite / Übersicht" 5266:16509  ·  Sync 2026-07-22 (#70)
   Spec: docs/figma-specs/course-single.md
   Template: learndash/ld30/course.php + templates/single-sfwd-courses.html
   States: Nav-Link :hover/:focus-visible · CTA :hover · Nav done (Häkchen).
           Leer/Fehler: n/a (LD liefert Kursdaten). Breakpoints: 1024 (stack) · 600 (mobile).
           Lektions-Grid reflowt fluid (auto-fit) → 2→1 Spalte ohne px-Breakpoint.
   ============================================================ */
.zo-course { background: var(--wp--preset--color--paper); padding: 32px 0 0; } /* Boden = Footer-Margin (#174) */
.zo-course, .zo-course * { box-sizing: border-box; }
.zo-course__wrap { width: var(--zo-rail-w); margin: 0 auto; }

/* Breadcrumb */
.zo-breadcrumb { display: flex; align-items: center; gap: 8px; margin-bottom: 32px;
	font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; color: var(--wp--preset--color--foreground); }
.zo-breadcrumb__item { color: inherit; text-decoration: none; }
.zo-breadcrumb__item--current { color: var(--wp--preset--color--grey); }
.zo-breadcrumb__item:not(.zo-breadcrumb__item--current):hover { color: var(--wp--preset--color--primary); }
.zo-breadcrumb__sep { color: var(--wp--preset--color--grey-mid); flex: 0 0 auto; }

/* Zwei-Spalten-Grid: Sidebar 328 · Gap 16 · Content flex (984 @ 1328, Grid #128) */
.zo-course__grid { display: grid; grid-template-columns: 328px minmax(0, 1fr); gap: 16px; align-items: start; }

/* Sidebar — Kurs-Navigation */
.zo-course__aside { background: var(--wp--preset--color--white); padding: 24px; align-self: start; }
.zo-course__eyebrow { margin: 0; font-size: var(--wp--custom--font-size--12); font-weight: 500; line-height: 16px; color: var(--wp--preset--color--foreground); }
.zo-course__title { margin: 8px 0 0; font-size: var(--wp--custom--font-size--20); font-weight: 700; line-height: 26px; color: var(--wp--preset--color--foreground); }

.zo-course__progress { margin-top: 24px; }

.zo-course-nav { list-style: none; margin: 24px 0 0; padding: 0; }
.zo-course-nav__item { display: flex; align-items: center; justify-content: space-between; gap: 8px;
	min-height: 62px; border-bottom: 1px solid var(--wp--preset--color--grey-light); }
.zo-course-nav__link { font-size: var(--wp--preset--font-size--medium); font-weight: 700; line-height: 22px; color: var(--wp--preset--color--foreground); text-decoration: none; }
.zo-course-nav__link:hover, .zo-course-nav__link:focus-visible { color: var(--wp--preset--color--primary); }
.zo-course-nav__item--current .zo-course-nav__link { color: var(--wp--preset--color--primary); }
.zo-course-nav__check { color: var(--wp--preset--color--primary); flex: 0 0 auto; }

/* Content-Panel */
.zo-course__main { background: var(--wp--preset--color--white); padding: 48px 40px 40px; min-width: 0; }

.zo-flag { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px 0 8px;
	background: var(--wp--preset--color--accent-orange); color: var(--wp--preset--color--foreground); font-size: var(--wp--preset--font-size--small); font-weight: 500; }
.zo-flag__icon { color: var(--wp--preset--color--foreground); flex: 0 0 auto; }
.zo-flag__label { line-height: 1; }

.zo-course__h1 { margin: 24px 0 0; font-size: var(--wp--custom--font-size--48); font-weight: 700; line-height: 62px; color: var(--wp--preset--color--foreground); }
.zo-course__lead { margin: 24px 0 0; max-width: 936px; font-size: var(--wp--custom--font-size--18); font-weight: 500; line-height: 26px; color: var(--wp--preset--color--foreground); }

/* Kennzahl-Kacheln (Number-Counter): 4 × 234, Border + Divider */
.zo-course-stats { margin-top: 64px; display: grid; grid-template-columns: repeat(4, 1fr); border: 1px solid var(--wp--preset--color--grey-light); }
.zo-course-stats__item { display: flex; flex-direction: column; align-items: center; justify-content: center;
	min-height: 146px; text-align: center; border-left: 1px solid var(--wp--preset--color--grey-light); }
.zo-course-stats__item:first-child { border-left: 0; }
.zo-course-stats__value { font-size: var(--wp--custom--font-size--32); font-weight: 700; line-height: 42px; color: var(--wp--preset--color--primary); }
.zo-course-stats__label { margin-top: 4px; font-size: var(--wp--preset--font-size--small); font-weight: 500; line-height: 20px; color: var(--wp--preset--color--grey); }

/* Lektions-Grid im Kurs-Kontext: 2 Spalten @ Desktop (Frame 5266), reflowt fluid auf 1 Spalte,
   sobald zwei Karten unter ~360px fielen — kein Overflow, robust ohne px-Breakpoint. Überschreibt .zo-cards-Default. */
.zo-course__main .zo-cards--course { grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); gap: 16px; justify-content: start; margin-top: 64px; }

.zo-course__cta { margin-top: 40px; }

/* CTA-Zustände (#90, Verhaltens-Spec — kein Figma-Node, Optik = .zo-btn-Varianten):
   „Kurs abgeschlossen" ist ein statischer Marker (span.zo-btn) neben „Kurs wiederholen". */
.zo-course__cta-row { margin-top: 40px; display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }
.zo-course__cta-row .zo-course__cta { margin-top: 0; }
.zo-course__cta--done { cursor: default; pointer-events: none; }

/* CTA als Action-Link-Zeile (zo_course_cta style=link — Konto-Kurskarte #156, Review
   Philipp 18.08.): Links im Stil .is-style-zo-action-link (#188, COMPONENTS);
   „Kurs abgeschlossen" ist ein statischer Marker aus der Action-Link-Komponente (#359:
   Look + SM aus der gemeinsamen Regel, MD ab 1024 wie der Basis-Stil, Icon leading),
   Farbe foreground statt primary + cursor auto = nicht klickbar. */
.zo-course__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 24px; }
.zo-course__action-status { --zo-action-link-gap: 6px; color: var(--wp--preset--color--foreground); cursor: auto; }
@media (min-width: 1024px) {
	/* Action Link MD leading: 16/22 · icon 18 · gap 8 */
	.zo-course__action-status { --zo-action-link-font-size: var(--wp--preset--font-size--medium); --zo-action-link-line-height: 22px; --zo-action-link-icon: 18px; --zo-action-link-gap: 8px; }
}

/* Responsive */
@media (max-width: 1024px) {
	.zo-course__grid { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
	.zo-course__wrap { padding-inline: 16px; }
	.zo-course__main { padding: 24px; }
	.zo-course__h1 { font-size: var(--wp--custom--font-size--32); line-height: 40px; }
	.zo-course-stats { grid-template-columns: repeat(2, 1fr); }
	.zo-course-stats__item:nth-child(3) { border-left: 0; }
}

/* ============================================================
   Page: LearnDash Lektion + Topic  (Scope .zo-lesson)
   Figma „Kurs - Einstiegsseite / Orientierung – L" 4507-34294  ·  Sync 2026-07-28 (#85)
   Spec: docs/figma-specs/lesson-single.md
   Template: learndash/ld30/lesson.php + topic.php (geteilt via zo_render_course_step()).
   Teilt die Chrome mit .zo-course (Wrap/Grid/Aside/Main). Kein Breadcrumb (Design zeigt keinen).
   States: Nav-Buttons via .zo-btn (:hover/:focus-visible/disabled). Content-Typo statisch.
           Breakpoints: 1024 (stack) · 600 (mobile).
   ============================================================ */
.zo-lesson { background: var(--wp--preset--color--paper); padding: 64px 0 0; } /* Boden = Footer-Margin (#174) */
.zo-lesson, .zo-lesson * { box-sizing: border-box; }

/* Main-Panel: 40px rundum (Design), überschreibt das 48/40/40 von .zo-course__main. */
.zo-lesson__main { padding: 40px; }
.zo-lesson__h1 { margin: 0; font-size: var(--wp--custom--font-size--48); font-weight: 700; line-height: 62px; color: var(--wp--preset--color--foreground); }

/* Lesson-Content (editorial, von LD gerendert): 64px Block-Rhythmus, H2 32/42, Absatz 16/24. */
.zo-lesson__content { margin-top: 64px; }
.zo-lesson__content > * { margin-block: 0; }
.zo-lesson__content > * + * { margin-top: 64px; }
.zo-lesson__content h2 { font-size: var(--wp--custom--font-size--32); font-weight: 700; line-height: 42px; color: var(--wp--preset--color--foreground); }
.zo-lesson__content h2 + * { margin-top: 16px; }
.zo-lesson__content p, .zo-lesson__content li { font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 24px; color: var(--wp--preset--color--foreground); }
.zo-lesson__content ul { margin: 0; padding-left: 20px; }
.zo-lesson__content li + li { margin-top: 8px; }
.zo-lesson__content img, .zo-lesson__content iframe, .zo-lesson__content video { display: block; width: 100%; height: auto; }
.zo-lesson__content .wp-block-embed__wrapper, .zo-lesson__content .learndash_content_wrap .ld-video { aspect-ratio: 16 / 9; }
.zo-lesson__content .learndash_content_wrap .ld-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Prev/Next-Navigation */
.zo-lesson__nav { margin-top: 64px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.zo-lesson__nav-icon { width: 18px; height: 18px; flex: 0 0 auto; }
/* LD-Mark-Complete im rechten Slot: Layout-Reset; Optik/States adoptiert die .zo-btn-
   Komponente (XL/Primary) in der Components-Sektion (#86) — keine eigene Button-Regel. */
.zo-lesson__nav-complete form { margin: 0; }

/* Responsive */
@media (max-width: 1024px) {
	.zo-lesson .zo-course__grid { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
	.zo-lesson { padding-top: 32px; }
	.zo-lesson .zo-course__wrap { padding-inline: 16px; }
	.zo-lesson__main { padding: 24px; }
	.zo-lesson__h1 { font-size: var(--wp--custom--font-size--32); line-height: 40px; }
	.zo-lesson__content h2 { font-size: var(--wp--custom--font-size--24); line-height: 32px; }
	.zo-lesson__nav { flex-direction: column; align-items: stretch; }
	.zo-lesson__nav-prev, .zo-lesson__nav-next { justify-content: center; }
}


/* ============================================================
   Page: Expert:innen-Profil (author.html, #77, Figma 5301-15652)
   Spec: docs/figma-specs/expert-profile.md. Rail = Grid-Alias #128 (1328/16-24-32) —
   deckt Frame-1328/56 ab 1440 exakt; Sektions-Rhythmus = Modul-Reihe (s. u.). Seiten-BG paper (#F4F4F4).
   States: Schwerpunkt-Links :hover/:focus-visible. Breakpoints: 390/768/1440 —
   Bio stapelt <1024, Content-Boxen via zo-content-box-Queries, Karussells scrollen.
   ============================================================ */
/* Boden = Footer-Margin; das lose 120er-paddingBottom aus 5301-15652 ist Vor-Variablen-Stand
   (#174, module-gap.md §Nachtrag). */
.zo-author-main { background: var(--wp--preset--color--paper); }
/* Section rhythm = module series (#254): the XL frame 5034:41285 binds itemSpacing to
   the same variable 5033:24673 (96/XL) as module-gap.md — the old fixed 96 (template
   blockGap) was just the XL step; now viewport-stepped 40/56/64/96. */
:root .zo-author-main > * { margin-block: 0; }
:root .zo-author-main > * + * { margin-block-start: var(--zo-module-gap); }
.zo-author-section, .zo-author-section * { box-sizing: border-box; }
/* Boxed-Sektionen: Inhalt auf die Rail (PDP-Muster .zo-pdp-section > *). Karussell-/
   Teaser-Sektionen raillen sich selbst (rail-bleed in der Komponente). */
.zo-author-section--bio > *, .zo-author-section--boxes > *, .zo-author-section--termine > * {
	width: var(--zo-rail-w);
	margin-inline: auto;
}
.zo-author-section--bio { container-type: inline-size; }
.zo-author-bio { display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--60); /* 40 gestapelt */ }
@container (min-width: 1024px) {
	.zo-author-bio { grid-template-columns: 836px 425px; justify-content: space-between; gap: 24px; } /* 5301-15652: Spalten 836/425 */
}
.zo-author-bio__text { margin: 0; font-size: 18px; font-weight: 500; line-height: 26px;
	letter-spacing: 0.01em; color: var(--wp--preset--color--foreground); }
.zo-author-bio__focus-heading { margin: 0 0 var(--wp--preset--spacing--40); /* 24 */
	font-family: var(--wp--preset--font-family--display); font-size: 24px; font-weight: 700;
	line-height: 1.2; color: var(--wp--preset--color--foreground); }
.zo-author-bio__focus-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap;
	column-gap: var(--wp--preset--spacing--40); row-gap: var(--wp--preset--spacing--30); /* 24/16 */ }
.zo-author-bio__focus-link { display: inline-flex; align-items: center; gap: 6px; /* 5301-15652 Icon→Label */
	color: var(--wp--preset--color--foreground); font-size: 16px; font-weight: 500; line-height: 22px;
	text-decoration: underline; }
.zo-author-bio__focus-link:hover, .zo-author-bio__focus-link:focus-visible { color: var(--wp--preset--color--link); }
.zo-author-bio__focus-icon { display: inline-flex; flex: 0 0 auto; }
.zo-author-bio__focus-icon svg { width: 18px; height: 18px; }

.zo-author-boxes__heading { margin: 0 0 var(--wp--preset--spacing--40); /* 24: H2→Karten */
	font-family: var(--wp--preset--font-family--display); font-size: 32px; font-weight: 700;
	line-height: 42px; color: var(--wp--preset--color--foreground); }
/* Rail kommt von der Sektion; Karten-Metrik des Profil-Frames (Padding 32, Gap 12) statt
   Komponenten-Default 24/16 (5301-15652: Titel x88 − Karte x56 = 32). */
.zo-author-main .zo-content-box__grid { padding-inline: 0; }
.zo-author-main .zo-content-box__item { padding: var(--wp--preset--spacing--50); /* 32 */ gap: 12px; }

/* margin-block statt Shorthand: margin-inline:auto der Sektions-Rail muss erhalten bleiben. */
.zo-author-section__heading { margin-block: 0 var(--wp--preset--spacing--50); /* 32: Heading→Zeilen (1322−1290) */
	font-family: var(--wp--preset--font-family--display); font-size: 40px; font-weight: 700;
	line-height: 52px; color: var(--wp--preset--color--foreground); }

.zo-author-section--kurse { background: var(--wp--preset--color--accent-lilac);
	padding-block: 56px; /* 5301-15652: 1916−1860 / 2530−2474 */ }
.zo-author-section--testimonials { background: var(--wp--preset--color--white);
	padding-block: var(--wp--preset--spacing--70); /* 64: 2691−2627 */ }

/* Organisation profile (#275): reuses the .zo-author-* layout above 1:1 (grid 836/425,
   rhythm, rail). Only the intro delta: rich editor content instead of the single bio
   <p>, and the contact rows stack vertically instead of the focus-pill wrap. */
.zo-author-bio__text--rich :is(p, ul, ol) { margin-block: 0 16px; font-size: 18px;
	font-weight: 500; line-height: 26px; letter-spacing: 0.01em; }
.zo-author-bio__text--rich > :last-child { margin-block-end: 0; }
.zo-author-bio__focus-list--contact { flex-direction: column; row-gap: var(--wp--preset--spacing--30); /* 16 */ }
.zo-author-bio__focus-link--plain { text-decoration: none; }

/* ============================================================
   Artikel-Einzelseite (templates/single.html) — Grundgerüst mit drei Breitenstufen.
   Figma: Paragraph 5529:39784 · Video 5768:94 (dev-ready COMPONENT_SETs, Property
   „Integrated") · Skizze 5860:66435 (Playground, nur Reihenfolge/Abstände) · sync 2026-08-06.
   Abstände nachvalidiert gegen die freigegebene Detailseite 6058:19945 (#238, sync 2026-08-22).
   Spec: docs/figma-specs/artikel-grundgeruest.md · Issue #145.
   States: n/a (reines Layout-Gerüst, keine interaktiven Elemente).
   Breakpoints: SM <640 · MD 640 · LG 1024 · XL 1440 (Foundation, content-rail.md).
   ============================================================ */

/* Full-Bleed: die Rail entsteht erst im Content-Grid, nicht davor. Ohne die Resets zieht WPs
   Root-Padding (has-global-padding, gemessen 40 @1440) die Grid-Spuren um clamp(24,5vw,40)
   zusammen — die Rail käme auf 1296 statt 1328 heraus. */
main.zo-article { padding-inline: 0; }
.zo-article > * { margin-block: 0; }
/* Bereichs-Abstand = Modul-Abstand: die freigegebenen Artikel-Frames 6058:26535 (XL 96) /
   6058:26544 (LG 64) / 6058:26541 (MD 56) / 6075:38415 (SM 40) binden itemSpacing an dieselben
   Variablen wie module-gap.md (5033:24673/24677/24678/24672) — nachvalidiert in #238. */
.zo-article > * + * { margin-block-start: var(--zo-module-gap); }
/* Kein eigener Boden — Content→Footer liefert die Footer-Margin (#174, module-gap.md
   §Nachtrag); bestätigt in #238: alle vier freigegebenen Frames enden bündig mit dem
   letzten Modul, kein paddingBottom. */

/* Drei-Spuren-Grid: [full] [rail 1328] [full]. Named Lines statt 100vw/negativer Margins —
   dadurch kein Scrollbar-Artefakt (content-rail.md §align:full nennt den 100vw-Tradeoff).
   Spuren lösen auf zu 56|1328|56 (1440) · 32|960|32 (1024) · 24|592|24 (640) · 16|288|16 (320).
   Der Meta-Block (#147) sitzt in derselben Textspur wie der Content-Strom und teilt sich
   deshalb die Spuren-Definition — eine Quelle, kein zweites Grid daneben. */
.zo-article__content,
.zo-article__meta {
	display: grid;
	padding-inline: 0; /* post-content ist constrained → WP hängt has-global-padding an (s. o.) */
	grid-template-columns:
		[full-start] minmax(var(--zo-grid-margin), 1fr)
		[rail-start] minmax(0, var(--zo-content-max))
		[rail-end]   minmax(var(--zo-grid-margin), 1fr)
		[full-end];
	--zo-article-cols: var(--zo-grid-columns); /* SM/MD: Textspalte = volle Rail */
}
/* Abstand im Content-Strom, viewport-gestuft (nachvalidiert #238): itemSpacing der
   Content-Slots in den freigegebenen Artikel-Frames, variablengebunden — SM 32
   (I6075:38422;6062:3, Var 4401:30573) · MD 40 (I6059:35306;6062:5, Var 4488:31970) ·
   LG+XL 48 (I6059:31884;6062:7 + I6059:30827;6062:9, Var 4401:30575). Kein
   theme.json-Preset: 48 fehlt in der Skala (Muster --zo-module-gap).
   Margin flow instead of row-gap (#372): text pairs (heading -> paragraph, paragraph ->
   paragraph) sit closer than modules, and a grid row-gap cannot be undercut per pair.
   Grid items do not collapse margins, so module -> module stays exactly this gap. */
.zo-article__content { --zo-article-gap: 32px; }
@media (min-width: 640px)  { .zo-article__content { --zo-article-gap: 40px; } }
@media (min-width: 1024px) { .zo-article__content { --zo-article-gap: 48px; } }
/* Headings in the article stream keep their own step (#402): the approved article canvas
   6058:19945 (XL 6058:26535, LG 6058:26544, MD 6058:26541, SM 6075:38415, sync 2026-10-03)
   sets the article <h2> in the H2 step, the same size as the card carousel heading (XL/LG
   40/52, MD 24/32, SM 20/26), <h3> in H3 and <h4> in H4, gaps = the step's pb. This
   replaces the one-step-down remap from #372. */
@media (min-width: 1024px) { .zo-article__content, .zo-article__meta { --zo-article-cols: 8; } } /* LG 635 = 8/12 */
@media (min-width: 1440px) { .zo-article__content, .zo-article__meta { --zo-article-cols: 7; } } /* XL 768 = 7/12 */

/* Stufe 1 — Textspalte (Default). Spannweite im 12er-Raster, keine feste px-Breite:
   100% = Rail-Spur → XL 1328 ergibt 768 (5754:25232), LG 960 ergibt 634,67 (5754:25262).
   Doppelter Selektor (0,2,0), damit die constrained-Layout-Regel von post-content verliert. */
.zo-article .zo-article__content > *,
.zo-article .zo-article__content > .zo-w-text,
.zo-article .zo-article__meta > * {
	grid-column: rail-start / rail-end;
	width: calc((100% + var(--zo-grid-gutter)) / var(--zo-grid-columns)
		* var(--zo-article-cols) - var(--zo-grid-gutter));
	max-width: 100%;
	margin-inline: auto;
	margin-block: 0; /* WP flow gap; spacing comes from the rule below */
}
.zo-article .zo-article__content > * + * { margin-block-start: var(--zo-article-gap); }
/* SM (<640) the article anchor nav has no in-content state, only the fixed condensate, so its
   box is 0 high. It must not add a gap of its own: the block after it keeps the gap it would
   have to the block before it (text -> text one copy line, text -> heading 24, else the
   article gap). Without this the first two paragraphs stood 64 apart instead of 20 (#374). */
@media (max-width: 639px) {
	.zo-article .zo-article__content > .zo-anchor-nav--article { margin-block-start: 0; }
	.zo-article .zo-article__content > .zo-anchor-nav--article:first-child + * { margin-block-start: 0; }
	.zo-article .zo-article__content > :is(p, ul, ol) + .zo-anchor-nav--article + :is(p, ul, ol) { margin-block-start: var(--zo-copy-gap); }
	.zo-article .zo-article__content > :is(p, ul, ol) + .zo-anchor-nav--article + :is(h1, h2, h3, h4, h5, h6) { margin-block-start: var(--zo-text-gap); }
}
/* MD+ the in-content pill row sits with the same gap above and below (#402): the approved
   canvas 6058:19945 stacks content container, Anchor Navigation, content container with the
   section itemSpacing MD 56, LG/XL 64. The pill row's own module-gap margin (PDP) is dropped
   here, otherwise the gap above was article gap + module gap (XL 144) against 48 below. */
@media (min-width: 640px) {
	.zo-article__content { --zo-article-nav-gap: 56px; }
	.zo-article .zo-article__content > .zo-anchor-nav--article:not(:first-child),
	.zo-article .zo-article__content > .zo-anchor-nav--article + * { margin-block-start: var(--zo-article-nav-gap); }
	.zo-article .zo-article__content > .zo-anchor-nav--article .zo-anchor-nav__incontent { margin-top: 0; }
}
@media (min-width: 1024px) { .zo-article__content { --zo-article-nav-gap: 64px; } }
/* Bulleted list in the article stream (#374, Figma "List Bullet" in the article slots
   I6059:30827;6062:9;6059:30936 XL · I6059:31884;6062:7;6059:31878 LG ·
   I6059:35306;6062:5;6059:35300 MD · 6075:38422 SM, sync 2026-09-27): square 3x3 marker in
   foreground, centred on the first line, flush with the text column; marker -> text and
   item -> item 8 from LG, 6 below. Size, line height and the gaps around the list come from
   the text rhythm (#372). Only plain <ul>: Figma has no numbered list (<ol> keeps its
   numbers), component lists (zo-*, e.g. the check list) keep their own marker. */
.zo-article__content { --zo-list-gap: 6px; }
@media (min-width: 1024px) { .zo-article__content { --zo-list-gap: var(--wp--preset--spacing--20); /* 8 */ } }
.zo-article .zo-article__content > ul:not([class*="zo-"]) { list-style: none; padding-inline-start: 0; }
.zo-article .zo-article__content > ul:not([class*="zo-"]) > li { position: relative; padding-inline-start: calc(3px + var(--zo-list-gap)); }
.zo-article .zo-article__content > ul:not([class*="zo-"]) > li + li { margin-block-start: var(--zo-list-gap); }
.zo-article .zo-article__content > ul:not([class*="zo-"]) > li::before { content: ""; position: absolute; top: calc(0.5lh - 1.5px); left: 0;
	width: 3px; height: 3px; background: var(--wp--preset--color--foreground); }

/* Stufe 2 — Hervorgehoben: volle Inhalts-Rail 1328 (5529:39743 → Kind x=56 w=1328). */
.zo-article .zo-article__content > .alignwide,
.zo-article .zo-article__content > .zo-w-rail {
	grid-column: rail-start / rail-end;
	width: 100%;
}

/* Stufe 3 — Fensterbreite: bis zum Viewport-Rand (5860:66488 Image Carousel, 5860:66490
   Quote Standalone: x=0 w=1440). */
.zo-article .zo-article__content > .alignfull,
.zo-article .zo-article__content > .zo-w-viewport {
	grid-column: full-start / full-end;
	/* width:100%, nicht auto: das constrained-Layout von post-content setzt Kindern ohne
	   align-Klasse margin-inline:auto !important — bei width:auto schrumpft das Grid-Item
	   dann auf seinen Inhalt (gemessen 179,84 statt Viewport). */
	width: 100%;
	max-width: none;
}

/* ---------- Bild + Video im Content-Strom (#149) ----------
   Figma: 5754:19996 COMPONENT_SET „Image" · 5768:94 COMPONENT_SET „Video" (beide dev-ready,
   Viewport × Integrated) · sync 2026-08-06. Spec: docs/figma-specs/artikel-bausteine.md §1.
   Bewusst artikel-gescopet und nur auf DIREKTE Kinder des Content-Stroms: so bleibt die
   globale core/image-Darstellung (PDP, Teaser, Karussells) unangetastet und geschachtelte
   Bilder — z. B. der Avatar im Zitat — behalten ihre eigene Form.
   Der Play-Knopf des Videos ist der Block-Style .is-style-zo-video (COMPONENTS).
   States: n/a (Link/Fokus liegen am core/image selbst).
   Breakpoints: Bildunterschrift 12/16 unter 1024, 14/20 ab 1024 (5754:19992 / 5754:19995). */
.zo-article .zo-article__content > .wp-block-image {
	--zo-am-gap: 12px;                              /* 5754:19992 itemSpacing */
	--zo-am-cap-fs: var(--wp--custom--font-size--12);
	--zo-am-cap-lh: 16px;
	--zo-am-cap-ls: 0.12px;
	--zo-am-cap-max: 680px;                         /* Text-Knoten maxWidth, Textspalte */
}
/* 16:9-Ausschnitt (5754:19995 768×432, 5754:24965 1328×747, 5754:19992 288×162). */
.zo-article .zo-article__content > .wp-block-image img {
	width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; display: block;
}
.zo-article .zo-article__content > .wp-block-image.alignwide { --zo-am-cap-max: 800px; }
.zo-article .zo-article__content > .wp-block-image figcaption {
	margin: var(--zo-am-gap) 0 0; max-width: var(--zo-am-cap-max); text-align: left;
	font-family: var(--wp--preset--font-family--body); font-weight: 500;
	font-size: var(--zo-am-cap-fs); line-height: var(--zo-am-cap-lh);
	letter-spacing: var(--zo-am-cap-ls); color: var(--wp--preset--color--grey);
}
@media (min-width: 1024px) {
	.zo-article .zo-article__content > .wp-block-image {
		--zo-am-gap: var(--wp--preset--spacing--30); /* 16 — 5754:19995 itemSpacing */
		--zo-am-cap-fs: var(--wp--preset--font-size--small);
		--zo-am-cap-lh: 20px; --zo-am-cap-ls: 0.14px;
	}
}

/* ---------- Meta-Block: Datum · Lesezeit + Themen/Phase (#147) ----------
   Figma: 5860:67222 Intro-Block (Skizze, nur Zusammensetzung/Abstände) · Meta-Zeile aus der
   dev-ready Komponente .zo-meta-info (COMPONENTS) · Links aus 5200:58877 „Text link .base"
   (Size=SM), im Artikel auf Ink umgefärbt. Spec: docs/figma-specs/article-meta.md.
   States: Term-Link :hover (Link-Violett) · :focus-visible (Ring, Hausmuster). active/
   disabled n/a. Leerzustand: das Pattern rendert ohne Themen und ohne Phase nichts.
   Breakpoints: keine eigenen — Breite kommt aus der Textspur, die Zeile bricht um. */
.zo-article-meta { display: flex; flex-direction: column;
	gap: var(--wp--preset--spacing--30); } /* 16: 5860:67222 itemSpacing */

/* Themen UND Phase in EINEM umbruchfähigen Fluss (Philipp #147). Der Entwurf deckt das:
   5860:67138 und 5860:67140 führen beide layoutWrap WRAP mit counterAxisSpacing 8.
   flex-start statt baseline — Figma richtet oben aus, dadurch bleibt die Zeile exakt 22 hoch.
   Labels und Links liegen FLACH in einem Flex-Fluss statt wie in Figma als Label + genestete
   Link-Gruppe: eine genestete Gruppe ist EIN Flex-Element und rutscht komplett auf die
   nächste Zeile, „Themen:" stünde dann allein (gemessen: 5 Zeilen statt 2). Die 32 um die
   Labels entstehen aus dem 24er column-gap plus 8 Margin. Spec §4.4.
   The 8 before a label sits as trailing margin on the preceding link, not as leading margin on
   the label: a trailing margin at a line end is invisible, so a label that wraps to a new line
   starts flush at x=0 under "Themen:" (#367). */
.zo-article-meta__terms { display: flex; flex-wrap: wrap; align-items: flex-start;
	column-gap: var(--wp--preset--spacing--40); /* 24: 5860:67140 itemSpacing */
	row-gap: var(--wp--preset--spacing--20); }  /* 8: 5860:67138/67140 counterAxisSpacing */
.zo-article-meta__terms-label { font-size: var(--wp--preset--font-size--medium); font-weight: 700;
	line-height: 22px; letter-spacing: 0.16px; color: var(--wp--preset--color--foreground);
	margin-inline-end: var(--wp--preset--spacing--20); } /* 24 + 8 = 32: 5860:67138 itemSpacing */
.zo-article-meta__term:has(+ .zo-article-meta__terms-label) {
	margin-inline-end: var(--wp--preset--spacing--20); } /* 8 before the label, see above */
.zo-article-meta__term { font-size: var(--wp--preset--font-size--small); font-weight: 500;
	line-height: 20px; letter-spacing: 0.14px; color: var(--wp--preset--color--foreground);
	/* Unterstrich: im Node-JSON steht kein textDecoration, das Render von 5200:58877 zeigt ihn
	   trotzdem — 2px, eine Zeile unter den Buchstaben (Spec §3.2, Pixel-Sampling). */
	text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 2px; }
.zo-article-meta__term:hover { color: var(--wp--preset--color--link); }
.zo-article-meta__term:focus-visible { outline: 2px solid var(--wp--preset--color--foreground); outline-offset: 2px; }

/* Topics line -> first content block = the article gap 32/40/48 (#402, slot itemSpacing of
   the approved canvas 6058:19945; replaces the flat 32 from 5860:66471). Three-part selector
   so it beats `.zo-article > * + *`. */
.zo-article .zo-article__meta + .zo-article__content { margin-block-start: var(--zo-article-gap); }

/* Druckbild des Artikels (#146). Das Rahmenwerk (Nav, Fußbereich, Sprungmarken,
   Teilen/Drucken) blendet der @media-print-Block am Ende von COMPONENTS aus; hier bleibt der
   Textstrom: alle drei Breitenstufen kollabieren auf eine Spalte, Links zeigen ihr Ziel.
   Getrennt platziert, weil tools/css/check-sections.js jeden Selektor seiner Sektion zuordnet —
   .zo-article gehört nach PAGES, die Komponenten nach COMPONENTS. */
@media print {
	.zo-article > * + * { margin-block-start: var(--wp--preset--spacing--50); } /* 32 statt 96 */
	.zo-article .zo-article__content,
	.zo-article .zo-article__meta { display: block; } /* Meta-Block teilt die Spuren, #147 */
	.zo-article .zo-article__content > *,
	.zo-article .zo-article__content > .alignwide,
	.zo-article .zo-article__content > .alignfull,
	.zo-article .zo-article__content > .zo-w-text,
	.zo-article .zo-article__content > .zo-w-rail,
	.zo-article .zo-article__content > .zo-w-viewport,
	.zo-article .zo-article__meta > * {
		width: 100%;
		max-width: 100%;
		margin-inline: 0;
	}
	.zo-article .zo-article__content > * + * { margin-block-start: var(--wp--preset--spacing--40); }
	/* Auf Papier ist ein Filter-Link wertlos — Themen/Phase bleiben als Text lesbar. */
	.zo-article-meta__term { text-decoration: none; }
	/* Ziel-URL hinter externen/absoluten Links — auf Papier ist ein Link sonst wertlos. */
	.zo-article .zo-article__content a[href^="http"]::after { content: " (" attr( href ) ")"; font-size: var(--wp--custom--font-size--12); word-break: break-all; }
	/* PDP (#309 follow-up): card backgrounds don't print, but their paddings would keep
	   the content indented from the left edge for no visible reason — flush left. The
	   booking form (date select, buy/waitlist buttons) is interaction-only, off on paper;
	   the format flag would print white on white without its background. Selectors sit
	   after the screen rules in file order on the same specificity tier. */
	.single-product .zo-pdph__card { padding: 0; }
	.zo-pdp-topics__card { padding: 0; }
	.single-product .zo-pdph__card form.cart,
	.single-product .zo-pdph__card .wp-block-add-to-cart-form,
	.single-product .zo-pdph__card a.zo-pdph__continue,
	.single-product .zo-pdph__card button.zo-pdph__waitlist { display: none; }
	.single-product .zo-pdph__flag { background: none; color: var(--wp--preset--color--foreground); padding: 0; }
}

/* ===================================================================== *
 *  INTEGRATIONS — Overrides für Fremd-CSS (unlayered, müssen Plugin-/WP-CSS schlagen).
 *  Nur was gegen Plugin-Markup ankämpft — der WC-Loop (ul.products) und die Filterleiste.
 *  Ein eigener Seiten-Scope gehört auch dann nach PAGES, wenn die Seite von einem Plugin
 *  stammt (.zo-course = LearnDash-Kursseite).
 * ===================================================================== */

/* Archiv-Kontext der Filterleiste (#103): Widget unter der Archiv-Überschrift — Abstand wie
   die alte .zo-kat-filters-Zeile (40 zur Überschrift; die 40 zum Loop bringt ul.products).
   Im zo/product-grid (freie Seiten, #138) setzt .zo-product-grid .zo-filterbar den Abstand. */
.zo-kat-archive .zo-filterbar { margin-top: 40px; }

/* WooCommerce-Loop (ul.products) auf das Katalog-Grid mappen (Grid-Foundation #128:
   Spalten/Gutter aus den Grid-Tokens, li = span 4); !important überschreibt die WC-Default-Styles */
.zo-kat-archive ul.products {
	list-style: none; margin: 40px 0 0; padding: 0;
	display: grid; grid-template-columns: repeat(var(--zo-grid-columns), 1fr); gap: var(--zo-grid-gutter);
}

.zo-kat-archive ul.products::before,
.zo-kat-archive ul.products::after { content: none; }

.zo-kat-archive ul.products li.product {
	grid-column: span 4; width: auto !important; margin: 0 !important; padding: 0 !important; float: none !important;
}

.zo-kat-archive ul.products li.product .zo-kat-card { width: 100%; }

/* Bildhoehe im Archiv festnageln (#94): WC-Core setzt `ul.products li.product a img { height:auto }`
   (Spez. 0-3-1) und leitet aus den width/height-Attributen des <img> eine aspect-ratio ab -> das Bild
   spraengt sonst den 2:1-Media-Wrapper (#128: aspect-ratio statt Fixhoehe). Vier-Klassen-Selektor
   (0-4-2) schlaegt die WC-Regel ohne !important. */
.zo-kat-archive ul.products li.product .zo-kat-card__img { height: 100%; }

/* Pagination zentriert (Filterleiste ersetzt Zähler + Sortierung) */
.zo-kat-archive .woocommerce-pagination { margin-top: 40px; }

.zo-kat-archive .woocommerce-pagination ul { display: flex; justify-content: center; gap: 8px; list-style: none; margin: 0; padding: 0; }

/* WooCommerce Notice-Banner (#97): Success/Error/Warning/Info an die ZO-Palette angleichen.
   WC 10.9.1 rendert klassische Notices (wc_print_notice) UND die Cart/Checkout-Blocks-Banner
   über dasselbe Markup `.wc-block-components-notice-banner.is-{success|error|warning|info}`
   (Inline-<svg> als Status-Icon, `__content`, optional Dismiss-Button `.wc-block-components-button`).
   Weg b (Olaf/Philipp #97): Paper-Fläche + farbiger Left-Border + gefärbtes Line-Icon im 500er-Ton,
   KEINE Flächen-Tönung — nutzt nur belegte Töne, über alle vier States konsistent. Marke scharfkantig
   (Radius 0). WC-Default-SVG ersetzt durch eigenes RemixIcon-Set via CSS-Mask (Error = eigenes
   ZO-Oktagon `alert-2-line` 5551:22459, Warning `alert-line` 5551:22463, Info `information-line`
   2622:7118, Success `check-line` 2622:7090, Dismiss `close-line` 2622:7098).
   `!important`: WC-Block-CSS lädt nach dem Theme und setzt State-Farben/Link/Button teils selbst mit
   `!important` — ohne `!important` verloren. States: n/a im Block-Editor (rein Frontend-Feedback). */
.wc-block-components-notice-banner {
	background-color: var(--wp--custom--color--grey-50) !important;
	color: var(--wp--custom--color--ink) !important;
	border: 4px solid var(--wp--custom--color--ink) !important;
	border-radius: 0 !important;
	align-items: flex-start;
}

/* Default-SVG-Roundel ausblenden; eigenes Line-Icon per Mask davor setzen */
.wc-block-components-notice-banner > svg { display: none !important; }

.wc-block-components-notice-banner::before {
	content: "";
	flex: 0 0 24px;
	width: 24px;
	height: 24px;
	background-color: var(--wp--custom--color--ink);
	-webkit-mask: var(--zo-notice-icon) center / contain no-repeat;
	mask: var(--zo-notice-icon) center / contain no-repeat;
	--zo-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 7H13V9H11V7ZM11 11H13V17H11V11Z'/%3E%3C/svg%3E");
}

.wc-block-components-notice-banner.is-success { border-color: var(--wp--custom--color--green-500) !important; }
.wc-block-components-notice-banner.is-success::before {
	background-color: var(--wp--custom--color--green-500);
	--zo-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.9999 15.1709L19.1928 5.97705L20.6071 7.39126L9.9999 17.9993L3.63599 11.6354L5.0502 10.2212L9.9999 15.1709Z'/%3E%3C/svg%3E");
}

.wc-block-components-notice-banner.is-error { border-color: var(--wp--custom--color--red-500) !important; }
.wc-block-components-notice-banner.is-error::before {
	background-color: var(--wp--custom--color--red-500);
	--zo-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M15.936 2.5L21.5 8.067L21.5 15.937L15.936 21.5L8.066 21.5L2.5 15.936L2.5 8.066L8.066 2.5L15.936 2.5ZM15.107 4.5L8.894 4.5L4.501 8.895L4.501 15.108L8.894 19.502L15.107 19.502L19.501 15.108L19.501 8.894L15.107 4.501L15.107 4.5ZM11 15L13 15L13 17L11 17L11 15ZM11 7L13 7L13 13L11 13L11 7Z'/%3E%3C/svg%3E");
}

.wc-block-components-notice-banner.is-warning { border-color: var(--wp--custom--color--orange-500) !important; }
.wc-block-components-notice-banner.is-warning::before {
	background-color: var(--wp--custom--color--orange-500);
	--zo-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.8659 3.00017L22.3922 19.5002C22.6684 19.9785 22.5045 20.5901 22.0262 20.8662C21.8742 20.954 21.7017 21.0002 21.5262 21.0002H2.47363C1.92135 21.0002 1.47363 20.5525 1.47363 20.0002C1.47363 19.8246 1.51984 19.6522 1.60761 19.5002L11.1339 3.00017C11.41 2.52187 12.0216 2.358 12.4999 2.63414C12.6519 2.72191 12.7782 2.84815 12.8659 3.00017ZM4.20568 19.0002H19.7941L11.9999 5.50017L4.20568 19.0002ZM10.9999 16.0002H12.9999V18.0002H10.9999V16.0002ZM10.9999 9.00017H12.9999V14.0002H10.9999V9.00017Z'/%3E%3C/svg%3E");
}

.wc-block-components-notice-banner.is-info { border-color: var(--wp--custom--color--blue-500) !important; }
.wc-block-components-notice-banner.is-info::before {
	background-color: var(--wp--custom--color--blue-500);
	--zo-notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 7H13V9H11V7ZM11 11H13V17H11V11Z'/%3E%3C/svg%3E");
}

/* Links im Banner: allgemeines Link-Design (ink, kein Bold, Underline nur bei Hover, kein Sprung).
   WC stylt `.wc-forward` bei Spezifität (0,3,0) mit color:#2f2f2f!important, opacity:.7 (wirkt grau)
   und Underline-Default + opacity/decoration-Sprung auf Hover. Um das zu schlagen, doppeln wir die
   Root-Klasse ((0,4,0)) und setzen opacity/float/font-weight/decoration explizit zurück. */
.wc-block-components-notice-banner.wc-block-components-notice-banner .wc-block-components-notice-banner__content a,
.wc-block-components-notice-banner.wc-block-components-notice-banner .wc-block-components-notice-banner__content .wc-forward {
	color: var(--wp--custom--color--ink) !important;
	opacity: 1 !important;
	float: none !important;
	font-weight: 400 !important;
	text-decoration: none !important;
	text-underline-position: auto;
}
.wc-block-components-notice-banner.wc-block-components-notice-banner .wc-block-components-notice-banner__content a:hover,
.wc-block-components-notice-banner.wc-block-components-notice-banner .wc-block-components-notice-banner__content a:focus,
.wc-block-components-notice-banner.wc-block-components-notice-banner .wc-block-components-notice-banner__content .wc-forward:hover,
.wc-block-components-notice-banner.wc-block-components-notice-banner .wc-block-components-notice-banner__content .wc-forward:focus {
	opacity: 1 !important;
	text-decoration: underline !important;
}

/* Dismiss-X behalten: eigenes close-Icon, ink, dezent -> voll bei Hover/Focus */
.wc-block-components-notice-banner > .wc-block-components-button { color: var(--wp--custom--color--ink) !important; }
.wc-block-components-notice-banner > .wc-block-components-button > svg { display: none !important; }
.wc-block-components-notice-banner > .wc-block-components-button::before {
	content: "";
	display: block;
	width: 16px;
	height: 16px;
	background-color: var(--wp--custom--color--ink);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Konto-Strecke (#171): Woo-Formulare erben die Formular-Basis (BASE, #170). woocommerce.css
   rahmt form.login/register/lost_reset_password als Box (1px-Rahmen, Radius 5, Padding 20;
   Spez. 0-2-1), woocommerce-blocktheme.css legt auf die Felder einen Box-Stil (1px-Rahmen,
   Radius 4, weiss, 14px, eigenes Padding). Beides liegt ueber den niedrig-spezifischen
   BASE-:where()-Regeln — hier gezielt zurueckgenommen; Werte spiegeln die BASE-Feldregeln
   (gleiche Tokens, keine neuen Konstanten). Die Spiegelung schliesst Hover/Fokus ein, weil
   dieser hoeher-spezifische Reset sonst auch die BASE-Zustandsfarben schlagen wuerde.
   Scope .woocommerce-account = Login + alle Konto-Endpoints; Checkout bleibt unberuehrt (#171
   §Grenzen). Exception (#392): the login / e-mail verification gate of the order-pay
   endpoint is the same Woo form and joins by form class only. States: hover/focus/error wie BASE; Breakpoints: n/a (Felder fluid). */
.woocommerce-account .woocommerce form.login,
.woocommerce-account .woocommerce form.register,
.woocommerce-account .woocommerce form.lost_reset_password,
.woocommerce-order-pay .woocommerce form.login {
	border: 0;
	border-radius: 0;
	padding: 0;
}
.woocommerce-account .woocommerce form .form-row input.input-text,
.woocommerce-account .woocommerce form .form-row textarea,
.woocommerce-order-pay .woocommerce form.login .form-row input.input-text,
.woocommerce-order-pay .woocommerce form.woocommerce-verify-email .form-row input.input-text {
	border: 0;
	border-bottom: 4px solid var(--wp--preset--color--foreground);
	border-radius: 0;
	background-color: transparent;
	padding: 13px 0 9px;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
	line-height: 22px;
	letter-spacing: 0.16px;
	color: var(--wp--preset--color--foreground);
}
.woocommerce-account .woocommerce form .form-row input.input-text,
.woocommerce-order-pay .woocommerce form.login .form-row input.input-text,
.woocommerce-order-pay .woocommerce form.woocommerce-verify-email .form-row input.input-text { height: 48px; }
.woocommerce-account .woocommerce form .form-row input.input-text:hover:not(:disabled, [readonly]),
.woocommerce-account .woocommerce form .form-row textarea:hover:not(:disabled, [readonly]),
.woocommerce-order-pay .woocommerce form.login .form-row input.input-text:hover:not(:disabled, [readonly]),
.woocommerce-order-pay .woocommerce form.woocommerce-verify-email .form-row input.input-text:hover:not(:disabled, [readonly]) {
	border-bottom-color: var(--wp--custom--color--violet-dark);
}
.woocommerce-account .woocommerce form .form-row input.input-text:focus:not([readonly]),
.woocommerce-account .woocommerce form .form-row textarea:focus:not([readonly]),
.woocommerce-order-pay .woocommerce form.login .form-row input.input-text:focus:not([readonly]),
.woocommerce-order-pay .woocommerce form.woocommerce-verify-email .form-row input.input-text:focus:not([readonly]) {
	outline: 0;
	border-bottom-color: var(--wp--preset--color--primary);
}
.woocommerce-account .woocommerce form .form-row input.input-text[aria-invalid="true"],
.woocommerce-account .woocommerce .woocommerce-invalid input.input-text,
.woocommerce-order-pay .woocommerce form.login .woocommerce-invalid input.input-text,
.woocommerce-order-pay .woocommerce form.woocommerce-verify-email .woocommerce-invalid input.input-text {
	border-bottom-color: var(--wp--custom--color--red-500);
}
/* Account form selects (#325, edit-address endpoint): selectWoo is dequeued there
   (inc/woocommerce.php), so the native <select> carries the BASE dropdown rules (#170) —
   but Woo's .form-row box style (1px border, radius 4, 14px/400, own chevron, 3em padding)
   sits above them just like on the inputs and is mirrored back here with the same token
   values (arrow fill hexes = token values foreground/violet-dark, spec form-controls.md
   §Zustandsfarben). Disabled/readonly intentionally omitted like the input mirror above
   (does not occur on the account track). */
.woocommerce-account .woocommerce form .form-row select {
	height: 48px;
	border: 0;
	border-bottom: 4px solid var(--wp--preset--color--foreground);
	border-radius: 0;
	padding: 13px 26px 9px 0; /* right: arrow 18 + gap 8 (form-controls.md §Soll-Maße) */
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	line-height: 22px;
	letter-spacing: 0.16px;
	color: var(--wp--preset--color--foreground);
	appearance: none;
	background-color: transparent;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%231A1A1A' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right center;
	background-size: 18px 18px;
}
.woocommerce-account .woocommerce form .form-row select:hover:not(:disabled) {
	border-bottom-color: var(--wp--custom--color--violet-dark);
	color: var(--wp--custom--color--violet-dark);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%236842DB' d='M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z'/%3E%3C/svg%3E");
}
.woocommerce-account .woocommerce form .form-row select:focus {
	border-bottom-color: var(--wp--preset--color--foreground); /* Woo's border-color:currentColor would turn violet on hover */
}
.woocommerce-account .woocommerce .woocommerce-invalid select {
	border-bottom-color: var(--wp--custom--color--red-500);
}
/* Account details: password fieldset as plain subheading (#326). The WC template hardcodes
   <fieldset><legend> around the password rows — no hook, so the browser-default groove box
   is stripped here and the legend mirrors the theme.json h2 element styles (display font,
   x-large/700, lh 1.3) like the address-page headings; margins = spacing|50 ≈ the UA h2
   margin (0.83em = 33.2px @40px) those render with. float:left takes the legend out of the
   fieldset's border-box slot (margins are ignored there); the form rows clear the float.
   Fieldset/legend group semantics stay in the DOM for screen readers.
   States/Breakpoints: n/a (static heading, fluid font token). */
.woocommerce-account .woocommerce form.edit-account fieldset {
	border: 0;
	margin: 0;
	padding: 0;
	min-width: 0;
}
.woocommerce-account .woocommerce form.edit-account fieldset legend {
	float: left;
	width: 100%;
	margin: var(--wp--preset--spacing--50) 0;
	padding: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: 0;
	color: var(--wp--preset--color--foreground);
}
.woocommerce-account .woocommerce form.edit-account fieldset .form-row { clear: both; }

/* Konto-Subnavigation eingeloggt (#173, Figma 4501-35562 „Subnavigation" Type=plain/Drawer=No,
   Spec docs/figma-specs/konto-subnav.md · Sync 2026-08-10). Layout Nav/Inhalt = dokumentierter
   Best Guess auf der Grid-Foundation (kein Figma-Gesamtframe → #129): Grid-Tokens direkt am
   Woo-Wrapper, weil das Plugin-Markup keine .zo-grid-Utilities tragen kann. Scope
   .woocommerce-account.logged-in = nur eingeloggte Konto-Seiten; Login/Registrierung/
   Passwort-Reset bleiben unberührt (#171). Woo floatet Nav/Content 30/68 % — Floats sind
   als Grid-Items wirkungslos, nur die Breiten müssen zurück auf auto.
   States: Items :hover/:focus-visible = primary (Nav-Konvention .zo-mainnav), .is-active =
   primary inkl. Trennlinie; Abmelden-States über die .zo-btn-Adopter (COMPONENTS).
   disabled/leer/laden: n/a. Breakpoints: <1024 gestapelt (Nav über Inhalt, volle Breite),
   ab 1024 (LG/XL) Nav span 3 / Inhalt span 9. */
.woocommerce-account.logged-in .woocommerce {
	display: grid;
	grid-template-columns: repeat(var(--zo-grid-columns), 1fr);
	column-gap: var(--zo-grid-gutter);
	row-gap: var(--wp--preset--spacing--60);
	max-width: none; /* woocommerce-blocktheme.css deckelt den Konto-Wrapper auf 1000px */
}
/* Woo-Clearfix (display:table) würde als anonymes Grid-Item die Spalten verschieben */
.woocommerce-account.logged-in .woocommerce::before,
.woocommerce-account.logged-in .woocommerce::after { display: none; }
.woocommerce-account.logged-in .woocommerce > * { grid-column: 1 / -1; }
/* Leerer Notices-Wrapper wäre sonst eine Phantom-Grid-Zeile (row-gap) */
.woocommerce-account.logged-in .woocommerce > .woocommerce-notices-wrapper:empty { display: none; }
.woocommerce-account.logged-in .woocommerce-MyAccount-navigation,
.woocommerce-account.logged-in .woocommerce-MyAccount-content { width: auto; }
@media (min-width: 1024px) {
	.woocommerce-account.logged-in .woocommerce > .woocommerce-MyAccount-navigation { grid-column: span 3; }
	.woocommerce-account.logged-in .woocommerce > .woocommerce-MyAccount-content { grid-column: span 9; }
}
/* Weiße Karte = Container der Variante Drawer=No (Fill weiß, Padding 24 li/re, 12 oben/unten) */
.woocommerce-account.logged-in .woocommerce-MyAccount-navigation {
	align-self: start;
	background: var(--wp--preset--color--white);
	padding: 12px 24px;
}
/* Selektor-Anhebung (li./ul-Stufen): woocommerce-blocktheme.css setzt li{padding:1em 0},
   ul{margin:0 0 2em} und li.is-active a{underline} mit 0-2-1 bis 0-3-2 — die Regeln hier
   müssen sie per Spezifität schlagen, nicht nur per Reihenfolge. */
.woocommerce-account.logged-in .woocommerce-MyAccount-navigation ul { list-style: none; margin: 0; padding: 0; }
/* Item 62px inkl. 1px-Trennlinie (Figma strokeAlign INSIDE → Border in der Höhe enthalten) */
.woocommerce-account .woocommerce-MyAccount-navigation li.woocommerce-MyAccount-navigation-link {
	display: flex;
	box-sizing: border-box;
	height: 62px;
	margin: 0;
	padding: 0;
	border-bottom: 1px solid var(--wp--preset--color--grey-mid);
}
/* Woo unterstreicht is-active + :hover — im Design gibt es keine Unterstreichung */
.woocommerce-account .woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link a,
.woocommerce-account .woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link a:hover {
	text-decoration: none;
}
.woocommerce-account .woocommerce-MyAccount-navigation-link:not(.woocommerce-MyAccount-navigation-link--customer-logout) a {
	display: flex;
	align-items: center;
	width: 100%;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	line-height: 22px;
	letter-spacing: 0;
	color: var(--wp--preset--color--foreground);
	text-decoration: none;
}
.woocommerce-account .woocommerce-MyAccount-navigation-link:not(.woocommerce-MyAccount-navigation-link--customer-logout) a:hover,
.woocommerce-account .woocommerce-MyAccount-navigation-link:not(.woocommerce-MyAccount-navigation-link--customer-logout) a:focus-visible {
	color: var(--wp--preset--color--primary);
}
.woocommerce-account .woocommerce-MyAccount-navigation li.woocommerce-MyAccount-navigation-link.is-active { border-bottom-color: var(--wp--preset--color--primary); }
.woocommerce-account .woocommerce-MyAccount-navigation li.woocommerce-MyAccount-navigation-link.is-active a { color: var(--wp--preset--color--primary); }
/* Letzte Textzeile ohne Trennlinie (Render schlägt JSON, Spec §Fallen); das letzte li ist
   der Abmelden-Button, das vorletzte die letzte Textzeile → beide ohne Linie. */
.woocommerce-account .woocommerce-MyAccount-navigation li.woocommerce-MyAccount-navigation-link:nth-last-child(-n+2) { border-bottom: 0; }
/* Abmelden = Button, Entscheid (b) Secondary — Optik/States adoptieren .zo-btn (COMPONENTS).
   Hier nur Platzierung: volle Spaltenbreite, 24px Abstand zur Liste (Course-Variante 482−458). */
.woocommerce-account .woocommerce-MyAccount-navigation li.woocommerce-MyAccount-navigation-link--customer-logout {
	height: auto;
	padding: 0;
	margin-top: var(--wp--preset--spacing--40);
}
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a { width: 100%; }

/* --------------------------------------------------------------
   Woo-Tabellen: Smallscreen-Stacking neutralisieren (#179)
   woocommerce-smallscreen.css (<769px) stapelt shop_table_responsive zu
   Blöcken (tr/td display:block, data-title-::before, Zebra-BG,
   td text-align:right!important). Das Figma 6184:3086 sieht stattdessen
   Overflow-Scroll + Fade vor (COMPONENTS §Table). Spezifität: die doppelte
   Klasse .shop_table.shop_table_responsive schlägt Woos Regeln; nur
   text-align braucht !important gegen Woos !important (Whitelist).
   E-Mails unberührt: Woo-Mails inlinen email-styles.php (Klassen td/.order-totals),
   kein shop_table, kein Frontend-CSS — belegt #179.
   -------------------------------------------------------------- */
.woocommerce table.shop_table.shop_table_responsive thead { display: table-header-group; }
.woocommerce table.shop_table.shop_table_responsive tbody th { display: table-cell; }
.woocommerce table.shop_table.shop_table_responsive tr { display: table-row; }
.woocommerce table.shop_table.shop_table_responsive tr td {
	display: table-cell;
	text-align: inherit !important;    /* Woo: right!important bzw. left!important (order-actions) */
}
.woocommerce table.shop_table.shop_table_responsive tr td::before { content: none; }
.woocommerce table.shop_table.shop_table_responsive tr:nth-child(2n) td { background: transparent; }

/* --------------------------------------------------------------
   Woo-Bestellbestaetigung /checkout/order-received/ (#315)
   The totals + downloads tables adopt the .zo-table skin (COMPONENTS
   §Table); this section holds only what the skin has no rules for.
   tfoot: only these tables have one (subtotal/total/tax rows) — it
   continues the data-row look (1px border, no top; weights come from
   the skin's th/td rules).
   Alignment: Woo right-aligns the totals column and centers/right-
   aligns the downloads cells (tr > :first/:last-child = (0,2,3),
   printed after the theme stylesheet) — !important is the cheapest
   deterministic override. Everything start-aligned like the approved
   account-orders table (#179): consistency over per-case elegance.
   Address boxes: Woo draws 1px border + radius + 16px padding on the
   billing box; shipping is the identical neighbour block and behaves
   the same (issue names billing only — flagged in the issue comment).
   Doubled wrapper class = (0,2,0) beats Woo's (0,1,0) load-order-free.
   Additional information: gateway notices (e.g. Mollie payment
   instructions) render as classic .woocommerce-info boxes — icon,
   border, background off, plain text per issue order.
   -------------------------------------------------------------- */
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table tfoot { border: 0; }
.wc-block-order-confirmation-totals table.wc-block-order-confirmation-totals__table tfoot tr {
	border: 1px solid var(--wp--preset--color--grey-mid);
	border-top: 0;
	background: transparent;
}
.wc-block-order-confirmation-totals__table th,
.wc-block-order-confirmation-totals__table td,
.wc-block-order-confirmation-downloads__table th,
.wc-block-order-confirmation-downloads__table td { text-align: start !important; }
.wp-block-woocommerce-order-confirmation-billing-address.wc-block-order-confirmation-billing-address,
.wp-block-woocommerce-order-confirmation-shipping-address.wc-block-order-confirmation-shipping-address {
	border: 0;
	border-radius: 0;
	padding: 0;
}
.wc-block-order-confirmation-additional-information .woocommerce-info,
.wc-block-order-confirmation-additional-information .woocommerce-message {
	border: 0;
	padding: 0;
	background: transparent;
	color: inherit;
}
.wc-block-order-confirmation-additional-information .woocommerce-info::before,
.wc-block-order-confirmation-additional-information .woocommerce-message::before { display: none; }

/* --------------------------------------------------------------
   Woo Konto-Bestelldetail (view-order Endpoint) (#319)
   Same visual decisions as the order confirmation (#315), applied to
   the classic view-order page in the account area: the gateway
   instruction (e.g. Mollie "Zahlung durch ... erfolgt") renders as
   section.woocommerce-order-details.woocommerce-info — icon, blue top
   border and background off, plain text. The doubled base class is not
   needed here: the existing combo (0,2,0) already beats Woo's
   .woocommerce-info (0,1,0) load-order-free.
   Billing address box: woocommerce.css draws border+radius+padding on
   .woocommerce .woocommerce-customer-details address (0,2,1) and
   woocommerce-blocktheme.css re-draws it at (0,3,1) — the doubled
   class below yields (0,4,1) and wins load-order-free.
   -------------------------------------------------------------- */
.woocommerce-order-details.woocommerce-info {
	border: 0;
	padding: 0;
	background: transparent;
	color: inherit;
}
.woocommerce-order-details.woocommerce-info::before { display: none; }
.woocommerce-page .woocommerce-customer-details.woocommerce-customer-details address {
	border: 0;
	border-radius: 0;
	padding: 0;
}

/* --------------------------------------------------------------
   Woo Konto-Adressen (edit-address Endpoint) (#324)
   The edit/add links float right per woocommerce.css
   .woocommerce-account .addresses .title .edit (0,3,0) — the element
   step below yields (0,3,1) and wins load-order-free; blocktheme's
   display:block keeps each link on its own line, now left-aligned.
   The <address> element renders italic by browser default; the
   addresses page shows stored data, not a citation-style block.
   -------------------------------------------------------------- */
.woocommerce-account .addresses .title a.edit { float: none; }
.woocommerce-account .woocommerce-Address address { font-style: normal; }

/* --------------------------------------------------------------
   Woo Cart/Checkout-App auf der Grid-Foundation (#186)
   templates/page-cart.html + page-checkout.html rendern post-content
   alignfull im Flow — Rail-Konsumenten im Seiteninhalt (zo-container-
   Gruppen, Teaser-Bleed) rechnen gegen die Viewport-Breite wie auf allen
   anderen Seiten. Die Woo-App-Ansichten (gefüllter Warenkorb, Checkout-
   Formular) tragen kein eigenes Rail-Markup und würden sonst volle Breite
   laufen → hier das kanonische .zo-container-Rezept (KEIN Legacy-Alias
   --zo-rail-*, #128 Phase 3). Die Empty-Cart-Ansicht bleibt bewusst volle
   Breite: ihre Kinder sind Redaktions-Inhalt und railen selbst.
   -------------------------------------------------------------- */
.wp-block-woocommerce-cart > .wp-block-woocommerce-filled-cart-block,
.wp-block-woocommerce-checkout,
.woocommerce-order-pay .wp-block-post-content > .woocommerce {
	width: min(100% - 2 * var(--zo-grid-margin), var(--zo-content-max));
	margin-inline: auto;
}

/* --------------------------------------------------------------
   Woo "pay for order" endpoint /checkout/order-pay/<id>/ (#392)
   Mollie sends cancelled payments here (option "pending", default):
   the customer picks another payment method and pays again. The
   endpoint renders inside page-checkout.html, but its content is the
   classic shortcode output (form-pay.php: shop_table + #payment), or
   the login/e-mail verification gate — no checkout block. The wrapper
   joins the rail rule above; the shop_table already carries the
   .zo-table skin (COMPONENTS §Table).
   #payment: woocommerce.css draws a tinted, rounded box, a second
   tinted description box with a speech-bubble arrow and 13px labels.
   The checkout block it stands in for has none of that — box,
   tint and arrow off, labels and descriptions take the checkout
   block's computed radio-label type (14/500, lh 1.4, ls .16px, ink;
   measured on /checkout/ 2026-10-01). Woo selectors sit at (1,1,0)/
   (1,1,1)/(1,2,1); the body element step wins load-order-free. The rail
   rule needs max-width none: woocommerce-blocktheme.css caps
   .woocommerce-checkout main .woocommerce at 1000px.
   Follow-up (#392, Philipp): #payment spans half the rail from LG
   (= 6 of 12 grid columns), like the checkout block's form column;
   each method row is a flex row so the radio centres on the label
   text and Mollie's logo (floated right in the label, 24px, taller
   than the text line) sits centred at the row end instead of
   pushing the text off the radio. Woo's clearfix pseudos would turn
   into flex items, so they are switched off.
   Follow-up 2 (#392, Philipp): radios, h3 "Zahlart auswählen" (inc/
   woocommerce.php) and the consent checkbox take the table's cell
   inset (16 / LG 24, COMPONENTS §Table) so they line up with the
   table text, not the rail edge; the payment rule line keeps the
   column edges like the table's row lines. Only the method list and
   the consent rows are capped at half the rail — the pay button floats
   to the right end of the full content width. Spacing above / below
   the h3 = the text flow's text->heading gap and the h3 step.
   States: radio = native control like the checkout block's.
   Breakpoints: <LG full rail width, inset 16; LG+ half rail, inset 24.
   -------------------------------------------------------------- */
body.woocommerce-order-pay .wp-block-post-content > .woocommerce { max-width: none; } /* blocktheme caps main .woocommerce at 1000 (0,2,1) */
body.woocommerce-order-pay #payment {
	background: transparent;
	border-radius: 0;
}
body.woocommerce-order-pay #order_review { --zo-order-pay-inset: 16px; } /* = table cell inline padding */
body.woocommerce-order-pay #order_review > h3.zo-order-pay__heading {
	margin: var(--zo-text-gap) 0 0;
	padding-inline: var(--zo-order-pay-inset);
}
body.woocommerce-order-pay #payment ul.payment_methods {
	box-sizing: border-box;            /* half-rail cap includes the inset */
	margin-top: var(--zo-h3-pb);
	padding: 0 var(--zo-order-pay-inset) 16px;
	border-bottom-color: var(--wp--preset--color--grey-mid);
}
body.woocommerce-order-pay #payment div.form-row > :not(#place_order) {
	box-sizing: border-box;
	padding-inline: var(--zo-order-pay-inset);
}
body.woocommerce-order-pay #payment ul.payment_methods li,
body.woocommerce-order-pay #payment div.payment_box {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 1.4;
	letter-spacing: 0.16px;
	color: var(--wp--preset--color--foreground);
}
/* The label would otherwise take the BASE form-label type (12/500 grey). */
body.woocommerce-order-pay #payment ul.payment_methods li label {
	font: inherit;
	letter-spacing: inherit;
	color: inherit;
}
body.woocommerce-order-pay #payment ul.payment_methods li:not(.woocommerce-notice) {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}
body.woocommerce-order-pay #payment ul.payment_methods li:not(.woocommerce-notice)::before,
body.woocommerce-order-pay #payment ul.payment_methods li:not(.woocommerce-notice)::after { display: none; }
body.woocommerce-order-pay #payment ul.payment_methods li + li { margin-top: 8px; } /* logos would touch */
body.woocommerce-order-pay #payment ul.payment_methods li input.input-radio { margin: 0 16px 0 0; }
body.woocommerce-order-pay #payment ul.payment_methods li label {
	display: flex;
	flex: 1;
	align-items: center;
	min-height: 24px;                  /* = Mollie logo height */
	margin: 0;                         /* BASE label margin-bottom would decentre the row */
}
body.woocommerce-order-pay #payment ul.payment_methods li label img {
	float: none;
	margin: 0 0 0 auto;
}
body.woocommerce-order-pay #payment div.payment_box {
	flex-basis: 100%;
	margin: 0 0 8px;
	padding: 0 0 0 29px;               /* = label start: 13px native radio + 16px gap */
	border-radius: 0;
	background: transparent;
}
body.woocommerce-order-pay #payment div.payment_box::before { display: none; }
body.woocommerce-order-pay #payment div.form-row { padding: 16px 0 0; }
@media (min-width: 1024px) {
	body.woocommerce-order-pay #order_review { --zo-order-pay-inset: 24px; }
	body.woocommerce-order-pay #payment ul.payment_methods,
	body.woocommerce-order-pay #payment div.form-row > :not(#place_order) { max-width: calc(50% - var(--zo-grid-gutter) / 2); } /* 6 of 12 columns */
}

/* --------------------------------------------------------------
   FluentForms: EINE Formular-Optik im ganzen Theme (#214)
   Jedes Formular im Theme kommt aus FluentForms — Kontakt/freie Seiten (Block
   `fluentfom/guten-block`), Fuß-Newsletter, Warteliste, Reflexionsbögen. Der
   Plugin-Eigenstil ist serverseitig abgeschaltet (inc/fluentform.php: Wrapper
   verliert `ff-default`, Submit bekommt `ff_btn_no_style`), damit auf
   FluentForms-Feldern unverändert die Form-Controls-Basis aus #170 greift
   (BASE, Figma „Input field" 5551:21846) und der Submit die .zo-btn-Komponente
   adoptiert (COMPONENTS, Figma 4510:32604). Vorher lag beides dreimal kopiert in
   Footer, Warteliste und Reflexionsbox.
   Hier steht deshalb nur noch zweierlei: FluentForms' ungescoptes eigenes CSS
   (`fluent-forms-public.css` + der ungescopte Rest von `fluentform-public-default.css`,
   beide laden VOR dem Theme) zurechtrücken — und das Formular-LAYOUT, für das es
   keinen Figma-Frame gibt.
   Herkunft der Layout-Zahlen (Philipp #214: Optik aus den vorhandenen Vorlagen
   ableiten, ein Formular-Frame existiert in Figma nicht): Feld-Abstand 16 ist der
   Wert, den Footer-Newsletter, Warteliste und Reflexionsbox schon benutzen;
   Label→Feld 0 und Feld→Hinweis 8 sind dagegen belegt (docs/figma-specs/form-controls.md).
   Ohne Figma-Beleg und deshalb hier benannt: Ankreuzfeld/Radio haben KEIN Figma-Set
   (#170) — sie bleiben native Controls und werden nur über `accent-color` auf den
   Primary-Ton gezogen.
   States: Feld aus BASE (hover/focus/error/disabled), Knopf aus .zo-btn.
   Breakpoints: n/a — eine Größe auf allen Viewports (die Sets haben keine Size-Achse).
   -------------------------------------------------------------- */
.fluentform,
.fluentform * { box-sizing: border-box; }

.fluentform {
	/* FluentForms' eigene Variablen auf zo-Werte ziehen: `danger` färbt Fehlerrahmen,
	   Fehlertext und Pflicht-Sternchen, `input-select-height` steuert die Select-Höhe
	   (die Plugin-Regel dafür ist spezifischer als die Basis). Variablen am Formular
	   statt an :root — so gewinnt der nähere Knoten, unabhängig von der Ladereihenfolge. */
	--fluentform-danger: var(--wp--custom--color--red-500);
	--fluentform-input-select-height: 48px;
	margin: 0;
}

/* Feld-Abstand: 16 zwischen den Gruppen, senkrecht gestapelt. Das Fieldset trägt vom
   Plugin ein Inline-`margin/padding/border: 0 !important` — Abstände laufen deshalb
   über `gap`, nicht über Margins. Legende und versteckte Felder sind keine Flex-Items. */
.frm-fluent-form fieldset {
	display: flex;
	flex-direction: column;
	gap: 16px;
}
.fluentform .ff-el-group { margin: 0; }
/* Nebeneinanderliegende Felder (z. B. Vorname/Name) im selben Rhythmus wie gestapelte. */
.frm-fluent-form .ff-t-container { gap: 16px; }

/* Label sitzt bündig auf der Feld-Oberkante (Gap 0, Spec §Soll-Maße); Typo kommt aus der
   Basis. Plugin-Default wäre inline-block + 5px Abstand. */
.fluentform .ff-el-input--label {
	display: block;
	margin: 0;
}
.fluentform .ff-el-input--label label { display: block; }

/* Placeholder ist ink, nicht grau — das Plugin setzt hier spezifischer als die Basis. */
.fluentform .ff-el-form-control::placeholder {
	color: var(--wp--preset--color--foreground);
	opacity: 1;
}

/* Gesperrte/nur-lesbare Felder ohne Plugin-Graufläche: die Basis zeigt den Zustand über
   Unterkante und Textfarbe (Spec §Zustandsfarben). */
.fluentform .ff-el-form-control:disabled,
.fluentform .ff-el-form-control[readonly]:not(.flatpickr-input) {
	background-color: transparent;
}
/* Nur hier `!important`: die Plugin-Regel für nur-lesbare Felder setzt ihre Graufläche selbst
   mit !important (`fluent-forms-public.css`), Spezifität reicht dagegen nicht. */
.fluentform .ff-el-group .ff-read-only {
	background-color: transparent !important;
}

/* Fehlertext unterm Feld: Abstand 8 wie Hinweistext (Spec §Soll-Maße), Typo aus der Basis.
   Das Plugin setzt 4px auf `.text-danger` — gleiche Spezifität, hier gewinnt die Reihenfolge. */
.fluentform .ff-el-is-error .error { margin-top: 8px; }

/* Ankreuzfeld/Radio: kein Figma-Set (#170) → nativ lassen, nur einfärben. Die Zeile daneben
   ist ein <label> und trägt damit die Label-Typo der Basis (12/500 grey) — dieselbe Optik
   wie die Einwilligungszeile im Fuß-Newsletter. */
.fluentform .ff-el-form-check { accent-color: var(--wp--preset--color--primary); }
.fluentform .ff-el-form-check-label { display: inline-flex; align-items: center; gap: 8px; }
.fluentform .ff-el-form-check span.ff_span { margin-left: 0; }
.fluentform .ff-el-form-check-label .ff-el-form-check-input { top: 0; }

/* Success message after sending (#338): ZO box instead of the plugin frame. There is no
   Figma frame for form feedback — every value is taken from the Alert Box component
   (Figma 4750:18950, docs/figma-specs/alert-box.md, variant without flag/image/link):
   accent-lilac surface, padding 24 (SM 24/16), title display 700 24/32 (MD 20/26,
   SM 18/24), title->text 4, text 500 16/22 (MD/SM 14/20), foreground ink.
   Forms inside coloured components (footer newsletter band, reflection box, waitlist
   modal) keep the plain text line of #184 — a lilac box on lilac/orange would vanish.
   States/interaction: n/a (static status text). */
.ff-message-success {
	margin: 24px 0 0;
	padding: 24px;
	border: 0;
	box-shadow: none;
	background: var(--wp--preset--color--accent-lilac);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
	line-height: 22px;
	color: var(--wp--preset--color--foreground);
}
.ff-message-success :is(h2, h3, h4) {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--font-size--24);
	font-weight: 700;
	line-height: 32px;
	color: var(--wp--preset--color--foreground);
}
.ff-message-success p { margin: 4px 0 0; }
.ff-message-success > p:first-child { margin-top: 0; }
@media (max-width: 1023px) {
	.ff-message-success { font-size: var(--wp--preset--font-size--small); line-height: 20px; }
	.ff-message-success :is(h2, h3, h4) { font-size: var(--wp--custom--font-size--20); line-height: 26px; }
}
@media (max-width: 639px) {
	.ff-message-success { padding: 24px 16px; }
	.ff-message-success :is(h2, h3, h4) { font-size: var(--wp--custom--font-size--18); line-height: 24px; }
}
.zo-footer .ff-message-success,
.zo-reflection .ff-message-success,
.zo-waitlist .ff-message-success {
	padding: 0;
	background: transparent;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 22px;
}

/* ============================================================
   Utility: Externe Links  (a.zo-external)  — Issue #321
   Frontend JS (assets/js/zo-external-links.js) tags every http(s) link to a
   foreign host with .zo-external (+ .zo-external--media for icon/image-only
   links) and sets target=_blank — nav, footer, content and server-rendered
   blocks alike, no markup changes. Marker = the theme arrow icon rotated
   -45deg (up-right), per the issue text; there is NO Figma frame for this,
   so size/gap are em-based defaults derived from the running text.
   Links that already carry a trailing arrow do NOT get a second one:
   - every .wp-block-button__link arrow ::after (action link #188, text-image
     CTA, teaser CTA) just rotates,
   - event-list CTA (#176), page-header event (#129) and the Card Expert link
     (team cards may link out, #371 — its ::after is the stretched click area)
     rotate their inline SVG.
   Icon-only links (.zo-external--media: partner logos, social buttons) keep
   their visual untouched — new tab only.
   ============================================================ */
a.zo-external:not(.zo-external--media):not(.wp-block-button__link):not(.zo-pgh__event):not(.zo-eventlist__cta):not(.zo-card-expert__link)::after {
	content: "";
	display: inline-block;
	flex: 0 0 auto;
	width: 0.8em;
	height: 0.8em;
	margin-left: 0.15em;
	background: currentColor;
	-webkit-mask: var(--zo-icon-arrow-right) center / contain no-repeat;
	        mask: var(--zo-icon-arrow-right) center / contain no-repeat;
	transform: rotate(-45deg);
}

/* Buttons/action links with an own arrow ::after: rotate it (45deg = leaving). */
.wp-block-button__link.zo-external::after { transform: rotate(-45deg); }

/* Components with an inline SVG arrow: rotate that one. */
a.zo-external.zo-eventlist__cta svg,
a.zo-external.zo-pgh__event .zo-pgh__event-arrow svg,
a.zo-external.zo-card-expert__link svg { transform: rotate(-45deg); }
