/*
Theme Name: duo-2026
Theme URI: https://www.direktundonline.de
Author: direkt + online GmbH
Author URI: https://www.direktundonline.de
Description: Eigenes Block-Theme fuer den Neubau von www.direktundonline.de (Stil C). Kein
  Elementor, keine externen Nachladungen -- Montserrat ist lokal als woff2 eingebettet.
Version: 0.19.0
Requires at least: 6.5
Requires PHP: 8.0
Tested up to: 6.6
Text Domain: duo-2026
*/

/*
 * Montserrat, lokal eingebettet -- Herkunft siehe LOGBUCH.md (Thema "Theme-Geruest duo-2026").
 * Statische Schnitte aus der variablen Achse Montserrat[wght] von github.com/google/fonts,
 * ofl/montserrat/, SIL Open Font License 1.1 (Lizenztext: assets/fonts/OFL.txt), lokal mit
 * fonttools auf 300/400/500/600/700 instanziiert, auf Latin (inkl. Latin-1 Supplement und
 * Interpunktion/Waehrungszeichen) subsetted und nach woff2 konvertiert. Kein Nachladen von
 * fonts.googleapis.com oder fonts.gstatic.com zur Laufzeit.
 */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('assets/fonts/montserrat-300.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/montserrat-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/montserrat-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/montserrat-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('assets/fonts/montserrat-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
 * Stil C: keine border-radius, keine Schatten, keine Rahmen ausser Haarlinien.
 *
 * Task 12, Befund W8 (Opus-Gesamtreview, LOGBUCH.md): der vorherige Universalselektor
 * `* { border-radius:0 !important; box-shadow:none !important; }` griff ueber
 * add_editor_style() (functions.php, duo2026_setup()) auch in der Editor-Leinwand -- dort
 * flachte er WordPress-eigene UI-Zustaende ab, die selbst auf border-radius/box-shadow
 * angewiesen sind (Block-Auswahlrahmen, Fokus-Schatten der Kernbuttons/-Felder,
 * .components-*-Tooltips/-Popover). Frontend und Editor teilen sich dieselbe style.css
 * (add_editor_style() bindet exakt diese Datei ein), ein Universalselektor kann die beiden
 * Kontexte nicht unterscheiden.
 *
 * Fix: statt `*` nur die tatsaechlich betroffenen Frontend-Elemente -- Buttons, Bilder/Figuren,
 * Karten/Gruppen/Spalten des Theme-eigenen Markups -- UND explizit NICHT die WordPress-Kern-
 * UI-Klassen (.block-editor-*, .components-*, .editor-*). Da diese Kern-Klassen nur im Editor
 * vorkommen (nie im ausgelieferten Frontend-HTML dieses Themes), reicht ein Ausschluss ueber
 * :not() als zusaetzliche Absicherung, falls WordPress in einer kuenftigen Version eine dieser
 * Klassen doch einmal auf einem Frontend-Element vergibt.
 */
.wp-block-button__link:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-image img:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-image figure:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-cover:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-group:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-column:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-columns:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-table:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-table td:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
.wp-block-table th:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
input:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
textarea:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
select:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]),
button:not([class*="block-editor-"]):not([class*="components-"]):not([class*="editor-"]) {
  border-radius: 0 !important;
  box-shadow: none !important;
}

/*
 * Task 12, Befund W6 (Opus-Gesamtreview): Lesespalte fuer Fliesstext, die an derselben linken
 * Kante wie der ueber ihr liegende Kopf-Abschnitt beginnen soll, statt sich (schmaler als die
 * verfuegbare Breite) erneut zu zentrieren -- siehe page-legal.html/ueber-uns.html fuer die
 * durchgerechneten Pixelwerte des vorherigen Fehlers.
 *
 * !important auf max-width/margin ist hier kein Stilmittel, sondern noetig: WordPress-Kern
 * druckt fuer JEDEN "is-layout-constrained"-Container die generische Regel
 * `.is-layout-constrained > :where(...) { max-width:var(...); margin-left:auto !important;
 * margin-right:auto !important; }` (block-library/style.css, inline im <head>) -- diese Regel
 * traf sowohl <main> (page-legal.html) als auch wp:post-content (page-ueberuns.html) und
 * zentrierte den direkten Kind-Container erneut, selbst nachdem dessen EIGENES
 * "layout":{"type":"flow"} keine eigene Zentrierung mehr auf SEINE Kinder anwendet -- die
 * erzwungene Zentrierung kommt vom ELTERN-Container, nicht vom Element selbst. Per
 * Playwright nachgemessen: ohne die !important-Regeln unten blieb der Fliesstext trotz
 * max-width:760px weiterhin bei x=340px statt x=72px zentriert. `main .duo-lesespalte`
 * (Nachfahren-Selektor mit Typ-Selektor "main") hat hoehere Spezifitaet (0,1,1) als die
 * Kern-Regel (0,1,0, da :where() laut Spezifikation keine Spezifitaet beitraegt) und gewinnt
 * damit unabhaengig von der Reihenfolge im Cascade.
 *
 * Task 25: .duo-lesespalte ist ERSATZLOS ENTFERNT. Die Klasse war die Ursache der in der
 * Ist-Aufnahme belegten Geometrie-Abweichung der Inhaltsseiten: auf Impressum und
 * Datenschutzhinweise erzwang sie eine 760px breite, linksbuendige Spalte bei x=72, auf
 * /ueber-uns/ lag sie zusaetzlich auf einem Abschnitt, der bereits den Seitenrand trug --
 * 616px Zeilenlaenge, die schmalste Zeile der ganzen Website. Alle sechs Inhaltsseiten nutzen
 * seither denselben Zweispalter wie die Produktseiten (Randspalte 25% / Textspalte 70%,
 * blockGap.left 30px), der sich aus dem normalen constrained-Layout ergibt und keine
 * !important-Ausnahme braucht. Der Kommentarblock bleibt als Beleg stehen, warum die Regel
 * einmal noetig schien -- der zugrunde liegende Core-Mechanismus (erzwungene Zentrierung
 * direkter Kinder eines "constrained"-Containers) gilt unveraendert und trifft weiterhin
 * .duo-hero-linksbuendig weiter unten.
 */

/*
 * WordPress-Core setzt auf h1-h6/p/Listen/blockquote/figure eigene margin-top/-bottom
 * (Browser- bzw. Core-Defaults, theme.json setzt dafuer keinen Wert). Die Patterns aus
 * Task 5 steuern Abstaende bewusst ueber blockGap/padding der umgebenden Gruppen/Spalten --
 * ohne diesen Reset addieren sich Core-Margin UND blockGap, jeder Absatz/jede Ueberschrift
 * traegt also doppelten Abstand. Gefunden in der Review zu Thema 25 (Detailseite
 * Daten-Services, dort 14,5 % zu hoch gegen das Artboard) und per Playwright nachgemessen:
 * <p>-Elemente trugen zusaetzlich zum gap 16-19px margin-top UND -bottom. Einzelne, bewusst
 * gesetzte Inline-margin-Werte (z. B. das Zahlenband auf der Startseite) haben Vorrang, da
 * Inline-`style` diese Elementregel ohnehin schlaegt.
 */
h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, figure {
  margin: 0;
}

/*
 * Task 12, Befund K7 (LOGBUCH.md): WordPress' globales `word-break: break-word` (WP-Core)
 * bricht bei grossen H1-Ueberschriften in schmalen Kopf-Spalten nicht zuverlaessig an
 * Wort-/Bindestrichgrenzen (Thema 26: "Gesundheitswes/en:", "Kommunikation/s-Services", dort
 * mit zwei seitenspezifischen fontSize-Notpflastern behoben). Statt weiterer Einzelwerte pro
 * Seite: `hyphens: auto` als generischer Zweitmechanismus auf jeder H1 -- der Browser
 * bevorzugt eine sprachlich korrekte Trennstelle (Silbentrennung), bevor `break-word`
 * mitten im Wort umbricht. Wirkt nur, wenn eine Zeile tatsaechlich zu lang ist; passende
 * `lang`-Attribute liefert WordPress/Polylang je Sprachversion bereits (LOGBUCH.md,
 * "WPML: zwei Fallen").
 */
h1 {
  hyphens: auto;
  -webkit-hyphens: auto;
  overflow-wrap: break-word;
}

/*
 * Harter Diagonalschnitt im Kopfbereich (Stil C) -- Uebersetzung von `clip-path` aus
 * `kopfbereich()` in scripts/baue-stil-c.py (Zeile 292-311). Blockattribute kennen keinen
 * clip-path, deshalb als Utility-Klasse; `seitenkopf.php` setzt sie per className.
 */
.duo-diagonalschnitt {
  clip-path: polygon(0 0, 100% 0, 100% 88%, 0 100%);
}

/*
 * Task 15 (Rueckmeldung Punkt 4, "Menue oben: immer linksbuendig"): header.html/header-hell.html
 * setzen "justifyContent":"left" (vorher "space-between") -- damit ruecken Logo und Navigation
 * mit blockGap (46px) zusammen, statt sich mit gleich grossen Luecken ueber die ganze Kopfzeile
 * zu verteilen (Artboard C-Homepage.dc.html: Navigation "flex-grow:1" direkt nach dem Logo).
 * "flex-grow" ist kein Gutenberg-Blockattribut fuer "layout":{"type":"flex"} -- hier per Klasse
 * nachgetragen, damit die Navigation den GESAMTEN freien Platz zwischen Logo und Knopf fuellt
 * und der Knopf dadurch an den rechten Rand gedrueckt wird. Die Navigationspunkte selbst bleiben
 * per "justifyContent":"left" auf dem core/navigation-Block (header.html) linksbuendig
 * INNERHALB dieser jetzt breiten Navigation-Box.
 */
header.duo-kopf-ueberlappt .wp-block-navigation {
  flex-grow: 1;
}

/*
 * Task 15 (Rueckmeldung Punkt 6, Menuestruktur): WordPress' aufklappendes Untermenue
 * (".wp-block-navigation__submenu-container") rendert IMMER auf einem eigenen, weissen
 * Flyout-Hintergrund (Core-Block-Library-CSS) -- die TEXTFARBE erbt es aber vom umgebenden
 * core/navigation-Block. Auf der Startseite ist die Navigation hell (header-hell.html,
 * "textColor":"weiss", fuer den weissen Text auf der magentafarbenen Kopfflaeche gedacht) --
 * genau diese weisse Farbe faellt dann auch auf den WEISSEN Flyout-Hintergrund durch: weisser
 * Text auf weissem Grund, das Untermenue ist zwar bedienbar (Tastatur/Klick oeffnen es korrekt),
 * aber unlesbar. Fix: der Flyout selbst bekommt unabhaengig vom umgebenden Kontext immer eine
 * dunkle, lesbare Textfarbe -- auf Produktseiten (bereits dunkler Navigationstext) aendert das
 * sichtbar nichts.
 */
.wp-block-navigation__submenu-container,
.wp-block-navigation__submenu-container a {
  color: var(--wp--preset--color--tinte) !important;
}

/*
 * Task 24 (Befund 1 des Task-23-Reviews): derselbe Fehlertyp wie oben, eine Ebene hoeher --
 * im GEOEFFNETEN mobilen Ueberlagerungsmenue. Die Thema-15-Regel darueber fasst nur den
 * Flyout-Container, der Ueberlagerungscontainer blieb offen.
 *
 * Belegte Ursache (gemessen am gerenderten DOM bei 390px auf "/" und "/en/", die Regel per
 * CDP CSS.getMatchedStylesForNode am Knoten selbst nachgewiesen): das Core-Block-Library-
 * Stylesheet setzt
 *   .wp-block-navigation:not(.has-background)
 *     .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay)
 *     { background-color: #fff }
 * -- der geoeffnete Container traegt also rgb(255,255,255), NICHT Magenta (die gegenteilige
 * Annahme in Task 23 ist widerlegt, siehe Kommentar weiter unten und LOGBUCH.md Thema 48/49).
 * Die Textfarbe erbt der Container dagegen vom core/navigation-Block: auf der Startseite
 * "textColor":"weiss" (parts/header-hell.html), also .has-weiss-color mit !important.
 * Ergebnis: weisser Text auf weissem Grund, Kontrast 1:1. Betroffen waren genau die drei
 * Eintraege der ersten Ebene ("Leistungen", "Über uns", "Support" / "Services", "About us",
 * "Support"); die Untermenuepunkte lagen bereits durch die Thema-15-Regel auf tinte.
 *
 * Fix analog Thema 15: der geoeffnete Ueberlagerungscontainer setzt seine Textfarbe
 * unabhaengig vom umgebenden Kontext fest. Auf den Detailseiten (Navigationstext ohnehin
 * dunkel) aendert das sichtbar nichts.
 */
.wp-block-navigation__responsive-container.is-menu-open,
.wp-block-navigation__responsive-container.is-menu-open a,
.wp-block-navigation__responsive-container.is-menu-open button {
  color: var(--wp--preset--color--tinte) !important;
}

/*
 * Die Startseite hat im Artboard (C-Homepage.dc.html) einen flacheren Schnitt (100% 76%)
 * als die Detail-/Rechts-/Ueber-uns-Seiten (C-Detailseite.dc.html, 100% 88%, siehe
 * .duo-diagonalschnitt oben) -- eigene Farbflaeche ist insgesamt hoeher (Header + groessere
 * H1/Lead/Knopf-Reihe), bei gleichem Prozentwert waere der Schnitt sichtbar zu spitz.
 */
.duo-diagonalschnitt-start {
  clip-path: polygon(0 0, 100% 0, 100% 76%, 0 100%);
}

/*
 * Befund 1 (Task 13): Kopfflaeche (Header) legt sich ueber die Hero-Farbflaeche, statt davor
 * eigenen, ungefaerbten Platz einzunehmen -- Artboard-Struktur: absolut positionierte
 * Farbschicht HINTER einem transparenten, position:relative-Header. Hier ohne eigene
 * Absolut-Schicht nachgebildet: der Header zieht per negativem margin-bottom die
 * nachfolgende Hero-Flaeche (main > erster Abschnitt) um die eigene Hoehe nach oben unter
 * sich; die Hero-Flaeche gleicht das mit demselben Betrag zusaetzlichem padding-top wieder
 * aus (siehe scripts/content/startseite.html, theme-build/duo-2026/patterns/seitenkopf.php),
 * sodass H1/Lead exakt an der bisherigen Position stehen bleiben -- nur die Farbflaeche
 * reicht jetzt zusaetzlich hinter den Header. z-index haelt den (unpositionierten) Header
 * ueber der (statischen) Hero-Flaeche.
 *
 * --duo-kopf-versatz ist auf Mobil (<=600px) 0: der Header wird dort mehrzeilig (row-gap,
 * siehe unten) und seine tatsaechliche Hoehe ist nicht mehr 92px -- eine Ueberlappung mit
 * fixem Versatz wuerde dort Hero-Inhalt verdecken. Mobil bleibt daher bei der alten,
 * gestapelten (nicht ueberlappenden) Anordnung.
 */
:root {
  --duo-kopf-versatz: 92px;
}
/*
 * Task 15 (Rueckmeldung Punkt 5, "Menue oben ... festhalten"): der Header bleibt beim Scrollen
 * oben stehen (position:sticky statt relative), der Rest der Seite scrollt darunter weg. Die
 * Topbar (Telefon/E-Mail/Sprache) bleibt bewusst UNVERAENDERT (kein position:sticky) -- sie ist
 * kein eigenes Element hier, nur der Header selbst wird geklebt.
 *
 * position:sticky funktioniert nur, wenn KEIN Vorfahre overflow:hidden/auto/scroll traegt --
 * geprueft: weder .wp-site-blocks noch html/body noch irgendein Template/Pattern dieses Themes
 * setzt overflow auf einem Vorfahren des Headers (grep auf "overflow" in style.css trifft nur
 * overflow-wrap, kein einziges overflow:hidden/auto). Sticky greift deshalb ungehindert.
 *
 * Auftraggeber-Entscheidung zur Optik im gescrollten Zustand: KEIN eigener "gescrollt"-Stil --
 * der Header behaelt einfach die Hintergrundfarbe, die er im Ruhezustand der jeweiligen Seite
 * ohnehin hat (Magenta Startseite, Kopf-Ton #e4f2f4 Produktseiten, Hell-Grau #f2f3f4 Impressum/
 * Datenschutz/Ueber uns) -- siehe die vier body.*-Regeln weiter unten. Der Header ist dafuer
 * IMMER (nicht nur "wenn gestuckt") opak in dieser Farbe: sichtbar aendert sich dadurch nichts
 * im Ruhezustand (dieselbe Farbe liegt ohnehin direkt dahinter, siehe Kommentar in
 * parts/header.html), aber sobald die farbige Kopf-Flaeche selbst weggescrollt ist, bleibt der
 * jetzt oben klebende Header trotzdem korrekt gefaerbt -- ohne Scroll-Listener/JavaScript, rein
 * per CSS, weil beide Zustaende dieselbe Deklaration teilen.
 *
 * z-index angehoben (2 -> 20): der Header liegt jetzt dauerhaft ueber JEDEM nachfolgenden
 * Seitenabschnitt, nicht mehr nur ueber der eigenen Hero-Flaeche.
 */
/*
 * Task 15 (Rueckmeldung Punkt 5), Nachtrag waehrend der Sticky-Abnahme: position:sticky auf
 * dem Header SELBST (".duo-kopf-ueberlappt") funktionierte nicht -- sein direkter Elternknoten
 * ist der von WordPress automatisch erzeugte Template-Part-Wrapper
 * (<div class="wp-block-template-part">), der (da der Header dessen einziges Kind ist) exakt
 * dieselbe Hoehe hat wie der Header selbst (92px). position:sticky darf ein Element aber nur
 * INNERHALB der Hoehe seines eigenen Elternknotens festhalten -- ohne zusaetzlichen Spielraum
 * im Elternknoten "klebt" es fuer keinen einzigen Scroll-Pixel: die Elternbox verlaesst den
 * Sichtbereich praktisch im selben Moment wie das Kind selbst (per Playwright nachgemessen:
 * statt bei top:0 zu bleiben, sprang die Kopfleiste bei 500px Scroll direkt auf top:-460px,
 * exakt wie ein normal mitscrollendes, unpositioniertes Element).
 *
 * Fix: position:sticky wandert stattdessen auf ebendiesen Wrapper -- ueber "className":
 * "duo-header-huelle" auf dem wp:template-part-Aufruf selbst adressierbar gemacht (header.html/
 * header-hell.html, in allen vier Templates, die einen Header einbinden). DESSEN Elternknoten
 * ist .wp-site-blocks (Topbar/Header-Huelle/main/Footer als direkte Geschwister) -- das spannt
 * bereits die gesamte Dokumenthoehe auf, der Wrapper kann also ueber die volle Seite kleben.
 * Der Header selbst (".duo-kopf-ueberlappt") behaelt seinen eigenen Flex-Aufbau, traegt aber
 * kein position/z-index mehr -- das uebernimmt jetzt "duo-header-huelle".
 *
 * Der urspruengliche Versatz (frueher margin-bottom auf dem Header) wandert aus demselben Grund
 * (kollabierter Elternbeitrag waere fuer den jetzt sticky Wrapper genauso ein Problem) als
 * margin-top auf die NACHFOLGENDE Farbflaeche -- optisch identisches Ergebnis (die Flaeche
 * ruecht weiterhin um --duo-kopf-versatz unter den Header), ohne die Elternbox des sticky
 * Wrappers zu verkleinern. Die vier betroffenen Flaechen teilen sich zwei bestehende Klassen
 * (Diagonalschnitt Start-/Detailseiten) plus eine neue Hook-Klasse fuer die Rechtsseiten (kein
 * eigener Diagonalschnitt dort).
 */
.duo-header-huelle {
  position: sticky;
  top: 0;
  z-index: 20;
}
.duo-diagonalschnitt,
.duo-diagonalschnitt-start,
.duo-kopf-flach {
  margin-top: calc(-1 * var(--duo-kopf-versatz));
}
body.home .duo-header-huelle {
  background-color: var(--wp--preset--color--magenta);
}
/*
 * Nachtrag (Task 15, Korrektur nach Rueckmeldung): "Ueber uns" stand hier zunaechst bei
 * Hell-Grau -- die Auftragsformulierung ("hellgrau auf anderen Seiten") war an dieser Stelle
 * ungenau. Gemeint ist die Farbe, die die jeweilige Seite im RUHEZUSTAND ohnehin traegt
 * (siehe Kommentar oben); "Ueber uns" traegt seit Task 8 Kopf-Ton (#e4f2f4), genau wie die
 * vier Leistungsseiten (duo/seitenkopf-Struktur, backgroundColor:"kopf-ton" in
 * scripts/content/ueber-uns(.-en).html) -- NICHT Hell-Grau. Mit Hell-Grau stand die Leiste in
 * sichtbarem Farbbruch zur eigenen Hero-Flaeche darunter (per Screenshot am oberen Rand
 * bestaetigt). Nur Impressum und Datenschutzhinweise tragen tatsaechlich Hell-Grau
 * (page-legal.html, backgroundColor:"hell-grau") und bleiben hier stehen.
 *
 * Task 25: page-ueberuns und page-legal sind zum gemeinsamen Template page-inhalt
 * verschmolzen, dessen Kopfabschnitt auf allen sechs Inhaltsseiten denselben Produktton
 * kopf-ton traegt wie die Produktseiten (frueher Hell-Grau nur auf den beiden Rechtsseiten --
 * ein Sonderton fuer zwei Seiten, den nichts begruendete). Damit bleiben genau zwei
 * Kopfvarianten uebrig: Produkt-/Inhaltsseiten (kopf-ton) und die Startseite (Magenta,
 * .duo-kopf-hell weiter unten).
 */
body.page-template-page-leistung .duo-header-huelle,
body.page-template-page-inhalt .duo-header-huelle {
  background-color: var(--wp--preset--color--kopf-ton);
}

/*
 * Task 15 (Rueckmeldung Punkt 5, Ankerspruenge): #kontakt/#daten/#analytics/... duerfen nicht
 * unter dem jetzt dauerhaft oben klebenden Header verschwinden. scroll-padding-top auf dem
 * Wurzelelement wirkt fuer JEDEN Ankersprung (Klick UND direkter Aufruf mit #hash), ohne jedes
 * Sprungziel einzeln mit scroll-margin-top zu versehen. 92px = Header-Hoehe (siehe
 * "dimensions":{"minHeight":"92px"} in header.html/header-hell.html) plus 16px Luft. Mobil
 * (<=600px) wird der Header per row-wrap mehrzeilig und dadurch deutlich hoeher -- eigener,
 * grosszuegigerer Wert in der bestehenden 600px-Media-Query unten.
 *
 * Task 25: der Wert steht jetzt als CSS-Variable --duo-iv-leseband-oben, weil er an DREI
 * Stellen gebraucht wird und nur einmal gepflegt werden darf: scroll-padding-top (hier), der
 * top-Wert des klebenden Inhaltsverzeichnisses und die Oberkante des Lesebands, mit dem
 * assets/js/inhaltsverzeichnis.js die mitlaufende Markierung bestimmt (das Skript liest die
 * Variable per getComputedStyle aus). Laufen die drei auseinander, springt die Markierung an
 * einer anderen Stelle um als der Ankersprung absetzt.
 */
:root {
  --duo-iv-leseband-oben: 108px;
}

html {
  scroll-padding-top: var(--duo-iv-leseband-oben);
}

/*
 * Weiches Scrollen fuer Ankerspruenge -- und NUR, wenn der Leser keine Bewegungsreduktion
 * eingestellt hat. Bewusst per Media-Query "no-preference" statt per Ueberschreibung in
 * "reduce": so ist die bewegungsarme Fassung der Standard, nicht die Ausnahme. Playwright
 * setzt in diesem Projekt zentral reducedMotion:'reduce' (scripts/playwright-dev-context.js)
 * -- jede Abnahmemessung laeuft damit ohne Scrollanimation und ohne Wartezeiten.
 */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/*
 * Befund 6 (Task 13, Nachtrag): die vier Leistungsbaender der Startseite (Bild+Text-Paar
 * in wp:columns) werden von WordPress' eigener "constrained"-Layout-Regel bereits korrekt
 * auf max-width:1296px begrenzt und dabei zentriert (`margin-inline:auto !important`,
 * core-generierte CSS-Regel `.wp-container-*-is-layout-* > * {...}`) -- das Bild-Text-Paar
 * selbst waechst also NICHT mit der Viewport-Breite, sondern bleibt bei jeder Breite exakt
 * so gross wie bei 1440px. Was bei sehr breiten Bildschirmen (>1440px) trotzdem seltsam
 * wirkt: das Paar bleibt starr MITTIG, waehrend die Farbflaeche (Full-Bleed, Thema 30) auf
 * beiden Seiten immer mehr leeren Raum zeigt. Auftraggeber-Entscheidung (zweiter Nachtrag
 * zu Task 13): statt zu zentrieren wandert das unveraendert grosse Paar oberhalb 1440px
 * abwechselnd an den rechten/linken Rand (72px Aussenabstand -- der bereits vorhandene
 * Randabstand der Sektion selbst, siehe deren eigenes padding). Bei <=1440px aendert sich
 * nichts: dort ist margin-left/right ohnehin je (1296px verfuegbar minus 1296px Paarbreite)
 * / 2 = 0, zentriert und randbuendig fallen zusammen -- exakt der Artboard-Zustand.
 * !important noetig, um die oben genannte Core-Regel (selbst !important) zu ueberstimmen;
 * ID-Selektoren (Anker der vier Baender) halten die Spezifitaet dafuer hoch genug.
 */
/*
 * Befund 2 (Task 13): WordPress' eigener .wp-site-blocks-Wrapper (Kinder: Topbar, Header,
 * main, Footer-Template-Part) traegt denselben globalen Standardabstand
 * (--wp--style--block-gap, 24px, Folge von "blockGap":true in theme.json ohne eigenen
 * Wert) -- im Artboard schliesst die Fusszeile ohne Abstand an den Hauptinhalt an. Die
 * anderen drei Geschwister (Topbar/Header/main) haben eigene Hoehe/Padding und brauchen
 * diesen Fallback-Abstand nicht; generischer Fix auf Wrapper-Ebene statt Einzelpflaster
 * an einer bestimmten Seite -- wirkt auf allen 16 Seiten gleich. Die Klasse .wp-site-blocks
 * ist unspezifisch (kein ID-Selektor); WordPress' eigene Regel nutzt :where(), also
 * Spezifitaet 0 -- diese Regel gewinnt bereits ohne !important, wird hier trotzdem
 * ergaenzt, weil .wp-site-blocks in kuenftigen Core-Versionen abweichend generiert
 * werden koennte.
 */
.wp-site-blocks > * + * {
  margin-top: 0 !important;
}

/*
 * Task 15 (Rueckmeldung Punkt 2): siehe Kommentar in parts/footer.html -- WordPress' Default
 * fuer "layout":{"type":"flex"} ist align-items:center (block-library/style.css), die vier
 * unterschiedlich hohen Fusszeilenspalten zentrierten sich dadurch an ihrer eigenen Mitte statt
 * an ihrer Oberkante. flex-start richtet alle vier an der Oberkante der Zeile aus, gemeinsam mit
 * dem einheitlichen padding-top:30px auf der Fusszeile selbst (footer.html) ergibt das den vom
 * Auftraggeber gewuenschten einheitlichen ~30px-Abstand ueber allen vier Spalten.
 */
.duo-footer-spalten {
  align-items: flex-start;
}

/*
 * Task 15 (Rueckmeldung Punkt 1, "Startseite Hero: Text nicht mittig sondern linksbuendig"):
 * die Startseiten-Heldenflaeche (scripts/content/startseite.html/-en.html) liegt in einer
 * Sektion mit "layout":{"type":"constrained"} -- WordPress' Core-CSS zentriert dabei JEDES
 * direkte Kind per "max-width:var(--wp--style--global--content-size);margin-inline:auto
 * !important" (block-library/style.css, ".is-layout-constrained > :where(...)"), UNABHAENGIG
 * davon, ob das Kind selbst schmaler ist als diese Breite. H1 (max-width:14ch) und Lead-Absatz
 * (max-width:27em) sind beide schmaler als die geerbte Content-Breite (1296px) -- WordPress
 * zentriert sie deshalb INNERHALB dieser 1296px, statt sie an der linken Kante (72px Aussenrand)
 * stehen zu lassen (per Playwright nachgemessen: H1 lag bei x=378px statt x=72px). Derselbe
 * Mechanismus wie der bereits behobene Fall "main .duo-lesespalte" (Task 12, Befund W6) weiter
 * oben in dieser Datei -- hier als eigene, wiederverwendbare Klasse statt Element-Selektor, weil
 * mehrere unterschiedliche Blocktypen (Ueberschrift, Absatz, Buttons-Gruppe) betroffen sind.
 * Geprueft: alle anderen Seiten mit hartem max-width auf einem direkten Kind einer
 * "constrained"-Sektion (duo/seitenkopf: Lead-Absatz max-width:32em) liegen INNERHALB von
 * wp:columns, nicht direkt im "constrained"-Container -- wp:columns fuellt die volle
 * Content-Breite selbst aus, sodass margin:auto dort keinen sichtbaren Versatz erzeugt. Nur die
 * Startseiten-Heldenflaeche ist tatsaechlich betroffen.
 */
.duo-hero-linksbuendig {
  margin-left: 0 !important;
  margin-right: auto !important;
}

/*
 * Task 17 (Rueckmeldung Punkt 3, "Ueber uns: Hero-Foto niedriger, weniger Weissraum"):
 * gebaeude.jpg ist eine Hochformat-Aufnahme (768x1147px, Seitenverhaeltnis 0,67). In der 42%-
 * Spalte der "Ueber uns"-Kopfflaeche (verticalAlignment:center) rendert sie ungebremst bei
 * natuerlicher Groesse -- vorher gemessen 531,7 x 794,1px auf 1440px, waehrend die Textspalte
 * daneben (H1+H2+Knopf) nur 226px hoch ist. Die Zeile richtet sich am hoechsten Kind aus, das
 * Foto zieht die gesamte Kopfflaeche auf 1065,6px Hoehe und erzeugt durch die vertikale
 * Zentrierung ueberproportional viel Leerraum ueber und unter dem kurzen Textblock -- genau der
 * gemeldete "Weissraum". Fix: festes Seitenverhaeltnis 4:3 (statt der natuerlichen 0,67)
 * per object-fit:cover, object-position auf die obere Bildhaelfte (Gebaeudefassade, nicht das
 * Firmenschild im unteren Bilddrittel). Nachweis (Playwright, dev-proxy): 1440px Fotohoehe
 * 794,1px -> 398,8px (-49,8%), Kopfflaeche 1065,6px -> 670,3px (-37,1%); 390px Fotohoehe
 * 522,4px -> 262,5px (-49,8%), Kopfflaeche 1039,3px -> 779,4px (-25,0%). Kein neuer Wert in der
 * Sechs-Stufen-Schriftskala beruehrt, keine neue Farbe.
 */
.duo-ueberuns-hero-foto img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center 18%;
  width: 100%;
}

@media (min-width: 1441px) {
  #daten > .wp-block-columns,
  #integrations > .wp-block-columns {
    margin-left: auto !important;
    margin-right: 0 !important;
  }
  #analytics > .wp-block-columns,
  #kommunikation > .wp-block-columns {
    margin-left: 0 !important;
    margin-right: auto !important;
  }
}

/*
 * Kontaktband (Task 22, Auftraggeber-Wortlaut: "Bild oben und unten an die anderen Baender
 * schluessig anschliesst"). Ursache des gemeldeten Versatzes: die Bildspalte
 * (".wp-block-column:first-child", 26% Breite) liegt in einer Zeile mit
 * "verticalAlignment":"center" -- WP-Core setzt dafuer je Spalte "align-self:center"
 * (".wp-block-column.is-vertically-aligned-center"). Das Foto behaelt dadurch seine
 * natuerliche (quadratische) Groesse und "schwebt" mittig in der von der Textspalte (72px
 * Innenabstand oben/unten + Inhalt) vorgegebenen Zeilenhoehe -- gemessen 106px Luecke oben UND
 * unten bei 518px Bandhoehe (getBoundingClientRect(), 1440px). Die Bandkanten selbst stossen
 * bereits luecken-/ueberlappungsfrei aneinander (messe-bandluecken.js) -- der Versatz war
 * ausschliesslich zwischen Foto und der eigenen Bandflaeche, nicht zwischen zwei Baendern.
 *
 * Fix: die Bildspalte nimmt per align-self:stretch die VOLLE Zeilenhoehe ein (die Textspalte
 * bleibt weiterhin die hoehenbestimmende Seite), Figure und Bild fuellen diese Hoehe zu 100%
 * per object-fit:cover -- das Foto reicht dadurch IMMER exakt bis an Ober- und Unterkante des
 * Bandes, unabhaengig davon, wie hoch der Textinhalt gerade ausfaellt (kein fester Pixelwert,
 * kein Einzelpflaster je Seite -- generisch ueber die ID "#kontakt", die auf allen zehn
 * Instanzen gleichermassen sitzt).
 */
#kontakt .wp-block-columns > .wp-block-column:first-child {
  align-self: stretch;
}

#kontakt .wp-block-columns > .wp-block-column:first-child figure {
  height: 100%;
}

#kontakt .wp-block-columns > .wp-block-column:first-child img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/*
 * Task 11b (Schritt 4, messe-overflow.js neu auf 390px/Tablet ausgefuehrt statt nur auf
 * 1440px wie in Thema 21-29): der feste Aussenrand (--wp--preset--spacing--rand, 72px) und
 * jede mit "flexWrap":"nowrap" gebaute Zeile (Topbar, Header, die vierspaltige Fusszeile,
 * die Aktionsknopf-Reihe im Seitenkasten) waren nie fuer schmale Bildschirme gedacht -- bei
 * 390px blieben nach 2x72px Rand nur 246px fuer Telefonnummer+E-Mail+Sprachumschalter, und
 * jede nowrap-Zeile lief ueber den rechten Fensterrand hinaus (`messe-overflow.js`:
 * maxScrollLeft 44-281px, zunaechst auf allen 16, nach dem Rand-Fix noch auf 4 Seiten).
 * Stil C hat kein eigenes Mobil-Artboard (LOGBUCH.md, "Offene Punkte": nur ein 390-px-Kopf
 * der VERWORFENEN Richtung A liegt vor, nicht Stil C) -- deshalb hier keine neue
 * Mobil-Gestaltung erfunden, sondern generisch (ueber Spacing-Token und die von WordPress
 * selbst vergebene ".is-nowrap"-Klasse jedes "flexWrap":"nowrap"-Blocks, nicht pro Seite
 * oder per Hash-Klasse) so viel Raum geschaffen, dass nichts mehr uebersteht.
 */
@media (max-width: 600px) {
  :root {
    --wp--preset--spacing--rand: 20px;
    --duo-kopf-versatz: 0px;
  }
  header,
  .is-nowrap {
    flex-wrap: wrap !important;
    row-gap: 10px;
  }

  /*
   * Regressionsfund waehrend der Befund-1-Abnahme (Task 13): auf der Startseite ist der
   * Header hell (weisses Logo/weisse Nav, siehe header-hell.html) fuer die Ueberlappung
   * mit der magentafarbenen Hero-Flaeche gebaut. Bei <=600px ist --duo-kopf-versatz 0 --
   * der Header steht dann VOR der Hero-Flaeche auf dem normalen (weissen) Seitenhintergrund,
   * dort ist ein weisses Logo auf weissem Grund unsichtbar. Eigener Magenta-Hintergrund nur
   * fuer diesen Fall stellt den Kontrast wieder her, ohne die Ueberlappungs-Logik selbst
   * (margin/z-index) anzufassen.
   */
  .duo-kopf-hell {
    background-color: var(--wp--preset--color--magenta);
  }

  /*
   * ueberschrift-2 (h2) ist -- anders als ueberschrift-1 (h1) -- fest auf 32px verdrahtet
   * (theme.json, Befund 4/Task 13: sechs feste Schriftstufen, vorher 40px). "Direkt + Online GmbH" traegt
   * per `firma_html()` (scripts/baue-stil-c.py) ein festes `white-space: nowrap;` (Umbruchsperre
   * fuer den Firmennamen, gewollt -- der Name selbst darf nicht brechen). In einer 40px-H2 in
   * einer 350px-Spalte (390px Viewport minus 2x20px Rand) ist der unbrechbare Name allein schon
   * ~436px breit und lief ueber den rechten Rand hinaus (analytics-services: "Warum Analytics
   * mit Direkt + Online GmbH?", `messe-overflow.js` maxScrollLeft 66px). Gefunden ueber
   * messe-overflow.js bei 390px -- vorher nie bei dieser Breite gemessen (Thema 21-29 liefen
   * nur bei 1440px). Fix wie bei h1: kleinere Groesse unterhalb 600px, generisch ueber den
   * Preset-Token, nicht am einzelnen Satz.
   *
   * Nachtrag (Task 15, Korrektur nach Rueckmeldung): der urspruengliche Fix setzte 28px -- ein
   * SIEBTER Wert, den die Sechs-Stufen-Regel (Thema 38) nicht kennt und der nur auf dieser
   * einen Breite auftrat (Desktop/Tablet blieben bei den erlaubten 32px). Auftraggeber-Vorgabe:
   * "klare, feste und einheitliche Menge an Schriftgroessen", ausschliesslich {14,18,22,32,48,
   * 72}px. Von den beiden benachbarten Stufen ist 32px die urspruengliche, bereits als zu breit
   * nachgewiesene Groesse (s.o.) -- 22px (Token "ueberschrift-3") ist die naechstkleinere
   * erlaubte Stufe und bleibt sicher unterhalb der Ueberlauf-Schwelle. Optisch geprueft: auf
   * keiner der 16 Seiten steht ein H3 auf derselben Bildschirmseite wie ein mobiles H2 (die
   * Zwischenueberschriften der Leistungs-/Rechtsseiten sind durchgaengig H2, keine tiefere
   * Ebene im Fliesstext) -- 22px erzeugt also keine Verwechslung zweier Ueberschriften-Ebenen,
   * bleibt aber durch Fettung/Abstand klar vom 18px-Fliesstext abgesetzt (Screenshot-Pruefung,
   * analytics-services bei 390px). messe-overflow.js bei 390px auf allen 16 Seiten: 0
   * Ueberlauf-Treffer (vorher bei 28px ebenfalls 0 -- 22px ist die konservativere von zwei
   * bereits ueberlauffreien Optionen).
   *
   * WIDERLEGT / KORRIGIERT (Task 26, Befund 2 des Reviews zu Task 25): die Absenkung lag am
   * Preset-TOKEN und traf damit jede h2 -- auf /datenschutzhinweise/ bei 390px standen
   * 7 h2 und 25 h3 gemessen alle auf 22px/700/rgb(26,26,46), also OPTISCH IDENTISCH. Die
   * Annahme im Absatz oben ("auf keiner der 16 Seiten steht ein H3 auf derselben
   * Bildschirmseite wie ein mobiles H2") galt fuer den Stand von Task 15 und ist seit den
   * Inhaltsseiten aus Task 25 falsch: dort liegen h2 und h3 direkt ineinander verschachtelt.
   * Auf einer 33.367px hohen Seite auf dem Telefon war damit die oberste Gliederungsebene
   * nicht mehr von der zweiten zu unterscheiden -- genau die Orientierung, um die es ging.
   *
   * Korrektur, ohne eine siebte Schriftgroesse: das TOKEN bleibt bei 32px, die Absenkung auf
   * 22px gilt nur noch fuer die Stellen, die den Grad als GESTALTUNG benutzen und keine
   * Rangstufe sind -- die Kennzahlen der Startseite (2001 / 50+ / 200+ / 10.000+) und des
   * Kommunikationsbandes (1-4, 2.000 qm, 3.500, 10.000, 400.000). Die Preset-Klasse setzt
   * WordPress selbst mit !important, deshalb hier ebenfalls.
   *
   * Der urspruengliche Ueberlaufgrund faellt damit nicht unter den Tisch, er wird eine Zeile
   * weiter unten direkt behandelt (Umbruchsperre in Ueberschriften).
   */
  main p.has-ueberschrift-2-font-size,
  main li.has-ueberschrift-2-font-size,
  main span.has-ueberschrift-2-font-size {
    font-size: 22px !important;
  }

  /*
   * Die Umbruchsperre um den Firmennamen (`<span style="white-space: nowrap;">Direkt + Online
   * GmbH</span>`, gesetzt von scripts/baue-stil-c.py und baue-legal-content.py) ist im
   * Fliesstext richtig und bleibt dort. In einer 32px-Ueberschrift ist derselbe Name gemessen
   * 349px breit und passt in die 350px breite Spalte eines 390px-Viewports mit 1px Spielraum --
   * auf einem 360px-Geraet liefe er ueber. Deshalb gilt die Sperre auf dem Telefon in
   * Ueberschriften nicht: der Name darf dort umbrechen. Generisch ueber das Inline-Attribut,
   * nicht pro Seite oder pro Satz.
   */
  main :is(h1, h2, h3, h4, h5, h6) [style*="nowrap"] {
    white-space: normal !important;
  }

  /*
   * Task 15 (Rueckmeldung Punkt 5, mobil): der Header wird hier (row-wrap, siehe oben)
   * mehrzeilig und dadurch deutlich hoeher als die 92px Desktop-Hoehe -- ein Ankersprung mit
   * dem Desktop-Wert (scroll-padding-top:108px, oben in dieser Datei) wuerde auf einem 390px-
   * Viewport noch unter dem gestapelten Header verschwinden. Grosszuegigerer Wert deckt Logo-
   * Zeile + Navigation-Zeile + Knopf-Zeile ab.
   */
  /* Task 25: als Variable gesetzt, damit das klebende Inhaltsverzeichnis und das Leseband
     des Scroll-Spy denselben Wert mitbekommen (siehe :root oben). */
  :root {
    --duo-iv-leseband-oben: 220px;
  }
}

/*
 * Scroll-Einblendeanimationen (Task 14, "Schoen waeren auch noch Einblend-Animationen beim
 * Scrolling ... das gilt auch fuer Kaesten und Listen auf den Produktseiten"). Eigener
 * Theme-Code (assets/js/einblenden.js setzt "ist-sichtbar" per IntersectionObserver), keine
 * Bibliothek, nichts Nachgeladenes. Zurueckhaltend statt verspielt (Stil C: flaechig,
 * nuechtern) -- kurzer Weg (16px), kein Ueber-/Nachschwingen (ease-out, keine Bounce-Kurve).
 *
 * Der Ausgangszustand opacity:0 greift NUR unter html.js-einblenden-aktiv, eine Klasse, die
 * ausschliesslich einblenden.js setzt (synchron, sobald es laeuft). Ohne JavaScript bleibt
 * die Klasse aus und jeder folgende Selektor trifft nicht -- der Inhalt ist von Anfang an
 * normal sichtbar. Das ist absichtlich keine Regression der Abnahme-Messung: LOGBUCH.md,
 * Thema 5, hatte bereits einmal ein Element, das nur beim Scrollen einblendete und deshalb in
 * jeder page.screenshot({fullPage:true})-Aufnahme fehlte und zu einer Fehldiagnose fuehrte.
 * Hier zusaetzlich abgesichert: `scripts/playwright-dev-context.js` setzt in JEDEM
 * Playwright-Kontext dieses Projekts zentral reducedMotion:'reduce' (kein URL-Parameter,
 * kein Cookie -- 0-Cookies-Vorgabe) -- greift ueber die prefers-reduced-motion-Regel unten
 * und zeigt jede Ganzseiten-Aufnahme sofort vollstaendig, animationsfrei.
 */
html.js-einblenden-aktiv .duo-einblenden,
html.js-einblenden-aktiv .duo-einblenden-gruppe > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 550ms ease-out, transform 550ms ease-out;
  will-change: opacity, transform;
}
html.js-einblenden-aktiv .duo-einblenden.ist-sichtbar,
html.js-einblenden-aktiv .duo-einblenden-gruppe.ist-sichtbar > * {
  opacity: 1;
  transform: none;
}

/* Staffelung: innerhalb einer .duo-einblenden-gruppe blenden die direkten Kinder um je 70ms
   versetzt nacheinander ein, statt gleichzeitig -- Richtwert 60-80ms aus dem Auftrag, bis zu
   zehn Kinder abgedeckt (jede der gebauten Gruppen -- Kartenraster/Vierer-Index/Zahlenband/
   Merkmalsliste/Faktenstreifen/Stichpunktlisten -- bleibt darunter; ein elftes und weiteres
   Kind teilt sich den letzten Versatz, kein Fehler, nur keine zusaetzliche Staffelung mehr). */
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(1)  { transition-delay: 0ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(2)  { transition-delay: 70ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(3)  { transition-delay: 140ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(4)  { transition-delay: 210ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(5)  { transition-delay: 280ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(6)  { transition-delay: 350ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(7)  { transition-delay: 420ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(8)  { transition-delay: 490ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(9)  { transition-delay: 560ms; }
html.js-einblenden-aktiv .duo-einblenden-gruppe > *:nth-child(n+10) { transition-delay: 630ms; }

/*
 * Harte Bedingung 1 (Task 14): prefers-reduced-motion:reduce zeigt alles sofort sichtbar,
 * ohne Bewegung und ohne Verzoegerung -- per Media-Query, nicht nur per JS-Weiche. Dieselben
 * Selektoren wie oben, hier ohne Bedingung an html.js-einblenden-aktiv: greift unabhaengig
 * davon, ob JS die Aktivierungsklasse gesetzt hat.
 */
@media (prefers-reduced-motion: reduce) {
  .duo-einblenden,
  .duo-einblenden-gruppe > * {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    transition-delay: 0ms !important;
  }
}

/*
 * Rueckruf-Formular (duo/rueckruf, Task 19/20). Stil C: kein border-radius, kein box-shadow,
 * Rahmen ausschliesslich als 1px-Haarlinie (Token "linie"). Nur die sechs Schriftstufen aus
 * theme.json, nur Farbtokens -- keine rohen Hex-Werte.
 *
 * Task 20: vom fest eingebauten Abschnitt zum per Knopf aufgerufenen Dialog umgebaut. Der
 * Knopf (.duo-rueckruf-knopf) ist ohne JavaScript ein normaler Anker-Link auf das <dialog>-
 * Element; die Regel `html:not(.js-rueckruf-aktiv) .duo-rueckruf-dialog` weiter unten
 * erzwingt dessen Sichtbarkeit im normalen Textfluss, solange rueckruf-dialog.js die
 * Aktivierungsklasse nicht gesetzt hat (kein <dialog>-Support ODER JavaScript aus/blockiert)
 * -- exakt dasselbe Progressive-Enhancement-Muster wie .duo-einblenden weiter oben (Thema 39).
 */
.duo-rueckruf-knopf {
  display: inline-block;
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--fliesstext);
  /* Task 23: 600 war rechnerisch nicht eindeutig "fett" -- scripts/messe-textkontrast.js
     (neu, DOM-Sweep statt fester Hex-Paare) fand den Knopf im Kontaktband auf Magenta als
     Verstoss gegen die Thema-8-Regel ("weiss auf Magenta nur ab 24px oder ab 18px fett").
     700 macht das eindeutig. */
  font-weight: 700;
  color: var(--wp--preset--color--weiss);
  background-color: transparent;
  border: 1px solid var(--wp--preset--color--weiss);
  border-radius: 0;
  box-shadow: none;
  padding: 12px 32px;
  text-decoration: none;
  cursor: pointer;
}

.duo-rueckruf-knopf:hover,
.duo-rueckruf-knopf:focus-visible {
  color: var(--wp--preset--color--magenta-tief);
  background-color: var(--wp--preset--color--weiss);
}

.duo-rueckruf-knopf:focus-visible {
  outline: 2px solid var(--wp--preset--color--weiss);
  outline-offset: 2px;
}

/*
 * Kontaktband (Task 22, Auftraggeber-Wortlaut: "3cx Option kann raus ... und stattdessen der
 * Rueckruf Button -- kompakt gestalten, sodass alles in eine Zeile passt"). Der 3CX-Anruflink
 * (Thema 44) ist aus allen zehn Kontaktband-Instanzen entfernt; an seiner Stelle steht jetzt
 * <!-- wp:duo/rueckruf /--> als drittes Element DERSELBEN Knopfreihe (Telefon, E-Mail,
 * Rueckruf), nicht mehr als eigener Abschnitt darunter (siehe scripts/entferne-3cx-link.py).
 *
 * .duo-rueckruf-block (Wrapper aus duo_rueckruf_render()) wird dadurch selbst zum Flex-Kind
 * von .wp-block-buttons -- ohne eigene Geometrie wuerde es sich am hoechsten Geschwister
 * (align-items:stretch, WP-Core-Default fuer .wp-block-buttons) ausrichten, aber NICHT
 * automatisch dieselbe Innenabstands-/Randgeometrie wie die WP-Core-Knopf-Links bekommen --
 * beide Knopftypen (.wp-block-button__link UND .duo-rueckruf-knopf) werden deshalb hier
 * gemeinsam auf identische, kompaktere Masse gebracht (Hoehe/Innenabstand/Zeilenhoehe), damit
 * alle drei Elemente bei 1440px exakt auf derselben Grundlinie (offsetTop) stehen und in EINER
 * Zeile Platz finden. Schriftgroesse bleibt bei "fliesstext" (18px, sechsstufige Skala) --
 * Kompaktheit kommt ausschliesslich aus Innenabstand und Abstand zwischen den Knoepfen, nicht
 * aus einer neuen Schriftstufe. Bei 390px greift weiterhin der WP-Core-Standard
 * flex-wrap:wrap -- die drei Elemente brechen dort regulaer um (messe-overflow.js/
 * nachweis-rueckruf-overflow.js pruefen das).
 */
#kontakt .wp-block-buttons {
  column-gap: 12px;
  row-gap: 12px;
  align-items: center;
}

#kontakt .wp-block-buttons .wp-block-button__link,
#kontakt .duo-rueckruf-knopf {
  box-sizing: border-box;
  padding: 10px 22px;
  line-height: 1.3;
  border-width: 1px;
}

#kontakt .duo-rueckruf-knopf {
  margin: 0;
}

/*
 * Ohne eigenen Rahmen (der gefuellte Telefon-Knopf) haette 0px Rahmenbreite gegenueber den
 * 1px-Haarlinien der beiden anderen Elemente einen sichtbaren Hoehenunterschied erzeugt --
 * derselbe Effekt, der zuvor zwischen dem WP-Core-Standard fuer ".is-style-outline" (2px) und
 * dem eigens auf 1px gesetzten ".duo-rueckruf-knopf"-Rahmen fuer 4px Hoehenunterschied sorgte.
 * Transparenter 1px-Rahmen gleicht die Box-Hoehe an, ohne die Optik des gefuellten Knopfs zu
 * aendern (Stil C: weiterhin nur eine Haarlinien-Staerke im gesamten Band).
 */
#kontakt .wp-block-buttons .wp-block-button:not(.is-style-outline) .wp-block-button__link {
  border: 1px solid transparent;
}

/*
 * Nativer <dialog>-Reset: kein border-radius, kein box-shadow (Stil C), Rahmen als
 * 1px-Haarlinie, Farben ausschliesslich aus theme.json. Breite so begrenzt, dass bei 390px
 * kein horizontaler Ueberlauf entsteht (messe-overflow.js prueft das auch mit geoeffnetem
 * Dialog, siehe Nachweis im Logbuch).
 */
.duo-rueckruf-dialog {
  position: fixed;
  inset: 0;
  margin: auto;
  width: 100%;
  max-width: 640px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  padding: 0;
  border: 1px solid var(--wp--preset--color--linie);
  border-radius: 0;
  box-shadow: none;
  background-color: var(--wp--preset--color--hell-grau);
  color: var(--wp--preset--color--tinte);
}

@media (max-width: 680px) {
  .duo-rueckruf-dialog {
    max-width: calc(100vw - 32px);
  }
}

/* Kein rohter Hex-/rgba-Wert -- Token "tinte" mit CSS-opacity abgedunkelt (Stil C erlaubt nur
   Farbtoken, opacity ist ein Standard-CSS-Merkmal, kein neuer Farbwert). */
.duo-rueckruf-dialog::backdrop {
  background-color: var(--wp--preset--color--tinte);
  opacity: 0.6;
}

/* Progressive Enhancement: ohne die JS-Aktivierungsklasse bleibt der Dialog ein normaler,
   immer sichtbarer Seitenabschnitt im Textfluss -- kein toter Knopf ohne JavaScript. */
html:not(.js-rueckruf-aktiv) .duo-rueckruf-dialog {
  display: block;
  position: static;
  inset: auto;
  margin: 24px 0 0;
  width: auto;
  max-width: none;
  max-height: none;
  overflow: visible;
}

html:not(.js-rueckruf-aktiv) .duo-rueckruf-dialog::backdrop {
  display: none;
}

.duo-rueckruf-schliessen {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  line-height: 1;
  color: var(--wp--preset--color--tinte);
  background-color: transparent;
  border: 1px solid var(--wp--preset--color--linie);
  cursor: pointer;
}

.duo-rueckruf-schliessen:hover,
.duo-rueckruf-schliessen:focus-visible {
  color: var(--wp--preset--color--weiss);
  background-color: var(--wp--preset--color--magenta);
  border-color: var(--wp--preset--color--magenta);
}

.duo-rueckruf-schliessen:focus-visible {
  outline: 2px solid var(--wp--preset--color--tinte);
  outline-offset: 2px;
}

html:not(.js-rueckruf-aktiv) .duo-rueckruf-schliessen {
  /* Ohne JS bewirkt der Knopf nichts (kein Klick-Handler) -- aus dem Lesefluss/Fokusweg
     genommen, damit kein toter Knopf angesteuert werden kann. */
  display: none;
}

.duo-rueckruf {
  max-width: 640px;
  margin-inline: auto;
  padding: 48px var(--wp--preset--spacing--rand, 24px);
  background-color: var(--wp--preset--color--hell-grau);
  position: relative;
}

.duo-rueckruf-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px 24px;
}

/* Alle Formularfelder (auch Honeypot und die drei versteckten Felder) explizit auf die
   Meta-Stufe -- ohne diese Regel faellt ein <input> ausserhalb von .duo-rueckruf-feld (Honeypot,
   Zeitstempel, Submit-Flag, Nonce) auf die Browser-UA-Vorgabe zurueck (13,3333px), eine siebte,
   nicht erlaubte Groesse aus der Sechs-Stufen-Skala. */
.duo-rueckruf input,
.duo-rueckruf select,
.duo-rueckruf textarea {
  font-size: var(--wp--preset--font-size--meta);
}

.duo-rueckruf-feld {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.duo-rueckruf-feld-breit {
  grid-column: 1 / -1;
}

.duo-rueckruf-feld label {
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--meta);
  font-weight: 600;
  color: var(--wp--preset--color--tinte);
}

.duo-rueckruf-feld input,
.duo-rueckruf-feld select,
.duo-rueckruf-feld textarea {
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--tinte);
  background-color: var(--wp--preset--color--weiss);
  border: 1px solid var(--wp--preset--color--linie);
  border-radius: 0;
  box-shadow: none;
  padding: 10px 12px;
}

.duo-rueckruf-feld input:focus,
.duo-rueckruf-feld select:focus,
.duo-rueckruf-feld textarea:focus {
  outline: 2px solid var(--wp--preset--color--magenta);
  outline-offset: 1px;
}

.duo-rueckruf-feld input[aria-invalid="true"],
.duo-rueckruf-feld textarea[aria-invalid="true"] {
  border-color: var(--wp--preset--color--magenta-tief);
  border-width: 2px;
}

.duo-rueckruf-feldfehler {
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--meta);
  color: var(--wp--preset--color--magenta-tief);
  margin: 0;
}

.duo-rueckruf-fehler-allgemein {
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--fliesstext);
  color: var(--wp--preset--color--magenta-tief);
  border: 1px solid var(--wp--preset--color--magenta-tief);
  padding: 14px 16px;
  margin: 0 0 20px;
}

.duo-rueckruf-erfolg {
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--fliesstext);
  color: var(--wp--preset--color--tiefsee);
  border: 1px solid var(--wp--preset--color--linie);
  background-color: var(--wp--preset--color--weiss);
  padding: 20px;
  margin: 0;
}

/* Honeypot -- fuer Menschen unsichtbar (off-screen statt display:none, damit ein Bot-Skript,
   das display:none-Felder ueberspringt, trotzdem hineinschreibt), fuer Screenreader per
   aria-hidden ausgeblendet und per tabindex="-1" aus der Tab-Reihenfolge genommen. */
.duo-rueckruf-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.duo-rueckruf-nur-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.duo-rueckruf-absenden {
  grid-column: 1 / -1;
  justify-self: start;
  font-family: var(--wp--preset--font-family--montserrat);
  font-size: var(--wp--preset--font-size--fliesstext);
  font-weight: 700;
  color: var(--wp--preset--color--weiss);
  background-color: var(--wp--preset--color--magenta);
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 12px 32px;
  cursor: pointer;
}

.duo-rueckruf-absenden:hover,
.duo-rueckruf-absenden:focus-visible {
  background-color: var(--wp--preset--color--magenta-tief);
}

.duo-rueckruf-absenden:focus-visible {
  outline: 2px solid var(--wp--preset--color--tinte);
  outline-offset: 2px;
}

@media (max-width: 600px) {
  .duo-rueckruf-form {
    grid-template-columns: 1fr;
  }
}

/*
 * Task 23: LOGBUCH.md Thema 8 verlangt fuer JEDEN weissen Text unter 24px auf Magenta-Grund
 * mindestens font-weight 700 ("fett ab 18px") -- unabhaengig vom nominellen WCAG-Kontrast
 * (weiss auf Magenta trifft 4,50:1 exakt, ohne jeden Puffer). scripts/messe-kontrast.py kann
 * das strukturell nicht pruefen, es rechnet nur feste Hex-Farbpaare nach. Das neue
 * scripts/messe-textkontrast.js (DOM-Sweep ueber alle 16 Seiten) deckte auf, dass diese Regel
 * an mehreren, bis dahin unbemerkten Stellen verletzt wurde: dem Kopf-Knopf
 * "Kontakt aufnehmen"/"Get in touch", den vier Leistungsband-Knoepfen "... ansehen"/"View ...",
 * zwei Shop-Knoepfen ("Im Shop selbst auswaehlen"/"Zum Shop") und der Kopfnavigation der
 * Startseite. Statt jede Stelle einzeln im Content zu pflegen: generische Regeln, die JEDE
 * heutige UND kuenftige Instanz abdecken -- ein neuer Knopf/Menuepunkt auf Magenta ist damit
 * automatisch regelkonform, ohne dass jemand daran denken muss.
 *
 * KORREKTUR Task 24 (Befund 2 des Reviews): hier stand, der Hintergrund des mobilen
 * Ueberlagerungsmenues sei "ebenfalls Magenta, WP-Core-Default". Das ist widerlegt --
 * gemessen ist er rgb(255,255,255) (Core-Regel, siehe Kommentar bei
 * .wp-block-navigation__responsive-container.is-menu-open weiter oben). Im
 * Ueberlagerungsmenue gibt es keine Magenta-Flaeche; die Thema-8-Regel greift dort nicht.
 * Wo sie in der Navigation wirklich greift, ist die Kopfzeile der STARTSEITE: dort liegen
 * die drei Eintraege der ersten Ebene als weisser Text 18px auf der magentafarbenen
 * Heldenflaeche (gemessen #ffffff auf rgb(230,0,126)).
 */
.wp-block-button__link.has-magenta-background-color {
  font-weight: 700;
}

/*
 * Befund 7: die Knopfreihe der Heldenflaeche mischte 400 ("Projekt besprechen",
 * magenta-tief auf weisser Knopfflaeche -- faellt NICHT unter die Thema-8-Regel) und 700
 * ("Im Shop stöbern", weiss auf Magenta -- faellt darunter). Zwei benachbarte Knoepfe
 * derselben Reihe mit verschiedenem Gewicht. Die Reihe wird einheitlich auf 700 gezogen;
 * das ist die einzige in sich stimmige Loesung, denn der Magenta-Knopf DARF nicht auf 400.
 * "#top" gibt es nur auf der Startseite (DE scripts/content/startseite.html, EN analog),
 * die Kopfbereiche aller anderen Seiten kommen aus patterns/seitenkopf.php ohne Anker.
 */
#top .wp-block-buttons .wp-block-button__link {
  font-weight: 700;
}

/*
 * Befund 3: hier stand
 *   .wp-block-navigation__responsive-dialog .wp-block-navigation-item__content
 * -- .wp-block-navigation__responsive-dialog liegt im Core-Markup auf JEDER Breite vor, nicht
 * nur im geoeffneten Ueberlagerungsmenue. Die Regel traf damit gemessen alle 20
 * Navigationslinks der Seite (9 Kopfzeile + 11 Fusszeile) und hob sie von 400 auf 700 --
 * auch die Fusszeilennavigation (14px, meta-hell #b6bcc9 auf tiefsee, 8,96:1, kein Magenta),
 * die dadurch genauso fett wurde wie ihre Spaltenueberschriften. Der Selektor fasst jetzt
 * genau die Stellen, an denen weisser Text unter 24px auf Magenta liegt: die erste
 * Menueebene in der hellen Kopfzeile der Startseite, und nur solange das
 * Ueberlagerungsmenue NICHT geoeffnet ist (im geoeffneten Overlay ist der Grund weiss und
 * der Text per Regel oben tinte -- dort greift die Thema-8-Regel nicht).
 */
.duo-kopf-hell .wp-block-navigation__responsive-container:not(.is-menu-open)
  .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content {
  font-weight: 700;
}

/* ==========================================================================
   Inhaltsverzeichnis (Komponente duo/inhaltsverzeichnis, Task 25)
   ==========================================================================
   Vorlage: patterns/inhaltsverzeichnis.php -- Verhalten: assets/js/inhaltsverzeichnis.js.
   Loest die Randspalten-Navigation aus Task 5 (duo/sprungnavigation) ab, deren aktiver
   Eintrag fest im Markup verdrahtet war (immer der erste) und die nicht klebte (gemessen
   position:static). Eingesetzt auf allen zwoelf Unterseiten: vier Produktseiten und drei
   Inhaltsseiten, je DE und EN.

   Stil C bleibt gewahrt: keine Rundungen, keine Schatten, Rahmen nur als Linie. Farben und
   Schriftgroessen ausschliesslich aus den Tokens -- die Eintraege stehen auf der Meta-Stufe
   (14px), die einzige Stufe unterhalb des Fliesstexts, damit das Verzeichnis nicht mit dem
   Text konkurriert. 14px/400 in "meta" (#40525e) auf Weiss ergibt 8,0:1 (messe-textkontrast.js
   prueft das dauerhaft mit). */

.duo-inhaltsverzeichnis {
  /* Der Nav-Container selbst traegt keinen eigenen Abstand nach unten -- darunter steht auf
     den Produktseiten der Seitenkasten mit eigenem margin-top. */
  align-self: start;
}

.duo-iv-titel {
  border-bottom: 3px solid var(--wp--preset--color--tinte);
  padding-bottom: 12px;
  margin: 0;
}

.duo-iv-liste {
  list-style: none;
  margin: 0;
  padding: 0;
}

.duo-iv-liste li {
  margin: 0;
  border-left: 4px solid var(--wp--preset--color--linie-hell);
}

/* Der Link fuellt die ganze Zeile: die Trefferflaeche ist damit so gross wie der sichtbare
   Eintrag, nicht nur so breit wie der Text (Bedienbarkeit auf dem Telefon). */
.duo-iv-liste a {
  display: block;
  padding: 11px 8px 11px 14px;
  color: var(--wp--preset--color--meta);
  text-decoration: none;
}

.duo-iv-liste a:hover {
  color: var(--wp--preset--color--tinte);
  background-color: var(--wp--preset--color--hell-teal);
}

/* Sichtbarer Fokus -- Pflicht aus dem Task-Brief. outline-offset negativ, damit der Rahmen
   innerhalb der Zeile liegt und den 4px-Balken links nicht ueberdeckt. */
.duo-iv-liste a:focus-visible {
  outline: 2px solid var(--wp--preset--color--magenta);
  outline-offset: -2px;
  color: var(--wp--preset--color--tinte);
}

/* Die Markierung haengt ausschliesslich an aria-current bzw. der vom Skript gesetzten
   Klasse -- ohne JavaScript gibt es beides nicht, und das Verzeichnis ist eine schlichte,
   vollstaendig bedienbare Ankerliste ohne falsche Markierung (Progressive Enhancement wie
   .duo-einblenden und der Rueckruf-Dialog). */
.duo-iv-liste li.ist-aktiv {
  border-left-color: var(--wp--preset--color--magenta);
}

.duo-iv-liste a[aria-current="true"] {
  color: var(--wp--preset--color--tinte);
  font-weight: 700;
}

/* Klebend erst ab dem Breakpoint, an dem WordPress-Core die Spalten ueberhaupt nebeneinander
   stellt (wp-block-columns bricht unterhalb 782px um). top = scroll-padding-top + 16px Luft,
   damit das Verzeichnis unter der klebenden Kopfzeile steht und nicht dahinter. Die Hoehe ist
   auf den sichtbaren Rest des Fensters begrenzt und scrollt notfalls in sich -- ein langes
   Verzeichnis kann damit nie laenger werden als der Bildschirm. */
@media (min-width: 782px) {
  .duo-inhaltsverzeichnis {
    position: sticky;
    top: calc(var(--duo-iv-leseband-oben) + 16px);
    max-height: calc(100vh - var(--duo-iv-leseband-oben) - 32px);
    overflow-y: auto;
  }
}

/* Unterhalb 782px stapelt der Zweispalter: die Randspalte wird zur ersten vollbreiten Zeile
   ueber dem Text. Das bleibt so -- eine eingeklappte Sonderfassung waere ein zweites
   Bedienmuster fuer dieselbe Sache, und ein Verzeichnis, das man erst aufklappen muss, wird
   auf einer 30.388px hohen Seite wie den Datenschutzhinweisen kaum benutzt. Zwei Aenderungen
   gegenueber Desktop: NICHT klebend (sonst naehme es dauerhaft den halben Bildschirm weg --
   ausdrueckliche Vorgabe des Task-Briefs), und in der Hoehe auf 50vh begrenzt, damit auch ein
   langes Verzeichnis den Einstieg in den Text nicht unter den Falz schiebt. */
@media (max-width: 781px) {
  .duo-inhaltsverzeichnis {
    max-height: 50vh;
    overflow-y: auto;
  }
}

/* Fusspunkt-Sentinel, den inhaltsverzeichnis.js ans Dokumentende haengt: erkennt das
   Seitenende, ohne dass ein Scroll-Handler mitlaufen muss. Negatives margin-top, damit er die
   Dokumenthoehe nicht veraendert (messe-overflow.js/messe-bandluecken.js messen sonst gegen
   eine um 1px verschobene Seite). */
.duo-iv-fusspunkt {
  height: 1px;
  margin-top: -1px;
  pointer-events: none;
}

/* ==========================================================================
   Rangstufen und Etiketten (Task 26, Befund 3 des Reviews zu Task 25)
   ==========================================================================
   Widerlegt: die Schriftstaffel aus Task 25 fuehrte h5 und h6 als Rangstufen, obwohl h6 mit
   14px KLEINER war als h5 (18px) und kleiner als der Fliesstext (18px). In einer Kette
   h4 > h5 > h6 kehrte sich die Hierarchie optisch um -- derselbe Fehler, der im Impressum
   gerade behoben wurde (dort stand der Haftungsausschluss als h5 zwischen acht h6). h4
   unterschied sich von h5 ausserdem nur durch die Farbe, nicht durch eine Groesse.

   ENTSCHEIDUNG: Rangstufen sind h1 bis h4 (48/32/22/18 px, alle 700, tinte). h5 und h6 sind
   in theme.json auf denselben Stand wie h4 gesetzt -- sie sind keine eigene Ebene mehr,
   sondern nur noch der Boden der Staffel. Damit ist keine Ebene kleiner als die ihr
   uebergeordnete und keine kleiner als der Fliesstext. Auf keiner ausgelieferten Seite
   kommt heute ein h5 oder h6 vor; wer eine tiefere Gliederung braucht, gliedert die Seite
   um, statt eine fuenfte Ebene zu erfinden.

   Der Versalien-Stil, der frueher am h6 hing, bleibt erhalten -- aber als ETIKETT, nicht als
   Rang: .duo-etikett. Ein Etikett steht ueber einer Aufzaehlung oder einem Datenblock und
   benennt ihn; es gliedert das Dokument nicht und gehoert deshalb NICHT ins
   Inhaltsverzeichnis und nicht in die Ueberschriftenpruefung von
   scripts/messe-inhaltsseiten.js. Es traegt bewusst ein <p>, kein h-Element. */

.duo-etikett {
  font-size: var(--wp--preset--font-size--meta);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--wp--preset--color--meta);
}

/* ==========================================================================
   Vertikaler Rhythmus im Fliesstext (Task 25)
   ==========================================================================
   Ausgangslage: die globale Regel `h1..h6,p,ul,ol,dl,blockquote,figure { margin:0 }` weiter
   oben ist noetig (sonst addieren sich Core-Margin und blockGap doppelt), sie nimmt aber JEDEM
   Fliesstext auch den Eigenabstand. Auf den Rechtsseiten kam dazu, dass wp:post-content mit
   "layout":"flow" gar keine blockGap-Regel erzeugte -- gemessen klebte dort JEDE Ueberschrift
   mit 0px am vorangehenden Absatz (Y-Werte im Impressum: 430, 461, 551, 575, 605, 629, ...).

   Korrektur bewusst NICHT an der globalen Regel -- die trifft alle 16 Seiten, auch Startseite
   und Produktseiten, deren Abstaende millimetergenau abgenommen sind. Stattdessen eine
   Utility-Klasse, die nur dort liegt, wo Fliesstext frei fliesst: .duo-rhythmus auf den
   Abschnitten der Inhaltsseiten. Startseite, Produktseiten und alle Baender tragen sie nicht
   und aendern sich dadurch nicht (belegt per Vorher-/Nachher-Messung, siehe LOGBUCH.md).

   Regel: vor einer Ueberschrift mehr Abstand als danach -- die Ueberschrift gehoert optisch
   zu dem, was ihr folgt. Die Werte sind Vielfache von 4 und bleiben unterhalb des
   Abschnittsabstands (blockGap 56px in der Textspalte), damit die Gliederungsebenen
   erkennbar bleiben. */

.duo-rhythmus > * + * {
  margin-top: 20px;
}

/* Nach einer Ueberschrift: eng. */
.duo-rhythmus > h2 + *,
.duo-rhythmus > h3 + *,
.duo-rhythmus > h4 + *,
.duo-rhythmus > h5 + *,
.duo-rhythmus > h6 + * {
  margin-top: 12px;
}

/* Vor einer Ueberschrift: weit. Diese Regeln stehen ABSICHTLICH nach den vorherigen -- bei
   gleicher Spezifitaet (0,1,1) entscheidet die Reihenfolge, und wenn eine Ueberschrift direkt
   auf eine Ueberschrift folgt, soll der grosse Abstand gewinnen. */
.duo-rhythmus > * + h2 {
  margin-top: 48px;
}

.duo-rhythmus > * + h3 {
  margin-top: 36px;
}

.duo-rhythmus > * + h4,
.duo-rhythmus > * + h5,
.duo-rhythmus > * + h6,
.duo-rhythmus > * + .duo-etikett {
  margin-top: 28px;
}

/* Ein Etikett gehoert zu dem, was ihm folgt -- wie eine Ueberschrift. Ausdruecklich nur vor
   Fliesstext und Listen: auf eine Ueberschrift soll weiterhin der grosse Abstand wirken, und
   diese Auswahl hat dieselbe Spezifitaet (0,2,1) wie die Ueberschriften-Regeln darueber. */
.duo-rhythmus > .duo-etikett + p,
.duo-rhythmus > .duo-etikett + ul,
.duo-rhythmus > .duo-etikett + ol,
.duo-rhythmus > .duo-etikett + dl {
  margin-top: 12px;
}

/* Listen: als Block vom Absatz abgesetzt, die Punkte untereinander enger als Absaetze. */
.duo-rhythmus > ul,
.duo-rhythmus > ol {
  margin-top: 16px;
  padding-left: 22px;
}

.duo-rhythmus > ul li + li,
.duo-rhythmus > ol li + li {
  margin-top: 8px;
}

.duo-rhythmus > :first-child {
  margin-top: 0;
}
