/*
 * Goblin Toolkit — Struktur.
 *
 * Hier steht ausschliesslich, was ein Bauteil zum Funktionieren braucht:
 * Positionierung, Schichtung, Sichtbarkeit, Verschachtelung. Keine Farbe,
 * kein Rahmen, keine Schrift, kein Schatten — die Gestaltung liefert in P2
 * das Theme gegen `theme.json`-Variablen.
 *
 * ## Der Breakpoint steht nicht in dieser Datei
 *
 * Diese Datei ist mobile-first und enthaelt **keine** Breiten-Media-Query.
 * (Die eine Abfrage weiter unten fragt `prefers-reduced-motion` ab — eine
 * Benutzereinstellung, keine Viewport-Breite.) Die eine
 * Regel, die vom Layout-Breakpoint abhaengt, erzeugt `Toc::breakpoint_css()`
 * und haengt sie ueber `wp_add_inline_style()` an dieses Stylesheet an. Grund:
 * Eine CSS-Custom-Property kann in `@media (min-width: …)` nicht stehen, ein
 * fest verdrahteter Wert waere in einem zweiten Projekt mit anderem Layout
 * stumm falsch — es gaebe eine Breite mit zwei Verzeichnissen oder eine ganz
 * ohne. Der Wert kommt deshalb aus dem Filter
 * `goblin_toolkit/toc/breakpoint`, Voreinstellung `992px`: der eine
 * Viewport-Breakpoint von `goblin-base` (`assets/css/layout.css`), an dem das
 * Seitenlayout von einspaltig auf Inhalt + Seitenleiste umschaltet.
 *
 * ## Schichtung
 *
 * `goblin-base` legt die klebende Kopfleiste auf `z-index: 20` und die
 * klebende Seitenleiste auf `1`. Die mobile Inhaltsleiste liegt mit `19`
 * zwischen beiden: ueber Inhalt und Seitenleiste, aber unter der
 * Kopfleistenpille, unter der sie haengt.
 */

/* ------------------------------------------------------------------
 * Inhaltsverzeichnis — Liste
 * ------------------------------------------------------------------ */

.g-toc__list {
	list-style: none;
	margin: 0;
	padding-inline-start: 0;
}

/*
 * Die Einrueckung der tieferen Ebene ist Struktur, nicht Schmuck: Sie ist die
 * sichtbare Entsprechung der Verschachtelung im Markup.
 */
.g-toc__list .g-toc__list {
	padding-inline-start: 1em;
}

/* ------------------------------------------------------------------
 * Ausspielung 1 — Seitenleiste
 * ------------------------------------------------------------------ */

/*
 * Unterhalb des Layout-Breakpoints stapelt sich die Seitenleiste **hinter**
 * den Beitrag. Ein Inhaltsverzeichnis, das erst nach dem gesamten Text kommt,
 * hat keinen Zweck mehr — und neben der mobilen Inhaltsleiste stuende es ein
 * zweites Mal da. Das ist kein Gestaltungsurteil: Es geht darum, dass eine der
 * drei Ausspielungen sonst an einer Stelle steht, an der sie nichts leistet.
 *
 * Die Gegenregel ab dem Breakpoint kommt aus `Toc::breakpoint_css()`.
 */
.g-toc__nav--sidebar {
	display: none;
}

/*
 * DIE SCHIENE DES AKTIVEN EINTRAGS.
 *
 * Jeder Eintrag traegt links eine 2 px breite, DURCHSICHTIGE Kante. Sie ist
 * kein Schmuck, sondern reservierter Platz: Faerbte der Skin sie erst beim
 * aktiven Eintrag ein und gaebe es sie vorher nicht, ruckte bei jedem Wechsel
 * des Abschnitts der ganze Text um zwei Pixel zur Seite. Genau so stand es bis
 * zum 2026-09-03 im Skin dieses Projekts (`padding-inline-start` nur an
 * `.is-active`).
 *
 * HIER STEHT KEINE FARBE — `transparent` ist keine, sondern die Abwesenheit
 * einer. WELCHE Farbe die Schiene im aktiven Zustand traegt und ob noch ein
 * zweites Merkmal dazukommt, entscheidet der Skin. Es MUSS ein zweites geben:
 * Kontext nie allein ueber Farbe.
 */
.g-toc__link {
	display: block;
	border-inline-start: var(--g-toc-rail, 2px) solid transparent;
	padding-block: var(--g-toc-item-pad-block, 7px);
	padding-inline: var(--g-toc-item-pad-inline, 12px) 0;
}

/*
 * Ein ausgezeichneter Eintrag stellt Zeichen und Titel nebeneinander. Nur die
 * Anordnung steht hier; Farbe und Gewicht kommen aus dem Skin. `flex-shrink`
 * am Zeichen, weil ein langer Titel es sonst zusammendrueckt statt umzubrechen.
 *
 * DAS ZEICHEN HAENGT IN DEN INNENABSTAND UND RUECKT DEN TITEL NICHT EIN.
 *
 * Vorher stand es IM Textblock: Der ausgezeichnete Eintrag begann damit als
 * einziger 28 px weiter rechts als die acht anderen, und in einer 232 px
 * schmalen Spalte kostete ihn das eine ganze Zeile. Eine Auszeichnung, die
 * eine Kante verschiebt, macht aus einer Liste zwei.
 *
 * Der Zug nach links ist genau so gross wie das, was das Zeichen im Fluss
 * belegt (`Groesse + Luecke`) — abgeleitet und nicht als zweite Zahl
 * hingeschrieben, sonst laufen beide beim naechsten Wert auseinander.
 *
 * UND ER HAT EINE GRENZE, DIE MAN NICHT SIEHT: `Groesse + Luecke` darf
 * `--g-toc-item-pad-inline` nicht ueberschreiten. Die Seitenleiste traegt
 * `overflow-y: auto` (der Rueckfall der klebenden Spalte, siehe
 * `goblin-base/assets/css/layout.css`), und sobald eine Achse nicht mehr
 * `visible` ist, rechnet der Browser die andere auf `auto` — was links aus
 * der Spalte ragt, ist ABGESCHNITTEN. GEMESSEN am 2026-09-03: Mit 16 px
 * Zeichen und 7 px Luecke stand vom Schild ein Rest von 7 px da, und im
 * Markup war davon nichts zu sehen.
 */
.g-toc__link--marked {
	display: flex;
	align-items: center;
	gap: var(--g-toc-icon-gap, 7px);
}

.g-toc__link--marked .g-toc__icon {
	flex: 0 0 auto;

	/*
	 * Die Groesse ist eine Nahtstelle. Ohne sie erbt das Zeichen die 1,5em
	 * aus `base.css` und stuende neben 14-px-Text mit 21 px da — groesser als
	 * die Zeile, die es begleitet.
	 */
	--g-icon-size: var(--g-toc-icon-size, 1.125rem);
}

/*
 * DER ZUG NACH LINKS GILT NUR IN DER SEITENLEISTE, und die Begruendung oben
 * sagt auch warum: Sie ist die schmale Spalte, in der eine eingerueckte Zeile
 * aus einer Liste zwei macht, und sie ist die mit `overflow-y: auto`.
 * Im Textfluss und in der mobilen Leiste ist keines von beidem so — dort steht
 * das Zeichen im Fluss vor dem Titel, wie der Entwurf es zeigt.
 */
.g-toc__nav--sidebar .g-toc__link--marked .g-toc__icon {
	/*
	 * DIE SCHIENENBREITE IST TEIL DES ZUGS. Ohne sie sass das Zeichen im
	 * Innenabstand und begann 2 px rechts von der Schiene, die alle anderen
	 * Eintraege im aktiven Zustand zeigen — zwei Kanten dicht nebeneinander,
	 * die dasselbe meinen. Mit ihr steht das Zeichen genau dort, wo sonst die
	 * Schiene steht. Der ausgezeichnete Eintrag traegt deshalb nie eine
	 * (Regel im Skin): An einem Ort passt nur ein Merkmal.
	 *
	 * Der Titel bleibt an seiner Kante, weil die Schiene als durchsichtige
	 * Kante stehen bleibt und nur ihre Farbe entfaellt. Waere sie auf 0
	 * gesetzt, ruckte die Zeile um 2 px.
	 */
	margin-inline-start: calc( -1 * ( var(--g-toc-icon-size, 1.125rem) + var(--g-toc-icon-gap, 7px) + var(--g-toc-rail, 2px) ) );

	/*
	 * UND GENAU SO VIEL WIEDER ZURUECK. Ein negativer Aussenabstand zieht
	 * nicht nur das Zeichen, sondern alles dahinter: GEMESSEN stand der Titel
	 * des ausgezeichneten Eintrags danach bei 132 statt 134, also 2 px links
	 * von den acht anderen. Genau die Schienenbreite. Eine Auszeichnung, die
	 * eine Kante verschiebt, macht aus einer Liste zwei — dieselbe Falle wie
	 * beim Zug selbst, nur an der anderen Seite des Zeichens.
	 */
	margin-inline-end: var(--g-toc-rail, 2px);
}

/* ------------------------------------------------------------------
 * Ausspielung 1a — die Kurzfassung beim Lesen
 * ------------------------------------------------------------------ */

/*
 * Der Knopf wird vom Skript erzeugt. Ohne JavaScript gibt es ihn nicht — dann
 * steht das Verzeichnis vollstaendig da, was die richtige Rueckfallebene ist.
 *
 * Was hier steht, ist Verhalten, nicht Gestaltung: sichtbar/unsichtbar,
 * Umbruchverhalten, Scrollbarkeit. Wie der Knopf AUSSIEHT, entscheidet das
 * Theme.
 */
/*
 * ZWEI ZEILEN UNTEREINANDER, NICHT ZWEI SPALTEN.
 *
 * Nebeneinander teilten sich Titel und Zaehler eine 232 px schmale Spalte:
 * Der Zaehler kuerzt nie, also blieb dem Titel, was uebrig war, und das war
 * je nach Abschnitt verschieden viel. Gestapelt bekommt der Titel die ganze
 * Breite und der Zaehler steht darunter, wo er nichts wegnimmt.
 */
.g-toc__current {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	inline-size: 100%;
	gap: var(--g-toc-current-gap, 2px);
	text-align: start;
}

/*
 * DER TITEL HAT EINE FESTE HOEHE, und das ist der ganze Zweck.
 *
 * Die Kurzfassung wechselt beim Scrollen ihren Text. Waechst der Kasten dabei
 * mit, springt die ganze klebende Seitenleiste bei jedem Abschnittswechsel —
 * und zwar genau dann, wenn der Blick woanders ist. Deshalb zwei Zeilen
 * IMMER: `min-block-size` haelt die Hoehe bei kurzem Text, `line-clamp`
 * schneidet langen nach derselben Zahl ab. Ein Wert, zwei Zeilen.
 *
 * Abgeschnitten wird an der Zeile, nicht im Wort: `line-clamp` setzt die
 * Auslassungspunkte hinter das letzte ganze Wort der letzten Zeile.
 *
 * `1lh` und keine gerechnete Zeilenhoehe: Die Zeilenhoehe entscheidet der
 * Skin, und eine zweite Zahl hier waere beim naechsten Wert falsch.
 */
.g-toc__current-text {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--g-toc-current-lines, 2);
	line-clamp: var(--g-toc-current-lines, 2);
	overflow: hidden;
	min-block-size: calc( var(--g-toc-current-lines, 2) * 1lh );
	inline-size: 100%;
	min-inline-size: 0;
}

/* Die Positionsangabe kuerzt nie: Sie ist der Ersatz fuer die ganze Liste. */
.g-toc__current-count {
	flex: 0 0 auto;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

.g-toc__nav--sidebar.is-collapsed .g-toc__list {
	display: none;
}

/*
 * UND DIE GEGENRICHTUNG: Steht die Liste offen, verschwindet der Titel.
 *
 * Er beantwortet dieselbe Frage wie der hervorgehobene Eintrag — „in welchem
 * Abschnitt stehe ich" —, und zwei Antworten auf eine Frage sind eine zu
 * viel. Der ZAEHLER bleibt: „1 von 9" ist die einzige Angabe, die die Liste
 * selbst nicht macht, und er ist einzeilig, also kein zweiter Block.
 * Weisung des Auftraggebers vom 2026-09-03.
 *
 * `display: none` WAERE HIER FALSCH. Der Titel ist der halbe Name des
 * Knopfes; ohne ihn hiesse der Umschalter fuer eine Vorlesesoftware nur noch
 * „1 von 9". Also sichtbar weg und im Zugaenglichkeitsbaum drin — dieselbe
 * Technik, mit der die mobile Ausspielung ihre Beschriftung versteckt.
 *
 * Und `position: absolute` und nicht `visibility: hidden`: Der Titel muss
 * seinen Platz RAEUMEN. Bliebe die feste Hoehe von zwei Zeilen stehen, staende
 * ueber der offenen Liste ein leerer Streifen.
 */
.g-toc__nav--sidebar:not( .is-collapsed ) .g-toc__current-text {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	min-block-size: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
}

/*
 * Aufgeklappt scrollt die Liste in sich selbst. Ohne diese Grenze waere im
 * offenen Zustand genau das Hoehenproblem zurueck, gegen das die Kurzfassung
 * gebaut ist — die ganze Seitenleiste klebt, und was ueber den Fensterrand
 * hinausragt, waere unerreichbar.
 *
 * `--g-toc-list-max` ist die Nahtstelle. Ein Projekt, das das Verzeichnis
 * lieber immer vollstaendig zeigt und in Kauf nimmt, dass sein Ende unter dem
 * Fensterrand liegt, setzt sie auf `none`; ohne Grenze scrollt
 * `overflow-y: auto` nie. Es ist eine Abwaegung und keine Struktur, deshalb
 * steht sie nicht fest.
 */
.g-toc__nav--sidebar:not( .is-collapsed ) .g-toc__list {
	max-block-size: var( --g-toc-list-max, 60dvh );
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* ------------------------------------------------------------------
 * Ausspielung 2 — die Inline-Box im Textfluss
 * ------------------------------------------------------------------ */

/*
 * SIE IST DAS VERZEICHNIS UNTERHALB DES BREAKPOINTS, und das ist der Grund,
 * warum sie hier ueberhaupt eine Regel bekommt.
 *
 * Bis zum 2026-09-03 hatte sie keine. Auf einer Vorlage mit Seitenleiste
 * (`single.html`) stand sie gar nicht im Markup, die Seitenleisten-Ausspielung
 * war mobil `display: none`, und die Inhaltsleiste erscheint erst, wenn der
 * Leser das Verzeichnis im Textfluss passiert hat — also nie, wenn es keines
 * gibt. Gemessen bei 375 px: kein bedienbares Verzeichnis auf der ganzen
 * Seite. Die Gegenregel ab dem Breakpoint kommt aus `Toc::breakpoint_css()`.
 *
 * Hier steht Anordnung, keine Gestaltung: Rahmen, Schrift und das Zeichen am
 * Aufklapper gehoeren dem Theme.
 */
/*
 * `list-style: none` UND `::-webkit-details-marker` weiter unten, weil es zwei
 * Mechanismen sind: Der erste greift in Firefox und in Chromium ab 89, der
 * zweite in aelteren WebKit-Fassungen. Wer nur einen schreibt, hat auf der
 * Haelfte der Geraete zwei Zeichen nebeneinander — das des Browsers und das
 * des Themes.
 */
.g-toc__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--g-toc-summary-gap, 10px);
	cursor: pointer;
	list-style: none;
}

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

/* ------------------------------------------------------------------
 * Ausspielung 3 — die mobile Inhaltsleiste
 * ------------------------------------------------------------------ */

/*
 * GEAENDERT am 2026-09-01. Hier standen `.g-toc-toggle` (schwebender Knopf
 * unten rechts) und `.g-toc-overlay` (modaler Dialog). Der Entwurf sieht mobil
 * eine Leiste unter der Kopfleiste vor, die erscheint, sobald das Verzeichnis
 * im Textfluss nach oben weggescrollt ist.
 *
 * Die Leiste steht `fixed` unter der Kopfleiste. WO das ist, weiss allein das
 * Layout: `--g-header-offset` (goblin-base/assets/css/layout.css, mobil 92 px,
 * ab 992 px 104 px). Der Rueckfall 92px greift nur, wenn das Parent-Stylesheet
 * fehlt — dieselbe Zahl ein zweites Mal hinzuschreiben waere der Anfang des
 * Auseinanderlaufens.
 *
 * Schichtung: unter der Kopfleistenpille (z-index 20 in `goblin-base`), ueber
 * der klebenden Seitenleiste (1) und ueber dem Inhalt.
 */
.g-toc-mobile {
	position: fixed;
	inset-block-start: var(--g-header-offset, 92px);
	inset-inline: 0;
	z-index: 19;
}

/*
 * Die Leiste entsteht erst im Skript; `hidden` im Markup ist der Ladezustand
 * ohne JavaScript und der Zustand „noch nicht weggescrollt". Deshalb steht
 * `display` hier ausdruecklich hinter `:not([hidden])` — eine unbedingte
 * `display`-Regel wuerde das Attribut aushebeln, weil `[hidden]` nur aus dem
 * Browser-Stylesheet kommt und jeder Autorenregel unterliegt.
 */
.g-toc-mobile:not([hidden]) {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

/*
 * Dieselbe Falle, eine Ebene weiter: `skin.css` laedt nach diesem Stylesheet
 * (Prioritaet 30) und gestaltet `.g-toc-bar`. Eine `display`-Regel dort wuerde
 * die verborgene Leiste dauerhaft sichtbar machen — sie klebte dann von der
 * ersten Zeile an unter der Kopfleiste. Darum hier `!important`: Es verteidigt
 * einen Zustand, keine Gestaltung.
 */
.g-toc-mobile[hidden] {
	display: none !important;
}

/*
 * Der Abschnittstitel kuerzt einzeilig; der Knopf behaelt seine Groesse.
 *
 * `flex-basis: 0` UND NICHT `auto`, und das ist der Unterschied zwischen einer
 * Leiste und zwei Zeilen: Der Traeger traegt `flex-wrap: wrap` (die Liste
 * klappt darunter auf). In einem umbrechenden Traeger verteilt der Browser die
 * Teile ANHAND IHRER HYPOTHETISCHEN GROESSE auf Zeilen und schrumpft sie erst
 * DANACH. Mit `auto` ist die hypothetische Groesse die volle Titellaenge, der
 * Titel bekam eine eigene Zeile, und der Knopf rutschte darunter — GEMESSEN am
 * 2026-09-03 bei 375 px: Kopf 373 px breit, Leiste 71 statt 48 px hoch. Das
 * `text-overflow: ellipsis` darunter griff trotzdem und sah deshalb richtig
 * aus.
 */
.g-toc-bar__head {
	flex: 1 1 0;
	min-inline-size: 0;
	display: flex;
	align-items: center;
	margin: 0;
}

.g-toc-bar__text {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-inline-size: 0;
}

.g-toc-bar__toggle {
	flex: 0 0 auto;
}

/*
 * Die Liste klappt UNTER der Leiste auf, nicht daneben — deshalb die eigene
 * Zeile im Flex-Umbruch. `55dvh` ist der Wert aus dem Entwurf, hier als
 * Scrollgrenze: Ohne sie waere ein zwoelfteiliges Verzeichnis unten aus dem
 * Fenster heraus unerreichbar. `dvh` und nicht `vh`, weil die Adressleiste
 * mobiler Browser mitwandert.
 */
.g-toc__nav--mobile {
	flex: 1 0 100%;
	max-block-size: 55dvh;
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* ------------------------------------------------------------------
 * Die Autorenkarte in der Spalte
 * ------------------------------------------------------------------ */

/*
 * `assets/js/toc.js` setzt diese Klasse an die Autorenkarte in der klebenden
 * Spalte, sobald der Autorenkasten im Beitrag im Viewport steht.
 *
 * `display: none` und nicht `visibility` oder `opacity`: Der Entwurf ist hier
 * ausdruecklich, und der Grund ist eine Messung — unsichtbar, aber im Fluss,
 * bleibt zwischen zwei Haarlinien eine leere Flaeche stehen.
 *
 * `!important`, weil die Karte aus `goblin-base` kommt und das Theme sie
 * gestaltet: Jede `display`-Regel des Skins auf derselben Spezifitaet laedt
 * spaeter und gewaenne. Ohne Skript wird die Klasse nie gesetzt, die Karte
 * bleibt also stehen — diese Regel richtet allein nichts an.
 */
.g-toc-away {
	display: none !important;
}

/* ------------------------------------------------------------------
 * Pruefzeile in der Seitenleiste
 * ------------------------------------------------------------------ */

/*
 * Zeichen und Satz in einer Reihe. Die Zeile hat keine eigene Linie und keinen
 * eigenen Abstand — beides gehoert zur Seitenleiste und steht in
 * `goblin-base/assets/css/layout.css` an `.g-reviewed-side`.
 *
 * `align-items: center` und nicht `baseline`: Das Zeichen ist ein Quadrat ohne
 * Schriftlinie, an einer Grundlinie ausgerichtet haengt es zu tief.
 */
.g-reviewed-side__line {
	display: flex;
	align-items: center;
	gap: var(--g-reviewed-side-gap, 8px);
	margin: 0;
}

.g-reviewed-side__icon {
	flex: 0 0 auto;
}

/* Ohne das sprengt eine lange Beschriftung die schmale Spalte statt
   umzubrechen — dieselbe Zeile wie an der Einzeilerliste, aus demselben
   Grund. */
.g-reviewed-side__text {
	min-inline-size: 0;
}

/* Ziffern gleicher Breite. Das Datum steht im Entwurf in einer Spalte mit dem
   Veroeffentlichungsdatum der Metabox; springende Ziffernbreiten liessen die
   beiden Zeilen gegeneinander wandern. Kein Gestaltungsurteil, sondern ein
   Ausrichtungsproblem. */
.g-reviewed-side__date {
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------
 * Lesezeit
 * ------------------------------------------------------------------ */

/*
 * Die Lesezeit steht in `g-post-meta` neben Datum und Autor, in einem
 * Flex-Layout mit Umbruch. Zahl und Einheit gehoeren zusammen: Ein Umbruch
 * zwischen "6" und "Minuten Lesezeit" macht aus einer Angabe zwei Fetzen.
 * Das ist Umbruchverhalten, keine Gestaltung — wie die Angabe aussieht,
 * entscheidet in P2 das Theme.
 */
.g-reading-time__value {
	white-space: nowrap;
}

/* ------------------------------------------------------------------
 * Lesefortschritt
 * ------------------------------------------------------------------ */

/*
 * Die Schiene liegt an der OBERKANTE DES VIEWPORTS.
 *
 * GEAENDERT am 2026-09-01. Hier stand `inset-block-start:
 * var(--wp--custom--nav-height, 5rem)` — der Balken sass unter einer
 * Kopfleiste, die im Fluss stand und 80 px hoch war.
 *
 * Das trifft nicht mehr zu: `goblin-base` baut die Kopfleiste seither als
 * **schwebende Pille** mit 12 px Abstand nach oben, und sie ist damit gar
 * nicht mehr die Oberkante. Ein Balken unter ihr laege mitten im Inhalt.
 *
 * Der Entwurf dieses Projekts sagt es ausdruecklich: „Lesefortschritt: 3 px
 * hohe Linie an der **Oberkante des Viewports**." Das ist auch der Ort, an dem
 * ein Fortschrittsbalken ueberall sonst im Web sitzt — die Ausnahme war die
 * alte Fassung, nicht diese.
 *
 * `--g-progress-top` bleibt als Stellschraube: Ein Theme mit einer Leiste im
 * Fluss setzt sie auf deren Hoehe und bekommt das alte Verhalten zurueck, ohne
 * diese Datei zu aendern.
 *
 * `z-index: 19` liegt knapp **unter** der Kopfleiste von `goblin-base` (20)
 * und ueber der klebenden Seitenleiste (1). Unter der Kopfleiste, weil die
 * Pille den Balken an ihrer Stelle verdecken darf; ueber der Seitenleiste,
 * weil er sonst darunter verschwaende.
 *
 * Keine Breitenabfrage: Die Regel gilt auf jeder Breite gleich.
 */
.g-progress {
	position: fixed;
	inset-block-start: var(--g-progress-top, 0);
	inset-inline: 0;
	z-index: 19;
	block-size: var(--g-progress-height, 0.25rem);
	pointer-events: none;
	overflow: hidden;
}

/*
 * Cores Kappung der Anker-Gruppe aufheben — **die** Regel, ohne die dieses
 * Bauteil nicht funktioniert. Sie steht bewusst allein, mit doppelter Klasse.
 *
 * Die Anker-Gruppe ist `layout: constrained`. Core druckt dafuer
 * (`wp-includes/block-supports/layout.php`, Zweig `'constrained'`):
 *
 *   .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
 *       max-width: var(--wp--style--global--content-size);
 *       margin-left: auto !important;
 *       margin-right: auto !important;
 *   }
 *
 * Das trifft **jedes** Kind, auch ein `position: fixed` — `max-width` und
 * `margin` wirken unabhaengig von `position`. In `goblin-base` ist
 * `content-size` 46rem; gemessen in `wp-dev-lab` war die Schiene deshalb
 * 736 statt 1440 px breit und sass mittig ueber der Inhaltsspalte.
 *
 * **Zwei Feinheiten, an denen ein Nachbau scheitert:**
 *
 * 1. Cores Margin traegt `!important` und ist **physisch** (`margin-left` /
 *    `margin-right`). Ein `margin-inline: 0` ohne `!important` ueberstimmt sie
 *    nicht. Es steht hier deshalb nicht: Bei `inset-inline: 0` und
 *    `inline-size: auto` bleibt nichts zu verteilen, und die `auto`-Margins
 *    rechnen sich ohnehin zu 0. **Wer seiner Ausgabe eine explizite
 *    `inline-size` gibt, muss die Margin mit `!important` zurueckholen** —
 *    sonst zentriert Core sie wieder.
 * 2. Cores Selektor hat wegen `:where()` die Spezifitaet 0-1-0, genau wie eine
 *    einfache Klasse hier. Es entschiede die Quellreihenfolge — heute
 *    zugunsten des Toolkits, morgen nicht mehr, sobald Layout-Stile spaeter
 *    gedruckt werden (eine im Editor gesetzte `contentSize` am Anker-Block
 *    ueber `wp_enqueue_block_support_styles`, ein Optimierungsplugin, das CSS
 *    umordnet). Die doppelte Klasse macht daraus 0-2-0 und beendet die Frage.
 */
.g-progress.g-progress {
	max-inline-size: none;
}

/*
 * Der innere Balken traegt die Breite. `scaleX` statt einer Prozentbreite —
 * das laeuft im Compositor, siehe `assets/js/progress-bar.js`. Der Ursprung
 * liegt am Zeilenanfang, damit der Balken in einem RTL-Layout von rechts
 * waechst.
 *
 * **Hier steht keine Farbe.** Global Constraint: Kein Feature setzt eine
 * Farbe. Sichtbar wird der Balken erst, wenn `goblin-base` in P2
 * `.g-progress__bar` einen Hintergrund gibt — bis dahin ist er
 * vorhanden, gemessen und transparent. Siehe Bericht zu Task 6.
 *
 * Der Startwert `scaleX(0)` steht im Stylesheet und nicht im Markup: Ohne ihn
 * stuende der Balken zwischen dem Aufbau der Seite und dem ersten Lauf des
 * verzoegerten Skripts einen Wimpernschlag lang auf voller Breite.
 */
.g-progress__bar {
	block-size: 100%;
	inline-size: 100%;
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 100ms linear;
}

.g-progress__bar:dir(rtl) {
	transform-origin: right center;
}

/*
 * Springen darf er, animieren nicht. `prefers-reduced-motion` ist eine
 * Benutzerabfrage, keine Breitenabfrage — der Global Constraint gegen
 * `max-width`-Abfragen ist davon nicht beruehrt.
 */
@media (prefers-reduced-motion: reduce) {
	.g-progress__bar {
		transition: none;
	}
}

/* ------------------------------------------------------------------
 * Kurzfassung — bewusst ohne Regel
 * ------------------------------------------------------------------ */

/*
 * `.g-tldr__heading` und `.g-tldr__text` stehen hier absichtlich
 * nicht. Die Kurzfassung ist eine Ueberschrift und ein Absatz in der
 * Anker-Gruppe des Themes; deren Layout (`is-layout-constrained`) und deren
 * Abstaende liefert das Theme. Es gibt nichts, was die Bauteile zum
 * Funktionieren braeuchten — Abstand, Rahmen und Schrift sind Gestaltung und
 * kommen in P2. Eine Regel hier waere eine, die das Theme spaeter
 * ueberschreiben muesste.
 *
 * Folge fuer die Assets: `Tldr` haengt dieses Stylesheet nicht ein. Eine Datei
 * zu laden, deren Regeln auf nichts zeigen, ist derselbe Fehler wie sie zu
 * laden, wenn gar nichts erscheint.
 */

/* ------------------------------------------------------------------
 * Autorenprofil — Liste der Netzwerke
 * ------------------------------------------------------------------ */

/*
 * Nur Struktur: Eine Liste von Links soll nebeneinander stehen und umbrechen
 * duerfen, statt als Aufzaehlung untereinander. Mehr braucht das Bauteil nicht,
 * um zu funktionieren.
 *
 * Keine Farbe, keine Schriftgroesse, keine Icons — das ist Gestaltung und kommt
 * mit P2. Der Abstand haengt an `--wp--style--block-gap` und damit am Theme;
 * fehlt die Variable, greift der Rueckfall.
 *
 * Mobile-first und ohne Breitenabfrage: `flex-wrap` loest dasselbe Problem wie
 * ein Umbruchpunkt, nur ohne eine Breite zu erfinden.
 *
 * Eingehaengt wird dieses Stylesheet von `Author_Profile` **nicht**: Wo die
 * Liste im Frontend erscheint, entscheidet P2. Solange sie nirgends steht,
 * gaebe es nichts zu gestalten — und ein Stylesheet fuer nichts zu laden ist
 * derselbe Fehler wie bei der Kurzfassung weiter oben.
 */
.g-author-profiles {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--style--block-gap, 0.75rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.g-author-profiles__item {
	margin: 0;
}

/* ------------------------------------------------------------------
 * Autorenbild
 * ------------------------------------------------------------------ */

/*
 * Die Initialen-Grafik erbt ihre Farbe ueber `currentColor`. Damit sie das
 * ueberhaupt kann, muss sie inline im Dokument stehen — als `<img src="data:…">`
 * ist das SVG ein eigenes Dokument und `currentColor` loest dort auf die
 * Vorgabe des Browsers auf, nicht auf die Farbe der Umgebung. Siehe Bericht zu
 * Task 7; die Entscheidung, wie das Theme damit umgeht, faellt in P2.
 *
 * Hier steht deshalb nur, was ohnehin gilt: Ein Autorenbild ist quadratisch und
 * skaliert mit seinem Kasten.
 */
.g-avatar__preview {
	max-inline-size: 100%;
	block-size: auto;
	aspect-ratio: 1;
}

/* ------------------------------------------------------------------
 * KI-Hinweis am Beitragsbild
 * ------------------------------------------------------------------ */

/*
 * Eine Bildunterschrift unter dem Bild — mehr ist das nicht, und mehr steht
 * hier auch nicht. Keine Farbe (Global Constraint): Ob der Hinweis
 * zurueckgenommen oder hervorgehoben wirkt, entscheidet P2 im Theme.
 *
 * **`flex-basis` ist kein Zierrat.** Der Hinweis ist ein Geschwister des
 * Beitragsbild-Blocks und erbt damit dessen Traeger. In `single.html` und
 * `single-review.html` ist das eine `constrained`-Gruppe, in `single-wide.html`
 * das `main`-Element — dort steht er ohnehin unter dem Bild. Aber der Traeger
 * gehoert dem Theme: Stellt die Redaktion die Gruppe im Site-Editor auf
 * „Zeile", stuende der Hinweis **neben** dem Bild statt darunter. Genau das ist
 * im Bestand des Auftraggebers schon passiert. `flex-basis: 100%` zwingt ihn in
 * einem Flex-Traeger in die naechste Zeile und ist ausserhalb eines solchen
 * wirkungslos — die Regel kostet also nichts, wo sie nicht gebraucht wird.
 *
 * Der Abstand nach oben ist klein und der nach unten null: Der Hinweis gehoert
 * optisch zum Bild, nicht zum folgenden Text. Die Werte kommen aus den
 * Presets von `theme.json`; die Rueckfallwerte greifen nur in einem Theme, das
 * die Presets nicht setzt.
 */
.g-ai-notice {
	flex-basis: 100%;
	margin-block-start: var(--wp--preset--spacing--2-xs, 0.5rem);
	margin-block-end: 0;
	font-size: var(--wp--preset--font-size--xs, 0.875rem);
	/*
	 * Zeilenumbrueche sind erlaubt: Der Text ist redaktionell und kann in
	 * einem zweiten Projekt deutlich laenger sein als „KI-generierte
	 * Darstellung". Ein `nowrap` schoebe ihn dann aus dem Kasten.
	 */
	text-wrap: pretty;
}

/* ------------------------------------------------------------------
 * Nachladen statt Blaettern
 *
 * Struktur, keine Gestaltung: Der Knopf bekommt hier weder Farbe noch
 * Rahmen. Er ist ein Link, und wie ein Link in diesem Projekt aussieht,
 * entscheidet das Theme. Was hier steht, ist das, was ohne Regel kaputt
 * waere — die Zentrierung und ein Platzhalter, der ueberhaupt Platz
 * einnimmt.
 * ------------------------------------------------------------------ */
.g-load-more {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--wp--preset--spacing--xs, 0.5rem);
}

/*
 * Die Ansage ist fuer Vorlesesoftware und nicht fuer das Auge. Sie wird
 * **nicht** mit `display: none` versteckt — das nimmt sie aus dem
 * Zugaenglichkeitsbaum, und dann sagt sie nichts mehr. Das hier ist die
 * uebliche Technik: da, messbar, aber nicht sichtbar.
 */
.g-load-more__status {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
	border: 0;
}

/*
 * Platzhalterkarten waehrend des Ladens. Die Hoehe ist geraten und darf
 * geraten sein: Sie soll verhindern, dass der Fuss nach oben springt,
 * und nicht die echte Karte nachbauen.
 */
.g-post-card--placeholder {
	min-height: 12rem;
	border-radius: inherit;
	background: currentColor;
	opacity: 0.08;
	list-style: none;
}

/*
 * Waehrend geladen wird, bleibt das Raster bedienbar, aber es sagt an,
 * dass es sich aendert. Mehr als das gehoert nicht hierher.
 *
 * GEAENDERT am 2026-09-02 (BL56): Hier stand `.g-post-grid__items`, also der
 * Name EINER Uebersicht. Seit die Vorlage ihren Rasternamen selbst nennt, gibt
 * es mehrere — die Trefferliste der Suche heisst `g-search-hits`. Also haengt
 * die Regel jetzt am Zustand und nicht am Namen.
 *
 * WARUM EINE EIGENE KLASSE UND NICHT `[aria-busy="true"]`. Das Attribut setzt
 * nicht nur dieses Skript; Core und Plugins benutzen es ebenfalls. Ein
 * unqualifizierter Attributselektor aus einem Plugin-Stylesheet griffe dann in
 * fremde Bauteile. Die Klasse setzt das Skript zusammen mit `aria-busy` und
 * nimmt sie zusammen mit ihm wieder weg.
 */
.g-load-more-busy {
	cursor: progress;
}

/*
 * Verborgen heisst verborgen.
 *
 * Das Skript setzt `hidden` auf die Blaetter-Navigation. Das allein reicht
 * **nicht**: Core gibt fuer jeden Flex-Layout-Block eine eigene Regel aus
 * (`.wp-container-core-query-pagination-is-layout-…{display:flex}`), und die
 * schlaegt das `[hidden]{display:none}` des Browsers, weil eine Klasse
 * spezifischer ist als ein Elementtyp. Gemessen: `hidden === true` im DOM und
 * die Seitenzahlen trotzdem sichtbar, neben dem Knopf.
 *
 * Kein `!important`. Zwei Selektoren sind spezifischer als Cores einer —
 * das genuegt, und zwar unabhaengig von der Reihenfolge der Stylesheets.
 */
.g-pagination[hidden] {
	display: none;
}
