/**
 * Milchland — Komponenten-Ebene
 *
 * Regel: Diese Datei enthält KEINE Werte, nur Verweise auf die Tokens aus
 * theme.json (--wp--preset--* und --wp--custom--*). Wer hier eine Farbe oder
 * eine Schriftgröße als Literal findet, hat einen Fehler gefunden.
 *
 * Ausnahmen, bewusst und begründet:
 *   - (seit 017 keine mehr:) Overlays und Schatten sind `color-mix()` auf `black`/`white`
 *     mit Deckkraft — gleiche berechnete Farbe wie das fruehere rgba(), aber am Token
 *   - Struktur-Maße ohne CD-Bedeutung (1px Rahmen, 44px Badge)
 *   - die .ml-spec-Klassen der Kundenübersicht: Signalgelb, das bewusst NICHT
 *     zur Palette gehört, damit Hilfstext nie wie Seiteninhalt aussieht
 */

/* ---------------------------------------------------------------- Basis -- */

/*
 * Kuhflecken. EIN Motiv fuer alle Stellen: die gelieferte
 * `Kuhflecken-Muster.png` (5589 x 6000, 14 Flecken), nachgezeichnet als SVG
 * mit 14 Pfaden im selben viewBox (002). Liegt im Theme, damit nichts auf
 * eine Instanz-URL zeigt.
 *
 * Eingesetzt wird sie als MASKE, nie als Hintergrundbild. Eine Maske traegt
 * nur die Form; die Farbe kommt aus einem Token und passt sich der Flaeche
 * an, auf der sie liegt. Das erspart das `filter: invert(1)` des Entwurfs
 * und damit eine Datei je Farbe.
 */
:root {
	--ml-kuhflecken: url("../img/kuhflecken-muster.svg");
}

/*
 * Schrift zurueckholen. GeneratePress setzt in main.min.css
 *
 *   body, button, input, select, textarea { font-family: -apple-system, ... }
 *
 * Die Regel hat dieselbe Spezifitaet wie das body-font-family aus theme.json,
 * steht im Head aber SPAETER — und gewinnt damit. Ohne diese Zeilen rendert
 * nur das in Nunito, wo eine Komponente die Familie ausdruecklich setzt;
 * Fliesstext, Kartentexte, Zahlenleiste und alle Core-Bloecke fallen auf die
 * Systemschrift zurueck. Gemessen: 46 von 554 Textelementen in Nunito.
 *
 * Bewusst derselbe Selektor, nicht !important: gleiche Spezifitaet, spaetere
 * Quelle. Wer die Reihenfolge der Stylesheets aendert, muss das hier pruefen.
 */
body,
button,
input,
select,
textarea {
	font-family: var(--wp--preset--font-family--nunito);
	/* Bau 44 (0.67.0): dieselbe Ursache fuer die Zeilenhoehe - GeneratePress setzt
	   hier 1.5 und laedt spaeter als theme.json. Jetzt gilt das Token (1.6). */
	line-height: var(--wp--custom--line-height--body);
}

/*
 * Fliesstextgroesse zurueckholen (0.22.0, 23.09.) — derselbe Mechanismus wie
 * die Schrift darueber und die Ueberschriften darunter (A1, A6).
 *
 * `theme.json` weist `body` die Groesse `font-size--body` zu, GeneratePress'
 * main.min.css setzt `body, button, input, select, textarea { font-size: 17px }`
 * und steht spaeter. Gemessen: 17 px bei 390, 768, 1024 UND 1440 — das Token
 * hat nie gewirkt, auch nicht in seiner alten Fassung (15 -> 19 px).
 *
 * Nur `body`, nicht die Formularelemente: Knoepfe und Felder behalten ihre
 * eigene Groesse. Wert aus dem Token, Kurve 16 px bei 390 -> 18 px bei 1440,
 * Anschlag 18 (Entwurf: Fliesstext 18 px).
 *
 * `html body` statt `body`: Im Editor haengt GeneratePress ein eigenes
 * `body { font-size: 17px }` HINTER diese Datei (gemessen: 17 px im Canvas,
 * obwohl das Frontend schon 18 zeigte). (0,0,2) schlaegt (0,0,1) in beiden
 * Reihenfolgen — dasselbe Mittel wie `body h1` bei den Ueberschriften.
 */
html body {
	font-size: var(--wp--preset--font-size--body);
}

/*
 * Ueberschriften zurueckholen — dasselbe Muster wie die Schrift darueber.
 *
 * `theme.json` weist seine Element-Styles als `global-styles-inline-css` zu
 * (Position 17 im Head). GeneratePress' `main.min.css` steht an 18 und setzt
 * dieselben Typselektoren mit eigenen Werten: 42 / 35 / 29 / 24 / 20 / 17 px,
 * Schnitt 400. Gleiche Spezifitaet (0,0,1), spaetere Quelle — GeneratePress
 * gewinnt.
 *
 * Deshalb `body h1` statt `h1`: (0,0,2) schlaegt (0,0,1) unabhaengig von der
 * Reihenfolge. Die schlichte Variante haette im Frontend gereicht — diese
 * Datei liegt dort an 22 —, aber NICHT im Editor: dort haengt GeneratePress
 * seine Stile hinter unsere, und ein blosses `h2` verlor wieder gegen 35 px.
 * Gemessen in beiden Umgebungen, nicht angenommen.
 *
 * Zwei Typselektoren bleiben schwaecher als jede Komponentenklasse: die 22 px
 * von `.ml-card__title` (0,1,0) gewinnen weiterhin gegen `body h3`.
 *
 * Betroffen ist NICHT nur die Groesse: Schnitt, Zeilenhoehe und Laufweite aus
 * `theme.json` werden ebenso ueberschrieben. Ein getipptes H2 stand in 35 px
 * bei Schnitt 400 statt in 68 px bei 900.
 *
 * Das trifft jede Ueberschrift, die der Redakteur selbst tippt — genau den
 * Fall, den die Bauvorlage unter „Fliesstext ohne Element" zusichert. In den
 * Elementen fiel es nicht auf, weil deren Komponentenklassen ihre Groesse
 * ohnehin selbst setzen.
 *
 * Die Werte sind hier NICHT zweitgepflegt: sie verweisen auf dieselben Tokens
 * wie `theme.json`. Wer dort etwas aendert, aendert es auch hier.
 */
body h1 {
	font-size: var(--wp--preset--font-size--titel-xl);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--hero);
	letter-spacing: var(--wp--custom--tracking--display);
}

body h2 {
	font-size: var(--wp--preset--font-size--titel-l);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--section);
	letter-spacing: var(--wp--custom--tracking--display);
}

body h3 {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 800;
	line-height: var(--wp--custom--line-height--card);
	letter-spacing: var(--wp--custom--tracking--display);
}

/*
 * H4 bis H6 kennt `theme.json` nicht — sie behielten deshalb die Werte von
 * GeneratePress (24 / 20 / 17). Mit H3 auf seinen Token-Wert von 22 px waere
 * H4 groesser als H3 gewesen. Sie bekommen hier nur eine Groesse aus dem
 * vorhandenen Bestand, damit die Reihe faellt; Schnitt und Zeilenhoehe bleiben
 * unangetastet, weil es fuer sie keine Entwurfsvorgabe gibt.
 */
/*
 * 023 Nachtrag 2 (Marc 17.10.): direkt eingefuegte Ueberschriften (A14, Block
 * `core/heading`, Klasse `wp-block-heading`) seitenweit in den Rollen der Elemente:
 * H2 wie der erste Titel auf /qualitaetsfoerderung/ (`ml-titel-section-bild`, 48 bei
 * 1440, einfarbig), H3 wie `ml-titel-section-halb` (34). Vorher 68 / 22 aus `body h2/h3`.
 * Element-Titel tragen `wp-block-heading` nicht und bleiben unberuehrt. Spezifitaet
 * (0,2,2): schlaegt `body h2` und die Editor-Regeln von GeneratePress; die Regel fuer
 * eine H2 in mehrspaltigen Spalten (A5, 0,5,1) bleibt staerker.
 * WooCommerce-Seiten ausgenommen: dort gilt die Shop-Entscheidung (B4, H2 in
 * `ml-titel-section-halb`) — gemessen 023: „Neu im Shop" auf Warenkorb/Kasse bliebe sonst
 * nicht bei 34.
 */
:is(body:not(.woocommerce-page), .editor-styles-wrapper) h2.wp-block-heading {
	font-size: var(--wp--preset--font-size--titel-seite);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--pagehead);
	letter-spacing: var(--wp--custom--tracking--display);
}

:is(body:not(.woocommerce-page), .editor-styles-wrapper) h3.wp-block-heading {
	font-size: var(--wp--preset--font-size--titel-halb);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--pagehead);
	letter-spacing: var(--wp--custom--tracking--display);
}

body h4 { font-size: var(--wp--custom--ui--size-l); }
body h5 { font-size: var(--wp--custom--ui--size); }
body h6 { font-size: var(--wp--preset--font-size--card); }


/*
 * Kicker. Seit dem Entwurf „Magazin August 26" nicht mehr in Versalien und
 * ohne Sperrung: eine Stufe groesser, dafuer ruhiger. Die Plaketten (.ml-pill)
 * behalten Versalien und Sperrung — der Unterschied ist gewollt und
 * unterscheidet die beiden Sorten voneinander.
 */
.ml-label {
	display: block;
	font-family: var(--wp--preset--font-family--nunito);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	line-height: 1.25;
	/*
	 * Schwarz mit Deckkraft statt `gray-dark` — dasselbe Muster wie beim
	 * FAQ-Antworttext (0.82): die Deckkraft haelt den Text automatisch im
	 * Verhaeltnis zur Flaeche, auf der er steht, und kostet kein neues Token.
	 *
	 * Anlass: Der Kicker ist 16 px bei Schnitt 700 und damit normaler Text
	 * nach WCAG (gross ist erst ab 18,66 px fett) — gefordert sind 4,5 : 1.
	 * `gray-dark` #7F7F7F schaffte das auf keiner hellen Flaeche:
	 *
	 *   auf Weiss 4,004 · auf `gray-bg` 3,638 · auf Tint 3,561
	 *
	 * Mit 0.62: 6,193 · 5,990 · 5,985. Das Minimum waere 0.55 (4,742 · 4,638
	 * · 4,639) — zu knapp, 0.62 gibt Polster. Effektiv rgb(97,97,97) auf
	 * Weiss, der Kicker bleibt damit deutlich heller als der Fließtext
	 * (#222, 15,910) und tritt weiter zurueck.
	 *
	 * ACHTUNG: Die Deckkraft vererbt sich an jede Regel, die nur `color`
	 * setzt. Wer unten eine eigene Kickerfarbe vergibt, MUSS `opacity: 1`
	 * dazuschreiben — sonst wird sie still abgedunkelt.
	 */
	color: var(--wp--preset--color--black);
	opacity: 0.62;
	margin: 0 0 1.25rem;
}

/* Zweite Stufe: Spaltenkoepfe der Fusszeile, Kopf der Aufklappliste. */
.ml-label-s {
	font-size: var(--wp--preset--font-size--label-s);
}

.ml-section-dark .ml-label {
	color: var(--wp--preset--color--gray-light);
	/* Eigene Farbe — Deckkraft der Grundregel zuruecknehmen. */
	opacity: 1;
}

.ml-display {
	font-family: var(--wp--preset--font-family--nunito);
	font-weight: 900;
	letter-spacing: var(--wp--custom--tracking--display);
	line-height: var(--wp--custom--line-height--section);
	margin: 0;
	/*
	 * Bauauftrag 2, Punkt 15 (10.10.): lange Komposita trennen, wie seit jeher
	 * bei `.ml-card__title`. Ohne das sprengt ein Wort wie
	 * "Milchviehhaltungsbetriebe" bei 390 px die Seitenbreite und erzeugt
	 * waagerechtes Scrollen. `anywhere` bricht notfalls ohne Trennstrich,
	 * `hyphens: auto` setzt ihn, wo die Silbentrennung greift.
	 */
	overflow-wrap: anywhere;
	hyphens: auto;
}

/* ------------------------------------------------------------- Sektion -- */

.ml-section {
	padding-block: var(--wp--preset--spacing--sektion);
	padding-inline: var(--wp--preset--spacing--rand);
}

.ml-section > * {
	/* Dieselbe Breite wie wideSize aus theme.json — bewusst dieselbe Quelle. */
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

/*
 * Ausnahme fuer den Hero: Bild und Verlauf liegen absolut und sollen die volle
 * Fensterbreite fuellen. Ohne diese Regel greift die 1360er Begrenzung von
 * oben auch auf sie — das Bild stand dann zentriert mit schwarzen Raendern.
 * Dasselbe fuer die Kuhflecken-Huellen von S16 und S22 (002): ihre Lage
 * gilt zur Sektion, nicht zur 1360er Spur.
 */
.ml-hero > .ml-hero__wechsel,
.ml-hero > .ml-hero__media,
.ml-hero > .ml-hero-scrim,
.ml-hero > .ml-hero-scrim-seite,
.ml-section > .ml-ansprech__flecken,
.ml-section > .ml-videodok__flecken {
	max-width: none;
	margin-inline: 0;
}

/*
 * Viel Luft davor, keine dahinter. Die Erklärung gehört zu dem Block, der
 * DARUNTER folgt — nicht zu dem darüber. Ohne diese Asymmetrie liest man sie
 * als Nachtrag zum vorherigen Element.
 */
.ml-section-tight {
	padding-block: calc(var(--wp--preset--spacing--sektion) + 1rem) 0;
}

/*
 * Das erklärte Element rückt dicht unter seine Erklärung — aber nicht zu dicht:
 * der Zeiger an der Unterkante braucht Platz, sonst steht er im Kicker.
 */
.ml-section-tight + .ml-section {
	padding-top: var(--wp--preset--spacing--band);
}

.ml-section-dark {
	background-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

.ml-section-dark :is(h1, h2, h3, h4, p) {
	color: var(--wp--preset--color--white);
}

/*
 * Kuhflecken hinter dem Highlight-Mosaik, oben rechts, angeschnitten.
 *
 * Nur dort, wo tatsaechlich ein Mosaik steht — `:has()` statt einer zweiten
 * Marker-Klasse: Das Mosaik ist das einzige Element, das diesen Untergrund
 * traegt, und eine Klasse, die nur an einer Stelle steht, ist keine.
 */
.ml-section-dark:has(.ml-mosaic) {
	position: relative;
	overflow: hidden;
}

.ml-section-dark:has(.ml-mosaic)::before {
	content: "";
	position: absolute;
	top: -100px;
	inset-inline-end: -200px;
	width: 720px;
	height: 720px;
	background-color: var(--wp--preset--color--white);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: contain;
	-webkit-mask-size: contain;
	mask-repeat: no-repeat;
	-webkit-mask-repeat: no-repeat;
	opacity: 0.08;
	pointer-events: none;
}

/* Der Inhalt liegt ueber dem Untergrund. */
.ml-section-dark:has(.ml-mosaic) > * {
	position: relative;
	z-index: 1;
}

/*
 * Zahlenleiste (Element 17): blau als Vorgabe, schwarz als Variante.
 * Die Marker-Klasse ml-stats-section haengt die Regel im Editor-Access-Profil
 * an genau diese Sektion — sonst bekaeme jede Sektion das Auswahlfeld.
 */


.ml-stats-section {
	/* Im Entwurf ein schmales Band von 48 px, kein volles Sektionsmass. */
	padding-block: var(--wp--preset--spacing--band);
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

.ml-stats-section[data-variante="schwarz"] {
	background-color: var(--wp--preset--color--black);
}

.ml-stats-section :is(h1, h2, h3, h4, p, span) {
	color: var(--wp--preset--color--white);
}

/*
 * Umschaltbare Sektionsflaeche fuer Split-Banner, FAQ, Slider und Galerie.
 * Ebenfalls per Marker-Klasse begrenzt: nur wo ml-flaeche steht, gibt es die
 * Auswahl.
 *
 * `hell` hatte bis 0.43.2 keine Regel - als Vorgabe, die "nichts aendert".
 * Das trug nur so lange, wie die Flaeche hinter dem Abschnitt ueberall
 * dieselbe ist. Am 02.10. die Elternkette nachgelaufen, bis zur ersten
 * deckenden Flaeche:
 *
 *   Seite:   section -> .entry-content -> .inside-article          = #FFFFFF
 *   Eintrag: section -> .dynamic-entry-content -> article
 *            .dynamic-content-template -> main#main -> #primary ->
 *            #content -> #page (alle transparent) -> body          = #F7F8F9
 *
 * Die Vorlage der Einzelansicht rendert kein `inside-article`, deshalb faellt
 * die Kette dort bis zum body durch. Derselbe Eintrag im Auswahlfeld des
 * Redakteurs ergab damit zwei Flaechen, 1,0633 auseinander - derselbe Schritt,
 * fuer den 0.43.1 eine Linie gebaut hat.
 *
 * Darum traegt `hell` seine Flaeche jetzt selbst: Weiss, die Grundflaeche des
 * Entwurfs. Ein Abschnitt OHNE Attribut gilt mit, sonst laufen Vorgabe und
 * Leerwert auseinander.
 *
 * Kein Abschnitt braucht die Flaeche seines Elternelements: am 02.10. ueber
 * alle Beitragstypen gezaehlt liegt keine `ml-flaeche` in einer anderen, keine
 * traegt ein Hintergrundbild, und die dunklen Baender (`ml-section-dark`,
 * `ml-videodok`, `ml-stats-section`, `ml-hero`) tragen die Marker-Klasse nicht.
 *
 * Spezifitaet (0,2,0) - wie `tint` und `grau`. Die Achse `data-kasten` liegt
 * bei (0,3,0) und bleibt davon unberuehrt (Regel 12 der Bauvorlage); sie setzt
 * ohnehin dieselbe Flaeche.
 */
.ml-flaeche:not([data-variante]),
.ml-flaeche[data-variante="hell"] {
	background-color: var(--wp--preset--color--white);
}

.ml-flaeche[data-variante="tint"] {
	background-color: var(--wp--preset--color--blue-tint);
}

.ml-flaeche[data-variante="grau"] {
	background-color: var(--wp--preset--color--gray-bg);
}

/*
 * Dunkel kam mit dem Element „Sektion" dazu: ein leeres Farbband, in das
 * Bausteine gelegt werden. Fläche und Schrift wechseln gemeinsam — sonst
 * steht schwarzer Text auf schwarzem Grund, und das faellt erst im
 * Barrierefreiheits-Check auf.
 */
.ml-flaeche[data-variante="schwarz"] {
	background-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

.ml-flaeche[data-variante="schwarz"] :is(h1, h2, h3, h4, p, li, blockquote, span) {
	color: var(--wp--preset--color--white);
}

.ml-flaeche[data-variante="schwarz"] a {
	color: var(--wp--preset--color--blue-tint);
}

/*
 * Bau 40 (0.65.0): Textlinks auf getoenter und grauer Flaeche in blue-dark.
 * Ein Link im Fliesstext nimmt sonst die Linkfarbe von GeneratePress (#1E73BE,
 * nicht das Token `blue`) und erreicht als 18-px-Text auf getoent 4,3937, auf grau
 * 4,3708 - unter 4,5. blue-dark ist dieselbe Entscheidung wie bei Hinweisbox-Link,
 * Reiter und Plakette. Nur Links OHNE eigene Klasse in Absatz und Listenpunkt:
 * Buttons, Karten- und Dokumentlinks tragen Klassen und behalten ihre Farbe.
 * Hover und Fokus bleiben bei GeneratePress (#222 im Hover), sonst ginge die
 * Rueckmeldung beim Ueberfahren verloren.
 */
.ml-flaeche:is([data-variante="tint"], [data-variante="grau"]) :is(p, li) a:not([class]):not(:hover, :focus) {
	color: var(--wp--preset--color--blue-dark);
}


/*
 * Im Sektionskopf entscheidet die Stelle ueber die Groesse, nicht der Rang.
 *
 * Die Ueberschrift eines Sektionskopfs ist mal H2, mal H1 — auf der Startseite
 * traegt sie die H1, weil der Hero rangfrei ist. Aussehen soll sie in beiden
 * Faellen gleich. Diese Regel setzt sie deshalb unabhaengig vom Typselektor
 * auf `titel-l`; die Klassenkette (0,2,0) schlaegt die Basisregeln oben (0,0,1).
 *
 * Bis 0.16.2 stand hier die Begruendung, GeneratePress schlage `theme.json` —
 * das stimmt, ist aber seit 0.17.0 in der Basis geloest (siehe oben) und nicht
 * mehr die Aufgabe dieser Regel. Der Hero braucht sie ohnehin nicht:
 * .ml-hero__title bringt seine Groesse selbst mit.
 */
.ml-sectionhead .ml-display,
.ml-section__head .ml-display {
	font-size: var(--wp--preset--font-size--titel-l);
	/* Titelrolle section: 680 px Feld (Vorgabe Titelsatz, 0.23.0; vorher 760). Groesse bleibt titel-l = 68 px, entschieden 22.09. */
	max-width: var(--wp--custom--titel--feld--section);
}
/*
 * Ausnahme Startseite: breiteres Titelfeld.
 *
 * claude/vorgabe-titelsatz.md schreibt fuer Sektionstitel 680 px vor. Der Titel
 * der Startseite hat 67 Zeichen und stuende damit vierzeilig; gemessen am 22.09.
 * passen bei 680 px nur 50 Zeichen in drei Zeilen. Entschieden am 22.09.:
 * die Startseite bekommt 860 px, die Vorgabe bleibt fuer alle Unterseiten gueltig.
 *
 * Marker-Klasse statt `body.home`, weil die Editor-Leinwand keine home-Klasse
 * traegt - sonst saehe der Redakteur beim Tippen einen anderen Umbruch als im
 * Frontend. Die Klasse sitzt am .ml-sectionhead von S04 auf Seite 191.
 */
.ml-sectionhead-breit .ml-display {
	max-width: var(--wp--custom--sektionskopf--titelbreite-start);
}

.ml-sectionhead.ml-sectionhead-breit {
	--ml-kopf-titelfeld: var(--wp--custom--sektionskopf--titelbreite-start);
}


.ml-section__head {
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--gap-l);
	margin-bottom: var(--wp--preset--spacing--band);
}

/* --------------------------------------------------------------- Karte -- */

/*
 * Keine Mindesthoehe (0.40.0, 30.09.): Das Raster zieht die Karten einer Zeile
 * ohnehin auf dieselbe Hoehe - .ml-card ist direktes Rasterkind, align-items
 * steht auf normal (= stretch). Seit die Buehne der Themenkarte auf 16:10 steht,
 * bestimmte `min-height: 480px` die Karte an 12 von 12 Messpunkten; die Vorlage
 * setzt keine. Dass `.ml-cardslider__item > .ml-card` die Zeile seit jeher mit
 * `min-height: 0` aushebeln musste, war der zweite Hinweis auf einen Behelf.
 */
.ml-card {
	position: relative;
	display: flex;
	flex-direction: column;
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
	transition: border-color 0.2s ease, transform 0.2s ease;
}

/*
 * Flaechenfarbe je Karte. Im Entwurf wechseln sich weiss, blau getoent und
 * grau ab — das ist Teil des Rhythmus, nicht Zufall. Als Attribut, damit der
 * Redakteur es spaeter ueber ein Auswahlfeld umstellen kann.
 */
.ml-card[data-variante="tint"] { background-color: var(--wp--preset--color--blue-tint); }
.ml-card[data-variante="grau"] { background-color: var(--wp--preset--color--gray-bg); }

/* Bildbereich ist die Buehne fuer die Kategorie-Pill. */
/*
 * Bildbuehne. 5:4 gilt fuer News-, Material- und Sliderkarten.
 * Die Themenkarte weicht ab (16:10, Entwurf "Uebersichtsseite Qualitaet",
 * Zeile 211) und traegt dafuer seit 0.39.0 den eigenen Marker
 * `ml-card-thema`. BEWUSST ein positiver Marker und kein
 * `:not(.ml-card-news)`: eine Negationsregel wuerde jede Karte treffen,
 * die den Gegenmarker nur noch nicht traegt (Stolperstelle 35).
 */
.ml-card__stage {
	position: relative;
	aspect-ratio: 5 / 4;
	overflow: hidden;
	background-color: var(--wp--preset--color--black);
}

.ml-card-thema .ml-card__stage {
	aspect-ratio: 16 / 10;
}

.ml-card__stage .ml-pill {
	position: absolute;
	top: 14px;
	left: 14px;
	z-index: 2;
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--black);
}

/* Sanfte Vergroesserung beim Ueberfahren — im Entwurf .photo-card. */
.ml-card__stage img {
	transition: transform 0.6s ease;
}

.ml-card:has(.ml-card__link:hover) .ml-card__stage img {
	transform: scale(1.03);
}

/*
 * Kopfzeile im Kartenkoerper. Bis 0.14.0 stand hier links der Nummernkreis.
 * Der Entwurf „Magazin August 26" hat ihn fallen lassen — die Karten sind
 * keine numerierte Folge, und die Nummer stand in Konkurrenz zur Plakette
 * auf dem Bild. Geblieben ist der Pfeil, rechtsbuendig.
 */
.ml-card__row {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	margin-bottom: 14px;
}

/*
 * height: auto ist Pflicht, nicht Kosmetik. Die Attribute width/height am
 * <img> wirken als Präsentationsattribute; ohne diese Regel gewinnt die
 * Pixelhöhe gegen aspect-ratio. Im Frontend fängt GeneratePress das mit einer
 * globalen Regel ab, im Block-Editor nicht — dort war die Karte 1706 px hoch.
 */
.ml-card__media {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ml-card__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	align-items: stretch;
	padding: 1.5rem;
}

.ml-card__title {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--card);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0 0 10px;
	/* Lange Komposita wie „Unterrichtsmaterial" sprengen sonst die Karte. */
	overflow-wrap: anywhere;
	hyphens: auto;
}

.ml-card__text {
	font-size: var(--wp--preset--font-size--card);
	line-height: var(--wp--custom--line-height--card-body);
	color: var(--wp--preset--color--black);
	opacity: 0.78;
	margin: 0;
}

.ml-card__meta {
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--custom--text--gedaempft);
	margin: 0;
}

/*
 * Container-Link ohne Container-<a>.
 * Der Linktext ist die Überschrift — Screenreader lesen "Titel, Link", nicht
 * den gesamten Kartentext. Die Klickfläche wird per ::after aufgezogen.
 * Text bleibt markierbar, der Fokusring liegt auf der ganzen Karte.
 */
.ml-card__link {
	color: inherit;
	text-decoration: none;
}

.ml-card__link::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.ml-card:has(.ml-card__link:hover) {
	border-color: var(--wp--preset--color--blue);
}

.ml-card:has(.ml-card__link:hover) .ml-card__title {
	color: var(--wp--preset--color--blue);
}

.ml-card:has(.ml-card__link:focus-visible) {
	outline-style: solid;
	outline-width: var(--wp--custom--focus--width);
	outline-color: var(--ml-focus, var(--wp--preset--color--blue));
	outline-offset: var(--wp--custom--focus--offset);
}

/*
 * Der einzige `outline: none` dieser Datei, und bewusst. Der Link der Karte
 * ist ein gestreckter Link (sein ::after deckt die ganze Karte); ein Rahmen
 * um den Link selbst umschlaesse nur die Titelzeile. Den Rahmen traegt
 * deshalb die Karte (Regel oben, `:has()`), der Link gibt seinen ab.
 * Spezifitaet (0,3,0) gegen die globale Fokusregel (0,2,1).
 */
.ml-card .ml-card__link:focus-visible {
	outline: none;
}

/*
 * News-Karte (Element 09). Weicht bewusst von der Themenkarte ab: engerer
 * Koerper, Kategorie als umrandete Pill statt auf dem Bild, Datum unten
 * angeschlagen. Werte aus dem Magazin-Entwurf.
 */
/*
 * Gleiche Höhe für alle Karten einer Reihe. Das Raster dehnt den Rahmen des
 * Loopers (.gb-loop-item), nicht die Karte darin - ohne diese Zeile wächst bei
 * einem dreizeiligen Titel nur die betroffene Karte. Gemessen am 22.09.:
 * eine Karte 424 px, die drei anderen 400 px, alle vier Rahmen 424 px.
 */
.ml-card-news {
	height: 100%;
}

.ml-card-news .ml-card__body {
	padding: 22px;
}

.ml-card-news .ml-card__title {
	font-size: 19px;
	font-weight: 800;
	line-height: 1.25;
	letter-spacing: -0.01em;
	margin: 0 0 14px;
}

/*
 * Abstand Plakette → Titel. Im Entwurf sitzt die Plakette in einer eigenen
 * Zeile mit Abstand nach unten; beim Bau ist der Wrapper entfallen und der
 * Abstand mit ihm. Gemessen am 22.09.: Unterkante Plakette zu Oberkante Titel
 * war 0 px.
 */
.ml-card-news .ml-pill {
	margin-bottom: var(--wp--custom--abstand--label);
}

.ml-card-news .ml-pill {
	background-color: var(--wp--preset--color--gray-bg);
	/*
	 * 0.36.0: `blue-dark` statt `blue`. Die Plakette traegt ihre graue Flaeche
	 * selbst, unabhaengig von der Sektion: Blau 11 px / 700 auf `gray-bg` lag
	 * bei 4,3419 : 1 (unter 4,5), `blue-dark` dort bei 6,4571 : 1.
	 */
	color: var(--wp--preset--color--blue-dark);
	border: 1px solid var(--wp--preset--color--rule);
	padding: 4px 10px;
	font-size: 11px;
	letter-spacing: 0.08em;
}

.ml-card-news .ml-card__meta {
	margin-top: auto;
}

/* --------------------------------------------------------- Auszeichner -- */

.ml-pill {
	display: inline-block;
	align-self: flex-start;
	padding: 5px 12px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: var(--wp--custom--tracking--pill);
	line-height: 1.2;
	text-transform: uppercase;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--blue-tint);
	/* 0.36.0: `blue-dark` — Blau auf `blue-tint` laege bei 4,3647 : 1. */
	color: var(--wp--preset--color--blue-dark);
}

.ml-pill-ink {
	background-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

/* Plakette auf blauem Grund - im Entwurf die Rezept-Empfehlung. */
.ml-pill-blau {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/*
 * .ml-badge-num ist mit 0.15.0 entfallen — siehe .ml-card__row. Die Klasse
 * steht in keinem Pattern mehr; die Regel ist mit entfernt, damit sie nicht
 * als Angebot missverstanden wird.
 */

/*
 * Bildnachweis. Liegt im Bild unten rechts, ueber dem Motiv. Setzt einen
 * positionierten Vorfahren voraus — .ml-card__stage und .ml-hero bringen
 * ihn mit. Nicht anklickbar, damit er die Kartenflaeche nicht zerschneidet.
 */
.ml-credit {
	position: absolute;
	right: 10px;
	bottom: 8px;
	z-index: 2;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.3;
	color: color-mix(in srgb, var(--wp--preset--color--white) 90%, transparent);
	text-shadow: 0 1px 4px color-mix(in srgb, var(--wp--preset--color--black) 60%, transparent);
	pointer-events: none;
}

.ml-arrow {
	flex: none;
	width: 20px;
	height: 20px;
	color: var(--wp--preset--color--black);
	transition: transform 0.2s ease;
}

.ml-arrow svg {
	display: block;
	width: 100%;
	height: 100%;
}

/*
 * Nachtrag vom 11.10. (Befund zu Pruefauftrag 46, Liste 8, Punkt 3).
 *
 * Punkt 5 hat die ganze Karte klickbar gemacht, sobald im Titel ein Link steht. Steht
 * keiner, blieb der Pfeil trotzdem stehen und versprach ein Ziel, das es nicht gibt.
 * Dieselbe Bedingung wie die Klickflaeche selbst, nur umgekehrt gelesen.
 */
.ml-card:not(:has(.ml-card__title a)) .ml-arrow {
	display: none;
}

.ml-card:has(.ml-card__link:hover) .ml-arrow {
	transform: translate(3px, -3px);
	color: var(--wp--preset--color--blue);
}

/* -------------------------------------------------------------- Button -- */

.ml-btn {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 14px 24px;
	font-family: var(--wp--preset--font-family--nunito);
	font-size: 14px;
	font-weight: 700;
	line-height: 1;
	text-decoration: none;
	border: 1.5px solid transparent;
	border-radius: var(--wp--custom--radius--pill);
	/* Beschriftungen brechen nicht um — im Entwurf steht jeder Button einzeilig. */
	white-space: nowrap;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.ml-btn-blue {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

.ml-btn-blue:hover,
.ml-btn-blue:focus-visible {
	background-color: var(--wp--preset--color--blue-dark);
	color: var(--wp--preset--color--white);
}

.ml-btn-ink {
	background-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

.ml-btn-ink:hover,
.ml-btn-ink:focus-visible {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

.ml-btn-outline {
	background-color: transparent;
	border-color: currentColor;
	color: inherit;
}

/* Weisse Umrissvariante — nur auf dunklem Grund, im Entwurf im Hero. */
.ml-btn-outline-white {
	background-color: transparent;
	border-color: color-mix(in srgb, var(--wp--preset--color--white) 70%, transparent);
	color: var(--wp--preset--color--white);
}

.ml-btn-outline-white:hover,
.ml-btn-outline-white:focus-visible {
	background-color: var(--wp--preset--color--white);
	border-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--black);
}

.ml-btn__icon {
	display: inline-flex;
	flex: none;
}

.ml-btn__icon svg {
	display: block;
}

.ml-btn-outline:hover,
.ml-btn-outline:focus-visible {
	background-color: var(--wp--preset--color--blue);
	border-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------- Element 1: Mosaik -- */

/*
 * 12-Spalten-Raster mit benannten Bereichen. Der Redakteur ordnet nichts an —
 * er tauscht Bild, Kicker und Titel. Die Anordnung ist Teil des Layouts.
 */
/*
 * WICHTIG: Jeder Bereichsname in grid-template-areas muss ein RECHTECK bilden.
 * Ein L- oder T-förmiger Bereich macht die gesamte Deklaration ungültig — CSS
 * verwirft sie dann stillschweigend, und alle Kacheln landen übereinander in
 * derselben Zelle. Das ist genau der Fehler, den dieser Prototyp einmal hatte.
 *
 * Aufteilung nach „Magazin August 26": links eine Aufmacherkachel über zwei
 * Reihen, rechts daneben zwei mal zwei gestapelte Kacheln, unten eine über die
 * volle Breite.
 *
 * Bis 0.15.0 stand hier eine andere Aufteilung (7/5 statt 5/4/3) und sechs
 * gleiche Bildkacheln. Die Bauvorlage hat immer sechs VERSCHIEDENE Sorten
 * beschrieben — gebaut war das nie, und die Delta-Notiz vom 15.09. hat den
 * Unterschied als „deckungsgleich" durchgewunken, weil sie nur die sechs
 * Rasterflächen gezählt hat, nicht deren Zuschnitt und Inhalt.
 *
 * Die Reihenhöhe ist bewusst NICHT fest. Ein festes `grid-auto-rows` schneidet
 * Textkacheln ab, sobald eine Kachel mehr trägt als Titel und Plakette; die
 * Höhe kommt jetzt aus den Kacheln der rechten Spalten, die Aufmacherkachel
 * spannt sich darüber.
 */
.ml-mosaic {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	gap: var(--wp--preset--spacing--gap-l);
	grid-template-areas:
		"a a a a a b b b b c c c"
		"a a a a a d d d d e e e"
		"f f f f f f f f f f f f";
}

/*
 * Grundkachel: helle Karte auf schwarzem Grund. Die Sorte steht als eigene
 * Klasse am selben Element (ml-mosaic__tile-gross usw.) — die Platzierung
 * bleibt an :nth-child, weil die Anordnung laut Bauvorlage fest ist und die
 * Blöcke ohnehin gegen Verschieben gesperrt sind.
 */
.ml-mosaic__tile {
	position: relative;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--black);
}

.ml-mosaic__tile:nth-child(1) { grid-area: a; }
.ml-mosaic__tile:nth-child(2) { grid-area: b; }
.ml-mosaic__tile:nth-child(3) { grid-area: c; }
.ml-mosaic__tile:nth-child(4) { grid-area: d; }
.ml-mosaic__tile:nth-child(5) { grid-area: e; }
.ml-mosaic__tile:nth-child(6) { grid-area: f; }

/*
 * Die dunkle Sektion färbt Überschriften, Absätze und Kicker weiß (0,2,0). Die
 * Kacheln sind helle Karten und müssen das zurückholen — über echt höhere
 * Spezifität, nicht über die Quellreihenfolge. Sonst steht schwarze Schrift
 * auf weißem Grund nur so lange richtig, wie niemand die Datei umsortiert.
 */
.ml-section-dark .ml-mosaic__tile :is(h2, h3, h4, p) {
	color: var(--wp--preset--color--black);
}

/*
 * Der Kachel-Text ist gedaempft (Token `gedaempft`, Schwarz 60 % auf Weiss =
 * 5,7418 : 1). Die Regel oben setzt ihn mit (0,2,1) auf Schwarz zurueck, die
 * Grundregel `.ml-mosaic__text` (0,1,0) griff dadurch nie. Dieser Selektor
 * (0,4,0) holt nur den Kachel-Text zurueck; Titel, Kicker und Link behalten
 * die Rueckgabe. Die blaue Aussage-Kachel bleibt ausgenommen: auf Blau gilt
 * nur volles Weiss.
 */
.ml-section-dark .ml-mosaic__tile:not(.ml-mosaic__tile-aussage) .ml-mosaic__text {
	color: var(--wp--custom--text--gedaempft);
}

/*
 * Die Kachel ist WEISS (`.ml-mosaic__tile` setzt `background-color: white`),
 * obwohl der Selektor die dunkle Sektion nennt. Markenblau steht hier also
 * auf Weiss: 4,907 — ueber AA, ohne Polster. Am 21.09. bewusst so belassen,
 * der blaue Akzent auf der hellen Kachel ist gewollt.
 */
.ml-section-dark .ml-mosaic__tile .ml-label {
	color: var(--wp--preset--color--blue);
	opacity: 1;
}

/* ------------------------------------------- Mosaik: gemeinsame Teile -- */

.ml-mosaic__stage {
	position: relative;
	overflow: hidden;
	aspect-ratio: 5 / 4;
	background-color: var(--wp--preset--color--black);
}

/*
 * Hier ist `height: 100%` richtig und `height: auto` falsch: das Bild soll die
 * Bühne füllen, nicht sein Eigenmaß behalten. Die Präsentationsattribute
 * width/height am <img> werden damit sicher geschlagen — auch im Editor-Rahmen,
 * der den Reset von GeneratePress nicht erbt.
 */
.ml-mosaic__stage img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ml-mosaic__stage .ml-pill {
	position: absolute;
	top: 16px;
	left: 16px;
	z-index: 2;
}

.ml-mosaic__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: 22px;
}

.ml-mosaic__title {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--card);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0 0 12px;
}

.ml-mosaic__title a {
	color: inherit;
	text-decoration: none;
}

.ml-mosaic__text {
	font-size: var(--wp--preset--font-size--card);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--custom--text--gedaempft);
	margin: 0 0 20px;
}

/* Der Textlink sitzt am Fuß der Kachel, egal wie lang der Text darüber ist. */
.ml-mosaic__link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	align-self: flex-start;
	margin-top: auto;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 700;
	color: var(--wp--preset--color--blue);
	text-decoration: none;
}

.ml-mosaic__link svg {
	flex: none;
	width: 12px;
	height: 12px;
}

.ml-mosaic__tile:has(a:focus-visible) {
	outline-style: solid;
	outline-width: var(--wp--custom--focus--width);
	outline-color: var(--ml-focus, var(--wp--preset--color--white));
	outline-offset: var(--wp--custom--focus--offset);
}

/* ------------------------------------------ a · Aufmacher mit Kennzahlen -- */

.ml-mosaic__tile-gross .ml-mosaic__stage { aspect-ratio: 16 / 9; }
.ml-mosaic__tile-gross .ml-mosaic__body  { padding: 32px; }

.ml-mosaic__tile-gross .ml-mosaic__title {
	font-size: 34px;
	line-height: 1.1;
	margin-bottom: 14px;
}

.ml-mosaic__tile-gross .ml-mosaic__text {
	font-size: var(--wp--custom--ui--size);
	margin-bottom: 24px;
}

/* Fuß: zwei Kennzahlen links, Button rechts, über einer Trennlinie. */
.ml-mosaic__foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 28px;
	margin-top: auto;
	padding-top: 22px;
	border-top: 1px solid var(--wp--preset--color--rule);
}

.ml-mosaic__foot .ml-btn { margin-inline-start: auto; }

/*
 * Eigene Kennzahlen statt .ml-stat: die Zahlenleiste bringt 40 px und weiße
 * Schrift mit, beides steht auf einer hellen Kachel falsch.
 */
.ml-mosaic__kennzahl {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.ml-mosaic__kennzahl-num {
	font-size: 28px;
	font-weight: 900;
	line-height: 1;
	letter-spacing: var(--wp--custom--tracking--display);
}

.ml-mosaic__kennzahl-text {
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--custom--text--gedaempft);
}

/* --------------------------------------------------- b · Aussage (blau) -- */

.ml-mosaic__tile-aussage {
	min-height: 260px;
	padding: 32px;
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/*
 * Kuhflecken als Maske, nicht als Hintergrundbild: die Grafik trägt nur die
 * Form, die Farbe kommt aus dem Token. Damit entfällt das filter: invert(1)
 * des Entwurfs und die zweite Datei für die zweite Farbe.
 */
.ml-mosaic__tile-aussage::before {
	content: "";
	position: absolute;
	inset: 0;
	background-color: var(--wp--preset--color--white);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: auto 220%;
	-webkit-mask-size: auto 220%;
	mask-repeat: no-repeat;
	-webkit-mask-repeat: no-repeat;
	mask-position: right -40px top -60px;
	-webkit-mask-position: right -40px top -60px;
	opacity: 0.12;
	pointer-events: none;
}

.ml-mosaic__tile-aussage > * {
	position: relative;
	z-index: 1;
}

.ml-section-dark .ml-mosaic__tile-aussage .ml-label {
	/*
	 * Die Aussage-Kachel ist blau gefuellt — eigene Farbe, volle Deckkraft.
	 * 0.29.0: volles Weiss statt Weiss 0,8 (effektiv #CCE3F2, 3,7105 : 1).
	 * Weiss auf `blue` ergibt 4,9073 : 1, den Hoechstwert auf dieser Flaeche.
	 * Ein Kicker ist Beschriftung, kein Beiwerk — er wird nicht gedaempft.
	 */
	color: var(--wp--preset--color--white);
	opacity: 1;
}

.ml-mosaic__claim {
	margin: auto 0;
	font-size: 32px;
	font-weight: 900;
	line-height: var(--wp--custom--ui--claim-line-height);
	letter-spacing: var(--wp--custom--tracking--display);
}

.ml-section-dark .ml-mosaic__tile-aussage .ml-mosaic__link {
	margin-top: 24px;
	padding-bottom: 4px;
	font-size: 14px;
	color: var(--wp--preset--color--white);
	border-bottom: 2px solid var(--wp--preset--color--white);
}

/* ------------------------------------------------------- c · Medien -- */

.ml-mosaic__tile-medien .ml-mosaic__stage::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background-color: color-mix(in srgb, var(--wp--preset--color--black) 28%, transparent);
}

.ml-mosaic__play {
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background-color: color-mix(in srgb, var(--wp--preset--color--white) 92%, transparent);
	color: var(--wp--preset--color--black);
}

.ml-mosaic__play svg {
	width: 18px;
	height: 18px;
	margin-inline-start: 2px;
}

/* ---------------------------------------------------------- d · Text -- */

.ml-mosaic__tile-text .ml-mosaic__body { padding: 32px; }

.ml-mosaic__tile-text .ml-mosaic__title {
	font-size: 34px;
	line-height: 1.08;
}

/* -------------------------------------------------------- f · Breit -- */

.ml-mosaic__tile-breit {
	display: grid;
	grid-template-columns: 1.4fr 1fr;
	align-items: stretch;
	border: 1px solid var(--wp--preset--color--rule);
}

/* Bau 43 (E6): 560 sind die TEXTspalte des Entwurfs. Vorher schloss
   max-width das Polster ein - fuer Text blieben 480, der Titel brach um. */
.ml-mosaic__tile-breit .ml-mosaic__body {
	justify-content: center;
	max-width: calc(var(--wp--custom--mosaik--breit-text) + 2 * var(--wp--custom--mosaik--breit-polster));
	padding: var(--wp--custom--mosaik--breit-polster);
}

.ml-mosaic__tile-breit .ml-mosaic__title {
	font-size: 34px;
	line-height: 1.08;
	margin-bottom: 14px;
}

.ml-mosaic__tile-breit .ml-mosaic__text { margin-bottom: 24px; }

.ml-mosaic__tile-breit .ml-btn {
	align-self: flex-start;
	margin-top: 0;
}

/* Die Bühne folgt hier der Zellhöhe, nicht einem Seitenverhältnis. */
.ml-mosaic__tile-breit .ml-mosaic__stage {
	aspect-ratio: auto;
	min-height: 240px;
}

@media (max-width: 1024px) {
	.ml-mosaic {
		grid-template-areas:
			"a a a a a a a a a a a a"
			"b b b b b b c c c c c c"
			"d d d d d d e e e e e e"
			"f f f f f f f f f f f f";
	}

	.ml-mosaic__tile-gross .ml-mosaic__title,
	.ml-mosaic__tile-text .ml-mosaic__title,
	.ml-mosaic__tile-breit .ml-mosaic__title {
		font-size: 28px;
	}
}

@media (max-width: 700px) {
	.ml-mosaic {
		grid-template-columns: 1fr;
		grid-template-areas: "a" "b" "c" "d" "e" "f";
	}

	.ml-mosaic__tile-breit { grid-template-columns: 1fr; }
	.ml-mosaic__tile-breit .ml-mosaic__body { max-width: none; }
	.ml-mosaic__tile-gross .ml-mosaic__body,
	.ml-mosaic__tile-text .ml-mosaic__body { padding: 24px; }
}

/* ---------------------------------------------- Element 2 + 3: Raster -- */

.ml-grid {
	display: grid;
	gap: var(--wp--preset--spacing--gap-s);
	grid-template-columns: repeat(4, 1fr);
}

/* Die News-Reihe steht im Entwurf einen Tick luftiger. */
.ml-grid-news {
	gap: var(--wp--preset--spacing--gap-l);
}

/*
 * S04 Themenkarten: 24px statt 20px (Entwurf Übersichtsseite Qualitaet,
 * gemessen 01.10.). Positiver Marker statt `.ml-grid` pauschal - sonst
 * traefe es auch S18 Material-Raster. `spacing.gap-s` bleibt unberuehrt,
 * es sitzt an mehr Stellen als dieser.
 */
.ml-grid:has(> .ml-card-thema) {
	gap: var(--wp--preset--spacing--gap-l);
}

/* Spaltenzahl als Variante — Auswahlfeld am Raster-Block. */
.ml-grid[data-variante="3"] { grid-template-columns: repeat(3, 1fr); }
.ml-grid[data-variante="2"] { grid-template-columns: repeat(2, 1fr); }

/*
 * Die Variantenregel oben liegt bei (0,2,0) und schlaegt eine schlichte
 * .ml-grid-Regel (0,1,0) auch innerhalb einer Media Query. Ohne den
 * Zusatz [data-variante] blieb ein dreispaltiges Raster bis 390px
 * dreispaltig - gemessen 3 x 102,7px. Aufgefallen ist es erst, als mit
 * der Seite Qualitaetsfoerderung zum ersten Mal data-variante="3"
 * eingesetzt wurde; die Startseite faehrt den Vorgabewert 4 und trifft
 * keine Variantenregel.
 */
@media (max-width: 1024px) {
	.ml-grid,
	.ml-grid[data-variante] { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
	.ml-grid,
	.ml-grid[data-variante] { grid-template-columns: 1fr; }
}

/* ------------------------------------------------- Reduzierte Bewegung -- */

@media (prefers-reduced-motion: reduce) {
	.ml-card,
	.ml-arrow,
	.ml-btn {
		transition: none;
	}
}

/* ------------------------------------------------------------- Header -- */

/*
 * Sticky kommt vom Site-Header-Block: das Attribut data-gb-is-sticky lädt
 * dist/sticky-element.js, und das Runtime setzt beim Scrollen die Klasse
 * .gb-is-sticky auf das Element.
 *
 * Shrink ist deshalb KEIN Plugin-Feature, sondern CSS auf dieser Klasse —
 * kein eigenes JavaScript nötig.
 *
 * Steuerung über data-Attribute am Block:
 *   data-gb-sticky-header-type   always | scroll-up | past-threshold
 *   data-gb-sticky-animation     slide | none
 *   data-gb-sticky-speed         Millisekunden (Vorgabe 200)
 *   data-gb-sticky-threshold     z. B. 500px
 *   data-gb-sticky-breakpoint    Media-Query, z. B. "min-width: 769px"
 */

.ml-header {
	background-color: var(--wp--preset--color--white);
	border-bottom: 1px solid var(--wp--preset--color--rule);
	width: 100%;

	/*
	 * BEFUND 18.09.: Das Mega-Menue-Panel lag im RUHENDEN Zustand hinter dem
	 * Hero-Slider. Nicht wegen seines eigenen z-index - der steht auf 9999 -,
	 * sondern weil GB Pro dem Menuepunkt einen eigenen Stapelkontext gibt
	 * (.menu-item-has-gb-mega-menu{position:relative} plus
	 * .gb-menu-item:focus-within{z-index:1}). Innerhalb dieses Kontexts liegt
	 * das Panel oben, der KONTEXT selbst aber nur auf 1 - und der
	 * .ml-container des Hero traegt 2. Gemessen: an der Panelmitte lag
	 * div.ml-container [z 2] ueber dem Panel.
	 *
	 * Im Sticky-Zustand trat der Fehler nicht auf: dort setzt
	 * sticky-element.js die Kopfzeile auf position:fixed mit z-index 100 -
	 * genau der Stapelkontext, der ruhend fehlte. Deshalb hier derselbe Wert
	 * als Token, damit beide Zustaende dieselbe Ebene haben.
	 */
	position: relative;
	z-index: var(--wp--custom--ebene--kopfzeile);
}

.ml-header.gb-is-sticky {
	box-shadow: 0 2px 16px color-mix(in srgb, var(--wp--preset--color--black) 8%, transparent);
}

/*
 * Spur (003): Flaechen laufen vollbreit, der Inhalt steht in derselben
 * 1360er Spur wie die Sektionen. Der Innenabstand ist der Seitenrand, ab
 * 1473 px Fensterbreite der halbe Ueberstand ueber wideSize - so liegt die
 * Spur mittig, und darunter aendert sich nichts. Prozent beziehen sich auf
 * die Breite der Kopfzeile (= Fensterbreite ohne Scrollleiste).
 */
.ml-header__bar {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 1.5rem;
	height: 40px;
	padding-inline: max(var(--wp--preset--spacing--rand), calc((100% - var(--wp--style--global--wide-size)) / 2));
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	overflow: hidden;
	transition: height 0.25s ease;
}

.ml-header__bar a {
	color: inherit;
	text-decoration: none;
}

/* Beim Scrollen verschwindet die Top-Bar, der Hauptheader schrumpft. */
.ml-header.gb-is-sticky .ml-header__bar {
	height: 0;
}

.ml-header__main {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 2rem;
	height: var(--wp--custom--header--height);
	padding-inline: max(var(--wp--preset--spacing--rand), calc((100% - var(--wp--style--global--wide-size)) / 2));
	transition: height 0.25s ease;
}

.ml-header.gb-is-sticky .ml-header__main {
	height: var(--wp--custom--header--height-sticky);
}

/*
 * Seit 0.19.11 traegt die Kopfzeile das echte Bildzeichen statt des
 * Schriftzugs: das LVN-Siegel als Inline-SVG. Inline, damit weder eine
 * Attachment-ID noch eine Instanz-URL im Pattern steht - beides waere ein
 * Migrationsposten. Die Hoehe kommt aus dem Token, das seit dem ersten
 * Kopfzeilenbau dafuer bereitliegt und bisher keinen Abnehmer hatte.
 */
.ml-logo {
	display: flex;
	align-items: center;
	height: var(--wp--custom--header--logo);
	text-decoration: none;
	transform-origin: left center;
	transition: transform 0.25s ease;
}

/*
 * Das Logo kommt als Bild aus der Mediathek. Die Hoehe steht hier und nicht
 * am <img>, damit sie aus dem Token kommt - und sie MUSS gesetzt sein:
 * der Editor-Iframe erbt den Frontend-Reset nicht, ohne height schlagen die
 * Praesentationsattribute des Bildes durch (Regel 1 der Bauvorlage).
 */
.ml-logo img {
	display: block;
	height: 100%;
	width: auto;
}

.ml-header.gb-is-sticky .ml-logo {
	transform: scale(var(--wp--custom--header--logo-scale));
}

.ml-nav {
	display: flex;
	align-items: center;
	gap: 1.75rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ml-nav a {
	font-size: var(--wp--custom--header--nav);
	font-weight: 700;
	color: var(--wp--preset--color--black);
	text-decoration: none;
	transition: font-size 0.25s ease, color 0.2s ease;
}

.ml-header.gb-is-sticky .ml-nav a {
	font-size: var(--wp--custom--header--nav-sticky);
}

.ml-nav a:hover,
.ml-nav a:focus-visible {
	color: var(--wp--preset--color--blue);
}

/*
 * Die frühere Regel "@media (max-width: 768px) { .ml-nav { display: none } }"
 * ist mit 0.19.0 entfallen. Sie stammt aus der Zeit ohne Mobilnavigation und
 * haette das aufgeklappte Mobilmenue ausgeblendet: dort IST .ml-nav die Liste,
 * die sichtbar sein soll. Das Ein- und Ausblenden steuert jetzt der
 * Navigationsblock ueber .gb-menu-container--toggled.
 */

@media (prefers-reduced-motion: reduce) {
	.ml-header__bar,
	.ml-header__main,
	.ml-logo,
	.ml-nav a {
		transition: none;
	}
}

/* ==========================================================================
   Bauvorlage Inhaltselemente — Komponenten für die 17 Elemente
   Regel unverändert: keine Literale, nur Tokens aus theme.json.
   ========================================================================== */

/* ------------------------------------------------------------ Container -- */

/*
 * Ein Container pro Element, immer derselbe. Ohne ihn steht jedes Element
 * auf einer anderen Breite — der häufigste Grund für „alles ist verschoben".
 */
.ml-container {
	width: 100%;
	/* Dieselbe Breite wie wideSize aus theme.json — bewusst dieselbe Quelle. */
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

/*
 * Dieselben Breiten im Editor durchsetzen.
 *
 * GeneratePress setzt im Editor-Iframe `body .wp-block { max-width:
 * var(--content-width) }`. Die Regel ist mit (0,1,1) spezifischer als jede
 * Klassenregel dieser Datei, und `--content-width` ist im Iframe nicht
 * gesetzt — die Breitenbegrenzung landet also bei `none`, und JEDE eigene
 * Begrenzung innerhalb eines Blocks laeuft im Editor ins Leere.
 *
 * Gemessen bei 1905px Canvas: .ml-container 1793px statt 1360px. Der
 * Redakteur sah damit ein anderes Raster als die Seite.
 *
 * Und GenerateBlocks setzt im Editor zusaetzlich
 * `.editor-styles-wrapper .wp-block-generateblocks-element { max-width: unset }`
 * — (0,2,0), also gleichauf mit einer Klassenregel, aber spaeter geladen.
 * Deshalb steht hier die GB-Blockklasse mit im Selektor: (0,3,0) schlaegt
 * beide, ohne !important.
 *
 * Der Hero ist nicht betroffen: seine Ausnahme steht auf eigenen Klassen.
 */
.editor-styles-wrapper .wp-block-generateblocks-element.ml-container {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

.editor-styles-wrapper .wp-block-generateblocks-element.ml-spec {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

/*
 * Editor wie Website (014, 14.10.). Nur unter .editor-styles-wrapper - auf der
 * Website greift keine dieser Regeln.
 *
 * Sektionskopf: GenerateBlocks setzt im Editor
 * `.editor-styles-wrapper .wp-block-generateblocks-text:where(:not(h1...p)) { margin-bottom: 0 }`
 * (0,2,0, spaeter geladen) und nimmt dem Kicker die 14 px zum Titel
 * (Stolperstelle 104). (0,3,0) gibt sie zurueck.
 */
.editor-styles-wrapper .ml-sectionhead .ml-label {
	margin-bottom: var(--wp--custom--abstand--label);
}

/*
 * Kuhflecken S16/S22: der Editor setzt jeden Block auf `position: relative`
 * (.block-editor-block-list__block) - die Huelle stand im Fluss, 0 px hoch, in
 * der 1360er Spur. Wie auf der Website: absolut ueber der ganzen Sektion.
 */
.editor-styles-wrapper .ml-section > .ml-ansprech__flecken,
.editor-styles-wrapper .ml-section > .ml-videodok__flecken {
	position: absolute;
	inset: 0;
	max-width: none;
	margin: 0;
}

/*
 * Reiter: auf der Website traegt der <button> GeneratePress' `border: 1px solid
 * transparent` (main.min.css), im Editor fehlt die Regel - 51 statt 52 px.
 * Den unsichtbaren Rand als Innenabstand nachbilden (oben und seitlich; unten
 * steht der 3-px-Strich von core/tabs in beiden).
 */
.editor-styles-wrapper .ml-tabs [role="tab"] {
	padding: calc(0.75rem + 1px) calc(1.25rem + 1px) 0.75rem;
}

/*
 * 015 (14.10.) - Feinschliff.
 *
 * Teilen-Zeile der Material-Einzelansicht (GP-Element 626, Sektion `ml-teilen`):
 * die Sektion hatte keine Flaeche, sichtbar war die Seitenflaeche #F7F8F9.
 * Entwurf: weiss (Entscheidung 14.10.). Abstaende bleiben.
 */
.ml-section.ml-teilen {
	background-color: var(--wp--preset--color--white);
}

/*
 * Endet der Inhalt mit einem Kasten (S20/S21 `data-kasten="ja"`, weisse Sektion),
 * steht die Teilen-Zeile im Entwurf in DERSELBEN weissen Flaeche: 32 unter dem
 * Kasten (Kastenabstand) + 12 Innenabstand = 44 bis zum Inhalt, bei allen
 * Breiten (Entwurf Upcycling, gemessen Pruefung 015). Vorher stand hier der
 * volle Sektionsabstand (120 bei 1440) - seit die Flaeche weiss ist, eine
 * sichtbare Luecke. Unten bleibt der Sektionsabstand.
 */
.dynamic-entry-content:has(> [data-kasten="ja"]:last-child) + .ml-section.ml-teilen {
	padding-top: calc(var(--wp--custom--anleitung--kasten-abstand) + 0.75rem);
}

/*
 * S03: die Bildunterschrift ist ein <p> und trug unten GeneratePress'
 * Absatzrand (1.5em = 19,5 px) - Bild und Text standen unten nicht buendig.
 */
.ml-split__media-wrap > .ml-caption:last-child {
	margin-bottom: 0;
}

/*
 * Mobiles Mega-Menue: GB Pro gibt dem verankerten Panel `width: 100vw`
 * (.menu-item-has-gb-mega-menu .gb-overlay--anchored.gb-overlay--width-full,
 * 0,3,0). Im Mobilmenue steht es aber statisch im eingerueckten Menuepunkt
 * und ragte um dessen Einzug ueber den rechten Rand (Pruefung 005: 1066 bei
 * 1024, 802 bei 768, 411 bei 390). Dort: so breit wie der Menuepunkt.
 */
.gb-menu-container--mobile .menu-item-has-gb-mega-menu .gb-overlay--anchored.gb-overlay--width-full {
	width: 100%;
}

/* Farbvarianten der Sektion, als Block-Styles gesetzt */
.ml-section-tint {
	background-color: var(--wp--preset--color--blue-tint);
}

/* -------------------------------------------- Fliesstext auf Seitenebene -- */

/*
 * Absatz, Ueberschrift, Liste, Zitat und Bild bekommen KEIN eigenes Element.
 * Der Redakteur tippt sie direkt auf die Seite; damit sie dabei richtig
 * sitzen, regelt das diese Ebene.
 *
 * Warum hier und nicht in theme.json: GeneratePress ist ein klassisches
 * Theme. `the_content()` landet in `.entry-content`, und dieser Wrapper
 * traegt KEINE Layout-Klasse. Die Regeln, die WordPress aus
 * `settings.layout` erzeugt, greifen ausschliesslich unter
 * `.is-layout-constrained` — also nur INNERHALB von Bloecken mit
 * Layout-Unterstuetzung, nie auf der Seitenebene selbst. contentSize und
 * wideSize allein bewirken hier nichts; sie liefern nur die Werte, auf die
 * diese Regeln verweisen.
 *
 * Der Editor bekommt dieselben Regeln ueber `.is-root-container` — sonst
 * sieht der Redakteur im Editor eine andere Breite als auf der Seite.
 *
 * ZWEI DINGE SIND AUF WURZELEBENE AUSGENOMMEN:
 *   .ml-section        — die Sektion im Frontend
 *   .gb-is-root-block  — der Wrapper, den GenerateBlocks im EDITOR um jedes
 *                        Wurzelelement legt. Die Sektion liegt darin und ist
 *                        deshalb kein direktes Kind mehr. Ohne diese Ausnahme
 *                        kappt die Lesebreite jedes Element im Editor auf
 *                        680px — gemessen: der Hero war 680 statt 1905 breit.
 */

/*
 * Die linke Kante des Rasters. Sie ist der Seitenrand, solange das Fenster
 * schmaler ist als der Container — und danach der halbe Ueberschuss, weil der
 * Container dann zentriert steht.
 *
 * Genau dort beginnt auch der Inhalt INNERHALB der Elemente: .ml-container
 * sitzt an dieser Kante. Fliesstext auf Seitenebene mit `margin-inline: auto`
 * zu zentrieren, waere zwar symmetrisch, wuerde aber gegenueber jedem Element
 * einruecken — bei 1440px um 324px.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :not(.ml-section):not(.gb-is-root-block):not(.ml-block) {
	/*
	 * Lesebreite, aber nie ohne Seitenrand: auf schmalen Viewports gewinnt
	 * der zweite Term und laesst links und rechts Luft.
	 */
	max-width: min(
		var(--wp--style--global--content-size),
		calc(100% - 2 * var(--wp--preset--spacing--rand))
	);
	margin-inline: max(
		var(--wp--preset--spacing--rand),
		calc((100% - var(--wp--style--global--wide-size)) / 2)
	) auto;
}

/*
 * „Breite Breite" fluchtet mit den Sektionen — und ein Baustein auf oberster
 * Ebene verhaelt sich genauso. Er ist kein Fliesstext: Galerie und Slider
 * brauchen die volle Bahn, nicht die Lesebreite von 680px. Die eigene
 * Maximalbreite behaelt jeder Baustein trotzdem (.ml-note 680, .ml-video 960)
 * und sitzt damit linksbuendig in der Bahn — wie die Lesespalte innerhalb
 * einer Sektion.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(
		.alignwide,
		.ml-block,
		.is-style-ml-check,
		.is-style-ml-check-2,
		.is-style-ml-check-3
	):not(.ml-section):not(.gb-is-root-block) {
	/*
	 * GeneratePress zieht .alignwide mit negativem Rand aus dem Container
	 * heraus (`margin-left:-40px; width:calc(100% + 80px)`). Das gilt fuer
	 * sein eigenes Raster und muss hier zurueckgenommen werden, sonst steht
	 * der Block um 40px verschoben.
	 *
	 * Die beiden :not() im Selektor tragen nichts zur Auswahl bei — sie
	 * heben die Spezifitaet auf die der Lesebreiten-Regel. Ohne sie gewinnt
	 * dort 680px, und „breite Breite" waere wirkungslos.
	 */
	width: auto;
	/*
	 * Die Bahn ist die Obergrenze, nicht die Breite. Ein Baustein mit eigener
	 * Maximalbreite (Token baustein.schmal/lese/medien: .ml-note schmal,
	 * .ml-faq/.ml-tabs/.ml-slider lese, .ml-media/.ml-video medien) muss
	 * sie behalten — diese Regel liegt bei (0,2,0) und wuerde eine schlichte
	 * Komponentenregel (0,1,0) sonst ueberschreiben. Er meldet sie deshalb
	 * ueber --ml-eigenbreite an, statt sie hier zu verteidigen. Ohne Angabe
	 * gilt 100vw, also keine eigene Grenze — dann bleibt die Bahn.
	 */
	max-width: min(
		var(--ml-eigenbreite, 100vw),
		var(--wp--style--global--wide-size),
		calc(100% - 2 * var(--wp--preset--spacing--rand))
	);
	/*
	 * Der linke Rand muss hier mitstehen. .alignwide bekaeme ihn zwar noch aus
	 * der Lesebreiten-Regel, .ml-block ist dort aber ausgeschlossen — ohne diese
	 * Zeile stuende jeder Baustein auf oberster Ebene an der Fensterkante
	 * statt an der Rasterkante der Sektionen.
	 */
	margin-inline: max(
		var(--wp--preset--spacing--rand),
		calc((100% - var(--wp--style--global--wide-size)) / 2)
	) auto;
}

:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> .alignfull:not(.ml-section):not(.gb-is-root-block) {
	width: auto;
	max-width: none;
	margin-inline: 0;
}

/*
 * 040 (Marc 19.10.): Eine getippte Liste auf oberster Ebene steht mit ihrer Aussenkante auf der
 * Spaltenkante — die Lesebreiten-Regel oben setzt `margin-inline` und nimmt ihr damit den Einzug
 * von GeneratePress (`margin-left: 3em`). Punkte und Nummern hingen links ausserhalb der Spalte
 * (Wiki 1440: Liste und Text bei 380, Zeichen davor). Der Einzug kommt deshalb als Innenabstand
 * zurueck: 3 em wie in Spalten und Sektionen (54 bei 1440). `border-box` (GeneratePress) haelt die
 * rechte Kante auf der Spalte. Haekchen- und Nummernstile (`is-style-ml-*`) bringen ihren eigenen
 * Einzug mit und bleiben aussen vor.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(ul, ol):not([class*="is-style-ml-"]) {
	padding-inline-start: 3em;
}

/*
 * Die einzigen beiden Stellen in dieser Datei mit !important — und sie sind
 * unvermeidbar. Der Block-Editor erzeugt fuer seine Wurzel selbst:
 *
 *   .block-editor-block-list__layout.is-root-container
 *     > :where(:not(.alignleft):not(.alignright):not(.alignfull))
 *     { margin-left: auto !important; margin-right: auto !important; }
 *
 * Gegen ein !important hilft keine Spezifitaet. Ohne diese Regeln stuende
 * derselbe Absatz im Editor zentriert und im Frontend linksbuendig.
 */
.editor-styles-wrapper .is-root-container
	> :not(.gb-is-root-block):not(.alignfull) {
	margin-inline: max(
		var(--wp--preset--spacing--rand),
		calc((100% - var(--wp--style--global--wide-size)) / 2)
	) auto !important;
}

/* Der GB-Wrapper traegt die Sektion — er darf nichts begrenzen. */
.editor-styles-wrapper .is-root-container > .gb-is-root-block {
	max-width: none !important;
	margin-inline: 0 !important;
}

/*
 * Ein Baustein auf oberster Ebene steckt im Editor in genau diesem Wrapper und
 * ist damit KEIN Wurzelkind mehr — die Regel oben erreicht ihn nicht. Er
 * bekommt die Bahn deshalb hier, eine Ebene tiefer. Die GB-Blockklasse steht
 * mit im Selektor, weil GenerateBlocks im Editor
 * `.wp-block-generateblocks-element { max-width: unset }` setzt (0,2,0) und
 * eine reine Klassenregel damit gleichauf laege.
 *
 * NACHTRAG 16.09.: Ein Baustein muss kein `generateblocks/element` sein.
 * B04 · Bild-Slider ist ein Karussell und traegt im Editor `gb-carousel`
 * statt `wp-block-generateblocks-element` — die Regel griff dort nicht, und
 * der Slider stand mit 1600px auf einer 1600px-Leinwand statt mit 1328.
 * `:is()` nimmt die Spezifitaet seines staerksten Arguments; beides sind
 * einfache Klassen, die Rechnung bleibt also unveraendert.
 */
.editor-styles-wrapper .is-root-container
	> .gb-is-root-block
	> :is(.wp-block-generateblocks-element, .gb-carousel, .wp-block-generateblocks-query).ml-block {
	width: auto;
	/* Wie im Frontend: die Eigenbreite der Komponente ist die engere Grenze. */
	max-width: min(
		var(--ml-eigenbreite, 100vw),
		var(--wp--style--global--wide-size),
		calc(100% - 2 * var(--wp--preset--spacing--rand))
	);
	margin-inline: max(
		var(--wp--preset--spacing--rand),
		calc((100% - var(--wp--style--global--wide-size)) / 2)
	) auto;
}

/*
 * Und derselbe Baustein INNERHALB einer Sektion. Dort greift die Regel oben
 * nicht — er ist kein Kind des Wurzel-Wrappers, sondern steckt im
 * .ml-container. Im Frontend genuegt dafuer die Komponentenregel
 * (`.ml-faq { max-width: var(--wp--custom--baustein--lese) }`), im Editor
 * nicht: GenerateBlocks setzt
 * `.wp-block-generateblocks-element { max-width: unset }` mit (0,2,0) und
 * gewinnt gegen die einfache Klasse.
 *
 * Gemessen vor der Korrektur: dasselbe FAQ war im Frontend 860 und im Editor
 * 1360 Pixel breit — der Redakteur haette die Zeilenlaenge falsch beurteilt.
 */
/* NACHTRAG 11.10. (E2): `.gb-carousel` mit aufgenommen - aus demselben Grund
   wie beim Baustein auf oberster Ebene (Nachtrag 16.09. oben): B04 ist ein
   Karussell, kein `generateblocks/element`. Ohne das Argument haette der
   Slider INNERHALB einer Sektion im Editor weiter die ganze Bahn eingenommen,
   waehrend er im Frontend auf 860 steht. `:is()` nimmt die Spezifitaet seines
   staerksten Arguments - zwei einfache Klassen, die Rechnung bleibt (0,2,0). */
/* NACHTRAG 16.10. (025): `.wp-block-generateblocks-query` in beiden Editor-Regeln -
   B09 Produktkarte ist ein Abfrage-Block mit `.ml-block`. Ohne das Argument stand
   sie im Editor mit 1000 auf der 1000er-Leinwand statt mit ihrer Eigenbreite 328.
   Andere Abfrage-Bloecke tragen `.ml-section`, nicht `.ml-block` - sie bleiben unberuehrt. */
.editor-styles-wrapper
	:is(.wp-block-generateblocks-element, .gb-carousel, .wp-block-generateblocks-query).ml-block {
	max-width: min(var(--ml-eigenbreite, 100vw), 100%);
}

/*
 * Vertikaler Rhythmus. „Sektion auf Wurzelebene" heisst im Frontend
 * .ml-section und im Editor .gb-is-root-block — beide zusammen, damit die
 * Abstaende in beiden Ansichten dieselben sind.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content) > * + * {
	margin-block-start: 1.1em;
}

:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> * + :is(h2, h3, h4, .wp-block-heading) {
	margin-block-start: 1.8em;
}

/*
 * 023 Nachtrag 2: vor einer getippten H2 `band` (48) statt 1,8 em — bei 48 px Schrift
 * waeren das 86, vorher bei 68 px 122. Der Rand des vorigen Absatzes (27) faellt mit
 * diesem zusammen. (0,3,1) gegen (0,3,0) oben.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> * + h2.wp-block-heading {
	margin-block-start: var(--wp--preset--spacing--band);
}

/*
 * Der eigentliche Zweck: Fliesstext darf nicht an einer Sektion kleben.
 * Die Sektion bringt ihren Innenabstand mit, aber ihre Flaeche endet hart an
 * der Kante — ohne diesen Abstand beginnt der naechste Absatz unmittelbar an
 * einem farbigen oder dunklen Block. Fuer einen Baustein gilt dasselbe, nur
 * aus dem umgekehrten Grund: er bringt gar keinen Innenabstand mit.
 *
 * Was „Sektion" bzw. „Baustein" auf Wurzelebene heisst, ist in beiden Ansichten
 * verschieden — im Editor liegt der GB-Wrapper dazwischen. Deshalb steht hier
 * beides nebeneinander, mit :has() auf den Wrapper.

 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(.ml-section, .gb-is-root-block:has(> .ml-section)) + *,
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(.ml-block, .gb-is-root-block:has(> .ml-block)) + *,
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> * + :is(.ml-section, .gb-is-root-block:has(> .ml-section)),
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> * + :is(.ml-block, .gb-is-root-block:has(> .ml-block)) {
	margin-block-start: var(--wp--preset--spacing--sektion);
}

/*
 * 037 (Marc 18.10.): Getippter Titel oder Absatz DIREKT nach einer Sektion traegt keinen eigenen
 * Rand oben — der Abstand kommt allein aus dem Innenabstand der Sektion (unten `sektion`). Vorher
 * addierten sich Innenabstand und der Rand der Regel oben (`sektion`): Kacheln → Text auf
 * /milch-wiki/ rund 240 bei 1440. Spezifitaet (0,5,0) — ueber der Regel oben (0,4,0); die
 * Erklaerkasten-Regel unten (`ml-section-tight` + Text, `band`, 0,6,0) bleibt staerker.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(.ml-section, .gb-is-root-block:has(> .ml-section))
	+ :is(h1, h2, h3, h4, h5, h6, p, .wp-block-heading) {
	margin-block-start: 0;
}

/*
 * 037: H3 direkt nach einer getippten H2 (ohne Absatz dazwischen) steht wie Titel → Folgetext: 20
 * (`gap-s`), vorher 1,8 em = 61 bei 1440. Im Frontend verschmilzt das mit dem Rand unten der H2
 * (GeneratePress, 20); im Editor fehlt dieser Rand — dort traegt die H3 den Abstand allein.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> h2.wp-block-heading + h3.wp-block-heading {
	margin-block-start: var(--wp--preset--spacing--gap-s);
}

/*
 * Zwei Sektionen hintereinander stossen bewusst aneinander — sie tragen ihren
 * Abstand als Innenabstand. Zwei Bausteine tun das NICHT und behalten deshalb
 * die volle Sektionshoehe aus der Regel darueber.
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(.ml-section, .gb-is-root-block:has(> .ml-section)) + :is(.ml-section, .gb-is-root-block:has(> .ml-section)) {
	margin-block-start: 0;
}

/*
 * Nur auf der Uebersichtsseite: ein Erklaerkasten kann auch vor Fliesstext
 * stehen, nicht nur vor einer Sektion. Dann darf die volle Sektionshoehe von
 * oben nicht greifen — die Erklaerung gehoert zu dem, was direkt folgt.
 * Im Editor sitzt die Marker-Klasse eine Ebene tiefer, daher das :has().
 */
:is(.entry-content, .editor-styles-wrapper .is-root-container, .single-wiki .dynamic-entry-content)
	> :is(.ml-section-tight, .gb-is-root-block:has(> .ml-section-tight))
	+ :not(:is(.ml-section, .gb-is-root-block:has(> .ml-section))) {
	margin-block-start: var(--wp--preset--spacing--band);
}

/* ----------------------------------------------------------- Bausteine -- */

/*
 * Ein Baustein ist ein Element OHNE Sektionswrapper: Hinweisbox, Akkordeon,
 * Tabs, Bild-Slider, Video, Bildergalerie. Er nimmt die Breite seines
 * Umfelds an und laesst sich damit auch in eine Spalte legen — was mit
 * eigenem Wrapper nicht ginge (56px Innenabstand, 120px Sektionsabstand und
 * eine 1360er Begrenzung waeren dort alle falsch).
 *
 * Die Geometrie auf oberster Ebene steht weiter oben bei „Breite Breite".
 * Hier steht nur, was innerhalb gilt.
 */

.ml-block > :first-child { margin-top: 0; }
.ml-block > :last-child  { margin-bottom: 0; }

/*
 * Zwei Bausteine in derselben Sektion brauchen Luft. Bewusst eng gefasst und
 * nicht als `.ml-container > * + *`: der Hero haelt mehrere Kinder im
 * Container, die ihre Abstaende selbst regeln.
 */
.ml-container > .ml-block + .ml-block {
	margin-top: var(--wp--preset--spacing--band);
}

/* ------------------------------------------------------- Container Queries -- */

/*
 * Nur fuer die Bausteine. Die Sektionen bleiben auf Media Queries — sie stehen
 * per Definition ueber die volle Breite, dort ist die Viewport-Frage richtig.
 *
 * `container-type` gehoert auf einen VORFAHREN, nie auf den Baustein selbst:
 * ein Container kann sich nicht selbst abfragen. Drei Orte, an denen ein
 * Baustein stehen kann, also drei Container:
 *
 *   .ml-container   — Baustein in einer Sektion
 *   .wp-block-column — Baustein in einer Spalte
 *   .entry-content  — Baustein auf oberster Ebene
 *
 * Der naechstgelegene benannte Container gewinnt, die Verschachtelung loest
 * sich also von selbst richtig auf.
 *
 * Zum Mitmessen: auf oberster Ebene ist der Container rund 112px breiter als
 * der Baustein darin (der Seitenrand links und rechts). Die Schwellen unten
 * sind entsprechend gesetzt.
 */
.ml-container,
.wp-block-column,
.entry-content,
.single-wiki .dynamic-entry-content,
.editor-styles-wrapper .is-root-container {
	container-type: inline-size;
	container-name: ml;
}

/* --------------------------------------------------------- Slider (B04) -- */

/*
 * GenerateBlocks Pro liest die Folienanzahl aus dieser Custom Property und
 * beobachtet sie per ResizeObserver — Aenderungen wirken live, ohne Neuladen.
 *
 * ZWEI FALLSTRICKE, beide gemessen:
 *   1. Die Property muss beim Initialisieren AUS DEM STYLESHEET gesetzt sein.
 *      Ist beim Start keine der vier gb-carousel-Properties gesetzt, legt
 *      GenerateBlocks gar keinen ResizeObserver an — spaetere Aenderungen
 *      verpuffen dann stillschweigend. Ein Setzen per JavaScript wirkt nicht.
 *   2. Der Wert wird von `.ml-slider` gelesen, nicht von einem Kind. Die
 *      Container Query muss also auf einen Vorfahren zielen (siehe oben).
 *
 * Eine Folie ist die abgenommene Fassung: ein Bild im Format 4:3 fuellt die
 * Bahn. Der Wert steht hier trotzdem ausdruecklich — damit der Beobachter
 * angelegt wird und eine mehrspaltige Fassung eine Zeile Arbeit ist:
 *
 *   @container ml (min-width: 1100px) { .ml-slider { --gb-carousel-slides-per-view: 2 } }
 */
.ml-slider {
	--gb-carousel-slides-per-view: 1;
	--gb-carousel-slide-gap: 24;
}

@container ml (max-width: 700px) {
	.ml-slider { --gb-carousel-slide-gap: 12; }
}

/* -------------------------------------------------------- Galerie (B06) -- */

/*
 * Core legt die Spaltenzahl der Galerie an eine VIEWPORT-Media-Query:
 * unter 600px Fensterbreite zweispaltig, darueber die Klasse `columns-3`.
 * In einer halben Spalte bleibt sie damit am Desktop dreispaltig mit rund
 * 200px pro Bild. Hier ersetzt durch dieselbe Rechnung auf Containerbasis.
 *
 * Der Selektor wirkt umstaendlich, ist es aber nicht: Core schreibt
 * `figure.wp-block-image:not(#individual-image)` und liegt damit bei (1,3,1) —
 * ein `:not()` auf eine ID zaehlt wie eine ID. Ohne dieselbe Konstruktion
 * gaebe es hier keine Chance ohne !important.
 *
 * ZWEI NACHTRAEGE, beide gemessen — die Regel hat vorher NIE gegriffen:
 *
 * 1. `.ml-gallery` sitzt nicht auf dem Galerie-Block, sondern auf dem
 *    generateblocks/element-Wrapper darueber. Die Baumfolge ist
 *    `div.ml-block.ml-gallery > figure.wp-block-gallery > figure.wp-block-image`.
 *    Ein Selektor `.ml-gallery.wp-block-gallery` verlangt beide Klassen am
 *    SELBEN Element und trifft damit nichts. Es braucht einen Nachfahren-
 *    Kombinator.
 *
 * 2. Core setzt die Spaltenzahl ueber
 *    `.wp-block-gallery.has-nested-images.columns-3 figure…:not(#individual-image)`
 *    in `@media (min-width: 600px)`. Das ist (1,4,1) — gleichauf mit der
 *    naheliegenden Fassung dieser Regel. Bei Gleichstand entscheidet die
 *    Quellreihenfolge, und WordPress laedt die Blockbibliothek blockweise
 *    NACH dem Child-Theme. Core gewann also selbst dann, wenn der Selektor
 *    richtig geschrieben war.
 *
 * `.ml-block` steht deshalb mit im Selektor. Es sitzt am selben Element wie
 * `.ml-gallery`, waehlt also nichts anderes aus — es hebt die Spezifitaet auf
 * (1,5,1) und damit ueber Core. Wer die Klasse entfernt, bekommt den Fehler
 * zurueck, ohne dass etwas kaputt aussieht: die Galerie ist dann in einer
 * halben Spalte dreispaltig mit 85px breiten Bildern.
 */
.ml-block.ml-gallery .wp-block-gallery.has-nested-images
	figure.wp-block-image:not(#individual-image) {
	width: calc(33.333% - var(--wp--style--unstable-gallery-gap, 16px) * 0.667);
}

/* Nachtrag 11.10. (Schritt 4, M1): Die Variante "4-spaltig" wirkte nicht - die
   Regel oben setzt 33,333 % fest, unabhaengig von der Core-Klasse `columns-N`.
   Gemessen: `columns-4` lieferte weiter 3 Bilder je Reihe. Die Vorgabe nennt
   beide Varianten (Zeile 1786).

   Die Ergaenzung steht in einer eigenen Container-Bedingung ab 901 px statt
   mit hoeherer Spezifitaet: eine Regel mit (1,6,1) haette die beiden
   Schmalstufen unten (50 % und 100 %, je (1,5,1)) mit ueberstimmt und die
   Galerie auf dem Handy vierspaltig gemacht. Getrennte Bereiche kollidieren
   nicht. */
@container ml (min-width: 901px) {
	.ml-block.ml-gallery .wp-block-gallery.has-nested-images.columns-4
		figure.wp-block-image:not(#individual-image) {
		width: calc(25% - var(--wp--style--unstable-gallery-gap, 16px) * 0.75);
	}
}

@container ml (max-width: 900px) {
	.ml-block.ml-gallery .wp-block-gallery.has-nested-images
		figure.wp-block-image:not(#individual-image) {
		width: calc(50% - var(--wp--style--unstable-gallery-gap, 16px) * 0.5);
	}
}

@container ml (max-width: 460px) {
	.ml-block.ml-gallery .wp-block-gallery.has-nested-images
		figure.wp-block-image:not(#individual-image) {
		width: 100%;
	}
}

/* ------------------------------------------- Tabs (B03) und Akkordeon (B02) -- */

/*
 * Die Reiterleiste bricht in einer schmalen Spalte um, statt zu ueberlaufen.
 */
@container ml (max-width: 560px) {
	.ml-tabs [role="tablist"] {
		flex-wrap: wrap;
	}
}

/* --------------------------------------------------- 1 · Hero mit Bild -- */

.ml-hero {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: var(--wp--custom--hero--min-height);
	/* Entwurfswerte: oben 72, unten 80 — nicht das Sektionsmass. */
	padding-block: var(--wp--custom--hero--padding-top) var(--wp--custom--hero--padding-bottom);
	padding-inline: var(--wp--preset--spacing--rand);
	overflow: hidden;
	background-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

/*
 * Bildwechsel. Drei Motive ueberblenden sich; gebaut auf dem GB-Pro-Karussell
 * mit `data-effect="fade"`, nicht auf eigenem JavaScript. Das Karussell liegt
 * als Schicht 0 hinter Verlauf, Verdunklung und Text.
 *
 * Die Bildunterschrift steht IM Bild, nicht daneben: so blendet sie mit dem
 * Motiv ueber und kann nie zum falschen Bild gehoeren. Die Auswahlpunkte
 * liefert das Karussell selbst (`.gb-carousel-pagination`).
 */
.ml-hero__wechsel {
	position: absolute;
	inset: 0;
	/*
	 * Kein eigener Stapelkontext (vorher `z-index: 0`). Die Auswahlpunkte sitzen
	 * in diesem Element mit `z-index: 5` — in einem Kontext auf Stufe 0 lag der
	 * Verlauf (`.ml-hero-scrim`, Stufe 1) darueber und dunkelte die Punkte auf
	 * etwa ein Drittel ab (gemessen: Weiss 255 -> 81). Ohne Kontext stehen sie
	 * ueber Verlauf und Text; die Bilder bleiben unter dem Verlauf, denn ihr
	 * Kontext ist `.ml-hero__rail` (Stufe 1, im Dokument vor dem Verlauf).
	 */
	z-index: auto;
}

.ml-hero__rail,
.ml-hero__slide {
	height: 100%;
}

.ml-hero__slide {
	position: relative;
}

.ml-hero__media {
	position: absolute;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top;
}

/*
 * Je Motiv ein eigener Bildausschnitt. Die Werte stehen im Entwurf und
 * haengen am Motiv, nicht am Element — deshalb eine Klasse pro Bild statt
 * eines Tokens.
 */
.ml-hero__slide[data-ausschnitt="a"] .ml-hero__media { object-position: center 78%; }
.ml-hero__slide[data-ausschnitt="b"] .ml-hero__media { object-position: center 62%; }
.ml-hero__slide[data-ausschnitt="c"] .ml-hero__media { object-position: center 58%; }

/*
 * Bildunterschrift unten rechts. Der Platz rechts daneben gehoert den
 * Auswahlpunkten; `--ml-hero-punkte-raum` haelt beide auseinander. Wer ein
 * viertes Motiv aufnimmt, erhoeht den Wert um 17px (Punkt plus Abstand).
 */
.ml-hero {
	--ml-hero-punkte-raum: 61px;
}

.ml-hero__caption {
	position: absolute;
	right: calc(24px + var(--ml-hero-punkte-raum));
	bottom: 18px;
	z-index: 5;
	max-width: 46ch;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	line-height: 1.35;
	text-align: right;
	color: color-mix(in srgb, var(--wp--preset--color--white) 62%, transparent);
	/*
	 * Zusatz zum Entwurf. 0.62 Weiss reicht ueber den drei gelieferten
	 * Motiven aus — gemessen 5.46:1 bei 1440 und 4.98:1 bei 390 —, aber der
	 * Untergrund ist austauschbar: der Redakteur waehlt die Bilder. Der
	 * Schatten haelt die Leichtigkeit der Zeile und gibt Luft nach unten,
	 * falls ein helleres Motiv nachrueckt. Dieselbe Loesung wie beim
	 * Bildnachweis.
	 */
	text-shadow: 0 1px 4px color-mix(in srgb, var(--wp--preset--color--black) 75%, transparent);
	pointer-events: none;
}

/*
 * Die Karussell-Stile von GB Pro werden erst beim Rendern des Blocks
 * eingehaengt und stehen damit HINTER components.css. Bei gleicher
 * Spezifitaet gewinnen sie — deshalb hier eine Stufe mehr ueber .ml-hero.
 */
.ml-hero .ml-hero__dots {
	position: absolute;
	right: 24px;
	bottom: 18px;
	z-index: 5;
	display: flex;
	gap: 8px;
	width: auto;
}

.ml-hero__dots .gb-carousel-dot {
	width: 9px;
	height: 9px;
	padding: 0;
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--white) 85%, transparent);
	border-radius: var(--wp--custom--radius--pill);
	background: transparent;
	cursor: pointer;
	transition: background 0.25s ease;
}

.ml-hero__dots .gb-carousel-dot.is-active {
	background: var(--wp--preset--color--white);
}

/*
 * Fokusumrandung der Karussell-Punkte: kein eigener Block mehr. GB Pro setzt
 * `.gb-carousel-dot:focus-visible { outline: 2px solid currentcolor }`; die
 * globale Regel im Abschnitt „Fokusrahmen" (0,2,1) steht darueber, die Farbe
 * kommt aus `--ml-focus` (im Hero Weiss, sonst Blau).
 */

/*
 * Editor-Darstellung (008). Der Block-Editor setzt jeden Block auf
 * `.block-editor-block-list__layout .block-editor-block-list__block
 * { position: relative }` (WordPress-Kern, block-editor/content.css, 0,2,0)
 * und schlaegt damit die einfachen Klassenregeln oben: Bildwechsel,
 * Verdunklung, Bild und Bildunterschrift lagen im Fluss, der Hero (flex)
 * stellte Bildkasten und Text nebeneinander. `.editor-styles-wrapper` gibt
 * es nur im Editor-iframe - auf der Website greift hier nichts.
 */
.editor-styles-wrapper .ml-hero > .ml-hero__wechsel,
.editor-styles-wrapper .ml-hero > .ml-hero-scrim,
.editor-styles-wrapper .ml-hero > .ml-hero-scrim-seite,
.editor-styles-wrapper .ml-hero .ml-hero__media,
.editor-styles-wrapper .ml-hero .ml-hero__caption {
	position: absolute;
}

/*
 * Weitere Editor-Regeln, die die Website-Werte gegen Editor-Vorgaben halten:
 * `.editor-styles-wrapper img { height: auto }` (WordPress) stauchte das Bild
 * nicht, sondern machte es hoeher als den Hero - der Bildausschnitt verschob
 * sich. Die GenerateBlocks-Regel `margin: 0` an GB-Bloecken im Editor
 * (Stolperstelle 104) nahm Kicker und Knopfzeile ihre Abstaende; die Textbreite
 * war im Editor nicht begrenzt. Dieselben Token wie auf der Website.
 */
.editor-styles-wrapper .ml-hero .ml-hero__media {
	height: 100%;
}

.editor-styles-wrapper .ml-hero .ml-label {
	margin-bottom: var(--wp--custom--hero--kicker-abstand);
}

.editor-styles-wrapper .ml-hero .ml-actions {
	margin-top: var(--wp--custom--hero--knopf-abstand);
}

.editor-styles-wrapper .ml-hero .ml-hero__text,
.editor-styles-wrapper .ml-hero .ml-hero__note {
	max-width: var(--wp--custom--hero--prose-width);
}

/*
 * Punkte und Bildunterschrift: Im Editor-iframe fehlt `box-sizing: border-box`
 * der Website - die Punkte wurden 11 statt 9 px gross. Die Bildunterschrift
 * erbte im Karussell des Editors die Systemschrift statt Nunito und lief
 * schmaler (gemessen 6 px bei 1040).
 */
.editor-styles-wrapper .ml-hero .ml-hero__dots .gb-carousel-dot {
	box-sizing: border-box;
}

.editor-styles-wrapper .ml-hero .ml-hero__caption {
	font-family: var(--wp--preset--font-family--nunito);
}

/*
 * Das Karussell blendet im Editor ueber Deckkraft: die aktive Folie traegt
 * `is-active`, die anderen liegen unsichtbar (Deckkraft 0) DARUEBER und
 * fingen den Klick ab - ein Klick aufs Bild waehlte das unsichtbare Bild der
 * letzten Folie, und dafuer zeigte der Editor keine Werkzeugleiste. Nicht
 * aktive Folien lassen den Klick durch - samt Nachfahren, weil der Editor
 * jeden Block wieder auf `pointer-events: auto` setzt. Ueber die Listenansicht
 * bleibt jede Folie waehlbar.
 */
.editor-styles-wrapper .ml-hero .ml-hero__slide:not(.is-active),
.editor-styles-wrapper .ml-hero .ml-hero__slide:not(.is-active) * {
	pointer-events: none;
}

/* Fest im Pattern. Nicht editierbar — sonst kippt der Kontrast (BFSG). */
.ml-hero-scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: var(--wp--custom--hero--overlay);
	pointer-events: none;
}

/*
 * Zweite Verdunklung, waagerecht von links. Der Grundverlauf allein reicht
 * nicht mehr: die Schlagzeile steht jetzt auf drei wechselnden Motiven, und
 * eines davon ist im Textbereich hell. Senkrecht maskiert, damit sie oben
 * unter der Kopfzeile und unten ueber der Bildunterschrift auslaeuft.
 *
 * Drei Auslaeufe stehen zur Wahl — der Entwurf stellt sie nebeneinander.
 * Vorgabe ist „frueh". Umgestellt wird ueber data-scrim an der Sektion.
 */
.ml-hero-scrim-seite {
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	z-index: 1;
	width: var(--wp--custom--hero--scrim-width);
	background: var(--wp--custom--hero--scrim);
	mask-image: var(--wp--custom--hero--scrim-mask);
	-webkit-mask-image: var(--wp--custom--hero--scrim-mask);
	pointer-events: none;
}

.ml-hero[data-scrim="spaet"] .ml-hero-scrim-seite {
	width: min(1120px, 92%);
	background: linear-gradient(97deg, color-mix(in srgb, var(--wp--preset--color--black) 78%, transparent) 0%, color-mix(in srgb, var(--wp--preset--color--black) 78%, transparent) 42%, color-mix(in srgb, var(--wp--preset--color--black) 76%, transparent) 54%, color-mix(in srgb, var(--wp--preset--color--black) 70%, transparent) 63%, color-mix(in srgb, var(--wp--preset--color--black) 60%, transparent) 71%, color-mix(in srgb, var(--wp--preset--color--black) 47%, transparent) 78%, color-mix(in srgb, var(--wp--preset--color--black) 33%, transparent) 85%, color-mix(in srgb, var(--wp--preset--color--black) 19%, transparent) 91%, color-mix(in srgb, var(--wp--preset--color--black) 8%, transparent) 96%, color-mix(in srgb, var(--wp--preset--color--black) 0%, transparent) 100%);
}

.ml-hero[data-scrim="voll"] .ml-hero-scrim-seite {
	width: min(1180px, 94%);
	background: linear-gradient(97deg, color-mix(in srgb, var(--wp--preset--color--black) 82%, transparent) 0%, color-mix(in srgb, var(--wp--preset--color--black) 82%, transparent) 62%, color-mix(in srgb, var(--wp--preset--color--black) 80%, transparent) 71%, color-mix(in srgb, var(--wp--preset--color--black) 74%, transparent) 78%, color-mix(in srgb, var(--wp--preset--color--black) 63%, transparent) 84%, color-mix(in srgb, var(--wp--preset--color--black) 48%, transparent) 89%, color-mix(in srgb, var(--wp--preset--color--black) 31%, transparent) 93%, color-mix(in srgb, var(--wp--preset--color--black) 16%, transparent) 96%, color-mix(in srgb, var(--wp--preset--color--black) 6%, transparent) 98%, color-mix(in srgb, var(--wp--preset--color--black) 0%, transparent) 100%);
}

.ml-hero .ml-container {
	position: relative;
	z-index: 2;
}

/* Textspalte des Hero — Titelrolle hero-start, 1050 px (Abgleich 23.09., 4.9; vorher 760). Der Fliesstext darin bleibt bei 640 px (hero.proseWidth). */
.ml-hero__body {
	max-width: var(--wp--custom--titel--feld--hero-start);
}

.ml-hero__title {
	font-size: var(--wp--preset--font-size--titel-hero-start);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--hero);
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--preset--color--white);
	margin: 0;
}

.ml-hero__text {
	max-width: var(--wp--custom--hero--prose-width);
	margin: 28px 0 0;
	font-weight: 500;
	line-height: 1.6;
	color: var(--wp--preset--color--white);
}

.ml-hero__note {
	display: block;
	max-width: var(--wp--custom--hero--prose-width);
	margin: 10px 0 0;
	font-weight: 700;
	line-height: 1.6;
	color: var(--wp--preset--color--white);
}

/*
 * Kicker mit vorangestelltem Strich, wie im Entwurf. Als ::before statt als
 * eigener Block — ein Zierstrich ist kein Inhalt und hat im Editor nichts
 * verloren, wo der Redakteur ihn versehentlich leeren koennte.
 */
.ml-hero .ml-label {
	color: var(--wp--preset--color--white);
	opacity: 0.85;
	margin-bottom: var(--wp--custom--hero--kicker-abstand);
}

.ml-hero .ml-label::before {
	content: "";
	display: inline-block;
	width: 36px;
	height: 1px;
	margin-right: 12px;
	vertical-align: middle;
	background-color: currentColor;
}

/*
 * Im Entwurf stehen die drei Buttons in einer Zeile und duerfen dabei ueber
 * die 760 px der Textspalte hinauslaufen. Erst auf schmalen Schirmen umbrechen.
 */
.ml-hero .ml-actions {
	margin-top: var(--wp--custom--hero--knopf-abstand);
	flex-wrap: nowrap;
	width: max-content;
	/* Darf ueber die Textspalte hinauslaufen — so im Entwurf. */
	max-width: none;
}

@media (max-width: 900px) {
	.ml-hero .ml-actions {
		flex-wrap: wrap;
		width: auto;
	}
}

.ml-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

/* --------------------------------------------------- 2 · Seiten-H1 -- */

/*
 * Traegt die H1 der Unterseiten (Entwurf „Qualitaetsfoerderung", 17.09.).
 * Der Typselektor h1 aus theme.json liefert die Hero-Groesse 60px; der
 * Entwurf sichert an dieser Stelle 48px bei 1440 zu. Nach Regel 7 gehoert
 * eine zugesicherte Groesse an eine Klasse, nicht an einen Typselektor.
 * Groesse und Zeilenhoehe stehen als Token in theme.json (titel-seite,
 * line-height pagehead) — hier nur der Verweis, kein Literal.
 * Klassennamen sind Bestand aus dem verworfenen „Seitenkopf schlicht".
 */
.ml-pagehead__title {
	font-size: var(--wp--preset--font-size--titel-seite);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--pagehead);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0 0 1rem;
	max-width: var(--wp--custom--titel--feld--section-bild);
}

/*
 * Abstand Absatz -> Absatz im Vorspann: 18px (Entwurf, Zeilen 141-153).
 * Bis 0.38.0 stand hier `margin: 0` - das hat die Regel
 * `:root :where(.is-layout-flow) > *` aus den Global Styles (24px) bei
 * gleicher Spezifitaet und spaeterer Quelle geschlagen; die beiden
 * Vorspannabsaetze standen buendig aneinander. Gemessen: 0px.
 */
.ml-pagehead__text {
	max-width: 62ch;
	margin: var(--wp--custom--abstand--vorspann) 0 0;
	font-size: var(--wp--preset--font-size--label);
	line-height: var(--wp--custom--ui--line-height);
	color: var(--wp--custom--text--gedaempft);
}

/*
 * Abstand H1 -> erster Vorspannabsatz: 32px (Entwurf, Zeile 141:
 * margin: "32px 0 18px 0" am Vorspann). Gemessen vorher: 24px - der
 * Blockabstand der Global Styles ueber `:root :where(.is-layout-flow) > *`.
 *
 * Der Abstand haengt am Absatz, nicht am Titel: `margin` am Titel kommt dort
 * nicht an. `.ml-pagehead__title { margin: 0 0 1rem }` (Zeile 2067) verliert
 * gegen die Titelrollen-Regel `:is(.ml-titel-hero-start, ...)` mit `margin: 0`
 * - gleiche Spezifitaet (0,1,0), spaeter in derselben Datei. Am 30.09. im
 * Browser ueber document.styleSheets aufgeloest.
 *
 * (0,1,1) schlaegt sowohl den Blockabstand (0,1,0) als auch das 18px oben.
 * Der allgemeine Blockabstand bleibt bei 24px.
 */
.ml-pagehead__title + p {
	margin-block-start: var(--wp--custom--abstand--vorspann-titel);
}

/* ----------------------------------------------------- 3 · Sektionskopf -- */

.ml-sectionhead {
	/* Titelfeld fuer den Intro-Schalter unten (015); Startseite breiter. */
	--ml-kopf-titelfeld: var(--wp--custom--titel--feld--section);
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	justify-content: space-between;
	gap: 32px;
	margin-bottom: calc(var(--wp--preset--spacing--band) + 1rem);
}

/* Der Kicker der Sektion steht blau, nicht grau — so im Entwurf. */
/*
 * `blue-dark` und nicht `blue`: Der Kicker ist 16 px bei Schnitt 700 und damit
 * normaler Text nach WCAG (gross ist erst ab 18,66 px fett) — gefordert sind
 * 4,5 : 1. Gemessen am 19.09. mit `blue`:
 *
 *   auf Weiss 4,907 · auf `gray-bg` 4,459 · auf Tint 4,365
 *
 * Auf Tint faellt das durch, auf Weiss liegt es ohne Polster darueber. Mit
 * `blue-dark`: 7,298 · 6,631 · 6,491.
 *
 * Nur die HELLEN Flaechen. Auf dunklem Grund traegt `.ml-section-dark
 * .ml-sectionhead .ml-label` weiterhin `gray-light` — dort waere ein
 * dunkleres Blau eine Verschlechterung (blau auf schwarz 4,279,
 * blau-dunkel auf schwarz nur 2,878).
 */
.ml-sectionhead .ml-label {
	color: var(--wp--preset--color--blue-dark);
	/* Eigene Farbe — Deckkraft der Grundregel zuruecknehmen. */
	opacity: 1;
	margin-bottom: var(--wp--custom--abstand--label);
}

.ml-section-dark .ml-sectionhead .ml-label {
	color: var(--wp--preset--color--gray-light);
	opacity: 1;
}

/* Linksbuendig, nicht rechts: der Entwurf setzt hier keinen Flattersatz. */
.ml-sectionhead__intro {
	/* Bau 43 (Y3): 340 nach beiden Entwuerfen, vorher 360.
	   015 (Entscheidung 14.10.): 340 nur, wenn Titel und Intro NEBENEINANDER
	   passen (Titelfeld + Luecke 32 + 340 <= Kopfbreite); untereinander die
	   volle Breite - vorher stand das Intro auch gestapelt 340 schmal und
	   endete mit einem Wort allein. Schalter ohne Medienabfrage: ist die
	   Kopfbreite (100 %) kleiner als die Summe, wird der zweite Term gross und
	   positiv (-> 100 %), sonst negativ (-> 340). */
	max-width: max(
		var(--wp--custom--sektionskopf--intro-breite),
		min(100%, calc((var(--ml-kopf-titelfeld) + 32px + var(--wp--custom--sektionskopf--intro-breite) - 100%) * 1000))
	);
	margin: 0;
	font-size: 16px;
	line-height: 1.55;
	color: var(--wp--custom--text--gedaempft);
}

/* ----------------------------------------------------- 3 · Text mit Bild -- */

.ml-split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	/* Bau 43 (E4): Bild oben buendig mit der Textspalte, nicht mittig. */
	align-items: start;
	/* Bau 43 (E3): Spaltenabstand 72 wie S23 (Newsentwurf 72, Milchlandpreis-
	   entwurf 64 - der juengere Abgleich gilt). Der Zeilenabstand der
	   einspaltigen Lage bleibt `sektion`, sonst aendert sich 390 mit. */
	gap: var(--wp--preset--spacing--sektion) var(--wp--custom--split--gap);
}

.ml-split__media {
	/* Bau 43 (E9): als Inline-Bild trug es die Unterlaenge der Zeile mit -
	   Abstand zur Bildunterschrift 20 statt der 12 aus .ml-caption. */
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--split--schatten);
}

/* Bau 43 (E2): Abstaende der Textspalte nach dem Newsentwurf - Titel ->
   erster Teil 32 (`abstand.vorspannTitel`; Milchlandpreisentwurf 24), jeder
   weitere Abstand 20 (`abstand.absatz`), kein Rand unter dem letzten Teil.
   Vorher 1rem plus der `margin-bottom: 1.5em` von GeneratePress, der in der
   Spalte stehen blieb (31,5 nach dem Vorspann, 27 unter dem letzten Absatz). */
/* Der Kicker (nur noch in Bestandsinstanzen vor Bau 29) behaelt seinen eigenen
   Abstand nach unten: der Titel traegt `margin: 0` aus der Titelrollen-Regel. */
.ml-split__body > :not(.ml-label) {
	margin-bottom: 0;
}

.ml-split__body > * + * {
	margin-top: var(--wp--custom--abstand--absatz);
}

/* S03-Kicker, optional (009, 14.10.): wie S02/S10/S16 - `blue-dark`, volle
   Deckkraft, 14 zum Titel. Leer faellt er aus der Ausgabe
   (milchland_optionale_teile, Marker `ml-split__kicker`). */
.ml-split__body > .ml-label {
	color: var(--wp--preset--color--blue-dark);
	opacity: 1;
	margin-bottom: var(--wp--custom--abstand--label);
}

.ml-split__body > .ml-label + * {
	margin-top: 0;
}

.ml-split__body > .ml-display + * {
	margin-top: var(--wp--custom--abstand--vorspann-titel);
}

.ml-split__title {
	font-size: var(--wp--preset--font-size--titel-l);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--section);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0;
}

/* Bild und Bildunterschrift (Bauauftrag 11, 0.32.0) - der Wrapper ist das
   Rastermitglied, nicht mehr das <img> direkt; die order-Regel fuer die
   Variante "links" haengt deshalb hier statt an .ml-split__media. */
.ml-split__media-wrap {
	min-width: 0;
}

/* Variante als Block-Style: Bild links */
.ml-split[data-variante="links"] .ml-split__media-wrap { order: -1; }

@media (max-width: 782px) {
	.ml-split { grid-template-columns: 1fr; }
	.ml-split[data-variante="links"] .ml-split__media-wrap { order: 0; }
}

/* Vorspann-Achse (0.32.0): hebt den ersten Absatz hervor, unabhaengig von
   der Bild-Variante. Zweite Achse, kein eigenes Muster - Vorgabe des
   Bauauftrags. Vorgabewert "nein", nicht gebauter Bestand bleibt unberuehrt. */
/* Bau 39 (D3): S15 bekommt dieselbe Hervorhebung — das Feld „Erster Absatz“ (Satz 730) bot
   „Hervorgehoben“ auch am Seitenanfang an, dort stand aber nur „einleitung“ in der CSS.
   Selektorliste wie bei „einleitung“ unten, kein neuer Wert. */
.ml-split[data-vorspann="ja"] .ml-split__body p:first-of-type,
.ml-section[data-vorspann="ja"] .ml-pagehead__title ~ p:first-of-type {
	font-size: 21px;
	font-weight: 600;
}

/* -------------------------------------------------------- 6 · Hinweisbox -- */

.ml-note {
	--ml-eigenbreite: var(--wp--custom--baustein--schmal);
	max-width: var(--wp--custom--baustein--schmal);
	padding: 1.75rem 2rem;
	border-radius: var(--wp--custom--radius--panel);
	background-color: var(--wp--preset--color--blue-tint);
	border-left: 4px solid var(--wp--preset--color--blue);
}

.ml-note__title {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 800;
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0 0 0.5rem;
}

.ml-note__text {
	margin: 0;
}

/* Bau 39 (D5): blue-dark statt blue. Markenblau erreichte auf der getoenten Box 4,3647
   (2 x auf der Elementuebersicht), auf `grau` 4,3419. blue-dark: 6,4910 / 6,4571.
   Die Variante `blau` setzt den Link weiter auf Weiss (Regel unten). */
.ml-note__link {
	display: inline-block;
	margin-top: 0.75rem;
	font-weight: 700;
	color: var(--wp--preset--color--blue-dark);
}

/*
 * Varianten haengen am Attribut data-variante, nicht an eigenen Klassen.
 * Grund: der Redakteur bekommt dafuer im Editor-Access-Profil ein Auswahlfeld,
 * und ein Attribut laesst sich sauber umschalten. Hintergrund und Textfarbe
 * wechseln immer gemeinsam — den Kontrast gibt das Element vor, nicht der
 * Redakteur (BFSG).
 */
.ml-note[data-variante="grau"] {
	background-color: var(--wp--preset--color--gray-bg);
	border-left-color: var(--wp--preset--color--gray-dark);
}

.ml-note[data-variante="blau"] {
	background-color: var(--wp--preset--color--blue);
	border-left-color: var(--wp--preset--color--blue-dark);
	color: var(--wp--preset--color--white);
}

.ml-note[data-variante="blau"] :is(.ml-note__title, .ml-note__text, .ml-note__link) {
	color: var(--wp--preset--color--white);
}

/* ------------------------------------------------------ 10 · Split-Banner -- */

.ml-banner {
	display: grid;
	/*
	 * Nachtrag 11.10. (Schritt 4, M2): Die Vorgabe (Zeile 1400) nennt 1,4 : 1,
	 * gemessen waren 1 : 1 (656,3 / 656,3 bei 1440). Die Textspalte ist die
	 * breitere; das Bild bleibt in voller Hoehe (`align-items: stretch`).
	 */
	grid-template-columns: 1.4fr 1fr;
	align-items: stretch;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--panel);
	background-color: var(--wp--preset--color--gray-bg);
}

.ml-banner__body {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.875rem;
	padding: var(--wp--preset--spacing--band);
}

/* S06-Kicker wie ueberall (009): `blue-dark`, volle Deckkraft; der Abstand
   zum Titel ist die Luecke der Spalte (14), kein eigener Rand. */
.ml-banner__body .ml-label {
	color: var(--wp--preset--color--blue-dark);
	opacity: 1;
	margin-bottom: 0;
}

.ml-banner__title {
	font-size: var(--wp--preset--font-size--titel-l);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--section);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0;
}

.ml-banner__media {
	width: 100%;
	height: 100%;
	min-height: 320px;
	object-fit: cover;
}

/*
 * S06-Bildspalte mit optionaler Bildunterschrift (009, 14.10.). Neue Instanzen
 * tragen das Bild in `.ml-banner__media-wrap`, darunter die Bildunterschrift
 * (`ml-caption`, leer faellt sie weg - milchland_s03_bildunterschrift). Das
 * Bild fuellt die Spalte wie bisher; aeltere Instanzen ohne Huelle bleiben
 * wie sie sind.
 */
.ml-banner__media-wrap {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.ml-banner__media-wrap > .ml-banner__media {
	flex: 1 1 auto;
	height: auto;
}

.ml-banner__media-wrap > .ml-caption {
	padding: 0 var(--wp--preset--spacing--gap-l) var(--wp--preset--spacing--gap-l) 0;
}

@media (max-width: 782px) {
	.ml-banner { grid-template-columns: 1fr; }
}

/* ------------------------------------------------- Häkchenliste ---------- */

/*
 * Kein Element und kein Pattern, sondern drei Block-Styles auf `core/list`.
 * Der Redakteur tippt eine normale Liste und waehlt die Darstellung — er
 * bedient damit einen Block, den er ohnehin kennt, und das Markup bleibt
 * ein semantisches <ul> mit <li>.
 *
 * Spalten ueber `columns`, nicht ueber Grid. Grund ist nicht das Markup —
 * Grid liesse die Liste ebenfalls ein <ul> —, sondern die Vorlesbarkeit:
 * `display: grid` nimmt VoiceOver in Safari die Listensemantik, `columns`
 * laesst `display` unangetastet. Preis ist die spaltenweise Lesereihenfolge
 * (erst Spalte eins von oben nach unten, dann Spalte zwei); bei ungeordneten
 * Fakten ist das unkritisch und bewusst so entschieden.
 *
 * `list-style: none` hat dieselbe Nebenwirkung auf die Semantik. Dagegen
 * traegt ein render_block-Filter in der functions.php am <ul> ein
 * `role="list"` nach — CSS allein kann das nicht.
 */
.wp-block-list:is(.is-style-ml-check, .is-style-ml-check-2, .is-style-ml-check-3) {
	list-style: none;
	padding-left: 0;
	margin-inline: 0;
	/*
	 * Eigenbreite wie bei den Bausteinen anmelden, nicht nur begrenzen:
	 * `core/list` unterstuetzt `align` nicht, die Liste bekommt also keine
	 * Klasse `alignwide` und faellt sonst auf die Lesebreite von 680px —
	 * gemessen, bevor diese Zeilen standen. Die Bahn-Regel weiter oben nimmt
	 * den Wert auf und setzt zugleich den Seitenrand.
	 */
	--ml-eigenbreite: 720px;
	max-width: 720px;
	column-gap: 56px;
}

.wp-block-list.is-style-ml-check-2,
.wp-block-list.is-style-ml-check-3 {
	--ml-eigenbreite: 1100px;
	max-width: 1100px;
}

.wp-block-list.is-style-ml-check-2 { columns: 2; }
.wp-block-list.is-style-ml-check-3 { columns: 3; }

.wp-block-list:is(.is-style-ml-check, .is-style-ml-check-2, .is-style-ml-check-3) > li {
	position: relative;
	/* 26px Marker plus 16px Abstand. */
	padding-left: 42px;
	min-height: 26px;
	/*
	 * Abstand der Punkte 16px, wie im Entwurf „Beitragsseite Upcycling". Bis
	 * 03.10. standen hier 22px; gemessen waren drei Listen im Bestand (alle auf
	 * der Elementuebersicht), also angeglichen. Gilt fuer alle drei Haekchen-Stile.
	 */
	margin-block-end: 16px;
	font-size: var(--wp--custom--ui--size-l);
	line-height: var(--wp--custom--line-height--liste);
	font-weight: 600;
	/*
	 * Ohne das reisst der Spaltenumbruch einen zweizeiligen Punkt
	 * auseinander — Marker in der einen Spalte, halber Satz in der naechsten.
	 */
	break-inside: avoid;
}

.wp-block-list:is(.is-style-ml-check, .is-style-ml-check-2, .is-style-ml-check-3) > li:last-child {
	margin-block-end: 0;
}

/* Der Kreis. */
.wp-block-list:is(.is-style-ml-check, .is-style-ml-check-2, .is-style-ml-check-3) > li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 0;
	width: 26px;
	height: 26px;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--blue);
}

/*
 * Der Haken. Als Maske, nicht als Bild: Bei `mask-image` zaehlt nur der
 * Alphakanal, die Farbe im SVG ist bedeutungslos. Die sichtbare Farbe kommt
 * damit aus dem Token und nicht als Literal aus einer Data-URI — sonst
 * staende hier ein Weiss, das keiner findet, wenn die Palette wechselt.
 */
.wp-block-list:is(.is-style-ml-check, .is-style-ml-check-2, .is-style-ml-check-3) > li::after {
	content: "";
	position: absolute;
	/* (26 - 14) / 2 — der Haken sitzt mittig im Kreis. */
	inset-inline-start: 6px;
	inset-block-start: 6px;
	width: 14px;
	height: 14px;
	background-color: var(--wp--preset--color--white);
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
	mask-size: contain;
	mask-repeat: no-repeat;
	mask-position: center;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-position: center;
}

/*
 * Auf schmalen Umfeldern faellt die Mehrspaltigkeit weg — zwei Spalten zu
 * je 150px sind keine Aufzaehlung mehr. Container-, nicht Fensterbreite:
 * die Liste kann in einer halben Spalte stehen.
 */
@container ml (max-width: 700px) {
	.wp-block-list.is-style-ml-check-2,
	.wp-block-list.is-style-ml-check-3 { columns: 1; }
}

/* ------------------------------------------------- Nummernkreise --------- */

/*
 * Der vierte Listenstil auf `core/list`, Schwester der Haekchenliste (03.10.,
 * Bauauftrag 24). Vorher waren die blauen Kreise fest in S21 verdrahtet: Der
 * Zaehler kam aus `.ml-schritte li::before`, und ausserhalb dieses Bausteins
 * bekam der Redakteur schlichte Zahlen. Die Haekchen waren waehlbar, die
 * Nummernkreise nicht — das hatte niemand entschieden.
 *
 * ZWEI DINGE, DIE EIN BLOCK-STYLE NICHT VON ALLEIN MITBRINGT:
 *
 * 1. Der Zaehler hat seinen eigenen `counter-reset` AM LISTENELEMENT. Sass er
 *    an einem Vorfahren (wie bis dahin `.ml-schritte ol`), zaehlten zwei
 *    Listen auf derselben Seite durch.
 * 2. `list-style: none` nimmt der Liste in Safari die Listensemantik. Der
 *    render_block-Filter `milchland_liste_rolle` in der functions.php traegt
 *    `role="list"` nach — er kennt beide Stile, nicht nur die Haekchen.
 *
 * Die Masse sind die des Entwurfs „Beitragsseite Upcycling": Kreis 26px,
 * Zahl 13px, Text 17px / 1,5, Abstand Kreis zu Text 14px, Abstand der
 * Schritte 20px. Der Kreis ist derselbe Wert wie der Haekchen-Marker, damit
 * die beiden Listen als Paar lesen.
 *
 * Gezaehlt wird mit einem eigenen Zaehler und nicht mit `list-item`: Der
 * Zaehler beginnt immer bei 1. Ein gesetztes `start` am <ol> wird nicht
 * uebernommen.
 */
.wp-block-list.is-style-ml-nummer {
	list-style: none;
	counter-reset: ml-nummer;
	padding-left: 0;
	margin-inline: 0;
	max-width: var(--wp--style--global--content-size);
}

.wp-block-list.is-style-ml-nummer > li {
	counter-increment: ml-nummer;
	position: relative;
	/* Kreis plus Abstand: 26px + 14px. */
	padding-left: calc(var(--wp--custom--anleitung--schritt-nummer) + var(--wp--custom--abstand--label));
	min-height: var(--wp--custom--anleitung--schritt-nummer);
	font-size: var(--wp--custom--ui--size-l);
	line-height: var(--wp--custom--line-height--liste);
}

.wp-block-list.is-style-ml-nummer > li + li {
	margin-top: var(--wp--preset--spacing--gap-s);
}

.wp-block-list.is-style-ml-nummer > li::before {
	content: counter(ml-nummer);
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--wp--custom--anleitung--schritt-nummer);
	height: var(--wp--custom--anleitung--schritt-nummer);
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--meta);
}
/* ------------------------------------------ B02/B03 · Akkordeon und Tabs -- */

/*
 * Beide nutzen Core-Blöcke (WP 6.9 / 7.1). Hier nur die Anpassung an das CD —
 * die Mechanik und die ARIA-Rollen bleiben unangetastet.
 *
 * Zur Spezifitaet: Die Core-Blockstile stehen im <head> VOR dieser Datei
 * (gemessen 28.08.). Gleichstand genuegt hier also. Wo unten trotzdem mehr
 * steht, ist es noetig, weil die Core-Regel selbst schon mehrgliedrig ist —
 * das ist jeweils vermerkt.
 */
.ml-faq {
	--ml-eigenbreite: var(--wp--custom--baustein--lese);
	max-width: var(--wp--custom--baustein--lese);
}

/* S13 (009, Entscheidung 14.10.): Reiter und Inhalt ueber die volle
   Containerbreite wie im Entwurf Milchlandpreis, nicht mehr Lesebreite. */
.ml-tabs {
	--ml-eigenbreite: 100vw;
	max-width: none;
}

/* ---------------------------------------------------- B02 · Eintrag ------ */

/*
 * Kein Kasten, nur eine Trennlinie unten. Der letzte Eintrag behaelt sie —
 * er schliesst den Block sichtbar ab, so steht es im Entwurf.
 */
.ml-faq .wp-block-accordion-item {
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

/*
 * Die Frage. 15px/600 statt der frueheren Ueberschriftengroesse: Der Entwurf
 * behandelt das Akkordeon als Bedienelement, nicht als Textabschnitt.
 * `--wp--custom--ui--size` ist bewusst FEST und skaliert nicht mit dem
 * Viewport — anders als `font-size--body`, das bis 19px waechst und den
 * Schalter danebenstellen wuerde.
 */
.ml-faq .wp-block-accordion-heading__toggle {
	font-family: var(--wp--preset--font-family--nunito);
	font-size: var(--wp--custom--ui--size);
	font-weight: 600;
	letter-spacing: normal;
	gap: var(--wp--preset--spacing--gap-l);
	padding-block: 14px;
	/*
	 * Ohne diese Zeile erbt der Knopf die Zeilenhoehe der h3 darueber — als
	 * Laenge, nicht als Faktor. Gemessen: 35px Zeilenkasten bei 15px Schrift,
	 * die Zeile war damit hoeher als der 28px-Schalter und der Eintrag 63
	 * statt 56 Pixel hoch. 1.3 haelt den Kasten unter der Kreisgroesse, die
	 * Zeilenhoehe des Eintrags kommt dann vom Schalter.
	 */
	line-height: 1.3;
	/*
	 * Ausdruecklich, nicht geerbt. GeneratePress faerbt JEDEN <button> ueber
	 * `generate_advanced_css` (inline, `generate-style-inline-css`):
	 * Ruhe `#55555e`, Hover und Fokus `#3f4047`, Schrift weiss. Der Selektor
	 * dort ist `button:hover` (0,1,1) — unsere (0,3,0) gewinnt, aber nur fuer
	 * die Eigenschaften, die hier auch dastehen. Bis 0.19.12 stand hier nur
	 * `color`, also blieb der fremde Hintergrund stehen: gemessen
	 * `rgb(63,64,71)` mit Markenblau darauf, Kontrast 2,102.
	 */
	background-color: transparent;
	transition: color 0.18s ease, background-color 0.18s ease;
}

/*
 * Hover und Fokus gemeinsam. Getrennt gesetzt hiesse: der fremde Hintergrund
 * kaeme beim Tastaturfokus zurueck — genau das war der Zustand vor 0.19.13
 * (Fokus: `rgb(63,64,71)` auf Weiss, 10,316 — hoher Kontrast, falsche Farbe).
 */
.ml-faq .wp-block-accordion-heading__toggle:hover,
.ml-faq .wp-block-accordion-heading__toggle:focus-visible {
	background-color: transparent;
	color: var(--wp--preset--color--blue);
}

/*
 * Der Fokusrahmen des Schalters kommt aus dem Abschnitt „Fokusrahmen" am
 * Dateiende (3 px, Abstand 3 px, Blau). Er umschliesst die ganze Zeile des
 * Schalters, nicht den Kreis; der Kreisrand (Token `rule`, 1,601 : 1 gegen
 * Getoent) bleibt ein eigener offener Posten.
 */

/*
 * Core unterstreicht den Titel beim Ueberfahren. Der Entwurf faerbt ihn nur.
 * Die Core-Regel ist `.wp-block-accordion-heading__toggle:hover .…__toggle-title`
 * (0,2,0) — mit `.ml-faq` davor liegen wir darueber.
 */
.ml-faq .wp-block-accordion-heading__toggle:hover .wp-block-accordion-heading__toggle-title,
.ml-faq .wp-block-accordion-heading__toggle:focus-visible .wp-block-accordion-heading__toggle-title {
	text-decoration: none;
}

/* ---------------------------------------------------- B02 · Schalter ----- */

/*
 * Core rendert als Schalter ein Textzeichen:
 *
 *   <span class="…__toggle-icon" aria-hidden="true">+</span>
 *
 * Es traegt `aria-hidden`, die Zustandsansage liegt am Knopf (`aria-expanded`).
 * Das Zeichen zu verbergen kostet also nichts an Barrierefreiheit — der
 * Screenreader liest weiterhin „Schaltflaeche, reduziert/erweitert".
 *
 * Aus der Span wird der Kreis, die beiden Balken kommen aus ::before und
 * ::after. `font-size: 0` blendet das „+" aus, ohne es aus dem Baum zu nehmen.
 */
.ml-faq .wp-block-accordion-heading__toggle-icon {
	position: relative;
	flex-shrink: 0;
	width: 28px;
	height: 28px;
	/*
	 * `gray-dark` und nicht das Trennlinien-Token. Der Schalter ist ein
	 * Bedienelement, WCAG 1.4.11 verlangt dafuer 3 : 1 gegen die Flaeche
	 * dahinter. Gemessen mit `rule` #C1C1C1:
	 *
	 *   auf Weiss 1,800 · auf `gray-bg` 1,636 · auf Tint 1,601
	 *
	 * Dreimal durchgefallen. Mit `gray-dark` #7F7F7F: 4,004 · 3,638 · 3,561 —
	 * traegt auf allen drei Sektionsflaechen. Die Trennlinie zwischen den
	 * Eintraegen bleibt `rule`: sie ist Zierde, kein Bedienelement.
	 *
	 * Betrifft nur den GESCHLOSSENEN Zustand. Offen faerbt sich der Kreis
	 * ohnehin auf `blue` — die Regel weiter unten setzt Rand und Flaeche.
	 */
	border: 1.5px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--black);
	font-size: 0;
	transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.ml-faq .wp-block-accordion-heading__toggle-icon::before,
.ml-faq .wp-block-accordion-heading__toggle-icon::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	background-color: currentColor;
	border-radius: 2px;
	transition: opacity 0.18s ease;
}

/* Waagerechter Balken — bleibt in beiden Zustaenden stehen. */
.ml-faq .wp-block-accordion-heading__toggle-icon::before {
	width: 14px;
	height: 2.4px;
	transform: translate(-50%, -50%);
}

/* Senkrechter Balken — verschwindet im offenen Zustand, aus Plus wird Minus. */
.ml-faq .wp-block-accordion-heading__toggle-icon::after {
	width: 2.4px;
	height: 14px;
	transform: translate(-50%, -50%);
}

.ml-faq .wp-block-accordion-item.is-open
	> .wp-block-accordion-heading
	.wp-block-accordion-heading__toggle-icon {
	/*
	 * Core dreht den Schalter im offenen Zustand um 45 Grad — aus dem Plus
	 * wird dort ein Kreuz. Der Entwurf will ein Minus, deshalb muss die
	 * Drehung zurueckgenommen werden; ohne diese Zeile staende der Strich
	 * schraeg. Die Core-Regel liegt bei (0,3,0), diese mit `.ml-faq` bei
	 * (0,4,0) — deshalb steht die Klasse hier ausdruecklich mit im Selektor.
	 */
	transform: none;
	background-color: var(--wp--preset--color--blue);
	border-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

.ml-faq .wp-block-accordion-item.is-open
	> .wp-block-accordion-heading
	.wp-block-accordion-heading__toggle-icon::after {
	opacity: 0;
}

/* ---------------------------------------------------- B02 · Antwort ------ */

/*
 * Der Blockabstand aus theme.json setzt die Antwort 24px unter die Frage.
 * Im Entwurf schliesst sie direkt an — der Abstand nach unten macht die
 * Trennung, nicht der nach oben.
 */
.ml-faq .wp-block-accordion-panel {
	margin-top: 0;
}

.ml-faq .wp-block-accordion-panel :is(p, li) {
	/* 009 (14.10.): Fliesstext (18 bei 1440) statt Bediengroesse 15. */
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--body);
	max-width: 640px;
	/*
	 * Kein eigener Grauton: Die Deckkraft haelt den Text automatisch im
	 * Verhaeltnis zur Flaeche, auf der er steht — auch auf der getoenten und
	 * der grauen Sektionsvariante.
	 */
	opacity: 0.82;
}

.ml-faq .wp-block-accordion-panel > :last-child {
	margin-bottom: 18px;
}

/* ---------------------------------------------------------- B03 · Tabs --- */

/*
 * Der Reiter ist ein <button> ohne eigene Klasse. Bis 0.19.12 stand hier
 * keine Farbe fuer den inaktiven Zustand — er trug deshalb GeneratePress'
 * Knopffarben aus `generate_advanced_css`: Ruhe `rgb(85,85,94)`, Hover und
 * Fokus `rgb(63,64,71)`. Beides sind keine Palettenwerte.
 *
 * Neu, beide aus theme.json:
 *   inaktiv  `gray-dark` #7F7F7F, Schrift schwarz   — Text 5,245
 *   Hover    `black`,             Schrift weiss     — Text 21,000
 *   aktiv    `blue`,              Schrift weiss     — Text 4,907
 *
 * `gray-dark` statt `gray-light`: Die Pille muss sich auch von der Flaeche
 * abheben, auf der sie steht. `gray-light` #C6C6C6 kommt auf Weiss nur auf
 * 1,708 und auf `gray-bg` auf 1,552 — die Pillenform waere dort kaum zu
 * sehen. `gray-dark` traegt auf allen drei Sektionsflaechen ueber 3 : 1
 * (Weiss 4,004 · `gray-bg` 3,638 · Tint 3,561).
 */
.ml-tabs [role="tab"] {
	font-family: var(--wp--preset--font-family--nunito);
	/* 009 (14.10.): 16 px wie der Kicker, nicht mehr die Bediengroesse 15. */
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	/* Bau 44: eigene Zeilenhoehe. Seit die Fliesstext-Zeilenhoehe auch an
	   `button` greift (1.6), waere der Reiter 50,5 -> 52 px hoch geworden. */
	line-height: var(--wp--custom--line-height--bedienung);
	padding: 0.75rem 1.25rem;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--gray-dark);
	color: var(--wp--preset--color--black);
	transition: background-color 0.18s ease, color 0.18s ease;
}

/*
 * Hover und Fokus gemeinsam — sonst kaeme beim Tastaturfokus `rgb(63,64,71)`
 * zurueck. Schwarz und nicht `blue-dark`: Blau ist hier der aktive Zustand,
 * ein blauer Hover auf einem inaktiven Reiter waere nicht zu unterscheiden.
 */
.ml-tabs [role="tab"]:hover,
.ml-tabs [role="tab"]:focus-visible {
	background-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

/*
 * Der aktive Reiter behaelt Blau in jedem Zustand. (0,4,0) gegen (0,3,0)
 * der Regel darueber — ohne diese drei Selektoren wuerde der aktive Reiter
 * beim Ueberfahren schwarz.
 */
.ml-tabs [role="tab"][aria-selected="true"],
.ml-tabs [role="tab"][aria-selected="true"]:hover,
.ml-tabs [role="tab"][aria-selected="true"]:focus-visible {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/* -------------------------------------------------------- 13 · Bild-Slider -- */

/*
 * Der Slider ist der GenerateBlocks-Pro-Karussellblock. Autoplay ist die
 * Vorgabe „aus"; hier nur die Anpassung an das CD.
 */
.ml-slider {
	position: relative;
	/*
	 * Beschneiden mit Rand: siehe „Fokusrahmen" am Dateiende. Hier stand
	 * `overflow-y: hidden` gegen die senkrechte Scrollleiste des Karussells
	 * (der Inhalt ist durch Rundung zwei Pixel hoeher als der Rahmen);
	 * `overflow: clip` kennt keine Scrollleiste.
	 */
}

/*
 * E2 (11.10.): Der Bild-Slider hatte als einziger Baustein KEINE Eigenbreite
 * und lief damit auf die ganze Bahn (1328 bei Fenster 1440) - gemessen 1053 px
 * Hoehe bei 4 : 3. Er steht jetzt auf der Lesebreite wie B02/B03.
 *
 * Der Selektor muss `.ml-block` mitfuehren: S12 (Sektion mit Slider) traegt
 * ebenfalls `ml-slider`, dort aber zusammen mit `ml-section, ml-flaeche` -
 * eine Sektion darf nicht auf 860 gestaucht werden. Die Baustein-Wurzel traegt
 * `ml-block, ml-slider, ml-baustein`, also trifft `.ml-block.ml-slider` nur
 * den Baustein.
 *
 * Mechanik wie bei jedem Baustein: `--ml-eigenbreite` meldet die Grenze an die
 * Bahn-Regel (siehe Abschnitt "Bahn"), `max-width` gilt innerhalb einer
 * Sektion. (0,2,0) ist zugleich noetig, weil GenerateBlocks im Editor
 * `max-width: unset` setzt.
 */
.ml-block.ml-slider {
	--ml-eigenbreite: var(--wp--custom--baustein--lese);
	max-width: var(--wp--custom--baustein--lese);
}

.ml-slider .gb-carousel-pagination {
	display: flex;
	justify-content: center;
	gap: 0.5rem;
	margin-top: var(--wp--preset--spacing--gap-s);
	/*
	 * Nachtrag 11.10. (Schritt 4, M5): Der aktive Punkt ist 10,5 px hoch und
	 * ragte 1,8 px ueber die Unterkante; die Sektion traegt `overflow: clip`,
	 * also wurden Punkt und Fokusrahmen abgeschnitten. Die Vorgabe (Zeile 1758)
	 * nennt 8 px Rand - das ist genau das Token `focus.raum`, das auch den
	 * Abstand des Fokusrahmens traegt. Kein Literal.
	 */
	padding-block: var(--wp--custom--focus--raum);
}

/*
 * 4 : 3 seit 0.22.0 (Entwurf: redaktionelle Motive in Galerie und Karussell,
 * Abgleich 23.09., 4.5). Vorher 3 : 2.
 */
.ml-slider__item img {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

/*
 * 13px/600 nach dem Entwurf (beide Entwuerfe, 01.10.). Die FARBE des
 * Entwurfs wird NICHT uebernommen: #7F7F7F kommt auf Weiss nur auf
 * 4,0041, auf #FAFAFA auf 3,8362 und auf #F1F1F0 auf 3,5428 - alle drei
 * unter 4,5 bei 13px. `text.gedaempft` traegt 5,7418 / 5,5326.
 */
.ml-caption {
	display: block;
	margin-top: 0.75rem;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--custom--text--gedaempft);
}

/* ------------------------------------------------ 13b · Bild mit Unterschrift -- */

/*
 * Bildvariante von S15. Kein eigener Baustein, nur der Platz fuer Bild plus
 * Bildunterschrift - damit die Unterschrift dort genauso sitzt wie bei B05.
 * Eigenbreite wie .ml-video, damit beide Varianten auf oberster Ebene
 * gleich breit stehen.
 * height: auto nach Regel 1 - der Editor-Iframe erbt den Reset nicht.
 */
.ml-media {
	--ml-eigenbreite: var(--wp--custom--baustein--medien);
	max-width: var(--wp--custom--baustein--medien);
}

.ml-media img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--wp--custom--radius--card);
}

/* --------------------------------------------------------------- 14 · Video -- */

.ml-video {
	--ml-eigenbreite: var(--wp--custom--baustein--medien);
	max-width: var(--wp--custom--baustein--medien);
}

.ml-video__title {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 800;
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0 0 0.75rem;
}

.ml-video .wp-block-embed__wrapper {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
}

/*
 * WordPress haelt das Seitenverhaeltnis ueber einen ::before-Platzhalter mit
 * padding-top frei. Zusammen mit aspect-ratio ergibt das die doppelte Hoehe —
 * sichtbar als weisse Flaeche unter dem Video. Einer von beiden muss weg.
 */
.ml-video .wp-block-embed__wrapper::before {
	display: none;
}

.ml-video .wp-block-embed__wrapper iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

/* ---------------------------------------------------------- 15 · CTA-Banner -- */

.ml-cta {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1rem;
	padding: var(--wp--preset--spacing--band);
	border-radius: var(--wp--custom--radius--panel);
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
	text-align: center;
}

.ml-cta__claim {
	font-size: var(--wp--preset--font-size--titel-l);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--section);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0;
	max-width: 22ch;
	color: var(--wp--preset--color--white);
}

.ml-cta__text {
	margin: 0;
	max-width: 52ch;
	color: var(--wp--preset--color--white);
}

.ml-cta .ml-label {
	color: var(--wp--preset--color--white);
	/*
	 * Volle Deckkraft (vorher 0.85, effektiv #D9EAF5, 3,9879 : 1 auf `blue`).
	 * Weiss auf `blue` 4,9073 : 1. `opacity: 1` muss stehen bleiben, sonst
	 * erbt der Kicker die 0.62 der Grundregel .ml-label.
	 */
	opacity: 1;
	margin: 0;
}

/* ------------------------------------------ S14 · Karten-Slider ---------- */

/*
 * Dasselbe Kartendesign wie S04 und S05, nur auf einer Schiene. Die Karten
 * kommen aus einer Abfrage, nicht aus dem Editor.
 *
 * Zum Aufbau: Das Pro-Karussell verlangt `carousel-item` als DIREKTES Kind von
 * `carousel-items` — ein Looper dazwischen ist blocktypseitig verboten.
 * Deshalb tragen Looper und Loop-Item die beiden Karussell-Klassen selbst;
 * das JavaScript sucht ueber genau diese Klassen, teils mit `:scope >`.
 * Wer die Klassen entfernt, bekommt eine stumme Liste statt eines Sliders.
 */
.ml-cardslider {
	position: relative;
	/*
	 * Muss aus dem Stylesheet kommen, sonst legt GenerateBlocks keinen
	 * ResizeObserver an und die Stufung unten verpufft (Regel aus B04).
	 */
	--gb-carousel-slides-per-view: 1;
	--gb-carousel-slide-gap: 24;
}

/*
 * Gestuft nach Containerbreite, nicht nach Fensterbreite — der Slider kann in
 * einer halben Spalte stehen. Die Schwellen sind so gesetzt, dass eine Karte
 * zwischen etwa 280 und 340 Pixel breit bleibt; der Entwurf hat feste 300.
 */
@container ml (min-width: 640px)  { .ml-cardslider { --gb-carousel-slides-per-view: 2; } }
@container ml (min-width: 980px)  { .ml-cardslider { --gb-carousel-slides-per-view: 3; } }
@container ml (min-width: 1240px) { .ml-cardslider { --gb-carousel-slides-per-view: 4; } }

.ml-cardslider__nav {
	display: flex;
	justify-content: flex-end;
	gap: 10px;
	margin-bottom: var(--wp--preset--spacing--gap-l);
}

.ml-slidernav {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	border-radius: var(--wp--custom--radius--pill);
	cursor: pointer;
	transition: background-color 0.18s ease, color 0.18s ease;
}

.ml-slidernav svg {
	width: 16px;
	height: 16px;
}

.ml-slidernav-hell {
	background-color: var(--wp--preset--color--white);
	border: 1.5px solid var(--wp--preset--color--black);
	color: var(--wp--preset--color--black);
}

.ml-slidernav-dunkel {
	background-color: var(--wp--preset--color--black);
	border: none;
	color: var(--wp--preset--color--white);
}

/*
 * Hover und Fokus. Bis 0.19.12 gab es hier gar nichts: Die Grundregeln
 * `.ml-slidernav-hell` / `-dunkel` (0,2,0) setzen `background-color` und
 * schlagen damit GeneratePress' `button:hover` (0,1,1) — der fremde dunkle
 * Balken trat also nie auf, aber es gab auch keinerlei Rueckmeldung beim
 * Ueberfahren. Der Befund vom 19.09. fuehrt das als vom `is-disabled`
 * maskiert; gemessen ist es die Spezifitaet, nicht der Zustand.
 *
 * Richtung wie bei den Buttons: hell wird zu Tinte, dunkel wird zu Blau
 * (dasselbe Muster wie `.ml-btn-ink`).
 *
 * `:not(:disabled)`, weil der Karussellblock beide Knoepfe an den Raendern
 * der Folienreihe auf `disabled` stellt — ein ausgegrauter Knopf darf keine
 * Rueckmeldung geben, die eine Funktion verspricht.
 */
.ml-slidernav-hell:not(:disabled):hover,
.ml-slidernav-hell:not(:disabled):focus-visible {
	background-color: var(--wp--preset--color--black);
	border-color: var(--wp--preset--color--black);
	color: var(--wp--preset--color--white);
}

.ml-slidernav-dunkel:not(:disabled):hover,
.ml-slidernav-dunkel:not(:disabled):focus-visible {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/*
 * Fokusumrandung der Slider-Pfeile: aus dem Abschnitt „Fokusrahmen". GB Pro
 * setzt `[data-carousel-control]:focus-visible { outline: 2px solid
 * currentcolor }` (0,2,0) und laedt NACH components.css; die globale Regel
 * liegt bei (0,2,1) und gewinnt unabhaengig von der Reihenfolge.
 */

/* Ein Pfeil-SVG fuer beide Richtungen — zurueck ist derselbe, gedreht. */
.ml-slidernav-hell svg {
	transform: rotate(180deg);
}

/*
 * Damit alle Karten einer Reihe gleich hoch stehen. (0,2,0) seit 009: die
 * Karussellregel von GB Pro `.gb-carousel-item { height: 100% }` hat dieselbe
 * Spezifitaet wie die einfache Klasse, steht spaeter und gewann - eine
 * Prozenthoehe verhindert das Strecken in der Bahn (gemessen 415 / 439 px in
 * einer Reihe, Folie `display: block`). Mit der Stufe mehr streckt die Bahn
 * jede Folie auf die hoechste, die Karte fuellt sie.
 */
.ml-cardslider .ml-cardslider__item {
	display: flex;
	height: auto;
}

.ml-cardslider__item > .ml-card {
	width: 100%;
}

/* ------------------------------------------ B07 · Ansprechpartner -------- */

/*
 * Kuhflecken hinter der Ansprechpartner-Sektion (Entwurf, Zeilen 229-230).
 * Eigene Token, NICHT die des Seitenkopfs: der Entwurf setzt hier 680px,
 * top -100, right -200 und Deckkraft 0,05 gegen 640px / -120 / -180 / 0,06
 * im Seitenkopf. Dasselbe Motiv, andere Werte.
 */
.ml-ansprech {
	position: relative;
	overflow: hidden;
}

.ml-ansprech__flecken {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	overflow: hidden;
	pointer-events: none;
}

/*
 * Seit 002 traegt die Huelle das Motiv als Maske (`::before`); das alte
 * Inline-SVG ist seit 017 aus Muster und Inhalten entfernt. Quadratisches Feld,
 * Motiv ganz (`contain`), oben links im Feld - wie der Entwurf.
 */

.ml-ansprech__flecken::before {
	content: "";
	position: absolute;
	top: var(--wp--custom--ansprech--flecken-oben);
	right: var(--wp--custom--ansprech--flecken-rechts);
	width: var(--wp--custom--ansprech--flecken-groesse);
	height: var(--wp--custom--ansprech--flecken-groesse);
	background-color: var(--wp--preset--color--black);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: contain;
	-webkit-mask-size: contain;
	mask-repeat: no-repeat;
	-webkit-mask-repeat: no-repeat;
	opacity: var(--wp--custom--ansprech--flecken-deckkraft);
}

.ml-ansprech > .ml-container {
	position: relative;
	z-index: 1;
}

/*
 * Seit 0.22.0 ohne Bild (Entscheidung Auftraggeber 23.09.: "alle ohne Bilder,
 * keine Silhouetten"; Entwurf: "Kontaktkarten fuehren kein Bild mehr").
 * Bildrahmen, seine fuenf Varianten und die Silhouetten-Regeln sind entfallen.
 *
 * Festes Vierer-Raster aus dem Entwurf, Abschnitt 05 — kein `auto-fit`: Bei
 * weniger als vier Personen bleiben Spalten leer, die Karten stehen links.
 * `minmax(0, 1fr)` statt `1fr` ist Absicht: `1fr` heisst `minmax(auto, 1fr)`,
 * und eine lange E-Mail-Adresse wuerde ihre Spalte sonst aufweiten.
 * Umbrueche am Viewport wie im Entwurf: 2 Spalten bis 1080, 1 bis 640.
 */
.ml-team {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--gap-l);
}

/*
 * Umbrueche als Container Query (0.23.0) — B07 ist ein Baustein und darf in
 * einer Spalte stehen. Zwei Faelle, weil der naechste Container `ml` je nach
 * Ort verschieden breit ist:
 *
 *   in einer Sektion / Spalte: Container = Inhaltsbreite. Die Entwurfswerte
 *   1080 / 640 px Viewport minus 2 x Rand (44,0 / 29,3 px) = 992,0 / 581,3 px.
 *   Schwellen 992.5 und 582 statt glatt 992 / 580: Bei 1080 px Fenster ist der
 *   Container 992,007 px breit, bei 1081 px 992,93 - nur 992.5 trennt beide
 *   wie das Viewport-Raster aus 0.22.0. Ebenso 640 -> 581,3 und 641 -> 582,3.
 *   auf oberster Ebene: Container = .entry-content = volle Fensterbreite,
 *   dort gelten die Entwurfswerte 1080 / 640 unmittelbar.
 *
 * Die Wurzelregel ist spezifischer (0,2,0) und gewinnt, wo beide greifen.
 *
 * Seit 026 ist B07 ein Abfrage-Block: `.ml-team` sitzt am Looper, eine Ebene
 * unter `.ml-team-abfrage`. Die Wurzelregel nennt beide Formen; die statische
 * Form bleibt fuer Inhalte, die noch nicht umgestellt sind.
 */
@container ml (max-width: 992.5px) {
	.ml-team { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@container ml (max-width: 582px) {
	.ml-team { grid-template-columns: minmax(0, 1fr); }
}

@container ml (max-width: 1080px) {
	:is(.entry-content, .is-root-container, .gb-is-root-block) > .ml-team,
	:is(.entry-content, .is-root-container, .gb-is-root-block) > .ml-team-abfrage > .ml-team { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@container ml (max-width: 640px) {
	:is(.entry-content, .is-root-container, .gb-is-root-block) > .ml-team,
	:is(.entry-content, .is-root-container, .gb-is-root-block) > .ml-team-abfrage > .ml-team { grid-template-columns: minmax(0, 1fr); }
}

/*
 * Aufbau nach dem Entwurf "Uebersichtsseite Qualitaet", Zeilen 241-252:
 * weisse Flaeche, NUR die blaue Oberkante, kein Rand ringsum, kein Radius.
 * Die drei Seitenraender und der Radius sind mit 0.39.0 entfallen - auf der
 * grauen Sektionsflaeche traegt ein 1px-Rand in #E8E8E8 ohnehin nicht
 * (gerechnet 1,0841).
 */
.ml-team__card {
	display: flex;
	flex-direction: column;
	padding: var(--wp--custom--ansprech--polster-oben) var(--wp--custom--ansprech--polster-seite) var(--wp--custom--ansprech--polster-unten);
	background-color: var(--wp--preset--color--white);
	border-top: 2px solid var(--wp--preset--color--blue);
}

.ml-team__name {
	font-family: var(--wp--preset--font-family--nunito);
	font-size: var(--wp--custom--ansprech--name);
	font-weight: 900;
	line-height: var(--wp--custom--ansprech--name-zeile);
	letter-spacing: var(--wp--custom--ansprech--name-sperrung);
	margin: 0 0 8px;
}

/*
 * Funktionsbezeichnung: im Markup VOR dem Namen, nicht per `order` - die
 * DOM-Reihenfolge ist die Vorlesereihenfolge.
 * Farbe `blue-dark` statt des Markenblaus der Vorlage: im selben Abschnitt
 * steht darueber der Kicker in `blue-dark`, zwei verschiedene Blau
 * uebereinander waeren Zufall. Gerechnet 7,2979 auf Weiss.
 */
.ml-team__role {
	font-size: var(--wp--preset--font-size--label-s);
	font-weight: 700;
	line-height: 1.35;
	color: var(--wp--preset--color--blue-dark);
	margin: 0 0 14px;
}

.ml-team__deg {
	font-size: var(--wp--preset--font-size--card);
	line-height: 1.5;
	color: var(--wp--custom--text--gedaempft);
	margin: 0 0 22px;
}

.ml-team__contact {
	display: flex;
	flex-direction: column;
	gap: 9px;
	/* Schiebt den Kontaktblock an die Unterkante, damit die Karten fluchten. */
	margin-top: auto;
	padding-top: 20px;
	border-top: 1px solid var(--wp--preset--color--rule);
}

.ml-team__link {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: var(--wp--custom--ui--size);
	font-weight: 600;
	color: var(--wp--preset--color--black);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.ml-team__link:hover {
	color: var(--wp--preset--color--blue);
}

/*
 * Die beiden Symbole als Maske statt als Bild — wie beim Haekchen: nur der
 * Alphakanal zaehlt, die Farbe kommt aus dem Token.
 */
.ml-team__link::before {
	content: "";
	flex-shrink: 0;
	width: 15px;
	height: 15px;
	background-color: var(--wp--preset--color--blue);
	mask-size: contain;
	mask-repeat: no-repeat;
	mask-position: center;
	-webkit-mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-position: center;
}

.ml-team__link-tel::before {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.9.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E");
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.9.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E");
}

.ml-team__link-mail::before {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m22 7-10 6L2 7'/%3E%3C/svg%3E");
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m22 7-10 6L2 7'/%3E%3C/svg%3E");
}

/* ------------------------------------------- S07 · Banner-Layout --------- */

/*
 * Zweite Aufteilung desselben Elements: Text links, Button rechts. Sie kommt
 * ueber `data-layout`, nicht ueber `data-variante` — die Variante regelt die
 * Farbe, das Layout die Anordnung. Beides in einen Schalter zu legen haette
 * „blau" und „Banner" zu Alternativen gemacht, die sich gegenseitig
 * ausschliessen; sie sind aber frei kombinierbar.
 *
 * Ohne Angabe gilt die mittige Fassung. Bestehende Instanzen tragen kein
 * `data-layout` und bleiben deshalb unveraendert — es gibt nichts zu migrieren.
 *
 * Das Markup ist in beiden Faellen dasselbe: vier Geschwister, flach. Statt
 * einen Textblock einzuziehen, werden die drei Textkinder per `grid-column`
 * in die erste Spalte gelegt und der Button in die zweite. Damit laesst sich
 * die Aufteilung im Editor umschalten, ohne den Block neu einzufuegen.
 */
.ml-cta[data-layout="banner"] {
	position: relative;
	overflow: hidden;
	display: grid;
	grid-template-columns: 1.4fr auto;
	/*
	 * Drei AUSDRUECKLICHE Zeilen, obwohl die drei Textkinder sie auch implizit
	 * erzeugen wuerden. Grund: `grid-row: 1 / -1` am Button zaehlt bis zum Ende
	 * des expliziten Rasters. Ohne diese Zeile gibt es keins, `-1` faellt auf
	 * Linie 1 zurueck, und der Button steht in Zeile 1 statt ueber alle drei —
	 * gemessen: er klebte oben neben dem Kicker statt mittig neben dem Text.
	 *
	 * Der senkrechte Rhythmus liegt deshalb als `margin-bottom` an den
	 * Textkindern und nicht als `row-gap`: Kicker und Text sind laut Vorlage
	 * optional, und eine leere Rasterzeile darf keinen Abstand hinterlassen.
	 */
	grid-template-rows: repeat(3, auto);
	/* 56px ist ein Strukturmass aus dem Entwurf, kein Abstands-Token. */
	column-gap: 56px;
	row-gap: 0;
	align-items: center;
	padding: 64px 56px;
	text-align: start;
}

.ml-cta[data-layout="banner"] > .ml-label     { grid-area: 1 / 1; margin-bottom: 16px; }
.ml-cta[data-layout="banner"] > .ml-cta__claim { grid-area: 2 / 1; margin-bottom: 16px; }
.ml-cta[data-layout="banner"] > .ml-cta__text  { grid-area: 3 / 1; }

.ml-cta[data-layout="banner"] > :is(.ml-label, .ml-cta__claim, .ml-cta__text) {
	justify-self: start;
}

.ml-cta[data-layout="banner"] > .ml-btn {
	grid-column: 2;
	grid-row: 1 / -1;
	align-self: center;
	white-space: nowrap;
}

/*
 * Im Banner-Layout ist die Aussage kleiner als in der mittigen Fassung —
 * 40px im Entwurf, weil daneben noch der Button Platz braucht.
 */
.ml-cta[data-layout="banner"] .ml-cta__claim {
	/*
	 * 40px im Entwurf. Die Schriftskala hat dort eine Luecke — `titel-m`
	 * endet bei 22px, `titel-l` beginnt bei 34 und laeuft bis 68. Deshalb ein
	 * eigener Token, der bei 40 deckelt statt eines Literals.
	 */
	font-size: var(--wp--custom--ui--claim);
	line-height: var(--wp--custom--ui--claim-line-height);
	max-width: none;
}

.ml-cta[data-layout="banner"] .ml-cta__text {
	font-size: var(--wp--custom--ui--size-l);
	max-width: 620px;
}

/*
 * Kuhflecken oben rechts, Deckkraft 0.12.
 *
 * Kein `filter: invert(1)` mehr. Der Entwurf invertiert eine dunkle PNG, um
 * sie auf blauem Grund hell zu bekommen — das bindet die Farbe an die Datei.
 * Als Maske traegt die Grafik nur noch die Form, die Farbe kommt aus einem
 * Token. Dieselbe Mechanik wie bei den Haken und den Kontaktsymbolen.
 */
.ml-cta[data-layout="banner"]::before {
	content: "";
	position: absolute;
	top: -80px;
	inset-inline-end: -120px;
	width: 520px;
	height: 520px;
	background-color: var(--wp--preset--color--white);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: contain;
	-webkit-mask-size: contain;
	mask-repeat: no-repeat;
	-webkit-mask-repeat: no-repeat;
	opacity: 0.12;
	pointer-events: none;
}

/* Der Inhalt liegt ueber dem Untergrund. */
.ml-cta[data-layout="banner"] > * {
	position: relative;
	z-index: 1;
}

/*
 * Der Button ist im Banner weiss auf Blau — im mittigen Layout ist er
 * schwarz. Deshalb hier und nicht an `.ml-btn-ink`, das anderswo stimmt.
 */
.ml-cta[data-layout="banner"] > .ml-btn {
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--blue);
	border-radius: var(--wp--custom--radius--pill);
}

.ml-cta[data-layout="banner"][data-variante="tint"] > .ml-btn {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/*
 * Unter 780px steht der Button unter dem Text statt daneben — 1,4fr auf
 * 300px waere keine Aufteilung mehr. Containerbreite, damit das Element
 * auch in einer Spalte richtig reagiert.
 */
@container ml (max-width: 780px) {
	.ml-cta[data-layout="banner"] {
		grid-template-columns: 1fr;
		/* Vier Zeilen: die drei Texte, darunter der Button. */
		grid-template-rows: repeat(4, auto);
		padding: var(--wp--preset--spacing--band);
	}
	.ml-cta[data-layout="banner"] > .ml-btn {
		grid-area: 4 / 1;
		justify-self: start;
		margin-top: 1rem;
	}
}

.ml-cta[data-variante="schwarz"] {
	background-color: var(--wp--preset--color--black);
}

.ml-cta[data-variante="tint"] {
	background-color: var(--wp--preset--color--blue-tint);
	color: var(--wp--preset--color--black);
}

.ml-cta[data-variante="tint"] :is(.ml-cta__claim, .ml-cta__text) {
	color: var(--wp--preset--color--black);
}

/*
 * Der getoente CTA ist die einzige helle Flaeche unter den CTA-Varianten —
 * hier gilt dieselbe Rechnung wie bei der Grundregel. `gray-dark` lag auf
 * Tint bei 3,561, und die 0.85 aus `.ml-cta .ml-label` druecken den Wert
 * zusaetzlich. Schwarz bei 0.62 ergibt 5,985.
 */
.ml-cta[data-variante="tint"] .ml-label {
	color: var(--wp--preset--color--black);
	opacity: 0.62;
}

/* -------------------------------------------------------- 16 · Bildergalerie -- */

/* 4 : 3 seit 0.22.0, wie der Bild-Slider (Abgleich 23.09., 4.5). Vorher 3 : 2. */
.ml-gallery img {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

/* ---------------------------------------------------------- 17 · Zahlenleiste -- */

.ml-stats {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--wp--preset--spacing--gap-l);
}

.ml-stat {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

/* Werte aus dem Magazin-Entwurf: 40 px Zahl, 14 px Bezeichnung, 11 px Zusatz. */
.ml-stat__num {
	font-size: 40px;
	font-weight: 900;
	line-height: 1;
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--preset--color--white);
}

/*
 * AUF MARKENBLAU GIBT ES NUR VOLLES WEISS (seit 0.30.0). Gedaempftes Weiss
 * erreicht auf `blue` hoechstens 4,5 : 1 bei 93,62 % Deckkraft — der
 * Spielraum ist so klein, dass jede Abstufung entweder durchfaellt oder nicht
 * zu sehen ist. Vorher: Zusatzzeile 0,8 (3,7105), Bezeichnung 0,95 (4,5861),
 * CTA-Text im Banner 0,92 (4,4005). Die Rangfolge auf blauer Flaeche entsteht
 * ueber Groesse und Schnitt (40 px / 900, 14 px / 700, meta / 600), nicht
 * ueber Deckkraft. Weiss auf `blue`: 4,9073 : 1.
 */
.ml-stat__label {
	font-size: 14px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--wp--preset--color--white);
}

.ml-stat__note {
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--preset--color--white);
}

@media (max-width: 782px) {
	.ml-stats { grid-template-columns: repeat(2, 1fr); }
}

/* --------------------------------------- Übersichtsseite: Zwischenköpfe -- */

/*
 * BEWUSSTE AUSNAHME von der Token-Regel dieser Datei — mit Absicht, nicht
 * aus Nachlässigkeit.
 *
 * Die Zwischenköpfe der Kundenübersicht sind Hilfstext und gehören
 * ausdrücklich NICHT zum Corporate Design. Sie müssen sich auf den ersten
 * Blick von jedem Inhaltselement unterscheiden. Genau deshalb steht hier ein
 * Signalgelb, das in der Milchland-Palette nicht vorkommt und dort auch nie
 * vorkommen wird: nähme man Blau oder Grau aus den Tokens, sähe der Hilfstext
 * aus wie eine Hinweisbox und würde in der Abnahme mitdiskutiert.
 *
 * Diese Klassen werden in keinem der 17 Elemente verwendet. Sie leben nur auf
 * der Übersichtsseite und verschwinden mit ihr.
 *
 * Kontraste geprüft: #7A5600 auf Weiß 6,6:1 · #5C4200 auf #FFF6DC 8,7:1.
 */

.ml-spec {
	position: relative;
	max-width: 1360px;
	margin: 0 auto;
	padding: 1.75rem 1.75rem 1.5rem;
	border: 2px dashed #7A5600;
	border-left: 10px solid #7A5600;
	border-radius: 6px;
	background-color: #FFF6DC;
	/* Feine Schraffur — signalisiert „Arbeitsstand", nicht „fertige Seite". */
	background-image: repeating-linear-gradient(
		135deg,
		rgba(122, 86, 0, 0.045) 0 8px,
		transparent 8px 18px
	);
}

/*
 * Zeiger an der Unterkante: zeigt auf das Element, das erklärt wird. Zusammen
 * mit dem großen Abstand darüber ist die Zuordnung ohne Nachdenken lesbar.
 */
.ml-spec::before {
	content: "";
	position: absolute;
	left: 2.5rem;
	bottom: -11px;
	width: 20px;
	height: 20px;
	transform: rotate(45deg);
	background-color: #FFF6DC;
	border-right: 2px solid #7A5600;
	border-bottom: 2px solid #7A5600;
}

.ml-spec__num {
	display: inline-block;
	padding: 5px 12px;
	border-radius: 3px;
	background-color: #7A5600;
	color: #FFFFFF;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 900;
	letter-spacing: var(--wp--custom--tracking--pill);
	text-transform: uppercase;
	margin: 0 0 0.75rem;
}

.ml-spec__title {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	letter-spacing: var(--wp--custom--tracking--display);
	color: #5C4200;
	margin: 0 0 0.35rem;
}

.ml-spec__desc {
	margin: 0 0 0.75rem;
	color: #5C4200;
}

/*
 * Ein Link im Erklaerkasten erbt die Kastenfarbe, er bekommt keine eigene.
 *
 * Gemessen am 28.09.: ohne diese Regel greift GeneratePress' Standard-Linkfarbe
 * `#1E73BE` = `rgb(30,115,190)`. Das ist weder ein Palettenwert noch die
 * Farbwelt des Kastens, und der Kontrast gegen die Kastenflaeche
 * `rgb(255,246,220)` liegt bei **4,5795** — ueber AA, aber ohne Polster.
 *
 * `inherit` statt eines eigenen Werts: Der Erklaerkasten fuehrt seine drei
 * Brauntoene bewusst ausserhalb der Palette (siehe Bauvorlage Teil D und
 * `vorgabe-titelsatz.md` 5). Ein Markenblau waere hier der Fremdkoerper, und
 * ein vierter Literalwert waere einer zu viel. Geerbt sind es **8,7130**.
 *
 * Die Unterstreichung bleibt — sie ist das einzige Merkmal, das den Link von
 * Text unterscheidet, sobald die Farbe dieselbe ist.
 */
.ml-spec a {
	color: inherit;
	text-decoration: underline;
}

.ml-spec__limits {
	display: inline-block;
	margin: 0;
	padding: 0.4rem 0.7rem;
	border-radius: 3px;
	background-color: rgba(122, 86, 0, 0.13);
	font-size: var(--wp--preset--font-size--card);
	font-weight: 700;
	color: #5C4200;
	font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
	.ml-spec::after {
		right: 0.75rem;
		font-size: 9px;
	}
}

.ml-lead {
	max-width: 760px;
	/* Linksbündig — „auto" hat den Vorspann früher in die Seitenmitte geschoben. */
	margin: 1rem 0 0;
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 400;
	line-height: 1.45;
}

/* ==========================================================================
   Hauptnavigation und Mega-Menue (0.19.0)

   Die handgebaute <ul> im Kopfzeilen-Pattern ist durch den Navigations-Stack
   von GenerateBlocks Pro ersetzt: navigation > menu-container > classic-menu.
   classic-menu rendert das WordPress-Menue "Hauptnavigation" und gibt seine
   globalClasses an die erzeugte <ul> weiter - .ml-nav sitzt also weiterhin
   auf der Liste.

   LADEREIHENFOLGE, umgekehrt zu Regel 7: GB Pro reiht
   dist/classic-menu-style.css erst beim Rendern des Blocks ein, also NACH
   milchland-components.css. Bei gleicher Spezifitaet gewinnt damit das
   Plugin - anders als bei den Core-Blockstilen. Deshalb traegt hier jede
   Regel, die gegen eine Plugin-Regel steht, die Kette .ml-header davor
   (0,2,0) statt einer blossen Klasse (0,1,0).
   ========================================================================== */

.ml-nav-root {
	display: flex;
	align-items: center;
}

/* ------------------------------------------------------- Menue, Desktop -- */

.ml-header .ml-nav {
	display: flex;
	align-items: center;
	gap: 1.75rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ml-header .ml-nav .gb-menu-item {
	position: relative;
}

/*
 * Im Modus "click" haengt GB Pro den Umschalter an das <a> selbst und ruft
 * preventDefault(). Der Punkt mit Mega-Menue fuehrt also NICHT mehr auf seine
 * Seite - darum steht der Einstieg als erster Eintrag im Panel.
 */
.ml-header .ml-nav .gb-menu-link {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	font-size: var(--wp--custom--header--nav);
	font-weight: 700;
	color: var(--wp--preset--color--black);
	text-decoration: none;
	cursor: pointer;
	transition: font-size 0.25s ease, color 0.2s ease;
}

.ml-header.gb-is-sticky .ml-nav .gb-menu-link {
	font-size: var(--wp--custom--header--nav-sticky);
}

.ml-header .ml-nav .gb-menu-link:hover,
.ml-header .ml-nav .gb-menu-link:focus-visible,
.ml-header .ml-nav .menu-item-has-gb-mega-menu > a[aria-expanded="true"] {
	color: var(--wp--preset--color--blue);
}

.ml-header .ml-nav .gb-submenu-toggle-icon {
	width: 0.7em;
	height: 0.7em;
	transition: transform 0.2s ease;
}

/*
 * Aufklappliste fuer Punkte OHNE Mega-Menue. Heute traegt nur Milchexperten
 * Unterpunkte, und dort blendet GB Pro die Liste mit !important aus -
 * das Panel tritt an ihre Stelle. Die Regel steht fuer den naechsten Punkt,
 * der Unterpunkte bekommt, ohne ein Panel zu verdienen.
 */
.ml-header .ml-nav .gb-sub-menu {
	min-width: var(--wp--custom--header--dropdown-width);
	margin: 0;
	padding: 0.5rem 0;
	list-style: none;
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--panel);
	box-shadow: 0 8px 24px color-mix(in srgb, var(--wp--preset--color--black) 10%, transparent);
	z-index: 10;
}

.ml-header .ml-nav .gb-sub-menu .gb-menu-link {
	display: block;
	padding: 0.5rem 1rem;
	font-size: var(--wp--custom--ui--size);
	font-weight: 600;
}

/* ------------------------------------------------ Warenkorb (031) ----- */

/*
 * Link mit Einkaufstasche und Zahl (`milchland_warenkorb_kopf`), zwei
 * Fundstellen, je Ansicht eine: bis 1024 (Schaltpunkt des Menueknopfs)
 * `.ml-warenkorb--mobil` vor dem Knopf, gleich gross (40 x 40); darueber
 * `li.ml-warenkorb-eintrag` als letzter Menuepunkt (Abstand wie die
 * Menuepunkte, 28 hoch). Im HTML `hidden`, sichtbar nur mit Artikeln
 * (warenkorb-kopf.js). Farbe wie Menuelinks, Hover/Fokus blau; Fokusrahmen
 * global (A11). Zahl im Kreis: Grund `blue`, Schrift weiss 700 (4,91 : 1).
 */
.ml-warenkorb {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	color: var(--wp--preset--color--black);
	text-decoration: none;
}

:is(.ml-warenkorb, .ml-warenkorb-eintrag)[hidden] {
	display: none;
}

.ml-warenkorb:hover,
.ml-warenkorb:focus-visible {
	color: var(--wp--preset--color--blue);
}

.ml-warenkorb__symbol {
	width: 24px;
	height: 24px;
}

.ml-warenkorb__zahl {
	position: absolute;
	top: 0;
	right: -2px;
	min-width: 18px;
	height: 18px;
	padding: 0 4px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
	font-size: 11px;
	font-weight: 700;
	line-height: 18px;
	text-align: center;
}

.ml-header .ml-nav .ml-warenkorb--menue {
	width: 32px;
	height: 28px;
}

.ml-warenkorb--menue .ml-warenkorb__symbol {
	width: 22px;
	height: 22px;
}

.ml-warenkorb--menue .ml-warenkorb__zahl {
	top: -6px;
	right: -8px;
}

@media (min-width: 1025px) {
	.ml-warenkorb--mobil {
		display: none;
	}

	/* Nur in der breiten Ansicht sichtbar (sonst stuende er im aufgeklappten
	   Mobilmenue); `:not([hidden])`, damit `hidden` gilt (Stolperstelle 159). */
	.ml-header .ml-nav .ml-warenkorb-eintrag:not([hidden]) {
		display: flex;
		align-items: center;
	}
}

/* Ausgleich bis 1279 (031, Pruefung 1): Mit Warenkorb ruecken die Menuepunkte
   enger (18 statt 28), die Tasche ist 24 breit — die Navigation wird nicht
   breiter als ohne Warenkorb: kein zusaetzlicher Umbruch, Logo nicht schmaler
   (gemessen 1025-1320 in 5er-Schritten). */
@media (min-width: 1025px) and (max-width: 1279px) {
	.ml-header .ml-nav:has(> .ml-warenkorb-eintrag:not([hidden])) {
		gap: 1.125rem;
	}

	.ml-header .ml-nav .ml-warenkorb--menue {
		width: 24px;
	}

	.ml-warenkorb--menue .ml-warenkorb__zahl {
		right: -9px;
	}
}

@media (max-width: 1024px) {
	.ml-header .ml-warenkorb-eintrag {
		display: none;
	}
}

/* ------------------------------------------------------- Mobilschalter -- */

/*
 * Der Navigationsblock blendet den Schalter oberhalb von
 * data-gb-mobile-breakpoint selbst aus - ueber eine Regel auf
 * .gb-navigation-<uniqueId>. Hier steht nur das Aussehen.
 */
.ml-nav-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.5rem;
	background: none;
	border: 0;
	color: var(--wp--preset--color--black);
	cursor: pointer;
}

/* ----------------------------------------------------- Mega-Menue-Panel -- */

/*
 * Das Panel ist ein Overlay-Panel vom Typ mega-menu. GB Pro behandelt es
 * intern als "anchored", stellt es per JavaScript unter den Menuepunkt und
 * gibt ihm bei width_mode=full die volle Fensterbreite (100vw). Die
 * Begrenzung auf das Seitenraster macht deshalb der Inhalt, nicht das Panel.
 */
/*
 * 019: Mega-Panel buendig an der Kopfunterkante. GB Pro setzt das Panel mit
 * `transform: translate(x, <ganze Zahl>px)` relativ zum Menuepunkt. Der stand,
 * mittig in der 128/72 px hohen Kopfzeile, auf einer Bruchkante (28,797 px hoch
 * -> oben 89,594), das Panel landete 0,406 px zu hoch (168,594 statt 169,
 * 72,594 statt 73). Mit ganzzahliger Hoehe steht er auf 90/22, das Panel auf
 * 169/73. Die Links ruecken um 0,4 px. Erst ab 1200 px: darunter brechen die
 * Menuepunkte zweizeilig um, dort darf die Hoehe nicht fest sein.
 */
@media (min-width: 1200px) {
	.ml-header .gb-menu-container:not(.gb-menu-container--mobile) .gb-menu--base > .menu-item {
		height: 28px;
	}
}

.menu-item-has-gb-mega-menu .gb-overlay--anchored .gb-overlay__content {
	background-color: var(--wp--preset--color--white);
	border-bottom: 1px solid var(--wp--preset--color--rule);
	box-shadow: 0 16px 32px color-mix(in srgb, var(--wp--preset--color--black) 8%, transparent);
}

.ml-mega {
	width: 100%;
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	/*
	 * Oben knapper als unten: das Panel soll an der Kopfzeile haengen, nicht
	 * unter ihr schweben. 48 px oben wirkten losgeloest (gemessen 48 px
	 * zwischen Kopfzeilenkante und Ankerzeile), 0 klebte die Ankerzeile seit
	 * 005 an die Kopfzeilenlinie. Seit 006: 24 px (gap-l), Marc 13.10. nach
	 * Bildvergleich 0 / 24 / 48. Mobil gilt die eigene Regel weiter unten.
	 */
	padding-block: var(--wp--preset--spacing--gap-l) var(--wp--preset--spacing--band);
	padding-inline: var(--wp--preset--spacing--rand);
	display: grid;
	/*
	 * Gemessen am 18.09.: mit minmax(200px, 1fr) wurden die zwei Spalten bei
	 * 1440 je 612 px breit - eine Linkliste in Plakatbreite. Die Obergrenze
	 * haelt sie auf Lesebreite, justify-content setzt sie nach links an die
	 * Kante des Seitenrasters statt sie zu verteilen.
	 */
	grid-template-columns: repeat(auto-fit, minmax(200px, 260px));
	justify-content: start;
	/*
	 * Zeilen- und Spaltenabstand getrennt: zwischen den Saeulen bleiben 48 px
	 * (sektion waere hier 120 px gewesen - gemessen und verworfen), zwischen
	 * der Ankerzeile und den Saeulen sind es 24. Damit rueckt der ganze Block
	 * unter der Trennlinie um 24 px nach oben.
	 */
	column-gap: var(--wp--preset--spacing--band);
	row-gap: var(--wp--preset--spacing--gap-l);
}

/*
 * Der Spaltenkopf setzt auf .ml-label auf (Nunito, 700, gray-dark) und
 * korrigiert nur die Groesse: der Entwurf setzt den Kopf der Aufklappliste
 * auf 13 px, nicht auf die 14 der Fusszeilen-Spaltenkoepfe. Die Groesse steht
 * an der Klassenkette, nicht an einem Typselektor - Regel 7.
 */
.ml-mega .ml-mega-col__kopf {
	/*
	 * 18.09.: erst von 13 auf 16 px und in Markenblau, dann eine Stufe weiter
	 * auf den Karten-H3-Token. Der laeuft ueber clamp() mit 18 px auf schmalen
	 * und 22 px ab 1440 - dieselbe Ebene, die auch eine Kartenueberschrift
	 * traegt, und damit eine klare Stufe ueber den 15-px-Links.
	 */
	font-size: var(--wp--preset--font-size--titel-m);
	color: var(--wp--preset--color--blue);
	/* 22 px bei 700 — grosser Text, 3 : 1 reicht. Eigene Farbe, volle Deckkraft. */
	opacity: 1;
	margin-bottom: 0.75rem;
}

.ml-mega .ml-mega-liste {
	display: grid;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ml-mega .ml-mega-liste a {
	font-size: var(--wp--custom--ui--size);
	font-weight: 600;
	line-height: 1.35;
	color: var(--wp--preset--color--black);
	text-decoration: none;
	transition: color 0.2s ease;
}

.ml-mega .ml-mega-liste a:hover,
.ml-mega .ml-mega-liste a:focus-visible {
	color: var(--wp--preset--color--blue);
}

/*
 * Die "Uebersicht" jeder Saeule steht in der normalen Textfarbe - blau ist
 * jetzt der Saeulenkopf, und zwei blaue Ebenen uebereinander nehmen dem Kopf
 * seine Wirkung. Hervorgehoben bleibt sie ueber das Schriftgewicht.
 */
.ml-mega .ml-mega-liste__top a {
	font-weight: 800;
	color: var(--wp--preset--color--black);
}

/* ------------------------------------------------------------- Mobil -- */

/*
 * Im aufgeklappten Mobilmenue stellt GB Pro das Panel statisch
 * (position: static !important). Der Panelinhalt steht dort inline im Menue
 * und IST damit die Aufklappliste - die echten Untermenuepunkte blendet das
 * Plugin bei einem Mega-Menue-Punkt ueberall mit !important aus.
 * Deshalb hier nur Rahmen und Flaeche zuruecknehmen, nicht umbauen.
 */
.gb-menu-container--mobile .ml-mega {
	grid-template-columns: 1fr;
	padding-inline: 0;
	padding-block: 0 var(--wp--preset--spacing--gap-l);
}

.gb-menu-container--mobile .menu-item-has-gb-mega-menu .gb-overlay__content {
	background-color: transparent;
	border: 0;
	box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
	.ml-header .ml-nav .gb-menu-link,
	.ml-header .ml-nav .gb-submenu-toggle-icon,
	.ml-mega .ml-mega-liste a {
		transition: none;
	}
}

/* ===== ml-mobilmenue-block =================================================
   Mobiles Menue - Vollbild unter der Kopfzeile.

   BEFUND 18.09.: Der Navigationsblock bringt sein Mobil-Layout ueber die im
   Editor gesetzten Block-Styles mit, nicht ueber eine statische Plugin-Regel.
   Unsere Kopfzeile ist ueber einen Blockspec ohne "styles" gebaut - der
   Container blieb deshalb im Fluss (position: static) und die Menueliste lief
   als Flex-Zeile ueber den Rand. Gemessen bei 390 px: 650 px Ueberlauf,
   mit geoeffnetem Panel 911 px.
   ========================================================================= */

.ml-header .gb-menu-container--mobile {
	position: fixed;
	inset: 0;
	padding-block: calc(var(--wp--custom--header--height) + var(--wp--preset--spacing--gap-l)) var(--wp--preset--spacing--band);
	padding-inline: var(--wp--preset--spacing--rand);
	background-color: var(--wp--preset--color--white);
	overflow-y: auto;
	z-index: 100;
}

/* Zwischen 769 und 1024 ist der Kopf sticky und geschrumpft. */
.ml-header.gb-is-sticky .gb-menu-container--mobile {
	padding-block-start: calc(var(--wp--custom--header--height-sticky) + var(--wp--preset--spacing--gap-l));
}

/* ----- ml-mobilmenue-liste: untereinander statt als Zeile ----- */

.ml-header .gb-menu-container--mobile .ml-nav {
	display: block;
	width: 100%;
	gap: 0;
}

.ml-header .gb-menu-container--mobile .gb-menu-item {
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

.ml-header .gb-menu-container--mobile .gb-menu-link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding-block: 0.875rem;
	font-size: var(--wp--custom--ui--size-l);
}

/* Im Vollbildmenue traegt die Kopfzeile ihre eigene Groesse nicht weiter. */
.ml-header.gb-is-sticky .gb-menu-container--mobile .gb-menu-link {
	font-size: var(--wp--custom--ui--size-l);
}

/* ----- ml-mega-anker: die Ebene ueber den Saeulen -----------------------

   Im Modus "click" ist der Menuepunkt selbst ein Schalter und fuehrt nicht
   mehr auf seine Seite. Diese Zeile traegt den Einstieg in die Uebersicht des
   Clusters - eine Ebene ueber den vier Saeulen, deshalb quer ueber die volle
   Panelbreite und mit Trennlinie darunter.
   --------------------------------------------------------------------- */

.ml-mega .ml-mega-anker {
	grid-column: 1 / -1;
	/*
	 * Kein eigener Kopfabstand mehr: die Zeile setzt direkt an der Unterkante
	 * der Kopfzeile an. Was optisch bleibt, ist nur der Zeilen-Ueberhang der
	 * Schrift - gemessen, nicht geschaetzt.
	 */
	padding-top: 0;
	display: flex;
	align-items: center;
	gap: 10px;
	padding-bottom: var(--wp--preset--spacing--gap-s);
	border-bottom: 1px solid var(--wp--preset--color--rule);
	font-size: var(--wp--custom--ui--size-l);
	font-weight: 800;
	color: var(--wp--preset--color--black);
	text-decoration: none;
	transition: color 0.2s ease;
}

.ml-mega .ml-mega-anker:hover,
.ml-mega .ml-mega-anker:focus-visible {
	color: var(--wp--preset--color--blue);
}

/* Derselbe Griff wie auf den Karten: der Pfeil wandert beim Ueberfahren. */
.ml-mega .ml-mega-anker:hover .ml-arrow,
.ml-mega .ml-mega-anker:focus-visible .ml-arrow {
	transform: translate(3px, -3px);
	color: var(--wp--preset--color--blue);
}

@media (prefers-reduced-motion: reduce) {
	.ml-mega .ml-mega-anker { transition: none; }
}

/* ----- ml-mega-versatz: entfallen (005, 0.88.1) -------------------------

   GB Pro setzt das Panel per transform an die Unterkante des Elements aus
   _gb_overlay_position_to_parent - hier .ml-header. Bis 0.88.0 zog ein
   negativer Rand (gap-l) den Kasten 24 px naeher an die Navigationszeile;
   ruhend ueberdeckte er damit das Logo (gemessen bei 1440: Panel-Oberkante
   144,59, Logo-Unterkante 148). Seit 005 beginnt das Panel ruhend wie
   geschrumpft an der Unterkante der Kopfzeile (169 / 73). Den transform
   fasst weiter niemand an.
   --------------------------------------------------------------------- */

/* ----- Seitentitel als H1 auf vollbreiten Seiten (0.21.1, 23.09.) ---------

   Seite 506 fuehrt ihre H1 ueber den GeneratePress-Seitentitel
   (h1.entry-title), nicht ueber S15. Auf einer Seite mit
   full-width-content hat .inside-article keinen Innenabstand - der Titel
   stand gemessen bei 0 px am linken Rand, die Sektionen bei 56 px.
   Hier dieselbe Flucht wie .ml-section > .ml-container: Rand-Token aussen,
   wideSize innen. Schrift bleibt bei der body-h1-Regel (0.17.0).
   Greift nur, wo der Titel nicht per _generate-disable-headline
   abgeschaltet ist - am 23.09. ist das allein Seite 506.
   --------------------------------------------------------------------- */

.full-width-content .inside-article > .entry-header {
	padding-inline: var(--wp--preset--spacing--rand);
	padding-block: var(--wp--preset--spacing--band);
	margin: 0;
}

.full-width-content .inside-article > .entry-header > .entry-title {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	margin-block: 0;
}

.full-width-content .inside-article > .entry-header + .entry-content {
	margin-top: 0;
}

/* ----- S18 · Abstand Vorspann -> Raster (0.21.1, 23.09.) ------------------

   In S17 steht zwischen Vorspann und erster Karte die Navigationszeile des
   Karussells: gemessen 72 px (48 Knoepfe + 24 Abstand). S18 hat keine -
   dort lag das Raster mit 0 px direkt unter dem Vorspann (Seite 61,
   1440 und 390). Dieselbe Strecke wie in S17, aus denselben Tokens.
   --------------------------------------------------------------------- */

.ml-material-abfrage .ml-lead + .ml-grid {
	margin-top: calc(var(--wp--preset--spacing--band) + var(--wp--preset--spacing--gap-l));
}

/* ----- Sechs Titelrollen (0.23.0, 23.09.) ----------------------------------

   Entwurf "Struktur & Regeln", Abschnitt 03: Groesse, Zeilenhoehe und
   Feldbreite gehoeren zur ROLLE und stehen hier zentral. Auf der Seite steht
   der Rollenname, nie font-size oder max-width. Alle Werte aus theme.json:

     Rolle            Groesse (Token)          Zeilenhoehe   Feld
     hero-start       titel-hero-start 30-64   hero 1.02     1050
     hero-uebersicht  titel-hero-uebersicht 48-100  0.92     980
     hero-beitrag     titel-xl 36-60           hero          820
     section          titel-l 34-68 (*)        section 0.95  680
     section-bild     titel-seite 30-48        pagehead 1.06 520
     section-halb     titel-halb 26-34         pagehead 1.06 Spalte

   (*) Entwurf 64, bleibt bei 68 - entschieden 22.09.

   Die bestehenden Elemente tragen ihre Rolle ueber dieselben Token:
   .ml-hero__title = hero-start, .ml-sectionhead .ml-display = section,
   .ml-pagehead__title = section-bild. Die Klassen hier sind fuer neue
   Stellen; hero-uebersicht, hero-beitrag und section-halb haben am 23.09.
   noch keinen Einsatzort (kein Beitragstemplate, keine Rubrikseite).
   Kein text-wrap: balance - der Umbruch entsteht allein aus dem Feld.
   --------------------------------------------------------------------- */

:is(.ml-titel-hero-start, .ml-titel-hero-uebersicht, .ml-titel-hero-beitrag, .ml-titel-section, .ml-titel-section-bild, .ml-titel-section-halb) {
	font-family: var(--wp--preset--font-family--nunito);
	font-weight: 900;
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0;
}

.ml-titel-hero-start {
	font-size: var(--wp--preset--font-size--titel-hero-start);
	line-height: var(--wp--custom--line-height--hero);
	max-width: var(--wp--custom--titel--feld--hero-start);
}

.ml-titel-hero-uebersicht {
	font-size: var(--wp--preset--font-size--titel-hero-uebersicht);
	line-height: var(--wp--custom--line-height--hero-uebersicht);
	max-width: var(--wp--custom--titel--feld--hero-uebersicht);
}

.ml-titel-hero-beitrag {
	font-size: var(--wp--preset--font-size--titel-xl);
	line-height: var(--wp--custom--line-height--hero);
	max-width: var(--wp--custom--titel--feld--hero-beitrag);
}

.ml-titel-section {
	font-size: var(--wp--preset--font-size--titel-l);
	line-height: var(--wp--custom--line-height--section);
	max-width: var(--wp--custom--titel--feld--section);
}

.ml-titel-section-bild {
	font-size: var(--wp--preset--font-size--titel-seite);
	line-height: var(--wp--custom--line-height--pagehead);
	max-width: var(--wp--custom--titel--feld--section-bild);
}

.ml-titel-section-halb {
	font-size: var(--wp--preset--font-size--titel-halb);
	line-height: var(--wp--custom--line-height--pagehead);
	max-width: none;
}

/* ----- Feldbreiten im Editor durchsetzen (0.23.0) ---------------------------

   Gemessen im Editor-Canvas am 23.09.: KEINE der Feldbreiten kam dort an -
   auch die alten 760 px nicht. Zwei Gegner, beide spaeter geladen:
     body .wp-block { max-width: var(--content-width) }            (0,1,1)
       -> schlaegt .ml-hero__body und .ml-pagehead__title (0,1,0);
          S15 stand im Editor auf 820 px, der Hero auf none
     .editor-styles-wrapper .wp-block-generateblocks-text:where(h1..p)
       { max-width: unset }                                         (0,2,0)
       -> gleichauf mit .ml-sectionhead .ml-display, spaeter geladen
   Der Redakteur sah damit einen anderen Umbruch als das Frontend. Dasselbe
   Mittel wie bei .ml-container: die Editorklasse `.wp-block` mit in den
   Selektor, dazu .editor-styles-wrapper. Werte bleiben die Token.
   Reihenfolge: die Startseiten-Ausnahme steht HINTER der Sektionsregel.
   --------------------------------------------------------------------- */

.editor-styles-wrapper .ml-hero__body.wp-block {
	max-width: var(--wp--custom--titel--feld--hero-start);
}

.editor-styles-wrapper .ml-sectionhead .ml-display.wp-block,
.editor-styles-wrapper .ml-section__head .ml-display.wp-block {
	max-width: var(--wp--custom--titel--feld--section);
}

.editor-styles-wrapper .ml-sectionhead-breit .ml-display.wp-block {
	max-width: var(--wp--custom--sektionskopf--titelbreite-start);
}

.editor-styles-wrapper .ml-pagehead__title.wp-block {
	max-width: var(--wp--custom--titel--feld--section-bild);
}

.editor-styles-wrapper .ml-titel-hero-start.wp-block { max-width: var(--wp--custom--titel--feld--hero-start); }
.editor-styles-wrapper .ml-titel-hero-uebersicht.wp-block { max-width: var(--wp--custom--titel--feld--hero-uebersicht); }
.editor-styles-wrapper .ml-titel-hero-beitrag.wp-block { max-width: var(--wp--custom--titel--feld--hero-beitrag); }
.editor-styles-wrapper .ml-titel-section.wp-block { max-width: var(--wp--custom--titel--feld--section); }
.editor-styles-wrapper .ml-titel-section-bild.wp-block { max-width: var(--wp--custom--titel--feld--section-bild); }
.editor-styles-wrapper .ml-titel-section-halb.wp-block { max-width: none; }

/* ----- Titel: ein Feld, Farbe aus der Zeile (0.37.0, 29.09.) -----------------

   Ein Titel ist ein einzelnes Textfeld (generateblocks/text, h1-h6). Die
   erste Zeile ist schwarz, jede weitere blau: ::first-line ist der einzige
   zeilenbezogene Selektor, den CSS kennt. Der Farbwechsel folgt dem Umbruch,
   statt ihn zu erzwingen. Der Punkt am Satzende wird getippt, nicht per CSS
   gesetzt - er nimmt die Farbe der Zeile an, in der er steht.

   Gemessen 29.09. (Chromium, Firefox, WebKit): ::first-line schlaegt in einen
   farblosen Span im Titel durch (Seitenkopf); ein Span mit eigener `color`
   gewinnt; ein Titel, der selbst display:flex oder grid ist, bleibt stumm
   blau. Heute steht kein Titel auf flex/grid.

   Dunkle Flaechen: fuer ::first-line gelten die Regeln fuer den Titel selbst
   nicht mit. Ohne eigene Regel stuende die erste Zeile schwarz auf dunkel.
   Dort ist der ganze Titel weiss.

   Farbe der ersten Zeile (0.38.0, 30.09.): der Textton, nicht der Token
   `black`. Aller uebrige Text rendert var(--contrast) = #222222, weil
   GeneratePress theme.json ueberschreibt (Stolperstelle 17); die erste Zeile
   war seit 0.37.0 #000000 - zwei Schwarztoene im Haus. Sie ist jetzt an den
   Textton gebunden, ueber custom.text.grund = var(--contrast, #222222). Der
   Rueckfallwert steht in theme.json, nicht hier, und ist keine Kosmetik: ohne
   ihn waere die Deklaration bei fehlendem --contrast ungueltig, ::first-line
   erbte vom Titel selbst (Blau) und der ganze Titel stuende blau.
   Aendert jemand im Customizer die globale Farbe Kontrast, folgt die erste
   Zeile mit - gewollt.

   Marker .ml-display--einfarbig: jede Zeile in der Farbe der Umgebung (die
   Startseite, abgenommen). `inherit` statt eines festen Schwarz, damit der
   Titel auch auf einer dunklen Flaeche lesbar bleibt.
   --------------------------------------------------------------------- */

.ml-display {
	color: var(--wp--preset--color--blue);
}

.ml-display::first-line {
	color: var(--wp--custom--text--grund);
}

:is(.ml-section-dark, .ml-flaeche[data-variante="schwarz"], .ml-videodok, .ml-stats-section) .ml-display,
:is(.ml-section-dark, .ml-flaeche[data-variante="schwarz"], .ml-videodok, .ml-stats-section) .ml-display::first-line {
	color: var(--wp--preset--color--white);
}

.ml-display--einfarbig,
.ml-display--einfarbig::first-line {
	color: inherit;
}

/* Untergeordnete Ueberschrift (0.50.0, 03.10.): Der Farbwechsel kennzeichnet
   Hero- und Sektionstitel. Eine Ueberschrift INNERHALB einer Sektion
   (Halbspalten-Titel, 34 px) traegt ihn nicht - im Entwurf steht sie als
   einfacher Textknoten ohne Farbangabe. Durchgehend Textton, Element UND
   ::first-line (::first-line erbt von seinem eigenen Element, Stolperstelle
   38). Auf dunkler Flaeche gewinnt weiter die Weiss-Regel oben: :is() nimmt
   die Spezifitaet seines staerksten Arguments (0,2,0), also (0,3,0) gegen
   (0,2,0) hier. */
.ml-display.ml-titel-section-halb,
.ml-display.ml-titel-section-halb::first-line {
	color: var(--wp--custom--text--grund);
}

/* Feldtitel in der Anleitung (0.51.0, 03.10.): "Ihr braucht:" (S20) und
   "So geht's:" (S21) tragen ml-anleitung-feld; der Anleitungskopf (S19) nicht.
   Der Entwurf setzt im Anleitungskopf den Wechsel (blauer Span), im Feldtitel
   nicht (ein Textknoten ohne Farbangabe). Gleiche Rolle ml-titel-anleitung,
   zwei Verhalten: der Marker ml-anleitung-feld entscheidet. Durchgehend
   Textton, Element UND ::first-line (Stolperstelle 38); auf dunkler Flaeche
   gewinnt weiter die Weiss-Regel oben (:is() = 0,2,0 -> 0,3,0 gegen 0,2,0). */
.ml-display.ml-anleitung-feld,
.ml-display.ml-anleitung-feld::first-line {
	color: var(--wp--custom--text--grund);
}

/* Lead-Titel einfarbig (0.52.0, 03.10.): ml-titel-section-bild (Seitenanfang,
   Lead neben dem Bild, 48 px) steht durchgehend im Textton. DOKUMENTIERTE
   ABWEICHUNG VOM ENTWURF, entschieden vom Auftraggeber am 03.10.: Der Entwurf
   setzt den Wechsel an einer Stelle im Satz (z. B. am Gedankenstrich); bei uns
   sitzt er am Zeilenumbruch, und wo Zeile 2 beginnt, haengt von der Breite ab
   (der Lead der Newsseite laeuft ueber fuenf Zeilen). Sektions- und Hero-Titel
   behalten den Wechsel. Element UND ::first-line (Stolperstelle 38); auf
   dunkler Flaeche gewinnt weiter die Weiss-Regel oben. ml-pagehead__title
   traegt die Feldbreite, nicht die Farbe, und bleibt unberuehrt. */
.ml-display.ml-titel-section-bild,
.ml-display.ml-titel-section-bild::first-line {
	color: var(--wp--custom--text--grund);
}

/* ========================================================================
   Footer (0.25.1, 24.09.)

   Globales Modul, GP-Element Block-Elements-Typ "site-footer" — gleiche
   Bauweise wie die Kopfzeile (site-header.php): eine Sektion mit eigener
   Fläche, kein Baustein, deshalb Media Queries statt Container Queries.

   Fläche seit 0.25.1 `blue-dark`, nicht `blue` — Entscheidung der Steuerung
   vom 24.09. (Bauauftrag 3b): Auf `blue` bestand nur die 95%-Stufe 4,5:1,
   fünf von sechs Stufen darunter. Auf `blue-dark` liegt der Vollton bei
   7,2979:1 statt 4,9073:1 — genug Abstand, um eine Deckkraftleiter zu halten.

   Deckkraftleiter seit 0.25.1 (weiße Schrift auf `blue-dark`, vier Stufen):
   95% Spaltentitel · 90% Markenzeile-Unterzeile · 85% Adresse/Listenlinks ·
   75% Newsletter-Einleitung/Kontaktzeile/„Folgt uns“/Abschlusszeile.
   Kontaktzeile und Abschlusszeile waren zuvor 70% und 65% (dort unter 4,5:1)
   und stehen jetzt auf der bereits vorhandenen 75%-Stufe, nicht auf der
   rechnerischen Untergrenze (70,89%) — Sicherheitsabstand statt Grenzwert.
   Werte und Kontrastrechnung im Protokoll.
   ===================================================================== */

/*
 * Der Seitenrand sitzt am BAND, nicht am Container - genau wie bei
 * `.ml-section` (Zeile 199). Bis 0.43.3 trug `.ml-footer__container`
 * `padding: 64px rand 36px` auf einem Element, das bereits
 * `max-width: wide-size` fuehrt: der Rand wirkte INNERHALB der 1360px.
 * Gemessen bei 1440: Inhalt 1248,01 @ 96 statt 1328,03 @ 55,98 - die
 * Differenz ist (1440 - 1360) / 2 = 40px. Unterhalb von 1360px greift
 * die Begrenzung nicht und die Kante stimmte schon vorher.
 */
.ml-footer {
	padding-inline: var(--wp--preset--spacing--rand);
	background-color: var(--wp--preset--color--blue-dark);
	color: var(--wp--preset--color--white);
}

.ml-footer a {
	text-decoration: none;
}

.ml-footer__container {
	padding: 64px 0 36px;
}

/* ------------------------------------------------------- Kopfzeile -- */

.ml-footer__top {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 28px;
	padding-bottom: 56px;
	margin-bottom: 64px;
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--white) 25%, transparent);
}

.ml-footer__brand {
	display: flex;
	align-items: center;
}

/* (0,2,0): `.woocommerce-page img { height: auto }` (0,1,1) aus dem WooCommerce-CSS
   setzte die Hoehe sonst zurueck - das SVG ohne eigene Masse wurde 0 x 0 (021). */
.ml-footer .ml-footer__brand-logo {
	display: block;
	height: 92px;
	width: auto;
}

.ml-footer__brand-text {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.ml-footer__brand-title {
	margin: 0;
	font-size: 40px;
	line-height: 1.05;
	font-weight: 900;
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--preset--color--white);
}

.ml-footer__brand-sub {
	margin: 0;
	font-size: 13px;
	color: color-mix(in srgb, var(--wp--preset--color--white) 90%, transparent);
}

/* ----------------------------------------------------- Vier Spalten -- */

.ml-footer__cols {
	display: grid;
	grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.5fr);
	gap: 48px;
	align-items: start;
	margin-bottom: 64px;
}

.ml-footer__col {
	min-width: 0;
}

.ml-footer__col-title {
	margin: 0 0 14px;
	font-size: 15px;
	font-weight: 700;
	color: color-mix(in srgb, var(--wp--preset--color--white) 95%, transparent);
}

/* Spalte 1 — Kontakt. .ml-footer__address wird per render_block-Filter
   (milchland_footer_adresse) von <div> auf <address> umgestellt, weil
   "address" nicht im tagName-Enum von generateblocks/element steht —
   derselbe Weg wie beim zweiteiligen Titel (data-rang, Regel 9/18). */

.ml-footer__address {
	font-style: normal;
	font-size: 14px;
	line-height: 1.7;
	color: color-mix(in srgb, var(--wp--preset--color--white) 85%, transparent);
}

.ml-footer__address-lines {
	margin: 0;
}

.ml-footer__contact-row {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 8px;
	font-size: 13px;
	color: color-mix(in srgb, var(--wp--preset--color--white) 75%, transparent);
}

.ml-footer__address + .ml-footer__contact-row {
	margin-top: 14px;
}

.ml-footer__contact-icon {
	display: flex;
	flex-shrink: 0;
	color: inherit;
}

.ml-footer__contact-link {
	color: inherit;
}

.ml-footer__contact-link:hover,
.ml-footer__contact-link:focus-visible {
	text-decoration: underline;
}

/* Spalte 2 + 3 — Themen, Service. Dummy-Links auf "#" bis zur Migration,
   Entscheidung vom 18.09. (siehe uebergabe-startseite.md). */

.ml-footer__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 11px;
	font-size: 14px;
}

.ml-footer__link {
	color: color-mix(in srgb, var(--wp--preset--color--white) 85%, transparent);
}

.ml-footer__link:hover,
.ml-footer__link:focus-visible {
	color: var(--wp--preset--color--white);
	text-decoration: underline;
}

/* Spalte 4 — Newsletter. Nur ein Platzhalter, kein Formular — entschieden
   am 24.09. Das Anmeldefeld kommt spaeter unmittelbar von Cleverreach. */

.ml-footer__newsletter-lead {
	margin: 10px 0 16px;
	font-size: 14px;
	line-height: 1.5;
	color: color-mix(in srgb, var(--wp--preset--color--white) 75%, transparent);
}

.ml-footer__newsletter {
	box-sizing: border-box;
	height: 96px;
	margin-bottom: 24px;
	border: 1px dashed color-mix(in srgb, var(--wp--preset--color--white) 35%, transparent);
	border-radius: var(--wp--custom--radius--panel);
}

.ml-footer__follow-label {
	margin: 0 0 12px;
	font-size: 13px;
	font-weight: 700;
	color: color-mix(in srgb, var(--wp--preset--color--white) 75%, transparent);
}

.ml-footer__social-row {
	display: flex;
	gap: 8px;
}

.ml-footer__social-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--wp--custom--radius--pill);
	background-color: color-mix(in srgb, var(--wp--preset--color--white) 14%, transparent);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--white) 35%, transparent);
	color: var(--wp--preset--color--white);
	transition: background-color 0.2s ease;
}

.ml-footer__social-btn:hover,
.ml-footer__social-btn:focus-visible {
	background-color: color-mix(in srgb, var(--wp--preset--color--white) 24%, transparent);
}

.ml-footer__social-icon {
	display: flex;
}

/* ------------------------------------------------------ Abschlusszeile -- */

.ml-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding-top: 24px;
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--white) 25%, transparent);
	font-size: 12px;
}

.ml-footer__copy {
	margin: 0;
	color: color-mix(in srgb, var(--wp--preset--color--white) 75%, transparent);
}

.ml-footer__legal {
	display: flex;
	flex-wrap: wrap;
	gap: 22px;
}

.ml-footer__legal-link {
	color: color-mix(in srgb, var(--wp--preset--color--white) 75%, transparent);
}

.ml-footer__legal-link:hover,
.ml-footer__legal-link:focus-visible {
	color: var(--wp--preset--color--white);
	text-decoration: underline;
}

/* -------------------------------------------------------- Umbruch -- */

@media (max-width: 1080px) {
	.ml-footer__cols {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 44px 40px;
	}
}

@media (max-width: 700px) {
	.ml-footer__cols {
		grid-template-columns: 1fr;
		gap: 36px;
	}

	.ml-footer__bottom {
		justify-content: flex-start;
	}
}

@media (prefers-reduced-motion: reduce) {
	.ml-footer__social-btn {
		transition: none;
	}
}


/* ============================================== Seitenkopf (0.27.0) ======

   Globales Modul: GP-Block-Element vom Typ `page-hero`, Hook
   `generate_after_header`. Ein Modul mit zwei Fuellungen; gebaut ist
   Variante A (Rubrik- und Inhaltsseiten): Brotkrume + grosser Titel OHNE Rang.
   Die H1 der Seite steht weiter im Inhalt (S15) - der Titel hier ist Schmuck.

   Der Klassenname ist bewusst NICHT `ml-pagehead`: `.ml-pagehead__title` und
   `.ml-pagehead__text` gehoeren dem Element S15 (Seitenanfang mit Medium).

   Seitenrand am Band, nicht am Container: so beginnt der Inhalt bei 1440 px
   bei 56 px, fluchtend mit `.ml-section > .ml-container`. Laege der Rand am
   1360-px-Container, stuende die linke Kante bei 96.

   Alle Masse aus `custom.seitenkopf` (theme.json). Die Brotkrume selbst
   (Glieder, Chevron, JSON-LD) erzeugt der Filter `milchland_seitenkopf`.
   ========================================================================= */

.ml-seitenkopf {
	position: relative;
	padding-block: var(--wp--custom--seitenkopf--abstand-oben) var(--wp--custom--seitenkopf--abstand-unten);
	padding-inline: var(--wp--preset--spacing--rand);
	background-color: var(--wp--preset--color--white);
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

.ml-seitenkopf__container {
	position: relative;
	z-index: 1;
}

/*
 * Kuhflecken: Inline-SVG, Farbe und Deckkraft aus Token, nicht anklickbar.
 *
 * Die Huelle (`.gb-shape`) ist nur die Beschneidungsflaeche und deckt das
 * Band ab; das SVG steht darin absolut und ragt ueber den Rand. Das
 * Beschneiden sitzt bewusst HIER und nicht am Band: `overflow: hidden` am
 * Band wuerde einen zu breiten Titel oder ein langes Wort in der Krume
 * stumm abschneiden, statt einen messbaren Ueberlauf zu zeigen.
 */
.ml-seitenkopf__flecken {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	overflow: hidden;
	pointer-events: none;
}

/* Seit 002: Motiv als Maske an der Huelle (altes Inline-SVG seit 017 entfernt). */

.ml-seitenkopf__flecken::before {
	content: "";
	position: absolute;
	top: var(--wp--custom--seitenkopf--flecken-oben);
	right: var(--wp--custom--seitenkopf--flecken-rechts);
	width: var(--wp--custom--seitenkopf--flecken-groesse);
	height: var(--wp--custom--seitenkopf--flecken-groesse);
	background-color: var(--wp--preset--color--black);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: contain;
	-webkit-mask-size: contain;
	mask-repeat: no-repeat;
	-webkit-mask-repeat: no-repeat;
	opacity: var(--wp--custom--seitenkopf--flecken-deckkraft);
}

/* Brotkrume: eigene Zeile, umbruchfaehig. Der Strich steht vor der Liste. */
.ml-seitenkopf__krume {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--custom--abstand--label);
	margin-block: var(--wp--custom--seitenkopf--krume-oben) var(--wp--custom--seitenkopf--krume-unten);
	font-family: var(--wp--preset--font-family--nunito);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 600;
	line-height: var(--wp--custom--line-height--card-body);
	color: var(--wp--custom--text--gedaempft);
}

.ml-seitenkopf__strich {
	flex: none;
	width: var(--wp--custom--seitenkopf--strich-breite);
	height: 1px;
	/* Mitte der ersten Zeile, auch wenn die Krume umbricht. */
	margin-top: calc(var(--wp--custom--line-height--card-body) * 0.5em);
	background-color: var(--wp--preset--color--black);
}

.ml-seitenkopf__liste {
	display: flex;
	flex: 1 1 0;
	flex-wrap: wrap;
	align-items: center;
	gap: calc(var(--wp--custom--abstand--label) / 2) var(--wp--custom--abstand--label);
	min-width: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ml-seitenkopf__glied {
	display: flex;
	align-items: center;
	gap: var(--wp--custom--abstand--label);
	min-width: 0;
	margin: 0;
	padding: 0;
}

.ml-seitenkopf__link {
	color: var(--wp--custom--text--gedaempft);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.ml-seitenkopf__link:hover,
.ml-seitenkopf__link:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.ml-seitenkopf__aktuell {
	font-weight: 500;
	color: var(--wp--preset--color--blue);
	overflow-wrap: anywhere;
}

.ml-seitenkopf__chevron {
	flex: none;
	width: var(--wp--custom--seitenkopf--chevron);
	height: var(--wp--custom--seitenkopf--chevron);
	opacity: var(--wp--custom--seitenkopf--chevron-deckkraft);
}

/*
 * Titel: Groesse, Zeilenhoehe und Feld kommen von `ml-titel-hero-uebersicht`.
 *
 * Trennen statt ueberlaufen: bei 390 px ist "Qualitaetsfoerderung" in 45,6 px
 * 411 px breit, das Feld nur 348 px. Weiche Trennung nur, wo das Wort nicht
 * passt (Sprache der Seite: de); `break-word` faengt ab, falls der Browser
 * kein Trennwoerterbuch hat.
 */
.ml-seitenkopf__titel {
	position: relative;
	hyphens: auto;
	overflow-wrap: break-word;
}

/* ------------------------------------------------- Fokusrahmen (07) ------ */

/*
 * Der sichtbare Tastaturfokus: 3 px, Abstand 3 px (Entwurf „Struktur &
 * Regeln", Abschnitt 07). Masse aus theme.json (`custom.focus`), keine
 * Literale in dieser Datei.
 *
 * Spezifitaet (0,2,1) mit Absicht. GB Pro liefert eigene Fokusregeln
 * (`[data-carousel-control]:focus-visible`, `.gb-carousel-dot:focus-visible`,
 * beide 0,2,0), die NACH components.css laden. `:root body` hebt die globale
 * Regel darueber, ohne !important. Fuer Karten und Kacheln gilt eigenes:
 * dort traegt der Container den Rahmen (siehe `.ml-card`, `.ml-mosaic__tile`).
 *
 * `:focus-visible`, nicht `:focus` — sonst erschiene der Rahmen auch beim
 * Mausklick. Die Farbe steht als Langschreibweise, nicht in der Kurzform
 * (Befund 19.09.: in der Kurzform faellt sie auf `currentColor` zurueck).
 *
 * Die Farbe kommt aus `--ml-focus`, vorgegeben ist Markenblau. Gemessen
 * gegen die Flaeche: Blau auf Weiss 4,9073 : 1, Weiss auf Blau 4,9073,
 * Weiss auf Blau dunkel 7,2979, Weiss auf Schwarz 21 : 1 — Blau auf Blau
 * 1 : 1, auf Blau dunkel 1,4872, auf Schwarz 4,2793. Blau ist auf Blau und
 * Blau dunkel also unsichtbar; auf Schwarz genuegte es den 3 : 1 zwar noch,
 * dort gilt aber wie auf den blauen Flaechen Weiss (Vorgabe des Entwurfs).
 * Jede dunkle oder blaue Flaeche setzt deshalb `--ml-focus` auf Weiss.
 */
:root body :focus-visible {
	outline-style: solid;
	outline-width: var(--wp--custom--focus--width);
	outline-color: var(--ml-focus, var(--wp--preset--color--blue));
	outline-offset: var(--wp--custom--focus--offset);
}

.ml-section-dark,
.ml-videodok,
.ml-flaeche[data-variante="schwarz"],
.ml-stats-section,
.ml-header__bar,
.ml-hero,
.ml-note[data-variante="blau"],
.ml-cta:not([data-variante="tint"]),
.ml-mosaic__tile-aussage,
.ml-footer {
	--ml-focus: var(--wp--preset--color--white);
}

/*
 * Die Kacheln des Mosaiks sind WEISSE Karten in der schwarzen Sektion: fuer
 * das, was IN der Kachel steht, gilt wieder Blau. Die Kachel selbst (ihr
 * eigener Rahmen, `:has()`) sitzt auf Schwarz und behaelt Weiss — deshalb
 * greift die Regel nur auf die Kinder.
 */
.ml-section-dark .ml-mosaic__tile:not(.ml-mosaic__tile-aussage) > * {
	--ml-focus: var(--wp--preset--color--blue);
}

/*
 * Der Rahmen darf nicht abgeschnitten werden. Das Karussell beschneidet
 * seinen Inhalt (GB Pro: `overflow-x: hidden`), und der Rahmen einer Karte am
 * Rand oder eines Pfeils oben rechts ragt 6 px (Breite plus Abstand) darueber
 * hinaus. `overflow: clip` mit `overflow-clip-margin` schneidet erst hinter
 * diesem Rand ab, ohne dass sich Layout oder Maße verschieben. Wo ein Browser
 * `overflow-clip-margin` nicht kennt, bleibt es beim bisherigen Beschneiden.
 * (0,2,0), weil GB Pro `.gb-carousel-initialized` nachlaedt.
 */
.ml-block.ml-cardslider,
.ml-block.ml-slider {
	overflow: clip;
	overflow-clip-margin: var(--wp--custom--focus--raum);
}

/*
 * Das mobile Menue scrollt in einem eigenen Container. Springt der Fokus auf
 * den letzten Eintrag, scrollt der Browser ihn bis an die Unterkante — der
 * Rahmen laege dann ausserhalb. Der Scroll-Abstand haelt Platz dafuer frei.
 */
.gb-menu-container--mobile {
	scroll-padding-block: var(--wp--custom--focus--raum);
}

/* ==========================================================================
   Material-Einzelansicht — Bauauftrag 8 (0.31.0, 26.09.)
   ========================================================================== */

/* Brotkrume: eine Stufe ohne Ziel steht als Text, nicht als Link.
   Gleiche Farbe wie der Link, nur ohne Unterstreichung beim Hovern. */
.ml-seitenkopf__stufe {
	color: var(--wp--custom--text--gedaempft);
	overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   S19 · Anleitungskopf
   -------------------------------------------------------------------------- */

/* Titelrolle: dieselben Token wie der Seitenanfang (clamp 30–48, 1,06),
   aber ohne feste Feldbreite — hier ist die Spalte das Feld. */
.ml-titel-anleitung {
	font-size: var(--wp--preset--font-size--titel-seite);
	line-height: var(--wp--custom--line-height--pagehead);
}

/* Feldtitel "Ihr braucht:" (S20) / "So geht's:" (S21): 34 px bei 1440 wie im
   Entwurf, darunter fliessend (titel-halb 26-34, 012, 14.10.). Rang bleibt H2. */
.ml-titel-anleitung.ml-anleitung-feld {
	font-size: var(--wp--preset--font-size--titel-halb);
}

.ml-anleitungskopf__raster {
	display: grid;
	grid-template-columns: var(--wp--custom--anleitung--spalte-text) var(--wp--custom--anleitung--spalte-bild);
	gap: var(--wp--preset--spacing--band);
	align-items: start;
}

@media (max-width: 1080px) {
	.ml-anleitungskopf__raster {
		grid-template-columns: 1fr;
		gap: var(--wp--preset--spacing--gap-l);
	}
}

.ml-anleitungskopf {
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

.ml-anleitungskopf__text {
	min-width: 0;
}

/* S19-Vorspann (009, 14.10.): Fliesstext wie im Entwurf Upcycling, nicht 22. */
.ml-anleitungskopf .ml-lead {
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--body);
}

/* Der Schwierigkeitsgrad. Fehlt er, fällt der ganze Block weg — der Dynamic
   Tag liefert dann eine leere Zeichenkette (Regel 18 der Bauvorlage). */
.ml-anleitung__grad {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--custom--abstand--label);
	margin-top: var(--wp--preset--spacing--gap-l);
	padding: 6px 14px;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--pill);
	font-size: var(--wp--preset--font-size--card);
	font-weight: 600;
	color: var(--wp--preset--color--black);
	background-color: var(--wp--preset--color--white);
}

.ml-anleitung__grad-wert {
	color: var(--wp--preset--color--blue);
}

.ml-anleitungskopf__bild {
	min-width: 0;
}

/* 016: die Folienbilder sind seit dem Bildwaehler `generateblocks/media` - ein <img>
   direkt in der Folie statt in <figure>. Als Inline-Element stand es auf der
   Grundlinie und liess 8,8 px Luft darunter; als Block wie vorher die figure. */
.ml-anleitungskopf__bild .ml-slider__item > img {
	display: block;
}

/* --------------------------------------------------------------------------
   S23 · Zwei Textabschnitte
   -------------------------------------------------------------------------- */

.ml-duo__raster {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--wp--custom--duo--gap);
}

@media (max-width: 1080px) {
	.ml-duo__raster {
		grid-template-columns: 1fr;
		gap: var(--wp--custom--duo--gap-mobil);
	}
}

.ml-duo__spalte {
	min-width: 0;
}

/* Bau 43 (E1): Titel -> erster Absatz 24 (Entwurf 23,92). Vorher -0,03:
   Titel `margin: 0`, Absatz `margin-top: 0` von GeneratePress. */
.ml-duo__spalte > .ml-display + * {
	margin-top: var(--wp--custom--duo--titel-abstand);
}

.ml-duo__abschluss {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--gap-l);
	margin-top: var(--wp--preset--spacing--band);
	padding-top: var(--wp--preset--spacing--gap-l);
	border-top: 1px solid var(--wp--preset--color--rule);
}

.ml-duo__quelle {
	margin: 0;
	/* Bau 43 (E10): 13 / 600 wie die Bildunterschrift seit Bau 23 (vorher 14 / 400). */
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--custom--text--gedaempft);
}
/* --------------------------------------------------------------------------
   S20 · Zutatenliste
   -------------------------------------------------------------------------- */

.ml-zutaten__raster {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: var(--wp--preset--spacing--band);
	align-items: start;
}

@media (max-width: 1080px) {
	.ml-zutaten__raster {
		grid-template-columns: 1fr;
		gap: var(--wp--preset--spacing--gap-l);
	}
}

/*
 * Beide Listen sind Listenstile — S20 Haekchen (`is-style-ml-check`), S21
 * Nummernkreise (`is-style-ml-nummer`) — und fuehren ihre Darstellung dort.
 * Die Klassen bleiben als Marker stehen: das HowTo-Schema in der
 * functions.php findet Zutaten und Schritte ueber `ml-zutaten__liste` und
 * `ml-schritte__liste`. Hier steht nur der Abstand zur Ueberschrift — und
 * kein Abstand nach unten, den GP sonst an jedes <ul> / <ol> setzt.
 */
.ml-zutaten__liste,
.ml-schritte__liste {
	margin-block: var(--wp--preset--spacing--gap-l) 0;
}

/* Das Bild überlappt die Fläche nach unten. Der Versatz ist ein Token,
   damit er nicht an zwei Stellen steht. */
.ml-zutaten__bild {
	width: var(--wp--custom--anleitung--bild-breite);
	max-width: 100%;
	margin-bottom: calc(-1 * var(--wp--custom--anleitung--bild-versatz));
}

@media (max-width: 1080px) {
	.ml-zutaten__bild {
		margin-bottom: 0;
	}
}

.ml-zutaten__bild img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--wp--custom--radius--panel);
}

/* --------------------------------------------------------------------------
   S21 · Arbeitsschritte
   -------------------------------------------------------------------------- */

/*
 * Die Nummerierung ist ein Listenstil (Nummernkreise, `is-style-ml-nummer`)
 * und steht oben im Abschnitt „Nummernkreise". Seit 03.10. (Bauauftrag 24)
 * fuehrt S21 hier keine eigenen Regeln mehr. Die Klasse bleibt als Marker
 * stehen: das HowTo-Schema in der functions.php findet die Schritte ueber
 * `ml-schritte__liste`. Der Abstand zur Ueberschrift steht beim Marker von S20.
 *
 * Seit 0.83.0 steht hier wieder eine eigene Regel — aber keine Darstellung des
 * Listenstils, sondern eine Breitenentscheidung fuer diesen einen Einsatzort.
 */

/*
 * Zweispaltig ueber die ganze Bahn, ab sechs Schritten (12.10., 0.83.0 bis
 * 0.85.0).
 *
 * Der Anlass: eine Anleitung mit zehn Schritten stand auf der Lesebreite von
 * 680px, rechts blieben bei 1440px 648,03px Bahn leer — gemessen auf Material
 * 350 (Vogelhaeuschen), Listenhoehe dort 716px.
 *
 * FUENF ENTSCHEIDUNGEN STECKEN IN DIESER REGEL:
 *
 * 1. NUR IN S21, nicht am Listenstil. `is-style-ml-nummer` kann der Redakteur
 *    ueberall waehlen, auch in einer halben Spalte — dort weiss die Regel
 *    nicht, wie breit ihr Umfeld ist. Der Marker `ml-schritte__liste` steht
 *    nur in S21 (gezaehlt am 12.10.: 7 lebende Instanzen, alle aus S21).
 * 2. SECHS PUNKTE als Schwelle, abgefragt mit `:has(> li:nth-child(6))`. Zwei
 *    Spalten mit zwei Punkten sind keine Aufzaehlung mehr. Von den 7 Instanzen
 *    hat am 12.10. genau eine sechs oder mehr Schritte (Material 350 mit 10),
 *    die uebrigen sechs haben vier und bleiben unberuehrt.
 * 3. MEDIA QUERY, nicht Container Query. Teil A der Bauvorlage: Container
 *    Queries sind fuer die Bausteine, die Sektionen bleiben auf Media Queries
 *    — sie stehen per Definition ueber die volle Breite, und S21 ist eine
 *    Sektion.
 *    DIE GRENZE IST 1024px, NICHT DIE TABLET-GRENZE DER DATEI (0.85.0,
 *    Entscheidung des Auftraggebers). 0.83.0 hatte 783px, die Gegenseite der
 *    782px-Grenze, die diese Datei achtmal benutzt. Gemessen auf Material 350
 *    mit zehn Schritten bringt die zweite Spalte dort aber fast nichts: die
 *    Liste geht von 716px auf 712px — VIER Pixel —, und die Spalten sind nur
 *    345,41px breit. Bei 1024px sind es 457,88px Spaltenbreite und 157px
 *    gewonnene Hoehe, bei 1440 und 1920 je 310px.
 *    Die Huelle ist `min-width`, obwohl der Rest der Datei desktop-first
 *    arbeitet: so braucht der Stand von vor 0.83.0 keine Gegenregel, die ihn
 *    zuruecknimmt. Unterhalb von 1024px greift hier gar nichts — auch der
 *    feste Umbruch aus Entscheidung 5 steht in derselben Huelle.
 * 4. DER ABSTAND DER PUNKTE WIRD UMGEDREHT. `li + li { margin-top }` wirkt im
 *    Mehrspaltensatz auch am KOPF der zweiten Spalte — Schritt 6 staende dann
 *    20px tiefer als Schritt 1. Deshalb `margin-bottom` an jedem Punkt und 0
 *    am letzten, genau wie bei den Haekchenlisten. Die Summe ist dieselbe,
 *    die Gesamthoehe aendert sich dadurch nicht.
 * 5. DER UMBRUCH WIRD FESTGESETZT, nicht dem Hoehenausgleich ueberlassen.
 *    `columns: 2` gleicht die SPALTENHOEHEN aus, nicht die Anzahl. Auf
 *    Material 350 mit zehn Schritten gemessen: bei 783, 800, 900, 1024, 1100,
 *    1280, 1536, 1680, 1920 und 2560px ergibt der Ausgleich 4 | 6, nur bei
 *    genau 1440px 5 | 5. Bei 1920 ist die rechte Spalte dabei sogar HOEHER
 *    als die linke (381 gegen 315px) — der Ausgleich loest hier also nicht
 *    einmal seine eigene Aufgabe.
 *
 *    Der Umbruch steht deshalb fest, vor dem Punkt ceil(n/2)+1. LINKS STEHT
 *    BEI UNGERADER ANZAHL EINER MEHR — mit floor(n/2)+1 stand er rechts
 *    (0.84.0, vom Pruefchat gemessen: 7 ergab 3|4, 9 ergab 4|5, 19 ergab
 *    9|10). Berichtigt in 0.85.0.
 *
 *    CSS kann nicht zaehlen, also steht je Anzahlpaar eine Bedingung:
 *    `:has(> li:nth-child(n)):not(:has(> li:nth-child(n+2)))` trifft genau die
 *    Listen mit n oder n+1 Punkten, und beide brechen an derselben Stelle.
 *    Die erste Zeile steht allein, weil sechs Punkte ihren eigenen Umbruch
 *    haben (3|3). Acht Zeilen decken 6 bis 20 Schritte ab; ab 21 greift
 *    wieder der Hoehenausgleich — eine Anleitung mit einundzwanzig Schritten
 *    hat ein anderes Problem als ihre Spaltenaufteilung.
 *
 *    Folge, bewusst in Kauf genommen: die linke Spalte darf hoeher sein als
 *    die rechte. Die Liste liest sich von oben nach unten und dann rechts
 *    weiter — eine Luecke unten rechts stoert weniger als eine Nummernfolge,
 *    die links frueher aufhoert.
 *
 * Der Spaltenabstand ist der Abstand der Spalten-Bloecke: an
 * `.wp-block-columns` gemessen 24px, derselbe Wert wie das Token `gap-l`. Der
 * Token steht hier statt `--wp--style--block-gap`, weil in diese Datei nur
 * Verweise auf theme.json-Tokens gehoeren (Regel 23); theme.json fuehrt
 * heute kein `styles.spacing.blockGap`, die 24px kommen aus dem Kern. Wer das
 * dort setzt, zieht diese Zeile nach.
 *
 * Der Zaehler laeuft ueber beide Spalten weiter: `counter-increment` folgt der
 * Dokumentfolge, nicht der Spalte.
 *
 * Der Tipp-Kasten darunter ist nicht beruehrt — er ist ein Geschwister der
 * Liste und behaelt seine Breite.
 */
@media (min-width: 1024px) {
	.wp-block-list.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(6)) {
		max-width: none;
		columns: 2;
		column-gap: var(--wp--preset--spacing--gap-l);
	}

	/* Entscheidung 4 im Kommentar darueber. */
	.wp-block-list.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(6)) > li {
		margin-top: 0;
		margin-bottom: var(--wp--preset--spacing--gap-s);
		break-inside: avoid;
	}

	.wp-block-list.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(6)) > li:last-child {
		margin-bottom: 0;
	}

	/* Entscheidung 5: der feste Umbruch vor ceil(n/2)+1. */
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(6)):not(:has(> li:nth-child(7))) > li:nth-child(4),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(7)):not(:has(> li:nth-child(9))) > li:nth-child(5),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(9)):not(:has(> li:nth-child(11))) > li:nth-child(6),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(11)):not(:has(> li:nth-child(13))) > li:nth-child(7),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(13)):not(:has(> li:nth-child(15))) > li:nth-child(8),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(15)):not(:has(> li:nth-child(17))) > li:nth-child(9),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(17)):not(:has(> li:nth-child(19))) > li:nth-child(10),
	.ml-schritte__liste.is-style-ml-nummer:has(> li:nth-child(19)):not(:has(> li:nth-child(21))) > li:nth-child(11) {
		break-before: column;
	}
}

/* Der Tipp entfällt, wenn er leer ist — das erledigt der Dynamic Tag
   beziehungsweise das leere Feld; hier steht nur das Aussehen. */
/*
 * Volle Breite der Kastenflaeche (03.10., Bauauftrag 24): der Deckel auf die
 * Lesebreite ist weg. Innenabstand 18/22px, Radius 4px und Text 16px sind die
 * Werte des Entwurfs „Beitragsseite Upcycling"; Flaeche, Kante und die
 * Form (gerade links, rund rechts) bleiben.
 */
/* S21 (009, 14.10.): Schritte ueber die volle Kastenbreite wie der Tipp,
   Nummernkreise schwarz (Ziffer weiss, 21 : 1). Nur in S21 - der Listenstil
   bleibt anderswo blau. (0,3,0) gegen (0,2,0) des Listenstils. */
.wp-block-list.ml-schritte__liste.is-style-ml-nummer {
	max-width: none;
}

.wp-block-list.ml-schritte__liste.is-style-ml-nummer > li::before {
	background-color: var(--wp--preset--color--black);
}

.ml-schritte__tipp {
	margin-top: var(--wp--preset--spacing--band);
	padding: var(--wp--custom--anleitung--tipp-polster);
	border-left: 3px solid var(--wp--preset--color--blue);
	border-radius: 0 var(--wp--custom--radius--card) var(--wp--custom--radius--card) 0;
	background-color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--label);
}

.ml-schritte__tipp:empty {
	display: none;
}

/* --------------------------------------------------------------------------
   Teilen-Zeile
   -------------------------------------------------------------------------- */

.ml-teilen__raster {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--gap-l);
}

.ml-teilen__knoepfe {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--gap-s);
}

/*
 * Der Teilen-Knopf ist ein Bedienelement: WCAG 1.4.11 verlangt 3 : 1 fuer
 * seine Grenze. Mit dem Trennlinien-Token waeren es 1,2253 auf Weiss
 * (nach dem Wechsel auf #E8E8E8); `gray-dark` #7F7F7F liefert 4,0041.
 * `gray-dark` ist im Projekt Flaeche und Linie, nie Text (Regel 3).
 */
.ml-teilen__knopf {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--wp--custom--radius--pill);
	border: 1px solid var(--wp--preset--color--gray-dark);
	color: var(--wp--preset--color--black);
	background-color: var(--wp--preset--color--white);
	text-decoration: none;
}

.ml-teilen__knopf:hover {
	border-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--blue);
}

.ml-teilen__knopf svg {
	width: 20px;
	height: 20px;
}


/* ========================================================================
   Bauauftrag 12 (0.35.0, 29.09.)
   S03 ohne Bild und mit Kasten · B08 Gewinnerkarte · S22 Videos und Dokumente

   Keine Literale: Farben, Radien, Abstaende und Schriftgroessen kommen aus
   theme.json. Neu dort: custom.gewinner und custom.videodok.
   ===================================================================== */

/* ---- S03 ohne Bild --------------------------------------------------------

   Faellt die Buehne aus (milchland_leere_buehne), bleibt eine Rasterspalte
   uebrig und der Text liefe ueber die halbe Seite. Er steht dann einspaltig in
   der Lesebreite (theme.json layout.contentSize), linksbuendig in der Bahn.
   Nur wo tatsaechlich kein Bild steht - :has() statt einer Variante: das Bild
   ist ein Inhalt, keine Einstellung.
   ------------------------------------------------------------------------- */
.ml-split:not(:has(> .ml-split__media-wrap, > .ml-split__media)) {
	/*
	 * Bauauftrag 2, Punkt 9 (10.10.): die Textspalte nimmt die INHALTSBREITE,
	 * nicht die Lesebreite. Bis 0.69.0 stand hier
	 * `minmax(0, var(--wp--style--global--content-size))` - der Text stand dann
	 * linksbuendig in der Bahn und liess rechts die halbe Sektion leer.
	 * Entscheidung 10.10.: volle Bahn.
	 */
	grid-template-columns: minmax(0, 1fr);
}

/* Ein Baustein (B01) unter dem Split derselben Sektion braucht Luft. */
.ml-container > .ml-split + .ml-block {
	margin-top: var(--wp--preset--spacing--band);
}

/* ---- B08 · Gewinnerkarte ---------------------------------------------------

   Zwei Groessen ueber data-groesse (Vorgabe normal):
     gross   volle Breite, Text | Bild        (Platz 1 bis 5)
     normal  Text, darunter das Bild; zwei Karten je Reihe (die TOP 11)
   Die Zweierreihe legt das Tab-Panel, nicht die Karte: das Panel wird zum
   Raster, sobald es eine normale Karte enthaelt. :not([hidden]) - ohne das
   schluege display:grid das versteckte Panel wieder auf.
   Umbruch bei 782 px Fensterbreite wie S03 (Container Queries greifen hier
   nicht: der naechste Container ist die Sektion, nicht der 860-px-Reiter).
   ------------------------------------------------------------------------- */
.ml-winner {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	grid-template-rows: 1fr auto;
	gap: var(--wp--preset--spacing--gap-l);
	padding: var(--wp--custom--gewinner--padding);
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--panel);
}

.ml-winner[data-groesse="gross"] {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	grid-template-rows: none;
	align-items: start;
	gap: var(--wp--preset--spacing--band);
}

/* Ohne Bild gibt es keine zweite Zeile - sonst bliebe ihr Abstand (gemessen: 24 px) als Leerraum unter dem Text. */
.ml-winner:not(:has(> .ml-winner__media)) {
	grid-template-rows: none;
}

/* Ohne Bild bleibt eine Spalte. */
.ml-winner[data-groesse="gross"]:not(:has(> .ml-winner__media)) {
	grid-template-columns: minmax(0, 1fr);
}

.ml-winner__body {
	min-width: 0;
}

/* Kicker: Platz. Blau dunkel wie der Sektionskicker, mit eigener Farbe also opacity 1. */
.ml-winner__platz {
	color: var(--wp--preset--color--blue-dark);
	opacity: 1;
	margin: 0 0 0.75rem;
}

.ml-winner__name {
	font-family: var(--wp--preset--font-family--nunito);
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--card);
	letter-spacing: var(--wp--custom--tracking--display);
	margin: 0;
}

.ml-winner[data-groesse="gross"] .ml-winner__name {
	font-size: var(--wp--preset--font-size--titel-halb);
}

.ml-winner__ort {
	font-size: var(--wp--custom--ui--size);
	font-weight: 700;
	line-height: 1.35;
	color: var(--wp--custom--text--gedaempft);
	margin: 0.375rem 0 1rem;
}

/*
 * 14px statt der Fliesstextgroesse (18px bei 1440). Die 4px sind der
 * Grund, dass das Platz-1-Panel 477,94 statt 395,5 px hoch steht
 * (Abgleich B, 01.10.). 14px auf #222222 ergeben 15,91 - weit ueber
 * jeder Schwelle. Die Zeilenhoehe bleibt am vorhandenen Token.
 */
.ml-winner__text {
	font-size: var(--wp--preset--font-size--card);
	line-height: var(--wp--custom--line-height--card-body);
	margin: 0;
}

.ml-winner__media {
	min-width: 0;
}

.ml-winner__media :is(figure, .wp-block-image) {
	margin: 0;
}

.ml-winner__media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--wp--custom--gewinner--bild);
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

.ml-winner__media figcaption {
	margin: 0.75rem 0 0;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	line-height: 1.5;
	color: var(--wp--custom--text--gedaempft);
	text-align: left;
}

.ml-tabs .wp-block-tab-panel:not([hidden]):has(> .ml-winner[data-groesse="normal"]) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--gap-l);
}

/* Der Abstand zwischen den Karten kommt aus dem Raster (gap); der Flow-Abstand (24 px) verschob sonst ab der zweiten Karte alles nach unten. */
.ml-tabs .wp-block-tab-panel:has(> .ml-winner[data-groesse="normal"]) > .ml-winner {
	margin-block: 0;
}

@media (max-width: 782px) {
	.ml-winner[data-groesse="gross"] {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--wp--preset--spacing--gap-l);
	}
	.ml-tabs .wp-block-tab-panel:not([hidden]):has(> .ml-winner[data-groesse="normal"]) {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* ---- S22 · Videos und Dokumente --------------------------------------------

   Sektion auf Markenblau. Auf Blau gilt nur volles Weiss (4,907 : 1) - keine
   Deckkraft auf Text, Symbol oder Linie; die Kacheln stehen auf `blue-dark`
   (Weiss darauf 7,298 : 1). Trennlinien der Dokumentenliste: 1 px, Weiss.
   Fokus: --ml-focus ist Weiss (Selektorliste im Abschnitt Fokusrahmen).
   Links: Unterstreichung statt Deckkraft beim Ueberfahren.
   ------------------------------------------------------------------------- */
.ml-videodok {
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

.ml-videodok :is(h2, h3, p, span, a, li) {
	color: var(--wp--preset--color--white);
}

/* (0,3,0) gegen .ml-sectionhead .ml-label (0,2,0): dort steht blue-dark. */
.ml-videodok .ml-sectionhead .ml-label {
	color: var(--wp--preset--color--white);
	opacity: 1;
}

.ml-videodok__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-items: start;
	gap: var(--wp--preset--spacing--band);
}

/*
 * Die rechte Rasterzelle fasst Einleitung und Dokumentenliste zusammen —
 * sonst faenden beide als Geschwister je eine eigene Zelle des
 * zweispaltigen Rasters. Derselbe Abstand wie in der Videospalte.
 */
.ml-videodok__spalte {
	display: grid;
	gap: var(--wp--preset--spacing--gap-l);
	align-content: start;
	min-width: 0;
}

/*
 * Die Absaetze der Sektion: 15px/400/1,65 nach dem Entwurf. Ohne eigene
 * Regel liefen sie auf der Fliesstextgroesse (18px bei 1440).
 */
.ml-videodok__text {
	margin: 0;
	font-size: var(--wp--custom--ui--size);
	font-weight: 400;
	line-height: var(--wp--custom--ui--line-height);
}

.ml-videodok__video {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	text-decoration: none;
	background-color: var(--wp--preset--color--blue-dark);
	border-radius: var(--wp--custom--radius--panel);
}

.ml-videodok__stage {
	margin: 0;
}

.ml-videodok__stage :is(figure, .wp-block-image) {
	margin: 0;
}

.ml-videodok__stage img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--wp--custom--videodok--stage);
	object-fit: cover;
}

.ml-videodok__label {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: var(--wp--custom--videodok--padding);
	font-size: var(--wp--custom--ui--size-l);
	font-weight: 700;
	line-height: var(--wp--custom--ui--claim-line-height);
	text-decoration: none;
}

.ml-videodok__video:hover .ml-videodok__label {
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

.ml-videodok__list {
	list-style: none;
	margin: 0;
	padding: 0;
	min-width: 0;
	border-top: 1px solid var(--wp--preset--color--white);
}

.ml-videodok__item {
	margin: 0;
	padding: 0;
	border-bottom: 1px solid var(--wp--preset--color--white);
}

.ml-videodok__doc {
	display: flex;
	align-items: center;
	gap: 0.875rem;
	padding-block: var(--wp--custom--videodok--zeile);
	/* 15px nach dem Entwurf (war ui--size-l = 17px). */
	font-size: var(--wp--custom--ui--size);
	font-weight: 600;
	line-height: var(--wp--custom--ui--line-height);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.ml-videodok__doc:hover {
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

.ml-videodok__doc .gb-shape,
.ml-videodok__label .gb-shape {
	display: inline-flex;
	flex: none;
}

/* GenerateBlocks liefert fuer das Symbol keine Groesse (gemessen: svg 0 x 0). */
.ml-videodok__doc .gb-shape svg,
.ml-videodok__label .gb-shape svg {
	display: block;
	width: var(--wp--custom--videodok--symbol);
	height: var(--wp--custom--videodok--symbol);
}

@media (max-width: 782px) {
	.ml-videodok__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* =============================================================================
   Bauauftrag 18 (0.41.0, 01.10.) - Milchlandpreis
   Werte aus theme.json (custom.abstand.sektionskopf, .gewinner, .note, .split,
   .videodok, .titel.feld.videodok). Dieser Block steht am Dateiende: bei
   gleicher Spezifitaet gewinnt er gegen die aelteren Regeln.
   ========================================================================== */

/* ---- Vorspann "einleitung": S03 und S15 --------------------------------

   Dieselbe Entwurfssektion ist auf zwei Seiten aus zwei verschiedenen
   Elementen gebaut: 720 fuehrt S03 (`ml-split`), 206 fuehrt S15
   (`ml-pagehead__title` + Absaetze in der Textspalte). Beide tragen
   dieselbe Achse `data-vorspann="einleitung"`, und die Werte stehen
   deshalb nur EINMAL - als Selektorliste, nicht als zweiter Block.
   Bei S15 ist der Titel ein h1, die Absaetze sind seine Geschwister;
   `p:first-of-type` trifft darum den ersten Absatz.
   ------------------------------------------------------------------- */
.ml-split[data-vorspann="einleitung"] .ml-split__body p:first-of-type,
.ml-section[data-vorspann="einleitung"] .ml-pagehead__title ~ p:first-of-type {
	font-size: 18px;
	font-weight: 500;
	line-height: 1.65;
}

.ml-split[data-vorspann="einleitung"] .ml-split__body p:nth-of-type(2),
.ml-section[data-vorspann="einleitung"] .ml-pagehead__title ~ p:nth-of-type(2) {
	font-size: 15px;
	font-weight: 400;
	line-height: 1.65;
	color: var(--wp--custom--text--gedaempft);
}

/* Bildformat (Bauauftrag 29, 0.53.0): data-bild steuert nur noch das Format
   (standard = 4 : 3 aus der Grundregel, foto = 3 : 2). Der Schatten haengt an
   .ml-split__media selbst und gilt fuer beide Formate. */
.ml-split[data-bild="foto"] .ml-split__media {
	aspect-ratio: var(--wp--custom--split--bild-foto);
}

/* ---- B01 Hinweisbox: zentrierte Variante (Achse data-mitte) --------------- */
.ml-note[data-mitte="ja"] {
	--ml-eigenbreite: var(--wp--custom--note--mitte-breite);
	max-width: var(--wp--custom--note--mitte-breite);
	margin-inline: auto;
	padding: var(--wp--custom--note--mitte-polster);
	text-align: center;
}

.ml-note[data-mitte="ja"] .ml-note__text {
	font-size: var(--wp--custom--ui--size-l);
	font-weight: 800;
	line-height: 1.5;
}

.ml-container > .ml-split + .ml-note[data-mitte="ja"] {
	margin-top: var(--wp--custom--note--mitte-abstand);
}

/* ---- B13 Reiter: Linie an der Leiste, Text statt Pille --------------------- */
.ml-tabs [role="tablist"] {
	border-bottom: 1px solid var(--wp--preset--color--blue);
	gap: 0;
}

.ml-tabs [role="tab"] {
	background-color: transparent;
	border-radius: 0;
	color: var(--wp--custom--text--gedaempft);
	border-bottom: 3px solid transparent;
	margin-bottom: -1px;
}

.ml-tabs [role="tab"]:hover,
.ml-tabs [role="tab"]:focus-visible {
	background-color: transparent;
	color: var(--wp--preset--color--black);
}

.ml-tabs [role="tab"][aria-selected="true"],
.ml-tabs [role="tab"][aria-selected="true"]:hover,
.ml-tabs [role="tab"][aria-selected="true"]:focus-visible {
	background-color: transparent;
	color: var(--wp--preset--color--blue-dark);
	border-bottom-color: var(--wp--preset--color--blue);
}

/*
 * Luecke Reiterleiste -> Panel: 40px (Entwurf Detailseite). Gemessen
 * vorher 24px - das ist der Blockabstand der Global Styles ueber
 * `:root :where(.is-layout-flow) > *` (0,1,0) am Panel-Wrapper.
 * (0,2,0) schlaegt ihn.
 */
.ml-tabs .wp-block-tab-panels {
	margin-block-start: var(--wp--custom--tabs--luecke);
}

/* Reiter mit Gewinnerkarten laufen auf Spurbreite statt 860 px. */
.ml-tabs:has(.ml-winner) {
	--ml-eigenbreite: 100vw;
	max-width: none;
}

/* ---- B08 Gewinnerkarte: Text | Foto | Video -------------------------------- */
.ml-winner[data-groesse="gross"] {
	padding: var(--wp--custom--gewinner--padding-gross);
}

.ml-winner[data-groesse="gross"] .ml-winner__name {
	font-size: var(--wp--custom--gewinner--name-gross);
}

.ml-winner[data-groesse="gross"]:has(> .ml-winner__video) {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--gap-l);
}

.ml-winner[data-groesse="normal"]:has(> .ml-winner__video) {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	grid-template-rows: 1fr auto;
	column-gap: var(--wp--preset--spacing--gap-l);
	row-gap: var(--wp--preset--spacing--gap-l);
}

.ml-winner[data-groesse="normal"]:has(> .ml-winner__video) > .ml-winner__body {
	grid-column: 1 / -1;
}

.ml-winner__video {
	min-width: 0;
}

/* Platzhalter: Foto fehlt / Video folgt. gedaempft auf gray-bg = 5,53 : 1. */
.ml-winner__media--leer,
.ml-winner__video {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: var(--wp--custom--gewinner--bild);
	background-color: var(--wp--preset--color--gray-bg);
	border: 1px dashed var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
	text-align: center;
}

/*
 * Kuhflecken auf der Videoflaeche der Gewinnerkarte (002, Entwurf
 * Milchlandpreis): Flaeche gefuellt, 150 %, mittig, wiederholt. Nur das
 * direkte Kind der Karte - die S22-Buehne nutzt dieselbe Klasse ohne Flecken.
 */
.ml-winner > .ml-winner__video {
	position: relative;
	overflow: hidden;
}

.ml-winner > .ml-winner__video::before {
	content: "";
	position: absolute;
	inset: 0;
	background-color: var(--wp--preset--color--black);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: 150%;
	-webkit-mask-size: 150%;
	mask-position: center;
	-webkit-mask-position: center;
	mask-repeat: repeat;
	-webkit-mask-repeat: repeat;
	opacity: var(--wp--custom--gewinner--flecken-deckkraft);
	pointer-events: none;
}

.ml-winner > .ml-winner__video > * {
	position: relative;
}

.ml-winner__platzhalter {
	font-size: var(--wp--custom--ui--size);
	font-weight: 700;
	color: var(--wp--custom--text--gedaempft);
}

@media (max-width: 782px) {
	.ml-winner[data-groesse="gross"]:has(> .ml-winner__video),
	.ml-winner[data-groesse="normal"]:has(> .ml-winner__video) {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: none;
	}
}

@media (max-width: 480px) {
	.ml-winner[data-groesse="gross"] {
		padding: var(--wp--custom--gewinner--padding);
	}
}

/* ---- S22 Videos und Dokumente --------------------------------------------- */
.ml-videodok {
	position: relative;
	overflow: hidden;
	padding-block: var(--wp--custom--videodok--polster);
}

.ml-videodok > .ml-container {
	position: relative;
	z-index: 1;
}

.ml-videodok__flecken {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	overflow: hidden;
	pointer-events: none;
}

/* Seit 002: Motiv als Maske, weiss auf Blau, quadratisch (altes Inline-SVG seit 017 entfernt). */

.ml-videodok__flecken::before {
	content: "";
	position: absolute;
	top: var(--wp--custom--videodok--flecken-oben);
	right: var(--wp--custom--videodok--flecken-rechts);
	width: var(--wp--custom--videodok--flecken-groesse);
	height: var(--wp--custom--videodok--flecken-groesse);
	background-color: var(--wp--preset--color--white);
	mask-image: var(--ml-kuhflecken);
	-webkit-mask-image: var(--ml-kuhflecken);
	mask-size: contain;
	-webkit-mask-size: contain;
	mask-repeat: no-repeat;
	-webkit-mask-repeat: no-repeat;
	opacity: var(--wp--custom--videodok--flecken-deckkraft);
}

.ml-videodok__grid {
	grid-template-columns: var(--wp--custom--videodok--spalten);
	gap: var(--wp--custom--videodok--luecke);
}

.ml-videodok__item {
	border-bottom-color: var(--wp--custom--videodok--linie);
}

.ml-videodok__list {
	border-top-color: var(--wp--custom--videodok--linie);
}

.ml-videodok__doc .gb-shape svg {
	width: var(--wp--custom--videodok--dok-symbol);
	height: var(--wp--custom--videodok--dok-symbol);
}

.ml-videodok .ml-sectionhead .ml-display {
	max-width: var(--wp--custom--titel--feld--videodok);
}

.editor-styles-wrapper .ml-videodok .ml-sectionhead .ml-display.wp-block {
	max-width: var(--wp--custom--titel--feld--videodok);
}

@media (max-width: 782px) {
	.ml-videodok__grid {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--wp--preset--spacing--band);
	}
}

/* ---- Sektionskopf -> Inhalt: 56 px als Token, nur am Sektionskopf ------------ */
.ml-sectionhead {
	margin-bottom: var(--wp--custom--abstand--sektionskopf);
}

/* TOP 11: alle Karten gleich hoch, auch ueber Zeilen hinweg (gemessen 1024 px: Zeilen 504,97 / 531,63). */
.ml-tabs .wp-block-tab-panel:not([hidden]):has(> .ml-winner[data-groesse="normal"]) {
	grid-auto-rows: 1fr;
}

/* Nachtrag 3 (0.41.3): Vorschau-Platzhalter in der S22-Videokachel - Format der Buehne, ohne gestrichelten Rand. */
.ml-videodok__stage .ml-winner__video {
	aspect-ratio: var(--wp--custom--videodok--stage);
	border: 0;
	border-radius: 0;
}

/* Auf Blau steht der Platzhaltertext sonst weiss auf Hellgrau (.ml-videodok span, 0,1,1). */
.ml-videodok .ml-winner__platzhalter {
	color: var(--wp--custom--text--gedaempft);
}

/* ==========================================================================
   S20 / S21 — zweite Achse `data-kasten` (0.42.0, 01.10.)
   ==========================================================================
   Der Entwurf „Beitragsseite Upcycling" zeigt EINE weisse Sektion mit ZWEI
   grauen Kaesten, 32 px auseinander. Gebaut als zweite Achse am Element, nicht
   als Aenderung der Grundform: Vorgabe ist `nein`, und wer nichts einstellt,
   merkt nichts. Vorbild ist `data-vorspann` an S03 und `data-mitte` an B01.

   Die Spezifitaet ist absichtlich (0,3,0): `.ml-flaeche[data-variante="grau"]`
   liegt bei (0,2,0), und die Achse muss unabhaengig von der Quellreihenfolge
   gewinnen (Regel 12 der Bauvorlage).
   ========================================================================== */

.ml-flaeche.ml-zutaten[data-kasten="ja"],
.ml-flaeche.ml-schritte[data-kasten="ja"] {
	/*
	 * Oben der Sektionsabstand, unten nichts (03.10., Bauauftrag 24). Die Null
	 * vom 01.10. war fuer den Abstand ZWISCHEN den Kaesten richtig und fuer den
	 * UEBER dem ersten falsch: Kopf und Kasten stiessen ohne Luft aneinander.
	 * Der zweite Kasten ueberschreibt padding-top mit der `+`-Regel unten
	 * (0,4,0 gegen 0,3,0) und behaelt seine 32px; unten steht die Teilen-Zeile
	 * mit eigenem Innenabstand.
	 */
	padding-block: var(--wp--preset--spacing--sektion) 0;
	/*
	 * Gemessen am 01.10.: Kasten auf der Seitenflaeche (#F7F8F9) 1,0629 —
	 * praktisch keine Kante. Auf Weiss 1,1302, der Hauswert fuer gray-bg auf
	 * Weiss. Der Entwurf nennt eine weisse Sektion, deshalb traegt die Achse
	 * die Flaeche und nicht die Variante `hell` (die bewusst keine Regel hat).
	 */
	background-color: var(--wp--preset--color--white);
}

/* Der innere Block traegt die Flaeche und den Radius. */
.ml-zutaten[data-kasten="ja"] > .ml-container,
.ml-schritte[data-kasten="ja"] > .ml-container {
	padding: var(--wp--preset--spacing--band);
	background-color: var(--wp--preset--color--gray-bg);
	border-radius: var(--wp--custom--radius--panel);
}

/* Bis 768 px Innenabstand `gap-l` (24) statt `band` (48) - Entscheidung 14.10.
   (015). Gemessen vorher bei 390: Kasten 348, Liste nur 252 breit. */
@media (max-width: 768px) {
	.ml-zutaten[data-kasten="ja"] > .ml-container,
	.ml-schritte[data-kasten="ja"] > .ml-container {
		padding: var(--wp--preset--spacing--gap-l);
	}
}

/* Zwei Kaesten hintereinander: der Abstand aus dem Entwurf. */
.ml-zutaten[data-kasten="ja"] + .ml-zutaten[data-kasten="ja"],
.ml-zutaten[data-kasten="ja"] + .ml-schritte[data-kasten="ja"],
.ml-schritte[data-kasten="ja"] + .ml-zutaten[data-kasten="ja"],
.ml-schritte[data-kasten="ja"] + .ml-schritte[data-kasten="ja"] {
	/*
	 * padding statt margin: der Zwischenraum gehoert zur weissen Flaeche.
	 * Als margin zeigte er die Seitenflaeche und zerschnitt das Band.
	 */
	padding-top: var(--wp--custom--anleitung--kasten-abstand);
}

/*
 * Dasselbe im Editor (03.10., Bauauftrag 24). GenerateBlocks legt dort um
 * jedes Wurzelelement einen eigenen Wrapper (`.gb-is-root-block`); die Sektion
 * hat kein Geschwister, die `+`-Regel oben greift nicht (Stolperstelle 35).
 * Ohne diese Regel zeigte der Editor am zweiten Kasten den vollen
 * Sektionsabstand statt der 32px des Frontends. Der Wrapper ist in der
 * Bahn-Regel bereits Bezugspunkt.
 */
.editor-styles-wrapper .gb-is-root-block:has(> :is(.ml-zutaten, .ml-schritte)[data-kasten="ja"]) + .gb-is-root-block > :is(.ml-zutaten, .ml-schritte)[data-kasten="ja"] {
	padding-top: var(--wp--custom--anleitung--kasten-abstand);
}
/*
 * Im Kasten kein Ueberstand. Der Versatz von 92 px laesst das Bild sonst aus
 * der grauen Flaeche heraus und in den naechsten Kasten laufen — bei 32 px
 * Abstand unvermeidlich. Der Ueberstand des Entwurfs wird in dieser Achse
 * bewusst nicht nachgebaut.
 */
.ml-zutaten[data-kasten="ja"] .ml-zutaten__bild {
	margin-bottom: 0;
}

/*
 * 390 px gemessen: 8,98 px Ueberlauf nach rechts. Im Kasten bleiben nach
 * 2 x 48 px Innenabstand 252,03 px, die Rasterspalte stand aber weiter bei
 * 330 px — dem festen Bildmass. `min-width: 0` am Rasterkind aendert daran
 * nichts (am lebenden Objekt gemessen: min-width 0px, Spur unveraendert 330px).
 *
 * `minmax(0, 1fr)` nimmt der Spur die inhaltsbasierte Untergrenze. Danach
 * greift das vorhandene `max-width: 100%` am Bildkasten: 252,03 px bei 390 px,
 * Ueberlauf 0. Nur die einspaltige Lage wird angefasst — oberhalb von 1080 px
 * bleibt das Bild bei den 330 px des Entwurfs (gegengeprueft bei 1440 px).
 */
@media (max-width: 1080px) {

	.ml-zutaten[data-kasten="ja"] .ml-zutaten__raster {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* --------------------------------------------------------------------------
   Die Kante am Seitenende der Einzelansicht (0.43.1, 02.10.)
   --------------------------------------------------------------------------
   Am 02.10. auf der Materialseite gemessen: Ansprechpartner #F1F1F0 (y 2457,
   719 px hoch) und verwandte Eintraege #F1F1F0 (y 3177, 853 px) — zwei
   gleiche Flaechen hintereinander, Verhaeltnis 1,0000, ohne Linie. Das ist
   dieselbe Lage, die am 01.10. die Achse `data-kasten` begruendet hat.

   Die Flaeche wechselt am Block (Variante `grau` -> `hell`, Verhaeltnis dann
   1,0629). Diese Regel setzt nur die Linie des Entwurfs:
   #E8E8E8 auf #F1F1F0 = 1,0841 (Entwurfswert), auf #F7F8F9 = 1,1523 — bei uns
   also etwas deutlicher als dort.

   An den Body-Klassen, nicht an der Variante allein: `hell` steht auch an der
   News-Abfrage der privaten Seite „Milchlandpreis 2025", und die bleibt
   unberuehrt. Kein vierter Flaechenwert — #FAFAFA bleibt ungefuehrt
   (Entscheidung vom 30.09., 1,0187 gegen die Seitenflaeche).
   -------------------------------------------------------------------------- */

.single-material .ml-material-abfrage[data-variante="hell"],
.single-post .ml-news-abfrage[data-variante="hell"] {
	border-top: 1px solid var(--wp--preset--color--rule);
}
/* --------------------------------------------------------------------------
   Zwei gleiche Flaechen hintereinander: die Kante (0.43.2, 02.10.)
   --------------------------------------------------------------------------
   Am 02.10. auf /fuer-kids/milchspass/ gemessen: sieben Abschnitte
   `ml-material-abfrage` in Folge, alle `data-variante="grau"`, alle #F1F1F0 —
   sechs Paare mit Verhaeltnis 1,0000 und 6.427 px gleiche Flaeche ohne eine
   einzige Linie.

   Die Flaechen werden hier NICHT abgewechselt: es sind sieben gleichrangige
   Abschnitte derselben Art (H2 Malen … H2 Lernen, je ein Kartenraster). Eine
   abwechselnde Flaeche wuerde eine Rangordnung behaupten, die es nicht gibt.
   Die durchgehende Flaeche bleibt, was fehlt ist die Kante.

   Der Nachbarschafts-Selektor zielt auf den Defekt, nicht auf die Seite: er
   greift nur, wo zwei gleiche Flaechen tatsaechlich aneinanderstossen, und
   nimmt jede kuenftige Stelle von selbst mit. Am 02.10. am gerenderten Markup
   gezaehlt: 8 Treffer — 6 auf Seite 506, 2 auf dem Entwurf 868. Auf Seite 61
   greift er bewusst nicht: dort liegen die weissen Beschriftungsstreifen des
   Katalogs (`ml-section-tight`) zwischen den Flaechen, die Flaechen beruehren
   sich also nicht (Stolperstelle 35).

   #E8E8E8 auf #F1F1F0 = 1,0841 — derselbe Wert, den der Entwurf setzt.
   -------------------------------------------------------------------------- */

/* Nachtrag 11.10. (Befund 49 A, S20 + S21): Diese Regel vom 02.10. hatte keine
   Kasten-Ausnahme - die Linie fuer HELLE Flaechen bekam sie erst am 10.10.
   (Bauauftrag 45, Posten 1). Stellt der Redakteur S20 und S21 auf "Kasten",
   bleiben die Musterflaechen `grau`, und die Linie lief zwischen zwei Kaesten
   durch - genau der Fall, den die Ausnahme ausschliessen sollte. Dieselbe
   Zwei-Regel-Form wie dort: die erste greift, wenn die ZWEITE Sektion kein
   Kasten ist, die zweite, wenn nur die ERSTE keiner ist. "Beide Kaesten" wird
   von keiner getroffen. Die 7 Treffer auf /fuer-kids/milchspass/ (kein Kasten)
   bleiben unberuehrt. */

.ml-flaeche[data-variante="grau"]
	+ .ml-flaeche[data-variante="grau"]:not([data-kasten="ja"]) {
	border-top: 1px solid var(--wp--preset--color--rule);
}

.ml-flaeche[data-variante="grau"]:not([data-kasten="ja"])
	+ .ml-flaeche[data-variante="grau"][data-kasten="ja"] {
	border-top: 1px solid var(--wp--preset--color--rule);
}

/* --------------------------------------------------------------------------
   Dieselbe Kante zwischen zwei HELLEN Flaechen (Bauauftrag 45, Posten 1, 10.10.)
   --------------------------------------------------------------------------
   Bau 44 hat die Regel nicht gebaut, weil 5 Treffer auf 3 veroeffentlichten
   Adressen lagen (Abbruchbedingung). Entscheidung der Steuerung vom 09.10.:
   bauen - und die Kaesten ausnehmen.

   Die weisse Gruppe ist dieselbe wie seit dem 02.10.: `hell` und "ohne
   Variante" rendern beide #FFFFFF. S04 und S07 (nur `ml-section`) gehoeren
   seit 015 dazu (Entscheidung 14.10.), siehe die Regel direkt unten.
   Gemessen am 10.10.: 2 solche Stoesse auf der Elementuebersicht, 1 auf 1041,
   2 auf 1058 - sie bleiben ohne Linie.

   Die Ausnahme gilt dem PAAR, nicht der einzelnen Sektion. Am
   Fledermauseimer stossen zwei Kaesten aneinander (`data-kasten="ja"`, im
   ganzen Bestand nur dort, zweimal): graue Kaesten auf weisser Flaeche, die
   Trennung leisten die Kaesten selbst. Eine Linie ueber die volle Breite laege
   dort zwischen zwei Kaesten. Steht dagegen eine gewoehnliche helle Sektion
   neben einem Kasten, stoesst Flaeche an Flaeche - dort SOLL die Linie kommen.

   Darum zwei Regeln statt einer Regel mit Ruecknahme: die erste greift, wenn
   die zweite Sektion kein Kasten ist, die zweite, wenn nur die erste keiner
   ist. Der Fall "beide Kaesten" wird von keiner getroffen. Vier DOM-Faelle,
   gemessen am 10.10.: Kasten+Kasten nein, Kasten+normal ja, normal+Kasten ja,
   normal+normal ja.

   #E8E8E8 auf #FFFFFF = 1,2253 - deutlicher als auf grau (1,0841), wo die
   Linie am 02.10. gebaut wurde.
   -------------------------------------------------------------------------- */

/* 015 (Entscheidung 14.10.): S04 und S07 gehoeren jetzt dazu - dieselbe
   Weissgruppe wie die Abstandsregel von Punkt 22 (`ml-section` ohne eigene
   Flaeche), aber OHNE die Erklaerkaesten der Elementuebersicht
   (`ml-section-tight`): sonst stuende ueber und unter jedem Kasten eine Linie.
   Gezaehlt am 14.10.: 1 neues Paar, auf der Elementuebersicht; 0 auf allen
   anderen veroeffentlichten Seiten. */
:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight))
	+ :is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight)):not([data-kasten="ja"]) {
	border-top: 1px solid var(--wp--preset--color--rule);
}

:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight)):not([data-kasten="ja"])
	+ :is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight))[data-kasten="ja"] {
	border-top: 1px solid var(--wp--preset--color--rule);
}

/*
 * Im Editor liegt zwischen Elternebene und Sektion der Wrapper
 * `.block-editor-block-list__block` (bei GenerateBlocks zusaetzlich
 * `.gb-is-root-block`) - die Sektionen sind dort keine Geschwister mehr, und
 * der `+`-Selektor oben greift nicht. Dieselbe Mechanik wie bei Punkt 22.
 * Mitgezogen wird hier auch GRAU: die Linie vom 02.10. fehlte im Editor
 * bisher ebenfalls (gemessen am 10.10.), und Editor und Seite sollen gleich
 * aussehen.
 */
.editor-styles-wrapper .block-editor-block-list__layout
	> .block-editor-block-list__block:has(:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight)))
	+ .block-editor-block-list__block:has(:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight)):not([data-kasten="ja"]))
	:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok, .ml-section-tight)) {
	border-top: 1px solid var(--wp--preset--color--rule);
}

.editor-styles-wrapper .block-editor-block-list__layout
	> .block-editor-block-list__block:has(.ml-flaeche[data-variante="grau"])
	+ .block-editor-block-list__block:has(.ml-flaeche[data-variante="grau"])
	.ml-flaeche[data-variante="grau"] {
	border-top: 1px solid var(--wp--preset--color--rule);
}
/* --------------------------------------------------------------------------
   Der Vorsatz im Hinweiskasten (0.42.1, 01.10.)
   --------------------------------------------------------------------------
   Der Entwurf setzt im Hinweiskasten einen fetten Vorsatz — „Alternative:",
   „Tipp:", „Achtung:", je nach Inhalt. Das Wort gehoert deshalb in den Text und
   nicht als ::before an das Element: eine feste Beschriftung aus CSS traefe
   beide Instanzen und stuende auf Seite 61 doppelt vor dem Blindtext.

   Gewicht 800 wie an den anderen hervorgehobenen Titeln (`body h3`,
   `.ml-note__title`, `.ml-video__title`). theme.json fuehrt kein Token fuer
   Schriftgewichte; die nackte Zahl ist hier die Hausschreibweise.
   -------------------------------------------------------------------------- */

.ml-schritte__tipp strong {
	font-weight: 800;
}

/* --------------------------------------------------------------------------
   Schlusszeile in der Teilen-Leiste
   -------------------------------------------------------------------------- */

/*
 * Der Entwurf setzt die Schlusszeile neben die Teilen-Leiste, und genau dort
 * steht sie schon: im Block `mltltx` der beiden Content Templates, Wort fuer
 * Wort wie im Entwurf und mit demselben Ziel. Am 01.10. an der Quelle
 * nachgelesen — der Befund „Schlusszeile fehlt" galt nur fuer den
 * Seiteninhalt. Eine zweite Zeile im Seiteninhalt stand deshalb doppelt
 * (gemessen: y = 2274 und y = 3342) und ist wieder entfernt.
 *
 * Die Masse aus dem Auftrag gelten also hier. Vorher gemessen: 18 px / 400,
 * danach 20 px / 600, Kontrast Text 14,96 und Link 4,62 bei Unterstreichung.
 *
 * Nachgezaehlt am 01.10.: Die Teilen-Leiste steht nur in der Vorlage
 * „Material-Einzelansicht" (Element 626), die Beitrags-Vorlage (701) hat keine.
 * Von 53 veroeffentlichten Material-Eintraegen rendert heute genau einer seine
 * Einzelansicht (615), die anderen 52 springen auf ihre Datei. Die Regel
 * greift also auf einer Seite und auf jedem kuenftigen Eintrag mit Inhalt.
 */
.ml-teilen__text {
	margin: 0;
	font-size: var(--wp--custom--anleitung--abschluss-text);
	font-weight: 600;
	line-height: var(--wp--custom--line-height--body);
}

/*
 * Der Link braucht mehr als Farbe. Unterstreichung ist die Auszeichnung, die
 * auch ohne Farbwahrnehmung traegt (WCAG 1.4.1). Der Abstand macht sie bei
 * 20 px lesbar, ohne die Grundlinie zu beruehren.
 */
.ml-teilen__text a {
	color: var(--wp--preset--color--blue);
	text-decoration: underline;
	text-underline-offset: 0.18em;
}

.ml-teilen__text a:hover,
.ml-teilen__text a:focus-visible {
	text-decoration-thickness: 2px;
}

/* ==========================================================================
   Bauauftrag 25 (0.48.0, 03.10.) - Milchlandpreis: S22 zweizeilig, Gewinnerkarte ohne Blaukante
   Zeile 1 = .ml-videodok__grid (Dokumente | Video 1), Zeile 2 = .ml-videodok__zeile
   (Video 2 | Nachsatz). Werte aus theme.json (custom.videodok.*). Die Kontaktkarte
   (.ml-team__card) ist eine eigene Klasse und behaelt ihre Oberkante.
   ========================================================================== */
.ml-videodok__zeile {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-items: center;
	gap: var(--wp--custom--videodok--zeile-luecke);
	margin-top: var(--wp--custom--videodok--luecke);
	padding-top: var(--wp--custom--videodok--vorlauf);
}

.ml-videodok__nachsatz {
	min-width: 0;
}

.ml-videodok__nachsatz > .ml-videodok__text {
	margin-bottom: var(--wp--custom--videodok--nachsatz-absatz);
}

.ml-videodok__nachsatz > .ml-videodok__text:last-of-type {
	margin-bottom: var(--wp--custom--videodok--nachsatz-liste);
}

@media (max-width: 782px) {
	.ml-videodok__zeile {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--wp--preset--spacing--band);
		margin-top: var(--wp--preset--spacing--band);
		padding-top: 0;
	}
}

/* ==========================================================================
   Bauauftrag 43 (0.66.0, 09.10.) - Elementmaengel aus Pruefauftrag 42
   Die uebrigen Posten stehen an ihren Regeln (E1-E4, E6, E9, E10, Y3).
   ========================================================================== */

/* ---- E7 · S04 Kartentitel 21 statt 21,9952 --------------------------------
   Nur die Themenkarte. Das Token deckelt die Rolle `titel-m` bei 21 px
   (ab 1171 px Fensterbreite); darunter bleibt die Kurve gleich, bei 390
   also 18,11 px wie vorher. Rasterabstand bleibt 24 (Entscheidung 09.10.). */
.ml-card-thema .ml-card__title {
	font-size: var(--wp--custom--karte--titel-thema);
}

/* ---- E8 · S23 Beschriftung „Teilen" -------------------------------------
   Entwurf 16 / 700 in #7F7F7F (4,0041) - die Farbe nicht: gedaempft wie
   jeder Hilfstext (5,7418 auf Weiss). Sitzt im Container `.ml-duo__teilen`
   und faellt mit ihm weg (data-teilen="nein"). */
.ml-teilen__titel {
	margin: 0;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	line-height: 1.25;
	color: var(--wp--custom--text--gedaempft);
}

/* ---- Posten 5 · Datum eines Beitrags ---------------------------------------
   Kommt aus dem GP-Element „Beitragsdatum" (Haken generate_before_do_template_part,
   Prioritaet 5, vor der Beitrags-Einzelansicht mit 10; Bedingung post:post).
   Steht als Kicker UEBER der ersten Sektion: das Band traegt deren Flaeche,
   die erste Sektion rueckt auf den Kickerabstand (`abstand.label`, 14) heran.
   Farbe blue-dark wie der Sektionskopf-Kicker: Markenblau faellt auf `grau`
   mit 4,3419 und auf `tint` mit 4,3647 unter 4,5. */
.ml-beitragsdatum {
	padding: var(--wp--preset--spacing--sektion) var(--wp--preset--spacing--rand) 0;
	background-color: var(--wp--preset--color--white);
}

/* GeneratePress setzt `.separate-containers .site-main > * { margin-bottom: 20px }` -
   ohne diese Regel stand zwischen Band und Sektion ein 20-px-Streifen Seitenflaeche. */
.site-main > .ml-beitragsdatum {
	margin-bottom: 0;
}

.ml-beitragsdatum .ml-beitragsdatum__text {
	margin: 0;
	color: var(--wp--preset--color--blue-dark);
	opacity: 1;
}

body.single-post:has(.dynamic-entry-content > .ml-flaeche[data-variante="grau"]:first-child) .ml-beitragsdatum {
	background-color: var(--wp--preset--color--gray-bg);
}

body.single-post:has(.dynamic-entry-content > .ml-flaeche[data-variante="tint"]:first-child) .ml-beitragsdatum {
	background-color: var(--wp--preset--color--blue-tint);
}

.single-post .dynamic-entry-content > .ml-flaeche:is(:not([data-variante]), [data-variante="hell"], [data-variante="grau"], [data-variante="tint"]):first-child {
	padding-top: var(--wp--custom--abstand--label);
}

/* ==========================================================================
   Bauauftrag 2, Punkt 5 (10.10.) - die ganze Karte klickbar, sobald im Titel
   ein Link steht
   --------------------------------------------------------------------------
   Die Mechanik stand seit jeher, aber nur fuer `.ml-card__link` - die Klasse,
   die die Abfragen (S05, S14, S17, S18) ueber ihre Dynamic Tags mitbringen.
   Gezaehlt am 10.10.: 73 Kartentitel-Links im Bestand, alle mit der Klasse,
   **0 ohne**. Setzt der Redakteur selbst einen Link in einen Kartentitel -
   genau der Fall einer Themenkarte -, bekommt er ein nacktes <a> und die
   Karte blieb auf ihren Titel beschraenkt klickbar.

   Deshalb gilt ab hier jeder Link IM KARTENTITEL als Kartenlink. Kein Link
   im Titel heisst weiterhin: keine Klickflaeche (Anforderung des Auftrags).
   `.ml-card` traegt bereits `position: relative`, das ::after zieht also auf
   die Karte auf, nicht auf einen fremden Vorfahren.
   ========================================================================== */

.ml-card__title a {
	color: inherit;
	text-decoration: none;
}

.ml-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.ml-card:has(.ml-card__title a:hover) {
	border-color: var(--wp--preset--color--blue);
}

.ml-card:has(.ml-card__title a:hover) .ml-card__title {
	color: var(--wp--preset--color--blue);
}

.ml-card:has(.ml-card__title a:hover) .ml-card__stage img {
	transform: scale(1.03);
}

.ml-card:has(.ml-card__title a:focus-visible) {
	outline-style: solid;
	outline-width: var(--wp--custom--focus--width);
	outline-color: var(--ml-focus, var(--wp--preset--color--blue));
	outline-offset: var(--wp--custom--focus--offset);
}

.ml-card__title a:focus-visible {
	outline: none;
}


/* ==========================================================================
   Bauauftrag 2, Paket D (10.10.) - Darstellung im Frontend
   ========================================================================== */

/* ---- Punkt 11 - Galerie mit EINEM Bild ------------------------------------
   Ein einzelnes Bild fuellt die Bahn und steht mit 4:3 sehr hoch (bei 1328 px
   Bahn waeren das 996 px). Mit nur einer Kachel ist das kein Raster mehr,
   sondern eine Abbildung - die bekommt 3:2, wie die Bildbuehne in S03.
   `:has(> figure:only-of-type)` trifft genau den Fall einer einzigen Kachel.
   -------------------------------------------------------------------------- */
.ml-gallery .wp-block-gallery.has-nested-images:has(> figure.wp-block-image:only-of-type) img {
	aspect-ratio: 3 / 2;
}

/* ---- Punkt 12 - fuenf Kennzahlen: ZURUECKGENOMMEN (E1, 11.10.) ------------
   Hier stand eine Regel, die bei genau fuenf Kennzahlen auf drei Spalten
   schaltete, damit die fuenfte Zahl nicht allein in der zweiten Reihe steht.
   Die Entscheidung E1 vom 11.10. laesst die Vorgabe gelten: S08 traegt GENAU
   VIER Kennzahlen. Eine Regel fuer einen Fall, den es laut Vorgabe nicht gibt,
   verdeckt den Fehler statt ihn zu zeigen - mit fuenf Zahlen steht die fuenfte
   jetzt wieder sichtbar allein, und das ist der gewollte Hinweis an die
   Redaktion. Punkt 12 aus dem Bildvergleich ist damit zurueckgenommen.
   -------------------------------------------------------------------------- */

/* ---- Punkt 14 - Pfeile nur, wenn es etwas zu blaettern gibt ---------------
   Steht im Karussell nur eine Folie, fuehren die Pfeile ins Leere. Sie
   verschwinden dann samt Auswahlpunkten.
   (Fassung 2 vom 10.10. - die erste zaehlte nur Folien und traf den
   falschen Klassennamen.)
   -------------------------------------------------------------------------- */
/* Zwei Faelle, beide am gerenderten Markup gemessen (10.10.):
   a) Eine einzige Folie - dann gibt es nichts zu blaettern.
   b) Alle Folien stehen vollstaendig im Bild. Swiper setzt dafuer selbst
      `swiper-slide-fully-visible` und aktualisiert es bei jeder
      Groessenaenderung; CSS liest mit. "Kein Item OHNE die Klasse" ist
      die CSS-Fassung von "alle Items tragen sie".
   Die Folie heisst `gb-carousel-item`, NICHT `gb-carousel-slide` - der
   erste Entwurf dieser Regel zielte auf den falschen Namen und griff nie.
   Die Pfeile tragen `data-carousel-control` und liegen in
   `.ml-cardslider__nav` VOR der Folienbahn. */
:is(.ml-cardslider, .ml-slider):not(:has(.gb-carousel-item:not(.swiper-slide-fully-visible))) :is([data-carousel-control], .gb-carousel-pagination, .ml-cardslider__nav) {
	display: none;
}

/* ---- Punkt 22 - gleiche Flaeche zweimal: der obere Innenabstand entfaellt --
   Zwei Sektionen derselben Farbe sind optisch EINE Flaeche. Beide bringen
   ihren vollen Sektionsabstand mit, gemessen am 09.10. im Zusammenbau:
   120 unten + 120 oben + 19 Rand = 259 px zwischen zwei Inhalten, ohne dass
   man der Flaeche ansieht, dass dort eine Grenze liegt.

   Gruppiert nach TATSAECHLICHER Farbe, nicht nach Klasse. Weiss umfasst
   deshalb auch S04 und S07: sie tragen nur `ml-section` und erben Weiss
   (gemessen 09.10.). Die Negation listet die vier Baender, die eine eigene
   Farbe mitbringen - wer eine neue farbige Sektion baut, traegt sie hier
   nach, sonst gilt sie als weiss (Stolperstelle 35).

   AUSGENOMMEN, wie beauftragt: Hero und Zahlenleiste (eigene Baender mit
   eigenem Mass) und die Kasten-Variante `data-kasten="ja"` - dort steht der
   Abstand zwischen zwei Kaesten, nicht zwischen zwei Flaechen.

   Die Kante zwischen zwei grauen Flaechen (0.43.2) bleibt: ohne Abstand
   wird sie wichtiger, nicht ueberfluessig.
   -------------------------------------------------------------------------- */

/* weiss auf weiss */
:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok)) + :is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok)):not(.ml-hero, .ml-stats-section, [data-kasten="ja"]) {
	padding-top: 0;
}

/* grau auf grau */
:is(.ml-flaeche[data-variante="grau"]) + :is(.ml-flaeche[data-variante="grau"]):not(.ml-hero, .ml-stats-section, [data-kasten="ja"]) {
	padding-top: 0;
}

/* getoent auf getoent */
:is(.ml-flaeche[data-variante="tint"]) + :is(.ml-flaeche[data-variante="tint"]):not(.ml-hero, .ml-stats-section, [data-kasten="ja"]) {
	padding-top: 0;
}

/* dunkel auf dunkel */
:is(.ml-flaeche[data-variante="schwarz"], .ml-section-dark) + :is(.ml-flaeche[data-variante="schwarz"], .ml-section-dark):not(.ml-hero, .ml-stats-section, [data-kasten="ja"]) {
	padding-top: 0;
}

/* Im Editor stehen dieselben Klassen, aber jede Sektion liegt in einem
   Block-Wrapper - die Geschwisterbeziehung laeuft dort eine Ebene hoeher.
   Eigene Regel, damit der Redakteur sieht, was erscheint. */
.editor-styles-wrapper .block-editor-block-list__layout > .block-editor-block-list__block:has(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok)) + .block-editor-block-list__block:has(:is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok)):not(.ml-hero, .ml-stats-section, [data-kasten="ja"])) :is(.ml-flaeche:not([data-variante]), .ml-flaeche[data-variante="hell"], .ml-section:not(.ml-flaeche, .ml-hero, .ml-stats-section, .ml-section-dark, .ml-videodok)) {
	padding-top: 0;
}
.editor-styles-wrapper .block-editor-block-list__layout > .block-editor-block-list__block:has(.ml-flaeche[data-variante="grau"]) + .block-editor-block-list__block:has(:is(.ml-flaeche[data-variante="grau"]):not(.ml-hero, .ml-stats-section, [data-kasten="ja"])) :is(.ml-flaeche[data-variante="grau"]) {
	padding-top: 0;
}
.editor-styles-wrapper .block-editor-block-list__layout > .block-editor-block-list__block:has(.ml-flaeche[data-variante="tint"]) + .block-editor-block-list__block:has(:is(.ml-flaeche[data-variante="tint"]):not(.ml-hero, .ml-stats-section, [data-kasten="ja"])) :is(.ml-flaeche[data-variante="tint"]) {
	padding-top: 0;
}
.editor-styles-wrapper .block-editor-block-list__layout > .block-editor-block-list__block:has(.ml-flaeche[data-variante="schwarz"], .ml-section-dark) + .block-editor-block-list__block:has(:is(.ml-flaeche[data-variante="schwarz"], .ml-section-dark):not(.ml-hero, .ml-stats-section, [data-kasten="ja"])) :is(.ml-flaeche[data-variante="schwarz"], .ml-section-dark) {
	padding-top: 0;
}
/* -------------------------------------------------------------------------
 * Editor-Hinweise (Bauauftrag 2, Punkte 6 und 7, 10.10.2026)
 *
 * Gesetzt von assets/js/editor-hinweise.js am Block-Umschlag: Klasse `ml-hinweis`,
 * Attribut `data-ml-hinweis` (der Text) und `title` (derselbe Text als Werkzeugspitze).
 * Der Text steht im Skript, nicht hier - die CSS liest ihn mit attr().
 *
 * Zwei Teile: ein Rahmen ueber `outline` (verschiebt kein Layout und wirkt auch an einem
 * <img>) und eine Textfahne ueber ::after. An einem <img> zeichnet kein Browser ::after;
 * dort bleiben Rahmen und Werkzeugspitze. Die Klasse kommt nur im Editor vor, deshalb
 * aendert dieser Abschnitt im Frontend nichts.
 * ---------------------------------------------------------------------- */

.editor-styles-wrapper .ml-hinweis {
	outline: 2px dashed var(--wp--custom--hinweis--rand);
	outline-offset: 2px;
}

.editor-styles-wrapper .ml-hinweis[data-ml-hinweis]::after {
	content: attr(data-ml-hinweis);
	display: block;
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	z-index: 2;
	max-width: 100%;
	padding: var(--wp--custom--hinweis--polster);
	background: var(--wp--custom--hinweis--grund);
	border: 1px solid var(--wp--custom--hinweis--rand);
	border-radius: var(--wp--custom--radius--card);
	color: var(--wp--custom--hinweis--text);
	font-family: var(--wp--preset--font-family--system, inherit);
	font-size: var(--wp--custom--hinweis--schrift);
	line-height: var(--wp--custom--line-height--bedienung);
	text-align: start;
	pointer-events: none;
}

/* Bezug fuer die Fahne. `relative` nur, wenn der Block nicht schon selbst positioniert ist. */
.editor-styles-wrapper .ml-hinweis[data-ml-hinweis]:not(.ml-hero, [class*="__stage"]) {
	position: relative;
}

/* -------------------------------------------------------------------------
 * Der Editor rechnet dieselben Werte wie die Seite (Bauauftrag 45, Posten 3, 10.10.)
 *
 * Zwei echte Abweichungen, eine Scheinabweichung. Gemessen im Block-Editor-Iframe
 * dieser Instanz, bei Fenster 1440 (Iframe 1000 px) und 1920 (Iframe 1480 px).
 *
 * KEIN Fehler war die Schriftgroesse. `font-size--body` ist
 * clamp(1rem, 0.9536rem + 0.1905vw, 1.125rem); im Iframe bezieht sich vw auf die
 * IFRAME-Breite. Bei 1000 px ergibt das 15,2576 + 1,905 = 17,1626 px - genau der
 * gemessene Wert; bei 1480 px greift der Deckel mit 18 px, auch gemessen. Hier ist
 * also nichts zu beheben, und eine feste Schriftgroesse im Editor wuerde dem
 * Fliesstext seine Fluiditaet nehmen. Nicht gebaut.
 *
 * 1) ZEILENHOEHE. Gemessen 25,7439 px bei 17,1626 px = 1,50, waehrend das Token
 *    `lineHeight.body` auf 1.6 steht (Frontend: 28,8 bei 18 = 1,6). Die gewinnende
 *    Regel ist im Iframe eine INLINE-Quelle mit `body { line-height: 1.5 }`, die
 *    NACH unserer Regel `body, button, input, select, textarea { line-height:
 *    var(--wp--custom--line-height--body) }` kommt - gleiche Spezifitaet (0-0-1),
 *    spaetere Quelle gewinnt. Dieselbe Mechanik wie im Frontend gegen
 *    GeneratePress (Stolperstelle 86), nur mit umgekehrter Ladereihenfolge
 *    (Stolperstelle 2). Darum NICHT ueber die Reihenfolge, sondern ueber die
 *    Spezifitaet: im Iframe traegt der `body` selbst die Klasse
 *    `editor-styles-wrapper`, `body.editor-styles-wrapper` ist 0-1-1 und gewinnt
 *    unabhaengig davon, wo das Blatt eingehaengt wird. Weiterhin ein Tokenverweis.
 *
 *    Der Reiter behaelt seine eigene Zeilenhoehe (`lineHeight.bedienung` = 1.5, Bau
 *    44): sie steht an einer eigenen Regel und wird nicht vererbt. Im Editor
 *    gemessen: 22,5 px Zeilenhoehe, Reiterhoehe 49,5 px - vor und nach dieser Regel.
 *
 * 2) BILDHOEHE. Im Iframe fehlt, was GeneratePress im Frontend mitbringt
 *    (`img { height: auto; max-width: 100% }`). Der Kern bringt es nur
 *    blockweise mit (`.wp-block-image img`, Galerie) - deshalb war das
 *    Galeriebild (B06) mit 289,8 x 217,3 schon richtig, das `generateblocks/media`
 *    von S03 aber 422,67 breit und **2002** hoch: die Zahl aus dem
 *    height-Attribut. Es ist also EINE Ursache und nicht eine Reihe von
 *    Elementfehlern. Die Regel gilt im Editor fuer jedes Bild; die
 *    zugeschnittene Galerie behaelt ihr `height: 100%`, weil deren Selektor
 *    hoeher spezifisch ist.
 *
 * Beide Regeln stehen unter `.editor-styles-wrapper` und aendern im Frontend
 * nichts - belegt mit 18 Seitenhoehen Delta 0 px.
 * ---------------------------------------------------------------------- */

body.editor-styles-wrapper {
	line-height: var(--wp--custom--line-height--body);
}

.editor-styles-wrapper img {
	height: auto;
	max-width: 100%;
}

/* ======================================================================
   Kleinere Ueberschrift in einer mehrspaltigen Spalte
   Entschieden am 12.10.2026 - gilt. (Als Prototyp gebaut, am selben Tag
   vom Pruefchat abgenommen: 33,9989 px bei 1440, 26,2215 px bei 390, alle
   anderen Ueberschriften unveraendert, Fokusrahmen am Slider vollstaendig,
   B05-Titel in einer Spalte unveraendert 22 px.)
   ----------------------------------------------------------------------
   Weg 1 der Entscheidung vom 12.10.: Eine Ueberschrift, die der Redakteur
   SELBST in eine Spalte tippt, laeuft ueber `body h2` auf `titel-l` - bei 1440
   sind das 68,00 px, in einer 328 px breiten Spalte. Die naechste Stufe, die er
   waehlen kann, ist H3 mit 22,00 px. Dazwischen liegt nichts. `titel-halb`
   (34,00 / 26,22 px) ist die fehlende Stufe und seit 0.26.0 gebaut - sie haengt
   nur an einer Klasse, die der Redakteur nicht setzen kann.

   BEDINGUNG, UND SIE IST SCHON ERFUELLT: Die Steuerung hat verlangt, dass
   `container-type` an `.wp-block-column` weder den Slider (overflow: clip,
   Fokusrahmen) noch den Sticky-Header stoert. `container-type: inline-size`
   steht dort seit der Container-Query-Stufe laengst (Zeile 1793) - diese Regel
   fuegt KEIN Containment hinzu.

   DESHALB STRUKTURELL UND NICHT PER SCHWELLE: Eine Container Query braeuchte
   eine Zahl, und die Zahlen liegen zu dicht - eine halbe Spalte auf breiter
   Bahn ist 652 px, eine EINZELNE Spalte auf Lesebreite 680 px. 28 px
   Unterschied als Schaltpunkt ist keine belastbare Angabe. `:has()` fragt
   stattdessen das Einzige, was den Fall wirklich beschreibt: steht der
   Spaltenblock auf mehr als einer Spalte?

   `:not([class*="ml-"])` ist tragend, nicht Kosmetik: ohne das trifft die Regel
   (0,6,1) auch jede Ueberschrift eines Elements - den Titel von B05
   (`.ml-video__title`, 22 px), die Rollenklassen `.ml-titel-*` und `.ml-display`
   - und wuerde sie alle auf 34 px heben. Eine getippte Ueberschrift traegt
   dagegen nur `wp-block-heading`.

   NUR H2: H3 steht mit 22,00 px bereits richtig, und eine H1 in einer Spalte
   waere die zweite der Seite - das faengt die H1-Zaehlung, nicht diese Regel.

   BEI 390 BLEIBT ES BEI 26 px - entschieden am 12.10., ausdruecklich KEINE
   `@media`-Huelle: dort stapeln die Spalten, und die Ueberschrift steht dann
   so gross wie in S23. Wer das aendern will, aendert eine Entscheidung, nicht
   eine Regel.
   ====================================================================== */
.wp-block-columns:has(> .wp-block-column:nth-child(2))
	> .wp-block-column h2:not([class*="ml-"]) {
	font-size: var(--wp--preset--font-size--titel-halb);
	line-height: var(--wp--custom--line-height--pagehead);
}

/* ========================================================================
   Shop (020, 0.95.0) — Grundregeln, Shop-Uebersicht, Produktseite

   Gestaltung nur aus dem System (Entscheidungen 13.10./15.10.). Auf der
   Uebersicht und der Produktseite (`body.ml-shop`) ist das allgemeine
   WooCommerce-CSS abgemeldet (milchland_shop_ohne_wc_css) - dort steht hier
   alles, was die Ansicht braucht. Warenkorb, Kasse und Konto behalten es;
   dort greifen nur die Grundregeln A (Knoepfe, Preis, Links, Felder,
   Meldungen), mit `body.woocommerce-page` vorn, damit sie gegen
   `.woocommerce button.button.alt` (0,3,1) und die Block-Regeln bestehen.
   Keine Farbliterale: Fehlerrot ist das Token `custom.fehler`.
   --------------------------------------------------------------------- */

/* ----- A · Flaeche und Spur ---------------------------------------------- */

/* GeneratePress fuehrt die Seitenflaeche #F7F8F9 (body) und eine weisse
   .inside-article. Auf den Shop-Ansichten ist die Flaeche ueberall weiss. */
body.ml-shop {
	background-color: var(--wp--preset--color--white);
}

body.ml-shop .site-main {
	margin: 0;
	padding-block: var(--wp--preset--spacing--band) var(--wp--preset--spacing--sektion);
	padding-inline: max(var(--wp--preset--spacing--rand), calc((100% - var(--wp--style--global--wide-size)) / 2));
	background-color: var(--wp--preset--color--white);
}

body.ml-shop .site-main > :is(article, .woocommerce-archive-wrapper),
body.ml-shop .site-main .inside-article {
	margin: 0;
	padding: 0;
	background-color: transparent;
}

body.ml-shop .site-main .entry-content {
	margin: 0;
}

/* Die Fliesstext-Regel (A14) setzt jedes direkte Kind von .entry-content auf 680 px
   und zieht es mit eigenem Rand in die Spur - hier liefert .site-main die Spur
   schon selbst. Deren :is() nimmt die Spezifitaet von `.editor-styles-wrapper
   .is-root-container` an: (0,5,0); hier (0,5,1). */
:root body.ml-shop .site-main .entry-content > :not(.ml-section, .gb-is-root-block, .ml-block) {
	max-width: none;
	margin-inline: 0;
}

/* ----- A · Knoepfe ------------------------------------------------------- */

/* Kaufaktion = Bild von .ml-btn + .ml-btn-blue (components.css, Element-Knoepfe). */
body.woocommerce-page :is(.button.alt, .single_add_to_cart_button, .checkout-button, .woocommerce-form-login__submit, .wc-block-cart__submit-button, .wc-block-components-checkout-place-order-button),
body.woocommerce-page :is(.button, .wc-block-components-totals-coupon__button):not(.alt, .single_add_to_cart_button, .checkout-button, .woocommerce-form-login__submit) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 0;
	padding: 14px 24px;
	font-family: var(--wp--preset--font-family--nunito);
	font-size: 14px;
	font-weight: 700;
	line-height: 1;
	letter-spacing: normal;
	text-decoration: none;
	text-transform: none;
	white-space: nowrap;
	border: 1.5px solid transparent;
	border-radius: var(--wp--custom--radius--pill);
	box-shadow: none;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

body.woocommerce-page :is(.button.alt, .single_add_to_cart_button, .checkout-button, .woocommerce-form-login__submit, .wc-block-cart__submit-button, .wc-block-components-checkout-place-order-button) {
	background-color: var(--wp--preset--color--blue);
	border-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

/* Hover und Fokus: Grund blue-dark, Schrift bleibt weiss (007: im Fokus war die
   Beschriftung #222 auf #32373C, 1,32 : 1). */
body.woocommerce-page :is(.button.alt, .single_add_to_cart_button, .checkout-button, .woocommerce-form-login__submit, .wc-block-cart__submit-button, .wc-block-components-checkout-place-order-button):is(:hover, :focus, :focus-visible, :active) {
	background-color: var(--wp--preset--color--blue-dark);
	border-color: var(--wp--preset--color--blue-dark);
	color: var(--wp--preset--color--white);
	box-shadow: none;
}

/* Nebenaktion = Bild von .ml-btn-outline. */
body.woocommerce-page :is(.button, .wc-block-components-totals-coupon__button):not(.alt, .single_add_to_cart_button, .checkout-button, .woocommerce-form-login__submit) {
	background-color: transparent;
	border-color: currentColor;
	color: var(--wp--custom--text--grund);
}

body.woocommerce-page :is(.button, .wc-block-components-totals-coupon__button):not(.alt, .single_add_to_cart_button, .checkout-button, .woocommerce-form-login__submit):is(:hover, :focus-visible) {
	background-color: var(--wp--preset--color--blue);
	border-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}

body.woocommerce-page :is(.button, .wc-block-components-button) .wc-block-components-button__text {
	color: inherit;
}

/* Fokusrahmen der Knoepfe: unser Rahmen, kein Block-Schatten. */
:root body.woocommerce-page :is(.button, .wc-block-components-button):focus-visible {
	outline-style: solid;
	outline-width: var(--wp--custom--focus--width);
	outline-color: var(--ml-focus, var(--wp--preset--color--blue));
	outline-offset: var(--wp--custom--focus--offset);
	box-shadow: none;
}

/* ----- A · Preis und Pflichtangaben -------------------------------------- */

/* Preis: Textton, 700. Angebot: neuer Preis wie Preis, alter durchgestrichen,
   gedaempft, 400. :is() hebt die Spezifitaet ueber die Regeln des
   WooCommerce-CSS auf Warenkorb/Kasse (`.woocommerce ul.products li.product .price`). */
/* 021: ohne die Betraege im Abzeichen „Spare …" (dort blue-dark, siehe Paket 2). */
:root body.woocommerce-page :is(.price, ul.products li.product .price, div.product p.price, div.product span.price, .wc-block-components-product-price, .wc-block-components-product-price__value, .wc-block-formatted-money-amount):not(.wc-block-components-product-badge *) {
	color: var(--wp--custom--text--grund);
	font-weight: 700;
}

:root body.woocommerce-page :is(.price, .wc-block-components-product-price) :is(del, .wc-block-components-product-price__regular) {
	color: var(--wp--custom--text--gedaempft);
	font-weight: 400;
	text-decoration: line-through;
	opacity: 1;
}

:root body.woocommerce-page :is(.price, .wc-block-components-product-price) ins {
	color: inherit;
	font-weight: 700;
	text-decoration: none;
	background: none;
}

/* Pflichtangaben (Germanized): kleiner als der Preis, gedaempft; Link blue-dark. */
body.woocommerce-page .wc-gzd-additional-info {
	margin: 0;
	font-size: var(--wp--preset--font-size--label-s);
	line-height: var(--wp--custom--line-height--liste);
	color: var(--wp--custom--text--gedaempft);
}

body.woocommerce-page .wc-gzd-additional-info a {
	color: var(--wp--preset--color--blue-dark);
}

/* ----- A · Textlinks ----------------------------------------------------- */

/* GeneratePress setzt #1E73BE. :where() haelt die Regel bei (0,0,1): jede
   Komponentenklasse (.ml-card__link, Knoepfe, Kopf- und Fusszeile) bleibt
   staerker. Auf der ganzen Seite, damit auch die textlosen Links (Logo,
   Sprunglink) den fremden Wert nicht mehr tragen. */
:where(body.woocommerce-page) a {
	color: var(--wp--preset--color--blue-dark);
}

:where(body.woocommerce-page) a:hover {
	color: var(--wp--preset--color--blue);
}

/* ----- A · WooCommerce-Ueberschriften ------------------------------------- */

/* H2 von WooCommerce (Anmelden, Produkte im Warenkorb, Aehnliche Produkte …)
   in der Rolle ml-titel-section-halb statt der 68 px aus `body h2`.
   `h2:is(h2)` = (0,0,2) wie `body h2` und steht spaeter; jede Klasse
   (.ml-card__title, Block-Titel) bleibt staerker. */
:where(body.woocommerce-page .site-main) h2:is(h2) {
	font-size: var(--wp--preset--font-size--titel-halb);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--pagehead);
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--custom--text--grund);
}

/* Keine Versalien im Shop (nur .ml-pill, .ml-spec__num). */
body.woocommerce-page :is(.wc-block-cart-items__header, .wc-block-cart__totals-title, .wc-block-components-product-badge, table.shop_table th, .wc-block-checkout__shipping-option--free) {
	text-transform: none;
	letter-spacing: normal;
}

/* ----- A · Felder ---------------------------------------------------------- */

body.woocommerce-page :is(input.input-text, input.qty, select.orderby, .woocommerce-ordering select, .woocommerce-Input, textarea.input-text) {
	padding: 10px 12px;
	font-family: var(--wp--preset--font-family--nunito);
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--bedienung);
	color: var(--wp--custom--text--grund);
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: none;
}

/* Block-Felder (Kasse, Gutschein): Rand und Radius nach A; die Schriftgroesse
   bleibt bei der schwebenden Beschriftung des Blocks (Paket 2). */
body.woocommerce-page :is(.wc-block-components-text-input input, .wc-blocks-components-select__select, .wc-block-components-textarea, .wc-block-components-totals-coupon__input input) {
	color: var(--wp--custom--text--grund);
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
}

body.woocommerce-page .wc-block-components-quantity-selector {
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--white);
}

body.woocommerce-page .wc-block-components-quantity-selector::after {
	border: 0;
}

body.woocommerce-page .wc-block-components-quantity-selector input.wc-block-components-quantity-selector__input {
	font-size: var(--wp--preset--font-size--body);
	color: var(--wp--custom--text--grund);
	background-color: transparent;
}

body.woocommerce-page .wc-block-components-checkbox .wc-block-components-checkbox__input[type="checkbox"],
body.woocommerce-page input[type="checkbox"]:is(.woocommerce-form__input-checkbox, .input-checkbox) {
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--white);
}

/* Fokus = unser Rahmen (3 px, Abstand 3), auch dort, wo WooCommerce ihn durch
   einen inneren Schatten (Mengenwaehler) oder 1 px (Checkbox) ersetzt. */
:root body.woocommerce-page :is(input, select, textarea):focus-visible,
:root body.woocommerce-page .wc-block-components-quantity-selector input.wc-block-components-quantity-selector__input:focus-visible,
:root body.woocommerce-page .wc-block-components-checkbox .wc-block-components-checkbox__input[type="checkbox"]:focus-visible {
	outline-style: solid;
	outline-width: var(--wp--custom--focus--width);
	outline-color: var(--ml-focus, var(--wp--preset--color--blue));
	outline-offset: var(--wp--custom--focus--offset);
	box-shadow: none;
}

/* Feldfehler: Rand, Beschriftung und Text im Token `fehler`. */
body.woocommerce-page .has-error :is(input, select, textarea) {
	border-color: var(--wp--custom--fehler);
}

body.woocommerce-page :is(.has-error label, .wc-block-components-validation-error, .wc-block-components-validation-error p) {
	color: var(--wp--custom--fehler);
}

/* ----- A · Meldungen = Bild der Hinweisbox B01 (getoent) ------------------ */

body.woocommerce-page :is(.woocommerce-message, .woocommerce-info, .woocommerce-error, .woocommerce-noreviews, .wc-block-components-notice-banner) {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem 1.5rem;
	margin: 0 0 var(--wp--preset--spacing--gap-l);
	padding: 1.75rem 2rem;
	font-size: var(--wp--preset--font-size--body);
	color: var(--wp--custom--text--grund);
	list-style: none;
	background-color: var(--wp--preset--color--blue-tint);
	border: 0;
	border-left: 4px solid var(--wp--preset--color--blue);
	border-radius: var(--wp--custom--radius--panel);
	box-shadow: none;
}

/* Breite der Hinweisbox (B01: baustein.schmal 680). */
body.woocommerce-page :is(.woocommerce-message, .woocommerce-info, .woocommerce-error) {
	max-width: var(--wp--custom--baustein--schmal);
}

body.woocommerce-page :is(.woocommerce-message, .woocommerce-info, .woocommerce-error, .woocommerce-noreviews)::before {
	content: none;
}

/* Fehler: Kante im Token `fehler`; erkennbar auch am Text (Kein-Farbe-allein). */
body.woocommerce-page :is(.woocommerce-error, .wc-block-components-notice-banner.is-error) {
	border-left-color: var(--wp--custom--fehler);
}

body.woocommerce-page .wc-block-components-notice-banner > svg {
	display: none;
}

body.woocommerce-page :is(.woocommerce-message, .woocommerce-info, .woocommerce-error, .wc-block-components-notice-banner) a:not(.button) {
	color: var(--wp--preset--color--blue-dark);
}

/* Knopf in der Meldung (Warenkorb anzeigen) ans Ende der Zeile. */
body.woocommerce-page :is(.woocommerce-message, .woocommerce-info) .button {
	order: 2;
	float: none;
}

/* ----- B · Shop-Uebersicht ------------------------------------------------- */

/* Kategorien als Seitenleiste (032, Marc 17.10.). Liste = Kontomenue aus 022
   (dieselben Regeln, Selektoren oben um .ml-kategorien erweitert). Ab 1024:
   Leiste 280 links, Luecke `band`, Raster rechts 3 Spalten; darunter Knopf
   „Kategorien" (nur mit JavaScript) klappt die Liste auf. */
body.ml-shop .ml-kategorien {
	margin: 0 0 var(--wp--preset--spacing--gap-l);
}

body.ml-shop .ml-kategorien__titel {
	margin: 0 0 var(--wp--preset--spacing--gap-s);
}

/* `.ml-btn` setzt `display` und wuerde `hidden` ueberstimmen (Stolperstelle 159):
   ohne JavaScript bleibt der Knopf aus, die Liste steht offen. */
body.ml-shop .ml-kategorien__knopf[hidden] {
	display: none;
}

body.ml-shop .ml-kategorien__zahl {
	font-weight: 400;
	color: var(--wp--custom--text--gedaempft);
}

body.ml-shop .ml-shop-inhalt {
	transition: opacity 0.2s ease;
}

body.ml-shop .ml-shop-inhalt--laedt {
	opacity: 0.5;
}

@media (min-width: 1024px) {
	body.ml-shop .ml-shop-layout {
		display: grid;
		grid-template-columns: 280px minmax(0, 1fr);
		column-gap: var(--wp--preset--spacing--band);
		align-items: start;
	}

	body.ml-shop .ml-kategorien {
		margin: 0;
	}

	body.ml-shop .ml-kategorien__knopf {
		display: none;
	}

	body.ml-shop .ml-shop-inhalt ul.products {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 1023px) {
	/* Ueberschrift nur fuer Hilfstechnik; sichtbar traegt der Knopf den Namen. */
	body.ml-shop .ml-kategorien--js .ml-kategorien__titel {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	body.ml-shop .ml-kategorien--js .ml-kategorien__liste {
		margin-top: var(--wp--preset--spacing--gap-s);
	}

	body.ml-shop .ml-kategorien--js:has(.ml-kategorien__knopf[aria-expanded="false"]) .ml-kategorien__liste {
		display: none;
	}
}

/* Blaettern (030): 24 je Seite, `nav` „Seiten" (gettext), Pfeile mit Beschriftung
   (`milchland_blaettern`). Zahlen in Fliesstextgroesse, Links und aktive Seite
   `blue-dark`, aktive fett. Fokus: globaler Rahmen. Das allgemeine WooCommerce-CSS
   ist in Shop-Ansichten abgemeldet — die Liste ist sonst ungestaltet. */
body.ml-shop .woocommerce-pagination {
	margin-top: var(--wp--preset--spacing--band);
}

body.ml-shop .woocommerce-pagination ul.page-numbers {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--gap-s);
	margin: 0;
	padding: 0;
	list-style: none;
}

body.ml-shop .woocommerce-pagination li {
	margin: 0;
}

body.ml-shop .woocommerce-pagination .page-numbers:is(a, span) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	min-width: 44px;
	min-height: 44px;
	padding: 0 0.5em;
	border-radius: var(--wp--custom--radius--card);
	font-size: var(--wp--preset--font-size--body);
	line-height: 1;
	color: var(--wp--preset--color--blue-dark);
	text-decoration: none;
}

body.ml-shop .woocommerce-pagination a.page-numbers:hover {
	text-decoration: underline;
}

body.ml-shop .woocommerce-pagination .page-numbers.current {
	font-weight: 700;
}

body.ml-shop .woocommerce-pagination .page-numbers.dots {
	color: var(--wp--custom--text--gedaempft);
}

body.ml-shop .woocommerce-products-header {
	margin: 0 0 var(--wp--custom--abstand--vorspann-titel);
}

body.ml-shop .woocommerce-products-header .term-description {
	max-width: var(--wp--style--global--content-size);
	margin-top: var(--wp--custom--abstand--vorspann);
}

body.ml-shop :is(.woocommerce-result-count, .woocommerce-ordering) {
	margin: 0 0 var(--wp--preset--spacing--gap-l);
}

body.ml-shop .woocommerce-result-count {
	color: var(--wp--custom--text--gedaempft);
}

/* Ergebniszahl und Sortierung in einer Zeile, ab 600 px nebeneinander. */
@media (min-width: 601px) {
	body.ml-shop .woocommerce-result-count {
		float: left;
	}

	body.ml-shop .woocommerce-ordering {
		float: right;
	}
}

/* Raster wie S18: 4 / 2 / 2 / 1 (Schwellen wie .ml-grid). */
body.ml-shop ul.products {
	clear: both;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--gap-s);
	margin: 0;
	padding: 0;
	list-style: none;
}

body.ml-shop ul.products::before,
body.ml-shop ul.products::after {
	content: none;
}

body.ml-shop ul.products li.product {
	display: flex;
	margin: 0;
	padding: 0;
}

@media (max-width: 1024px) {
	body.ml-shop ul.products { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
	body.ml-shop ul.products { grid-template-columns: minmax(0, 1fr); }
}

/* Shop und Kategorien mobil zwei Karten je Reihe (033, Marc 17.10.); „Aehnliche
   Produkte" auf der Produktseite bleiben einspaltig. Karte kompakter: Innenabstand
   `gap-s` statt 1,5rem, Titel in `label-s` (900; bei 122/108 px Kartentext passen
   Woerter wie „Unterrichtsmaterial" in keiner Stufe — sie trennen, `overflow-wrap`/
   `hyphens` von .ml-card__title, nichts ragt ueber den Rand). */
@media (max-width: 600px) {
	body.ml-shop .ml-shop-inhalt ul.products {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	body.ml-shop .ml-shop-inhalt .ml-produktkarte .ml-card__body {
		padding: var(--wp--preset--spacing--gap-s);
	}

	body.ml-shop .ml-shop-inhalt .ml-produktkarte .ml-card__title {
		font-size: var(--wp--preset--font-size--label-s);
	}
}

/* Produktkarte = .ml-card (Buehne 5:4, Rand rule, Radius card, Fokus an der
   ganzen Karte). Nur das, was die Karte ueber .ml-card hinaus braucht. */
.ml-produktkarte {
	flex: 1;
	width: 100%;
}

.ml-produktkarte .ml-card__media {
	margin: 0;
}

.ml-produktkarte .price {
	display: block;
	margin: 0 0 6px;
	font-size: var(--wp--preset--font-size--label);
}

/* Pflichtangaben mit eigenem Link (Versandkosten) liegen ueber dem gestreckten
   Kartenlink, sonst waeren sie nicht anklickbar. */
.ml-produktkarte .wc-gzd-additional-info a {
	position: relative;
	z-index: 2;
}

/* ----- C · Produktseite ------------------------------------------------------ */

/* Bild und Kaufbereich nebeneinander ab 1024 px, darunter untereinander. */
body.ml-shop div.product {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--band);
	align-items: start;
}

@media (min-width: 1024px) {
	body.ml-shop div.product {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: var(--wp--preset--spacing--band);
	}
}

body.ml-shop div.product > .woocommerce-product-gallery,
body.ml-shop div.product > .summary {
	width: auto;
	margin: 0;
	float: none;
}

body.ml-shop div.product > :not(.woocommerce-product-gallery, .summary) {
	grid-column: 1 / -1;
}

body.ml-shop .woocommerce-product-gallery {
	position: relative;
}

body.ml-shop .woocommerce-product-gallery__wrapper {
	margin: 0;
}

body.ml-shop :is(.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder) img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 5 / 4;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

/* Galerie mit mehreren Bildern (heute keine): Vorschaubilder in vier Spalten. */
body.ml-shop .woocommerce-product-gallery .flex-control-thumbs {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--gap-s);
	margin: var(--wp--preset--spacing--gap-s) 0 0;
	padding: 0;
	list-style: none;
}

body.ml-shop .woocommerce-product-gallery .flex-control-thumbs img {
	display: block;
	width: 100%;
	cursor: pointer;
	opacity: 0.6;
	border-radius: var(--wp--custom--radius--card);
}

body.ml-shop .woocommerce-product-gallery .flex-control-thumbs img.flex-active {
	opacity: 1;
}

body.ml-shop .woocommerce-product-gallery__trigger {
	position: absolute;
	top: 14px;
	right: 14px;
	z-index: 2;
}

/* Kaufbereich: Preis · Pflichtangaben · Kurzbeschreibung · Menge + Knopf. */
body.ml-shop div.product .summary > * {
	margin-top: 0;
}

body.ml-shop div.product p.price {
	margin: 0 0 6px;
	font-size: var(--wp--preset--font-size--titel-m);
}

body.ml-shop div.product .legal-price-info {
	margin: 0 0 var(--wp--preset--spacing--gap-l);
}

body.ml-shop div.product .woocommerce-product-details__short-description {
	margin: 0 0 var(--wp--preset--spacing--gap-l);
}

body.ml-shop div.product .woocommerce-product-details__short-description > :last-child {
	margin-bottom: 0;
}

body.ml-shop div.product form.cart {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	gap: var(--wp--preset--spacing--gap-s);
	margin: 0 0 var(--wp--preset--spacing--gap-l);
}

body.ml-shop div.product form.cart .quantity {
	display: flex;
	margin: 0;
}

body.ml-shop div.product form.cart input.qty {
	width: 5em;
	text-align: center;
}

body.ml-shop .ml-produkt-beschreibung {
	max-width: var(--wp--style--global--content-size);
	padding-top: var(--wp--preset--spacing--band);
}

body.ml-shop .ml-produkt-beschreibung > .ml-titel-section-halb {
	margin: 0 0 var(--wp--custom--abstand--vorspann);
}

/* Aehnliche Produkte / Zusatzverkaeufe (heute keine): Karten wie B. */
body.ml-shop :is(.related, .up-sells) > h2 {
	margin: 0 0 var(--wp--custom--abstand--vorspann-titel);
}

/* Bildschirmleser-Texte (sonst aus dem abgemeldeten WooCommerce-CSS). */
body.ml-shop .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ========================================================================
   Shop Paket 2 (021, 0.96.0) — Warenkorb und Kasse

   Seitenkopf wie die Produktseite (60 px, milchland_seitenkopf). Alles hier
   auf Token; die Block-Klassen von WooCommerce werden ueberstimmt, nicht
   ersetzt. Kleinste Schrift im Kaufweg `meta` (13), nur fuer Hilfstexte,
   MwSt.-Zeilen und Spaltenkoepfe; alles, was gelesen werden muss, ab `label`.
   Die Blockregeln von WooCommerce liegen meist bei (0,2,0)-(0,3,1); mit
   `body.woocommerce-cart` / `body.woocommerce-checkout` vorn liegen diese
   Regeln darueber.
   --------------------------------------------------------------------- */

/* ----- Warenkorb: Artikelliste ----------------------------------------- */

/* Luft unter dem Seitenkopf (die Kasse hat sie ueber ihre Abschnittstitel). */
body.woocommerce-cart .wp-block-woocommerce-cart {
	padding-top: var(--wp--preset--spacing--gap-l);
	padding-bottom: var(--wp--preset--spacing--band);
}

body.woocommerce-cart .wc-block-cart-items th,
body.woocommerce-cart .wc-block-cart-items .wc-block-cart-items__header {
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--custom--text--gedaempft);
	text-transform: none;
	letter-spacing: normal;
}

body.woocommerce-cart table.wc-block-cart-items,
body.woocommerce-cart table.wc-block-cart-items :is(th, td) {
	border-color: var(--wp--preset--color--rule);
}

body.woocommerce-cart table.wc-block-cart-items td {
	border-top: 1px solid var(--wp--preset--color--rule);
}

body.woocommerce-cart table.wc-block-cart-items {
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

body.woocommerce-page :is(.wc-block-cart-item__image, .wc-block-components-order-summary-item__image) img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 5 / 4;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

/* Produktname: Fliesstextgroesse, blue-dark, 700 (Warenkorb und Bestelluebersicht). */
body.woocommerce-page :is(.wc-block-cart-items, .wc-block-components-order-summary) .wc-block-components-product-name {
	font-size: var(--wp--preset--font-size--body);
	font-weight: 700;
	line-height: var(--wp--custom--line-height--card);
	color: var(--wp--preset--color--blue-dark);
	text-decoration: none;
}

body.woocommerce-page :is(.wc-block-cart-items, .wc-block-components-order-summary) a.wc-block-components-product-name:hover {
	color: var(--wp--preset--color--blue);
	text-decoration: underline;
}

/* Preise in Zeilen und Summen mindestens `label`. */
body.woocommerce-page :is(.wc-block-cart-items, .wc-block-components-order-summary) :is(.wc-block-components-product-price, .wc-block-components-product-price__value, .wc-block-components-product-price__regular, .wc-block-formatted-money-amount) {
	font-size: var(--wp--preset--font-size--label);
}

body.woocommerce-page :is(.wc-block-cart-items, .wc-block-components-order-summary) .wc-block-components-product-metadata {
	font-size: var(--wp--preset--font-size--meta);
	color: var(--wp--custom--text--gedaempft);
}

/* Die Beschreibung darin rechnet in em (0,875) - ohne das 11,4 px. */
body.woocommerce-page .wc-block-components-product-metadata :is(.wc-block-components-product-metadata__description, p) {
	font-size: var(--wp--preset--font-size--meta);
}

/* Abzeichen „Spare …": Bild von .ml-pill auf blue-tint, Schrift blue-dark;
   Groesse `meta` statt 10 px (D: nichts unter 13 px), ohne Versalien. */
body.woocommerce-page .wc-block-components-product-badge {
	display: inline-block;
	padding: 4px 10px;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 700;
	line-height: 1.2;
	color: var(--wp--preset--color--blue-dark);
	text-transform: none;
	letter-spacing: normal;
	background-color: var(--wp--preset--color--blue-tint);
	border: 0;
	border-radius: var(--wp--custom--radius--pill);
	/* Darf umbrechen: bei 390 schob „Spare 0,50 €" in einer Zeile die Tabelle 22 px ueber den Rand. */
	white-space: normal;
}

body.woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__total {
	min-width: 0;
	width: auto;
}

/* Betrag im Abzeichen: die Preisregel (0,3,1) faerbte ihn sonst im Textton. (0,4,1). */
:root body.woocommerce-page .wc-block-components-product-badge :is(.wc-block-formatted-money-amount, .wc-block-components-formatted-money-amount__currency-symbol, bdi) {
	font-size: inherit;
	font-weight: inherit;
	color: inherit;
}

/* Entfernen: Symbolknopf, Farbe Textton. */
body.woocommerce-cart .wc-block-cart-item__remove-link {
	color: var(--wp--custom--text--grund);
}

/* ----- Warenkorb: Summenkasten ------------------------------------------ */

body.woocommerce-cart .wc-block-cart__sidebar {
	align-self: start;
	padding: var(--wp--preset--spacing--gap-l);
	background-color: var(--wp--preset--color--gray-bg);
	border-radius: var(--wp--custom--radius--panel);
}

body.woocommerce-cart .wc-block-cart__sidebar .wc-block-components-totals-wrapper {
	border-color: var(--wp--preset--color--rule);
	padding-inline: 0;
}

body.woocommerce-cart .wc-block-cart__sidebar .wc-block-cart__totals-title {
	margin: 0 0 var(--wp--custom--abstand--label);
	padding: 0;
	/* 022: `titel-m` wie die Bestelluebersicht der Kasse - einzeilig in der Summenspalte. */
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--pagehead);
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--custom--text--grund);
	text-transform: none;
	text-align: left;
}

/* Gesamtsumme Textton 700 in `titel-m` (Warenkorb und Kasse). */
body.woocommerce-page .wc-block-components-totals-footer-item :is(.wc-block-components-totals-item__label, .wc-block-components-totals-item__value, .wc-block-components-totals-footer-item-tax-value) {
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 700;
	color: var(--wp--custom--text--grund);
}

/* MwSt.-Zeile `meta`, gedaempft. */
body.woocommerce-page .wc-block-components-totals-footer-item .wc-block-components-totals-footer-item-tax,
body.woocommerce-page .wc-block-components-totals-footer-item .wc-block-components-totals-footer-item-tax .wc-block-components-totals-footer-item-tax-value {
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 400;
	color: var(--wp--custom--text--gedaempft);
}

body.woocommerce-cart .wc-block-cart__submit {
	margin: var(--wp--preset--spacing--gap-l) 0 0;
}

body.woocommerce-cart .wc-block-cart__submit-button {
	width: 100%;
}

/* ----- Warenkorb leer -------------------------------------------------- */

/* Ohne grosses Symbol; Text als H2 nach Grundregel. */
body.woocommerce-cart .wc-block-cart__empty-cart__title.with-empty-cart-icon::before {
	content: none;
	display: none;
}

body.woocommerce-cart .wc-block-cart__empty-cart__title {
	margin: 0 0 var(--wp--custom--abstand--vorspann);
	font-size: var(--wp--preset--font-size--titel-halb);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--pagehead);
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--custom--text--grund);
	text-align: left;
}

/* Trennlinie und „Neu im Shop" entfallen (die Sammlung selbst rendert nicht,
   milchland_warenkorb_ohne_neu_im_shop). */
body.woocommerce-cart .wp-block-woocommerce-empty-cart-block > :is(hr, h2 ~ h2) {
	display: none;
}

body.woocommerce-cart .ml-warenkorb-leer__knopf {
	margin: 0;
	text-align: left;
}

/* ----- Kasse: Abschnittstitel und Hilfstexte --------------------------- */

/* Abschnittstitel in `titel-m`, 900, Textton (eine Stufe unter section-halb). */
body.woocommerce-checkout :is(.wc-block-components-checkout-step__title, .wc-block-components-checkout-order-summary__title .wc-block-components-checkout-order-summary__title-text) {
	margin-block: 0;
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--card);
	letter-spacing: var(--wp--custom--tracking--display);
	color: var(--wp--custom--text--grund);
}

body.woocommerce-checkout :is(.wc-block-checkout__guest-checkout-notice, .wc-block-components-checkout-step__description, .wc-block-components-address-form__address_2-toggle) {
	font-size: var(--wp--preset--font-size--meta);
	color: var(--wp--custom--text--gedaempft);
}

/* ----- Kasse: Felder ----------------------------------------------------- */

/* Feldtext in Fliesstextgroesse; die schwebende Beschriftung ruht in `label`,
   gedaempft. Hoehe und Innenabstand wachsen mit der Schrift. */
body.woocommerce-checkout :is(.wc-block-components-text-input, .wc-block-components-combobox .wc-block-components-combobox-control) input,
body.woocommerce-checkout .wc-blocks-components-select__select {
	min-height: 56px;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--bedienung);
	color: var(--wp--custom--text--grund);
}

body.woocommerce-checkout .wc-block-components-text-input input {
	padding-top: 26px;
	padding-bottom: 6px;
}

/* Ruhender Rand: WooCommerce setzt `color-mix(currentcolor 80%)` mit
   `.wc-block-components-form .wc-block-components-text-input input[type=…]` (0,4,1). (0,4,2). */
body.woocommerce-checkout .wc-block-components-form .wc-block-components-text-input input:is([type], :not([type])) {
	border: 1px solid var(--wp--preset--color--gray-dark);
}

/* Preis im Titel der Bestelluebersicht (unter 1024 sichtbar): mindestens `label`. */
body.woocommerce-checkout .wc-block-components-checkout-order-summary__title .wc-block-components-checkout-order-summary__title-price {
	font-size: var(--wp--preset--font-size--label);
}

body.woocommerce-checkout :is(.wc-block-components-text-input label, .wc-blocks-components-select__label) {
	font-size: var(--wp--preset--font-size--label);
	color: var(--wp--custom--text--gedaempft);
}

body.woocommerce-checkout .wc-block-components-text-input:not(.is-active) label {
	top: 50%;
	transform: translateY(-50%);
}

/* Feldfehler: auch die schwebende Beschriftung und der Rand im Token. */
body.woocommerce-checkout .wc-block-components-text-input.has-error input,
body.woocommerce-checkout .wc-blocks-components-select.has-error .wc-blocks-components-select__select {
	border-color: var(--wp--custom--fehler);
	box-shadow: none;
}

body.woocommerce-checkout :is(.wc-block-components-text-input.has-error label, .wc-blocks-components-select.has-error .wc-blocks-components-select__label, .wc-block-components-validation-error, .wc-block-components-validation-error > p) {
	color: var(--wp--custom--fehler);
}

body.woocommerce-checkout .wc-block-components-validation-error {
	font-size: var(--wp--preset--font-size--meta);
}

body.woocommerce-checkout .wc-block-components-validation-error svg {
	fill: currentColor;
}

/* Fokus: WooCommerce setzt #2B2D2F und 1,5 px (0,4,1); unser Rahmen kommt aus A. */
body.woocommerce-checkout .wc-block-components-form .wc-block-components-text-input input:focus,
body.woocommerce-checkout .wc-block-components-form .wc-blocks-components-select .wc-blocks-components-select__select:focus {
	color: var(--wp--custom--text--grund);
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--gray-dark);
}

/* Feldfehler auch im Fokus (WooCommerce fokussiert das erste fehlerhafte Feld
   und legt dort einen roten Schatten #CC1818 an): Rand im Token, kein Schatten. */
body.woocommerce-checkout .wc-block-components-form .wc-block-components-text-input.has-error input,
body.woocommerce-checkout .wc-block-components-form .wc-block-components-text-input.has-error input:focus,
body.woocommerce-checkout .wc-block-components-form .wc-blocks-components-select.has-error .wc-blocks-components-select__select {
	border-color: var(--wp--custom--fehler);
	box-shadow: none;
}

body.woocommerce-checkout .wc-blocks-components-select .wc-blocks-components-select__expand {
	fill: currentColor;
	color: var(--wp--custom--text--grund);
}

/* ----- Kasse: Bestelluebersicht (Germanized-Tabellenfarbe per CSS) ------- */

/* Germanized setzt die Option `display_checkout_table_color` (#EEEEEE) als
   Grund der Artikelzeilen; hier ueberstimmt, die Option bleibt unberuehrt.
   Die rechte Spalte traegt zwei Uebersichtsbloecke (WooCommerce oben, die
   Gesamtsumme in Germanizeds Knopfbereich darunter) - zusammen EIN Kasten. */
body.woocommerce-checkout .wc-block-checkout__sidebar .wp-block-woocommerce-checkout-order-summary-block {
	background-color: var(--wp--preset--color--gray-bg);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--panel);
}

body.woocommerce-checkout .wc-block-checkout__sidebar > .wp-block-woocommerce-checkout-order-summary-block {
	border-bottom: 0;
	border-end-start-radius: 0;
	border-end-end-radius: 0;
}

body.woocommerce-checkout .wc-gzd-checkout-submit > .wp-block-woocommerce-checkout-order-summary-block {
	border-start-start-radius: 0;
	border-start-end-radius: 0;
}

/* Germanized setzt 18 px Abstand vor seinen Knopfbereich - der Kasten soll durchgehen. */
body.woocommerce-checkout .wc-gzd-checkout .wc-gzd-checkout-submit {
	margin-top: 0;
}

body.woocommerce-checkout .wc-block-checkout__sidebar :is(.wc-block-components-order-summary, .wc-block-components-order-summary-item, .wc-block-components-totals-wrapper, .wc-block-components-checkout-order-summary__content, .wc-block-components-checkout-order-summary__title, .wc-block-components-order-summary-item__total-price, .wc-block-components-order-summary-item__description) {
	background-color: transparent;
	border-color: var(--wp--preset--color--rule);
}

/* Mengenabzeichen am Bild: Kreis schwarz, Schrift weiss (bleibt), Groesse `meta`. */
body.woocommerce-checkout .wc-block-components-order-summary-item__quantity {
	min-width: 22px;
	min-height: 22px;
	font-size: var(--wp--preset--font-size--meta);
	color: var(--wp--preset--color--white);
	background-color: var(--wp--preset--color--black);
	border: 0;
	box-shadow: none;
}

/* Zeilen der Uebersicht in Fliesstextgroesse. */
body.woocommerce-checkout .wc-block-checkout__sidebar .wc-block-components-totals-item:not(.wc-block-components-totals-footer-item) :is(.wc-block-components-totals-item__label, .wc-block-components-totals-item__value, .wc-block-formatted-money-amount) {
	font-size: var(--wp--preset--font-size--body);
	color: var(--wp--custom--text--grund);
}

/* ----- Kasse: Haekchen unmittelbar ueber „Jetzt kaufen" ------------------ */

/* milchland_kasse_haekchen_zum_knopf setzt den Haekchen-Block in Germanizeds
   Knopfbereich direkt vor den Knopf. Abstand Haekchen -> Knopf `gap-l` (24). */
body.woocommerce-checkout .wc-gzd-checkout-submit .wp-block-woocommerce-germanized-checkout-checkboxes {
	margin: var(--wp--preset--spacing--gap-l) 0 0;
	padding: 0;
}

/* Germanized setzt hier 36 px oben und unten (0,4,0): (0,4,1). */
body.woocommerce-checkout .wc-gzd-checkout .wc-gzd-checkout-submit .wc-block-checkout__actions {
	margin-top: var(--wp--preset--spacing--gap-l);
	padding: 0;
}

body.woocommerce-checkout .wc-gzd-checkout-submit .wc-block-checkout__actions_row {
	margin: 0;
}

body.woocommerce-checkout .wc-gzd-checkout-submit .wc-block-components-checkout-place-order-button {
	width: 100%;
}

/* Haekchentexte (Germanized und „Hinweis zur Bestellung") in Fliesstextgroesse. */
body.woocommerce-checkout .wc-block-components-checkbox :is(.wc-block-components-checkbox__label, label > span) {
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--liste);
	color: var(--wp--custom--text--grund);
}

body.woocommerce-checkout .wc-block-components-checkbox label {
	align-items: flex-start;
}

body.woocommerce-checkout .wc-block-components-checkbox .wc-block-components-checkbox__input[type="checkbox"] {
	flex: none;
	margin-top: 2px;
}

body.woocommerce-checkout .wc-block-components-checkbox a {
	color: var(--wp--preset--color--blue-dark);
}

/* ----- Kasse: Versand- und Zahlungsarten -------------------------------- */

body.woocommerce-checkout .wc-block-components-radio-control__option {
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: none;
}

body.woocommerce-checkout .wc-block-components-radio-control__option-checked,
body.woocommerce-checkout .wc-block-components-radio-control-accordion-option:has(.wc-block-components-radio-control__option-checked) {
	border: 2px solid var(--wp--preset--color--blue);
	box-shadow: none;
}

/* Rahmen um die ganze Liste (Versand- und Zahlungsarten): WooCommerce zeichnet ihn
   als `::after` in Textton 20 % — hier `rule` (030, Pruefung 1). */
body.woocommerce-checkout .wc-block-components-radio-control--highlight-checked::after {
	border-color: var(--wp--preset--color--rule);
}

/* Trennlinie zwischen den Optionen (WooCommerce: 1 px Flaeche in Textton 20 %):
   jede Option hat schon ihren eigenen Rand `rule` — Linie entfaellt (030, Pruefung 2). */
body.woocommerce-checkout .wc-block-components-radio-control--highlight-checked :is(.wc-block-components-radio-control__option, .wc-block-components-radio-control-accordion-option)::after {
	display: none;
}

/* Auswahlkreise und Haekchen im Hausstil (031, Marc 17.10.): Rand 1 px
   `gray-dark` (4,0 : 1 auf Weiss), gewaehlt Rand und Punkt bzw. Haken `blue`.
   Nach Mausklick kein Umriss; per Tastatur der globale Fokusrahmen (A11). */
body.woocommerce-page .wc-block-components-radio-control__input {
	border: 1px solid var(--wp--preset--color--gray-dark);
}

body.woocommerce-page .wc-block-components-radio-control__input:checked {
	border-color: var(--wp--preset--color--blue);
}

body.woocommerce-page .wc-block-components-radio-control__input:checked::before {
	background-color: var(--wp--preset--color--blue);
}

body.woocommerce-page .wc-block-components-checkbox .wc-block-components-checkbox__input[type="checkbox"]:checked {
	border-color: var(--wp--preset--color--blue);
}

body.woocommerce-page .wc-block-components-checkbox .wc-block-components-checkbox__mark {
	fill: var(--wp--preset--color--blue);
}

body.woocommerce-page :is(.wc-block-components-radio-control__input, .wc-block-components-checkbox__input):focus:not(:focus-visible) {
	outline: none;
	box-shadow: none;
}

/* Weitere WooCommerce-Grautoene (Textton 20 %) auf Token (030, Pruefung 2):
   Linien im Summenkasten von Warenkorb und Kasse, Rahmen der gespeicherten Adresse,
   Hinweis „Adresse eingeben" bei den Versandoptionen. */
body.woocommerce-page .wp-block-woocommerce-cart-order-summary-block {
	border-bottom-color: var(--wp--preset--color--rule);
}

body.woocommerce-page :is(.wp-block-woocommerce-cart-order-summary-totals-block, .wp-block-woocommerce-checkout-order-summary-totals-block) {
	border-top-color: var(--wp--preset--color--rule);
}

body.woocommerce-checkout .wc-block-components-address-card {
	border-color: var(--wp--preset--color--rule);
}

body.woocommerce-checkout .wc-block-components-shipping-rates-control__no-shipping-address-message {
	color: var(--wp--custom--text--gedaempft);
	background-color: var(--wp--preset--color--gray-bg);
}

/* ========================================================================
   Shop Paket 3 (022, 0.97.0) — Mein Konto

   Seitenkopf 60 px (milchland_seitenkopf). Abgemeldet: Anmeldeformular in
   680; angemeldet: Kontomenue als Liste links (280, ab 1024), darunter ueber
   dem Inhalt. Das WooCommerce-CSS bleibt geladen; die Regeln hier liegen mit
   `body.woocommerce-account` vorn ueber dessen (0,2,0)-Regeln.
   --------------------------------------------------------------------- */

/* Der Konto-Rahmen laeuft in der 1360er Spur (A14 setzt jedes Kind von
   .entry-content auf 680; deren Spezifitaet (0,5,0), hier (0,5,1)). */
:root body.woocommerce-account.woocommerce-page .entry-content > .woocommerce {
	max-width: min(var(--wp--style--global--wide-size), calc(100% - 2 * var(--wp--preset--spacing--rand)));
	padding-block: var(--wp--preset--spacing--band) var(--wp--preset--spacing--sektion);
}

/* ----- Abgemeldet: Anmelden, Passwort vergessen ------------------------- */

body.woocommerce-account .woocommerce > h2,
body.woocommerce-account .woocommerce :is(.woocommerce-form-login, .woocommerce-form-register, .woocommerce-ResetPassword, .woocommerce-EditAccountForm, .woocommerce-address-fields) {
	max-width: var(--wp--custom--baustein--schmal);
}

body.woocommerce-account .woocommerce :is(.woocommerce-form-login, .woocommerce-form-register, .woocommerce-ResetPassword) {
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
}

/* Felder: `.woocommerce form .form-row .input-text` (0,3,1) schlaegt die Grundregel. */
body.woocommerce-account .woocommerce form .form-row :is(input.input-text, textarea, select) {
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--white);
}

body.woocommerce-account .woocommerce .form-row label {
	font-size: var(--wp--preset--font-size--label);
	color: var(--wp--custom--text--grund);
}

body.woocommerce-account .woocommerce .form-row .required {
	color: var(--wp--custom--fehler);
	text-decoration: none;
}

body.woocommerce-account .woocommerce-form-login .woocommerce-form-login__rememberme {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin: 0 var(--wp--preset--spacing--gap-l) 0 0;
}

body.woocommerce-account .woocommerce .lost_password {
	margin-top: var(--wp--preset--spacing--gap-s);
}

/* ----- Angemeldet: Menue links, Inhalt rechts ----------------------------- */

body.woocommerce-account .woocommerce :is(.woocommerce-MyAccount-navigation, .woocommerce-MyAccount-content) {
	float: none;
	width: auto;
}

body.woocommerce-account .woocommerce-MyAccount-navigation {
	margin: 0 0 var(--wp--preset--spacing--band);
}

@media (min-width: 1024px) {
	body.woocommerce-account .entry-content > .woocommerce:has(> .woocommerce-MyAccount-navigation) {
		display: grid;
		grid-template-columns: 280px minmax(0, 1fr);
		column-gap: var(--wp--preset--spacing--band);
		align-items: start;
	}

	body.woocommerce-account .woocommerce-MyAccount-navigation {
		margin: 0;
	}

	/* Das Clearfix-Pseudoelement des WooCommerce-CSS waere sonst die erste
	   Rasterzelle und schoebe das Menue in die zweite Spalte. */
	body.woocommerce-account .entry-content > .woocommerce:has(> .woocommerce-MyAccount-navigation)::before,
	body.woocommerce-account .entry-content > .woocommerce:has(> .woocommerce-MyAccount-navigation)::after {
		content: none;
	}
}

:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li {
	margin: 0;
	padding: 0;
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li:first-child {
	border-top: 1px solid var(--wp--preset--color--rule);
}

/* Kante links 3 px an jedem Eintrag (transparent), damit der Text beim
   aktiven Eintrag nicht springt. */
:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li a {
	display: block;
	padding: 12px 0 12px 12px;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--bedienung);
	color: var(--wp--custom--text--grund);
	text-decoration: none;
	border-left: 3px solid transparent;
}

:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li a:hover {
	color: var(--wp--preset--color--blue-dark);
}

:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li.is-active a,
:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li a[aria-current="page"] {
	font-weight: 700;
	color: var(--wp--preset--color--blue-dark);
	border-left-color: var(--wp--preset--color--blue);
}

/* Abmelden durch Abstand abgesetzt. */
body.woocommerce-account .woocommerce-MyAccount-navigation li.woocommerce-MyAccount-navigation-link--customer-logout {
	margin-top: var(--wp--preset--spacing--gap-l);
	border-top: 1px solid var(--wp--preset--color--rule);
}

:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li::before,
:is(body.woocommerce-account .woocommerce-MyAccount-navigation, .ml-kategorien) li a::before {
	content: none;
}

/* ----- Inhalt ------------------------------------------------------------- */

body.woocommerce-account .woocommerce-MyAccount-content > :is(p, form) {
	max-width: var(--wp--style--global--content-size);
}

body.woocommerce-account .woocommerce-MyAccount-content > p:first-of-type {
	margin-top: 0;
}

/* Bestellungen: wie die Artikelliste im Warenkorb. */
body.woocommerce-account table.woocommerce-orders-table {
	width: 100%;
	border: 0;
	border-collapse: collapse;
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

body.woocommerce-account table.woocommerce-orders-table th {
	padding: 8px 12px 8px 0;
	font-size: var(--wp--preset--font-size--meta);
	font-weight: 600;
	color: var(--wp--custom--text--gedaempft);
	text-align: left;
	text-transform: none;
	border: 0;
}

body.woocommerce-account table.woocommerce-orders-table td {
	padding: 16px 12px 16px 0;
	border: 0;
	border-top: 1px solid var(--wp--preset--color--rule);
}

/* Adressen: zwei Karten ab 768. */
body.woocommerce-account .woocommerce-Addresses {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--gap-l);
	margin-top: var(--wp--preset--spacing--gap-l);
}

@media (min-width: 768px) {
	body.woocommerce-account .woocommerce-Addresses {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

body.woocommerce-account .woocommerce-Addresses::before,
body.woocommerce-account .woocommerce-Addresses::after {
	content: none;
}

body.woocommerce-account .woocommerce-Addresses .woocommerce-Address {
	float: none;
	width: auto;
	margin: 0;
	padding: var(--wp--preset--spacing--gap-l);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--card);
}

body.woocommerce-account .woocommerce-Address-title {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
	margin: 0 0 var(--wp--custom--abstand--label);
}

body.woocommerce-account .woocommerce-Address-title::before,
body.woocommerce-account .woocommerce-Address-title::after {
	content: none;
}

body.woocommerce-account .woocommerce-Address-title h2 {
	float: none;
	margin: 0;
	font-size: var(--wp--preset--font-size--titel-m);
	font-weight: 900;
	line-height: var(--wp--custom--line-height--card);
}

body.woocommerce-account .woocommerce-Address-title .edit {
	float: none;
	color: var(--wp--preset--color--blue-dark);
}

body.woocommerce-account .woocommerce-Address address {
	margin: 0;
	font-style: normal;
}

/* ========================================================================
   Produkt-Teaser (025, 0.98.0) — B09 Produktkarte, S24 Produkt-Slider

   Beide zeigen die Shop-Produktkarte aus 020 (`.ml-card ml-produktkarte`,
   Buehne 5:4, Rand rule, Radius card, Fokus an der ganzen Karte). Auf
   normalen Seiten gibt es kein `body.woocommerce-page` und kein WooCommerce-
   CSS - Preis und Pflichtangaben stehen deshalb hier noch einmal fuer die
   Karte selbst, mit denselben Token wie die Grundregel B4.
   --------------------------------------------------------------------- */

/* B09: Baustein ohne eigenen Rahmen. Eigenbreite 328 (eine Spalte bei 680/2)
   auf oberster Ebene ueber die Bahn-Regel; in einer Spalte volle Spaltenbreite. */
.ml-produkt-teaser {
	--ml-eigenbreite: var(--wp--custom--baustein--karte);
	max-width: var(--wp--custom--baustein--karte);
}

/* In einer Spalte volle Spaltenbreite (A4) - im Frontend und im Editor, wo die
   allgemeine Baustein-Regel (0,3,0) sonst die Eigenbreite als Grenze setzt. In
   einer Sektion bleibt die Karte bei ihrer Eigenbreite, wie FAQ und Tabs. */
.wp-block-column > .ml-produkt-teaser,
.editor-styles-wrapper .wp-block-column > .ml-produkt-teaser.ml-block {
	max-width: none;
}

.ml-produkt-teaser .gb-loop-item {
	display: flex;
}

.ml-produkt-teaser .ml-produktkarte,
.ml-cardslider__item > .ml-produktkarte {
	height: 100%;
}

/* Preis und Pflichtangaben (Dynamic Tag ml_produkt_preis). */
.ml-produktkarte__preis {
	margin: 0 0 var(--wp--preset--spacing--gap-s);
}

.ml-produktkarte__preis .price {
	display: block;
	margin: 0 0 6px;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	color: var(--wp--custom--text--grund);
}

.ml-produktkarte__preis .price del {
	font-weight: 400;
	color: var(--wp--custom--text--gedaempft);
	text-decoration: line-through;
	opacity: 1;
}

.ml-produktkarte__preis .price ins {
	font-weight: 700;
	color: inherit;
	text-decoration: none;
	background: none;
}

.ml-produktkarte__preis .wc-gzd-additional-info {
	margin: 0;
	font-size: var(--wp--preset--font-size--label-s);
	line-height: var(--wp--custom--line-height--liste);
	color: var(--wp--custom--text--gedaempft);
}

/* Versandkosten-Link liegt ueber dem gestreckten Kartenlink (wie im Shop). */
.ml-produktkarte__preis .wc-gzd-additional-info a {
	position: relative;
	z-index: 2;
	color: var(--wp--preset--color--blue-dark);
}

.ml-produktkarte .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* B09: Knopf „Zum Produkt" (Umriss) am Fuss der Karte. Er ist der einzige Link
   der Karte und gestreckt (.ml-card__link): die ganze Karte fuehrt zum Produkt,
   der Fokusrahmen sitzt an der Karte. */
.ml-produktkarte__knopf {
	align-self: flex-start;
	margin-top: auto;
}

/* ---- Wiki-Artikelansicht (023) ---------------------------------------------

   GP-Element „Wiki-Artikelansicht" (content-template, post:wiki): nach dem
   Inhalt die Sektion `ml-wiki-anhang` mit den Schlagwörtern und „Mehr zum
   Thema" (gefüllt vom Plugin lvn-wiki), danach S16.

   Der Artikel ist getippter Fliesstext. Die Vorlage gibt ihn in
   `.dynamic-entry-content` aus, nicht in `.entry-content` — die Regeln der
   Seitenebene (A14) greifen dort nur, weil `.single-wiki .dynamic-entry-content`
   in ihren `:is()`-Listen steht (Abschnitt „Fliesstext auf Seitenebene"; gleiche
   Spezifität wie das stärkste Argument, (0,2,0)). Ohne das lief der Text über
   die volle Fensterbreite (gemessen 023: Absatz 0–1440).

   Die Fläche ist Weiss wie eine Seite: die Vorlage rendert kein
   `inside-article`, die Kette fällt sonst bis zum body (#F7F8F9) durch.

   Anhang: beide Teile in der Lesebreite, links bündig mit dem Text darüber.
   Die Sektion folgt dem Text näher als eine Sektion der anderen: oben `band`
   statt `sektion` — die Schlagwörter gehören zum Artikel.
   ------------------------------------------------------------------------- */
.single-wiki .dynamic-content-template {
	background-color: var(--wp--preset--color--white);
}

/* Der Artikel beginnt mit getipptem Text, nicht mit einer Sektion: ohne Abstand
   stand die erste Überschrift an der Unterkante des Seitenkopfs (gemessen 023). */
.single-wiki .dynamic-entry-content {
	padding-top: var(--wp--preset--spacing--band);
}

.ml-section.ml-wiki-anhang {
	padding-top: var(--wp--preset--spacing--band);
	background-color: var(--wp--preset--color--white);
}

.ml-wiki-anhang .ml-container > * {
	max-width: var(--wp--style--global--content-size);
}

.ml-wiki-schlagwoerter .ml-label {
	margin-bottom: 0.5rem;
}

.ml-wiki-schlagwoerter + .ml-wiki-mehr {
	margin-top: var(--wp--preset--spacing--band);
}

.ml-wiki-mehr__titel {
	margin-bottom: var(--wp--preset--spacing--gap-s);
}

.ml-wiki-mehr__liste ul {
	margin-bottom: 0;
}

/*
 * Nachtrag 2 (Marc 17.10.): die Lesespalte steht MITTIG in der Spur, ab 1024 — links
 * und rechts gleich. Darunter bleibt A14 (linker Seitenrand). Seitenkopf und S16 bleiben
 * links an der Spur, der Anhang folgt seit 040 der Lesespalte (unten). (0,5,0) wie die Lesebreiten-Regel, steht spaeter.
 * `flow-root` haelt umfliessende Bilder im Artikel.
 */
.single-wiki .dynamic-entry-content {
	display: flow-root;
}

@media (min-width: 1024px) {
	.single-wiki .dynamic-entry-content > :not(.ml-section):not(.gb-is-root-block):not(.ml-block) {
		margin-inline: auto;
	}

	/*
	 * 040 (Marc 19.10.): Schlagwoerter und „Mehr zum Thema" stehen unter dem Text, in derselben
	 * mittigen Lesespalte — nicht mehr links an der Spur (023 Nachtrag 2). Der Container der
	 * Sektion steht mittig in der Seite, `auto` setzt die Teile damit auf die Kante des Textes.
	 */
	.ml-wiki-anhang .ml-container > * {
		margin-inline: auto;
	}
}

/*
 * 034: Eingebettete Fremdinhalte ohne Huelle (Bestand: zwei podigee-Player als `<iframe>` in einem
 * HTML-Block, Kaelberaufzucht) sind Inline-Elemente — `margin-inline: auto` der Spalte wirkt an
 * ihnen nicht, sie standen bei 1440 bei x 0 und x 685 nebeneinander. Als Block nehmen sie Lage
 * und Breite der Spalte; die Hoehe bleibt die des Attributs. Abstand wie zwischen zwei
 * Absaetzen (`> * + *`).
 */
.single-wiki .dynamic-entry-content > :is(iframe, video, object, embed) {
	display: block;
	width: 100%;
}

/*
 * Ein Abstandhalter des Bestands IST der Abstand: der Block danach bringt keinen
 * eigenen Rand mehr mit. Sonst addierten sich 40 px Abstandhalter und 1,8 em vor
 * einer H3 zu 188 px (Gruenland, 1440; Grenze 120). `:is()` hebt auf (0,4,1) — ueber
 * die H2-Regel (0,3,1).
 */
.single-wiki .dynamic-entry-content > .wp-block-spacer + :is(*, h2.wp-block-heading) {
	margin-block-start: 0;
}

/*
 * Bilder mit `alignright`/`alignleft` fliessen INNERHALB der Spalte: der Rand zur
 * Fensterkante ist der Abstand der Spalte (ab 1024 mittig, darunter A14). Ohne das
 * stand das Bild an der Fensterkante (Kaelberaufzucht: x 1140 bei 1440).
 * Unter 768 kein Umfluss: das Bild nimmt die Spaltenbreite.
 */
.single-wiki .dynamic-entry-content > .alignright:not(.ml-section):not(.gb-is-root-block) {
	float: right;
	margin-left: var(--wp--preset--spacing--gap-l);
	margin-right: calc(100% - var(--wp--preset--spacing--rand) - min(var(--wp--style--global--content-size), 100% - 2 * var(--wp--preset--spacing--rand)));
}

.single-wiki .dynamic-entry-content > .alignleft:not(.ml-section):not(.gb-is-root-block) {
	float: left;
	margin-right: var(--wp--preset--spacing--gap-l);
	margin-left: max(var(--wp--preset--spacing--rand), calc((100% - var(--wp--style--global--wide-size)) / 2));
}

@media (min-width: 1024px) {
	.single-wiki .dynamic-entry-content > .alignright:not(.ml-section):not(.gb-is-root-block) {
		margin-right: calc((100% - var(--wp--style--global--content-size)) / 2);
	}

	.single-wiki .dynamic-entry-content > .alignleft:not(.ml-section):not(.gb-is-root-block) {
		margin-left: calc((100% - var(--wp--style--global--content-size)) / 2);
	}
}

@media (max-width: 767px) {
	/* `display: table` des Kerns (figure.wp-block-image.alignright) schrumpft auf das Bild — Block statt Tabelle. */
	.single-wiki .dynamic-entry-content > :is(.alignright, .alignleft):not(.ml-section):not(.gb-is-root-block) {
		display: block;
		float: none;
		margin-inline: var(--wp--preset--spacing--rand) auto;
	}

	.single-wiki .dynamic-entry-content > :is(.alignright, .alignleft) img {
		width: 100%;
	}
}

/* ---- Tabelle (`core/table`, 023 Nachtrag 2) ----------------------------------

   Fuer Redakteure freigeschaltet (Marc 17.10.). Linien aus `rule` statt der
   Textfarbe des Kerns, Kopfzeile fett; der Kern laesst `figure.wp-block-table`
   waagerecht scrollen (`overflow-x: auto`) — die Seite laeuft nicht ueber.
   --------------------------------------------------------------------------- */
.wp-block-table :is(td, th) {
	border-color: var(--wp--preset--color--rule);
}

.wp-block-table :is(thead, tfoot) {
	border-color: var(--wp--preset--color--rule);
}

.wp-block-table :is(thead, th) {
	font-weight: 700;
}

/* ---- Wiki-Suche und Wiki-Themen (024) ---------------------------------------

   S25 · Wiki-Suche (`.ml-wiki-suche-sektion` > Block `lvn-wiki/suche`) und
   S26 · Wiki-Themen (`.ml-wiki-themen-sektion` > Block `lvn-wiki/themen`); das Markup
   der Bloecke rendert das Plugin lvn-wiki. Themen- und Schlagwortseiten: Block
   `lvn-wiki/artikelliste` (`.ml-wiki-archiv`).
   Suche: Feld in der Lesebreite (680), links an der Spur; im Wiki-Artikel mittig wie
   die Lesespalte (023). Treffer als Liste unter dem Feld (Combobox/Listbox).
   Themen: Karten wie S04 (`ml-card-thema`, Buehne 16:10), 3 / 3 / 2 / 1 Spalten; das
   Themenfeld steht im Markup hinter seiner Kachel und spannt ueber alle Spalten —
   `grid-auto-flow: dense` setzt es unter die Reihe, die uebrigen Kacheln ruecken nach.
   --------------------------------------------------------------------------- */
.ml-section.ml-wiki-suche-sektion {
	padding-block: var(--wp--preset--spacing--band);
}

.ml-wiki-suche-sektion > .ml-wiki-suche {
	max-width: min(var(--wp--style--global--content-size), 100%);
	margin-inline: max(0px, calc((100% - var(--wp--style--global--wide-size)) / 2)) auto;
}

/*
 * 035 (Marc 18.10.): Auf der Wiki-Hauptseite (`ml-wiki-hauptseite`, Body-Klasse aus lvn-wiki) steht der
 * Fliesstext ab 1024 mittig in der Lesespalte wie im Artikel (023). Die Themenabschnitte stehen in
 * `core/columns` mit „Breite Breite" (1328) und behalten die volle Spur. (0,5,0) wie die
 * Lesebreiten-Regel (A14), steht spaeter. Suche und Kacheln (Sektionen) bleiben links an der Spur.
 */
@media (min-width: 1024px) {
	.ml-wiki-hauptseite .entry-content > :not(.ml-section):not(.gb-is-root-block):not(.ml-block) {
		margin-inline: auto;
	}
}

@media (min-width: 1024px) {
	.single-wiki .ml-wiki-suche-sektion > .ml-wiki-suche {
		margin-inline: auto;
	}
}

.ml-wiki-suche__form {
	position: relative;
	margin: 0;
}

.ml-wiki-suche__label {
	display: block;
	margin-bottom: var(--wp--custom--abstand--label);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	color: var(--wp--preset--color--blue-dark);
}

.ml-wiki-suche__zeile {
	display: flex;
	gap: var(--wp--preset--spacing--gap-s);
	align-items: stretch;
}

.ml-wiki-suche input.ml-wiki-suche__feld {
	flex: 1 1 auto;
	min-width: 0;
	min-height: 56px;
	padding: 0 var(--wp--preset--spacing--gap-s);
	font-size: var(--wp--preset--font-size--body);
	color: var(--wp--custom--text--grund);
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
}

.ml-wiki-suche input.ml-wiki-suche__feld::placeholder {
	color: var(--wp--custom--text--gedaempft);
	opacity: 1;
}

.ml-wiki-suche__knopf {
	flex: 0 0 auto;
	justify-content: center;
}

.ml-wiki-suche__liste {
	position: absolute;
	z-index: 20;
	inset-inline: 0;
	top: 100%;
	margin: 4px 0 0;
	padding: 0;
	list-style: none;
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--gray-dark);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: 0 8px 24px color-mix(in srgb, var(--wp--preset--color--black) 12%, transparent);
	max-height: min(70vh, 34rem);
	overflow-y: auto;
}

.ml-wiki-suche__liste[hidden],
.ml-wiki-suche__leer[hidden] {
	display: none;
}

.ml-wiki-suche__option {
	display: flex;
	flex-wrap: wrap;
	gap: 2px var(--wp--preset--spacing--gap-s);
	align-items: baseline;
	justify-content: space-between;
	margin: 0;
	padding: 12px var(--wp--preset--spacing--gap-s) 12px calc(var(--wp--preset--spacing--gap-s) - 3px);
	border-left: 3px solid transparent;
	cursor: pointer;
}

.ml-wiki-suche__option + .ml-wiki-suche__option {
	border-top: 1px solid var(--wp--preset--color--rule);
}

/* Markiert (Pfeiltasten oder Maus): Flaeche UND Kante — nicht nur ueber Farbe. */
.ml-wiki-suche__option[aria-selected="true"],
.ml-wiki-suche__option:hover {
	background-color: var(--wp--preset--color--blue-tint);
	border-left-color: var(--wp--preset--color--blue);
}

.ml-wiki-suche__titel {
	font-weight: 700;
	color: var(--wp--preset--color--blue-dark);
}

.ml-wiki-suche__thema,
.ml-wiki-suche__leer {
	font-size: var(--wp--preset--font-size--meta);
	color: var(--wp--custom--text--gedaempft);
}

.ml-wiki-suche__leer {
	margin: var(--wp--custom--abstand--label) 0 0;
}

.ml-wiki-suche__alle .ml-wiki-suche__titel {
	font-weight: 600;
}

.ml-wiki-suche__ergebnis {
	margin-top: var(--wp--preset--spacing--gap-l);
}

.ml-wiki-suche__zahl {
	margin: 0 0 var(--wp--custom--abstand--label);
	font-weight: 700;
}

.ml-wiki-suche__treffer {
	margin: 0 0 0 1.2em;
}

.ml-wiki-suche__treffer a,
.ml-wiki-liste a,
.ml-wiki-thema__alle a {
	color: var(--wp--preset--color--blue-dark);
}

/* Themenkacheln */
.ml-wiki-themen {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	grid-auto-flow: row dense;
	gap: var(--wp--preset--spacing--gap-l);
}

@media (max-width: 1023px) {
	.ml-wiki-themen {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 599px) {
	.ml-wiki-themen {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Offen bzw. aktuelles Thema: Rahmen 2 px und Pfeil nach unten — nicht nur Farbe. */
.ml-wiki-thema:is(.is-offen, .is-aktuell) {
	box-shadow: 0 0 0 2px var(--wp--preset--color--blue);
}

.ml-wiki-thema.is-offen .ml-arrow svg {
	transform: rotate(135deg);
}

.ml-wiki-thema__feld {
	grid-column: 1 / -1;
	padding: var(--wp--preset--spacing--gap-l);
	background-color: var(--wp--preset--color--gray-bg);
	border-radius: var(--wp--custom--radius--panel);
}

.ml-wiki-thema__feld[hidden] {
	display: none;
}

.ml-wiki-thema__beschreibung,
.ml-wiki-archiv__beschreibung {
	max-width: var(--wp--style--global--content-size);
	margin: 0 0 var(--wp--preset--spacing--gap-l);
}

/* Artikel als Linkliste, 3 / 2 / 2 / 1 Spalten (Lesereihenfolge spaltenweise wie A14). */
.ml-wiki-liste {
	margin: 0;
	padding: 0;
	list-style: none;
	columns: 3;
	column-gap: var(--wp--preset--spacing--gap-l);
}

.ml-wiki-liste li {
	margin: 0 0 var(--wp--custom--abstand--label);
	break-inside: avoid;
}

/* Liste 3 / 2 / 2 / 1 bei 1440 / 1024 / 768 / 390 — bei 1024 schon zwei (die Kacheln dort noch drei). */
@media (max-width: 1024px) {
	.ml-wiki-liste {
		columns: 2;
	}
}

@media (max-width: 599px) {
	.ml-wiki-liste {
		columns: 1;
	}
}

.ml-wiki-thema__alle {
	margin: var(--wp--preset--spacing--gap-s) 0 0;
	font-weight: 700;
}

/* Themen- und Schlagwortseite */
.ml-wiki-archiv__titel {
	margin-bottom: var(--wp--preset--spacing--gap-s);
}

.ml-wiki-archiv__leer {
	margin: 0;
}

/* ---- Seite Ansprechpartner (036) ---------------------------------------------

   Geschaeftsstellen: `core/columns` „Breite Breite" mit der Klasse `ml-geschaeftsstellen` —
   nebeneinander erst ab 1024, darunter gestapelt (Hannover zuerst); A5 stapelt sonst erst unter 782.
   Karte (Block `lvn-ansprechpartner/karte`): Buehne 4:3, Radius `card`, Rand 1 px `rule`.
   B07 im Modus „alle": Filterleiste ueber dem Raster; verborgene Karten ueber `hidden`
   (`.ml-team__card` setzt `display` — Stolperstelle 159/163).
   --------------------------------------------------------------------------- */
@media (max-width: 1023px) {
	.entry-content .wp-block-columns.ml-geschaeftsstellen {
		flex-direction: column;
	}

	.entry-content .wp-block-columns.ml-geschaeftsstellen > .wp-block-column {
		flex-basis: auto;
		width: 100%;
	}
}

.ml-karte {
	position: relative;
	aspect-ratio: 4 / 3;
	margin: var(--wp--preset--spacing--gap-l) 0 0;
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: var(--wp--custom--radius--card);
}

.ml-karte__rahmen {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

.ml-karte-editor__label {
	margin: 0;
	font-size: var(--wp--preset--font-size--meta);
	color: var(--wp--custom--text--gedaempft);
}

.ml-team-filter {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--gap-s);
	margin-bottom: var(--wp--preset--spacing--gap-l);
}

.ml-team-filter[hidden],
.ml-team__card[hidden] {
	display: none;
}

.ml-team-filter__knopf[aria-pressed="true"] {
	background-color: var(--wp--preset--color--blue);
	border-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
}
