/*
 * Seitenlayout.
 *
 * Genau ein Viewport-Breakpoint: 992px. Er schaltet das Seitenlayout von
 * einspaltig auf Inhalt + Seitenleiste. Jede weitere Anpassung läuft über
 * Container Queries — ein Bauteil kennt nur die Breite seines Containers,
 * nie die des Fensters. Das ist die Voraussetzung dafür, dass dieselbe
 * Beitragskarte in Inhaltsspalte, Archivraster, Seitenleiste und in jedem
 * Custom Loop unverändert funktioniert.
 */

/*
 * Der Versatz unter der schwebenden Kopfleiste.
 *
 * Steht hier oben und nicht beim Header, weil ihn drei Dinge brauchen, die
 * ueber die Datei verteilt sind: der Platz fuer den Seiteninhalt, der
 * Klebepunkt der Seitenleiste und der Versatz der Sprungziele. Eine Zahl,
 * eine Quelle. Die Rechnung steht am Header, Abschnitt „Die schwebende
 * Pille".
 *
 * `scroll-padding-top` an der Wurzel und nicht `scroll-margin-top` an jedem
 * Sprungziel: Letzteres muesste an jeder Ueberschrift stehen, die je ein Ziel
 * werden kann — und der Anker-Automat des Toolkits vergibt Ziele zur
 * Laufzeit. Eine Regel an der Wurzel gilt fuer alle, auch fuer die, die es
 * noch nicht gibt.
 */
:root {
	--g-header-offset: 92px;
	scroll-padding-top: var(--g-header-offset);
}

.wp-site-blocks {
	padding-block-start: var(--g-header-offset);
}

.g-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--custom--layout--column-gap);
}

.g-layout__content,
.g-layout__sidebar {
	min-width: 0;
	container-type: inline-size;
}

/* Die Seitenleiste ist zusätzlich benannt — siehe die Regel zur schmalen
   Karte weiter unten. */
.g-layout__sidebar {
	container-name: sidebar;
}

@media (min-width: 992px) {
	.g-layout {
		grid-template-columns: minmax(0, 1fr) var(--wp--custom--layout--sidebar-width);
	}

	/*
	 * Die GANZE Spalte klebt, nicht ein Part darin.
	 *
	 * Vorher klebte der erste von zwei Parts. Ein klebendes Element wird aus
	 * seinem Flussplatz verschoben, aber der Fluss reserviert die Verschiebung
	 * nicht — der nachfolgende Geschwister-Part rueckt weiter nach oben, als
	 * klebte nichts. Kollision war damit nicht der Sonderfall, sondern der
	 * Normalfall: Ein klebendes Element kollidiert immer mit dem, was ihm
	 * folgt. (Beobachtet am ersten Projekt: Inhaltsverzeichnis und Empfohlene
	 * Beitraege lagen uebereinander.)
	 *
	 * `align-self: start` ist die Bedingung dafuer. Ohne es dehnt das Raster
	 * die Spalte auf die Hoehe der Inhaltsspalte (Grid-Standard `stretch`) —
	 * und ein klebendes Element, das so hoch ist wie sein Rasterfeld, hat
	 * keinen Weg zum Kleben.
	 */
	.g-layout__sidebar {
		position: sticky;
		top: var(--g-header-offset);
		align-self: start;
		z-index: 1;

		/*
		 * Der Rueckfall, wenn die Spalte trotz eingeklapptem Verzeichnis
		 * hoeher wird als das Fenster: Sie scrollt in sich selbst, statt ihr
		 * unteres Ende unerreichbar zu machen. Das ist der bekannte Preis der
		 * klebenden Gesamtspalte — hier bezahlt, nicht verschwiegen.
		 *
		 * `--g-sidebar-max` ist die Nahtstelle dafuer. Ein Projekt, das lieber
		 * die ganze Spalte am Stueck zeigt und in Kauf nimmt, dass ihr Ende
		 * unter dem Fensterrand liegt, setzt sie auf `none`; ohne Grenze
		 * scrollt `overflow-y: auto` nie. Die Entscheidung gehoert dorthin,
		 * weil sie eine Abwaegung ist und keine Struktur.
		 */
		max-block-size: var(
			--g-sidebar-max,
			calc(100dvh - var(--g-header-offset) - var(--wp--preset--spacing--md))
		);
		overflow-y: auto;
		overscroll-behavior: contain;
	}
}

/*
 * ---------------------------------------------------------------------------
 * Beitragsraster (`g-article-grid`).
 * ---------------------------------------------------------------------------
 *
 * Vier Spuren, Seitenleiste LINKS, Text rechts:
 *
 *     minmax(0,1fr)  18.5rem       minmax(0,41rem)  minmax(0,1fr)
 *     Rinne          Seitenleiste  Lesespalte       Rinne
 *
 * DIE RINNE NEBEN DER SEITENLEISTE IST EINE NAHTSTELLE (`--g-article-edge`).
 * Mit dem Vorgabewert `1fr` stehen beide Rinnen gleich breit, so wie der
 * Entwurf sie zeichnet. Setzt ein Projekt sie auf `0fr`, faellt sie weg: Die
 * Seitenleiste beginnt dann an derselben Kante wie Kopfleiste, H1 und
 * Kartenraster jeder anderen Seite, und die ganze freie Breite sammelt sich
 * auf der Gegenseite — dort, wo der Ausbruch der Tabelle ohnehin hinlaeuft.
 * Es ist EINE Zahl, keine zweite Spurdefinition; wer die Leiste eines Tages
 * nach rechts stellt, setzt dieselbe Nahtstelle an die dann aeussere Spur.
 *
 * SIE STEHT ALS RUECKFALL IN DER SPURDEFINITION UND NICHT ALS EIGENSCHAFT AN
 * `.g-article-grid`. Eine Deklaration am Element selbst schlaegt jeden geerbten
 * Wert von `:root` — ein Skin, der sie dort setzt, haette nichts bewirkt und
 * die Regel waere trotzdem ausgeliefert worden. Gemessen am 2026-09-03: Die
 * Seitenleiste blieb bei 164px stehen, obwohl `0fr` im Skin stand.
 *
 * Die Kopfzone der Beitragsseite und der Hauptbereich benutzen **dieselbe**
 * Klasse und damit dieselbe einzige Deklaration. Der Entwurf verspricht
 * „Metabox und Inhaltsverzeichnis fluchten, Abweichung 0 px". Dieses
 * Versprechen ist hier nicht gemessen, sondern **konstruiert**: Es gibt keine
 * zweite Spurdefinition, die auseinanderlaufen koennte. Wer eine anlegt, hebt
 * die Zusage auf.
 *
 * `.g-layout` daneben bleibt unberuehrt — es traegt das zweispaltige Raster
 * von `single-review.html` und ist ein anderes Bauteil.
 *
 * Mobile-first: unter 992px gibt es keine Seitenleistenspur, alles steht
 * einspaltig in Dokumentreihenfolge. Der Breakpoint ist der eine des Systems.
 */

.g-article-grid {
	/*
	 * Spurbreite der Seitenleiste. 18.5rem ist der Wert des Entwurfs,
	 * davon 4rem Abstand nach rechts, sichtbar also 14.5rem.
	 * Als Custom Property, damit ein Projekt sie im Skin ersetzen kann,
	 * ohne die Spurdefinition zu verdoppeln.
	 */
	--g-article-side: 18.5rem;

	/*
	 * Versatz der klebenden Spalte: 104px.
	 *
	 * Die Zahl ist im Entwurf **gesetzt** (`scroll-margin-top: 104px`) und
	 * nicht gerechnet. Die frueher hier stehende Begruendung „Kopfleiste 80px
	 * plus 24px Luft" stammte aus `leserfuehrung.md`; nach **D14** gilt bei
	 * Widerspruechen `bauteile.md`, und dort ist die Pille 72px hoch. Die
	 * Begruendung war also falsch, der Wert bleibt richtig.
	 */
	--g-article-sticky-top: var(--g-header-offset);

	display: grid;
	grid-template-columns: 1fr;
	column-gap: 0;
	row-gap: var(--wp--preset--spacing--md);

	/*
	 * `wideSize` PLUS die beiden Seitenraender, und das ist kein Zuschlag,
	 * sondern die Berichtigung eines Messfehlers.
	 *
	 * Jeder andere Traeger des Themes ist ein `constrained`-Container: Der
	 * Seitenrand kommt dort von `main`, die Breitengrenze greift INNERHALB
	 * davon, und die INHALTSbreite ist deshalb genau `wideSize`. Hier lag der
	 * Rand im selben Kasten wie die Grenze — die Inhaltsbreite war damit
	 * `wideSize` minus 32px.
	 *
	 * Gemessen am 2026-09-03 bei 1280px: Rubrikseite und Startseite laufen
	 * 40..1240 (1200px), die Beitragsseite 56..1224 (1168px). Zwei Seiten
	 * desselben Themes mit zwei Rasterkanten, und im Markup war beides
	 * richtig. Mit dem Zuschlag steht die Inhaltskante wieder auf 40.
	 */
	max-width: calc(var(--wp--style--global--wide-size) + 32px);
	margin-inline: auto;

	/*
	 * Seitenrand mobil 16px, laut Entwurf. Er kommt genau einmal, hier.
	 * Deshalb steht `main` in `single.html` auf `default` und nicht auf
	 * `constrained` — sonst laege das Root-Padding zusaetzlich davor.
	 */
	padding-inline: 16px;
}

/*
 * Verschachtelte `constrained`-Gruppen bringen ihren Seitenrand ein zweites
 * Mal ein, sobald ueber ihnen keine Gruppe mit `has-global-padding` mehr
 * steht (der Core-Regel fehlt dann der Vorfahre, an dem sie null setzt).
 * Innerhalb des Beitragsrasters kommt der Rand vom Raster, sonst nirgends.
 * `:where()` haelt die Spezifitaet bei null, damit ein Skin ohne `!important`
 * dagegen ankommt.
 */
.g-article-grid :where(.has-global-padding) {
	padding-inline: 0;
}

/*
 * Der Template-Part `post-meta` liefert Kopf und Metabox als zwei
 * Geschwister. `display: contents` loest den Part-Wrapper auf, damit beide
 * direkte Rasterkinder werden. Ohne das waeren sie ein einziges Feld und die
 * Metabox koennte nicht in der Seitenleistenspur stehen.
 */
.g-post-hero > .wp-block-template-part {
	display: contents;
}

/*
 * ---------------------------------------------------------------------------
 * DAS BEITRAGSENDE AUF DEM TELEFON
 * ---------------------------------------------------------------------------
 *
 * UNTERHALB DES BREAKPOINTS STEHT DER AUTOR ZUERST UND DIE LESETIPPS ZULETZT.
 * Weisung des Auftraggebers vom 2026-09-04: Autorenkasten, dann
 * Beitragsverlauf, dann Lesetipps. Auf dem Desktop bleibt die
 * Dokumentreihenfolge, weil dort die Seitenleiste danebensteht und der Autor
 * schon in ihr vorkommt.
 *
 * WARUM `order` UND KEIN UMBAU DES TEMPLATES. Die Reihenfolge ist NUR mobil
 * eine andere. Wer sie im Markup dreht, muesste sie auf dem Desktop mit
 * denselben Mitteln zuruecknehmen — dann traegt die breite Ansicht das
 * Risiko, und die ist die geprueftere. So bleibt der Desktop Byte fuer Byte
 * unberuehrt: Die Flex-Regel wird ab 992 px wieder auf `block` gesetzt.
 *
 * WARUM DAS ERSTE KIND SEINEN OBERRAND VERLIERT. In einem Flex-Container
 * kollabieren Raender nicht mehr. Der Beitragstext traegt 21 px oben; im
 * Blockfluss wandert dieser Rand aus `main` heraus, im Flex-Fluss bliebe er
 * drin und schoebe die ganze Spalte 21 px nach unten. Gemessen am 2026-09-04.
 *
 * `:has(> .g-author-box)` und kein eigener Selektor: Der Autorenkasten kommt
 * als Template-Part, und dessen Umschlag traegt keine Klasse.
 */
.g-article-grid__main {
	display: flex;
	flex-direction: column;
}

.g-article-grid__main > :first-child {
	margin-block-start: 0;
}

.g-article-grid__main > :has(> .g-author-box) {
	order: 1;
}

.g-article-grid__main > .g-changelog {
	order: 2;
}

.g-article-grid__main > .g-related {
	order: 3;
}

/*
 * DIE SEITENLEISTE DER BEITRAGSSEITE FAELLT MOBIL WEG.
 *
 * Sie sagt unterhalb des Breakpoints nichts, was der Beitrag nicht schon
 * gesagt haette: Das Verzeichnis traegt die Inline-Box und die Inhaltsleiste,
 * die Autorenkarte doppelt den Autorenkasten (dieselbe Person, dieselbe Bio,
 * 280 px darunter), die Pruefzeile haengt an der Karte, und die Empfehlungen
 * stehen als Lesetipps am Ende. Gemessen am 2026-09-04 bei 375 px: drei
 * Bloecke ab y 17021, alle nach dem Autorenkasten.
 *
 * `display: none` und nicht ein leerer Anker: Die Spalte ist gefuellt, `:empty`
 * greift also nicht — derselbe Fall wie bei der Ankergruppe am Seitenende.
 *
 * Der Selektor bleibt am Beitragsraster. `.g-layout__sidebar` schlechthin
 * traefe auch `single-review.html`, und dort ist die Frage nicht gestellt.
 */
.g-article-grid > .g-article-grid__side {
	display: none;
}

@media (min-width: 992px) {
	/* Ab hier wieder Blockfluss: Die Reihenfolge oben gilt nur mobil. */
	.g-article-grid__main {
		display: block;
	}

	.g-article-grid > .g-article-grid__side {
		display: block;
	}

	.g-article-grid {
		grid-template-columns:
			minmax(0, var(--g-article-edge, 1fr))
			var(--g-article-side)
			minmax(0, var(--wp--style--global--content-size))
			minmax(0, 1fr);
	}

	/*
	 * Spur 2 traegt die Seitenleiste, Spur 3 den Text — und BEIDE ausdruecklich
	 * in Reihe 1.
	 *
	 * **Ohne `grid-row` landet die Seitenleiste unter dem Artikel.** Der Text
	 * steht im Markup vorher und bekommt Reihe 1; die automatische Platzierung
	 * ruecht danach nicht zurueck, also faellt die Leiste in Reihe 2. Gemessen
	 * am 2026-09-02: Artikel bei y=961, Inhaltsverzeichnis bei **y=5715** —
	 * eine mitlaufende Leiste, die erst nach dem Beitrag anfaengt.
	 *
	 * Im HTML war alles richtig, `position: sticky` stand da, die Spalte war
	 * die richtige. Sichtbar war es nur an der Position.
	 */
	.g-article-grid > .g-article-grid__side {
		grid-column: 2;
		grid-row: 1;
		padding-right: 4rem;
	}

	.g-article-grid > .g-article-grid__main {
		grid-column: 3;
		grid-row: 1;
	}

	/*
	 * DIE RICHTUNG DES AUSBRUCHS FOLGT DER SEITENLEISTE, und deshalb stehen
	 * die beiden Werte HIER — direkt neben den Spuren, aus denen sie folgen.
	 * Die Leiste steht in Spur 2, also links; frei ist die Gasse rechts, und
	 * nur dorthin darf ein Bauteil die Lesespalte verlassen. Wer die Spuren
	 * tauscht, tauscht diese beiden Zeilen mit.
	 *
	 * DIE ZAHL IST GERECHNET, NICHT GESETZT. `--g-breakout-edge` ist der
	 * Abstand von der Fenstermitte zum rechten Rand der Lesespalte plus 16px
	 * Seitenrand; mit den heutigen Token sind das 492px — genau der Wert des
	 * Entwurfs. Gerechnet und nicht abgeschrieben, damit eine geaenderte
	 * Spaltenbreite ihn mitnimmt statt ihn stillschweigend falsch zu machen.
	 *
	 * Und die Deckelung bei -8rem ist der eigentliche Schutz: Ohne sie waere
	 * der Ausbruch auf einem breiten Fenster beliebig gross. Bei 992px ergibt
	 * die Rechnung nur -4px, der Ausbruch faellt dort also fast weg — genau
	 * richtig, denn dort ist keine Gasse.
	 *
	 * DIE RECHNUNG GILT FUER DIE SYMMETRISCHE RINNE (`--g-article-edge: 1fr`),
	 * und die Deckelung ist der Grund, warum sie mit `0fr` trotzdem traegt:
	 * Faellt die linke Rinne weg, rueckt die Lesespalte nach LINKS, der
	 * gerechnete Wert wird also zu klein und nicht zu gross — der Ausbruch
	 * bleibt vor dem Fensterrand stehen, statt ihn zu ueberschreiten. Gemessen
	 * am 2026-09-03 bei 992, 1280 und 1440px: waagerechter Ueberlauf 0.
	 * Eine Rechnung, die beide Faelle exakt trifft, braeuchte die Fensterbreite
	 * OHNE Bildlaufleiste; `100vw` schliesst sie ein und haette den Ausbruch
	 * auf einem Geraet mit sichtbarer Leiste ueber den Rand geschoben.
	 */
	.g-article-grid {
		--g-article-gutter: calc(
			(var(--wp--style--global--wide-size) - var(--g-article-side) - var(--wp--style--global--content-size)) / 2
		);
		--g-breakout-edge: calc(var(--wp--style--global--wide-size) / 2 - var(--g-article-gutter) + 16px);
		--g-breakout-start: 0px;
		--g-breakout-end: max(-8rem, calc(var(--g-breakout-edge) - 50vw));
	}

	/*
	 * Die Kopfzone stellt ihre Felder ausdruecklich. Reihe 1 Titel,
	 * Reihe 2 Metabox und TL;DR nebeneinander, Reihe 3 das Bild.
	 *
	 * **KEIN `>` HIER, UND DAS IST DER GANZE PUNKT.** Titel und Metabox
	 * stecken in einem Template-Part, dessen Wrapper oben auf
	 * `display: contents` steht — nur so werden sie ueberhaupt Rasterkinder.
	 * `display: contents` aendert aber das **Layout** und nicht die
	 * **Verwandtschaft im Selektor**: Im DOM bleibt der Wrapper ihr Elternteil,
	 * also trifft `.g-post-hero > .g-post-hero__head` sie nicht.
	 *
	 * Gemessen, bevor das behoben war: `grid-column: auto / auto` an Titel und
	 * Metabox, der Titel landete in der 108 px breiten 1fr-Gasse und brach auf
	 * „Mess / beitr / ag / Baut / eile" um. Im HTML war alles richtig, und die
	 * Regeln wurden ausgeliefert — sichtbar wurde es erst im Browser.
	 *
	 * Die Titelzeile spannt Spur 2 bis 3: Der Entwurf setzt sie ueber Metabox
	 * **und** Textspalte, nicht nur ueber den Text.
	 */
	.g-post-hero .g-post-hero__head {
		grid-column: 2 / 4;
		grid-row: 1;
	}

	.g-post-hero .g-post-hero__facts {
		grid-column: 2;
		grid-row: 2;
		padding-right: 4rem;
	}

	.g-post-hero .g-post-hero__lead {
		grid-column: 3;
		grid-row: 2;
	}

	/*
	 * Das Aufmacherbild spannt Spur 2 bis 3, wie die Titelzeile.
	 *
	 * Der Entwurf stellt JEDES Kind seiner Kopfzone auf `grid-column: 2 / 4`
	 * und nimmt nur Metabox und TL;DR davon aus (`Beitragsseite.dc.html`,
	 * Zeilen 32 bis 37). Das Bild gehoert damit zu den breiten Feldern; es
	 * beginnt an derselben Kante wie H1 und Metabox und endet an der der
	 * Lesespalte.
	 *
	 * Es stand bis zum 2026-09-03 in Spur 3 und war damit 656px breit statt
	 * 952 — der Aufmacher war schmaler als die Ueberschrift ueber ihm.
	 */
	.g-post-hero .g-post-hero__media {
		grid-column: 2 / 4;
		grid-row: 3;
	}

	/*
	 * Der KI-Hinweis gehoert unter das Bild, in die Textspalte.
	 *
	 * **Ohne diese Regel steckt er in der 1fr-Gasse.** Gemessen am 2026-09-02:
	 * `grid-column: auto`, Breite **108 px**, Hoehe 127 px — ein Hinweissatz,
	 * der senkrecht in den Rand gequetscht ist. Dieselbe Falle wie beim Titel
	 * und aus demselben Grund: Wer in dieses Raster kommt, ohne gestellt zu
	 * werden, faellt in die Gasse.
	 *
	 * Er kommt aus dem Toolkit und nicht aus dem Template — das Raster muss
	 * ihn trotzdem stellen.
	 */
	.g-post-hero .g-ai-notice {
		grid-column: 3;
		grid-row: 4;
	}

	/*
	 * Der Versatz der klebenden Spalte ist im Beitragsraster 104px, nicht
	 * der Wert aus `.g-layout`. Sprungziele tragen denselben Versatz.
	 */
	.g-article-grid > .g-layout__sidebar {
		top: var(--g-article-sticky-top);
		max-block-size: var(
			--g-sidebar-max,
			calc(100dvh - var(--g-article-sticky-top) - var(--wp--preset--spacing--sm))
		);
	}
}

/*
 * Der Anker des Verzeichnisses im Textfluss.
 *
 * Er steht in `single.html`, `single-review.html` und `single-wide.html` ueber
 * dem Beitragstext. Ein Beitrag unter der Mindestanzahl an Ueberschriften
 * bekommt keines — dann bleibt eine leere Gruppe stehen, und die kostet den
 * Blockabstand ihres Traegers. Dieselbe `:empty`-Regel wie an jedem anderen
 * fuellbaren Anker dieses Themes.
 */
.g-toc-inline:empty {
	display: none;
}

/*
 * UND OHNE VERZEICHNIS BEGINNT DIE KOPFZONE AN DERSELBEN STELLE.
 *
 * Seit dem 2026-09-04 steht das Verzeichnis mobil VOR der Kopfzone. Ein
 * `display: none` nimmt die Gruppe aus dem Fluss, aber nicht aus
 * `:first-child` — die Kopfzone bleibt also das zweite Kind und behaelt ihren
 * Blockabstand. Gemessen an `/messbeitrag-kurz/` bei 375 px: Kopfzone bei
 * y 168 statt 147, also 21 px tiefer als auf einem Beitrag MIT Verzeichnis.
 * Ein Versatz, den nur der Vergleich zweier Beitraege zeigt.
 */
.g-toc-inline:empty + .g-post-hero {
	margin-block-start: 0;
}

/*
 * ---------------------------------------------------------------------------
 * Die Seitenleiste der Beitragsseite (`g-sidebar-sticky`)
 * ---------------------------------------------------------------------------
 *
 * DREI BLOECKE IN DIESER REIHENFOLGE, so wie der Entwurf sie stellt:
 * Inhaltsverzeichnis, Autorenkarte, Pruefzeile. Die Empfehlungen kommen aus
 * dem zweiten Part (`sidebar-extra`) darunter — sie stehen im Entwurf nicht in
 * der Spalte und sind eine Zutat des Projekts.
 *
 * DREI BLOECKE, ABER NUR DREI TRENNUNGEN — UND DIE PRUEFZEILE GEHOERT ZUM
 * AUTOR. Sie sagt, wann DERSELBE Mensch zuletzt nachgesehen hat; eine Linie
 * dazwischen erklaerte sie zu einer vierten Sache. Sie steht deshalb ohne
 * Oberlinie direkt unter der Autorenkarte, und getrennt wird nur dort, wo ein
 * neuer Gedanke anfaengt: vor dem Verzeichnis, vor dem Autor, vor den
 * Empfehlungen.
 *
 * DIE BLOCKTRENNUNG IST DIE KRAEFTIGE LINIE, NICHT DIE HAARLINIE. Dieselbe
 * Unterscheidung wie im Rest des Themes: `--g-rule-strong` trennt Bloecke
 * (Metabox, Abschnitte der Startseite), `--g-rule` trennt Zeilen INNERHALB
 * eines Blocks. Vorher trug jede Grenze dieselbe Haarlinie, und die Spalte
 * las sich als eine einzige lange Liste. Beide Nahtstellen tragen einen
 * `currentColor`-Rueckfall, damit die Spalte auch ohne Skin gegliedert ist.
 *
 * `:empty` IST HIER KEINE FEINHEIT, SONDERN DIE BEDINGUNG. Zwei der drei
 * Bloecke sind Anker-Gruppen des Toolkits: Ein Beitrag ohne Ueberschriften
 * bekommt kein Inhaltsverzeichnis, einer ohne Pruefdatum keine Pruefzeile.
 * Ohne die Regel bliebe an ihrer Stelle eine Linie ueber nichts stehen — also
 * genau die Sorte Fehler, die im Markup richtig aussieht.
 * ------------------------------------------------------------------------- */
.g-sidebar-sticky > * {
	margin-block-start: 0;
}

.g-toc:empty,
.g-reviewed-side:empty {
	display: none;
}

.g-side-author {
	border-block-start: var(--g-side-block-rule, 2px) solid var(--g-rule-strong, currentColor);
	padding-block-start: var(--g-side-pad, 14px);
}

/*
 * DAS VERZEICHNIS BEKOMMT SEINE TRENNUNG ERST AB DEM BREAKPOINT — und das ist
 * dieselbe Regel wie `:empty` daroeber, nur fuer den anderen Fall.
 *
 * `:empty` faengt den leeren Anker: kein Verzeichnis, keine Linie. Unterhalb
 * von 992 px ist der Anker aber GEFUELLT und trotzdem unsichtbar; die
 * Ausspielung darin steht auf `display: none` (`goblin-toolkit`, `toolkit.css`
 * — unter dem Breitenwechsel stapelt sich die Spalte hinter den Artikel, dort
 * leistet ein Verzeichnis nichts). Linie und Polster blieben als Rest stehen.
 *
 * Gemessen am 2026-09-03 an `/epomaker-th108-pro/` bei 375 px: `.g-toc` 24 px
 * hoch (2 px Linie plus 22 px Polster) bei y = 16371, also eine Haarlinie ueber
 * nichts am Ende einer 17 000 px hohen Seite. Im Markup war alles richtig.
 */
@media (min-width: 992px) {
	.g-toc:not(:empty) {
		border-block-start: var(--g-side-block-rule, 2px) solid var(--g-rule-strong, currentColor);
		padding-block-start: var(--g-side-pad, 14px);
	}
}

/*
 * Die Autorenkarte in der Spalte. Sie ist NICHT der Autorenkasten unter dem
 * Beitrag (`g-author-box`) in klein, und auch nicht die Redaktionskarte
 * (`g-author-card`, aus `Author_Profile::render_roster()`) — der Name war
 * zuerst dafuer vergeben, und ihre Token `--g-author-card-figure: 52px`
 * schlugen am 2026-09-03 lautlos auf diese Spalte durch. Sie ist ein eigenes,
 * viel schmaleres Bauteil: Initiale links, drei Zeilen rechts. Was beide teilen, ist die
 * Initiale — sie kommt aus demselben Anker `g-author-figure` wie auf der
 * Autorenseite, und `--g-author-figure-size` stellt sie hier auf das Mass der
 * Spalte. Eine zweite Quelle fuer „was steht im Kreis" gibt es nicht.
 */
.g-side-author {
	margin-block-start: var(--g-side-author-start, 16px);
	display: flex;
	gap: var(--g-side-author-gap, 11px);
	align-items: flex-start;
	--g-author-figure-size: var(--g-side-author-figure, 38px);
}

/*
 * Ohne `min-inline-size: 0` sprengt ein langer Name die 232 px schmale Spalte:
 * Ein Flex-Kind schrumpft nicht unter seine Inhaltsbreite, solange man es ihm
 * nicht erlaubt. Dieselbe Zeile wie in der Einzeilerliste, aus demselben Grund.
 */
/*
 * Die Initiale ist ein Flex-Kind mit `display: block` und ohne eigene Breite:
 * Ohne `flex: 0 0 auto` schrumpft sie, sobald der Text daneben mehr Platz
 * verlangt als die Spalte hat. Gemessen am 2026-09-03: Der Traeger war auf
 * **15px** eingelaufen, waehrend der 38px-Kreis darin unveraendert blieb — die
 * Initiale lag damit ueber der Beschriftung „Getestet von". Im Markup war
 * nichts davon zu sehen, und die Wache fuer die Kreisgroesse blieb gruen: Sie
 * misst den Kreis, nicht seinen Traeger.
 */
.g-side-author > .g-author-figure {
	flex: 0 0 auto;
}

/*
 * Beide Kinder sind Bloecke im Sinne des Editors und bekommen von Core den
 * Blockabstand als `margin-block-start`. An einem Flex-Kind wirkt der als
 * Versatz nach unten: Der Textblock stand 21px tiefer als die Initiale, statt
 * mit ihr auf einer Linie zu beginnen.
 */
.g-side-author > * {
	margin-block-start: 0;
}

.g-side-author__body {
	min-inline-size: 0;
}

.g-side-author__body > * {
	margin-block-start: 0;
}

/*
 * Die Pruefzeile schliesst den Autorenblock ab: kein Rahmen, nur Abstand.
 * Sie trug bis zum 2026-09-03 dieselbe Oberlinie wie die Bloecke daneben und
 * stand damit als eigener Block da, obwohl sie eine Angabe ueber den Autor
 * darueber ist.
 */
.g-reviewed-side:not(:empty) {
	margin-block-start: var(--g-reviewed-side-start, 10px);
	border-block-start: 0;
	padding-block-start: 0;
}

/*
 * Die Empfehlungen stehen im zweiten Part und damit AUSSERHALB des klebenden
 * Stapels — sie sollen mitlaufen und nicht mitkleben. Die Blocktrennung
 * bekommen sie trotzdem, und dieselbe wie die anderen: Fuer den Leser ist es
 * der dritte Block derselben Spalte, und ein Block ohne Linie saehe dort aus
 * wie ein Versehen.
 */
.g-recommend {
	border-block-start: var(--g-side-block-rule, 2px) solid var(--g-rule-strong, currentColor);
	padding-block-start: var(--g-side-pad, 14px);
}

.g-recommend > * {
	margin-block-start: 0;
}

/*
 * ---------------------------------------------------------------------------
 * Metabox (`g-post-facts`).
 * ---------------------------------------------------------------------------
 *
 * Keine Flaeche, 2px Linie oben, einzeilige Zeilen mit Haarlinie darunter,
 * Bezeichnung links, Wert rechts. Einzeilig ist Absicht: bei kurzem TL;DR
 * wuerde eine gestapelte Fassung die rechte Spalte ueberragen.
 *
 * Nur Struktur. Die Farben der beiden Linien und die Schriftgroessen der
 * Bezeichnungen kommen aus dem Skin; hier stehen sie als `currentColor`
 * hinter zwei benannten Nahtstellen, damit die Box auch ohne Skin sichtbar
 * ist und nicht als unsichtbares Bauteil durchrutscht.
 */
.g-post-facts {
	border-block-start: 2px solid var(--g-rule-strong, currentColor);
}

/*
 * DIE ZEILEN STEHEN OHNE ABSTAND UEBEREINANDER, und das ist der Punkt der
 * Liste: Die Haarlinie unter jeder Zeile ist zugleich die Oberkante der
 * naechsten. Core gibt jedem Kind einer Gruppe seinen Blockabstand als
 * `margin-block-start` — gemessen am 2026-09-03 waren das 21px, aus 44px
 * Zeilenhoehe wurde ein Raster von 65px, und die ERSTE Zeile hatte als
 * einzige keinen davor. Genau so sah sie aus: unten luftig, oben an die
 * 2px-Linie geklebt. Der Abstand gehoert ins Polster der Zeile, damit er an
 * jeder Zeile gleich ist, auch an der ersten.
 */
.g-post-facts > * {
	margin-block-start: 0;
}

.g-post-facts__row {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;

	/* Polster 10/0 laut Entwurf; es traegt, sobald eine Zeile umbricht. */
	padding-block: var(--g-post-facts-pad, 10px);

	/* Tap-Ziel und Zeilenmass: mindestens 44px. */
	min-block-size: 44px;
	border-block-end: 1px solid var(--g-rule, currentColor);
}

/*
 * Zwei der Zeilen sind Anker des Toolkits und bleiben leer, wenn das Feature
 * nichts liefert (kein Pruefdatum, keine Lesezeit). Eine leere Zeile mit
 * 44px Hoehe und Haarlinie waere eine sichtbare Luecke, deshalb faellt sie
 * ganz aus dem Fluss. Die Anker-Gruppen rendern exakt `<div ...></div>`,
 * `:empty` greift also.
 */
.g-post-facts__row:empty {
	display: none;
}

/*
 * `Reviewed` liefert Bezeichnung und Datum in einem eigenen Absatz. Der wird
 * selbst zur Zeile, damit „Geprueft" links und das Datum rechts steht — die
 * Bezeichnung kann nicht im Template stehen, sonst waere sie auch ohne Datum
 * da.
 */
.g-post-facts__row > .g-reviewed__line,
.g-post-facts__row > .g-test-duration__line {
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin: 0;
}

.g-post-facts__label,
.g-test-duration__label,
.g-reading-time__label {
	margin: 0;
	flex: 0 0 auto;
}

.g-post-facts__value,
.g-test-duration__value {
	margin: 0;
	flex: 0 1 auto;
	text-align: right;
}

/*
 * Die Lesezeit steht seit dem 2026-09-03 als Bezeichnung UND Wert da, nicht
 * mehr als ein Satz. Der Anker ist die Zeile selbst, beide Teile sind ihre
 * direkten Kinder — die Zeile legt sie an ihre Raender, hier steht nur, dass
 * der Wert nicht schrumpft.
 */
.g-reading-time__value {
	flex: 0 1 auto;
	text-align: right;
}

/* „Von": Initialen-Avatar 22px plus Name. */
.g-post-facts__author {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.g-post-facts__author .wp-block-avatar img {
	display: block;
	inline-size: 22px;
	block-size: 22px;
}

/*
 * Drei ineinanderliegende Container, weil eine Container Query immer den
 * nächsten *Vorfahren*-Container auswertet — ein Element kann sich nie über
 * seinen eigenen Container stylen:
 *
 *   grid     = das Raster selbst  -> entscheidet über die Spaltenspanne
 *   cardslot = das Grid-Item (das <li class="wp-block-post"> von
 *              core/post-template) -> entscheidet über das Karteninnenlayout
 *   card     = die Karte          -> entscheidet über ihre eigenen Nachfahren
 */
.g-post-grid {
	container-type: inline-size;
	container-name: grid;
}

/*
 * Beitragsraster — der Entwurf gibt genau zwei Zustaende vor: eine Spalte,
 * und ab 992 px drei GLEICHE Spalten mit 14 px Abstand.
 *
 * WARUM DIE MEDIA QUERY UND NICHT EINE SCHWELLE IN REM
 *
 * Hier stand zuerst `@container grid (min-width: 60rem)`, gerechnet aus
 * „75 rem Inhalt minus 16 px Rand". Der Wert war falsch, und zwar auf eine
 * Weise, die nur in DIESEM Projekt nicht auffiel: Das Wurzelpolster des
 * Parents ist `--wp--preset--spacing--sm` und damit **21 px**, nicht 16. Der
 * Container misst bei 992 px Viewport also 950 px = 59,375 rem, und der
 * Dreispalter kippte erst rund 10 px SPAETER als die drei
 * `@media (min-width: 992px)`-Bloecke derselben Datei. Dass es hier passte,
 * lag allein daran, dass das Child sein Polster auf 16 px setzt — die geerbte
 * Schicht haette an einem Markenwert gehangen.
 *
 * Jetzt steht der Umschaltpunkt dort, wo der Entwurf ihn nennt, und die
 * Seitenleiste wird eine Zeile weiter unten wieder auf eine Spalte gezogen.
 * Zwei Regeln statt einer gerechneten, aber keine davon kann verrutschen.
 *
 * `minmax(0, 1fr)` und nicht `1fr`: Ein langer Produktname ohne Trennstelle
 * setzt sonst die Spaltenbreite und sprengt das Raster.
 *
 * Der Abstand kommt aus einer Custom Property, damit der Wert 14 px in der
 * MARKENSCHICHT stehen kann. Dieses Repo kennt keine Entwurfsmasse; der
 * Rueckfall ist die Abstandsstufe des Systems.
 */
.g-post-grid__items {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-post-grid-gap, var(--wp--preset--spacing--sm));
}

@media (min-width: 992px) {
	.g-post-grid__items {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* Dasselbe Raster traegt die Seitenleiste (`patterns/empfehlungs-widget.php`).
   Dort gibt es keine drei Spalten — 14,5 rem geben das nicht her. Die
   Container Query greift nur, wo ein Vorfahre `container-name: sidebar`
   traegt; ausserhalb der Leiste feuert sie nie. Sie steht NACH der Media
   Query, damit sie sie schlaegt: gleiche Spezifitaet, Quellreihenfolge
   entscheidet. */
@container sidebar (max-width: 22rem) {
	.g-post-grid__items {
		grid-template-columns: 1fr;
	}
}

/*
 * Das Grid-Item war bis zum 2026-09-02 ein Container (`container-name:
 * cardslot`). Die einzige Abfrage darauf ist mit dem 1:1-Abgleich entfallen,
 * und ein Container ohne Abfrage ist nicht neutral: `container-type:
 * inline-size` erzwingt `contain: layout style inline-size` auf JEDEM
 * Grid-Item, macht es zum Containing Block und unterdrueckt
 * Margin-Collapsing. Nebenwirkungen ohne Nutzen.
 *
 * `container-name: card` an der Karte bleibt — dort haengt kein `@container`
 * dran, aber die `cqi`-Einheit der Rubrikkennzeichnung im Child. Wer beide
 * fuer gleich haelt und mit aufraeumt, bricht die Schriftgroesse der
 * bildlosen Karte.
 */
.g-post-grid__items > * {
	/* Cores Flow-Layout haengt jedem nicht-ersten <li> den blockGap als
	   margin-block-start an. Im Raster versetzt das die Karten derselben
	   Zeile gegeneinander — den Abstand traegt hier allein `gap`. */
	margin-block-start: 0;
}

/* Die Karte trägt selbst einen Container, damit ihr Innenleben auf die
   eigene Breite reagiert und nicht auf die des Fensters. */
/*
 * Die Karte ist EINE Spalte mit EINEM Abstand — der Entwurf schreibt
 * `display: flex; flex-direction: column; gap: 10px`.
 *
 * NUR: FLEX IST HIER GENAU DIE FALSCHE UEBERSETZUNG, und das ist gemessen.
 * Beide Gruppen sind `is-layout-constrained`, und Core haengt jedem Kind
 * darin nicht nur `margin-block-start` an, sondern auch
 * `margin-left: auto; margin-right: auto` (mit `!important`). Im Flussl
 * ayout ist das harmlos — der Block ist ohnehin breiter als sein Inhalt. In
 * einem Flex-Container ZENTRIEREN Auto-Margins und schrumpfen das Element
 * auf seinen Inhalt: Gemessen stand der Titel danach 105 px vom linken Rand
 * und war 181 px breit statt 367.
 *
 * Der Abstand kommt deshalb ueber `* + *` und ueberschreibt Cores Wert an
 * derselben Eigenschaft, statt eine zweite daneben zu setzen. Cores Selektor
 * ist `:root :where(.is-layout-constrained) > *` und liegt durch `:where()`
 * bei 0,0,1 — eine Klasse genuegt dagegen.
 *
 * Die Lehre gehoert zu den Messfallen: Ein `gap` aus dem Entwurf ist eine
 * Aussage ueber ABSTAENDE, nicht die Anweisung, ein Flex-Layout zu bauen.
 */
.g-post-card {
	container-type: inline-size;
	container-name: card;
	height: 100%;

	/* Traeger fuer die Trefferflaeche der ganzen Karte, siehe unten. */
	position: relative;
}

.g-post-card > * + *,
.g-post-card__body > * + * {
	margin-block-start: var(--g-post-card-gap, var(--wp--preset--spacing--2xs));
}

/*
 * DER TEXTBLOCK DARF NICHT POSITIONIERT SEIN.
 *
 * Gemessen am 2026-09-02: `.g-post-card__body` kam als `position: relative`
 * heraus, obwohl **kein** Stylesheet der Seite eine Regel dafuer traegt — 46
 * Blaetter abgesucht, alle lesbar, null Treffer. Woher der Wert kommt, ist
 * offen; wirksam war er trotzdem, und die Folge war praezise: Die
 * Trefferflaeche unten bezog ihr `inset: 0` auf den TEXTBLOCK statt auf die
 * Karte. Klickbar war damit der Text, nicht die Karte — also genau das, was
 * die Flaeche beheben sollte.
 *
 * Diese Zeile macht den Bezugsrahmen eindeutig, statt ihn zu erben. Sie ist
 * kein Flicken auf einen unbekannten Wert, sondern die Aussage: Der einzige
 * positionierte Vorfahre innerhalb der Karte ist die Karte.
 */
.g-post-card__body {
	position: static;
}

/*
 * DIE GANZE KARTE IST DIE TREFFERFLAECHE.
 *
 * Im Entwurf ist die Karte ein einziges `<a>`; mit Core-Bloecken geht das
 * nicht — Bild, Kicker und Titel bringen je einen eigenen Link mit. Gemessen
 * war die Folge: Nur Bild und Titel waren klickbar, die 12 px Polster und die
 * Metazeile waren toter Raum, und wer daneben tippte, traf nichts.
 *
 * Der Titel-Link spannt deshalb eine unsichtbare Flaeche ueber die Karte.
 * Der Link des Beitragsbildes liegt darunter und fuehrt ohnehin zum selben
 * Ziel; er ist zusaetzlich aus der Tabreihenfolge genommen
 * (`inc/post-image-link-a11y.php`), damit die Tastatur die Karte einmal und
 * nicht dreimal besucht.
 *
 * Preis dieser Loesung: Text in der Karte laesst sich nicht markieren. Im
 * Entwurf, wo die Karte ein Link ist, gilt dasselbe.
 */
.g-post-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

/*
 * Kompakte Karte in der Seitenleiste: Meta-Angaben und Auszug treten zurück.
 *
 * Abgefragt wird die Breite des Seitenleisten-Containers, nicht die der Karte.
 * Das ist eine Korrektur: Über die Kartenbreite sind die beiden Fälle
 * nachweislich nicht zu trennen. Gemessen wurde
 *
 *   Seitenleiste, Karte                       20,00 rem
 *   Archivkarte, 390 px Viewport, einspaltig  20,81 rem
 *   Archivkarte, 360 px Viewport, einspaltig  18,94 rem
 *   Archivkarte, 1000 px Viewport, dreispaltig 18,77 rem
 *
 * — die Archivkarte unterschreitet die Seitenleistenbreite sowohl schmal als
 * auch breit. Sie muss laut Template-Matrix in Archiv und Suche „von Vik ·
 * Datum" und den dreizeiligen Auszug tragen. Jede Schwelle auf der
 * Kartenbreite träfe deshalb zwangsläufig auch Archivkarten. Der
 * Seitenleisten-Container trennt sauber: Karten außerhalb der Seitenleiste
 * haben keinen Vorfahren-Container dieses Namens, die Regel greift dort nie.
 *
 * Die 22 rem bleiben als Wert stehen: Sie liegen über der Seitenleistenbreite
 * von 20 rem, sodass ein späteres Padding oder eine geringfügig breitere
 * Leiste im Child-Theme die Regel nicht kippt.
 */
@container sidebar (max-width: 22rem) {
	/* Der Nachfahren-Selektor ist Absicht: Core setzt das Flex-Layout von
	   `__meta` über die globale Regel `body .is-layout-flex { display: flex }`.
	   Die hat durch den Typselektor `body` die Spezifität 0,1,1 und schlägt
	   einen einklassigen Selektor (0,1,0) unabhängig von der
	   Dokumentreihenfolge. 0,2,0 gewinnt. */
	/* `__excerpt` stand hier bis zum 2026-09-02 mit. Die Karte traegt seit
	   dem 1:1-Abgleich keinen Auszug mehr — weder `bauteile.md` noch der
	   Entwurf zeigen einen. Ein Selektor auf ein Element, das es nicht mehr
	   gibt, sieht wie eine Regel aus und ist keine. */
	.g-post-card .g-post-card__meta {
		display: none;
	}
}

/*
 * HIER STANDEN ZWEI REGELN, DIE DER ENTWURF NICHT KENNT. Entfernt am
 * 2026-09-02 beim 1:1-Abgleich gegen `Uebersichten.dc.html`. Sie stehen als
 * Kommentar da, weil sie plausibel aussahen und sonst wiederkommen.
 *
 * 1 · `.g-post-grid__items > :first-child { grid-column: span 2 }`
 *     Eine hervorgehobene erste Karte. Der Entwurf zeigt sie an keiner der
 *     drei Uebersichten; er zeigt drei gleiche Spalten. Und die Projektregel
 *     sagt: ein Karten-Bauteil, ueberall gleich. Eine Karte, die anders
 *     aussieht, weil sie zufaellig zuerst kommt, ist genau die Sonderregel,
 *     die die Regel verbietet.
 *
 * 2 · `@container cardslot (min-width: 34rem)` — Bild und Text nebeneinander.
 *     Gerechnet, nicht geraten: Im Dreispalter misst ein Grid-Item rund
 *     23 rem, einspaltig auf dem Telefon rund 24 rem. Beide bleiben unter
 *     34 rem, die Regel feuerte dort also nie. Gefeuert hat sie zwischen etwa
 *     700 und 991 px Viewport — einspaltig, Item rund 43 rem. Genau dort
 *     zeigte die Karte eine Form, die im Entwurf nicht vorkommt: ein dritter
 *     Zustand zwischen den zwei vorgesehenen.
 */

/* Bildlose Karte: die redaktionelle Kennzeichnung statt des Bildes
   (`inc/post-card-fallback.php`). Sie steht in derselben Stelle und haelt
   deshalb dasselbe Seitenverhaeltnis — sonst springt das Raster, je nachdem
   welche Beitraege gerade ein Bild haben.

   Hier steht nur, was ohne Regel kaputt waere: die Stelle, ihre Proportion
   und die Zentrierung. Farbe, Rahmen und Typo gehoeren ins Child — dieses
   Repo kennt keine Farben.

   `overflow-wrap` ist kein Zierat: Rubriknamen wie „Gaming Zubehoer" stehen
   hier gross und gesperrt, und eine Rubrik mit einem langen Wort schiebt die
   Karte sonst auf. */
.g-post-card__mark {
	display: grid;
	place-items: center;

	/* `width: 100%` ist nicht ueberfluessig, sondern die ganze Regel.
	   Gemessen war die Kennzeichnung **41,7 px breit** statt spaltenbreit:
	   `aspect-ratio` loest die unbestimmte Achse aus der bestimmten auf, und
	   in der breiten Karte machte `align-items: center` die Hoehe bestimmt —
	   also wurde aus 30 px Textzeile eine Breite von 53 px statt aus der
	   Spaltenbreite eine Hoehe. Mit fester Breite laeuft es in die richtige
	   Richtung. */
	width: 100%;
	aspect-ratio: 16 / 9;
	overflow-wrap: anywhere;
	text-align: center;
}

/*
 * Header.
 *
 * `min-height` bindet die Kopfleiste an `token-nav-hoehe`. Der Wert ist kein
 * reiner Gestaltungswert: An ihm hängen der Versatz des Fortschrittsbalkens
 * und der der klebenden Seitenleiste. Weil die tatsächliche Inhaltshöhe der
 * Leiste je Breite leicht schwankt (76,88 / 78,22 / 79,34 px bei 390 / 834 /
 * 1440), liegt der Token bewusst knapp darüber — so ist die Leiste auf jeder
 * Breite exakt so hoch wie der Token behauptet.
 */
/*
 * Die schwebende Pille.
 *
 * Der Entwurf (`design/entwurf/bauteile.md`, Abschnitt Kopfleiste) verlangt
 * keine durchgehende Leiste, sondern eine Pille: `fixed`, 12 px vom oberen
 * Rand, 16 px zu den Seiten, hoechstens 75 rem breit, zentriert.
 *
 * WAS DAMIT ZUSAMMENHAENGT, und darum ist es keine kleine Regel: Eine
 * `fixed` Leiste nimmt keinen Platz mehr ein. Der Versatz aller nachfolgenden
 * Inhalte muss deshalb ausdruecklich entstehen — hier ueber
 * `--g-header-offset` an `.wp-site-blocks`.
 *
 * DIE ZAHLEN DES ENTWURFS GEHEN AUF, und das ist keine Zufall:
 *
 *   mobil    12 px oben + 60 px Pille + 20 px Luft =  92 px
 *   ab 992   12 px oben + 72 px Pille + 20 px Luft = 104 px
 *
 * 104 px ist genau der Wert, den der Entwurf fuer `scroll-margin-top` und
 * fuer das mitlaufende Inhaltsverzeichnis nennt. 92 px ist genau die Hoehe,
 * ab der laut Entwurf die mobile Inhaltsleiste erscheint. Ein Versatz, der
 * aus einer anderen Rechnung kaeme, wuerde an drei Stellen gleichzeitig
 * auseinanderlaufen.
 *
 * ABLOESUNG VON `nav-height`: Der alte Token (80 px) beschrieb eine Leiste im
 * Fluss, deren tatsaechliche Hoehe je Breite schwankte; 80 px lag bewusst
 * knapp darueber. Die Pille hat dagegen eine **gesetzte** Hoehe, und zwar
 * zwei verschiedene. Ein einzelner Token kann das nicht tragen. `nav-height`
 * bleibt definiert, damit nichts still bricht, wird hier aber nicht mehr
 * benutzt.
 */
.g-header {
	--g-header-top: 12px;
	--g-header-height: 60px;

	position: fixed;
	inset-block-start: var(--g-header-top);
	inset-inline: var(--wp--style--root--padding-left, 16px);
	max-inline-size: var(--wp--style--global--wide-size);
	margin-inline: auto;

	/*
	 * Ueber dem Inhalt, aber unter allem, was eine Einwilligung einholt. Der
	 * Consent-Dialog liegt bei Real Cookie Banner deutlich hoeher; wer hier
	 * eine grosse Zahl einsetzt, verdeckt ihn.
	 */
	z-index: 20;
}

/*
 * Die Bildmarke wird an ihre HOEHE gebunden, nicht an ihre Breite.
 *
 * GEMESSEN: `wp:site-logo {"width":38}` hat auf dieses Logo keine Wirkung —
 * die Datei ist ein SVG **ohne Pixelmasse** (`width="99.31868mm"`), und Core
 * druckt dafuer keine `width`/`height`-Attribute am `<img>`. Ergebnis war ein
 * Logo von 375 x 264 px und eine Pille von 264 px Hoehe, hinter der der
 * Beitragstitel verschwand.
 *
 * Die Hoehe ist hier die richtige Achse: Der Entwurf nennt „Bildmarke, 38 px
 * hoch". Eine Breitenangabe waere bei einem querformatigen Zeichen die falsche
 * Grenze.
 */
.g-header .wp-block-site-logo,
.g-header .wp-block-site-logo img {
	block-size: 38px;
	inline-size: auto;
	max-inline-size: none;
}

/*
 * DER GESCROLLTE ZUSTAND.
 *
 * Die Pille schrumpft ab 24 px Scrolltiefe und bekommt dort den **einzigen**
 * Schatten des Systems. Ausgeloest wird das nicht hier, sondern vom Feature
 * `Scroll_State` im Toolkit, das `data-g-scrolled` an das `<html>`-Element
 * setzt — beobachtet, nicht bei jedem Scrollbild gerechnet.
 *
 * **Warum die Auswahl `html[data-g-scrolled] .g-header` und nicht `.g-header`
 * mit einer Media-Query:** `--g-header-height` steht an `.g-header` (0,1,0)
 * und wird ab 992 px an derselben Auswahl ueberschrieben. Eine Media-Query
 * erhoeht die Spezifitaet **nicht** — die gescrollte Fassung braucht deshalb
 * eine hoehere Auswahl (0,1,1), und der Desktopwert eine zweite Regel mit
 * derselben Auswahl **nach** dieser. Genau diese Reihenfolge ist in diesem
 * Projekt schon einmal falsch gewesen.
 *
 * Ohne JavaScript bleibt die Ruhehoehe. Das ist ein gueltiger Zustand.
 */
html[data-g-scrolled] .g-header {
	--g-header-height: 52px;
}

.g-header__pill {
	/*
	 * BEZUGSRAHMEN FUER DAS SUCHFELD, und das ist kein Beiwerk.
	 *
	 * Mobil soll das Feld die Breite der Pille haben. Solange sein
	 * Bezugsrahmen das 46 px breite Bedienelement war, rechnete der Browser
	 * seine linke Kante aus `right: 0` minus Mindestbreite — GEMESSEN am
	 * 2026-09-04 bei 375 px: `left: -289.8px`, Feldanfang bei x −63, also
	 * 63 px links ausserhalb des Bildschirms, Ende bei 273 statt 359.
	 *
	 * Mit dieser Zeile misst `inset-inline: 0` gegen die Pille, und das ist
	 * genau der Traeger, unter dem das Feld haengen soll.
	 */
	position: relative;

	min-block-size: var(--g-header-height);
	transition: min-block-size var(--wp--custom--motion--normal, 200ms) var(--wp--custom--motion--kurve, ease),
		box-shadow var(--wp--custom--motion--normal, 200ms) var(--wp--custom--motion--kurve, ease);
	border-radius: var(--wp--custom--radius--card, 16px);

	/*
	 * Der dunkle Grund ist eine Rolle, kein Farbwert: Wie `contrast` aussieht,
	 * entscheidet das Child. Ohne Grund waere die Pille durchsichtig und der
	 * Inhalt darunter laese durch.
	 */
	background-color: var(--wp--preset--color--contrast);
	padding-inline: var(--wp--preset--spacing--sm);

	/*
	 * DIE TEXTFARBE IST HIER KEINE GESTALTUNG, SONDERN DIE BEDINGUNG.
	 *
	 * Gemessen ohne diese Zeile: Wortmarke, Rubriken und Bedienelemente hatten
	 * `rgb(29,30,26)` auf `rgb(29,30,26)` — Kontrast **1,0:1**, alles
	 * unsichtbar. Die Elemente waren da und richtig gross (Pille 72 px,
	 * Wortmarke 111 x 28, Rubrikzeile 359 x 31); nur sehen konnte man nichts.
	 *
	 * Ein dunkler Grund verlangt die inverse Textrolle. Welche Farbe `surface`
	 * traegt, entscheidet weiterhin das Child — hier steht nur, dass es die
	 * inverse ist.
	 */
	color: var(--wp--preset--color--surface);
}

/*
 * Links in der Pille erben ihre Farbe. Ohne diese Regel gewinnt die
 * Linkfarbe aus der `theme.json` (Markenfarbe auf hellem Grund gedacht) und
 * die Rubriken stehen wieder fast unlesbar auf dem dunklen Grund.
 *
 * Spezifitaet: Cores Elementregel ist `.wp-site-blocks a:where(...)`, also
 * 0,1,0. Diese hier ist 0,1,1 und gewinnt damit ohne `!important`.
 */
.g-header__pill a {
	color: inherit;
}

/*
 * Die Wortmarke darf nie umbrechen — auch nicht, bevor Bricolage geladen ist.
 * Ohne diese Zeile bricht „HARDWARE" in der Ersatzschrift um und die Pille
 * springt beim Nachladen in der Hoehe.
 */
.g-header__wordmark {
	white-space: nowrap;
	margin: 0;
}

/*
 * Mobil traegt die Pille nur die Bildmarke. Die Wortmarke kommt ab dem
 * Breakpoint dazu — so steht es im Entwurf, und so bleibt links Platz fuer
 * die zwei Bedienelemente rechts.
 */
.g-header__brand .g-header__wordmark {
	display: none;
}

/*
 * Die Panels: Suche und Menue.
 *
 * OHNE JAVASCRIPT BEDIENBAR, und das ist der Grund fuer `<details>`. Der
 * Entwurf beschreibt Kopfleiste und Panels als einen `fixed`-Container in
 * einer Flex-Spalte. Diese Fassung setzt die Panels stattdessen absolut unter
 * die Pille — sichtbar dasselbe, aber der Umschalter kann im `<summary>`
 * stehen und braucht kein Skript. Ein Menue, das ohne JavaScript nicht
 * aufgeht, ist auf einer Inhaltsseite kein Menue.
 */
.g-header__panel {
	position: relative;
}

.g-header__panel > summary {
	cursor: pointer;
	list-style: none;

	/* Tap-Ziel, die Pruefliste des Entwurfs verlangt mindestens 44 px. */
	min-block-size: 44px;
	min-inline-size: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
}

.g-header__panel > summary::-webkit-details-marker {
	display: none;
}

/*
 * Das aufgeklappte Panel haengt an der Pille, nicht am Bildschirm: Es sitzt
 * unter ihr und folgt ihr damit von selbst, wenn sie beim Scrollen schrumpft.
 */
.g-header__panel[open] > :not(summary) {
	position: absolute;
	inset-block-start: calc(100% + 8px);
	inset-inline-end: 0;
	min-inline-size: min(20rem, 80vw);
	border-radius: var(--wp--custom--radius--card, 16px);
	background-color: var(--wp--preset--color--surface);
	padding: var(--wp--preset--spacing--sm);
	box-shadow: var(--wp--custom--shadow);

	/*
	 * DIE TEXTFARBE MUSS ZURUECKGENOMMEN WERDEN, und zwar aus demselben Grund,
	 * aus dem die Pille sie ueberhaupt setzt.
	 *
	 * Gemessen ohne diese Zeile: Das aufgeklappte Menue zeigte einen hellen
	 * Kasten mit vier Links darin — und alle vier waren unsichtbar, weil sie
	 * die helle Schriftfarbe der Pille geerbt haben. Derselbe Fehler wie oben,
	 * eine Ebene tiefer: Wer eine Flaeche umdreht, muss die Schrift mitdrehen.
	 */
	color: var(--wp--preset--color--contrast);
}

/*
 * Und die Links im Panel nehmen dessen Farbe, nicht die der Pille. Ohne diese
 * Regel gewinnt `.g-header__pill a` weiter oben — es ist dieselbe Spezifitaet,
 * steht aber vorher.
 */
.g-header__panel[open] a {
	color: inherit;
}

/*
 * ---------------------------------------------------------------------------
 * DAS SUCHFELD AUF DEM TELEFON
 * ---------------------------------------------------------------------------
 *
 * Es nimmt die volle Breite der Pille, also den Seitenrand der Seite und
 * keinen eigenen. Der Entwurf laesst es die Inhaltsleiste ueberlagern; das
 * darf es, angeschnitten sein darf es nicht.
 *
 * `position: static` am Bedienelement ist die tragende Zeile: Erst damit ist
 * der Bezugsrahmen die Pille (siehe dort) und nicht das 46 px breite
 * `<details>`. `inset-block-start: calc(100% + 8px)` misst dann die Hoehe der
 * Pille — das Feld folgt ihr also weiterhin, wenn sie beim Scrollen
 * schrumpft.
 *
 * Mobile-first: Ab dem Breakpoint steht die Rueckstellung auf das schmale
 * Aufklappfeld unter dem Bedienelement, wie bisher.
 */
.g-header__panel--suche {
	position: static;
}

.g-header__panel--suche[open] > :not(summary) {
	inset-block-start: calc(100% + 8px);
	inset-inline: 0;
	min-inline-size: 0;
}

/*
 * ---------------------------------------------------------------------------
 * DER OFFENE ZUSTAND, SICHTBAR OHNE FARBE
 * ---------------------------------------------------------------------------
 *
 * Weisung des Auftraggebers vom 2026-09-04: „solange suche offen ist soll auch
 * der menü punkt active sein … und wenn active also offen dann auch als solche
 * ui technisch markieren".
 *
 * ZWEI DINGE, UND SIE SIND VERSCHIEDEN. Technisch markiert wird ueber
 * `aria-expanded` am `<summary>` — das setzt `inc/header-panels.php` beim
 * Rendern und das Feature `Disclosure_State` des Toolkits beim Umschalten.
 * Hier steht nur, was man SIEHT.
 *
 * UND ES IST BEWUSST KEINE FARBE. Der Ring ist eine Form; er erscheint auch
 * dort, wo Farben nicht ankommen (Kontrastmodus, monochrome Ausgabe). Eine
 * eingefaerbte Flaeche allein waere „Kontext ueber Farbe", und die Marke
 * schliesst das aus.
 *
 * DER MENUEKNOPF GILT MIT, SOLANGE DIE SUCHE OFFEN IST. Das Geschwisterpaar
 * steht so in `parts/header.html`: erst die Suche, dann das Menue. Wer die
 * beiden tauscht, dreht diesen Selektor mit.
 */
.g-header__panel[open] > summary,
.g-header__panel--suche[open] ~ .g-header__panel--menue > summary {
	outline: var(--g-header-toggle-ring, 2px) solid currentColor;
	outline-offset: var(--g-header-toggle-ring-offset, 2px);
	border-radius: var(--wp--custom--radius--pill, 999px);
}

/*
 * Mobil das Menue als Panel, ab dem Breakpoint die Rubriken in der Zeile.
 * Mobile-first: die Zeile ist ausgeblendet, bis Platz da ist.
 */
.g-header__menu {
	display: none;
}

/*
 * Die Desktop-Fassung der Kopfleiste steht ABSICHTLICH hier und nicht in der
 * Breitenabfrage weiter oben.
 *
 * Gemessen, als sie oben stand: Bei 1400 px war die Wortmarke `display: none`.
 * Die Mobil-Regeln des Headers stehen in dieser Datei weiter unten als jene
 * Abfrage, und bei **gleicher Spezifitaet** gewinnt die spaetere Regel — eine
 * Breitenabfrage erhoeht die Spezifitaet nicht. Nebeneinander gelesen ist das
 * Paar ausserdem verstaendlich; hundert Zeilen auseinander ist es eine Falle.
 *
 * Der Breakpoint-WERT bleibt der eine erlaubte (992 px). Die Konvention
 * verlangt einen Wert, nicht einen einzigen Block — es gibt schon zwei.
 */
@media (min-width: 992px) {
	:root {
		--g-header-offset: 104px;
	}

	.g-header {
		--g-header-height: 72px;
	}

	/*
	 * Der gescrollte Wert fuer Desktop. Er MUSS hier stehen und nicht oben:
	 * Dieselbe Auswahl wie die mobile Fassung (0,1,1), also entscheidet die
	 * Reihenfolge — und diese Regel kommt spaeter.
	 */
	html[data-g-scrolled] .g-header {
		--g-header-height: 60px;
	}

	/*
	 * Ab hier traegt die Pille auch die Wortmarke.
	 *
	 * `flex`, NICHT `block`: Diese Auswahl (0,2,0) gewinnt gegen `.g-wordmark`
	 * (0,1,0), und mit `block` faende das zweizeilige Wortbild seine Spalte
	 * nicht — die zwei Zeilen stuenden nebeneinander. Die Richtung kommt
	 * weiterhin aus `.g-wordmark`.
	 */
	.g-header__brand .g-header__wordmark {
		display: flex;
	}

	/* Und die Rubriken stehen in der Zeile statt im Panel. */
	.g-header__menu {
		display: flex;
	}

	.g-header__panel--menue {
		display: none;
	}

	/*
	 * Und das Suchfeld ist ab hier wieder ein schmales Aufklappfeld unter
	 * seinem Bedienelement. Die volle Breite oben gilt dem Telefon; auf 1280 px
	 * waere ein 1200 px breites Suchfeld kein Feld, sondern ein Balken.
	 */
	.g-header__panel--suche {
		position: relative;
	}

	.g-header__panel--suche[open] > :not(summary) {
		inset-inline: auto 0;
		min-inline-size: min(20rem, 80vw);
	}
}

/*
 * Klebende Navigation (`nav-sticky`).
 *
 * Dieselbe Falle wie bei der Seitenleiste: Der umschließende Block der
 * Header-Gruppe ist ihr eigener Part-Wrapper und exakt so hoch wie sie. Das
 * Kleben gehört deshalb an den Wrapper, dessen umschließender Block das
 * Seitenwurzel-Element ist. `:has()` trifft den Wrapper von `header` wie von
 * `header-minimal` — beide tragen `.g-header`.
 *
 * Das z-index liegt über dem der klebenden Seitenleiste, damit beide
 * gleichzeitig kleben können, ohne sich zu überdecken.
 */
.wp-block-template-part:has(> .g-header) {
	position: sticky;
	top: 0;
	z-index: 20;
}

/*
 * Der Schatten der Kopfleiste.
 *
 * `bauteile.md`: genau ein Schatten im ganzen System, und er erscheint erst ab
 * 24 px Scrolltiefe. Im Ruhezustand traegt die Pille keinen — sie liegt dann
 * auf dem Seitengrund und braucht keine Abhebung.
 */
html[data-g-scrolled] .g-header__pill {
	box-shadow: var(--wp--custom--shadow);
}

/*
 * ---------------------------------------------------------------------------
 * Die Marke am Dokumentanfang (`#g-top`).
 * ---------------------------------------------------------------------------
 *
 * Sie ist Messpunkt und Sprungziel in einem. Kommt aus dem Toolkit.
 *
 * **Kein `display: none`.** Ein ausgeblendetes Element wird vom
 * `IntersectionObserver` als „nie sichtbar" gemeldet, und damit waere die
 * Messung dauerhaft falsch statt fehlerhaft — der schlimmere Fall.
 *
 * 1 px hoch bei `top: 0`: Sie verlaengert das Dokument nicht.
 */
.g-scroll-marker {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	inline-size: 1px;
	block-size: 1px;
	pointer-events: none;
}

/*
 * ---------------------------------------------------------------------------
 * Der Aufmacher der Startseite (`g-hero`).
 * ---------------------------------------------------------------------------
 *
 * Der Aufmacher steht im breiten Traeger, damit seine Ueberschrift an
 * derselben Kante beginnt wie Kopfleiste und Kartenraster. Die ZEILENLAENGE
 * kommt dann nicht mehr vom Traeger und muss am Text stehen — sonst laeuft die
 * Ueberschrift ueber 75 rem, und das liest niemand.
 *
 * Die Masse gehen ueber Token: Der Wert gehoert dem Entwurf, die Regel hierher.
 */
.g-hero__title {
	max-inline-size: var(--g-hero-title-width, 22ch);
}

.g-hero__lead {
	max-inline-size: var(--g-hero-lead-width, 56ch);
}

/*
 * Dasselbe fuer das Intro einer Rubrikvorschau: Es steht seit dem 2026-09-02
 * im breiten Traeger und braucht seine Zeilenlaenge deshalb selbst.
 */
.g-topic__intro {
	max-inline-size: var(--g-topic-intro-width, 58ch);
}

/*
 * ---------------------------------------------------------------------------
 * Lesefortschritt (`g-progress`).
 * ---------------------------------------------------------------------------
 *
 * **Hier stehen die zwei Farben, und deshalb war der Balken durchsichtig.**
 * Lage, Hoehe und `scaleX` bringt das Toolkit mit; eine Farbe setzt dort kein
 * Feature (Global Constraint), und `goblin-base` hatte sie nie nachgereicht.
 * Ergebnis: ein Bauteil, dessen Mechanik lief und das nichts malte — am
 * Markup nicht zu sehen. Gemessen am 2026-09-02, beide Flaechen
 * `rgba(0, 0, 0, 0)`.
 *
 * Rollen statt Werten: Die Schiene ist eine leise Linie auf dem Seitengrund,
 * der Balken die Antwortfarbe. Ein Projekt, das das anders will, setzt es im
 * Skin.
 */
.g-progress {
	background-color: color-mix(in srgb, var(--wp--preset--color--contrast) 12%, transparent);
}

.g-progress__bar {
	background-color: var(--wp--preset--color--accent);
}

/*
 * ---------------------------------------------------------------------------
 * Sprung nach oben (`g-to-top`).
 * ---------------------------------------------------------------------------
 *
 * Erscheint ab 700 px Scrolltiefe, unten rechts. Struktur hier, Marke im Child.
 *
 * **`display: none` ist Absicht und nicht bloss Optik:** Es nimmt den Link
 * zugleich aus der Tabulatorfolge. Ein unsichtbarer, aber fokussierbarer Link
 * ist eine Falle fuer Tastaturbedienung — der Fokus verschwindet dann an eine
 * Stelle, die niemand sieht.
 */
.g-to-top {
	display: none;
}

html[data-g-deep] .g-to-top {
	position: fixed;
	inset-block-end: var(--wp--preset--spacing--sm, 16px);
	inset-inline-end: var(--wp--preset--spacing--sm, 16px);
	z-index: 20;

	display: grid;
	place-items: center;

	/*
	 * Quadratisch, und beide Maße gesetzt.
	 *
	 * Der Knopf traegt seit dem 2026-09-02 **nur das Zeichen** (Weisung des
	 * Auftraggebers). Damit gibt es keinen Text mehr, der ihm Breite gibt —
	 * ohne `min-inline-size` waere er so breit wie das Zeichen, also 24 px,
	 * und damit unter dem Mindestmaß fuer ein Tap-Ziel.
	 *
	 * 48 px statt 44: Ein Ziel ohne Text hat keinen Rand aus Buchstaben, an
	 * dem die Hand sich orientiert. Der Entwurf gibt fuer Knoepfe ohnehin 48.
	 */
	min-inline-size: 48px;
	min-block-size: 48px;

	text-decoration: none;
}

/*
 * Der Knopf weicht der Schlusszeile aus.
 *
 * `Scroll_State` im Toolkit setzt `data-g-to-top-weicht`, sobald die
 * Schlusszeile im Bild ist, und legt in `--g-to-top-ausweichen` ab, wie weit
 * der Knopf ueber den unteren Fensterrand muss. Dieselbe Arbeitsteilung wie
 * bei `data-g-deep`: Das Plugin meldet den Zustand, das Layout entscheidet,
 * was daraus folgt.
 *
 * WARUM DIESE REGEL NACH `html[data-g-deep]` STEHT. Beide Selektoren haben
 * dieselbe Spezifitaet (ein Attribut, eine Klasse). Bei gleicher Spezifitaet
 * entscheidet die Quellreihenfolge — eine Zeile weiter oben, und das
 * Ausweichen waere wirkungslos.
 *
 * DIE OBERGRENZE IST KEINE ZIERDE. Waere die Schlusszeile einmal hoeher als
 * das Fenster, schoebe der gerechnete Wert den Knopf oben aus dem Bild. `min()`
 * haelt ihn im Fenster; 96 px sind seine 48 px plus zweimal Luft.
 */
html[data-g-to-top-weicht] .g-to-top {
	inset-block-end: min( var(--g-to-top-ausweichen, 96px), calc( 100dvh - 96px ) );
}

.g-to-top__zeichen {
	line-height: 1;
}

/* ===========================================================================
 * Chips — EIN Bauteil, vier Verwendungen
 *
 * Der Entwurf zeigt dieselbe Pille an vier Stellen: als Rubrikfilter, als
 * Typfilter der Suche, als Themen auf der Autorenseite und als „Wo etwas
 * steht" im leeren Zustand. Vier Stellen, ein Bauteil — sonst entstehen vier
 * Staende, und die Erfahrung dieses Projekts ist eindeutig, dass sie
 * auseinanderlaufen.
 *
 * ALLE VIER SIND GEBAUT. Rubrikfilter und Typfilter der Suche kommen seit dem
 * 2026-09-02 aus dem Toolkit-Feature `Filter_Chips` — dasselbe Bauteil, nur
 * mit Zaehler und Ziel. Es bringt kein eigenes CSS mit; die Zahl steht in
 * `.g-chips__count` und traegt hier absichtlich keine Regel, weil der Entwurf
 * sie wie die Beschriftung setzt. Der Abstand dazwischen ist der `gap` der
 * Pille.
 *
 * Hier steht nur, was ohne Regel kaputt waere: die Reihe, die Trefferflaeche
 * und dass der Link kein Blockelement ist. Groesse, Gewicht, Radius und Farbe
 * gehoeren ins Child.
 *
 * WARUM DER SELEKTOR AUF DEN NACHFAHREN GEHT
 *
 * Zwei der vier Verwendungen kommen aus `core/categories`. Der Block laesst
 * eine `className` nur an der Liste zu, nicht am `<a>` darin. Ein Bauteil,
 * das nur mit eigener Klasse am Link funktioniert, waere an genau diesen
 * Stellen nicht benutzbar. Deshalb `.g-chips a` — Spezifitaet 0,1,1 und damit
 * ueber Cores Linkfarbe aus `:root :where(a:where(:not(.wp-element-button)))`,
 * die durch `:where()` bei 0,1,0 liegt.
 * ======================================================================== */
.g-chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--g-chip-gap, 0.5rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Cores Flow-Layout haengt jedem nicht-ersten Listenpunkt den blockGap als
   `margin-block-start` an. In einer Reihe versetzt das die Chips einer Zeile
   gegeneinander — den Abstand traegt hier allein `gap`. */
.g-chips > li {
	margin-block-start: 0;
}

/* Der Selektor fasst auch `.g-chip` — den nicht verlinkten Chip. Den zeigt
   der Entwurf auf der Autorenseite als Themen-Span. Markup dafuer gibt es
   noch nicht; die Regel steht, weil sie zum Bauteil gehoert und nicht, weil
   sie heute etwas trifft. */
.g-chip,
.g-chips a {
	display: inline-flex;
	align-items: center;
	gap: var(--g-chip-inner-gap, 0.375rem);

	/* Die Trefferflaeche. `min-block-size` und nicht `height`: Ein langer
	   Rubrikname darf umbrechen und den Chip hoeher machen, statt ihn zu
	   sprengen. */
	min-block-size: var(--g-chip-height, 40px);
	padding-block: var(--g-chip-pad-block, 9px);
	padding-inline: var(--g-chip-pad-inline, 15px);

	text-decoration: none;
}

/*
 * DER ZAEHLER KOMMT NICHT AUS `core/categories`, und das war der Grund fuer
 * eigenes Markup: `Walker_Category::start_el()` haengt „ (18)" **ausserhalb**
 * des `<a>` an, also neben die Pille statt in sie, und in Klammern. Die zwei
 * Verwendungen dieses Blocks (leerer Zustand, Autorenseite) setzen deshalb
 * `showPostCounts: false` und bleiben ohne Zahl.
 *
 * Die zwei Filterreihen schreibt `Filter_Chips` selbst und legt die Zahl in
 * ein `<span>` **im** Link. Eine Regel dafuer braucht es hier nicht.
 */

/* ===========================================================================
 * Blaetterleiste
 *
 * Werte aus dem Entwurf: Mindestmass 44 px im Quadrat fuer die Ziffern,
 * „Weiter" mit seitlichem Polster statt Quadrat. Farbe, Radius und Rahmen
 * gehoeren ins Child.
 *
 * Cores Markup: `.wp-block-query-pagination` traegt aussen, darin
 * `.wp-block-query-pagination-numbers` mit `<a class="page-numbers">` und
 * `<span class="page-numbers current">`. Die aktuelle Seite ist ein `<span>`
 * und kein Link — der Selektor muss beides fassen, sonst hat die aktive
 * Ziffer eine andere Groesse als die uebrigen.
 * ======================================================================== */
.g-pagination {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--g-pagination-gap, 0.5rem);
}

.g-pagination .wp-block-query-pagination-numbers {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--g-pagination-gap, 0.5rem);

	/* Core setzt hier `margin-inline: auto` und schiebt die Ziffernreihe
	   damit von „Zurueck" und „Weiter" weg. Der Entwurf zeigt eine
	   geschlossene Reihe. */
	margin: 0;
}

.g-pagination .page-numbers,
.g-pagination .wp-block-query-pagination-previous,
.g-pagination .wp-block-query-pagination-next {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-inline-size: var(--g-pagination-size, 44px);
	min-block-size: var(--g-pagination-size, 44px);
	text-decoration: none;
}

/* „Zurueck" und „Weiter" tragen ein Wort und werden deshalb breiter als
   quadratisch. Das Mindestmass von oben bleibt als Untergrenze stehen. */
.g-pagination .wp-block-query-pagination-previous,
.g-pagination .wp-block-query-pagination-next {
	padding-inline: var(--g-pagination-pad-inline, 16px);
	gap: var(--g-chip-inner-gap, 0.375rem);
}

/* ===========================================================================
 * Brotkrume
 *
 * Der Entwurf zeigt sie auf ALLEN drei Uebersichten und auf der
 * Beitragsseite. Sie lag bis zum 2026-09-02 als Markup in
 * `parts/post-meta.html` und war damit nur dort zu haben; jetzt ist sie ein
 * eigener Part (`parts/breadcrumb.html`).
 *
 * Das `nav` samt `aria-label` kommt vom SEO-Plugin, nicht von hier. Diese
 * Gruppe ist der Traeger fuer Abstand und Reihe.
 * ======================================================================== */
.g-breadcrumb {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--g-breadcrumb-gap, 0.5rem);
	padding-block: var(--g-breadcrumb-pad-top, 8px) var(--g-breadcrumb-pad-bottom, 16px);
}

/*
 * Der Traeger wird UNBEDINGT ausgegeben, sein Inhalt nicht: Liefert der
 * Shortcode des SEO-Plugins auf einer Adresse nichts, blieben 24 px
 * unerklaerlicher Abstand ueber dem Seitentitel stehen — und zwar auf vier
 * Adressen gleichzeitig, ohne dass am Markup etwas falsch aussieht. Genau
 * diese Fehlerklasse hat dieses Projekt schon mehrfach bezahlt.
 *
 * `:not(:has(*))` und nicht `:empty`: Der Blockinhalt enthaelt Zeilenumbrueche,
 * und Leerraum zaehlt fuer `:empty` als Inhalt. Gefragt ist „kein
 * Kindelement", und genau das prueft `:has()`.
 */
.g-breadcrumb:not(:has(*)) {
	display: none;
}

/* ===========================================================================
 * Die Suchergebnisseite
 *
 * Sie laeuft schmaler als die uebrigen Uebersichten: Der Entwurf legt einen
 * Traeger um den GANZEN Suchbereich, nicht um das Feld. Das Mass steht im
 * Skin, hier nur der Traeger und sein Rueckfall.
 *
 * Der Block traegt `alignwide`, sonst haengt er an `contentSize` (41 rem) und
 * waere schmaler als vorgesehen.
 *
 * WARUM DER SELEKTOR SO LANG IST, und das ist gemessen: Core setzt fuer
 * `alignwide` im gebundenen Layout `.wp-block-group.is-layout-constrained >
 * .alignwide { max-width: var(--wp--style--global--wide-size) }` — 0,3,0.
 * Eine einklassige Regel (0,1,0) verliert dagegen lautlos, und die Wache mass
 * 1200 px statt 832. `max-inline-size` hilft nicht: Logische und physische
 * Eigenschaft kaskadieren gemeinsam.
 * ======================================================================== */
.wp-block-group.is-layout-constrained > .g-search-page.alignwide {
	max-inline-size: var(--g-search-width, 52rem);
	margin-inline: auto;
}

/* ---------------------------------------------------------------------------
 * Das Suchfeld auf der Seite
 *
 * Cores `.wp-block-search__inside-wrapper` ist bereits `display: flex`. Hier
 * kommt dazu, was der Entwurf verlangt: die Lupe mittig zur Eingabezeile, ein
 * Abstand dazwischen, und ein Feld, das den ganzen Rest einnimmt.
 *
 * Die Lupe kommt aus dem Icon-Satz (`inc/search.php`) und steht VOR dem Feld
 * im Markup. Sie darf nicht schrumpfen — sonst quetscht ein langer Begriff
 * sie zusammen, statt das Feld zu fuellen.
 * ------------------------------------------------------------------------- */
.g-search-inline {
	margin-block-end: var(--g-search-field-gap, 14px);
}

.g-search-inline .wp-block-search__inside-wrapper {
	align-items: center;
	gap: var(--g-search-icon-gap, 12px);
	padding: var(--g-search-pad-block, 14px) var(--g-search-pad-inline, 16px);
}

.g-search-inline__icon {
	flex-shrink: 0;
}

/* Das Feld traegt weder Rahmen noch Flaeche: Beides sitzt am Traeger, sonst
   stehen zwei Rahmen ineinander. `outline` bleibt fuer die Tastatur —
   entfernt wird nur Cores voreingestellte Umrandung des Eingabefeldes. */
.g-search-inline .wp-block-search__input {
	flex: 1 1 auto;
	min-inline-size: 0;
	border: 0;
	background: none;
	padding: 0;
}

/* ---------------------------------------------------------------------------
 * Die Filterreihe der Suche
 *
 * Dasselbe Bauteil wie an der Rubrik, andere Facette: dort Schlagwoerter
 * innerhalb der Rubrik, hier Rubriken innerhalb der Suchanfrage. Gefuellt vom
 * Toolkit-Feature `Filter_Chips`, leer ohne Treffer — und dann weg.
 * ------------------------------------------------------------------------- */
/*
 * Wie an der Rubrikseite: Der Entwurf gibt jeder Zeile ihren Abstand nach
 * UNTEN, Cores Fluss-Layout haengt jedem nicht-ersten Kind zusaetzlich den
 * blockGap als `margin-block-start` an. Gemessen am 2026-09-02 an der Instanz:
 * zwischen Trefferzeile und Liste standen 16 + 21 = 37 px statt der
 * vorgesehenen 16. Die Filterreihe dazwischen haette den Fehler verdoppelt.
 */
.g-search-results > * {
	margin-block-start: 0;
}

.g-search-filter {
	margin-block-end: var(--g-search-filter-end, 22px);
}

.g-search-filter:empty {
	display: none;
}

/* ---------------------------------------------------------------------------
 * Die Trefferliste
 *
 * SIE TRAEGT SEIT DEM 2026-09-02 IHREN EIGENEN NAMEN, und das ist der ganze
 * Punkt von BL56. Vorher stand `g-post-grid__items` mit im `className` — nicht
 * weil die Suche Karten zeigt (sie zeigt Trefferzeilen), sondern weil
 * `Load_More` im Toolkit das Raster fest unter diesem Namen suchte. Die
 * Trefferliste musste den Kartennamen mittragen, um ueberhaupt nachladen zu
 * koennen, und zwei Regeln darunter nahmen dem Kartenraster wieder weg, was
 * die Suche anders macht.
 *
 * Jetzt nennt die Vorlage ihr Raster selbst (`gRaster` an der Ankergruppe in
 * `templates/search.html`), und diese Regel steht fuer sich. Sie wiederholt
 * damit `display: grid` und `grid-template-columns` — das ist keine Doppelung,
 * sondern das Ende einer Erbschaft, die nie eine war.
 *
 * KEINE Media Query fuer 992 px: Die Trefferliste ist auf jeder Breite
 * einspaltig. Genau dafuer stand die alte Zeile.
 * ------------------------------------------------------------------------- */
.g-search-hits {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-search-hits-gap, 12px);
	margin-block-end: var(--g-search-hits-end, 28px);
}

/* Dieselbe Ruecknahme wie am Kartenraster: Cores Flow-Layout haengt jedem
   nicht-ersten Kind den blockGap als margin-block-start an, und im Raster
   versetzt das die Zeilen gegeneinander. Den Abstand traegt allein `gap`. */
.g-search-hits > * {
	margin-block-start: 0;
}

/* ---------------------------------------------------------------------------
 * Die Trefferzeile
 *
 * KEINE Beitragskarte, sondern ein eigenes Bauteil — die Begruendung steht in
 * `patterns/search-result.php`. Einspaltig, ab 992 px Bild und Text
 * nebeneinander.
 *
 * `position: relative` traegt die Trefferflaeche des Titel-Links; der
 * Textblock bleibt `static`, sonst bezieht sie ihr `inset: 0` auf ihn statt
 * auf die Zeile. Genau dieser Fehler ist an der Karte gemessen worden.
 * ------------------------------------------------------------------------- */
.g-search-hit {
	/* Traeger fuer die `cqi`-Groesse der bildlosen Kennzeichnung im Child —
	   dieselbe Rolle wie `container-name: card` an der Karte. Ohne ihn misst
	   `cqi` gegen das Fenster und das Rubrikschild waere in der 200-px-Spalte
	   so gross wie ueber die ganze Breite. */
	container-type: inline-size;
	container-name: hit;

	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-search-hit-gap, 14px);
	position: relative;
}

@media (min-width: 992px) {
	.g-search-hit {
		grid-template-columns: var(--g-search-hit-media, 200px) 1fr;
	}

	/* Weder Bild noch Kennzeichnung: Dann gibt es keine erste Spalte, und eine
	   leere 200-px-Spalte waere ein Einzug ohne Grund. Der Fall trifft
	   Ergebnisse ohne Rubrik, etwa eine Seite. */
	.g-search-hit:not(:has(> .g-search-hit__media, > .g-search-hit__mark)) {
		grid-template-columns: 1fr;
	}
}

.g-search-hit__body {
	position: static;
}

/* Cores Fluss-Layout haengt jedem nicht-ersten Kind denselben blockGap an. Der
   Entwurf gibt jeder Zeile ihren eigenen Abstand nach UNTEN. */
.g-search-hit__body > * {
	margin-block-start: 0;
}

.g-search-hit__kicker {
	margin-block-end: var(--g-search-hit-kicker-gap, 5px);
}

.g-search-hit__title {
	margin-block-end: var(--g-search-hit-title-gap, 6px);
}

.g-search-hit__excerpt {
	margin-block-end: var(--g-search-hit-excerpt-gap, 8px);
}

.g-search-hit__excerpt p {
	margin-block: 0;
}

.g-search-hit__meta {
	margin-block-end: 0;
}

/* Die ganze Zeile ist die Trefferflaeche — im Entwurf ist sie EIN Link.
   Dieselbe Loesung wie an der Karte, samt Preis: Text laesst sich darin nicht
   markieren. */
.g-search-hit__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* Die Kennzeichnung der bildlosen Zeile (`inc/post-card-fallback.php`) haelt
   dieselbe Stelle und dieselbe Proportion wie das Bild. */
.g-search-hit__mark {
	display: grid;
	place-items: center;
	width: 100%;
	aspect-ratio: 16 / 9;
	overflow-wrap: anywhere;
	text-align: center;
}

/* ===========================================================================
 * Die Rubrikseite
 *
 * Vier Bauteile in einem Traeger: Kopfzone, Empfehlungskasten, Ueberschrift
 * mit Sortierung, FAQ. Hier steht nur, was ohne Regel kaputt waere — Reihen,
 * Raster, Abstaende, Trefferflaechen. Groessen, Farben und Radien gehoeren
 * ins Child und kommen ueber `--g-term-*` herein.
 *
 * ZWEI DER VIER ANKER FUELLT NICHT DIESES REPO. `g-term-recommendation` und
 * `g-term-faq` sind leere Gruppen der Vorlage; das Toolkit-Feature
 * `Term_Profile` schreibt Label, Ueberschrift und Inhalt hinein — oder nichts.
 * Deshalb traegt JEDER der drei fuellbaren Anker eine `:empty`-Regel: Ein
 * Kasten mit Flaeche und eine Linie ueber dem Nichts waeren sonst genau die
 * Spur, die ein leeres Feld nicht hinterlassen darf.
 * ======================================================================== */

/* Der Entwurf gibt jeder Zeile ihren eigenen Abstand nach UNTEN. Cores
   Fluss-Layout haengt jedem nicht-ersten Kind denselben blockGap als
   `margin-block-start` an; beides zusammen waere doppelt. */
.g-term-page > * {
	margin-block-start: 0;
}

/* ---------------------------------------------------------------------------
 * Kopfzone
 * ------------------------------------------------------------------------- */
.g-term-head {
	border-block-end: 2px solid var(--g-rule-strong, currentColor);
	padding-block-end: var(--g-term-head-pad, 22px);
	margin-block-end: var(--g-term-head-end, 22px);
}

.g-term-head > * {
	margin-block-start: 0;
}

/*
 * Der Kicker der Rubrik ist NICHT der Kicker der Karte. Gleiche Machart,
 * anderes Bauteil, andere Groesse — deshalb ein eigener Name.
 */
.g-term-kicker {
	display: flex;
	align-items: center;
	gap: var(--g-term-kicker-gap, 11px);
	margin-block-end: var(--g-term-kicker-end, 10px);
}

.g-term-title {
	margin-block-end: var(--g-term-title-end, 12px);
}

/*
 * Das Intro ist Cores Termbeschreibung, kein zweites Feld. Sie kommt als
 * `<div>` mit einem `<p>` darin; der Abstand steht am Traeger, damit ein
 * zweiter Absatz ihn nicht verdoppelt.
 *
 * Auf der Beitragsseite traegt dieselbe Klasse eine leere Ankergruppe, die
 * `inc/home-title.php` fuellt — daher die `:empty`-Regel wie an den uebrigen
 * Ankern. Cores Termdescription liefert bei leerer Beschreibung gar nichts.
 */
.g-term-description:empty {
	display: none;
}

.g-term-description {
	max-inline-size: var(--g-term-intro-width, 60ch);
	margin-block-end: 0;
}

.g-term-description p {
	margin-block: 0;
}

/* ---------------------------------------------------------------------------
 * Die Filterreihe
 *
 * Eine leere Ankergruppe, die das Toolkit-Feature `Filter_Chips` fuellt — oder
 * eben nicht: Ohne ein einziges Schlagwort in der Rubrik bleibt sie leer, und
 * ein „Alle N" allein waere ein Filter ohne Alternative. Deshalb dieselbe
 * `:empty`-Regel wie an den drei Ankern darunter.
 *
 * Die Chips selbst sind `.g-chips` weiter oben. Hier steht nur der Abstand,
 * den der Anker in der Spalte haelt.
 * ------------------------------------------------------------------------- */
.g-term-filter {
	margin-block-end: var(--g-term-filter-end, 12px);
}

.g-term-filter:empty {
	display: none;
}

/* ---------------------------------------------------------------------------
 * Empfehlungskasten
 *
 * DAS RASTER SITZT AM `__body` UND NICHT AM ANKER, weil das Feature alles in
 * diese eine Huelle legt: Label, Titel, Satz und Knopf sind vier Geschwister,
 * nicht ein Textblock plus Knopf. Ab 992 px stehen die ersten drei in Spalte 1
 * und der Knopf ueberspannt sie in Spalte 2.
 *
 * `grid-template-rows: repeat(3, auto)` ist dafuer die Bedingung und keine
 * Zierde: `grid-row: 1 / -1` zaehlt Linien des EXPLIZITEN Rasters. Ohne
 * gesetzte Zeilen gaebe es nur eine, und der Knopf saesse in Zeile 1 statt
 * mittig. Fehlt ein Textteil, bleibt seine Zeile leer und hoch 0 — der
 * Abstand kommt aus Aussenabstaenden, nicht aus `row-gap`.
 * ------------------------------------------------------------------------- */
.g-term-recommendation {
	padding: var(--g-term-rec-pad-block, 20px) var(--g-term-rec-pad-inline, 22px);
	margin-block-end: var(--g-term-rec-end, 28px);
}

.g-term-recommendation:empty {
	display: none;
}

.g-term-recommendation__body {
	display: grid;
	grid-template-columns: 1fr;
	grid-template-rows: repeat(3, auto);
	column-gap: var(--g-term-rec-gap, 16px);
}

.g-term-recommendation__label {
	margin-block: 0 var(--g-term-rec-label-end, 6px);
}

/*
 * Der Titel ist ein `<a>` und traegt seine Klasse selbst. Der Selektor nennt
 * deshalb das Element mit (0,1,1): Cores Linkregel liegt bei 0,1,0, und eine
 * gleich starke Regel entscheidet sich ueber die Ladereihenfolge. Genau so
 * war am 2026-09-02 jeder Kartentitel magenta unterstrichen.
 */
a.g-term-recommendation__title {
	display: block;
	margin-block-end: var(--g-term-rec-title-end, 4px);
	text-decoration: none;
}

.g-term-recommendation__text {
	margin-block: 0;
}

a.g-term-recommendation__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--g-term-rec-button-gap, 9px);

	min-block-size: var(--g-term-rec-button-height, 50px);
	padding: var(--g-term-rec-button-pad-block, 14px) var(--g-term-rec-button-pad-inline, 20px);

	/* Einspaltig steht der Knopf unter dem Text und braucht den Spalt als
	   Aussenabstand — `row-gap` ist hier 0, siehe oben. */
	margin-block-start: var(--g-term-rec-gap, 16px);
	justify-self: start;

	white-space: nowrap;
	text-decoration: none;
}

@media (min-width: 992px) {
	.g-term-recommendation__body {
		grid-template-columns: 1fr auto;
		align-items: center;
	}

	.g-term-recommendation__label,
	a.g-term-recommendation__title,
	.g-term-recommendation__text {
		grid-column: 1;
	}

	a.g-term-recommendation__button {
		grid-column: 2;
		grid-row: 1 / -1;
		align-self: center;
		margin-block-start: 0;
	}
}

/* ---------------------------------------------------------------------------
 * Ueberschrift und Sortierung
 *
 * `align-items: baseline`: Die 14-px-Zeile rechts sitzt auf derselben Linie
 * wie die Ueberschrift links, nicht mittig zu ihrer Hoehe.
 * ------------------------------------------------------------------------- */
.g-term-sort {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--g-term-sort-gap, 14px);
	margin-block-end: var(--g-term-sort-end, 16px);
}

/* Ohne Beitraege gibt `inc/category.php` nichts aus. Dann auch kein Abstand. */
.g-term-sort:empty {
	display: none;
}

.g-term-sort__heading {
	margin-block: 0;
}

.g-term-sort__choice {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--g-term-sort-inner-gap, 10px);
}

/*
 * Auf der Beitragsseite gibt `inc/category.php` KEINE Ueberschrift aus — die
 * H1 darueber nennt die Menge bereits. Ohne Nachbarn wuerde die Sortierwahl
 * durch `space-between` nach links rutschen; sie gehoert an dieselbe Kante wie
 * mit Ueberschrift.
 */
.g-term-sort__choice:only-child {
	margin-inline-start: auto;
}

a.g-term-sort__link {
	text-decoration: none;
}

/*
 * Der aktive Zustand haengt am Attribut und nicht an einer Klasse: Er steht
 * damit fuer die Hilfstechnik im Markup UND traegt die Gestaltung. Die Linie
 * ist nur EINE von drei Anzeigen — Gewicht und Farbe kommen im Skin dazu.
 */
a.g-term-sort__link[aria-current] {
	border-block-end: 2px solid var(--g-term-sort-active, currentColor);
	padding-block-end: var(--g-term-sort-active-pad, 2px);
}

/* ---------------------------------------------------------------------------
 * DER AUFKLAPPER — an zwei Orten, in einer Definition
 *
 * Ein Seitenbauteil, NICHT der `gw-faq` des Content-Vertrags im Beitrag.
 * Ueberschrift und Fragen gibt das Toolkit aus, Auf und Zu bringt der Browser.
 *
 * SEIT DEM 2026-09-04 TRAEGT DERSELBE AUFKLAPPER DIE GRUNDSAETZE DES
 * ABSCHNITTS „So arbeiten wir" auf der Ueber-uns-Seite
 * (`g-about__principle*`). Die Selektoren stehen deshalb GRUPPIERT und nicht
 * ein zweites Mal mit denselben Werten: Ein Aufklapper, den es zweimal gibt,
 * ist zwei Staende desselben Bauteils, und einer davon veraltet — dieselbe
 * Begruendung wie bei der Beitragskarte.
 *
 * Der Preis der Gruppierung ist ein Name: Die Stellschrauben heissen weiter
 * `--g-term-faq-*`, obwohl sie jetzt beide Orte stellen. Umbenennen hiesse den
 * Skin jedes Projekts mit umbenennen; der Name ist eine Schuld, kein Fehler.
 *
 * EIN UNTERSCHIED BLEIBT, und er ist inhaltlich: Der Zusammenfassungstext der
 * Grundsaetze ist eine ECHTE UEBERSCHRIFT (`h3`) und kein blosser Satz. Der
 * Abschnitt ist ein Fliesstext mit Gliederung, und wer nach Ueberschriften
 * springt, darf sie nicht dadurch verlieren, dass sie in einem `<summary>`
 * steht. Deshalb `g-about__principle-title` weiter unten.
 * ------------------------------------------------------------------------- */
.g-term-faq {
	border-block-start: 2px solid var(--g-rule-strong, currentColor);
	padding-block: var(--g-term-faq-pad-top, 22px) var(--g-term-faq-pad-bottom, 44px);
}

.g-term-faq:empty {
	display: none;
}

.g-term-faq__heading {
	margin-block: 0 var(--g-term-faq-heading-end, 14px);
}

.g-term-faq__list,
.g-about__principles {
	border-block-start: 1px solid var(--g-rule, currentColor);
}

.g-term-faq__item,
.g-about__principle {
	border-block-end: 1px solid var(--g-rule, currentColor);
}

.g-term-faq__question,
.g-about__principle-summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--g-term-faq-question-gap, 14px);
	min-block-size: var(--g-term-faq-question-height, 56px);
	padding: var(--g-term-faq-question-pad-block, 16px) var(--g-term-faq-question-pad-inline, 2px);
	cursor: pointer;
	list-style: none;
}

/*
 * DREI REGELN FUER EINEN PFEIL, und keine davon reicht allein: `list-style`
 * greift in Firefox, `::-webkit-details-marker` in aelteren WebKit-Fassungen,
 * und `display: flex` nimmt dem `<summary>` den `list-item`-Modus, an dem
 * Chromium seinen Marker haengt. Gemessen, nicht angenommen.
 */
.g-term-faq__question::-webkit-details-marker,
.g-about__principle-summary::-webkit-details-marker {
	display: none;
}

.g-term-faq__question::marker,
.g-about__principle-summary::marker {
	content: "";
}

/*
 * Das Pluszeichen gibt das Feature nicht aus — es ist Zustandsanzeige und
 * damit Sache der Darstellung. Die zweite `content`-Zeile haengt einen leeren
 * Alternativtext an, damit es nicht vorgelesen wird; wo die Schreibweise
 * unbekannt ist, faellt sie weg und die erste Zeile bleibt stehen.
 */
.g-term-faq__question::after,
.g-about__principle-summary::after {
	content: "+";
	content: "+" / "";
	flex-shrink: 0;
	line-height: 1;
}

/*
 * Offen zeigt ein Minus. Der Entwurf zeichnet nur den geschlossenen Zustand;
 * ein Umschalter, der in beiden Zustaenden gleich aussieht, zeigt keinen an.
 *
 * `−` ist U+2212 MINUS SIGN und nicht der Bindestrich: Der waere schmaler als
 * das Plus und saesse auf einer anderen Hoehe.
 */
.g-term-faq__item[open] > .g-term-faq__question::after,
.g-about__principle[open] > .g-about__principle-summary::after {
	content: "−";
	content: "−" / "";
}

.g-term-faq__answer,
.g-about__principle-answer {
	padding-inline-end: var(--g-term-faq-answer-pad, 30px);
}

.g-term-faq__answer p,
.g-about__principle-answer p {
	margin-block: 0 var(--g-term-faq-answer-end, 18px);
}

/* ---------------------------------------------------------------------------
 * Die Abstaende der Seitenebene
 *
 * Sie stehen HIER und nicht am Bauteil: Raster und Blaetterleiste kommen auf
 * mehreren Vorlagen vor, diese beiden Zahlen gelten fuer die Rubrikseite.
 * ------------------------------------------------------------------------- */
.g-term-page > .g-post-grid {
	margin-block-end: var(--g-term-grid-end, 28px);
}

.g-term-page .g-pagination {
	padding-block-end: var(--g-term-pagination-end, 36px);
}

/* ===========================================================================
 * Die Autorenseite
 *
 * Drei Bauteile in einem Traeger: der Kopf als Kasten, die Arbeitsweise
 * zwischen zwei Linien, die Ueberschrift ueber dem Kartenraster. Hier steht
 * nur, was ohne Regel kaputt waere — Raster, Reihen, Abstaende. Groessen,
 * Farben und Radien gehoeren ins Child und kommen ueber `--g-author-*` herein.
 *
 * DIE FUENF ANKER FUELLT NICHT DIESES REPO. `g-author-figure`,
 * `g-author-intro`, `g-author-method`, `g-author-posts` und `g-author-links`
 * sind leere Gruppen der Vorlage; das Toolkit-Feature `Author_Profile` schreibt
 * hinein — oder nichts. Deshalb traegt jeder von ihnen eine `:empty`-Regel:
 * ein leerer Kreis, eine Ueberschrift ohne Liste und zwei Linien um das
 * Nichts waeren genau die Spur, die ein ungepflegtes Feld nicht hinterlassen
 * darf.
 *
 * DAS KARTENRASTER IST DASSELBE WIE UEBERALL. Eine Autorenvariante der Karte
 * gibt es nicht; hier steht nur ihr Abstand nach unten.
 * ======================================================================== */

/* Der Entwurf gibt jeder Zeile ihren eigenen Abstand nach UNTEN. Cores
   Fluss-Layout haengt jedem nicht-ersten Kind denselben blockGap als
   `margin-block-start` an; beides zusammen waere doppelt. */
.g-author-page > * {
	margin-block-start: 0;
}

/* ---------------------------------------------------------------------------
 * Der Kopf
 *
 * Einspaltig, ab 992 px Bild und Text nebeneinander. `auto 1fr` und nicht
 * `88px 1fr`: Die Breite der ersten Spalte ist die des Bildes, und die steht
 * im Child. Eine Zahl hier waere dieselbe Zahl an zwei Orten.
 * ------------------------------------------------------------------------- */
.g-author-head {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-author-head-gap-row, 20px) var(--g-author-head-gap-col, 26px);
	padding: var(--g-author-head-pad-block, 24px) var(--g-author-head-pad-inline, 22px);
	margin-block-end: var(--g-author-head-end, 28px);
}

@media (min-width: 992px) {
	.g-author-head {
		grid-template-columns: auto 1fr;
	}
}

.g-author-figure:empty {
	display: none;
}

/*
 * Bild und Initialen sind dasselbe Mass und dieselbe Form. `flex-shrink` ist
 * hier ohne Wirkung und steht deshalb nicht da; im Raster haelt `auto` die
 * Spalte, und `aspect-ratio` haelt den Kreis auch dann rund, wenn die
 * Schriftgroesse aus dem Child ihn hoeher machen wollte.
 */
.g-author-figure__image,
.g-author-figure__initials {
	display: grid;
	place-items: center;
	inline-size: var(--g-author-figure-size, 88px);
	block-size: var(--g-author-figure-size, 88px);
	aspect-ratio: 1;
	border-radius: 50%;
	overflow: hidden;
}

.g-author-head__body > * {
	margin-block-start: 0;
}

.g-author-kicker {
	margin-block-end: var(--g-author-kicker-end, 6px);
}

.g-author-title {
	margin-block-end: var(--g-author-title-end, 10px);
}

.g-author-intro:empty {
	display: none;
}

.g-author-intro__body > * {
	margin-block-start: 0;
}

/*
 * Die Zeilenlaenge steht am Traeger und nicht am Absatz: Eine zweite
 * Absatzzeile soll dieselbe Breite haben, und der Abstand nach unten soll
 * sich nicht verdoppeln.
 */
.g-author-intro__bio {
	max-inline-size: var(--g-author-bio-width, 58ch);
	margin-block-end: var(--g-author-bio-end, 16px);
}

.g-author-intro__bio p {
	margin-block: 0;
}

/* Die Chips selbst sind `.g-chips` weiter oben — ein Bauteil, hier nur der
   Abstand. Auf dieser Seite sind es `<span>` ohne Link: eine Angabe, kein
   Filter. */
.g-author-topics {
	margin-block-end: var(--g-author-topics-end, 16px);
}

.g-author-meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--g-author-meta-gap-row, 8px) var(--g-author-meta-gap-col, 20px);
}

.g-author-meta__item,
a.g-author-meta__contact {
	display: inline-flex;
	align-items: center;
	gap: var(--g-author-meta-inner-gap, 7px);
	text-decoration: none;
}

/* Das Zeichen steht NEBEN dem Wort. Es darf deshalb nicht schrumpfen, wenn
   die Zeile umbricht — sonst wird aus einem Zeichen ein Strich. */
.g-author-meta__icon,
.g-author-method__icon {
	flex-shrink: 0;
}

/* Der Gegenpart dazu: Ein Flex-Kind schrumpft von sich aus nicht unter seinen
   Inhalt (`min-width: auto`). Ohne diese Zeile sprengt ein langes Wort die
   Zeile, statt umzubrechen. */
.g-author-meta__text,
.g-author-method__title,
.g-author-method__text {
	min-inline-size: 0;
}

/* ---------------------------------------------------------------------------
 * Womit ich teste
 *
 * Ueberschrift und Liste gibt das Feature aus. Die beiden Linien stehen am
 * Abschnitt, nicht an der Liste: Sie umschliessen auch die Ueberschrift.
 * ------------------------------------------------------------------------- */
.g-author-method {
	border-block: 1px solid var(--g-rule, currentColor);
	padding-block: var(--g-author-method-pad, 20px);
	margin-block-end: var(--g-author-method-end, 32px);
}

.g-author-method:empty {
	display: none;
}

/* Das Zeichen sitzt IM `<h2>` und nicht daneben: Zwei Geschwister brauchten
   einen zweiten Traeger, und der waere ein Kasten um eine Ueberschrift. */
.g-author-method__heading {
	display: flex;
	align-items: center;
	gap: var(--g-author-method-heading-gap, 9px);
	margin-block: 0 var(--g-author-method-heading-end, 12px);
}

.g-author-method__list {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-author-method-gap-row, 6px) var(--g-author-method-gap-col, 26px);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 992px) {
	.g-author-method__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* `list-style: none` an der Liste nimmt dem `<ol>` die eigenen Ziffern; die
   gezeigte Nummer ist ein eigenes Element, damit sie eine Farbe tragen kann.
   Der Abstand kommt aus `gap`, nicht aus Aussenabstaenden der Punkte. */
.g-author-method__item {
	display: flex;
	gap: var(--g-author-method-item-gap, 10px);
	padding-block: var(--g-author-method-item-pad, 7px);
	margin-block-start: 0;
}

.g-author-method__number {
	flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
 * Die Netzwerkprofile
 *
 * Reihe, Umbruch und Abstand der Liste stehen im Toolkit an `.g-author-profiles`
 * — hier steht nur, was am ANKER haengt. Bis zum 2026-09-02 fehlte ihm als
 * einzigem der fuenf die `:empty`-Regel (BL63): Ein Autor ohne gepflegte
 * Profile hinterliess eine leere Gruppe im Fluss.
 *
 * KEIN EINZUG. Der Anker trug bis zum 2026-09-02 als einzige Gruppe der
 * Autorenseite `layout: constrained`. Cores Einzug auf die Inhaltsbreite
 * setzte die Profilreihe damit 272 px eingerueckt und zentriert, waehrend
 * Kopf und Arbeitsweise an der Kante des Traegers beginnen — gemessen x=312
 * gegen x=40. Der Entwurf zeigt eine Kante, nicht drei. Deshalb steht in
 * `templates/author.html` und `parts/author-box.html` jetzt `default`; hier
 * gibt es dazu nichts zu regeln, die Zeile steht als Warnung vor dem
 * Rueckbau.
 * ------------------------------------------------------------------------- */
.g-author-links:empty {
	display: none;
}

/* ---------------------------------------------------------------------------
 * Der Autorenkasten am Beitragsende (`g-author-box`)
 *
 * Anordnung, Abstand und Polster bringt `parts/author-box.html` als
 * Core-Layout mit; hier steht nur, was Core nicht loesen kann.
 *
 * WARUM DER TEIL SEIT DEM 2026-09-03 KLASSEN TRAEGT. Name, Biografie und
 * Bild waren klassenlos und dadurch aus dem Skin nicht erreichbar — der
 * Kasten war bis dahin das einzige Bauteil der Beitragsseite ohne eine
 * einzige eigene Regel.
 *
 * UND WARUM `fontSize` UND `textColor` AUS DEM TEIL WEG SIND: Beides druckt
 * WordPress als Preset-Regel MIT `!important`, ein Child kommt nicht dagegen
 * an. Die Biografie stand damit in `muted` — der Rolle, die in diesem System
 * NIE Text traegt (gemessen 2,53:1). Derselbe Fall wie in
 * `patterns/post-card.php`, dort ausfuehrlich begruendet.
 * ------------------------------------------------------------------------ */
.g-author-box__text {
	/* Ein Flex-Kind schrumpft ohne diese Angabe nicht unter seine
	   Min-Content-Breite; ein langer Autorenname sprengte den Kasten. */
	min-inline-size: 0;
}

.g-author-box__figure img {
	display: block;
}

/* ---------------------------------------------------------------------------
 * Die Ueberschrift ueber dem Raster
 * ------------------------------------------------------------------------- */
.g-author-posts:empty {
	display: none;
}

/*
 * ZWEI KLASSEN IM SELEKTOR, UND DAS IST KEINE ZIERDE. Die Ueberschrift ist das
 * einzige Kind ihrer Gruppe, und Cores Fluss-Layout setzt
 * `:where(.is-layout-flow) > :last-child { margin-block-end: 0 }` — dieselbe
 * Spezifitaet wie eine einzelne Klasse, aber spaeter im Dokument. Gemessen: 0
 * statt 16. Derselbe Fall wie beim Kartentitel gegen Cores Linkfarbe.
 */
.g-author-posts > .g-author-posts__heading {
	margin-block: 0 var(--g-author-posts-heading-end, 16px);
}

.g-author-page > .g-post-grid {
	margin-block-end: var(--g-author-grid-end, 44px);
}

/* ===========================================================================
 * Die Zustandsseiten: leerer Zustand, leere Suche, 404
 *
 * Drei Seiten, eine Formensprache. Der Entwurf zeigt den leeren Zustand nur
 * fuer die SUCHE (`Seiten-und-Zustaende.dc.html`, D5): ein sprechender Kasten
 * mit Bubble-Ecke, darunter ein Kleinlabel und eine Chipreihe, darunter eine
 * Fusszeile mit Oberlinie. Rubrik und Archiv benutzen dasselbe Vokabular,
 * statt ein zweites zu erfinden.
 *
 * Hier steht nur, was ohne Regel kaputt waere: Traeger, Breiten, Fluss und die
 * `:empty`-Regeln der Anker. Flaeche, Ecke, Groesse und Farbe gehoeren ins
 * Child.
 * ======================================================================== */

/* ---------------------------------------------------------------------------
 * Der leere Zustand einer Uebersicht
 *
 * `g-empty__chips` ist eine leere Ankergruppe, die `inc/chips.php` fuellt —
 * oder eben nicht. Ohne Rubrik ausser der eigenen bleibt sie leer, und ein
 * Label ueber einer leeren Reihe waere ein Strich im Nichts.
 * ------------------------------------------------------------------------- */
.g-empty > *,
.g-search-empty > * {
	/* Cores Fluss-Layout haengt jedem nicht-ersten Kind den blockGap an. Der
	   Entwurf gibt jeder Zeile ihren Abstand nach UNTEN. */
	margin-block-start: 0;
}

.g-empty__chips:empty,
.g-search-suggest:empty,
.g-search-empty__suggestion:empty {
	display: none;
}

/*
 * Der Fluss der drei Zustaende. Dasselbe Gegenstueck wie bei `.g-404`: Die
 * Regel oben nimmt den Abstand nach OBEN, hier steht der nach UNTEN. Groesse,
 * Gewicht und Farbe der Ueberschrift bleiben im Skin (BL63).
 */
.g-empty__title,
.g-search-empty__title {
	margin-block-end: var(--g-empty-title-end, 8px);
}

/* Das Kleinlabel ueber einer Chipreihe. Nur der Abstand zur Reihe. */
.g-empty__label,
.g-search-suggest__label {
	margin-block-end: var(--g-empty-label-end, 12px);
}

/* ---------------------------------------------------------------------------
 * Die leere Suche
 *
 * Der Traeger ist `.g-search-page` weiter oben; hier stehen nur die drei
 * Bloecke darunter. Die Chipreihe ist `.g-chips` — ein Bauteil, keine fuenfte
 * Verwendung mit eigener Regel.
 * ------------------------------------------------------------------------- */
.g-search-empty__suggestion > p:last-child,
.g-search-empty__hint,
.g-empty__hint {
	margin-block-end: 0;
}

/*
 * Die Fusszeile. Sie ist ein Nachsatz und kein zweiter sprechender Kasten:
 * Oberlinie und Polster statt Flaeche. Die Farbe der Linie kommt wie bei
 * `.g-404__list` aus `--g-rule-soft`.
 */
.g-search-empty__foot {
	border-block-start: 1px solid var(--g-rule-soft, currentColor);
	padding-block-start: var(--g-search-empty-foot-pad, 18px);
}

/* ---------------------------------------------------------------------------
 * 404
 *
 * Schmaler als jede Uebersicht (44 statt 75 rem) und mit eigenem Polster. Der
 * Selektor ist so lang wie der der Suchseite und aus demselben Grund: Cores
 * `.wp-block-group.is-layout-constrained > .alignwide` liegt bei 0,3,0 und
 * schlaegt eine einklassige Regel lautlos.
 *
 * Das Polster sitzt am Traeger und nicht am `main`: Der Entwurf gibt fuer
 * diese Seite 24 oben und 64 unten, und das sind nicht die Werte, die die
 * uebrigen Seiten aus der Abstandsskala nehmen.
 * ------------------------------------------------------------------------- */
.wp-block-group.is-layout-constrained > .g-404.alignwide {
	max-inline-size: var(--g-404-width, 44rem);
	margin-inline: auto;
	padding-block: var(--g-404-pad-top, 24px) var(--g-404-pad-bottom, 64px);
}

.g-404 > * {
	margin-block-start: 0;
}

/*
 * Der Fluss der Seite. Er gehoert hierher und nicht in den Skin: Die Regel
 * oben nimmt jedem Kind den Abstand nach OBEN, den Abstand nach UNTEN traegt
 * jede Zeile selbst. Beide Haelften desselben Gedankens standen bis zum
 * 2026-09-02 in zwei Repos (BL63).
 */
.g-404__title {
	margin-block: var(--g-404-title-start, 8px) var(--g-404-title-end, 14px);
	margin-inline: 0;
}

/* Das Zeilenmass des Vorspanns. Eine Breite, also Struktur. */
.g-404__text {
	max-inline-size: var(--g-404-text-width, 54ch);
	margin-block-end: var(--g-404-text-end, 26px);
}

.g-404__label {
	margin-block-end: var(--g-404-label-end, 12px);
}

.g-404__search {
	max-inline-size: var(--g-404-search-width, 34rem);
}

/*
 * Die Liste der 404 ist eine EINZEILERLISTE. Ihre Anatomie steht weiter unten
 * unter `g-oneline` und nicht mehr hier; was bleibt, ist der Abstand nach
 * unten, der zum Fluss dieser Seite gehoert und nicht zum Bauteil.
 *
 * GEAENDERT am 2026-09-03. Die Anatomie stand hier und wurde ein zweites Mal
 * gebraucht — in der Seitenleiste der Beitragsseite. Sie zu kopieren waere
 * genau das dritte Listenformat gewesen, das dieses System nicht haben will.
 */
.g-404__list {
	margin-block-end: var(--g-404-list-end, 26px);
}

/* ---------------------------------------------------------------------------
 * Einzeilerliste (`g-oneline`)
 * ---------------------------------------------------------------------------
 *
 * EIN Titel je Zeile, ein Zeichen am rechten Rand, eine Haarlinie darunter.
 * Kein Bild, kein Auszug, kein zweites Ziel. Sie ist das dritte und letzte
 * Listenformat dieses Systems, neben der Beitragskarte (`g-post-card`) und der
 * Trefferzeile der Suche (`g-search-result`).
 *
 * WOZU EIN EIGENES BAUTEIL. Sie stand seit dem 2026-09-02 als `g-404__link` in
 * der 404-Seite. Am 2026-09-03 brauchte die Seitenleiste der Beitragsseite
 * dieselbe Anatomie: Die Empfehlungen benutzten dort die volle Beitragskarte
 * und wurden in einer 232 px schmalen Spalte **778 px hoch** — eine Karte, die
 * fuer einen Dreispalter gezeichnet ist. Die Anatomie zu kopieren haette ein
 * viertes Format erzeugt; sie steht deshalb einmal hier und wird an beiden
 * Stellen benutzt.
 *
 * WAS SICH JE ORT AENDERN DARF: die drei Masse unten und die Schriftgroesse
 * im Skin. Mehr nicht — wer hier `display` oder die Ausrichtung umdreht, baut
 * doch wieder ein zweites Bauteil.
 *
 * HIER STEHT KEINE FARBE. Die Oberlinie holt sie aus `--g-rule-soft` und
 * bleibt ohne Skin in `currentColor` sichtbar, statt als unsichtbares Bauteil
 * durchzurutschen. Unterlinie, Textfarbe und das Zeichen am Zeilenende
 * entscheidet der Skin.
 * ------------------------------------------------------------------------- */
.g-oneline {
	border-block-start: 1px solid var(--g-rule-soft, currentColor);
}

.g-oneline__items {
	margin: 0;
	padding: 0;
	list-style: none;
}

.g-oneline__items > li {
	margin-block-start: 0;
}

.g-oneline__link {
	margin-block: 0;
}

/*
 * `justify-content: space-between` ist der ganze Trick: Der Titel steht links,
 * das Zeichen des Skins rechts, und dazwischen liegt der Rest der Spalte. Ohne
 * `min-inline-size: 0` am Titel sprengt eine lange Ueberschrift in einer
 * schmalen Spalte den Traeger — Flex-Kinder schrumpfen nicht unter ihre
 * Inhaltsbreite, solange man es ihnen nicht erlaubt.
 */
.g-oneline__link a {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--g-oneline-gap, 14px);
	min-block-size: var(--g-oneline-height, 56px);
	padding-block: var(--g-oneline-pad, 15px);
	text-decoration: none;
	min-inline-size: 0;
}

/* ===========================================================================
 * Die Fusszeile
 *
 * Vier Spalten ab dem einen Breakpoint, darunter eine. Der Markenblock links
 * ist breiter als die drei Linkspalten, die Themenspalte etwas breiter als die
 * beiden davor — sie traegt die laengsten Beschriftungen.
 *
 * HIER STEHT KEINE FARBE. Die Fusszeile des Entwurfs ist dunkel, und das ist
 * die groesste Farbentscheidung der ganzen Seite; sie gehoert trotzdem ins
 * Child. Der Parent gibt nur die Nahtstellen `--g-footer-bg` und
 * `--g-footer-text` her. Ohne Skin bleibt die Fusszeile hell und lesbar —
 * ein Fuss, der ohne Child schwarz auf schwarz stuende, waere eine Falle.
 *
 * DER GRUND DER SPALTENZAHL. Vier Spalten sind die Struktur, ihre Verhaeltnisse
 * sind Entwurf. Die Verhaeltniszahl steht deshalb als Rueckfall in
 * `--g-footer-columns` und im Child noch einmal als Wert — dieselbe Aufteilung
 * wie bei jedem anderen Mass dieser Datei.
 * ======================================================================== */
.g-footer {
	background: var(--g-footer-bg, var(--wp--preset--color--surface));
	color: var(--g-footer-text, inherit);
	padding: var(--g-footer-pad-top, 40px) var(--g-footer-pad-inline, 16px) var(--g-footer-pad-bottom, 28px);
}

.g-footer__inner {
	max-inline-size: var(--g-footer-width, 75rem);
	margin-inline: auto;
}

.g-footer__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-footer-grid-gap, 32px);
}

@media (min-width: 992px) {
	.g-footer__grid {
		grid-template-columns: var(--g-footer-columns, 1.5fr 1fr 1fr 1.3fr);
	}
}

/*
 * Cores Fluss-Layout haengt jedem nicht-ersten Kind denselben blockGap als
 * `margin-block-start` an. Der Entwurf gibt jeder Zeile stattdessen ihren
 * eigenen Abstand nach UNTEN; beides zusammen waere doppelt. Dieselbe Stelle
 * wie auf der Autorenseite.
 */
.g-footer__brand > *,
.g-footer__col > * {
	margin-block-start: 0;
}

.g-footer__mark {
	margin-block-end: var(--g-footer-mark-end, 14px);
	gap: var(--g-footer-mark-gap, 11px);
}

/*
 * Die Bildmarke wird an ihre HOEHE gebunden, nicht an ihre Breite — dieselbe
 * Stelle wie in der Kopfleiste, und aus demselben gemessenen Grund.
 *
 * GEMESSEN AM 2026-09-02: `wp:site-logo {"width":44}` hat auf dieses Logo
 * keine Wirkung. Die Datei ist ein SVG ohne Pixelmasse, und Core druckt dafuer
 * keine `width`/`height`-Attribute am `<img>`. Ergebnis war ein Logo von
 * 375 px Breite in der Fusszeile und 114 px waagerechter Ueberlauf auf JEDER
 * Seite bei 375 px Fensterbreite. Die Blockangabe bleibt trotzdem stehen: Sie
 * ist richtig und wirkt, sobald jemand ein Rasterbild einsetzt.
 *
 * `flex-shrink: 0` dazu, weil ein Bild als einziges Kind seiner Box in einer
 * Flex-Reihe sonst als Erstes nachgibt.
 */
.g-footer__mark .wp-block-site-logo,
.g-footer__mark .wp-block-site-logo img {
	block-size: var(--g-footer-logo-height, 44px);
	inline-size: auto;
	max-inline-size: none;
	flex-shrink: 0;
}

.g-footer__mark .wp-block-site-logo img {
	display: block;
}

/*
 * Ohne Slogan in den Einstellungen rendert `core/site-tagline` ein LEERES
 * Element. Das ist kein sichtbarer Text, aber ein Abstand — und darunter
 * sitzt der Knopf. Die Regel haelt die Spalte in dem Fall zusammen.
 */
.g-footer__claim:empty {
	display: none;
}

.g-footer__claim {
	max-inline-size: var(--g-footer-claim-width, 32ch);
	margin-block-end: var(--g-footer-claim-end, 18px);
}

/*
 * Der Knopf. Form, Farbe und Uebergang stehen im Child; hier steht die
 * Mindesthoehe, weil sie eine Bedienbarkeitsvorgabe ist und keine Gestaltung:
 * Die Pruefliste des Entwurfs verlangt 48 px, unabhaengig von der Marke.
 */
.g-footer__cta {
	display: inline-flex;
	align-items: center;
	gap: var(--g-footer-cta-gap, 10px);
	min-block-size: var(--g-footer-cta-height, 48px);
	padding: var(--g-footer-cta-pad-block, 12px) var(--g-footer-cta-pad-inline, 16px);
	text-decoration: none;
}

.g-footer__cta-zeichen {
	flex-shrink: 0;
}

.g-footer__col-title {
	margin-block-end: var(--g-footer-col-title-end, 12px);
}

/*
 * Die Linkspalte.
 *
 * `core/navigation` bringt seine Flex-Spalte selbst mit; hier wird nur der
 * Abstand gesetzt und die Aufzaehlung entlistet. Ohne die zweite Regel traegt
 * jeder Punkt Cores Listenpolster und die Spalte sitzt eingerueckt.
 */
.g-footer__nav {
	--wp--style--block-gap: 0;
}

.g-footer__nav .wp-block-navigation__container {
	gap: var(--g-footer-link-gap, 10px);
}

/*
 * Links in der Fusszeile erben ihre Farbe nicht von selbst: Cores Elementregel
 * `.wp-site-blocks a:where(:not(.wp-element-button))` sitzt direkt am `a` und
 * schlaegt jede geerbte Farbe. Sie ist 0,1,0 spezifisch, diese hier 0,1,1 und
 * gewinnt damit ohne `!important`. Dieselbe Stelle wie in der Kopfleiste.
 *
 * WELCHE Farbe, entscheidet das Child. Ohne Skin bleibt es `currentColor`,
 * also die Textfarbe des Fusses — nie unsichtbar.
 */
.g-footer a {
	color: var(--g-footer-link, currentColor);
	text-decoration: none;
}

.g-footer a:hover,
.g-footer a:focus-visible {
	color: var(--g-footer-link-hover, currentColor);
}

/*
 * UND FUER DIE MENUELINKS NOCH EINMAL, MIT MEHR GEWICHT.
 *
 * GEMESSEN AM 2026-09-02: Cores Navigationsblock setzt
 *
 *   .wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content { color: inherit }
 *
 * — die Klasse ist ABSICHTLICH verdoppelt und die Regel damit 0,3,0
 * spezifisch. Die beiden Regeln darueber (0,1,1 und 0,2,0) verlieren dagegen.
 * Im Ruhezustand faellt das nicht auf, weil `inherit` dieselbe Farbe liefert;
 * beim `:hover` blieb der Link stumpf stehen, und im Markup war davon nichts
 * zu sehen. Genau die Sorte Fehler, wegen der es `check-render.mjs` gibt.
 *
 * Diese Regeln sind 0,3,1 und 0,4,1 und gewinnen ohne `!important`.
 */
.g-footer .g-footer__nav a.wp-block-navigation-item__content {
	color: var(--g-footer-link, currentColor);
}

.g-footer .g-footer__nav a.wp-block-navigation-item__content:hover,
.g-footer .g-footer__nav a.wp-block-navigation-item__content:focus-visible {
	color: var(--g-footer-link-hover, currentColor);
}

/*
 * Die Schlusszeile. Umbrechend, weil drei Rechtsangaben nebeneinander auf
 * keinem Telefon Platz haben und keine davon wegfallen darf.
 */
.g-footer__legal {
	display: flex;
	flex-wrap: wrap;
	gap: var(--g-footer-legal-gap-row, 8px) var(--g-footer-legal-gap-col, 20px);
	margin-block-start: var(--g-footer-legal-start, 32px);
	padding-block-start: var(--g-footer-legal-pad, 18px);
	border-block-start: 1px solid var(--g-footer-rule, currentColor);
}

/*
 * Das Wortbild. Zwei Zeilen uebereinander, beide ohne Umbruch — auch bevor
 * die Schrift geladen ist. Ohne `white-space` bricht die erste Zeile in der
 * Ersatzschrift um und der Fuss springt beim Nachladen in der Hoehe.
 * Schriftschnitt, Groesse und Achsen stehen im Child.
 */
.g-wordmark {
	display: flex;
	flex-direction: column;
	margin: 0;
	flex-shrink: 0;
}

/*
 * IST DAS WORTBILD VERLINKT, IST DER LINK DER SPALTENTRAEGER.
 *
 * Ein Flex-Container blockifiziert nur seine eigenen Kinder. Steht der `<a>`
 * dazwischen — Kopfleiste, wo das Wortbild zur Startseite fuehrt —, bleiben die
 * zwei Zeilen darin inline und stehen NEBENEINANDER statt uebereinander. Ohne
 * diese Regel sieht die Kopfleiste aus wie vor dem Umbau.
 */
.g-wordmark > a {
	display: flex;
	flex-direction: column;
}

.g-wordmark__zeile {
	white-space: nowrap;
}

/*
 * Die zweite Zeile ist im Entwurf kursiv und zusaetzlich geschert. Die
 * Scherung braucht einen Ursprung links, sonst wandert die Zeile nach rechts
 * aus der Flucht der ersten. Der Wert der Scherung steht im Child.
 */
.g-wordmark__zeile--2 {
	transform-origin: left;
}

/* ===========================================================================
 * Die Startseite: Vertrauenszeile, Aufmacherzone, Kacheln, Fragenliste,
 * Methodikkasten und Autorenvorstellung
 *
 * STRUKTUR, KEINE MARKE. Hier stehen Raster, Reihenfolge und Abstandsrollen;
 * Farben, Schriftgroessen und die Werte des Entwurfs stehen im Skin. Jede
 * Zahl, die aus dem Entwurf stammt, kommt ueber ein `--g-`Token mit
 * Rueckfallwert — die Seite bleibt damit auch ohne Skin benutzbar.
 *
 * Ein Abschnitt ohne Inhalt erzeugt NICHTS. Die beiden Ankergruppen
 * (`g-hero-trust`, `g-rubriken`) verschwinden ueber `:empty`, wie die Anker
 * der Autorenseite und der Rubrikseite auch. Ein leerer Kasten mit
 * Ueberschrift waere schlimmer als eine fehlende Zusage.
 * ======================================================================== */

/* ---------------------------------------------------------------------------
 * Die Vertrauenszeile im Aufmacher (`g-hero-trust`)
 * ------------------------------------------------------------------------ */
.g-hero-trust {
	display: flex;
	flex-wrap: wrap;
	gap: var(--g-hero-trust-gap-row, 8px) var(--g-hero-trust-gap-col, 20px);
}

/* Niemand hat etwas angemeldet: kein Abstand, keine Zeile, keine Luecke. */
.g-hero-trust:empty {
	display: none;
}

.g-hero-trust__item {
	display: flex;
	align-items: center;
	gap: var(--g-hero-trust-icon-gap, 7px);
}

/* Das Zeichen darf nicht schrumpfen, wenn der Text daneben umbricht. */
.g-hero-trust__icon {
	flex-shrink: 0;
}

.g-hero-trust__text {
	/* Traegt im Skin nur Farbe und Groesse. Die Regel steht hier, damit die
	   Klasse auch ohne Skin eine hat und nicht als tot gilt. */
	text-underline-offset: 0.2em;
}

/* ---------------------------------------------------------------------------
 * Der Abschnitt mit Trennlinie (`g-abschnitt`)
 *
 * Der Entwurf trennt die Zonen der Startseite mit einer 2 px starken Linie in
 * der Textfarbe und nicht mit Weissraum allein. Ein Bauteil fuer alle drei
 * Stellen, damit nicht dreimal derselbe Strich anders breit ist.
 * ------------------------------------------------------------------------ */
.g-abschnitt {
	border-block-start: var(--g-abschnitt-rule, 2px) solid var(--g-rule-strong, currentColor);
	padding-block-start: var(--g-abschnitt-pad-top, 22px);
	padding-block-end: var(--g-abschnitt-pad-bottom, 36px);
}

.g-abschnitt__title {
	margin-block: 0 var(--g-abschnitt-title-end, 6px);
}

.g-abschnitt__intro {
	margin-block: 0 var(--g-abschnitt-intro-end, 4px);
	max-inline-size: var(--g-abschnitt-intro-width, 62ch);
}

/* ---------------------------------------------------------------------------
 * Die Aufmacherzone (`g-lead`)
 *
 * Einspaltig, ab 992 px der Aufmacher links und „Ebenfalls neu" rechts. Das
 * Verhaeltnis 1.45fr zu 1fr steht im Skin: Es ist eine Entwurfszahl.
 * ------------------------------------------------------------------------ */
.g-lead {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-lead-gap, 28px);
}

@media (min-width: 992px) {
	.g-lead {
		grid-template-columns: var(--g-lead-columns, 1.45fr 1fr);
	}
}

/* Der Aufmacher selbst ist EIN Link, wie die Karte und die Trefferzeile. Die
   Trefferflaeche liegt am Titel-Link und braucht diesen Bezugsrahmen. */
.g-lead__main {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--g-lead-main-gap, 14px);
}

/* Cores Fluss-Layout haengt jedem nicht-ersten Kind den blockGap an. Den
   Abstand traegt hier `gap`, sonst addieren sich beide. */
.g-lead__main > * {
	margin-block-start: 0;
}

.g-lead__media {
	margin-block: 0;
}

.g-lead__kicker {
	margin-block: 0;
}

.g-lead__title {
	margin-block: 0 var(--g-lead-title-end, 10px);
}

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

.g-lead__excerpt {
	margin-block: 0;
	max-inline-size: var(--g-lead-excerpt-width, 58ch);
}

.g-lead__excerpt p {
	margin-block: 0;
}

/* Kicker und Datum stehen im Entwurf auf EINER Zeile. Der Abstand nach unten
   haengt deshalb an der Zeile und nicht am Kicker: An beiden wuerde er sich
   addieren und die Ueberschrift abrutschen lassen. */
.g-lead__meta {
	display: flex;
	align-items: center;
	gap: var(--g-lead-meta-gap, 10px);
	flex-wrap: wrap;
	margin-block: 0 var(--g-lead-meta-end, 8px);
}

.g-lead__meta > * {
	margin-block: 0;
}

/* Ohne Aufmacher (kein klebriger Beitrag) bleibt die linke Spalte leer. Dann
   soll „Ebenfalls neu" die Breite nehmen und nicht neben einem Loch stehen. */
@media (min-width: 992px) {
	.g-lead:not(:has(.g-lead__main)) {
		grid-template-columns: 1fr;
	}
}

/* ---------------------------------------------------------------------------
 * „Ebenfalls neu" (`g-newsline`)
 *
 * KEIN ZWEITES ZEILENFORMAT. Die Zeilen sind die Trefferzeile der Suche
 * (`patterns/search-result.php`) in einem anderen Traeger: derselbe Rahmen,
 * dieselbe Bewegung, dieselben Klassen. Hier stehen nur die drei
 * Unterschiede, die der Entwurf an dieser Stelle zeigt.
 *
 * Sie sind bewusst am TRAEGER notiert und nicht am Bauteil: Wer die
 * Trefferzeile aendert, aendert beide Orte mit; wer diesen Traeger entfernt,
 * bekommt wieder die Trefferzeile und keinen Rest.
 * ------------------------------------------------------------------------ */
.g-newsline {
	display: flex;
	flex-direction: column;
	gap: var(--g-newsline-gap, 12px);
}

.g-newsline__label {
	margin-block: 0;
}

/* 1. Bild RECHTS und auf jeder Breite neben dem Text, nicht erst ab 992 px. */
.g-newsline .g-search-hit {
	grid-template-columns: 1fr var(--g-newsline-media, 92px);
	align-items: center;
}

.g-newsline .g-search-hit__body {
	grid-column: 1;
	grid-row: 1;
}

.g-newsline .g-search-hit__media,
.g-newsline .g-search-hit__mark {
	grid-column: 2;
	grid-row: 1;
}

/*
 * 2. Das Seitenverhaeltnis. `!important` ist hier kein Notflicken, sondern
 * die einzige Moeglichkeit: `core/post-featured-image` druckt das Verhaeltnis
 * INLINE an die `<figure>` (`style="aspect-ratio:16/9;"`, gemessen an WP 6.9),
 * und eine Kontextregel kommt dagegen sonst nicht an. Der Entwurf verlangt an
 * dieser Stelle 92 x 62 und nicht 16/9.
 */
.g-newsline .g-search-hit__media {
	aspect-ratio: var(--g-newsline-media-ratio, 92 / 62) !important;
}

.g-newsline .g-search-hit__mark {
	aspect-ratio: var(--g-newsline-media-ratio, 92 / 62);
}

/*
 * 3. Kein Auszug und keine Metazeile. Der Entwurf zeigt die Zeile hier mit
 * Kicker und Titel; ein Auszug in 92 px Nachbarschaft ergaebe vier Zeilen
 * Text neben einem Daumennagel. `display: none` und nicht ein zweites Muster
 * ohne Auszug — die Frage „ein Bauteil oder zwei" ist damit nicht neu
 * gestellt.
 */
.g-newsline .g-search-hit__excerpt,
.g-newsline .g-search-hit__meta {
	display: none;
}

/* ---------------------------------------------------------------------------
 * Die Rubrik-Kachelnavigation (`g-rubriken`)
 *
 * Die Spaltenzahl kommt als `--g-rubriken-spalten` aus `inc/front-page.php`:
 * `repeat()` verlangt eine ganze Zahl, und die kennt nur die Stelle, die die
 * Kacheln zaehlt.
 * ------------------------------------------------------------------------ */
.g-rubriken {
	border-block-start: 1px solid var(--g-rule-soft, currentColor);
	padding-block: var(--g-rubriken-pad-top, 22px) var(--g-rubriken-pad-bottom, 34px);
}

/*
 * Zwei Ruecknahmen, und die zweite ist die wichtigere: `:empty` faengt den
 * Anker ohne Inhalt, `:has()` den Anker MIT Ueberschrift und ohne Kacheln.
 * Der zweite Fall ist der reale — die Ueberschrift „Wonach suchst du?" steht
 * in der Vorlage, die Kacheln kommen aus der Datenbank. Ohne die zweite Regel
 * stuende eine Frage ueber einer leeren Flaeche.
 */
.g-rubriken:empty,
.g-rubriken:not(:has(.g-rubrik-kachel)) {
	display: none;
}

.g-rubriken__label {
	margin-block: 0 var(--g-rubriken-label-end, 14px);
}

.g-rubriken__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--g-rubriken-gap, 10px);
}

@media (min-width: 992px) {
	.g-rubriken__grid {
		grid-template-columns: repeat(var(--g-rubriken-spalten, 6), minmax(0, 1fr));
	}
}

.g-rubrik-kachel {
	display: flex;
	align-items: center;
	gap: var(--g-rubrik-kachel-gap, 10px);
	min-block-size: var(--g-rubrik-kachel-height, 56px);
	padding: var(--g-rubrik-kachel-pad-block, 12px) var(--g-rubrik-kachel-pad-inline, 14px);
}

.g-rubrik-kachel__icon {
	flex-shrink: 0;
}

.g-rubrik-kachel__text {
	min-inline-size: 0;
}

/* ---------------------------------------------------------------------------
 * „Kurz erklaert" (`g-faqlist`)
 *
 * Sechs Zeilen, ab 992 px zweispaltig. Der Pfeil rechts steht als `::after`
 * und nicht im Markup: Er ist Zierat und traegt keine Bedeutung — im Dokument
 * waere er ein Zeichen, das Vorleseprogramme mitsprechen.
 * ------------------------------------------------------------------------ */
.g-faqlist {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0 var(--g-faqlist-gap-col, 32px);
}

@media (min-width: 992px) {
	.g-faqlist {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.g-faqlist__item {
	margin-block: 0;
}

.g-faqlist__item a {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--g-faqlist-inner-gap, 14px);
	min-block-size: var(--g-faqlist-height, 56px);
	padding-block: var(--g-faqlist-pad-block, 16px);
	border-block-end: 1px solid var(--g-rule-soft, currentColor);
}

.g-faqlist__item a::after {
	content: "→";
	flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
 * Der dunkle Sprechkasten (`g-method`)
 *
 * ER GEHOERT NICHT DER STARTSEITE. Sein erster Ort war der Methodikkasten,
 * daher der Name; dieselben Werte tragen den Finanzierungskasten der Seite
 * „Ueber uns". Ein zweiter Name mit denselben Zahlen waere ein zweiter Stand.
 * Das Raster (`g-method__grid`) ist optional — ein Kasten aus Titel, Intro
 * und Knopf ist vollstaendig.
 *
 * KEIN `scroll-margin-top` AN DIESER STELLE. Der Sprungversatz steht einmal
 * an der Wurzel als `scroll-padding-top` (siehe oben in dieser Datei). Beides
 * zusammen addiert sich lautlos — am 2026-09-02 landete ein Sprung dadurch
 * 208 px tief statt 104.
 * ------------------------------------------------------------------------ */
.g-method {
	border-radius: var(--g-method-radius, 16px);
	padding: var(--g-method-pad-block, 28px) var(--g-method-pad-inline, 22px);
	margin-block-end: var(--g-method-end, 36px);
}

.g-method__title {
	margin-block: 0 var(--g-method-title-end, 8px);
}

.g-method__intro {
	margin-block: 0 var(--g-method-intro-end, 22px);
	max-inline-size: var(--g-method-intro-width, 62ch);
}

.g-method__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-method-grid-gap-row, 20px) var(--g-method-grid-gap-col, 26px);
	margin-block-end: var(--g-method-grid-end, 24px);
}

@media (min-width: 992px) {
	.g-method__grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

.g-method__item {
	border-block-start: 1px solid var(--g-rule-soft, currentColor);
	padding-block-start: var(--g-method-item-pad-top, 14px);
}

.g-method__item > * {
	margin-block-start: 0;
}

.g-method__item-title {
	margin-block: 0 var(--g-method-item-title-end, 6px);
}

.g-method__item-text {
	margin-block: 0;
}

.g-method__cta .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* Der Abstand gilt nur, wenn der Knopf ein Zeichen traegt. Ohne Zeichen
	   hat `gap` an einem einzigen Kind keine Wirkung. */
	gap: var(--g-method-cta-gap, 10px);
	min-block-size: var(--g-method-cta-height, 48px);
}

/* ---------------------------------------------------------------------------
 * Die Autorenvorstellung (`g-authors`)
 *
 * Der Anker wird vom Toolkit-Feature `Author_Profile` gefuellt. Ohne einen
 * einzigen veroeffentlichten Beitrag bleibt er leer und verschwindet.
 *
 * `auto-fit` UND NICHT ZWEI FESTE SPALTEN: Der Entwurf zeigt zwei Autoren,
 * diese Instanz hat einen. Bei festen zwei Spalten stuende eine Karte
 * halbbreit neben einem Loch. Mit `auto-fit` fuellt einer die Zeile, zwei
 * teilen sie, drei brechen um — ohne dass jemand eine Zahl nachfuehrt.
 * ------------------------------------------------------------------------ */
/* Derselbe Fall wie bei den Kacheln: Die Ueberschrift „Wer hier schreibt"
   steht in der Vorlage, die Karten kommen aus der Datenbank. Ohne einen
   einzigen veroeffentlichten Beitrag faellt der ganze Abschnitt weg. */
.g-authors:empty,
.g-abschnitt:has(> .g-authors:empty) {
	display: none;
}

.g-authors__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-authors-gap, 14px);
}

@media (min-width: 992px) {
	.g-authors__grid {
		grid-template-columns: repeat(auto-fit, minmax(var(--g-author-card-min, 320px), 1fr));
	}
}

.g-author-card {
	display: flex;
	gap: var(--g-author-card-gap, 15px);
	padding: var(--g-author-card-pad-block, 18px) var(--g-author-card-pad-inline, 20px);
}

/*
 * Der Traeger UND was darin steht. Beide Zeilen sind noetig, und die zweite ist
 * die, die gefehlt hat: Steht im Kreis kein Bild, sondern die Initiale, kommt
 * sie als `g-author-figure__initials` — derselbe Anker wie auf der Autorenseite,
 * und der misst sich an `--g-author-figure-size` (88px). Der Traeger blieb 52px,
 * die Initiale darin wurde 88 und lag mit `overflow: hidden` beschnitten und
 * verrutscht im Kreis. Gemessen am 2026-09-04: 52x52 gegen 88x88, Ueberlappung
 * 2704 px². Dieselbe Zuweisung steht bei `.g-side-author` und aus demselben
 * Grund; hier hat sie gefehlt.
 */
.g-author-card__figure {
	display: grid;
	place-items: center;
	inline-size: var(--g-author-card-figure, 52px);
	block-size: var(--g-author-card-figure, 52px);
	--g-author-figure-size: var(--g-author-card-figure, 52px);
	border-radius: 50%;
	flex-shrink: 0;
	overflow: hidden;
}

.g-author-card__figure img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
}

.g-author-card__body {
	min-inline-size: 0;
}

.g-author-card__name {
	margin-block: 0;
}

.g-author-card__text {
	margin-block: var(--g-author-card-text-start, 3px) var(--g-author-card-text-end, 8px);
}

.g-author-card__link {
	display: inline-block;
}

/* ===========================================================================
 * Die Seite „Ueber uns"
 *
 * STRUKTUR, KEINE MARKE. Raster, Reihenfolge, Abstandsrollen und
 * Trefferflaechen; Groessen und Farben kommen ueber `--g-`Token aus dem Skin.
 * Der TEXT dieser Seite steht in keinem der beiden geerbten Repos — er ist
 * projekteigen und wird von einem Instanzskript in die Seite geschrieben.
 *
 * DREI DER FUENF ABSCHNITTE SIND WIEDERVERWENDUNG UND KEIN NEUES BAUTEIL:
 *
 *   - Die Kopfzone ist `g-term-head` / `g-term-title`. Sie heisst nach ihrem
 *     ersten Ort, ist aber laengst das Seitenkopf-Bauteil dieses Themes —
 *     `templates/home.html` benutzt sie fuer eine Seite ohne Term.
 *   - Die Redaktion ist die Autorenvorstellung (`g-authors`), dieselbe
 *     Ankergruppe wie auf der Startseite. Das Toolkit fuellt sie.
 *   - Der Finanzierungskasten ist `g-method`, derselbe dunkle Sprechkasten wie
 *     auf der Startseite. Ein zweiter Name mit denselben Werten waere ein
 *     zweiter Stand: Wer den einen aendert, uebersieht den anderen.
 *
 * Neu ist hier nur das Gegenueber „Was wir machen / Was wir nicht machen"
 * (`g-pledges`) und die Rechtsliste.
 * ======================================================================== */
.g-about > * {
	margin-block-start: 0;
}

/*
 * Die Ueberschriften der Seite. Die GROESSE steht im Skin und ist dieselbe wie
 * bei `g-abschnitt__title` und `g-method__title`; hier steht nur der Abstand,
 * den der Entwurf dieser Seite gibt.
 */
.g-about__title {
	margin-block: 0 var(--g-about-title-end, 16px);
}

/*
 * Cores Fluss-Layout haengt JEDEM nicht-ersten Kind denselben blockGap als
 * `margin-block-start` an. Unter einer Ueberschrift, die ihren Abstand selbst
 * traegt, ist das der zweite Abstand fuer dieselbe Luecke — der groessere
 * gewinnt, und der Wert des Entwurfs gilt nicht mehr.
 *
 * NUR das direkte Geschwister der Ueberschrift, nicht alle Kinder: Im
 * Fliesstext darunter sind Cores Abstaende genau richtig.
 */
.g-about__title + * {
	margin-block-start: 0;
}

.g-about__section {
	margin-block-end: var(--g-about-section-end, 40px);
}

/*
 * Ein Abschnitt, dessen einziger Inhalt ein leerer Anker ist, hinterlaesst
 * KEINE Spur — dieselbe Regel wie auf der Startseite. Ohne sie stuende
 * „Die Redaktion" ueber dem Nichts, sobald niemand etwas veroeffentlicht hat.
 */
.g-about__section:has(> .g-authors:empty) {
	display: none;
}

/*
 * Der Fliesstext bekommt seine Zeilenlaenge selbst.
 *
 * Die Seite steht im breiten Traeger, damit Kopfzone und Gegenueber an
 * derselben Kante beginnen wie ueberall sonst. Ein langer Text ueber 75 rem
 * liest niemand; die Breite gehoert deshalb an den Text und nicht an den
 * Traeger. Derselbe Fall wie bei `g-hero__lead`.
 *
 * DIE GRENZE STEHT SEIT DEM 2026-09-04 AN DEN KINDERN UND NICHT AM ABSCHNITT.
 * Vorher war der Abschnitt selbst 656 px breit, waehrend jeder andere Abschnitt
 * derselben Seite 1200 misst — zwei Breiten auf einer Seite, und der schmale
 * war ausgerechnet das Sprungziel `#so-arbeiten-wir`. Der Abschnitt ist jetzt so
 * breit wie die uebrigen, die Zeilenlaenge bleibt dieselbe.
 *
 * KEINE FLAECHE UND KEIN RADIUS, und das ist keine Auslassung: Nach der
 * Kaesten-Regel bekommen nur TL;DR, Callout, Kauf-Check und Autorenkasten eine
 * Flaeche, hoechstens einer je Bildschirmhoehe. Ein Kasten um vier
 * Bildschirmhoehen Fliesstext, direkt unter dem dunklen `g-method`, waere der
 * zweite dunkle Kasten in Folge und der groesste der Seite.
 */
.g-about__prose > * {
	max-inline-size: var(--g-about-prose-width, 41rem);
}

/* ---------------------------------------------------------------------------
 * Die Grundsaetze des Abschnitts „So arbeiten wir" (`g-about__principles`)
 *
 * Form, Masse und das Plus/Minus stehen OBEN beim Aufklapper; hier steht nur,
 * was diesem Ort eigen ist.
 *
 * DREI BEDINGUNGEN AUS DEM AUFTRAG, DIE MAN IM CSS WIEDERFINDEN MUSS, WEIL
 * SONST JEMAND SIE „AUFRAEUMT":
 *
 *   1. Die Einleitung („Kurz gesagt: …") steht VOR der Liste und klappt nicht.
 *      Ein Transparenztext, dessen Kern man wegklicken kann, ist keiner.
 *   2. Jede Zusammenfassung nennt den Grundsatz vollstaendig. Deshalb ist sie
 *      eine Ueberschrift und kein Stichwort.
 *   3. Der erste Grundsatz steht offen (`open` im Markup). Man muss sehen,
 *      was hinter dem Aufklappen steckt.
 * ------------------------------------------------------------------------- */

/*
 * Die Ueberschrift IM `<summary>`.
 *
 * `font: inherit` und nicht eigene Werte: Die Zusammenfassung traegt ihre
 * Schrift schon (Skin), und zwei Orte fuer dieselbe Groesse laufen
 * auseinander. Die `h3` ist hier eine Auszeichnung fuer die Gliederung, keine
 * zweite Gestaltung.
 *
 * `min-inline-size: 0`: Als Flex-Kind schrumpft sie sonst nicht unter ihre
 * laengste Zeile, und bei 375px schoebe sie das Plus aus dem Kasten.
 */
.g-about__principle-title {
	margin-block: 0;
	font: inherit;
	color: inherit;
	min-inline-size: 0;
}

/*
 * Der Abstand VOR der Liste. Die Einleitung darueber ist ein Absatz und
 * bringt Cores Fliessabstand mit; die Liste braucht ihren eigenen, weil sie
 * mit einer Linie beginnt und eine Linie dicht unter einem Satz wie ein
 * Unterstrich aussieht.
 */
.g-about__principles {
	margin-block-start: var(--g-about-principles-start, 28px);
}

/*
 * Der Inhalt eines aufgeklappten Grundsatzes ist Fliesstext und keine
 * Blockliste — er steht als rohes HTML im Seiteninhalt und bekommt deshalb
 * KEINEN `blockGap` von Core. Die Abstaende muessen von hier kommen.
 */
.g-about__principle-answer > :last-child {
	margin-block-end: 0;
}

.g-about__principle-answer ul,
.g-about__principle-answer ol {
	margin-block: 0 var(--g-term-faq-answer-end, 18px);
}

/*
 * KEIN `scroll-margin-top` AN DEN ABSCHNITTEN. Der Sprungversatz steht einmal
 * an der Wurzel als `scroll-padding-top` (oben in dieser Datei). Beides
 * zusammen addiert sich lautlos — am 2026-09-02 landete ein Sprung dadurch
 * 208 px tief statt 104. Der Anker `#so-arbeiten-wir` dieser Seite haengt an
 * genau dieser einen Zahl.
 */

/* ---------------------------------------------------------------------------
 * Das Gegenueber: „Was wir machen" und „Was wir nicht machen" (`g-pledges`)
 *
 * ZWEI SPALTEN ERST AB 992 px, darunter untereinander. Mobil-zuerst wie
 * ueberall; der eine Breakpoint dieses Systems steht in dieser Datei.
 *
 * Die beiden Seiten unterscheiden sich im Markup durch einen Modifikator und
 * nicht durch eine zweite Bauart: `g-pledge--positive` und
 * `g-pledge--negative` tragen im Skin ihre Farbe. NIE KONTEXT ALLEIN UEBER
 * FARBE — die Ueberschrift sagt es, das Vorzeichen sagt es, die Farbe
 * bestaetigt es.
 * ------------------------------------------------------------------------ */
/*
 * DERSELBE FALL, UND ER WAR IM BILD ZU SEHEN: Ohne diese Zeile bekommt die
 * zweite Spalte Cores blockGap als `margin-block-start` und beginnt 21 px
 * tiefer als die erste. Im Markup steht davon nichts; die beiden Spalten sind
 * gleich gebaut.
 */
.g-pledges > * {
	margin-block-start: 0;
}

.g-pledges {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-pledges-gap, 26px);
}

@media (min-width: 992px) {
	.g-pledges {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.g-pledge > * {
	margin-block-start: 0;
}

.g-pledge__title {
	display: flex;
	align-items: center;
	gap: var(--g-pledge-title-gap, 9px);
	margin-block: 0 var(--g-pledge-title-end, 12px);
}

.g-pledge__list {
	list-style: none;
	margin-block: 0;
	padding-inline-start: 0;
	display: flex;
	flex-direction: column;
	gap: var(--g-pledge-gap, 10px);
}

.g-pledge__item {
	display: flex;
	gap: var(--g-pledge-item-gap, 10px);
	padding-block-end: var(--g-pledge-item-pad, 10px);
	border-block-end: 1px solid var(--g-rule-soft, currentColor);
}

/* Der letzte Punkt schliesst die Liste ab und braucht keine Linie unter sich —
   sie waere ein Strich zwischen Liste und nichts. */
.g-pledge__item:last-child {
	padding-block-end: 0;
	border-block-end: 0;
}

/* Das Vorzeichen steht NEBEN dem Satz, nie statt seiner. Es darf nicht
   schrumpfen, sonst rutscht es bei langen Woertern in den Text. */
.g-pledge__sign {
	flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
 * Die Rechtsliste (`g-legal-nav`)
 *
 * EINE QUELLE, NICHT ZWEI: Das ist derselbe `core/navigation`-Block wie in der
 * Fusszeile, ueber dieselbe Platzklasse (`g-nav--fuss`) an dasselbe Menue
 * gebunden. Eine von Hand gepflegte zweite Liste waere ein zweiter Stand
 * derselben Rechtslinks — und genau die veraltet.
 *
 * Die 44 px sind eine Trefferflaeche und keine Gestaltung: Ein Link in einer
 * Liste, die auf dem Telefon getippt wird, braucht sie.
 * ------------------------------------------------------------------------ */
.g-legal-nav .wp-block-navigation__container {
	gap: var(--g-legal-nav-gap, 2px);
}

.g-legal-nav .wp-block-navigation-item__content {
	display: flex;
	align-items: center;
	min-block-size: var(--g-legal-nav-height, 44px);
}

/* ---------------------------------------------------------------------------
 * Die Dachzeile in der Ueberschrift (`g-post-kicker`)
 *
 * Sie steht IM `<h1>` und muss trotzdem eine eigene Zeile bilden — deshalb
 * `display: block`. Groesse, Sperrung und Farbe sind Marke und stehen im Skin.
 *
 * Der Trenner ist der ganze Zweck des Bauteils: Vorlesesoftware soll „Epomaker
 * TH108 Pro Test: Die Full-Size Custom-Tastatur" als EINEN Satz lesen. Er steht
 * deshalb im Text und wird hier NUR versteckt — nicht mit `display: none`, das
 * naehme ihn auch der Vorlesesoftware weg, und dann waere er sinnlos.
 * ------------------------------------------------------------------------ */
.g-post-kicker {
	display: block;
}

.g-post-kicker__separator {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* ---------------------------------------------------------------------------
 * Das Aufmacherbild (`g-post-image`)
 *
 * DER ZUSCHNITT STEHT SEIT DEM 2026-09-03 HIER UND NICHT AM BLOCK. Vorher trug
 * `core/post-featured-image` ein `aspectRatio` im Blockattribut; Core schreibt
 * das als INLINE-Stil an das `<img>`, und ein Inline-Stil schlaegt jede Regel
 * aus einem Stylesheet. Ein zweites Verhaeltnis fuer den Desktop war damit
 * nicht zu haben — die Regel wurde ausgeliefert und blieb wirkungslos.
 *
 * `object-fit` gehoert dazu und nicht daneben: Ohne es wuerde das Bild im
 * gesetzten Verhaeltnis verzerrt statt beschnitten.
 * ------------------------------------------------------------------------ */
.g-post-image img {
	display: block;
	inline-size: 100%;
	aspect-ratio: var(--g-post-image-ratio, 16 / 9);
	object-fit: cover;
}

.g-post-image__caption {
	display: block;
	margin-block-start: var(--g-post-image-caption-start, 8px);
}


@media (min-width: 992px) {
	/* Der Entwurf zeigt den Aufmacher ab dem Breakpoint breiter und flacher.
	   Das Bild liegt in 2560 x 1440 vor, der 21/9-Zuschnitt hat also genug
	   Bildpunkte. */
	.g-post-hero .g-post-image {
		--g-post-image-ratio: 21 / 9;
	}
}

/* Der Abstand UNTER dem Aufmacher entsteht nicht an der Kopfzone, sondern als
   Blockabstand des `main`-Flusses am folgenden Geschwister (gemessen 21px, der
   Entwurf zeigt 26). Gesetzt wird er deshalb dort, wo er entsteht: Ein zweiter
   Abstand an der Kopfzone addierte sich lautlos dazu. */
.g-post-hero + .g-article-grid {
	margin-block-start: var(--g-post-hero-end, 26px);
}

/* ---------------------------------------------------------------------------
 * Die seitlich scrollende Tabelle (`g-table-scroll`)
 *
 * Der Traeger kommt aus `inc/table-scroll.php` und haelt zwei Dinge zusammen,
 * die denselben Rand brauchen: den Hinweis und die scrollende `<figure>`.
 *
 * DER AUSBRUCH IST DIE EINZIGE STELLE, AN DER DIE LESESPALTE VERLASSEN WIRD.
 * Er benutzt die beiden Werte, die oben neben den Rasterspuren stehen, und
 * gilt erst ab dem Breakpoint — darunter gibt es keine Gasse, in die etwas
 * ausbrechen koennte.
 *
 * WAS ER NICHT DARF: die Seite waagerecht scrollen lassen. Dagegen steht die
 * Rechnung selbst — `--g-breakout-end` haengt an `50vw` und laesst 16px
 * Seitenrand stehen, auch wenn das Fenster schmaler wird als das Raster.
 * ------------------------------------------------------------------------ */
.g-table-scroll {
	margin-block: var(--g-table-scroll-block, 0);
}

/*
 * DER KOPF: Beschriftung links, Bedienhinweis rechts.
 *
 * Er ist erst am 2026-09-03 entstanden, und zwar aus einem Fehler: Die
 * Beschriftung der Tabelle stand als `<figcaption>` INNERHALB des
 * Bildlaufbereichs und wanderte beim ersten Wischen mit nach links aus dem
 * Bild. Eine Beschriftung, die man wegschieben kann, beschriftet nichts. Der
 * Hinweis stand aus demselben Grund von Anfang an aussen; jetzt teilen sich
 * beide eine Zeile.
 *
 * `align-items: baseline`: Zwei Texte verschiedener Groesse (12 und 12,5 px)
 * sitzen sonst mittig zueinander und stehen dann beide leicht daneben.
 *
 * Der Hinweis haelt sich mit `margin-inline-start: auto` rechts. `justify-
 * content: space-between` allein reichte NICHT: Eine Tabelle ohne
 * Beschriftung haette den Hinweis dann links stehen, und genau der Fall ist
 * der Normalfall im Bestand.
 */
.g-table-scroll__head {
	display: flex;
	align-items: baseline;
	gap: var(--g-table-scroll-head-gap, 12px);
	margin: 0 0 var(--g-table-scroll-hint-end, 10px);
}

.g-table-scroll__caption {
	margin: 0;
}

.g-table-scroll__hint {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: var(--g-table-scroll-hint-gap, 6px);
	margin: 0;
	margin-inline-start: auto;

	/*
	 * GEMESSEN bei 375 px: „seitlich wischen" brach zwischen die beiden
	 * Woerter, und der Pfeil stand allein neben dem zweiten. Der Hinweis ist
	 * zwei Woerter lang; die Beschriftung daneben darf umbrechen, er nicht.
	 */
	white-space: nowrap;
}

/* Das Zeichen steht NEBEN dem Wort, nie statt seiner. */
.g-table-scroll__arrow {
	flex-shrink: 0;
}

@media (min-width: 992px) {
	.g-article-grid__main .g-table-scroll {
		margin-inline-start: var(--g-breakout-start, 0px);
		margin-inline-end: var(--g-breakout-end, 0px);
	}
}

/* ---------------------------------------------------------------------------
 * Der Beitragsverlauf (`g-changelog`)
 *
 * Ein `<details>`: Das Auf und Zu bringt der Browser mit, ohne eine Zeile
 * JavaScript. Der Kopf traegt Beschriftung links und die Zusammenfassung
 * daneben; das Vorzeichen setzt der Skin als `::after`, weil es Dekoration ist.
 *
 * `list-style: none` UND `::-webkit-details-marker`: Das eine entfernt das
 * Dreieck in Firefox, das andere in aelteren WebKit-Fassungen. Nur eines von
 * beiden laesst den Marker auf einem der beiden stehen.
 * ------------------------------------------------------------------------ */
.g-changelog__box {
	border-block: 1px solid var(--g-rule-soft, currentColor);
}

.g-changelog__summary {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--g-changelog-summary-gap, 10px);
	min-block-size: var(--g-changelog-summary-height, 52px);
	padding-block: var(--g-changelog-summary-pad, 14px);
	cursor: pointer;
	list-style: none;
}

.g-changelog__summary::-webkit-details-marker {
	display: none;
}

.g-changelog__title {
	flex: 0 0 auto;
}

.g-changelog__count {
	flex: 1 1 auto;
}

.g-changelog__list {
	margin: 0;
	padding: 0 0 var(--g-changelog-list-end, 14px);
	list-style: none;
}

.g-changelog__item {
	display: flex;
	gap: var(--g-changelog-item-gap, 14px);
	padding-block: var(--g-changelog-item-pad, 11px);
	border-block-start: 1px solid var(--g-changelog-item-rule, var(--g-rule-soft, currentColor));
}

/* Das Datum bricht nicht um: Eine Datumsangabe ueber zwei Zeilen liest sich
   als zwei Angaben. */
.g-changelog__date {
	flex-shrink: 0;
	white-space: nowrap;
}

.g-changelog__text {
	flex: 1 1 auto;
}

/* Die Art steht IM Satz und nicht als eigene Spalte — sie ist der Anfang des
   Satzes und kein Merkmal daneben. */
.g-changelog__kind {
	margin-inline-end: 0.25em;
}

/* ---------------------------------------------------------------------------
 * Der Untertitel der Lesetipps (`g-related__subheading`)
 *
 * Er steht zwischen Ueberschrift und Liste und gehoert zur Ueberschrift, nicht
 * zur Liste: Deshalb kein Abstand nach oben, sondern nur nach unten.
 * ------------------------------------------------------------------------ */
.g-related__subheading {
	margin: 0 0 var(--g-related-subheading-end, 20px);
}

/* ---------------------------------------------------------------------------
 * Die Lesetipps (`g-related__list`)
 *
 * HIER STEHT KEIN RASTER MEHR, und das ist der ganze Punkt.
 *
 * Bis zum 2026-09-03 hatte dieser Ort eine eigene Anatomie: Bild links,
 * Kicker und Titel rechts, ab dem Breakpoint nebeneinander. Sie war die
 * zweite Kartenform des Themes, und sie sah anders aus als jede Uebersicht
 * derselben Seite — vier Eintraege, jeder so hoch wie sein Titel, teils mit
 * Bild und teils ohne.
 *
 * Seither rendert `inc/related-cards.php` das Muster `goblin-base/post-card`
 * und haengt der Liste `g-post-grid__items` an. Das Raster kommt damit von
 * dort (eine Spalte, ab 992 px drei gleiche), und hier bleibt nur, was eine
 * `<ul>` in jedem Fall braucht.
 *
 * Die Ruecknahme muss GESCHRIEBEN werden: `<ul>` bringt Punkte und Einzug vom
 * Browser mit, und `g-post-grid__items` nimmt sie nicht zurueck — es steht in
 * Archiv und Suche an einer Liste, die Core schon zurueckgesetzt hat.
 * ------------------------------------------------------------------------ */
.g-related__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Cores Fluss-Layout haengt jedem nicht-ersten Kind den blockGap als
   `margin-block-start` an; im Raster versetzte das die Zeilen gegeneinander.
   Den Abstand traegt allein `gap`. */
/*
 * Die gleiche Hoehe braucht hier KEINE eigene Regel, und das ist Absicht: Das
 * Rasterfeld streckt sich ohnehin auf die Zeilenhoehe, und `.g-post-card`
 * traegt `height: 100%`. Es ist derselbe Weg wie im Archiv, also dieselbe
 * Karte und nicht eine, die zufaellig gleich aussieht.
 */
.g-related__item {
	margin-block-start: 0;
}

/* ---------------------------------------------------------------------------
 * Die Rueckfallebene: die eigene Zeile des Toolkits
 *
 * UND SIE IST KEIN THEORETISCHER FALL. `goblin_base_post_card_html()` gibt
 * eine leere Zeichenkette zurueck, wenn das Muster `goblin-base/post-card`
 * nicht registriert ist — WordPress cacht die Muster eines Themes, und direkt
 * nach einer Aenderung an `patterns/` ist genau das der Zustand (siehe
 * `design/bestand/stufe0/REGELN.md`). Dann rendert das Toolkit wieder seine
 * eigene Zeile, und die braucht eine Anatomie.
 *
 * Was hier steht, ist deshalb bewusst das MINDESTE: Bild, Kicker, Titel
 * untereinander, ab dem Breakpoint nebeneinander. Keine Marke, keine Kante,
 * kein Radius — der Skin gestaltet die Karte, nicht diesen Rueckfall.
 * ------------------------------------------------------------------------ */
.g-related__link {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--g-related-item-gap, 14px);
}

@media (min-width: 992px) {
	.g-related__link {
		grid-template-columns: var(--g-related-media, 200px) 1fr;
	}

	/* Ohne Bild gibt es keine erste Spalte. Eine leere 200-px-Spalte waere ein
	   Einzug ohne Grund, und bildlose Beitraege gibt es hier wirklich. */
	.g-related__link:not(:has(> .g-related__thumb)) {
		grid-template-columns: 1fr;
	}
}

.g-related__thumb {
	display: block;
	inline-size: 100%;
	block-size: auto;
	aspect-ratio: var(--g-related-thumb-ratio, 16 / 9);
	object-fit: cover;
}

/* `min-inline-size: 0` ist der Rasterschutz: Ein Rasterfeld hat als
   Mindestbreite seinen Inhalt, und ein langer Titel schoebe die Bildspalte
   sonst aus der Zeile. */
.g-related__body {
	display: block;
	min-inline-size: 0;
}

.g-related__kicker,
.g-related__name {
	display: block;
}

.g-related__kicker {
	margin-block-end: var(--g-related-kicker-gap, 5px);
}
