/* GENERIERT aus assets/css/src – nicht direkt bearbeiten. Build: bin/build-assets.py */

/* ===== 00-tokens.css ===== */
/* =========================================================================
   S&M Media – „Sendefassung“
   00 Tokens (Besitz: Fundament F1)

   Sektionsdateien lesen nur die semantischen Tokens (--bg, --text, --mark …).
   Rohfarben (--c-*) stehen nur dort, wo die Spezifikation sie ausdrücklich
   nennt. Neue Tokens beantragt das jeweilige Team bei F.

   Unzulässige Paare – nachgerechnet nach WCAG 2.x, nie verwenden
   (Stylelint-Hinweis für Reviews: Paare unten sind gesperrt):
     #2FAFAF (--c-signal)  auf #FFFFFF          2,67  (Text und Linie)
     #F5C542 (--c-caption) auf #FFFFFF          1,62  (Text und Linie)
     #1C818B (--c-teal)    als Text < 24 px auf #EEF2F1   4,08
     #2FAFAF (--c-signal)  auf #156A72          2,36
     #156A72 (--c-teal-ink) auf #0D2427 (Studio) 2,57
   Deshalb kippen die Tokens je Grund, statt dass eine Sektion Farben wählt.
   ========================================================================= */

:root {
	/* ---------- Rohfarben ---------- */
	--c-white:      #FFFFFF;
	--c-chalk:      #EEF2F1; /* Sektion mist, helle Tafeln */
	--c-clip:       #D9E8E7; /* leerer Clip in der Schnitt-Spur */
	--c-line:       #D3DCDB; /* dekorative Trennlinie, nie alleinige UI-Grenze */
	--c-line-mist:  #C9D3D2; /* Trennlinie auf Kreide */
	--c-line-ui:    #7B8A8A; /* Feldrahmen, Ghost-Rand, Toggle-Rand (≥3:1) */
	--c-ink:        #101B1C; /* Text auf Hell */
	--c-ink-soft:   #4A5758; /* Sekundärtext auf Hell */
	--c-teal:       #1C818B; /* Markenteal: Primärbutton, H1-Tafel, Trim auf Hell, Rahmenmarken */
	--c-teal-ink:   #156A72; /* Teal für Text auf Hell, Segment, gefüllter Clip, Sektion teal */
	--c-teal-press: #0F4E54; /* Segment Hover/Active */
	--c-signal:     #2FAFAF; /* Logo-Teal, nur auf Studio */
	--c-studio:     #0D2427; /* Sektion deep, Panels, Footer */
	--c-studio-2:   #153438; /* zweite dunkle Ebene: Reels, Hover-Fläche auf Studio */
	--c-mute-dark:  #A7C0C2; /* Sekundärtext auf Studio */
	--c-caption:    #F5C542; /* Untertitelgelb, nur auf Studio (Ausnahme Hero-Wort mit Tintenschrift) */
	--c-error:      #B42318;
	--c-error-dark: #FFB4A0;
	/* Ergänzung Kundenfeedback 02.10.2026: grüner Haken der Gegenüberstellung
	   (56-versus.css). Nur Symbolfarbe, nie Text: auf Weiß 5,02, auf Kreide 4,45. */
	--c-success:    #1A7F4B;
	--c-teal-mist:  #CFEDEC; /* Kicker/Hervorhebung auf Sektion teal */

	/* Deckende Entsprechungen von Weiß 70 % und 78 % auf Studio (Tabelle 2.2).
	   Ergänzung F1: Footer und CTA-Intro brauchen sie, ohne dass eine
	   Sektionsdatei eine Transparenz-Rohfarbe schreibt. */
	--c-white-70:   #B6BDBE; /* Reassurance, Copyright auf Studio (8,48) */
	--c-white-78:   #CACFCF; /* Footer-Links, CTA-Intro auf Studio (10,27) */

	/* ---------- Semantische Tokens, Standard = Sektion white ---------- */
	--bg:            var(--c-white);
	--surface:       var(--c-chalk);   /* Fläche auf dem Grund (Hover-Zeile, Takeaway, Formularkarte-Alternative) */
	--text:          var(--c-ink);
	--text-soft:     var(--c-ink-soft);
	--accent-text:   var(--c-teal-ink); /* Kicker, Links, Sterne */
	--line:          var(--c-line);
	--line-ui:       var(--c-line-ui);
	--focus:         var(--c-teal-ink);
	--mark:          var(--c-teal);     /* Sucherrahmen-Marken, Pixelquadrate */
	--trim:          var(--c-teal);     /* Trim-Griffe */
	--plate-bg:      var(--c-teal);     /* Untertitel-Tafel in H1/CTA */
	--plate-fg:      var(--c-white);
	--bridge-bg:     var(--c-studio);   /* Tafel des Brückensatzes */
	--bridge-fg:     var(--c-white);
	--l3-name-bg:    var(--c-teal-ink);
	--l3-name-fg:    var(--c-white);
	--l3-role-bg:    var(--c-chalk);
	--l3-role-fg:    var(--c-ink);
	--clip-bg:       var(--c-clip);
	--clip-fg:       var(--c-ink);
	--clip-on-bg:    var(--c-teal-ink);
	--clip-on-fg:    var(--c-white);
	--playhead:      var(--c-ink);
	--star:          var(--c-teal-ink);
	--star-off:      var(--c-line-ui);
	--seg-off:       #707677;           /* Ink 60 % auf Weiß */
	--seg-on:        var(--c-ink);
	--error:         var(--c-error);
	--ok:            var(--c-success);
	/* Ergänzung F1: Grund der Textauswahl (Weiß darauf 6,29). Kippt nur in
	   Sektion teal, weil er dort dem Sektionsgrund gleicht. */
	--selection-bg:  var(--c-teal-ink);

	/* Buttons */
	--btn-label-bg:   var(--c-teal);
	--btn-label-fg:   var(--c-white);
	--btn-go-bg:      var(--c-teal-ink);
	--btn-go-fg:      var(--c-white);
	--btn-label-bg-h: var(--c-teal-ink);
	--btn-go-bg-h:    var(--c-teal-press);
	--ghost-border:   var(--c-line-ui);
	--ghost-fg:       var(--c-ink);
	--ghost-bg-h:     var(--c-ink);
	--ghost-fg-h:     var(--c-white);

	/* Ergänzung F1: Pfeil im Segment des CF7-Submit (4.5). Ein <input> kann
	   kein SVG-Kind tragen, also kommt der Pfeil als Hintergrundbild. Eine
	   Data-URI kennt kein currentColor, deshalb kippt der Pfeil als Token mit
	   dem Grund: weiß auf #156A72 (6,29), Studio auf #2FAFAF (6,06). */
	--btn-go-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6l6 6-6 6'/%3E%3C/svg%3E");

	/* ---------- Typografie ---------- */
	--font-display: "Archivo", "Archivo Fallback", Arial, sans-serif;
	--font-text:    "Schibsted Grotesk", "Schibsted Fallback", Arial, sans-serif;
	--font-mono:    "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;

	/* ABWEICHUNG von 3.4 (H2 760/96 %, Hervorhebung 850/76 %), Art-Director-
	   Befund „zweite Stimme sieht wie Renderfehler aus“: Zwischen 760/96 % und
	   850/76 % lagen 20 Breiten- und 90 Gewichtspunkte, unter 24rem (H2 86 %)
	   nur noch 10 Breitenpunkte. Die Wörter wirkten wie verrutschtes Kerning.
	   Im Screenshot-Vergleich (sieben Varianten, 1440 und 375 px, Kopf
	   startseite, strassenumfragen, ueber-uns) trug nur ein Paar beide Stimmen
	   eindeutig: Die Agentur spricht breiter und ruhiger (700/100 %), der O-Ton
	   am Rand der instanzierten Datei (Breite 72 %, Gewicht bis 880,
	   01-fonts.css) und optisch etwas größer (1.04em, 06-highlight.css).
	   Nur die Hervorhebung zu verschärfen (72 %/880 bei 760/96 %) blieb
	   mitten im Satz zweideutig („mehr Gewicht hat als“), schwer gegen schwer.
	   Ganz auf die Hervorhebung zu verzichten nähme der H2 die zweite Stimme,
	   die Leitidee (Kapitel 1) aber an dieser Stelle vorsieht. */
	--w-agency:  100%; /* Breite Überschriften (H2) */
	--wg-agency: 700;  /* Gewicht Überschriften (H2) */
	--w-oton:   76%;   /* Breite Namen, Einheiten (Bauchbinde, Register, Leitzahl) */
	--w-cut:    72%;   /* Breite Hervorhebung .hl: Minimum der Archivo-Datei */
	--wg-cut:   880;   /* Gewicht Hervorhebung .hl: Maximum der Archivo-Datei */
	--w-num:    100%;  /* Kennzahlen */
	/* FIX: Breite der H1 und CTA-Titel (3.4: 94 %, unter 24rem 86 %). Die
	   Schutzregel für 320 px stand nur als Elementregel in 02-base.css. Jede
	   Titelklasse mit eigenem font-stretch: 94% (Hero, Seitenkopf, Artikel,
	   404, footer-cta) überstimmte sie in jeder Breite, „Straßenumfragen,“
	   wurde bei 320 px getrennt. Als Token kippt der Wert unten per Media
	   Query am :root, und jede Klasse, die ihn liest, schrumpft mit – ohne
	   Wettlauf um Spezifität. */
	--stretch-title: 94%;

	/* ABWEICHUNG von 3.4 und 6.3/6.16 (375 px: H1 34 px, H2 28 px, CTA 30 px),
	   Befund „Silbentrennung in Display-Überschriften“: H1, H2, CTA-Titel und
	   Tafeln trennen nicht mehr (02-base.css). Lange Komposita müssen deshalb
	   ganz in die Zeile passen. Nur die Untergrenzen sinken um 2 px; der
	   mittlere Wert bleibt, die Größe gleitet also erst unter rund 400 px
	   darunter (H1 Split 32 px bei 320, 33 px bei 375; Seitenkopf 30/31,4;
	   H2 26/26,7; CTA 28/29). Gemessen im Browser bei 320 px (Satzbreite
	   284 px): „Straßenumfragen,“ in der Hero-H1 (800/86 %, 15ch) 249 statt
	   265 px, „Empfehlungsprogramm“ in der H2 bei 700/94 % 273 px,
	   „Herumprobieren“ im CTA-Panel (244 px) 198 px. Über alle 25 Seiten,
	   404, Suche und drei Artikel bei 320, 360, 375 und 414 px liegt kein
	   unteilbares Titelwort über 95 % seiner Zeile, nichts läuft über. */
	--fs-h1-split: clamp(2rem, 1.5rem + 2.4vw, 3.75rem);
	--fs-h1-wide:  clamp(2.5rem, 1.6rem + 3.6vw, 4.75rem);
	--fs-h1-page:  clamp(1.875rem, 1.4rem + 2.4vw, 3.25rem);
	--fs-h2:       clamp(1.625rem, 1.2rem + 2vw, 3rem);
	--fs-cta:      clamp(1.75rem, 1.3rem + 2.2vw, 3rem);
	--fs-h3:       clamp(1.25rem, 1.1rem + 0.6vw, 1.625rem);
	--fs-h4:       1.125rem;
	--fs-bridge:   clamp(1.375rem, 1rem + 1.6vw, 2.125rem);
	--fs-num-lead: clamp(3.5rem, 1rem + 8vw, 8.5rem);
	--fs-num:      clamp(2.75rem, 1.8rem + 3.4vw, 4.5rem);
	--fs-num-s:    clamp(2rem, 1.4rem + 2.2vw, 3rem);
	--fs-time:     clamp(4rem, 2rem + 6vw, 8rem);
	--fs-lead:     1.1875rem;
	--fs-body:     1.0625rem;
	--fs-prose:    1.09375rem;
	--fs-small:    0.9375rem;
	--fs-xs:       0.875rem;
	--fs-mono:     0.8125rem; /* Minimum für Mono */
	--lh-tight: 1.08;
	--lh-head:  1.1;
	--lh-body:  1.6;
	--lh-prose: 1.7;

	/* ---------- Raum und Raster ---------- */
	--container:        76rem;
	--container-narrow: 44rem;
	--measure:          42rem;
	--gutter:  clamp(1.125rem, 4.5vw, 3rem);  /* 18 px bei 320/375, 48 px ab 1067 px */
	--gap:     clamp(1rem, 2.2vw, 2rem);      /* Spaltenabstand 12er-Raster */
	--sp-1: .25rem; --sp-2: .5rem; --sp-3: .75rem; --sp-4: 1rem; --sp-5: 1.5rem;
	--sp-6: 2rem;   --sp-7: 3rem;  --sp-8: 4rem;   --sp-9: 6rem;
	--section-y:       clamp(4rem, 8vw, 7.5rem);
	--section-y-tight: clamp(2.5rem, 5vw, 4rem);
	--section-y-loose: clamp(5.5rem, 11vw, 10rem);
	--head-gap:        clamp(2.5rem, 5vw, 4rem); /* Sektionskopf → Inhalt */
	--header-h:        4.5rem; /* wird von initHeader überschrieben */

	/* ---------- Radien (nach Rolle) ---------- */
	--r-plate:   1px;   /* Untertitel-Tafel, Bauchbinde, Mono-Chips */
	--r-media:   2px;   /* Screens von Video/Bild, Beitragsbilder */
	--r-control: 3px;   /* Buttons, Felder, Toggles, Chips, Pfeilknöpfe */
	--r-panel:   4px;   /* CTA-Panel, featured Paket, Formularkarte, Megamenü-Teaser */
	--r-reel:    6px;   /* 9:16-Reels */
	--r-round:   50%;   /* nur Avatare */
	/* Tabellen, Registerzeilen, Sektionen: 0 */

	/* ---------- Schatten ---------- */
	--shadow-pop: 0 18px 40px rgb(13 36 39 / 14%); /* einziger Schatten: Dropdown, Megamenü */

	/* ---------- Bewegung ---------- */
	--ease-cut: cubic-bezier(.2, .8, .2, 1);
	--ease-out: cubic-bezier(.33, 1, .68, 1);
	--dur-1: 180ms;  /* Farbe, Pfeil, Trim */
	--dur-2: 260ms;  /* Registerfläche, FAQ-Höhe */
	--dur-3: 420ms;  /* Rahmenmarken, Listen-Einblendung */
	--dur-4: 900ms;  /* Walzenbasis */

	/* ---------- Ebenen ---------- */
	--z-raised:   2;
	--z-sticky:   40;
	--z-floating: 90;   /* Sticky-CTA, Nach-oben */
	--z-header:   100;
	--z-megamenu: 110;
	--z-nav:      120;  /* mobiles Panel */
	--z-skip:     1000;
}

/* Gemessen auf 320 px (Satzbreite 284 px): „Straßenumfragen,“ ist bei 800/94 %
   295 px breit und passt nicht, bei 86 % 273 px (3.4). */
@media (max-width: 24rem) {
	:root {
		--stretch-title: 86%;
	}
}

/* Sektion mist */
.section--bg-mist {
	--bg: var(--c-chalk);
	--surface: var(--c-white);
	--line: var(--c-line-mist);
	--l3-role-bg: var(--c-white);
	--clip-bg: var(--c-white);
}

/* Sektion deep (Template setzt data-theme="dark"), Header-Teaser, Footer, Panels.
   .section--bg-deep steht zusätzlich in der Liste: Vergisst ein Template das
   data-theme-Attribut, stünde sonst Tintenschrift auf Studio (1,09:1). */
[data-theme="dark"],
.theme-studio,
.section--bg-deep {
	--bg: var(--c-studio);
	--surface: var(--c-studio-2);
	--text: var(--c-white);
	--text-soft: var(--c-mute-dark);
	--accent-text: var(--c-signal);
	--line: rgb(255 255 255 / 12%);
	--line-ui: #869293;               /* Weiß 50 % */
	--focus: var(--c-signal);
	--mark: var(--c-signal);
	--trim: var(--c-caption);
	--plate-bg: var(--c-teal);
	--plate-fg: var(--c-white);
	--bridge-bg: var(--c-white);
	--bridge-fg: var(--c-studio);
	--l3-name-bg: var(--c-teal);
	--l3-role-bg: var(--c-white);
	--l3-role-fg: var(--c-studio);
	--clip-bg: var(--c-studio-2);
	--clip-fg: var(--c-white);
	--clip-on-bg: var(--c-teal);
	--playhead: var(--c-white);
	--star: var(--c-caption);
	--star-off: #869293;
	--seg-off: #869293;
	--seg-on: var(--c-white);
	--error: var(--c-error-dark);
	--ok: #6FD49B;                    /* auf Studio 8,9 */
	--btn-label-bg: var(--c-white);
	--btn-label-fg: var(--c-studio);
	--btn-go-bg: var(--c-signal);
	--btn-go-fg: var(--c-studio);
	--btn-label-bg-h: var(--c-signal);
	--btn-go-bg-h: var(--c-white);
	--ghost-border: #869293;
	--ghost-fg: var(--c-white);
	--ghost-bg-h: var(--c-white);
	--ghost-fg-h: var(--c-studio);
	--btn-go-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230D2427' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6l6 6-6 6'/%3E%3C/svg%3E");
}

/* Sektion teal (hat ebenfalls data-theme="dark", daher nach dem Dark-Block) */
.section--bg-teal {
	--bg: var(--c-teal-ink);
	--surface: #12545B;
	--text: var(--c-white);
	--text-soft: #D5E4E6;             /* Weiß 82 % */
	--accent-text: var(--c-teal-mist);
	--line: rgb(255 255 255 / 22%);
	--focus: var(--c-white);
	--mark: var(--c-white);
	--trim: var(--c-white);
	--plate-bg: var(--c-white);
	--plate-fg: var(--c-teal-ink);
	--l3-name-bg: var(--c-studio);
	--star: var(--c-white);
	--btn-label-bg: var(--c-white);
	--btn-label-fg: var(--c-studio);
	--btn-go-bg: var(--c-ink);
	--btn-go-fg: var(--c-white);
	--btn-label-bg-h: var(--c-teal-mist);
	--btn-go-bg-h: var(--c-studio);
	--selection-bg: var(--c-studio);  /* Weiß darauf 16,17; #156A72 wäre der Sektionsgrund */
	/* Ergänzung F1: Die Werte aus dem Dark-Block (#869293, #FFB4A0) liegen auf
	   #156A72 nur bei 1,96 bzw. 3,68:1. Ghost-Rand, Feld-/Pfeilknopf-Rand,
	   leere Sterne und inaktive Segmente brauchen 3:1, Fehlertext 4,5:1. */
	--line-ui: #D5E4E6;               /* 4,82 */
	--ghost-border: #D5E4E6;          /* 4,82 */
	--star-off: #D5E4E6;
	--seg-off: #D5E4E6;
	--error: #FFE3DB;                 /* 5,17 */
	--ok: #C8F2D9;                    /* 5,1 */
	/* Segment ist hier Tinte, der Pfeil also wieder weiß (17,56). */
	--btn-go-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6l6 6-6 6'/%3E%3C/svg%3E");
}

/* Breakpoints (in Media Queries als Literale, weil Custom Properties dort
   nicht greifen): 30rem (480), 48rem (768), 62rem (992), 75rem (1200).
   Mobile-first mit min-width. */

/* ===== 01-fonts.css ===== */
/* =========================================================================
   01 Schriften (Besitz: Fundament F1)

   Selbst gehostet, erzeugt mit bin/fonts.py aus Fontsource. Zur Laufzeit
   geht keine Anfrage an einen fremden Server (DSGVO, LG München I,
   3 O 17493/20). Vorgeladen werden nur Archivo und Schibsted aufrecht
   (inc/enqueue.php); Kursiv und Mono laden erst, wenn sie gebraucht werden.

   Archivo trägt Gewicht 560–880 und Breite 72–112 %: breit spricht die
   Agentur, schmal und schwer der O-Ton. ẞ (U+1E9E) und → (U+2192) fehlen in
   allen Familien, deshalb nirgends Versalien per CSS und Pfeile immer als SVG.
   ========================================================================= */

@font-face {
	font-family: "Archivo";
	src: url("../fonts/archivo-var.woff2") format("woff2");
	font-weight: 560 880;
	font-stretch: 72% 112%;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Schibsted Grotesk";
	src: url("../fonts/schibsted-grotesk-var.woff2") format("woff2");
	font-weight: 400 700;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Schibsted Grotesk";
	src: url("../fonts/schibsted-grotesk-var-italic.woff2") format("woff2");
	font-weight: 400 700;
	font-style: italic;
	font-display: swap;
}

@font-face {
	font-family: "IBM Plex Mono";
	src: url("../fonts/ibm-plex-mono-500.woff2") format("woff2");
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}

/* Metrisch angepasste Fallbacks gegen CLS.
   Grundlage: Laufweite eines deutschen Mustersatzes, gemessen gegen Arial / Arial Bold (macOS Supplemental).
   Archivo 800/94 % = 46,695 em, Arial Bold = 47,564 em → 98,2 %.
   Archivo hhea 0,878 / 0,210 → ascent 0,878/0,982, descent 0,210/0,982.
   Schibsted 400 = 46,201 em, Arial = 44,637 em → 103,5 %. hhea 0,9766 / 0,2578.
   Gegenprobe F1 am 15.09.2026 mit den instanzierten Theme-Dateien und dem
   Hero-/Formular-H1 der Startseite: Archivo 800/94 % zu Arial Bold 98,5 %,
   Schibsted 400 zu Arial 103,8 %. Beide Abweichungen liegen unter 0,5 % und
   damit innerhalb der erlaubten ±2 %; die Startwerte bleiben stehen. */
@font-face {
	font-family: "Archivo Fallback";
	src: local("Arial Bold"), local("Arial-BoldMT"), local("Arial");
	size-adjust: 98.2%;
	ascent-override: 89.4%;
	descent-override: 21.4%;
	line-gap-override: 0%;
}

@font-face {
	font-family: "Schibsted Fallback";
	src: local("Arial"), local("ArialMT");
	size-adjust: 103.5%;
	ascent-override: 94.3%;
	descent-override: 24.9%;
	line-gap-override: 0%;
}

/* ===== 02-base.css ===== */
/* =========================================================================
   02 Basis: Reset, Grundsatz, Prosa (Besitz: Fundament F1)

   Globale Elementselektoren stehen nur hier (Konfliktregel 8.5.3).
   Übernommene Korrekturen aus der alten app.css sind mit FIX markiert,
   ihre Begründung wandert mit.
   ========================================================================= */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	color-scheme: light;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	/* FIX: clip statt hidden: schneidet den ausgefahrenen Mobil-Navigationsbereich
	   ab, ohne einen Scroll-Container zu erzeugen, der position: sticky am
	   Header bricht. Achtung beim Messen: scrollWidth lügt unter clip (9.2). */
	overflow-x: clip;
	/* FIX: Sprungmarken (#gespraech, Inhaltsverzeichnis) landen sonst unter dem
	   klebenden Header. --header-h schreibt initHeader. Kein scroll-behavior:
	   smooth mehr – weiches Scrollen steht nicht im Bewegungsinventar (7.3). */
	scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font: 400 var(--fs-body)/var(--lh-body) var(--font-text);
	font-variant-numeric: normal;
	/* FIX: zweite Sicherung neben html. Ein einzelner zu breiter Block darf die
	   Seite auf dem Handy nicht seitlich verschieben. */
	overflow-x: clip;
}

/* FIX: figure, blockquote, dl und dd bringen im Browser je 40 px Seitenrand mit.
   In schmalen Spalten schneidet das den Text auf die halbe Breite. */
figure,
blockquote,
dl,
dd {
	margin: 0;
}

img,
picture,
video,
canvas,
svg {
	display: block;
	max-width: 100%;
	height: auto;
}

iframe {
	border: 0;
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

button {
	cursor: pointer;
}

address {
	font-style: normal;
}

/* FIX: Viele Komponenten setzen display und übersteuern damit das hidden-Attribut.
   Dann bleibt ein per JS ausgeblendetes Element sichtbar und bedienbar
   (Tonknopf, Timecode, Megamenü). !important ist hier bewusst die zweite
   Ausnahme neben dem Reduced-Motion-Netz: hidden muss jede display-Regel
   schlagen, egal wie spezifisch sie ist. */
[hidden] {
	display: none !important;
}

/* ---------- Überschriften ---------- */

h1,
h2,
h3,
h4 {
	font-family: var(--font-display);
	color: var(--text);
	margin: 0;
	font-kerning: normal;
	/* FIX: overflow-wrap greift nur, wenn ein Wort wirklich nicht in die Zeile
	   passt, und setzt dabei keinen Trennstrich. Das darf überall gelten. */
	overflow-wrap: break-word;
}

/* Breite über --stretch-title (94 %, unter 24rem 86 %, 00-tokens.css).
   Titelklassen, die font-stretch selbst setzen, lesen denselben Token.
   FIX: balance auch an der H1. Ohne blieb das letzte Wort allein auf einer
   Tafelzeile („sehen“ auf Karriere, „haben“ im Ratgeber, „zwanzig / Videos“
   im Podcast-Hero). text-wrap erbt, deshalb reicht die Elementregel auch
   für .hero__title, .page-head__title und h1.section__title. */
h1 {
	font-size: var(--fs-h1-page);
	font-weight: 800;
	font-stretch: var(--stretch-title);
	line-height: var(--lh-tight);
	letter-spacing: -.015em;
	text-wrap: balance;
}

/* ABWEICHUNG von 3.4 (760/96 %): 700/100 % aus --wg-agency und --w-agency.
   Breit und ruhig spricht die Agentur, damit die Hervorhebung (72 %/880,
   06-highlight.css) als zweite Stimme lesbar wird. Begründung und
   Variantenvergleich in 00-tokens.css. */
h2 {
	font-size: var(--fs-h2);
	font-weight: var(--wg-agency);
	font-stretch: var(--w-agency);
	letter-spacing: -.01em;
	line-height: var(--lh-tight);
	text-wrap: balance;
}

/* FIX: balance wie an der H2. Kartentitel, Registerzeilen und
   Problemtitel ließen sonst ein einzelnes Wort in der letzten Zeile stehen
   („… / sollst“, „TV- und Streaming- / Spots“). */
h3 {
	font-size: var(--fs-h3);
	font-weight: 700;
	font-stretch: 100%;
	line-height: 1.2;
	text-wrap: balance;
}

h4 {
	font-size: var(--fs-h4);
	font-weight: 700;
	font-stretch: 100%;
	line-height: 1.25;
}

h5,
h6 {
	margin: 0;
	font: 600 var(--fs-body)/1.4 var(--font-text);
	color: var(--text);
}

/* Gemessen auf 320 px (Satzbreite 284 px) mit 26 px (--fs-h2):
   „Empfehlungsprogramm“ ist bei 700/100 % 288 px breit, bei 94 % 273 px.
   Deshalb unter 22.5rem schmaler. Die H1 schrumpft über den Token
   --stretch-title (00-tokens.css), hier steht nur noch die H2.
   ABWEICHUNG von 3.4 (unter 24rem 86 %): 94 % erst unter 22.5rem. Bei 375 px
   (339 px Satzbreite) passt das Wort mit 296 px in voller Breite; mit 86 %
   läge die Agentur-Stimme dort wieder nur 14 Punkte neben der Hervorhebung. */
@media (max-width: 22.49rem) {
	h2 {
		font-stretch: 94%;
	}
}

/* Silbentrennung (Befund „Silbentrennung in Display-Überschriften“):
   ABWEICHUNG von 3.4 (hyphens: auto für h1, h2, h3 bis 30rem): Überschriften
   trennen nicht mehr. „Erst-/gespräch, 30 Minu-/ten“ in der H1 und
   „Um-/fragen“ in der Tafel lasen sich wie Satzfehler, nicht wie ein
   Untertitel. Stattdessen passen lange Komposita über die kleineren
   mobilen Untergrenzen (--fs-h1-*, --fs-h2, --fs-cta) und --stretch-title
   (00-tokens.css) ganz in die Zeile; Bindestrich-Komposita brechen weiter
   am Bindestrich. Tafeln (.hl--plate, .caption-plate) setzen hyphens: manual
   selbst, weil der Brückensatz die Trennung von .pain__bridge erbt
   (06-highlight.css).
   overflow-wrap: anywhere bleibt als letzte Sicherung, falls ein Redakteur
   ein Wort einsetzt, das auch so nicht passt: lieber ein Umbruch ohne Strich
   als ein Wort, das aus dem Bildschirm läuft.
   FIX: 29.99rem statt 30rem, wie bei 47.99/61.99. Mit 30rem galten bei genau
   480 px Mobil- und min-width-30rem-Regeln gleichzeitig. */
@media (max-width: 29.99rem) {
	h1,
	h2,
	h3 {
		overflow-wrap: anywhere;
	}

	/* Fließtext trennt: Zwischentitel aus dem Editor (Rechtstexte, Artikel)
	   gehören zum Text und können beliebig lange Wörter tragen.
	   „4. GEBÜHREN UND ZAHLUNGSBEDINGUNGEN“ (AGB) ist bei 320 px 295 px breit
	   und trennt korrekt „ZAHLUNGS-/BEDINGUNGEN“; ohne Trennung bräche
	   overflow-wrap das Wort ohne Strich vor dem letzten Buchstaben.
	   hyphenate-limit-chars hält kurze Wörter zusammen: mindestens acht
	   Zeichen im Wort, vier vor und vier nach dem Trennstrich. Safari kennt
	   dafür nur die -webkit-Einzelwerte. */
	.prose :is(h2, h3, h4) {
		-webkit-hyphens: auto;
		hyphens: auto;
		-webkit-hyphenate-limit-before: 4;
		-webkit-hyphenate-limit-after: 4;
		hyphenate-limit-chars: 8 4 4;
	}
}

/* ---------- Text ---------- */

p {
	margin: 0 0 1em;
	text-wrap: pretty;
}

ul,
ol {
	margin: 0 0 1em;
	padding-inline-start: 1.25em;
}

hr {
	border: 0;
	border-top: 1px solid var(--line);
	margin: 2.5rem 0;
}

a {
	color: var(--accent-text);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

a:hover {
	text-decoration-thickness: 2px;
}

/* FIX: Der Auswahlgrund ist ein Token. Fest #156A72 wäre in Sektion teal
   exakt Sektionsgrund und Textfarbe – markierter Text sähe dort aus wie
   unmarkierter. Dort kippt --selection-bg auf Studio (Weiß darauf 16,17:1). */
::selection {
	background: var(--selection-bg);
	color: var(--c-white);
}

/* Fokus: --focus kippt mit dem Grund (Teal-Ink auf Hell 6,29, Signal auf
   Studio 6,06, Weiß auf Sektion teal 6,29). FIX: Das helle #2FAFAF schaffte
   als Ring auf Weiß nur 2,67:1. */
:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 3px;
}

:focus:not(:focus-visible) {
	outline: none;
}

/* FIX: Skip-Link als erster Tabstopp. Er liegt außerhalb des Bildes, bis er
   Fokus bekommt, und ist dann eine deckende Tafel über dem Header. Farben aus
   den Grund-Tokens: Tintenfläche mit weißer Schrift (17,56). */
.skip-link {
	position: absolute;
	top: .75rem;
	inset-inline-start: -9999px;
	z-index: var(--z-skip);
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	padding: .625rem 1.25rem;
	background: var(--text);
	color: var(--bg);
	font: 600 var(--fs-small)/1.3 var(--font-text);
	border-radius: var(--r-control);
}

.skip-link:focus {
	inset-inline-start: .75rem;
	color: var(--bg);
}

/* FIX: body.nav-open blieb wirkungslos: Die overflow-Werte von body wandern nur
   dann auf den Viewport, wenn html overflow: visible hat. Hier steht dort
   aber overflow-x: clip. Also greift die Sperre direkt an html. Nur unter
   62rem, damit eine beim Drehen des Geräts hängengebliebene Klasse den
   Desktop nicht sperrt. */
@media (max-width: 61.99rem) {
	html.nav-open {
		overflow: hidden;
	}
}

/* FIX: Gegenstück zum scroll-padding-top an html. Chromium wertet damit
   alles, was in den obersten (Header-Höhe + 1rem) Pixeln liegt, als
   verdeckt – auch die Bedienelemente der klebenden Kopfleiste selbst.
   Bekamen Logo, Menüpunkt, CTA oder Burger bei gescrollter Seite den Fokus
   (Tab, Esc im Menü, die Fokusfalle), sprang die Seite um einen halben
   Bildschirm nach oben.
   Scrollen hilft einem klebenden Element nie. Der Scroll-Rand verschiebt das
   Zielrechteck deshalb um genau diesen Betrag nach unten (oben negativ,
   unten positiv, damit es nicht umklappt): Es gilt als sichtbar, nichts
   scrollt. Sprungmarken im Inhalt landen weiter unter dem Header, denn der
   Rand sitzt nur an den Kopfleisten-Elementen.
   Ausgenommen sind Elemente in eigenen Scroll-Containern: das mobile Panel
   ([data-nav] unter 62rem) und das Megamenü. Dort muss der Container zum
   fokussierten Link scrollen können. Selektoren über die JS-Haken
   (data-header, data-nav, data-megamenu), Spezifität 0 – die Reihenfolge
   entscheidet. */
:where([data-header]) :where(a, button, [tabindex]) {
	scroll-margin-block: calc(-1 * (var(--header-h) + 1rem)) calc(var(--header-h) + 1rem);
}

:where([data-megamenu]) :where(a, button, [tabindex]) {
	scroll-margin-block: 0;
}

@media (max-width: 61.99rem) {
	:where([data-nav]) :where(a, button, [tabindex]) {
		scroll-margin-block: 0;
	}
}

/* FIX (Regel für .site-header, Team A): Kein filter, transform,
   backdrop-filter, perspective, will-change: transform oder container-type am
   Header. Jede dieser Eigenschaften erzeugt einen Containing Block für
   position: fixed. Das mobile Menü hing sonst am 66 px hohen Header statt am
   Viewport und war nur einen Menüpunkt hoch. */

/* ---------- Prosa ----------
   Fließtext aus dem Editor (content, Artikel, FAQ-Antworten). Listen-,
   Tabellen- und Zitatregeln greifen nur an Elementen ohne eigene Klasse
   (bzw. den Core-Klassen), damit Komponentenlisten wie .checks oder
   .bullets innerhalb von .prose unberührt bleiben. */

.prose {
	max-width: 68ch;
	font-size: var(--fs-body);
	line-height: 1.65;
	color: var(--text);
}

@media (min-width: 48rem) {
	.prose {
		font-size: var(--fs-prose);
		line-height: var(--lh-prose);
	}
}

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

.prose > :last-child {
	margin-bottom: 0;
}

.prose :where(p, ul, ol, dl, figure, blockquote, pre, table) {
	margin-block: 0 1em;
}

/* FIX: kein scroll-margin-top an den Prosa-Überschriften. Sprungziele
   verrechnen scroll-padding des Scroll-Containers (html, oben) UND
   scroll-margin des Ziels – beides zusammen ließ eine Überschrift aus dem
   Inhaltsverzeichnis 2 × (Header + 1rem) tief landen, also eine Header-hohe
   Lücke unter dem klebenden Header. Das scroll-padding an html gilt für jedes
   Sprungziel und reicht allein (Abweichung von 6.20). */
.prose h2 {
	font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.125rem);
	margin: 2.5em 0 .6em;
}

.prose h3 {
	font-size: clamp(1.25rem, 1.15rem + .4vw, 1.3125rem);
	margin: 2em 0 .5em;
}

.prose h4 {
	margin: 1.75em 0 .5em;
}

/* Aufzählung: Pixelquadrat aus dem Logo (7 × 7 px, --mark ≥ 4,08:1 auf jedem
   Grund). list-style-type "" statt none: Safari/VoiceOver nimmt einer Liste
   mit list-style none die Listen-Semantik, der leere String rendert genauso
   keinen Marker, lässt die Rolle aber stehen. */
.prose ul:where(:not([class]), .wp-block-list) {
	list-style-type: "";
	padding-inline-start: 0;
}

.prose ul:where(:not([class]), .wp-block-list) > li {
	position: relative;
	padding-inline-start: 1.25rem;
}

.prose ul:where(:not([class]), .wp-block-list) > li::before {
	content: "";
	position: absolute;
	top: .62em;
	inset-inline-start: 0;
	width: 7px;
	height: 7px;
	background: var(--mark);
	border-radius: 1.5px;
}

/* Nummerierung: Die Reihenfolge ist echt, deshalb darf die Ziffer in Plex Mono
   stehen. ::marker statt eines eigenen Zählers, damit start, reversed und
   value aus dem Editor weiter stimmen. */
.prose ol:where(:not([class]), .wp-block-list) {
	padding-inline-start: 1.75rem;
}

.prose ol:where(:not([class]), .wp-block-list) > li::marker {
	font-family: var(--font-mono);
	font-size: var(--fs-mono);
	font-weight: 500;
	color: var(--text-soft);
}

.prose li + li {
	margin-top: .5em;
}

.prose li > :is(ul, ol) {
	margin-block: .5em 0;
}

/* FIX: :where(.prose) hält die Regel auf Elementstärke. Mit .prose img
   (0,1,1) schlug height: auto die Klassenregeln der Komponenten im Artikel,
   etwa .video-embed__poster (height: 100 %): Ein nicht 16:9 geschnittenes
   Poster ragte unten aus dem Bildschirm über Marken und Hinweiszeile.
   Redaktionsbilder tragen wp-image-N, deshalb geht hier kein :not([class]). */
:where(.prose) img {
	height: auto;
	border-radius: var(--r-media);
}

/* FIX: nur Bildunterschriften ohne eigene Klasse bzw. mit den Core-Klassen
   (Block-Editor, [caption]/[gallery]-Shortcode), wie bei Listen und Zitaten.
   Vorher schlug .prose figcaption (0,1,1) im Artikel .frame__note und
   .frame__cap (0,1,0): Der Hinweis unter dem Sucherrahmen stand 8 px statt
   --mark-off + .75rem unter dem Bildschirm, mitten in den unteren Marken
   (5.4). Die Gewichtung gegenüber den Block-Styles von WordPress bleibt. */
.prose figcaption:where(:not([class]), .wp-element-caption, .wp-caption-text) {
	margin-top: .5rem;
	font-size: var(--fs-xs);
	line-height: 1.5;
	color: var(--text-soft);
}

/* Zitat aus dem Editor (Core-Block bzw. blockquote ohne Klasse) in der Optik
   von smm-quote (6.23, 74-blocks.css): schmal und schwer wie ein O-Ton, mit
   hängendem „ vor der Satzkante, ohne Seitenlinie, ohne Fläche (9.6).
   FIX: Vorher ein fetter Zweizeiler ohne jedes Zitatzeichen, der im Artikel
   wie eine verirrte H3 wirkte.
   Die Zeichen kommen per quotes an die Absätze, nicht an das blockquote:
   Dessen ::before stünde als eigener anonymer Block allein über dem Text,
   und ein text-indent am blockquote erbte bis in jede Absatz- und
   cite-Zeile. Redaktion: Core-Zitate ohne eigene „“ eingeben, sonst stehen
   die Zeichen doppelt. */
.prose blockquote:where(:not([class]), .wp-block-quote) {
	margin-block: 2em;
	padding: 0;
	font: 650 clamp(1.375rem, 1.1rem + 1vw, 1.875rem)/1.3 var(--font-display);
	font-stretch: 88%;
	letter-spacing: -.005em;
	text-wrap: pretty;
	color: var(--text);
	quotes: "„" "“";
}

.prose blockquote:where(:not([class]), .wp-block-quote) > p:first-of-type {
	text-indent: -.42em;
}

.prose blockquote:where(:not([class]), .wp-block-quote) > p:first-of-type::before {
	content: open-quote;
}

.prose blockquote:where(:not([class]), .wp-block-quote) > p:last-of-type::after {
	content: close-quote;
}

.prose blockquote:where(:not([class]), .wp-block-quote) > p:last-of-type {
	margin-bottom: 0;
}

/* Klassisches blockquote ohne Absätze (Text direkt im Element). */
.prose blockquote:not([class]):not(:has(> p)) {
	text-indent: -.42em;
}

.prose blockquote:not([class]):not(:has(> p))::before {
	content: open-quote;
}

.prose blockquote:not([class]):not(:has(> p))::after {
	content: close-quote;
}

/* FAQ-Antworten haben kein seitliches Polster, und ::details-content
   schneidet ab 6 px Überstand ab (62-faq.css). Dort steht das „ deshalb
   innerhalb der Satzkante. */
.faq__a blockquote > p:first-of-type,
.faq__a blockquote:not(:has(> p)) {
	text-indent: 0;
}

.prose blockquote:where(:not([class]), .wp-block-quote) cite {
	display: block;
	margin-top: .75rem;
	font: 500 var(--fs-xs)/1.3 var(--font-text);
	font-style: normal;
	color: var(--text-soft);
}

.prose hr {
	margin: 2.5em 0;
}

.prose code {
	padding: .1em .35em;
	background: var(--surface);
	border-radius: var(--r-plate);
	font-family: var(--font-mono);
	font-size: .875em;
}

.prose pre {
	overflow-x: auto;
	padding: 1rem;
	background: var(--surface);
	border-radius: var(--r-media);
	font: 500 var(--fs-mono)/1.6 var(--font-mono);
}

.prose pre code {
	padding: 0;
	background: none;
	font-size: inherit;
}

/* FIX: Tabellen im Fließtext bekommen einen eigenen Scrollbereich. Ohne den
   schiebt eine vierspaltige Vergleichstabelle den Artikel auf dem Handy aus
   dem Bild; overflow-x: clip am Dokument versteckt das nur, abgeschnitten ist
   es trotzdem. Die Mindestbreite greift erst ab der dritten Spalte, damit
   zweispaltige Tabellen weiterhin ganz ohne Scrollen zu lesen sind. */
.prose .wp-block-table {
	max-width: 100%;
	overflow-x: auto;
}

.prose table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--fs-small);
	line-height: 1.5;
}

.prose table:has(th:nth-child(3), td:nth-child(3)) {
	min-width: 34rem;
}

/* FIX: Tabellen aus dem ACF-Editor kommen ohne figure-Wrapper. display: block
   macht das Element selbst scrollbar; die Zeilenstruktur bleibt über die
   Kindelemente erhalten. */
.prose > table {
	display: block;
	max-width: 100%;
	overflow-x: auto;
}

/* FIX: WordPress lädt auf Artikeln die Core-Tabellenregeln (wp-block-table:
   „td, th { border: 1px solid }“ in currentColor, „thead { border-bottom:
   3px solid }“) vor app.css mit gleicher Spezifität (0,1,1). Hier wurde nur
   border-bottom überschrieben, übrig blieben dunkle Senkrechte, ein Außenrand
   und ein 3-px-Balken unter dem Kopf: drei Linienstärken in Excel-Optik.
   „table :is(th, td)“ liegt mit (0,1,2) darüber und hängt damit nicht mehr an
   der Ladereihenfolge, die WP Rocket beim Zusammenfassen ändern kann. Es
   bleibt eine einzige 1-px-Zeilenlinie. */
.prose table :is(th, td) {
	padding: .75rem 1rem;
	border: 0;
	border-bottom: 1px solid var(--line);
	text-align: start;
	vertical-align: top;
}

/* Der Kopf setzt sich über seine Fläche (--surface) ab, nicht über eine
   Linie. Ein Rahmen an thead bliebe bei border-collapse ohnehin hinter der
   Zellenlinie verborgen. */
.prose table > :is(thead, tfoot) {
	border: 0;
}

.prose thead th {
	background: var(--surface);
	font: 600 var(--fs-xs)/1.4 var(--font-text);
	color: var(--text);
}

/* ===== 03-layout.css ===== */
/* =========================================================================
   03 Raster und Sektionen (Besitz: Fundament F1)

   Alle Flächen sind flach: keine Textur, kein Rauschen, kein Verlauf, keine
   Blobs. Tiefe entsteht nur durch Tafeln, Rahmenmarken und den Wechsel
   zwischen Weiß, Kreide und Studio.
   ========================================================================= */

.container {
	width: min(100% - 2 * var(--gutter), var(--container));
	margin-inline: auto;
}

/* Linksbündige Varianten setzen in ihrer Sektionsdatei margin-inline-start: 0. */
.container--narrow {
	max-width: var(--container-narrow);
	margin-inline: auto;
}

/* FIX: minmax(0, 1fr) statt 1fr. Eine 1fr-Spur ist mindestens so breit wie ihr
   breitester Inhalt (langes Wort, select, Tabelle) und schob den Text auf dem
   Handy aus dem Bild. */
.grid-12 {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	column-gap: var(--gap);
}

@media (min-width: 62rem) {
	.grid-12 {
		grid-template-columns: repeat(12, minmax(0, 1fr));
	}
}

/* FIX: Struktur-Container dürfen in Flex- und Grid-Eltern schrumpfen. */
.site-main {
	display: block;
	min-width: 0;
}

/* ---------- Sektionen ----------
   Der Abstand läuft über --section-pad, damit „gleicher Grund hintereinander“
   nur den Faktor oben halbiert: Eine Sektion mit space-tight wird zu halb
   tight, space-none bleibt 0, und eine Sektionsdatei, die ihr eigenes
   padding-block setzt (Hero), wird von der Nachbarregel nicht überstimmt. */

.section {
	--section-pad: var(--section-y);
	--section-pad-top: 1;
	padding-block: calc(var(--section-pad) * var(--section-pad-top)) var(--section-pad);
	background: var(--bg);
	color: var(--text);
}

/* FIX: Die Klasse kommt aus smm_section_attrs() für den Standardabstand. Sie
   existiert, damit die Absicht im Markup steht; der Wert ist der von .section. */
.section--space-default {
	--section-pad: var(--section-y);
}

.section--space-tight {
	--section-pad: var(--section-y-tight);
}

.section--space-loose {
	--section-pad: var(--section-y-loose);
}

.section--space-none {
	--section-pad: 0px;
}

/* Gleicher Grund hintereinander: oberer Abstand halbiert */
.section--bg-white + .section--bg-white,
.section--bg-mist + .section--bg-mist,
.section--bg-deep + .section--bg-deep,
.section--bg-teal + .section--bg-teal {
	--section-pad-top: .5;
}

/* Studio-Panels (Megamenü-Teaser, cta_band auf Weiß/Kreide, smm-cta-box,
   Footer) malen ihren Grund selbst; die Tokens kippen in 00-tokens.css. */
.theme-studio {
	background-color: var(--bg);
	color: var(--text);
}

/* ===== 04-utilities.css ===== */
/* =========================================================================
   04 Hilfsklassen (Besitz: Fundament F1)
   ========================================================================= */

/* Nur für Screenreader. FIX: position mit !important wie im alten Stand –
   eine Komponentenregel mit position: relative (später in der Kaskade) machte
   den Text sonst sichtbar und schob die Zeile auf.
   FIX: .screen-reader-text ist die Klasse, die WordPress selbst ausgibt
   (Paginierung, Suchformular, „weiterlesen“). Im alten CSS stand sie durch
   einen verrutschten Kommentar vor der Transkript-Regel und war nie
   versteckt. */
.sr-only,
.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* WordPress-Links „Zum Inhalt springen“ u. ä. werden bei Fokus sichtbar. */
.screen-reader-text:focus {
	position: absolute;
	top: .75rem;
	inset-inline-start: .75rem;
	z-index: var(--z-skip);
	width: auto;
	height: auto;
	margin: 0;
	padding: .625rem 1.25rem;
	clip: auto;
	clip-path: none;
	white-space: normal;
	background: var(--text);
	color: var(--bg);
	border-radius: var(--r-control);
}

/* Lead / Intro (3.4): Schibsted 400 1.1875rem/1.55 */
.lead {
	font-size: var(--fs-lead);
	line-height: 1.55;
	color: var(--text-soft);
}

/* Standardgröße für smm_icon(). Ohne Größe würde ein SVG mit viewBox durch
   width/height: auto aus der Basis so breit wie seine Spalte. */
.icon {
	flex: none;
	width: 1.5rem;
	height: 1.5rem;
}

/* Hinweis für Redakteure, wenn eine Sektionsvorlage fehlt (nur mit Rechten). */
.section-missing {
	padding-block: 1rem;
	background: var(--surface);
	color: var(--text);
	font: 500 var(--fs-small)/1.5 var(--font-text);
	border-block: 1px solid var(--line);
}

/* Ausrichtungsklassen aus dem klassischen Editor. Nur Medien werden zentriert,
   Text bleibt linksbündig (keine zentrierten Sektionen, 8.4). */
.alignleft {
	float: left;
	margin: .25rem 1.5rem 1rem 0;
}

.alignright {
	float: right;
	margin: .25rem 0 1rem 1.5rem;
}

.aligncenter {
	display: block;
	margin-inline: auto;
}

@media (max-width: 29.99rem) {
	.alignleft,
	.alignright {
		float: none;
		margin: 0 0 1rem;
	}
}

/* ===== 05-section-header.css ===== */
/* =========================================================================
   05 Sektionskopf (Besitz: Fundament F1) – smm_section_header()

   Modi: split (Standard), stack, aside. Keine Zentrierung, kein
   ::before am Kicker, keine Versalien – nirgends.
   Markup:
   <div class="section__header section__header--split [section__header--solo]">
     <div class="section__head"><p class="eyebrow">…</p><h2 class="section__title">…</h2></div>
     <p class="section__intro">…</p>
   </div>
   ========================================================================= */

.section__header {
	margin-bottom: var(--head-gap);
}

/* 375 px: Kicker, .5rem Abstand, H2 28 px, Intro 17 px mit 1rem Abstand. */
.eyebrow {
	margin: 0 0 .5rem;
	font: 600 var(--fs-small)/1.35 var(--font-text);
	color: var(--accent-text);
}

.section__title {
	max-width: 22ch;
	font-size: var(--fs-h2);
}

/* Ein Sektionskopf mit h1 (erste Sektion einer Seite ohne Hero, z. B. das
   Erstgespräch-Formular) spricht in Seitenkopf-Größe (3.4). */
h1.section__title {
	max-width: 20ch;
	font-size: var(--fs-h1-page);
}

.section__intro {
	max-width: 36ch;
	margin: 1rem 0 0;
	font-size: var(--fs-body);
	line-height: 1.55;
	color: var(--text-soft);
}

@media (min-width: 48rem) {
	.eyebrow {
		margin-bottom: .875rem;
	}

	.section__intro {
		font-size: var(--fs-lead);
	}
}

@media (min-width: 62rem) {
	/* split: Kicker und Titel links (Spalten 1–7), das Intro rechts (8–12)
	   auf der Grundlinie der letzten Titelzeile.
	   ABWEICHUNG von 4.3 (7fr/5fr, gap clamp(2rem, 5vw, 5rem)): Der Kopf liegt
	   auf demselben 12er-Raster wie .grid-12. Mit eigenen fr-Spalten begann das
	   Intro bei 1440 px 11 px rechts von Spalte 8 der Sektion darunter
	   (channel_proof, Schnitt-Spur), die Kanten liefen knapp aneinander vorbei.
	   Zwei Zeilen statt align-items: end: Kicker in Zeile 1, Titel und Intro
	   teilen Zeile 2 (subgrid im Kopf). Ist das Intro kürzer als der Titel,
	   sitzt es unten auf dessen letzter Zeile wie bisher. Ist es länger, wächst
	   Zeile 2 nach unten, und das Intro beginnt auf Höhe der ersten Titelzeile.
	   Vorher stieg ein fünf- bis sechszeiliges Intro 20–60 px über den Kicker.
	   Sehr lange Intros stellt smm_section_header() ohnehin auf stack um. */
	.section__header--split {
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		grid-template-rows: auto auto;
		column-gap: var(--gap);
	}

	.section__header--split .section__head {
		display: grid;
		grid-column: 1 / span 7;
		grid-row: 1 / span 2;
		grid-template-rows: subgrid;
	}

	.section__header--split .eyebrow {
		grid-row: 1;
	}

	.section__header--split .section__title {
		grid-row: 2;
		align-self: start;
	}

	.section__header--split .section__intro {
		grid-column: 8 / -1;
		grid-row: 2;
		align-self: end;
		margin: 0;
		padding-bottom: .35em;
	}

	/* Nur ein Intro, weder Kicker noch Titel: Es steht links, nicht allein
	   in der rechten Spalte. */
	.section__header--split .section__intro:only-child {
		grid-column: 1 / span 7;
	}

	/* Ohne Intro gibt es keine rechte Spalte, die das Raster tragen müsste. */
	.section__header--solo {
		display: block;
	}

	/* Automatisch gestapelter Kopf mit langem Intro (smm_section_header):
	   Das Intro liest sich als Lead unter dem Titel. Mit 36ch stünden 200 bis
	   250 Zeichen als schmale Säule in sechs, sieben Zeilen neben leerer
	   Fläche. 46ch entspricht bei 1440 px ungefähr der Titelbreite (22ch bei
	   --fs-h2), Titel und Intro bilden so einen Block. */
	.section__header--lead .section__intro {
		max-width: 46ch;
		margin-top: 1.25rem;
	}

	/* aside: gestapelt in der linken Spalte eines zweispaltigen
	   Sektionslayouts, sticky. Die rechte Spalte steht daneben, der Abstand
	   nach unten entfällt deshalb. */
	.section__header--aside {
		position: sticky;
		top: calc(var(--header-h) + 2rem);
		margin-bottom: 0;
	}
}

/* Niedrige Fenster: Ein klebender Kopf, der höher ist als der Rest des
   Fensters, würde Inhalt dauerhaft verdecken. */
@media (min-width: 62rem) and (max-height: 44rem) {
	.section__header--aside {
		position: static;
	}
}

/* ---------- Startseite: ein Kopfmuster ----------
   Feedback André vom 09.10.2026: „Die Startseite wirkt noch etwas
   unübersichtlich.“ Dort standen drei Kopfanordnungen nebeneinander (Titel
   links mit Intro rechts, gestapelt, zentriert). Auf der Startseite stehen
   Titel und Intro jetzt in jeder Sektion gleich: gestapelt, linksbündig, das
   Intro als Lead unter dem Titel. Die Unterseiten behalten den geteilten Kopf. */
@media (min-width: 62rem) {
	.home .section__header--split {
		display: block;
	}

	.home .section__header--split .section__intro {
		max-width: 46ch;
		margin: 1rem 0 0;
		padding-bottom: 0;
	}
}

/* ===== 06-highlight.css ===== */
/* =========================================================================
   06 Hervorhebung und Untertitel-Tafel (Besitz: Fundament F1)
   smm_highlight( $text, 'cut' | 'plate' | 'say' )

   Die Tafel steht höchstens dreimal pro Seite: H1, Titel des Schluss-CTA,
   Brückensatz in pain_points (Regel 1.2). Prüfung 9.1:
   document.querySelectorAll('.hl--plate, .caption-plate:not(.caption-plate--oton)').length <= 3
   ========================================================================= */

/* Bauchbinden-Schnitt: Betonung über Breite und Gewicht, nicht über Farbe.
   Kein Balken, kein Hintergrundbild – funktioniert auch bei
   Farbfehlsichtigkeit (5.2). */
/* ABWEICHUNG von 4.4 (850/76 %, Größe erbt), Befund „zweite Stimme sieht
   wie Renderfehler aus“: Breite und Gewicht am Rand der instanzierten Datei
   (72 %, 880; 01-fonts.css), die H2 dazu breiter und ruhiger (700/100 %,
   00-tokens.css). Schmale Schnitte wirken bei gleicher Schriftgröße kleiner;
   1.04em gleicht das aus, ohne die Zeile zu sprengen. Mehr (1.08em) sah im
   Vergleich kaum anders aus, machte aber „Empfehlungsprogramm“ in der
   FAQ-Randspalte bei 992 und 1152 px breiter als die Spalte (62-faq.css).
   Mit 1.04em und der geerbten Laufweite liegt das Wort bei 992, 1152 und
   1440 px bei höchstens 96 % der Spaltenbreite, vorher 95 %.
   line-height: 1 hält die Zeilenhöhe: 1.04em × 1 bleibt unter den 1.08
   bzw. 1.2 der Überschrift, eine Zeile mit Hervorhebung steht nicht höher
   als die übrigen.
   word-spacing: Das Leerzeichen schrumpft mit der Breitenachse auf 72 %,
   „einer davon dein“ lief sonst zu einem Wortblock zusammen. */
.hl {
	font-style: normal;
	font-stretch: var(--w-cut);
	font-weight: var(--wg-cut);
	font-size: 1.04em;
	line-height: 1;
	word-spacing: .04em;
	color: inherit;
}

/* Untertitel-Tafel: bricht wortweise um, jede Zeile bekommt ihre eigene
   Tafel (box-decoration-break, Safari nur mit Präfix).
   ABWEICHUNG von 4.4 (padding .02em .14em .06em):
   - Satzkante: Der negative Rand hebt die linke Polsterung auf. Mit clone
     gilt er für jedes Zeilenstück, der Tafeltext steht damit auf derselben
     Kante wie die übrigen Zeilen, die Fläche ragt .14em nach links in den
     Wortabstand bzw. den Gutter (mindestens 18 px). Vorher sprang eine
     Zeile, die mit der Tafel beginnt, 6–12 px nach rechts ein, und vor der
     Tafel stand ein doppelt breiter Wortabstand.
   - Fuge: oben 0, unten .03em. Die Tafel ist damit niedriger als die
     Zeilenhöhe 1.16, zwischen zwei Tafelzeilen bleibt eine Fuge von .045em
     (4 px bei 90 px, 1,6 px bei 36 px). Vorher stießen die Zeilen zu einem
     Treppenblock zusammen, statt als einzelne Untertitelzeilen zu lesen. */
.hl--plate {
	font-stretch: inherit;
	font-weight: inherit;
	/* Die Tafel spricht in der Titelschrift: Größe, Zeilenhöhe und
	   Wortabstand des Bauchbinden-Schnitts (.hl) gelten hier nicht. */
	font-size: inherit;
	line-height: inherit;
	word-spacing: inherit;
	/* Ein Untertitel trennt nicht (Befund „Silbentrennung in
	   Display-Überschriften“, 02-base.css). */
	-webkit-hyphens: manual;
	hyphens: manual;
	background: var(--plate-bg);
	color: var(--plate-fg);
	margin-inline-start: -.14em;
	padding: 0 .14em .03em;
	border-radius: var(--r-plate);
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
}

/* Tafeln verdecken keine Unterlängen der Zeile darüber. :is() hebt die Regel
   über eine einfache Titelklasse der Sektionsdatei (z. B. .hero__title mit
   line-height 1.1), damit die Tafelzeilen nie ineinanderlaufen. */
/* Leerzeichen vor einer Tafel (span.hl__gap aus smm_highlight): gibt den
   Wortabstand zurück, den der negative Rand der Tafel mitten in der Zeile
   frisst. Am Zeilenanfang wirkt nur der Rand, die Satzkante bleibt. */
.hl__gap {
	margin-inline-end: .14em;
}

:is(h1, h2, h3, p):has(.hl--plate),
.cta-band__title,
.footer-cta__title {
	line-height: 1.16;
}

/* Gelöste Tafelbindung (span.hl__nb aus smm_plate_runs, Befund
   titel-umbruch-tafel): Unter 48rem darf der Lauf umbrechen, sonst liefe er
   bei 320 px über. Ab 48rem trägt eine CTA-Titelzeile (--fs-cta höchstens
   48 px, schmalste Spalte im Split rund 500 px) die höchstens 21 Zeichen des
   Laufs, also bleibt „rund“ nicht allein vor „20 Kurzvideos“ stehen. Die
   Hero-Regel steht in 40-hero.css. */
@media (min-width: 48rem) {
	:is(.cta-band__title, .footer-cta__title) .hl__nb {
		white-space: nowrap;
	}
}

/* Kurze Läufe (span.hl__nb--s, höchstens 18 Zeichen, Befund zeilenfall-tafel)
   bleiben in jeder Breite ganz: gelöste Tafelbindungen wie „über 250
   Millionen“ (ueber-uns, vorher drei gestapelte Tafeln) und ein kurzes Wort
   mit Tafel wie „die Kunden bringen“ (strassenumfragen, vorher „die“ allein
   in der Zeile). white-space statt U+00A0: Unter 30rem gilt für Überschriften
   overflow-wrap: anywhere (02-base.css), das ein geschütztes Stück, das die
   15ch-Satzbreite der Hero-H1 um wenige Pixel überragt, mitten im Wort
   bräche. Gemessen von 320 bis 1920 px: Im Split-Hero bleiben mindestens
   14 px Luft zur Textspalte, in Seitenkopf und CTA-Titel (kleinere Schrift)
   mehr. Nur die breite Titelkarte ist unter 48rem mit 34 px Schrift zu groß
   dafür („rund 20 Kurzvideos“ 286 px bei 284 px Satz); dort gilt ab 48rem
   die Regel aus 40-hero.css. Nicht in schmalen Satzspalten wie der H1 im
   Formular von erstgespraech: „deine erste Frage“ lief dort bei 992 px 19 px
   über die Spalte, deshalb nur die hier gemessenen Titel. */
:is(.hero__title, .page-head__title, .case-head__title, .cta-band__title, .footer-cta__title) .hl__nb--s {
	white-space: nowrap;
}

@media (max-width: 47.99rem) {
	.hero--wide .hero__title .hl__nb--s {
		white-space: normal;
	}
}

/* Bauchbinden-Schnitt aus mehreren Wörtern bis 20 Zeichen (em.hl--keep aus
   smm_highlight, Befund zeilenfall-zweite-stimme): Die zweite Stimme riss
   sonst über den Umbruch („mehr Gewicht / hat als deine Anzeige“ auf der
   Startseite). Wie oben white-space statt U+00A0, damit overflow-wrap unter
   30rem das Stück nicht mitten im Wort trennt. */
.hl--keep {
	white-space: nowrap;
}

/* Hero-Wortauftakt: nur Hero-H1 bei $smm_index === 0 und höchstens 6 Wörtern.
   Keyframes an beiden Enden identisch, fill-mode none: harter Wechsel ohne
   Zwischenfarbe, davor und danach steht die ruhige Tafel. Reines CSS, läuft
   beim Laden und ist damit immun gegen „JavaScript verzögern“. Einmal,
   höchstens 6 × 360 ms, unter 3 Wechseln pro Sekunde, Fläche je Wort unter
   der Flash-Schwelle. Unter prefers-reduced-motion: reduce aus. */
@media (prefers-reduced-motion: no-preference) {
	.hl--say .hl__w {
		animation: hl-say 320ms linear calc(500ms + var(--i, 0) * 360ms) 1 none;
		border-radius: var(--r-plate);
	}
}

@keyframes hl-say {
	0%,
	100% {
		background-color: var(--c-caption);
		color: var(--c-ink);
		box-shadow: 0 0 0 .08em var(--c-caption);
	}
}

/* Tafel für den Brückensatz (pain_points) – 16,17 auf Weiß wie auf Studio.
   ABWEICHUNG von 5.1: negativer Rand wie bei .hl--plate. Jede Zeile des
   Brückensatzes beginnt mit der Tafel; ohne ihn stand der Text .35em
   (6–9 px) rechts der Satzkante des Absatzes darüber. Die Fläche ragt dafür
   in den Gutter (mindestens 18 px). */
/* hyphens: manual: .pain__bridge trennt unter 22.5rem (50-pain-points.css),
   die Tafel erbte das („zusätz-/lich“ bei 320 px). Ein Untertitel trennt
   nicht; gemessen passt bei 320 px jedes Wort der Kernaussagen allein in
   die Zeile (höchstens 90 %), der Satz bricht also nur an Wortgrenzen. */
.caption-plate {
	-webkit-hyphens: manual;
	hyphens: manual;
	background: var(--bridge-bg);
	color: var(--bridge-fg);
	margin-inline-start: -.35em;
	padding: .08em .35em;
	border-radius: var(--r-plate);
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
}

.caption-plate a {
	color: inherit;
}

/* O-Ton im Reel: gelbe Untertitelzeile auf Studio 88 %, auch über einem
   weißen Poster mindestens 6,95:1 (Tabelle 2.2). Zentrierung und
   Zeilenbegrenzung setzt .reel__quote (Team B). */
.caption-plate--oton {
	/* Zentriert im Reel: kein Ausgleich zur Satzkante, sonst säße jede Zeile
	   um .35em nach links versetzt. */
	margin-inline-start: 0;
	background: rgb(13 36 39 / 88%);
	color: var(--c-caption);
	font: 700 .9375rem/1.55 var(--font-text);
}

/* ===== 10-buttons.css ===== */
/* =========================================================================
   10 Buttons (Besitz: Fundament F1) – smm_button(), smm_main_cta()

   Teal ist Absender und Weg zum Erstgespräch: Ein Primärbutton führt nur zu
   smm_contact_url(), smm_booking_url() oder #gespraech, alles andere ist
   Ghost. Die Regel setzt smm_button() durch, nicht das CSS.

   <a class="btn btn--primary btn--lg" href="…" data-cta="hero">
     <span class="btn__label">Kostenloses Erstgespräch</span>
     <span class="btn__go" aria-hidden="true"><svg viewBox="0 0 24 24">…</svg></span>
   </a>
   <a class="btn btn--ghost" href="…"><span class="btn__label">…</span></a>

   Keine Pillen, kein Schatten, kein translateY. Farben wechseln hart, nur der
   Pfeil bewegt sich (7.3 Nr. 8).
   ========================================================================= */

.btn {
	--btn-go-w: 3rem;
	display: inline-flex;
	align-items: stretch;
	min-height: 3rem;
	max-width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: var(--r-control);
	overflow: hidden;
	background: transparent;
	color: inherit;
	font: 650 1rem/1.2 var(--font-display);
	font-stretch: 100%;
	text-align: start;
	text-decoration: none;
	vertical-align: middle;
	cursor: pointer;
}

.btn__label {
	display: flex;
	align-items: center;
	padding: .8rem 1.25rem;
}

.btn__go {
	display: grid;
	flex: none;
	place-items: center;
	width: var(--btn-go-w);
}

.btn__go svg {
	width: 18px;
	height: 18px;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
	fill: none;
	transition: transform var(--dur-1) var(--ease-cut);
}

.btn--lg {
	--btn-go-w: 3.5rem;
	min-height: 3.5rem;
	font-size: 1.0625rem;
}

.btn--sm {
	--btn-go-w: 2.75rem;
	min-height: 2.75rem;
	font-size: .9375rem;
}

/* ---------- Primär ---------- */

/* Die Fläche liegt zusätzlich am Element selbst: Ein .btn--primary ohne
   btn__label (fremdes oder altes Markup) bleibt so ein lesbarer Button statt
   weißer Schrift auf Weiß. Mit Label deckt die Label-Fläche genau dieselbe
   Farbe, das Segment liegt darüber. */
.btn--primary {
	background-color: var(--btn-label-bg);
	color: var(--btn-label-fg);
}

.btn--primary .btn__label {
	background: var(--btn-label-bg);
	color: var(--btn-label-fg);
}

.btn--primary .btn__go {
	background: var(--btn-go-bg);
	color: var(--btn-go-fg);
}

.btn--primary:where(:hover, :active):where(:not(:disabled, [aria-disabled="true"])),
.btn--primary:where(:hover, :active):where(:not(:disabled, [aria-disabled="true"])) .btn__label {
	background-color: var(--btn-label-bg-h);
}

.btn--primary:where(:hover, :active):where(:not(:disabled, [aria-disabled="true"])) .btn__go {
	background-color: var(--btn-go-bg-h);
}

.btn--primary:where(:hover):where(:not(:disabled, [aria-disabled="true"])) .btn__go svg {
	transform: translateX(3px);
}

/* ---------- Ghost ---------- */

/* FIX: Der Alias .btn--secondary (alte zweite Füllfarbe) ist entfernt. Kein
   Template und kein JS-Modul gibt ihn mehr aus, und smm_button_classes()
   (inc/helpers.php) übersetzt ihn für smm_button() und smm_main_cta() schon
   im PHP zu btn--ghost. Tote Selektoren erschwerten nur das Safelisting in
   WP Rocket. */
.btn--ghost {
	background: transparent;
	color: var(--ghost-fg);
	box-shadow: inset 0 0 0 1.5px var(--ghost-border);
}

.btn--ghost:where(:hover, :active):where(:not(:disabled, [aria-disabled="true"])) {
	background: var(--ghost-bg-h);
	color: var(--ghost-fg-h);
	box-shadow: none;
}

/* ---------- Breite, Zustände ---------- */

.btn--block {
	display: flex;
	width: 100%;
}

.btn--block .btn__label {
	flex: 1;
}

/* Rückfall für Markup ohne btn__label (z. B. ein reiner Text im Button):
   Innenabstand und Zentrierung, die sonst das Label liefert. Ein <input>
   hat nie Kinder und bekommt seinen Abstand im Submit-Block unten. */
.btn:not(input, :has(.btn__label)) {
	align-items: center;
	padding: .8rem 1.25rem;
}

.btn:disabled,
.btn[aria-disabled="true"] {
	opacity: .45;
	cursor: not-allowed;
}

/* FIX: Ein Button ist kein Fließtext-Link. Auf dunklen Abschnitten griff
   [data-theme="dark"] a mit höherer Spezifität als .btn und färbte die weiße
   Schaltfläche hellteal: 2,67:1 statt 4,5:1, ausgerechnet beim wichtigsten
   Klick der Seite. Die Farben kommen heute aus den Tokens; Unterstreichung
   bleibt trotzdem sicher aus. */
[data-theme="dark"] a.btn,
.theme-studio a.btn {
	text-decoration: none;
}

/* ---------- Contact Form 7 Submit ----------
   Ein <input> kann kein Segment-Kind tragen. Label-Fläche, Segment und Pfeil
   liegen deshalb als drei Hintergrundebenen übereinander: Pfeil (Token
   --btn-go-arrow, kippt mit dem Grund), einfarbige Segmentfläche rechts,
   Label-Fläche. Ein inset-box-shadow als Segment würde den Pfeil überdecken,
   weil Innenschatten über dem Hintergrundbild gemalt werden. */
.wpcf7-submit,
input.btn {
	-webkit-appearance: none;
	appearance: none;
	display: inline-block;
	min-height: 3rem;
	max-width: 100%;
	padding: .8rem calc(var(--btn-go-w, 3rem) + .5rem) .8rem 1.25rem;
	border: 0;
	border-radius: var(--r-control);
	background:
		var(--btn-go-arrow) right calc(var(--btn-go-w, 3rem) / 2 - 9px) center / 18px 18px no-repeat,
		linear-gradient(var(--btn-go-bg) 0 0) right center / var(--btn-go-w, 3rem) 100% no-repeat,
		var(--btn-label-bg);
	color: var(--btn-label-fg);
	font: 650 1rem/1.2 var(--font-display);
	font-stretch: 100%;
	text-align: start;
	white-space: normal;
	cursor: pointer;
}

input.btn--lg {
	min-height: 3.5rem;
	font-size: 1.0625rem;
}

input.btn--sm {
	min-height: 2.75rem;
	font-size: .9375rem;
}

.wpcf7-submit:where(:hover, :active):where(:not(:disabled)),
input.btn:where(:hover, :active):where(:not(:disabled)) {
	background:
		var(--btn-go-arrow) right calc(var(--btn-go-w, 3rem) / 2 - 12px) center / 18px 18px no-repeat,
		linear-gradient(var(--btn-go-bg-h) 0 0) right center / var(--btn-go-w, 3rem) 100% no-repeat,
		var(--btn-label-bg-h);
}

.wpcf7-submit:disabled {
	opacity: .45;
	cursor: not-allowed;
}

/* ---------- Reihe ---------- */

/* Immer linksbündig. FIX: Die Regel für .btn-row--center ist entfernt. Kein
   Template gibt die Klasse mehr aus; stünde sie noch in altem Markup, bleibt
   sie ohne eigene Regel genau das Alias ohne Wirkung, das 4.5 verlangt, denn
   .btn-row ist schon linksbündig (9.6). */
.btn-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-start;
	gap: .75rem;
}

/* ---------- Textlink mit Pfeil ---------- */

.arrow-link {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	min-height: 1.5rem; /* Zielgröße 24 px (WCAG 2.5.8) */
	color: var(--accent-text);
	font-family: var(--font-text);
	font-weight: 600;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

.arrow-link:hover {
	text-decoration-thickness: 2px;
}

.arrow-link svg {
	flex: none;
	width: 16px;
	height: 16px;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
	fill: none;
	transition: transform var(--dur-1) var(--ease-cut);
}

.arrow-link:hover svg {
	transform: translateX(3px);
}

/* ---------- Schmale Bildschirme: Label einzeilig halten ----------
   FIX (Befund button-label-umbruch-mobil): Bei 375 px blieben einem btn--lg
   im Studio-Panel (Satzbreite 299 px) nach Segment (56 px) und Label-Padding
   (40 px) nur 203 px Text. „Kostenloses Erstgespräch“, das Label an rund 66
   Stellen, brach um, der Primärbutton wurde 66 px hoch und stand über einem
   56 px hohen Ghost. Unter 30rem deshalb Segment 3rem wie beim Standard-
   Button und 1rem Label-Padding: Das Label steht damit im Panel bei 375 px
   und in Hero und footer-cta bei 320 px einzeilig. Die Schrift bleibt ab
   360 px bei 17 px wie in 4.5; erst darunter 16 px.
   Bricht ein langes Label trotzdem um („Umfang im Erstgespräch klären“),
   verteilt text-wrap: balance die Wörter, statt ein einzelnes Schlusswort
   in die zweite Zeile zu stellen. Das Segment bleibt quadratisch hoch
   genug (min-height), nur die Breite ändert sich. */
@media (max-width: 29.99rem) {
	.btn--lg {
		--btn-go-w: 3rem;
	}

	.btn__label {
		padding-inline: 1rem;
		text-wrap: balance;
	}

	.wpcf7-submit,
	input.btn {
		padding-left: 1rem;
	}
}

@media (max-width: 22.49rem) {
	.btn--lg,
	input.btn--lg {
		font-size: 1rem;
	}
}

/* ===== 11-forms.css ===== */
/* =========================================================================
   11 Formularfelder (Besitz: Fundament F1)

   Contact Form 7 bringt eigenes Markup mit (inc/forms.php hängt .smm-form an
   jedes Formular). Die Felder sehen überall gleich aus: weiß mit Tintenschrift,
   auch auf Studio. Schibsted 17 px verhindert den Zoom in iOS-Safari.
   CF7-Zustandsregeln des Plugins sind teils zwei Klassen plus Element stark;
   die Überschreibungen unten sind bewusst eine Stufe spezifischer, statt
   !important zu nutzen.
   ========================================================================= */

/* ---------- Raster ---------- */

/* FIX: minmax(0, 1fr) statt 1fr: Ein select ist von Haus aus so breit wie
   seine längste Option. Ohne die 0 als Minimum zieht es die Spalte auf und
   die Felder stehen auf dem Handy über den Kartenrand hinaus. */
.smm-form__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 1.25rem 1rem;
}

@media (min-width: 36rem) {
	.smm-form__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.smm-form__field {
	min-width: 0;
	margin: 0;
}

.smm-form__field--full {
	grid-column: 1 / -1;
}

.smm-form .wpcf7-form-control-wrap {
	display: block;
}

/* ---------- Label ---------- */

:where(.smm-form, .post-password-form) label {
	display: block;
	margin-bottom: .375rem;
	font: 600 var(--fs-small)/1.35 var(--font-text);
	color: var(--text);
}

/* Der Stern ist Zusatz, die Pflicht steht als Text im Label. */
.smm-form .req {
	color: var(--error);
}

/* ---------- Felder ---------- */

:where(.smm-form, .search-form, .post-password-form) :is(input:where(:not([type]), [type="text"], [type="email"], [type="tel"], [type="url"], [type="search"], [type="number"], [type="date"], [type="password"]), select, textarea) {
	-webkit-appearance: none;
	appearance: none;
	display: block;
	width: 100%;
	/* FIX: min-width 0 und max-width 100 %, sonst setzen Browser eine
	   intrinsische Mindestbreite (size-Attribut) und das Feld ragt aus der
	   Karte. */
	min-width: 0;
	max-width: 100%;
	min-height: 3.25rem;
	margin: 0;
	padding: .75rem .875rem;
	/* FIX: Ein Eingabefeld ist ein Bedienelement und braucht 3:1 gegen seine
	   Umgebung. #cbd7d7 kam auf 1,47:1. --line-ui: 3,59 auf Weiß, 3,18 auf
	   Kreide, 5,04 (Weiß 50 %) auf Studio. */
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	background: var(--c-white);
	color: var(--c-ink);
	font: 400 var(--fs-body)/1.4 var(--font-text);
}

:where(.smm-form, .search-form, .post-password-form) :is(input, textarea)::placeholder {
	color: var(--c-ink-soft);
	opacity: 1;
}

:where(.smm-form, .search-form, .post-password-form) textarea {
	min-height: 7rem;
	resize: vertical;
}

:where(.smm-form, .search-form, .post-password-form) select {
	padding-right: 2.75rem;
	background: var(--c-white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101B1C' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right .875rem center / 18px 18px;
}

/* Rahmen innen in Teal-Ink (gegen das weiße Feld 6,29), der Ring außen in
   --focus: auf Studio wäre #156A72 nur 2,57:1, dort greift Signal (6,06). */
:where(.smm-form, .search-form, .post-password-form) :is(input, select, textarea):focus-visible {
	border-color: var(--c-teal-ink);
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}

/* Fehlerzustand: CF7 setzt aria-invalid und .wpcf7-not-valid. */
.smm-form :is(input, select, textarea):is([aria-invalid="true"], .wpcf7-not-valid) {
	border-color: var(--error);
}

/* Meldung unter dem Feld: Schibsted 600 14 px mit Warnsymbol. Das Symbol ist
   eine Maske in currentColor, damit es mit --error kippt (6,57 hell,
   9,46 Studio). */
.smm-form .wpcf7-not-valid-tip {
	display: flex;
	align-items: flex-start;
	gap: .375rem;
	margin-top: .375rem;
	font: 600 var(--fs-xs)/1.4 var(--font-text);
	color: var(--error);
}

.smm-form .wpcf7-not-valid-tip::before {
	content: "";
	flex: none;
	width: 16px;
	height: 16px;
	margin-top: .1em;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5 2.5 20h19Z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Cpath d='M12 17.5h.01'/%3E%3C/svg%3E") no-repeat center / contain;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5 2.5 20h19Z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Cpath d='M12 17.5h.01'/%3E%3C/svg%3E") no-repeat center / contain;
}

/* ---------- Checkbox, Radio, Einwilligung ---------- */

/* Das ganze Label ist klickbar (CF7 legt das input ins label). */
.smm-form .wpcf7-list-item {
	display: block;
	margin: 0;
}

.smm-form .wpcf7-list-item + .wpcf7-list-item {
	margin-top: .5rem;
}

.smm-form .wpcf7-list-item label {
	display: grid;
	grid-template-columns: 1.375rem minmax(0, 1fr);
	align-items: start;
	gap: .75rem;
	margin: 0;
	font: 400 var(--fs-body)/1.5 var(--font-text);
	color: var(--text);
	cursor: pointer;
}

/* accent-color über --accent-text: auf Hell identisch mit #156A72, auf Studio
   Signal – ein Teal-Ink-Häkchenfeld hätte dort nur 2,57:1. */
:where(.smm-form) :is(input[type="checkbox"], input[type="radio"]) {
	width: 1.375rem;
	height: 1.375rem;
	margin: .05rem 0 0;
	accent-color: var(--accent-text);
	cursor: pointer;
}

.smm-form__consent .wpcf7-list-item label,
.smm-form__consent {
	font-size: var(--fs-xs);
	line-height: 1.5;
	color: var(--text-soft);
}

/* ---------- Absenden, Antwort ---------- */

.smm-form__submit {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .75rem;
	margin-top: .5rem;
}

/* Submit wie alle Sektions-CTAs: unter 48rem in voller Breite (btn--block),
   darüber so breit wie sein Label. FIX: Der Umschaltpunkt lag bei 36rem;
   zwischen 576 und 767 px stand der Submit als einziger Abschluss-Button
   der Seite nicht vollbreit (Befund sektions-cta-uneinheitlich). */
.smm-form__submit :is(.wpcf7-submit, .btn) {
	width: 100%;
}

@media (min-width: 48rem) {
	.smm-form__submit :is(.wpcf7-submit, .btn) {
		width: auto;
	}
}

.smm-form .wpcf7-spinner {
	margin: 0;
}

/* FIX: Unter 48rem ist der Submit vollbreit, der CF7-Spinner (24 px, bis
   zum Absenden unsichtbar) rutschte in eine eigene Zeile und hielt 36 px
   Leerraum unter dem Button. Er liegt dort deshalb über dem Pfeil-Segment
   des Buttons: sichtbar genau dann, wenn der Pfeil nichts mehr bedeutet. */
@media (max-width: 47.99rem) {
	.smm-form__submit {
		position: relative;
	}

	/* Mitte des Segments: 3rem breit (btn--lg unter 30rem, 10-buttons.css),
	   also 1.5rem vom rechten Rand. */
	.smm-form__submit > .wpcf7-spinner {
		position: absolute;
		top: calc(50% - 12px);
		right: calc(1.5rem - 12px);
	}
}

/* Zwischen 30 und 48rem ist das Segment eines btn--lg 3.5rem breit. */
@media (min-width: 30rem) and (max-width: 47.99rem) {
	.smm-form__submit > :where(.btn--lg) + .wpcf7-spinner {
		right: calc(1.75rem - 12px);
	}
}

.wpcf7 form.smm-form .wpcf7-response-output {
	margin: 1.5rem 0 0;
	padding: .875rem 1rem;
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	color: var(--text);
	font: 400 var(--fs-small)/1.5 var(--font-text);
}

.wpcf7 form.smm-form.sent .wpcf7-response-output {
	border-color: var(--accent-text);
}

.wpcf7 form.smm-form:is(.invalid, .unaccepted, .payment-required, .failed, .aborted, .spam) .wpcf7-response-output {
	border-color: var(--error);
}

/* Solange kein Formular verknüpft ist (smm_form_fallback). Linksbündig.
   Der Kalender-Button ersetzt dort den Submit und folgt derselben Regel:
   btn--lg, unter 48rem vollbreit (btn--block), darüber natürliche Breite. */
.form-fallback {
	display: grid;
	justify-items: start;
	gap: 1rem;
}

@media (min-width: 48rem) {
	.form-fallback > :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}

	.form-fallback :where(.btn--block > .btn__label) {
		flex: 0 1 auto;
	}
}

.form-fallback__text {
	margin: 0;
	color: var(--text-soft);
}

.form-fallback__hint {
	margin: 1.25rem 0 0;
	font-size: var(--fs-xs);
	color: var(--text-soft);
}

/* ---------- Suchformular ----------
   Feld plus quadratischer Button (3.25rem), Studio-Grund, weiße Lupe; der
   Button trägt aria-label „Suchen“ (Markup Team E). */

.search-form {
	display: flex;
	align-items: stretch;
	gap: .5rem;
	max-width: 100%;
}

.search-form input[type="search"] {
	flex: 1 1 auto;
	width: auto;
}

.search-form input[type="search"]::-webkit-search-decoration {
	-webkit-appearance: none;
}

.search-form [type="submit"] {
	display: inline-grid;
	flex: none;
	place-items: center;
	min-width: 3.25rem;
	min-height: 3.25rem;
	margin: 0;
	padding: 0 .875rem;
	border: 0;
	border-radius: var(--r-control);
	background: var(--c-studio);
	color: var(--c-white);
	font: 650 1rem/1.2 var(--font-display);
	cursor: pointer;
}

.search-form [type="submit"]:hover {
	background: var(--c-teal-ink);
}

.search-form [type="submit"] svg {
	width: 20px;
	height: 20px;
	stroke: currentColor;
	stroke-width: 2;
	fill: none;
}

/* Auf Studio und Sektion teal wäre ein Studio-Knopf unsichtbar: dort die
   helle Button-Fläche aus den Tokens (weiß mit Studio-Lupe, 16,17), Hover
   Signal auf Studio bzw. #CFEDEC auf teal – Signal auf teal wäre ein
   unzulässiges Paar (2,36). */
:is([data-theme="dark"], .theme-studio) .search-form [type="submit"] {
	background: var(--btn-label-bg);
	color: var(--btn-label-fg);
}

:is([data-theme="dark"], .theme-studio) .search-form [type="submit"]:hover {
	background: var(--btn-label-bg-h);
}

/* ===== 12-frame.css ===== */
/* =========================================================================
   12 Sucherrahmen (Besitz: Fundament F2) – docs/design-system.md 5.4

   Echtes Bewegtbild und Porträts stehen im Kamerasucher: vier Rahmenmarken
   außen um den Bildschirm. Keine Schattenkarte, kein weißer Rand, kein
   Anschnitt bis an den Viewport.

   Markup: template-parts/components/frame.php
     figure.frame.frame--{video|person}.frame--{16x9|9x16|4x5|auto}[data-reveal]
       div.frame__screen > img | video | .video-embed
       figcaption.frame__note            (nur Hinweis)
       figcaption.frame__cap             (Bauchbinde, optional span.frame__note)

   Das Einrasten der Marken (opacity/scale) steht mit allen anderen
   Ausgangszuständen in 90-motion.css.
   ========================================================================= */

.frame {
	--mark-len: 22px;
	--mark-w: 2px;
	--mark-off: 10px;
	position: relative;
	margin: 0;
	/* FIX: Als Grid- oder Flex-Kind darf das Medium seine Spalte nicht über
	   die min-content-Breite des Posters aufsprengen (altes minmax(0,1fr)-Thema). */
	min-width: 0;
	max-width: 100%;
}

.frame__screen {
	position: relative;
	max-width: 100%;
}

/* Bewegtbild: Bis das Poster geladen ist (oder wenn keins gepflegt ist),
   steht im Bildschirm eine ruhige Studio-2-Fläche statt des Seitengrunds.
   Kein weißes Aufblitzen, kein weißer Streifen (9.2). */
.frame--video .frame__screen {
	background: var(--c-studio-2);
	border-radius: var(--r-media);
}

.frame--16x9 .frame__screen { aspect-ratio: 16 / 9; }
.frame--9x16 .frame__screen { aspect-ratio: 9 / 16; }
.frame--4x5 .frame__screen { aspect-ratio: 4 / 5; }

/* FIX: Poster randlos. Früher standen über und unter dem Video weiße Streifen,
   weil ein Fließtext-Abstand und ein zweiter Radius im gerahmten Container
   saßen (alte app.css „.hero__media .blk-video { margin-block: 0 }“). Das
   Medium füllt den Bildschirm deshalb vollständig und ohne eigenen Abstand. */
.frame__screen > img,
.frame__screen > video,
.frame__screen > picture,
.frame__screen > .video-embed,
.frame__screen > .blk-video {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	object-fit: cover;
	border-radius: var(--r-media);
}

/* Die Zwei-Klick-Komponente kann ihr .video-embed noch in figure.blk-video
   hüllen. Auch dann füllt das Video den Bildschirm ohne Streifen. */
.frame__screen > .blk-video > .video-embed {
	height: 100%;
}

.frame__screen > picture > img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--r-media);
}

/* FIX: Porträts im festen 4:5-Zuschnitt verloren früher den Kopf (harter
   3:2-Zuschnitt, siehe smm_image_size_for). Der Bildausschnitt sitzt deshalb
   im oberen Fünftel, Kopf und Kinn bleiben sichtbar. */
.frame--person .frame__screen > img,
.frame--person .frame__screen > picture > img {
	object-position: 50% 20%;
}

/* Natürliches Seitenverhältnis (text_media, Hero-Porträt).
   Abweichung zu 5.4, begründet: Dort steht nur max-height: 80vh mit
   object-fit: contain. Bei einem hohen Porträt bliebe der Bildschirm dann
   spaltenbreit, das Bild darin schmaler, und die Marken säßen mit Luft neben
   dem Foto, also genau der „weiße Rand“, den der Rahmen beheben soll. Der
   Bildschirm schrumpft deshalb auf die Bildbreite. contain bleibt als
   Sicherung für Browser, die die Höhenbegrenzung nicht in die Breite
   übertragen. */
.frame--auto .frame__screen {
	width: fit-content;
}

.frame--auto .frame__screen > img,
.frame--auto .frame__screen > picture > img {
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 80vh;
	max-height: 80svh;
	object-fit: contain;
}

/* Rahmenmarken: je Ecke zwei Schenkel aus einfarbigen Verläufen. Das Pseudo-
   Element liegt um --mark-off nach außen versetzt; die Schenkel sitzen damit
   vollständig außerhalb des Bildes und überdecken nie Poster oder Knopf.
   Farbe über --mark: Teal auf Hell (4,60 / 4,08 auf Kreide), Signal auf
   Studio (6,06), Weiß auf Sektion teal. */
.frame__screen::after {
	content: "";
	position: absolute;
	inset: calc(var(--mark-off) * -1);
	pointer-events: none;
	background:
		linear-gradient(var(--mark) 0 0) top left / var(--mark-len) var(--mark-w),
		linear-gradient(var(--mark) 0 0) top left / var(--mark-w) var(--mark-len),
		linear-gradient(var(--mark) 0 0) top right / var(--mark-len) var(--mark-w),
		linear-gradient(var(--mark) 0 0) top right / var(--mark-w) var(--mark-len),
		linear-gradient(var(--mark) 0 0) bottom left / var(--mark-len) var(--mark-w),
		linear-gradient(var(--mark) 0 0) bottom left / var(--mark-w) var(--mark-len),
		linear-gradient(var(--mark) 0 0) bottom right / var(--mark-len) var(--mark-w),
		linear-gradient(var(--mark) 0 0) bottom right / var(--mark-w) var(--mark-len);
	background-repeat: no-repeat;
}

/* Hinweiszeile (Zwei-Klick-Hinweis). 7,51 auf Weiß, 8,44 auf Studio. */
.frame__note {
	display: block;
	margin-top: calc(var(--mark-off) + .75rem);
	font: 400 .875rem/1.5 var(--font-text);
	color: var(--text-soft);
	max-width: 60ch;
}

.frame__note a {
	color: inherit;
}

/* Bauchbinde im Fluss unter dem Bild (z. B. Titel in video_gallery).
   Der Abstand hält die unteren Marken frei. */
.frame__cap {
	display: block;
	margin-top: calc(var(--mark-off) + .75rem);
}

.frame__cap > .frame__note {
	margin-top: .5rem;
}

/* Überhängende Bauchbinde (5.3 .l3--overlap): Sie ist absolut an .frame
   verankert, figcaption selbst trägt dann keine Höhe. Das figure hält unten
   1.5rem frei, damit die Tafel keinen Folgetext berührt (13-lower-third.css
   deckelt den Überhang auf genau diesen Wert). */
.frame--overlap {
	margin-bottom: 1.5rem;
}

.frame--overlap > .frame__cap {
	margin: 0;
}

/* 375 px: Marken 6/16 px. 6 px Versatz plus 2 px Stärke liegen innerhalb
   des 18-px-Gutters, die Marken bleiben bei 320 px im Viewport (9.2). */
@media (max-width: 47.99rem) {
	.frame {
		--mark-len: 16px;
		--mark-off: 6px;
	}
}

/* ===== 13-lower-third.css ===== */
/* =========================================================================
   13 Bauchbinde (Besitz: Fundament F2) – docs/design-system.md 5.3

   Namen echter Menschen und Kanäle wie im Fernsehen: Namenstafel, darunter
   Rollentafel. Statisch, ohne Einblendung, ohne clip-path.

   Markup: template-parts/components/lower-third.php
     div.l3 > h3.l3__name + p.l3__role
     span.l3 > span.l3__name + span.l3__role   (in figcaption, Reel, O-Ton)

   Kontraste: Namenstafel Weiß auf #156A72 6,29 (hell), auf #1C818B 4,60
   (Studio), auf #0D2427 16,17 (Sektion teal). Rolle ab 15,56.
   ========================================================================= */

.l3 {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	max-width: 100%;
}

/* In einem Flex-Container werden die span-Kinder automatisch zu Blöcken,
   das deckt den figcaption-Fall aus 5.3 ab. max-width und overflow-wrap
   lassen lange Namen innerhalb der Tafel umbrechen, statt sie aus der
   Spalte zu schieben. Namen werden nicht silbengetrennt, auch wenn der Name
   als h3 unter der mobilen Trennregel für Überschriften (02-base) steht. */
.l3__name,
.l3__role {
	max-width: 100%;
	overflow-wrap: break-word;
	hyphens: manual;
}

.l3__name {
	margin: 0;
	background: var(--l3-name-bg);
	color: var(--l3-name-fg);
	font: 720 1.0625rem/1.2 var(--font-display);
	font-stretch: 84%;
	letter-spacing: 0;
	padding: .4rem .75rem .35rem;
	border-radius: var(--r-plate);
}

.l3__role {
	margin: 0;
	background: var(--l3-role-bg);
	color: var(--l3-role-fg);
	font: 500 .875rem/1.3 var(--font-text);
	padding: .3rem .75rem;
	border-radius: var(--r-plate);
}

/* Handles und andere echte Daten (3.4 Mono-Daten, nie versal). */
.l3--mono .l3__role {
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
}

/* Links in einer Tafel (etwa ein Firmenname) behalten die Tafelfarbe. */
.l3__name a,
.l3__role a {
	color: inherit;
}

/* Halb überhängend an der Unterkante des Mediums.
   Abweichung zu 5.3, begründet: translateY(50%) wächst mit der Tafelhöhe.
   Name plus zweizeilige Rolle ergeben bei 375 px rund 80 px, der Überhang
   läge dann bei 40 px, das figure hält aber nur 1.5rem (24 px) frei. Die
   Tafel läge auf dem Folgetext (verletzt 9.2). Der Überhang ist deshalb auf
   1.5rem gedeckelt; kurze Tafeln hängen weiter genau zur Hälfte über.

   ABWEICHUNG zu 5.3 und 6.14 (ab 48rem left: -1rem, darunter 0), nach
   Sichtprüfung: -1rem gegen die Marken bei -10 px ergab ab 48rem drei
   linke Kanten (Tafel, Marke, Bild), unter 48rem schaute neben der Tafel
   ein Stummel der unteren Marke heraus. Die Tafel beginnt jetzt genau an
   der Außenkante der Rahmenmarken (--mark-off, 10 px bzw. 6 px) und
   ersetzt die Ecke unten links vollständig: beide Schenkel liegen unter
   Namens- und Rollentafel. Eine Kante in allen Breiten; die 6 px liegen
   wie die Marken im 18-px-Gutter (9.2). Der Rückfall 0px gilt für eine
   Bauchbinde außerhalb von .frame. Gilt auch für Hero- und
   text_media-Porträts. */
.l3--overlap {
	position: absolute;
	left: calc(var(--mark-off, 0px) * -1);
	bottom: 0;
	z-index: var(--z-raised);
	max-width: calc(100% - 1rem);
	transform: translateY(min(50%, 1.5rem));
}

/* Windows-Kontrastmodus ersetzt Tafelflächen durch Canvas. Ein Rand hält die
   Tafeln als Einheit erkennbar. */
@media (forced-colors: active) {
	.l3__name,
	.l3__role {
		border: 1px solid CanvasText;
	}
}

/* ===== 14-trim.css ===== */
/* =========================================================================
   14 Trim-Griffe (Besitz: Fundament F2) – docs/design-system.md 5.5

   Grammatik: der einzige Auswahlzustand. „Ausgewählt“ sieht aus wie ein
   zugeschnittener Clip: Griffe links und rechts mit Kerbe, dünne Linien oben
   und unten.

   Einsatz:
     .trim.trim--hover   Registerzeilen, Fallstudien-, Such- und Post-Zeilen
     .trim.is-trimmed    Spalte B der Vergleichstabelle, featured Paket
     .trim--inset        nur die beiden Griffe, innen in der Fläche
                         (Aufmacherzeile im Leistungsregister, unten)

   Trim ist nie das einzige Signal: Fokus hat immer die eigene Outline, Hover
   ändert zusätzlich Fläche und Pfeil (Sektionsdateien).
   Kontraste: Teal 4,60 auf Weiß, 4,08 auf Kreide, Gelb 9,97 auf Studio,
   8,19 auf Studio-2, Weiß auf Sektion teal.

   --notch: Farbe der Kerbe im Griff. Standard ist der Sektionsgrund; liegt
   die Zeile beim Hover auf --surface, setzt die Sektion --notch: var(--surface).
   ========================================================================= */

.trim {
	position: relative;
	isolation: isolate;
}

.trim::after {
	--tw: 6px;
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	opacity: 0;
	background:
		linear-gradient(var(--notch, var(--bg)) 0 0) calc(var(--tw) / 2 - 1px) 50% / 2px 32% no-repeat,
		linear-gradient(var(--notch, var(--bg)) 0 0) calc(100% - var(--tw) / 2 + 1px) 50% / 2px 32% no-repeat,
		linear-gradient(var(--trim) 0 0) left 50% / var(--tw) 100% no-repeat,
		linear-gradient(var(--trim) 0 0) right 50% / var(--tw) 100% no-repeat,
		linear-gradient(var(--trim) 0 0) 50% 0 / 100% 2px no-repeat,
		linear-gradient(var(--trim) 0 0) 50% 100% / 100% 2px no-repeat;
	transition: opacity var(--dur-1) var(--ease-cut);
}

.trim.is-trimmed::after,
.trim--hover:is(:focus-visible, :focus-within, :active)::after {
	opacity: 1;
}

/* FIX: Auf Touchgeräten bleibt :hover nach dem Antippen „kleben“, die Zeile
   sähe danach dauerhaft ausgewählt aus. Hover-Trim deshalb nur mit echtem
   Zeiger; auf Touch erscheint er bei :active und :focus-visible (6.10). */
@media (hover: hover) {
	.trim--hover:hover::after {
		opacity: 1;
	}
}

/* ---------- Innen liegende Griffe (.trim--inset) ----------
   ABWEICHUNG von 5.5 (Art-Director-Befund Runde 2 „Gelber Rahmen um die
   Aufmacherzeile“): Ist der ausgewählte Clip selbst eine Studio-Fläche auf
   hellem Grund, liegen die Linien oben und unten und die Griffe an der
   Außenkante direkt auf Kreide. Sie lesen sich als gelber Rahmen (Regel 4:
   Gelb nie als Linie auf Hell) und wie der Fokusrahmen eines Formularfelds.
   Die Variante zeichnet nur die beiden Griffe mit Kerbe, eingerückt innerhalb
   der Fläche, ohne Linien. Gelb berührt so nie den hellen Grund.
   Einzug je Seite über --trim-inset-block, --trim-inset-start und
   --trim-inset-end (Standard .75rem); das Innenleben hält selbst Abstand. */
.trim--inset::after {
	inset:
		var(--trim-inset-block, .75rem)
		var(--trim-inset-end, .75rem)
		var(--trim-inset-block, .75rem)
		var(--trim-inset-start, .75rem);
	background:
		linear-gradient(var(--notch, var(--bg)) 0 0) calc(var(--tw) / 2 - 1px) 50% / 2px 32% no-repeat,
		linear-gradient(var(--notch, var(--bg)) 0 0) calc(100% - var(--tw) / 2 + 1px) 50% / 2px 32% no-repeat,
		linear-gradient(var(--trim) 0 0) left 50% / var(--tw) 100% no-repeat,
		linear-gradient(var(--trim) 0 0) right 50% / var(--tw) 100% no-repeat;
}

/* ===== 15-odometer.css ===== */
/* =========================================================================
   15 Walzenzähler (Besitz: Fundament F2) – docs/design-system.md 5.7

   Belegzahlen rollen einmal wie ein Aufrufzähler. Im Markup steht immer der
   echte Endwert (smm_odometer). 31-odometer.js zerlegt ihn nach
   document.fonts.ready, aber nur, wenn er dann noch unterhalb des Viewports
   steht (Sichtbares springt nie auf Nullen, 9.3):

     span.odo[data-odometer]
       span.sr-only                      Originaltext für Screenreader
       span.odo__reel[aria-hidden]
         span.odo__d[style="--n:5;--k:1"] > span.odo__s   0<br>1<br>…<br>9
         span.odo__c                     alles, was keine Ziffer ist

   Nach dem Rollen stellt das Skript den reinen Text wieder her.

   Vertrag für Sektionsdateien: Schriftgröße und Gewicht dürfen an .odo oder
   am Elternelement stehen, line-height aber nur am Elternelement. Sie liegt
   hier bewusst auf .odo selbst (1), damit statischer Text und Walze exakt
   gleich hoch sind und beim Wechsel nichts springt (kein CLS).
   ========================================================================= */

.odo {
	display: inline-block;
	/* Anker für das sr-only-Original: Es bleibt an der Zahl statt an einem
	   entfernten Vorfahren, der sonst überlaufen könnte. */
	position: relative;
	line-height: 1;
	font-variant-numeric: tabular-nums lining-nums;
	white-space: nowrap;
}

/* Ein Fenster je Ziffer, genau eine Zeile hoch. overflow: hidden steht als
   Rückfall für Safari vor 16, das clip nicht kennt. */
.odo__d {
	display: inline-block;
	height: 1em;
	overflow: hidden;
	overflow: clip;
	vertical-align: top;
}

/* Abweichung zu 5.7, begründet: display block statt flex column. Die zehn
   Ziffern sind durch <br> getrennt. In einem Flex-Container wird jedes <br>
   zu einem eigenen Flex-Element, dessen Höhe keine Spezifikation festlegt
   (Chrome: 0). Als Block ergeben die Ziffern zehn Zeilen von exakt 1em, in
   jeder Engine, und translateY(n × -1em) trifft die Ziffer genau. Optisch
   identisch; geprüft: Walze im Endstand deckungsgleich mit dem Text. */
.odo__s {
	display: block;
	line-height: 1;
	transition: transform calc(var(--dur-4) + var(--k, 0) * 120ms) var(--ease-cut);
}

.odo__c {
	white-space: pre;
}

.odo.is-rolling .odo__s {
	transform: translateY(calc(var(--n, 0) * -1em));
}

/* ===== 16-lists-checks-stars.css ===== */
/* =========================================================================
   16 Listen, Haken, Sterne, Chips (Besitz: Fundament F2)
   docs/design-system.md 4.1, 6.3 (.tick), 6.11 (.stars), 6.22 (.chip)

   Glyphen wie ✓ → ★ fehlen in allen drei Schriften (3.1). Haken, Sterne und
   Quadrate sind deshalb SVG oder CSS-Flächen, nie Textzeichen.
   ========================================================================= */

/* ---------- .bullets: Pixelquadrat-Liste (4.1) ----------
   Das Quadrat stammt aus dem Logo: 7×7 px, --mark (Teal 4,60 auf Weiß,
   4,08 auf Kreide, Signal 6,06 auf Studio, Weiß auf Sektion teal).
   Die alten Kreis-Haken entfallen. */

/* FIX: list-style-type "" statt none. Safari/VoiceOver nimmt einer Liste mit
   list-style none die Listen-Semantik („Liste, 3 Einträge“ entfällt). Der
   leere Marker blendet den Punkt genauso aus. none bleibt als Rückfall. */
.bullets {
	list-style: none;
	list-style-type: "";
	margin: 0;
	padding: 0;
	display: grid;
	gap: .75rem;
}

.bullets > li {
	position: relative;
	min-width: 0;
	padding-inline-start: 1.25rem;
	overflow-wrap: break-word;
	/* Befund text-wrap-einzelwoerter: kein einzelnes Wort allein in der
	   letzten Zeile („… / liegen“). pretty ändert nur die letzten Zeilen. */
	text-wrap: pretty;
}

/* top .62em nach 4.1; mit lh-Einheit sitzt das Quadrat bei jeder
   Zeilenhöhe exakt mittig auf der ersten Zeile. */
.bullets > li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: .62em;
	top: calc(.5lh - 3.5px);
	width: 7px;
	height: 7px;
	background: var(--mark);
	border-radius: 1.5px;
}

/* ---------- .checks: Haken-Liste (Formular-Benefits, Paket-Features) ----------
   Haken 18 px ohne Kreis, Strich --accent-text, stroke-width 2.25.
   Zwei Markup-Varianten funktionieren gleich:
     <li><svg …check…/><span>Text</span></li>   SVG aus smm_icon( 'check' )
     <li>Text mit <strong>Inline</strong></li>   Haken kommt aus CSS
   Abweichung zu 4.1 (Grid 1.5rem 1fr), begründet: Ein Grid macht aus jedem
   Textstück und jedem <strong> eine eigene Zelle und zerreißt Paket-Features
   mit Inline-Auszeichnung. Einzug plus absolut gesetzter Haken ergibt dieselbe
   1.5rem-Spalte mit hängendem Text, unabhängig vom Markup. */

.checks {
	list-style: none;
	list-style-type: "";
	margin: 0;
	padding: 0;
	display: grid;
	gap: .75rem;
}

.checks > li {
	position: relative;
	min-width: 0;
	padding-inline-start: 1.5rem;
	overflow-wrap: break-word;
	text-wrap: pretty; /* wie .bullets */
}

.checks > li > svg:first-child {
	position: absolute;
	inset-inline-start: 0;
	top: .2em;
	top: calc((1lh - 18px) / 2);
	width: 18px;
	height: 18px;
	fill: none;
	stroke: var(--accent-text);
	stroke-width: 2.25;
}

.checks > li:not(:has(> svg:first-child))::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: .2em;
	top: calc((1lh - 18px) / 2);
	width: 18px;
	height: 18px;
	background-color: var(--accent-text);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---------- .tick: Haken-Quadrat der Hero-Trustline (6.3) ----------
   20×20 px, Grund Teal, weißer Haken 12 px (4,60). Auf Studio Signal mit
   Haken #0D2427 (6,06). Auf Sektion teal umgekehrt: weißes Quadrat, Haken
   #156A72 (6,29), weil Teal auf #156A72 als Fläche verschwände.
   Markup: <span class="tick" aria-hidden="true"><svg …/></span> */

.tick {
	/* Größe als lokales Token: .hero__trust-item liest es, um das Quadrat
	   mittig auf die erste Zeile zu setzen (40-hero.css). */
	--tick-size: 20px;
	display: inline-grid;
	place-items: center;
	flex: none;
	width: var(--tick-size);
	height: var(--tick-size);
	border-radius: var(--r-control);
	background: var(--c-teal);
	color: var(--c-white);
	vertical-align: middle;
}

.tick svg {
	display: block;
	width: 12px;
	height: 12px;
	fill: none;
	stroke: currentColor;
	stroke-width: 3;
}

/* Befund trustline-icons: Play, Personen, Gebäude, Uhr und Stern werden bei
   12 px im Quadrat zu weißen Klecksen. Stehen solche Symbole in der Liste,
   bekommt die ganze Liste das größere Quadrat (hero.php setzt die Klasse an
   jedes .tick der Liste, auch an einen Haken darin, damit alle Zeilen gleich
   ausgerichtet bleiben). 24 px mit 16-px-Symbol und Strich 2 bleiben
   lesbar.
   ABWEICHUNG von 6.3 (20 px, Haken 12 px): gilt nur, wenn die Redaktion ein
   anderes Symbol als den Haken gewählt hat; der Haken allein bleibt 20 px. */
.tick--glyph {
	--tick-size: 24px;
}

.tick--glyph svg {
	width: 16px;
	height: 16px;
	stroke-width: 2;
}

:is([data-theme="dark"], .theme-studio) .tick {
	background: var(--c-signal);
	color: var(--c-studio);
}

.section--bg-teal .tick {
	background: var(--c-white);
	color: var(--c-teal-ink);
}

/* ---------- .stars (6.11, smm_stars) ----------
   16 px in --star (Teal-Ink hell, Gelb auf Studio, Weiß auf Sektion teal).
   Die Ansage „n von 5 Sternen“ steht als aria-label am Wrapper. */

.stars {
	display: inline-flex;
	gap: 2px;
	color: var(--star);
	line-height: 0;
	vertical-align: middle;
}

.stars svg,
.stars__star {
	display: block;
	flex: none;
	width: 16px;
	height: 16px;
}

/* FIX: Voller und leerer Stern lagen farblich nur 1,38:1 auseinander, der
   Unterschied zwischen vier und fünf Sternen war kaum zu sehen. Farbe allein
   kommt bei keiner Graustufe über 3:1, deshalb unterscheidet die Form: Der
   leere Stern ist ein Umriss in --star-off (3,59 auf Weiß, 5,04 auf Studio). */
.stars__star--off {
	color: var(--star-off);
}

.stars__star--off path {
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linejoin: round;
}

/* ---------- .chip (6.22, 6.23, 6.24) ----------
   Kategorie- und Tag-Chips. Schibsted 600 14 px, Rand 1.5px --line-ui
   (3,59 auf Weiß, 3,18 auf Kreide), Radius 3px, keine Pille.
   Aktiver Chip: aria-current="page", Grund Studio, weiße Schrift. */

.chip {
	display: inline-flex;
	align-items: center;
	max-width: 100%;
	min-height: 2.5rem;
	padding: .5rem .875rem;
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	background: transparent;
	color: var(--text);
	font: 600 var(--fs-xs)/1.3 var(--font-text);
	text-decoration: none;
	overflow-wrap: anywhere;
	transition: background-color var(--dur-1) var(--ease-cut), color var(--dur-1) var(--ease-cut), border-color var(--dur-1) var(--ease-cut);
}

/* FIX: Zielgröße. Der Chip ist 40 px hoch (6.22), 9.5 verlangt 44 px für
   Bedienelemente. Ein unsichtbarer Streifen verlängert die Trefferfläche
   oben und unten um je 2 px, ohne die Optik zu ändern. Die Lücke zwischen
   umbrechenden Chips (mindestens .5rem) bleibt größer, Flächen überlappen nicht. */
a.chip {
	position: relative;
}

a.chip::after {
	content: "";
	position: absolute;
	inset: -3.5px -1.5px;
}

a.chip:not([aria-current="page"]):hover {
	border-color: var(--text);
	background: var(--surface);
}

/* FIX: Der Alias .chip.is-active ist entfernt. index.php, archive.php und
   templates/template-blog.php setzen am aktiven Chip aria-current="page",
   kein Template und kein JS-Modul gibt .is-active mehr aus. Die Spezifität
   des Hover-Selektors oben bleibt gleich (:not() zählt sein stärkstes
   Argument, Attribut und Klasse wiegen gleich). */
.chip[aria-current="page"] {
	border-color: var(--c-studio);
	background: var(--c-studio);
	color: var(--c-white);
}

/* Auf Studio wäre ein Studio-Chip unsichtbar: dort kippt er auf Weiß. */
:is([data-theme="dark"], .theme-studio) .chip[aria-current="page"] {
	border-color: var(--c-white);
	background: var(--c-white);
	color: var(--c-studio);
}

/* Kleine Chips (Kategorien im Artikelkopf, 6.23). Trefferfläche wieder auf
   44 px verlängert. */
.chip--sm {
	min-height: 2rem;
	padding: .25rem .625rem;
}

a.chip--sm::after {
	inset: -7.5px -1.5px;
}

/* ---------- Windows-Kontrastmodus ----------
   Hintergrundflächen werden dort durch Canvas ersetzt; Quadrate und
   CSS-Haken wären unsichtbar. Sie übernehmen die Textfarbe. */
@media (forced-colors: active) {
	.bullets > li::before,
	.checks > li:not(:has(> svg:first-child))::before {
		forced-color-adjust: none;
		background-color: CanvasText;
	}

	.tick {
		border: 1px solid CanvasText;
	}
}

/* ===== 17-timemark.css ===== */
/* =========================================================================
   17 Zeitmarke (Besitz: Team schluss-zeitmarke, vorher Fundament F2)
   docs/design-system.md 5.8

   Signatur im Schluss-Panel (cta_band, footer-cta, Inline-CTA am
   Artikelende): Die kleine Hürde des Erstgesprächs wird als Timecode
   sichtbar, aber nur, wenn der vorhandene Text „NN Minuten“ nennt
   (smm_time_mark). Das Element ist aria-hidden; die Dauer steht ohnehin
   im gelesenen Text.

     div.timemark[aria-hidden][data-timemark]
       span.timemark__value   30:00
       span.timemark__clip > span   Clip mit festen Trim-Griffen
       span.timemark__clip::after   Playhead (nur während des Laufs)

   Farben über Tokens:
     Hell:          30:00 #156A72, Clip Kreide, Griffe Teal, Playhead Tinte
     Studio:        30:00 #2FAFAF (6,06), Clip #153438, Griffe Gelb, Playhead Weiß
     Sektion teal:  30:00 #CFEDEC, Clip #12545B, Griffe Weiß, Playhead Weiß
   Größe über --timemark-fs an einem Vorfahren (Standard --fs-time: 4rem
   bei 375 px, 8rem breit). Die Schluss-Panels setzen die Größe je
   Komposition (63-cta-band.css, 73-single.css); das Inline-CTA rechnet mit
   demselben Wert die Ausrichtung an der Titelzeile.

   ABWEICHUNG von 5.8 (Befund „Zeitmarke 30:00 ist statische Deko“): Die
   Zeitmarke spielt beim Eintritt einmal die Dauer im Zeitraffer ab, der
   Timecode zählt von 00:00 hoch (34-timemark.js), und ein Playhead läuft
   dabei einmal über die Trim-Leiste. Ohne JS, bei reduzierter Bewegung,
   im Druck und nach dem Lauf sieht die Zeitmarke genau aus wie in 5.8.
   ========================================================================= */

.timemark {
	/* Laufzeit des Zeitraffers. 34-timemark.js zählt mit derselben Dauer
	   (DURATION); wer sie hier ändert, ändert sie dort mit. */
	--timemark-run: 1600ms;
	/* Vorlauf: 00:00 und der Playhead am Einstiegspunkt stehen kurz, bevor
	   es losgeht (HOLD in 34-timemark.js). */
	--timemark-hold: 250ms;
	/* Mittelpunkt des Playheads an der Innenkante der Griffe (6 px) plus
	   1 px Luft, damit der Strich nie auf dem Griff steht. */
	--timemark-in: 7px;
}

/* Breite wie in 5.8: .timemark ist ein normaler Block, der Clip darunter
   läuft über die ganze Seitenspalte. Im cta_band und im footer-cta
   schrumpft die Spalte ab 62rem auf den Timecode (63-cta-band.css), dort
   ist die Leiste genau so breit wie die Ziffern, ebenso im Inline-CTA
   (73-single.css).
   Tabellarische Ziffern: Jeder Zwischenstand beim Hochzählen ist exakt so
   breit wie der Endwert (tnum ist in archivo-var.woff2 enthalten), der
   Zähler verschiebt nichts. */
.timemark__value {
	display: block;
	/* --timemark-fs setzen die Schluss-Panels an einem Vorfahren, damit
	   ihre Ausrichtungsrechnung denselben Wert liest; ohne Angabe gilt
	   --fs-time wie in 5.8. */
	font: 800 var(--timemark-fs, var(--fs-time))/.9 var(--font-display);
	font-stretch: 72%;
	font-variant-numeric: tabular-nums lining-nums;
	color: var(--accent-text);
	letter-spacing: -.01em;
	white-space: nowrap;
}

/* container-type: Der Playhead fährt die Breite des Clips über cqw ab,
   ohne left oder width zu animieren (Kapitel 1).
   ABWEICHUNG von 5.8 („1rem darunter“), begründet (Befund „Zeitmarke 30:00
   fast überall in gleicher Komposition“, Abnahme Runde 3): Timecode und
   Trim-Leiste sollen als eine Anzeige lesen. Die Zeilenbox des Timecodes
   (Zeilenhöhe .9) reicht schon 0,116 em unter die Grundlinie der Ziffern
   (Archivo: (0,9 − 1,088) / 2 + 0,210), bei 8rem also 15 px. Mit 1rem
   dazu standen Ziffern und Leiste rund 31 px auseinander. .375rem ergibt
   sichtbar etwa 21 px, gut anderthalb Leistenhöhen. Gilt in jeder
   Zeitmarke, deren Leiste unter dem Timecode steht (cta_band, footer-cta,
   Inline-CTA); in der Kopfzeile setzen die Panels margin-top: 0. */
.timemark__clip {
	position: relative;
	display: block;
	height: .75rem;
	margin-top: .375rem;
	background: var(--surface);
	container-type: inline-size;
}

/* Trim-Griffe fest (5.5), ohne Übergang. */
.timemark__clip > span {
	position: absolute;
	inset: 0;
	background:
		linear-gradient(var(--trim) 0 0) left / 6px 100% no-repeat,
		linear-gradient(var(--trim) 0 0) right / 6px 100% no-repeat;
}

/* ---------- Playhead (nur mit JS und ohne reduzierte Bewegung) ----------
   Grammatik wie in der Schnitt-Spur (5.6): 2 px Strich in --playhead mit
   einem 10-px-Quadrat als Kopf über dem Clip. Beide Teile sind Hintergründe
   eines einzigen Pseudo-Elements und bewegen sich deshalb als eines.

   Ruhezustand opacity 0: Vor dem Lauf, ohne JS und unter reduce gibt es
   keinen Playhead. is-rolling (34-timemark.js) startet zwei Animationen:
   timemark-play fährt ihn nach dem Vorlauf vom Einstiegs- zum
   Ausstiegspunkt, synchron zum Zähler (gleicher Vorlauf, gleiche Dauer,
   gleiche Kurve); timemark-out blendet ihn danach aus. Der Endzustand ist damit derselbe wie ohne JS, beim späten Laden von
   app.js springt nichts.

   Beide Zustände stehen unter no-preference UND html.smm-motion (7.1.3).
   :where() hält die Spezifität bei einer Klasse (8.5.4). */
@media (prefers-reduced-motion: no-preference) {
	.timemark__clip:where(html.smm-motion *)::after {
		content: "";
		position: absolute;
		top: -.625rem;
		bottom: -.25rem;
		left: calc(var(--timemark-in) - 5px);
		width: 10px;
		background:
			linear-gradient(var(--playhead) 0 0) 50% 0 / 10px 10px no-repeat,
			linear-gradient(var(--playhead) 0 0) 50% 0 / 2px 100% no-repeat;
		opacity: 0;
		pointer-events: none;
	}

	.timemark__clip:where(html.smm-motion .is-rolling > *)::after {
		animation:
			timemark-play var(--timemark-run) var(--ease-cut) var(--timemark-hold) both,
			timemark-out var(--dur-3) var(--ease-cut) calc(var(--timemark-hold) + var(--timemark-run)) both;
	}
}

@keyframes timemark-play {
	from {
		transform: translateX(0);
	}

	to {
		transform: translateX(calc(100cqw - 2 * var(--timemark-in)));
	}
}

/* Vor der Verzögerung gilt dank fill-mode both der from-Wert: Der Playhead
   ist während Vorlauf und Lauf voll sichtbar. */
@keyframes timemark-out {
	from {
		opacity: 1;
	}

	to {
		opacity: 0;
	}
}

@media print {
	.timemark__clip::after {
		display: none;
	}
}

/* ===== 29-topbar.css ===== */
/* =========================================================================
   29 Topbar: Vertrauensleiste über dem Header
   Besitzer: Team A (Rahmen) · Spezifikation 6.1
   Die Ankündigungsleiste (.topbar, .topbar__inner, .topbar__text,
   .topbar__link) steht weiter in 30-header.css. Hier stehen ausschließlich
   die Zusätze der Variante .topbar--trust, die header.php ausgibt, wenn die
   Leiste eingeschaltet, aber kein Ankündigungstext gesetzt ist.

   Die Leiste scrollt mit (kein position: sticky). Nur .site-header klebt,
   und nur sie misst initHeader in --header-h (10-header.js). Ohne
   JavaScript ist die Leiste unverändert sichtbar, sie bewegt sich nie und
   ihre Höhe steht vor dem ersten Bild fest: kein Layoutsprung.
   ========================================================================= */

/* ABWEICHUNG von 6.1 („Topbar (optional): Studio, Schibsted 14 px weiß,
   Link #2FAFAF, statisch“): Die Vertrauensleiste ergänzt drei Dinge, die 6.1
   für die Ankündigungsleiste nicht beschreibt — eine feste Höhe von 2.5rem
   statt Innenabstand, Zahlen in Plex Mono (erlaubt nach 3.1: Mono nur für
   echte Daten) und feine senkrechte Trenner zwischen den Angaben. Grund,
   Schrift, Linkfarbe und „statisch“ bleiben wie in 6.1. Kein Verlauf, kein
   Schatten, keine Pille. */
.topbar--trust .topbar__inner {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: 0;
	min-height: 2.5rem;
	padding-block: 0;
}

.topbar__facts {
	display: flex;
	flex-wrap: nowrap;
	align-items: stretch;
	min-width: 0;
	margin: 0;
	padding: 0;
	/* FIX: list-style-type "" statt none, wie bei .bullets (16-…). Safari und
	   VoiceOver nehmen einer Liste mit list-style: none die Listen-Semantik. */
	list-style: none;
	list-style-type: "";
}

.topbar__fact {
	display: flex;
	flex: none;
	align-items: center;
	gap: .5rem;
	/* Die Leiste bleibt einzeilig: Ein Umbruch würde sie verdoppeln und den
	   Header nach unten schieben. Was nicht passt, entfällt je Breite (unten).
	   flex: none, damit eine Angabe im Zweifel ganz entfällt und nicht
	   zusammengedrückt über die nächste läuft. */
	white-space: nowrap;
}

/* Feiner senkrechter Trenner. --line ist auf Studio Weiß 12 %: dekorativ,
   nie alleinige Grenze (2.2). Die Linie ist so hoch wie die Zeile (24 px),
   nicht wie die Leiste, und lässt oben und unten Luft. */
.topbar__fact + .topbar__fact {
	margin-inline-start: .75rem;
	border-inline-start: 1px solid var(--line);
	padding-inline-start: .75rem;
}

/* Bewertung: Der ganze Block ist der Link zum Portal. Zielgröße mindestens
   24 px hoch (WCAG 2.2 AA, 2.5.8); in der 2.5rem hohen Leiste bleiben mit
   Fokusrahmen (2 px, Versatz 3 px) oben und unten je 3 px Luft. */
.topbar__review {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	min-height: 1.5rem;
	color: var(--text);
	text-decoration: none;
}

/* Der Portalname trägt die Linkfarbe (--accent-text, auf Studio #2FAFAF,
   6,06 gegen #0D2427) und ist unterstrichen. Weiß gegen Signal liegt nur bei
   2,67, Farbe allein dürfte den Link also nicht kennzeichnen (WCAG 1.4.1).
   Beim Überfahren und im Fokus wird der Name weiß (16,17), die Linie bleibt. */
.topbar__source {
	color: var(--accent-text);
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: .25em;
}

.topbar__review:hover .topbar__source,
.topbar__review:focus-visible .topbar__source {
	color: var(--text);
}

/* FIX: Die Regeln für .topbar--trust .stars__star und .topbar__score sind
   entfallen. Die Leiste zeigt weder Sterne noch Note: Beides läse sich als
   Durchschnitt über alle Bewertungen, und dieser Durchschnitt steht nirgends
   belegt. Übrig bleiben Portalname und Anzahl. */

/* 3.1: Plex Mono nur für echte Daten. Die Anzahl und die Kennzahl sind Daten;
   die Wörter daneben bleiben Schibsted. Tabellarische Ziffern, damit die
   Leiste beim Wechsel der Zahl nicht zuckt. */
.topbar__num {
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	font-variant-numeric: tabular-nums;
}

/* Bezeichnung und Ort stehen zurück (--text-soft, auf Studio #A7C0C2, 8,44).
   Vorn steht, was zählt: Portal, Anzahl, Kennzahl. */
.topbar__count,
.topbar__label {
	color: var(--text-soft);
}

/* Die Anzahl trägt die Angabe, deshalb steht ihre Ziffer wie die Kennzahl in
   Weiß (16,17); zurück steht allein das Wort daneben. */
.topbar__count .topbar__num {
	color: var(--text);
}

/* Ruhiger Trenner zwischen Portalname und Anzahl, rein dekorativ. */
.topbar__count::before {
	content: "·";
	margin-inline-end: .5rem;
}

/* -------------------------------------------------------------------------
   Breiten: Was nicht in eine Zeile passt, entfällt, nichts läuft über.
   Im Browser nachgemessen (Stand 17.09.2026, nach dem Wegfall von Sternen und
   Note): Portal samt Anzahl 183 px, die Kennzahl samt Bezeichnung 305 px, der
   Standort 132 px, dazu je 25 px für Trenner und Abstand. Satzbreite: 284 px
   bei 320 px Fenster, 339 px bei 375 px, 699 px bei 768 px, 903 px bei 992 px.
   Die Bewertung passt damit in jeder Breite, ihre Anzahl entfällt nicht mehr
   (früher brauchte sie mit Sternen und Note 340 px und musste unter 48rem
   gekürzt werden). Portal und Standort zusammen brauchen 341 px und passen
   erst ab 48rem. Die Kennzahl bliebe ab 48rem rechnerisch möglich (670 px von
   699 px); sie kommt trotzdem erst ab 62rem dazu, damit sich das Verhalten
   der Leiste durch diesen Umbau nicht ändert.
   Verloren geht nichts: Die Bewertung steht ausführlich bei den Kundenstimmen
   (6.11), Kennzahlen und Anschrift stehen im Fußbereich.
   ------------------------------------------------------------------------- */

.topbar__fact--number,
.topbar__fact--place {
	display: none;
}

@media (min-width: 48rem) {
	.topbar__fact--place {
		display: flex;
	}
}

/* Erst ab 62rem ist Platz für die Kennzahl samt Bezeichnung. */
@media (min-width: 62rem) {
	.topbar__fact--number {
		display: flex;
	}
}

/* ===== 30-header.css ===== */
/* =========================================================================
   30 Header: Topbar, Kopfleiste, Desktop-Navigation, Dropdown, Burger
   Besitzer: Team A (Rahmen) · Spezifikation 6.1
   Mobiles Panel: 32-mobile-nav.css · Megamenü: 31-megamenu.css
   ========================================================================= */

/* -------------------------------------------------------------------------
   Topbar (optional): Studio-Zeile, statisch, linksbündig
   Die Tokens kommen von .theme-studio am Element.
   ------------------------------------------------------------------------- */

.topbar {
	background: var(--bg);
	color: var(--text);
	font: 400 var(--fs-xs)/1.45 var(--font-text);
}

.topbar__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-1) var(--sp-3);
	padding-block: var(--sp-2);
}

.topbar__text {
	margin: 0;
	min-width: 0;
}

.topbar__text a,
.topbar__link {
	color: var(--accent-text);
	font-weight: 600;
}

/* FIX: Zielgröße. Der Link in einer 14-px-Zeile war nur 20 px hoch;
   WCAG 2.2 verlangt mindestens 24 px Trefferfläche. */
.topbar__link {
	display: inline-flex;
	align-items: center;
	min-height: 1.5rem;
}

/* -------------------------------------------------------------------------
   Kopfleiste
   ------------------------------------------------------------------------- */

.site-header {
	/* FIX: Kein Containing Block am Header. backdrop-filter, filter, transform
	   oder container-type machen .site-header zum Bezugsrahmen für das fixe
	   mobile Menü. Es hing dann am 66 Pixel hohen Header statt am Viewport
	   und war nur einen Menüpunkt hoch. Deshalb Weiß deckend, ohne Unschärfe,
	   ohne Transparenz. position: sticky selbst erzeugt keinen solchen Rahmen. */
	position: sticky;
	top: 0;
	z-index: var(--z-header);
	background: var(--bg);
	color: var(--text);
	/* Die Linie ist schon da, nur unsichtbar: Beim Kleben springt nichts um 1 px. */
	border-bottom: 1px solid transparent;
}

/* Kleben: nur die Linie, kein Schatten, keine Bewegung (7.3). */
.site-header.is-stuck {
	border-bottom-color: var(--line);
}

.site-header__inner {
	display: flex;
	align-items: center;
	gap: var(--sp-4);
	min-height: 4rem;
}

.site-header__brand {
	display: inline-flex;
	flex: none;
	align-items: center;
	min-height: 2.75rem;
	text-decoration: none;
}

/* Querlogo (Bildmarke links, Wortmarke rechts, wie im Flyer). Kundenfeedback
   02.10.2026: Das gestapelte Logo wirkte verpixelt und zu klein. Quer ist die
   Wortmarke bei gleicher Höhe gut dreimal so groß. */
.site-header__logo {
	display: block;
	width: auto;
	height: 36px;
	object-fit: contain;
}

/* Gestapeltes Hausmotiv (header.php erkennt es an 2360 × 1502 px).
   ABWEICHUNG von 6.1 (Logo 40 px, mobil 34 px): Bei diesen Höhen war die
   Wortmarke 8–9 px hoch und „GmbH“ eine Punktreihe, der Absender wirkte neben
   Teal-Button und Burger schwach. Das Bildfeld endet jetzt in der Lücke
   zwischen Wortmarke (bis y 1365) und GmbH-Zeile (ab y 1415), object-position
   top schneidet die GmbH-Zeile ab; der Firmenname steht weiter im alt-Text
   und im Impressum. Mit 44 px (ab 62rem 52 px) ist „S&M Media“ 11 bzw.
   13 px hoch, so hoch wie die Versalhöhe der Navigation. Breite 75 bzw.
   89 px, bei 992 px bleibt neben Menü und CTA genug Reserve. */
.site-header__logo--cut {
	height: 44px;
	aspect-ratio: 2360 / 1390;
	object-fit: cover;
	object-position: top;
}

.site-header__actions {
	display: flex;
	flex: none;
	align-items: center;
	gap: var(--sp-3);
	margin-inline-start: auto;
}

/* Unter 62rem übernimmt die Sticky-CTA (6.28). */
.site-header__cta {
	display: none;
}

@media (min-width: 48rem) {
	.site-header__logo {
		height: 40px;
	}
}

@media (min-width: 62rem) {
	.site-header__inner {
		min-height: 4.5rem;
	}

	/* Erst mit der höheren Kopfleiste (72 px): In der 64-px-Leiste darunter
	   blieben bei 52 px nur je 6 px Luft. */
	.site-header__logo--cut {
		height: 52px;
	}

	.site-header__logo:not(.site-header__logo--cut) {
		height: 46px;
	}

	.site-header__cta {
		display: inline-flex;
	}

	/* Kontakt- und Danke-Seite geben keinen Header-CTA aus (header.php), und
	   ab 62rem ist der Burger ausgeblendet. Ein leerer Behälter bliebe als
	   Flex-Element mit Abstand stehen und rückte die Navigation 2–3rem vom
	   rechten Containerrand ab. */
	.site-header__actions:not(:has(.site-header__cta)) {
		display: none;
	}
}

@media (min-width: 75rem) {
	.site-header__inner {
		gap: var(--sp-5);
	}
}

/* -------------------------------------------------------------------------
   Untermenü-Schaltfläche: Grundform für beide Breiten
   ------------------------------------------------------------------------- */

.nav__toggle {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: var(--r-control);
	background: none;
	color: var(--text);
	cursor: pointer;
}

.nav__toggle svg {
	display: block;
	width: 11px;
	height: 8px;
}

.nav__toggle:hover {
	color: var(--accent-text);
}

.nav__toggle[aria-expanded="true"] svg {
	transform: rotate(180deg);
}

@media (prefers-reduced-motion: no-preference) {
	.nav__toggle svg {
		transition: transform var(--dur-1) var(--ease-cut);
	}
}

/* Ohne JavaScript tut die Schaltfläche nichts. Die Unterpunkte stehen dann
   offen in der Liste (32-mobile-nav.css) bzw. öffnen per :hover/:focus-within. */
.nav__toggle:where(html:not(.smm-js) *) {
	display: none;
}

/* -------------------------------------------------------------------------
   Desktop-Navigation ab 62rem
   ------------------------------------------------------------------------- */

@media (min-width: 62rem) {
	/* Die Liste streckt sich über die volle Headerhöhe. Dropdown und Megamenü
	   schließen so direkt an die Unterkante an, ohne Lücke, in der der Zeiger
	   das Hover verliert. */
	.nav {
		display: flex;
		align-self: stretch;
		margin-inline-start: auto;
	}

	.nav + .site-header__actions {
		margin-inline-start: var(--sp-4);
	}

	.nav__list {
		display: flex;
		align-items: stretch;
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.nav__item {
		position: relative;
		display: flex;
		align-items: center;
	}

	/* Das Megamenü bezieht sich auf die ganze Kopfleiste, nicht auf den Punkt. */
	.nav__item--mega {
		position: static;
	}

	/* Zwischen 62 und 75rem stehen Logo, Menü und der rund 270 px breite CTA eng
	   beieinander (Inhalt 903 px bei 992 px Breite). Die Punkte rücken dort
	   auf .5rem Seitenabstand zusammen, ab 75rem gilt .75rem (6.1). */
	.nav__link {
		display: inline-flex;
		align-items: center;
		min-height: 2.75rem;
		padding: .5rem;
		color: var(--text);
		font: 600 var(--fs-small)/1.2 var(--font-text);
		text-decoration: none;
		white-space: nowrap;
	}

	.nav__link:hover {
		color: var(--accent-text);
		text-decoration: none;
	}

	/* Aktuelle Seite: Unterstreichung statt Pille. Vorfahren (is-current)
	   zeigen, in welchem Bereich man steht. */
	.nav__link[aria-current="page"],
	.nav__item.is-current > .nav__link {
		text-decoration: underline 2px var(--mark);
		text-underline-offset: .5em;
	}

	/* Der Pfeil sitzt dicht am Wort. */
	.nav__item--has-children > .nav__link {
		padding-inline-end: 0;
	}

	/* FIX: Mit 44 px Breite und mittigem Pfeil stand der Chevron 17–19 px
	   hinter „Leistungen“ und damit fast so weit weg wie der nächste
	   Menüpunkt; er las sich wie ein eigener Eintrag. Der Pfeil steht jetzt
	   6 px hinter dem Wort, danach folgt bis zum nächsten Wort derselbe
	   Abstand wie zwischen zwei Menüpunkten.
	   ABWEICHUNG von 9.5 (Bedienelemente 44 × 44 px): Die Schaltfläche ist
	   28 × 44 px (unter 75rem 24 × 44). WCAG 2.2 AA (2.5.8) verlangt 24 × 24,
	   der Link „Leistungen“ daneben bleibt 44 px hoch und öffnet das Menü
	   ebenfalls per Hover und Fokus. Eine überlappende 44-px-Fläche hätte
	   Klicks auf das Wortende abgefangen. */
	.nav__toggle {
		width: 1.5rem;
		justify-items: start;
		padding-inline-start: .375rem;
	}

	/* Dropdown der übrigen Punkte: Weiß, eckig, einziger Schatten --shadow-pop. */
	.nav__submenu {
		position: absolute;
		top: 100%;
		inset-inline-start: 0;
		z-index: var(--z-megamenu);
		display: none;
		min-width: 15rem;
		margin: 0;
		padding: .5rem;
		list-style: none;
		background: var(--bg);
		border-top: 1px solid rgb(16 27 28 / 8%);
		border-radius: 0;
		box-shadow: var(--shadow-pop);
	}

	/* FIX (WCAG 4.1.2, 9.5): Mit JavaScript öffnet allein is-open, das
	   12-nav.js zusammen mit aria-expanded der Schaltfläche setzt (Hover,
	   Fokus, Klick, Esc). Öffnete CSS weiter per :hover/:focus-within, meldete
	   die Schaltfläche „zu“ bei sichtbarer Liste und konnte sie nicht schließen.
	   :hover/:focus-within bleibt die Rückfallebene ohne JavaScript.
	   Beide Selektoren halten die Spezifität bei zwei Klassen, damit die
	   Megamenü-Regel darunter gewinnt. */
	.nav__item--has-children:where(.is-open) > .nav__submenu,
	.nav__item--has-children:where(html:not(.smm-js) *):where(:hover, :focus-within) > .nav__submenu {
		display: block;
	}

	/* Mit Megamenü bleibt die einfache Klappliste des Trägers zu, sonst stünden
	   zwei Menüs übereinander (11-megamenu.js setzt is-open auch am Träger).
	   Ohne JavaScript bleibt sie die Rückfallebene. */
	.nav__item--mega:where(.smm-js *) > .nav__submenu {
		display: none;
	}

	.nav__submenu .nav__item {
		display: block;
	}

	.nav__link--sub {
		display: flex;
		width: 100%;
		min-height: 2.75rem;
		padding: .625rem .75rem;
		white-space: normal;
	}

	.nav__link--sub:hover {
		background: var(--surface);
		color: var(--text);
	}

	.nav__foot {
		display: none;
	}
}

@media (min-width: 75rem) {
	.nav + .site-header__actions {
		margin-inline-start: var(--sp-5);
	}

	.nav__link {
		padding-inline: .75rem;
	}

	.nav__item--has-children > .nav__link {
		padding-inline-end: 0;
	}

	.nav__toggle {
		width: 1.75rem;
	}
}

/* -------------------------------------------------------------------------
   Burger: 44 × 44, drei Linien, die sich zum X drehen (180 ms)
   ------------------------------------------------------------------------- */

.burger {
	display: inline-flex;
	flex: none;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 5px;
	width: 2.75rem;
	height: 2.75rem;
	margin: 0;
	padding: 0;
	background: var(--bg);
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	color: var(--text);
	cursor: pointer;
}

.burger__line {
	display: block;
	width: 1.25rem;
	height: 2px;
	background: currentColor;
}

/* Linienabstand 2 px + 5 px Lücke = 7 px bis zur Mitte */
.burger[aria-expanded="true"] .burger__line:nth-child(1) {
	transform: translateY(7px) rotate(45deg);
}

.burger[aria-expanded="true"] .burger__line:nth-child(2) {
	opacity: 0;
}

.burger[aria-expanded="true"] .burger__line:nth-child(3) {
	transform: translateY(-7px) rotate(-45deg);
}

@media (prefers-reduced-motion: no-preference) {
	.burger__line {
		transition: transform var(--dur-1) var(--ease-cut), opacity var(--dur-1) var(--ease-cut);
	}
}

/* Im Kontrastmodus werden Hintergründe ersetzt; die Linien wären unsichtbar. */
@media (forced-colors: active) {
	.burger__line {
		forced-color-adjust: none;
		background: CanvasText;
	}
}

@media (min-width: 62rem) {
	.burger {
		display: none;
	}
}

/* Ohne JavaScript öffnet der Burger nichts. Die Navigation steht dann als
   Liste unter dem Header (9.3, 32-mobile-nav.css). */
.burger:where(html:not(.smm-js) *) {
	display: none;
}

/* ===== 31-megamenu.css ===== */
/* =========================================================================
   31 Megamenü (ab 62rem)
   Besitzer: Team A (Rahmen) · Spezifikation 6.1 · Logik: 11-megamenu.js
   Markup: header.php baut es, inc/nav-walker.php hängt es in den ersten
   Hauptpunkt mit Unterpunkten (.nav__item--mega).
   ========================================================================= */

/* Unter 62rem gibt es kein Megamenü; die mobile Liste zeigt die Unterpunkte
   aus dem WordPress-Menü. Das hidden-Attribut hält es ohne JS geschlossen. */
.megamenu {
	display: none;
}

@media (min-width: 62rem) {
	/* Bezugsrahmen ist die klebende Kopfleiste (.nav__item--mega ist static). */
	.megamenu {
		position: absolute;
		top: 100%;
		inset-inline: 0;
		z-index: var(--z-megamenu);
		display: block;
		/* Auf niedrigen Laptop-Bildschirmen scrollt das Menü in sich,
		   statt unter den Viewport zu laufen. */
		max-height: calc(100vh - var(--header-h));
		max-height: calc(100dvh - var(--header-h));
		overflow-y: auto;
		overscroll-behavior: contain;
		background: var(--bg);
		color: var(--text);
		border-top: 1px solid rgb(16 27 28 / 8%);
		box-shadow: var(--shadow-pop);
	}

	/* Inneres 12er-Raster: Spalten 1–9 Einträge, 10–12 Teaser (ab 75rem).
	   Zwischen 62 und 75rem bekommt der Teaser vier Spalten, damit der Button
	   darin nicht auf eine Wortbreite zusammenfällt. */
	.megamenu__inner {
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--gap);
		align-items: start;
		padding-block: 2.5rem;
	}

	/* So viele gleich breite Spalten, wie gepflegt sind – keine leeren Felder. */
	.megamenu__cols {
		grid-column: 1 / -1;
		display: grid;
		grid-auto-columns: minmax(0, 1fr);
		grid-auto-flow: column;
		column-gap: var(--gap);
	}

	.megamenu__inner--teaser .megamenu__cols {
		grid-column: 1 / span 8;
	}

	.megamenu__teaser {
		grid-column: 9 / span 4;
	}

	/* Kundenfeedback 02.10.2026: Content-Produktion hat acht Einträge, die
	   übrigen drei Gruppen nur einen oder zwei. Die große Gruppe läuft über
	   zwei Spalten (Liste zweispaltig), die kleinen stapeln sich in der
	   dritten. Ohne :has() bleibt das bisherige gleichmäßige Raster. */
	.megamenu__cols:has(.megamenu__col--wide) {
		grid-auto-flow: row dense;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		row-gap: 1.75rem;
	}

	.megamenu__col--wide {
		grid-column: 1 / span 2;
		grid-row: span 3;
	}

	.megamenu__col--wide .megamenu__list {
		display: block;
		columns: 2;
		column-gap: var(--gap);
	}

	.megamenu__col--wide .megamenu__item {
		break-inside: avoid;
	}

	/* FIX: min-width-Deckelung aus der alten app.css. Ohne sie wird eine
	   Spalte so breit wie ihr längstes Wort und schiebt das Raster auf. */
	.megamenu__col,
	.megamenu__item {
		min-width: 0;
	}

	.megamenu__title {
		margin: 0 0 .75rem;
		color: var(--text-soft);
		font: 600 var(--fs-xs)/1.35 var(--font-text);
	}

	.megamenu__list {
		display: grid;
		margin: 0;
		padding: 0;
		list-style: none;
	}

	/* Die ganze Zeile ist der Link. Der negative Rand zieht Icon und Label an
	   die Kante des Spaltentitels, die Hover-Fläche reicht trotzdem darüber. */
	.megamenu__link {
		display: flex;
		align-items: flex-start;
		gap: .75rem;
		min-height: 2.75rem;
		margin-inline: -.75rem;
		padding: .625rem .75rem;
		border-radius: 0;
		color: var(--text);
		text-decoration: none;
	}

	.megamenu__link:hover {
		background: var(--surface);
		color: var(--text);
		text-decoration: none;
	}

	/* Fokus liegt innen, damit die Scrollfläche des Menüs ihn nicht abschneidet. */
	.megamenu__link:focus-visible {
		outline-offset: -2px;
	}

	.megamenu__icon {
		flex: none;
		width: 20px;
		height: 20px;
		margin-top: .0625rem;
		color: var(--accent-text);
	}

	.megamenu__text {
		display: grid;
		gap: .125rem;
		min-width: 0;
	}

	.megamenu__label {
		font: 600 var(--fs-small)/1.35 var(--font-text);
		overflow-wrap: break-word;
	}

	/* Etikett wie „NEU“: kleine Tafel in Teal-Tinte (Weiß darauf 6,29:1),
	   kein Pillen-Radius. */
	.megamenu__badge {
		display: inline-block;
		margin-inline-start: .375rem;
		padding: .0625rem .375rem;
		border-radius: 2px;
		background: var(--c-teal-ink);
		color: var(--c-white);
		font: 500 .6875rem/1.4 var(--font-mono);
		letter-spacing: .04em;
		vertical-align: .125em;
	}

	.megamenu__desc {
		color: var(--text-soft);
		font: 400 var(--fs-xs)/1.45 var(--font-text);
	}

	/* Teaser: Studio-Panel (Tokens über .theme-studio am Element) */
	.megamenu__teaser {
		display: grid;
		align-content: start;
		justify-items: start;
		gap: 1rem;
		padding: 1.75rem;
		border-radius: var(--r-panel);
		background: var(--bg);
		color: var(--text);
	}

	.megamenu__teaser-title {
		margin: 0;
		color: var(--text);
		font: 700 1.375rem/1.2 var(--font-display);
		font-stretch: 100%;
	}

	.megamenu__teaser-text {
		margin: 0;
		color: var(--text-soft);
		font-size: var(--fs-small);
		line-height: 1.55;
	}

	.megamenu__teaser .btn {
		max-width: 100%;
	}
}

@media (min-width: 75rem) {
	.megamenu__inner--teaser .megamenu__cols {
		grid-column: 1 / span 9;
	}

	.megamenu__teaser {
		grid-column: 10 / span 3;
	}
}

/* ===== 32-mobile-nav.css ===== */
/* =========================================================================
   32 Mobile Navigation (unter 62rem)
   Besitzer: Team A (Rahmen) · Spezifikation 6.1, 7.3 Nr. 10, 9.3
   Logik: 12-nav.js (is-open, html.nav-open, --nav-top, Fokusführung)

   Die Regeln stehen in (max-width: 61.99rem) statt mobile-first ohne Media
   Query: Das Panel setzt position, transform und display, die ab 62rem nicht
   zurückgesetzt werden dürften, ohne jede Desktop-Regel zu doppeln.
   Schreibweise wie 02-base.css (html.nav-open) statt Range-Syntax
   (width < 62rem), die Safari erst ab 16.4 versteht.
   ========================================================================= */

@media (max-width: 61.99rem) {
	/* Panel: fix unter der tatsächlichen Header-Unterkante, Weiß deckend.
	   FIX: --nav-top wird beim Öffnen aus der Unterkante des Headers gesetzt.
	   Eine Topbar über dem klebenden Header verschiebt sie; mit dem festen
	   --header-h lag das Panel dann über dem Burger, der sich nicht mehr
	   schließen ließ.
	   Geschlossen ist es display: none statt nur verschoben: Ein unsichtbares,
	   rechts neben dem Viewport geparktes Panel zählt sonst als horizontaler
	   Überlauf (9.2) und bleibt für Suchfunktionen im Browser erreichbar. */
	.nav {
		position: fixed;
		top: var(--nav-top, var(--header-h));
		inset-inline: 0;
		bottom: 0;
		z-index: var(--z-nav);
		display: none;
		flex-direction: column;
		margin: 0;
		padding: var(--sp-2) var(--gutter) calc(var(--sp-7) + env(safe-area-inset-bottom));
		overflow-y: auto;
		overscroll-behavior: contain;
		background: var(--bg);
		color: var(--text);
		transform: translateX(100%);
	}

	.nav.is-open {
		display: flex;
		transform: none;
	}

	/* Von rechts einfahren (260 ms). display wechselt diskret mit, damit das
	   Schließen sichtbar ausfährt; Browser ohne @starting-style öffnen sofort. */
	@media (prefers-reduced-motion: no-preference) {
		.nav {
			transition: transform var(--dur-2) var(--ease-out), display var(--dur-2) allow-discrete;
		}

		@starting-style {
			.nav.is-open {
				transform: translateX(100%);
			}
		}
	}

	/* Scroll-Sperre bei offenem Panel: html.nav-open in 02-base.css (FIX aus
	   dem alten Stand, Sperre an html statt body). 12-nav.js setzt die Klasse. */

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

	.nav__item {
		min-width: 0;
		border-bottom: 1px solid var(--line);
	}

	.nav__link {
		display: flex;
		align-items: center;
		min-height: 3.5rem;
		padding-block: .5rem;
		color: var(--text);
		font: 650 1.5rem/1.2 var(--font-display);
		font-stretch: 100%;
		text-decoration: none;
		overflow-wrap: break-word;
		hyphens: auto;
	}

	.nav__link:hover {
		color: var(--accent-text);
		text-decoration: none;
	}

	.nav__link[aria-current="page"],
	.nav__item.is-current > .nav__link {
		text-decoration: underline 2px var(--mark);
		text-underline-offset: .3em;
	}

	/* FIX: Der Menüpunkt wird so hoch wie sein aufgeklapptes Untermenü. Ein
	   absolut positionierter Pfeil mit top: 50 % landete dann mitten im Block.
	   Deshalb eine echte Zeile aus zwei Spalten. */
	.nav__item--has-children {
		display: grid;
		grid-template-columns: minmax(0, 1fr) 2.75rem;
		align-items: center;
		column-gap: var(--sp-2);
	}

	.nav__item--has-children > .nav__link {
		grid-column: 1;
		grid-row: 1;
	}

	.nav__item--has-children > .nav__toggle {
		grid-column: 2;
		grid-row: 1;
	}

	.nav__item--has-children > .nav__submenu {
		grid-column: 1 / -1;
		grid-row: 2;
	}

	.nav__submenu {
		display: none;
		margin: 0;
		padding: 0 0 var(--sp-3) var(--sp-4);
		list-style: none;
	}

	.nav__item--has-children.is-open > .nav__submenu {
		display: block;
	}

	/* Unterpunkte stehen ohne eigene Trennlinie unter ihrem Hauptpunkt. */
	.nav__submenu .nav__item {
		border-bottom: 0;
	}

	.nav__link--sub {
		min-height: 2.75rem;
		padding-block: .5rem;
		font: 600 var(--fs-body)/1.35 var(--font-text);
	}

	/* Das Megamenü ist eine Desktop-Ansicht, hier stehen die Menü-Unterpunkte. */
	.nav .megamenu {
		display: none;
	}

	/* Abschluss: der CTA gehört dorthin, wo der Nutzer gerade sucht.
	   Linksbündig statt zentriert (8.4). */
	.nav__foot {
		display: grid;
		justify-items: start;
		gap: var(--sp-2);
		margin-top: var(--sp-6);
	}

	.nav__foot .btn {
		justify-self: stretch;
	}

	.nav__foot-link {
		display: inline-flex;
		align-items: center;
		min-height: 2.75rem;
		color: var(--accent-text);
		font: 600 var(--fs-body)/1.3 var(--font-text);
	}

	/* ---------------------------------------------------------------------
	   Ohne JavaScript (9.3): Das Panel ist eine normale Liste unter dem Header.
	   Der Header klebt dann nicht, sonst läge die lange Liste dauerhaft über
	   dem Inhalt. Untermenüs stehen offen, die Schaltflächen sind ausgeblendet
	   (30-header.css).
	   --------------------------------------------------------------------- */
	.site-header:where(html:not(.smm-js) *) {
		position: relative;
	}

	.site-header__inner:where(html:not(.smm-js) *) {
		flex-wrap: wrap;
	}

	.nav:where(html:not(.smm-js) *) {
		position: static;
		/* Die Aktionen (CTA ausgeblendet, Burger ohne JS aus) bleiben in der
		   ersten Zeile; das ändert keine sichtbare Fokusreihenfolge. */
		order: 3;
		flex-basis: 100%;
		display: block;
		padding: 0 0 var(--sp-5);
		overflow: visible;
		transform: none;
	}

	.nav__item--has-children:where(html:not(.smm-js) *) {
		grid-template-columns: minmax(0, 1fr);
	}

	.nav__submenu:where(html:not(.smm-js) *) {
		display: block;
	}
}

/* ===== 33-footer.css ===== */
/* =========================================================================
   33 Footer: footer-cta und site-footer
   Besitzer: Team A (Rahmen) · Spezifikation 6.2 (footer-cta nach 6.16)

   footer-cta verwendet die Klassen cta-band__* aus 63-cta-band.css (Team D)
   wieder. Hier stehen nur die footer-spezifischen Regeln: vollbreit auf
   Studio ohne inneres Panel, Trennlinie nach unten, Zwei- bzw. Einspaltigkeit
   je nach Zeitmarke. Die Selektoren tragen .footer-cta vorn, damit sie ein
   Panel aus einer einfachen .cta-band__inner-Regel sicher aufheben.
   ========================================================================= */

/* -------------------------------------------------------------------------
   footer-cta
   ------------------------------------------------------------------------- */

.footer-cta {
	padding-block: var(--section-y);
	background: var(--bg);
	color: var(--text);
	/* Trennlinie zum site-footer, beide stehen auf Studio (6.2). */
	border-bottom: 1px solid rgb(255 255 255 / 10%);
}

/* FIX (Befund cta-deep-footer-uebergang): Endet der Seiteninhalt mit einer
   Studio-Sektion (cta_band oder channel_proof auf deep), gingen Sektion und
   footer-cta bzw. site-footer ohne Kante ineinander über, 200 bis 240 px
   leeres Studio. Dieselbe Linie wie zwischen footer-cta und site-footer
   trennt dann auch dort, wo zwei Studio-Flächen aneinanderstoßen. Nach
   Weiß, Kreide oder Teal trennt der Farbwechsel, dort bleibt es ohne Linie.
   :where() hält die Spezifität bei einer Klasse (8.5.4). */
.footer-cta:where(.site-main:has(> .section--bg-deep:last-child) + *),
.site-footer:where(.site-main:has(> .section--bg-deep:last-child) + *) {
	border-top: 1px solid rgb(255 255 255 / 10%);
}

.footer-cta .footer-cta__inner {
	display: grid;
	/* FIX: minmax(0, 1fr) statt 1fr/auto. Ohne Deckelung wird die Spur so
	   breit wie der breiteste Inhalt und schiebt den Text auf dem Handy aus
	   dem Bild. */
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sp-6);
	/* Kein Panel: der footer-cta steht selbst auf Studio. */
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
}

.footer-cta .cta-band__main {
	min-width: 0;
}

.footer-cta .cta-band__title {
	max-width: 22ch;
	/* Den Abstand zu den Buttons liefert .cta-band__actions (2rem, 63-cta-band.css). */
	margin: 0;
	color: var(--text);
	font-size: var(--fs-cta);
	font-weight: 800;
	/* FIX: Breite aus --stretch-title (94 %, unter 24rem 86 %, 00-tokens.css).
	   Das feste 94 % hatte hier zwei Klassen und hob damit auch die
	   24rem-Regel aus 63-cta-band.css auf: Unter 24rem blieb der Titel breit
	   und brach öfter um. */
	font-stretch: var(--stretch-title);
	/* Tafeln verdecken keine Unterlängen (4.4). */
	line-height: 1.16;
}

/* 375 px: Buttons untereinander über die volle Breite und gleich hoch,
   Primär zuerst (4.5). FIX (Befund button-label-umbruch-mobil): Die Reihe
   trägt dafür .cta-band__actions (footer.php) und nutzt die Regel aus
   63-cta-band.css; die eigene Kopie hier ließ ungleich hohe Buttons stehen,
   sobald ein Label umbrach. */

.footer-cta .cta-band__side {
	min-width: 0;
}

/* Ohne Zeitmarke: einspaltig, Lesebreite 48rem (6.16). */
.footer-cta .footer-cta__inner--solo {
	max-width: 48rem;
}

/* FIX (Befund „Zeitmarke 30:00 fast überall in gleicher Komposition“,
   Abnahme Runde 3): Einspaltig steht der footer-cta jetzt auf der 404-Seite
   (footer.php). Mit 22ch brach der Titel dort bei 1440 px in fünf Zeilen
   um, 627 px breit in einer 768 px breiten Spalte; der Block wurde hoch,
   daneben blieb über 400 px Höhe leeres Studio. Ab 48rem nutzt der Titel
   die ganze Lesebreite, darunter greift die Spalte selbst. */
@media (min-width: 48rem) {
	.footer-cta .footer-cta__inner--solo .cta-band__title {
		max-width: none;
	}
}

@media (min-width: 62rem) {
	/* ABWEICHUNG von 6.2/6.16 („align-items: end“ bzw. Runde 3 „Clip bündig
	   mit der Unterkante der Buttons“), begründet (Befund „Zeitmarke 30:00
	   fast überall in gleicher Komposition“, Abnahme Runde 3): Timecode oben
	   an der Titelzeile und Clip unten an den Buttons ließen dazwischen rund
	   200 px leere Spalte, die Leiste wirkte abgelöst. Jetzt dieselbe Einheit
	   wie im cta_band (63-cta-band.css, .cta-band__inner--mark): Leiste
	   direkt unter den Ziffern und so breit wie der Timecode, die Einheit
	   vertikal mittig neben dem Text und rechts bündig mit dem Container.
	   Auf der 404-Seite entfällt die Zeitmarke ganz (footer.php). */
	.footer-cta .footer-cta__inner--split {
		grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
		column-gap: 4rem;
		align-items: center;
	}

	/* FIX (Befund footer-cta-titel-22ch): Die 22ch galten auch im Split.
	   Der Titel endete bei 1440 px nach fünf Zeilen mit „funktionieren.“
	   allein bei x 650, die 7fr-Spalte reichte bis 845, die Zeitmarke begann
	   bei 909: rund 260 px Loch mitten im Schluss-Panel. Im Split begrenzt
	   die Spalte selbst, wie im cta_band (6.16 kennt dort keine Deckelung).
	   Einspaltig und unter 62rem bleiben die 22ch. */
	.footer-cta .footer-cta__inner--split .cta-band__title {
		max-width: none;
	}

	.footer-cta .footer-cta__inner--split .cta-band__actions {
		margin-top: var(--sp-7);
	}
}

/* -------------------------------------------------------------------------
   site-footer
   ------------------------------------------------------------------------- */

.site-footer {
	/* Weiß 78 % (#CACFCF, 10,27:1) und Weiß 70 % (#B6BDBE, 8,48:1) nennt 6.2
	   ausdrücklich; es gibt sie nur hier auf Studio. */
	--footer-link: rgb(255 255 255 / 78%);
	--footer-copy: rgb(255 255 255 / 70%);

	padding-block: clamp(3.5rem, 6vw, 5rem) 2rem;
	background: var(--bg);
	color: var(--text);
	font: 400 var(--fs-small)/1.6 var(--font-text);
}

/* FIX: Die Sticky-CTA liegt fix über dem Seitenende. Ohne Ausgleich verdeckt
   sie Impressum, Datenschutz und AGB im Footer. */
@media (max-width: 61.99rem) {
	.site-footer--sticky-space {
		padding-bottom: calc(2rem + 5.5rem + env(safe-area-inset-bottom));
	}
}

.site-footer__top {
	display: grid;
	/* FIX: minmax(0, 1fr), siehe footer-cta. */
	grid-template-columns: minmax(0, 1fr);
	gap: 2.5rem;
	padding-bottom: 2.5rem;
}

/* FIX: min-width: 0 an Rasterkindern, sonst sprengt ein langes Wort die Spalte. */
.site-footer__brand,
.site-footer__col {
	min-width: 0;
}

/* Marke */
.site-footer__logo {
	display: block;
	width: 180px;
	max-width: 100%;
	height: auto;
}

.site-footer__desc {
	max-width: 34ch;
	margin: 1.25rem 0 0;
	color: var(--text-soft);
	font-size: var(--fs-small);
	line-height: 1.6;
}

.site-footer__socials {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
	margin: 1.5rem 0 0;
	padding: 0;
	list-style: none;
}

/* 44-px-Quadrate, Rand Weiß 50 % (#869293, 5,04:1), Hover invertiert. Eigene
   Klassen statt .socials, das auch die Team-Sektion (Team D) nutzt. */
.site-footer__social {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	color: var(--text);
}

.site-footer__social:hover {
	border-color: var(--text);
	background: var(--text);
	color: var(--bg);
}

.site-footer__social svg {
	display: block;
	width: 18px;
	height: 18px;
}

/* Spalten: 375 px Leistungen | Unternehmen, Kontakt über volle Breite.
   FIX (Befund footer-spalten-mobil): Mit 1.5rem Spaltenabstand blieben bei
   375 px je 157 px, „Empfehlungsprogramm“ braucht 161 px und ragte 2 bis
   4 px in den Gutter. 1rem gibt jeder Spalte 161,5 px; unter 48rem stehen
   ohnehin nur diese zwei kurzen Linklisten nebeneinander. */
.site-footer__cols {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 2rem 1rem;
}

/* FIX (9.9): Ist nur eines der Menüs footer_1/footer_2 zugewiesen, stünde
   seine Spalte allein in der linken Hälfte neben einem leeren Feld. footer.php
   setzt dann --wide, die Spalte läuft wie Kontakt über die volle Breite. */
.site-footer__col--contact,
.site-footer__col--wide {
	grid-column: 1 / -1;
}

.site-footer__heading {
	margin: 0 0 1rem;
	color: var(--accent-text);
	font: 600 var(--fs-xs)/1.35 var(--font-text);
}

.site-footer__menu,
.site-footer__contact {
	display: grid;
	gap: .625rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-footer__contact li {
	color: var(--footer-link);
}

/* Trefferhöhe: 15 px × 1.6 = 24 px je Link (WCAG 2.2, 2.5.8). inline-block,
   weil die Trefferfläche eines Inline-Links nur so hoch ist wie die Schrift,
   nicht wie die Zeile. */
.site-footer__menu a,
.site-footer__contact a {
	display: inline-block;
	max-width: 100%;
	color: var(--footer-link);
	line-height: 1.6;
	text-decoration: none;
	/* Menüpunkte wie „Werbevideo erstellen lassen“ brechen bei 320 px in der
	   halben Spalte um statt über den Rand zu laufen.
	   FIX (Befund footer-spalten-mobil): break-word brach ein einzelnes zu
	   langes Wort am inline-block nicht, weil es die Mindestbreite nicht
	   verkleinert. anywhere tut das. Zuerst greift die Silbentrennung
	   („Empfehlungs-programm“, sofern die Seite lang="de" trägt), erst wenn
	   sie fehlt, der Notumbruch. hyphenate-limit-chars verhindert
	   Zwei-Buchstaben-Reste. */
	overflow-wrap: anywhere;
	hyphens: auto;
	hyphenate-limit-chars: 10 4 4;
}

.site-footer__menu a:hover,
.site-footer__contact a:hover,
.site-footer__menu a[aria-current="page"] {
	color: var(--text);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

/* Erreichbarkeit ist eine echte Zeitangabe: Plex Mono 13 px (Regel 3). */
.site-footer__contact .site-footer__hours {
	color: var(--text-soft);
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
}

/* Siegel: eine Reihe, 36 px hoch, Originalfarben */
.site-footer__badges {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem 2rem;
	margin: 0;
	padding: 1.5rem 0;
	list-style: none;
	border-top: 1px solid var(--line);
}

.site-footer__badge {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
}

.site-footer__badge-img {
	display: block;
	width: auto;
	max-width: 100%;
	height: 36px;
}

/* Unterzeile: 375 px gestapelt, ab 48rem nebeneinander */
.site-footer__bottom {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--line);
	font-size: var(--fs-xs);
}

.site-footer__copy {
	margin: 0;
	color: var(--footer-copy);
}

.site-footer__menu--legal {
	display: flex;
	flex-wrap: wrap;
	gap: .25rem 1.5rem;
	font-size: var(--fs-xs);
}

/* 14 px × 1.75 = 24,5 px Trefferhöhe */
.site-footer__menu--legal a {
	line-height: 1.75;
}

@media (min-width: 48rem) {
	.site-footer__cols {
		grid-template-columns: none;
		grid-auto-columns: minmax(0, 1fr);
		grid-auto-flow: column;
	}

	.site-footer__col--contact,
	.site-footer__col--wide {
		grid-column: auto;
	}

	.site-footer__bottom {
		flex-direction: row;
		flex-wrap: wrap;
		align-items: center;
		justify-content: space-between;
	}
}

/* Tablet: Marke oben über volle Breite, darunter drei Spalten.
   Ab 62rem: Raster 4fr | 8fr. */
@media (min-width: 62rem) {
	.site-footer__top {
		grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
		column-gap: clamp(2rem, 5vw, 5rem);
		padding-bottom: 3rem;
	}

	/* FIX (WCAG 2.4.11, 2.5.8): Der Nach-oben-Knopf (34-floating.css, fix
	   rechts unten, 1.25rem + 2.75rem = 4rem vom Rand) liegt am Seitenende
	   auf Höhe der Unterzeile. Durch space-between stehen dort die Rechtslinks;
	   bei 1280 px war der letzte rund 16 px verdeckt. Die Zeile hält rechts
	   frei, was der Knopf plus .5rem Luft über den Containerrand hinaus
	   braucht. Der Containerrand liegt max(--gutter, (100vw − --container) / 2)
	   vom Viewport entfernt; ab etwa 1400 px ist nichts mehr freizuhalten.
	   Die .5rem Luft gleichen auch aus, dass 100vw eine klassische
	   Scrollleiste mitzählt (Fehler höchstens ihre halbe Breite, rund 8 px).
	   Ohne JavaScript erscheint der Knopf nie, dann bleibt die Zeile bündig. */
	.site-footer__bottom:where(.smm-js *) {
		padding-inline-end: max(0px, 4.5rem - max(var(--gutter), (100vw - var(--container)) / 2));
	}
}

/* ===== 34-floating.css ===== */
/* =========================================================================
   34 Schwebende Bedienelemente: Sticky-CTA (unter 62rem), Nach oben (ab 62rem)
   Besitzer: Team A (Rahmen) · Spezifikation 6.28, 7.3 Nr. 11
   Logik: 40-floating-ui.js (is-visible, IntersectionObserver auf #gespraech)
   ========================================================================= */

/* -------------------------------------------------------------------------
   Sticky-CTA
   ------------------------------------------------------------------------- */

.sticky-cta {
	display: none;
}

@media (max-width: 61.99rem) {
	/* Studio-Leiste (Tokens über .theme-studio), heller Primärbutton. */
	.sticky-cta {
		position: fixed;
		inset-inline: 0;
		bottom: 0;
		z-index: var(--z-floating);
		display: block;
		padding: .75rem var(--gutter) calc(.75rem + env(safe-area-inset-bottom));
		background: var(--bg);
		color: var(--text);
		transform: translateY(100%);
		/* FIX: Ohne visibility war die ausgeblendete Leiste zwar verschoben,
		   ihr Button aber weiter im Tab-Lauf – der Fokus verschwand unter den
		   Bildschirmrand. */
		visibility: hidden;
	}

	.sticky-cta.is-visible {
		transform: none;
		visibility: visible;
	}

	/* Ausgeblendet, solange das mobile Menü offen ist (6.28). */
	.sticky-cta.is-visible:where(.nav-open *) {
		transform: translateY(100%);
		visibility: hidden;
	}

	.sticky-cta .btn {
		min-height: 3rem;
	}

	/* Einblenden 260 ms; visibility schaltet beim Ausblenden erst nach der
	   Fahrt um, damit die Leiste sichtbar hinausgleitet. Bei reduzierter
	   Bewegung gibt es gar keinen Übergang (auch keine Verzögerung). */
	@media (prefers-reduced-motion: no-preference) {
		.sticky-cta {
			transition: transform var(--dur-2) var(--ease-out), visibility 0s linear var(--dur-2);
		}

		.sticky-cta.is-visible {
			transition: transform var(--dur-2) var(--ease-out), visibility 0s;
		}
	}

	/* FIX (WCAG 2.2, 2.4.11): Ein per Tab angesteuertes Element darf nicht
	   vollständig unter der festen Leiste verschwinden. Der Browser hält beim
	   Scrollen zum Fokus diesen Abstand zum unteren Rand ein. */
	html:has(.sticky-cta.is-visible) {
		scroll-padding-bottom: calc(4.5rem + env(safe-area-inset-bottom));
	}
}

/* -------------------------------------------------------------------------
   Nach oben
   ------------------------------------------------------------------------- */

.to-top {
	display: none;
}

@media (min-width: 62rem) {
	.to-top {
		position: fixed;
		right: 1.25rem;
		bottom: 1.25rem;
		z-index: var(--z-floating);
		display: grid;
		place-items: center;
		width: 2.75rem;
		height: 2.75rem;
		margin: 0;
		padding: 0;
		/* Der Rand ist unsichtbar und wird beim Fokus weiß (siehe unten). */
		border: 2px solid transparent;
		border-radius: var(--r-control);
		background: var(--c-studio);
		color: var(--c-white);
		cursor: pointer;
		opacity: 0;
		/* FIX: Ohne diese beiden Zeilen war der Knopf zwar unsichtbar, aber
		   weiterhin anklickbar und im Tab-Lauf. */
		visibility: hidden;
		pointer-events: none;
	}

	.to-top.is-visible {
		opacity: 1;
		visibility: visible;
		pointer-events: auto;
	}

	.to-top:hover {
		background: var(--c-studio-2);
	}

	/* Zweifarbiger Fokus: außen der Fokus-Token der hellen Seite (6,29:1 auf
	   Weiß), innen Weiß gegen die Studio-Fläche. Über dem Studio-Footer, wo
	   der äußere Ring kaum absetzt, bleibt der innere sichtbar. */
	.to-top:focus-visible {
		border-color: var(--c-white);
		outline: 2px solid var(--focus);
		outline-offset: 2px;
	}

	.to-top svg {
		display: block;
		width: 18px;
		height: 18px;
	}

	@media (prefers-reduced-motion: no-preference) {
		.to-top {
			transition: opacity var(--dur-1) var(--ease-cut), visibility 0s linear var(--dur-1);
		}

		.to-top.is-visible {
			transition: opacity var(--dur-1) var(--ease-cut), visibility 0s;
		}
	}
}

/* ===== 35-breadcrumbs-pagination.css ===== */
/* =========================================================================
   35 Brotkrumen und Paginierung
   Besitzer: Team A (Rahmen) · Spezifikation 6.26, 6.27
   Markup: inc/breadcrumbs.php (smm_breadcrumbs, smm_pagination_arrows)
   ========================================================================= */

/* -------------------------------------------------------------------------
   Brotkrumen
   ------------------------------------------------------------------------- */

.breadcrumbs {
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.5 var(--font-text);
}

/* Band vor der ersten Sektion. Es trägt den Grund dieser Sektion
   (section--bg-* und data-theme kommen aus PHP) und steht damit optisch
   als Kopfzeile über dem Kicker. */
.breadcrumbs--band {
	padding-top: clamp(1rem, 2.5vw, 1.75rem);
	background: var(--bg);
}

/* Abstand Brotkrumen → Kicker: 1.5rem (6.26). Nur eine Sektion mit
   Standardabstand verliert dafür ihren oberen Sektionsabstand. Eine bewusste
   Wahl im Backend (tight, loose, none) bleibt unberührt.
   Bewusste Abweichung von 8.5 Regel 4: .section.section--space-default
   (drei Klassen) übertrifft .hero.section--space-default aus 40-hero.css,
   das später in der Kaskade steht. Sonst lägen zwischen Brotkrumen und
   Kicker bis zu 6rem. Entfällt, sobald hero.php smm_breadcrumbs( 'inline' )
   über dem Kicker aufruft (6.26, Abstimmung mit Team B). */
.breadcrumbs--band + .section.section--space-default {
	padding-top: 1.5rem;
}

/* Sektion ohne Abstand (etwa ein Hintergrundvideo-Hero bündig unter dem
   Header): Sie bleibt bündig, das Band hält selbst die 1.5rem zum Inhalt. */
.breadcrumbs--band:has(+ .section--space-none) {
	padding-bottom: 1.5rem;
}

.breadcrumbs--inline {
	margin-bottom: 1.5rem;
}

/* 375 px: eine Zeile, die seitlich scrollt. 10-header.js macht die Liste
   fokussierbar, sobald sie tatsächlich überläuft. Das Padding hält Platz für
   den Fokusring der Links, den der Scrollbereich sonst abschneidet; der
   negative Rand gleicht es in der Flucht wieder aus. */
.breadcrumbs__list {
	display: flex;
	align-items: center;
	margin: -.3125rem;
	padding: .3125rem;
	overflow-x: auto;
	list-style: none;
	white-space: nowrap;
	scrollbar-width: thin;
}

.breadcrumbs__item {
	display: flex;
	flex: none;
	align-items: center;
	min-width: 0;
}

.breadcrumbs__item[aria-current="page"] {
	color: var(--text);
}

/* Trenner als Pseudo-Inhalt: wird nicht verlinkt. Die zweite content-Zeile
   gibt ihm einen leeren Alternativtext, damit Screenreader nicht bei jedem
   Schritt „Schrägstrich“ ansagen; ältere Browser behalten die erste.
   FIX (Befund artikel-brotkrumen): Der Trenner hängt am vorigen Eintrag
   (::after) statt am folgenden (::before). Bricht ab 48rem ein langer
   Artikeltitel in die nächste Zeile, bleibt „/“ am Zeilenende stehen, statt
   die neue Zeile zu eröffnen. In einer Zeile sieht es aus wie bisher.
   ABWEICHUNG von 6.26 (li + li::before): Selektor entsprechend nachziehen. */
.breadcrumbs__item:not(:last-child)::after {
	content: "/";
	content: "/" / "";
	margin-inline: .5rem;
	color: var(--line-ui);
}

/* Trefferhöhe 24 px: inline-block, weil ein Inline-Link nur so hoch ist wie
   seine Schrift. */
.breadcrumbs__link {
	display: inline-block;
	padding-block: .1875rem;
	color: var(--text-soft);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

.breadcrumbs__link:hover {
	color: var(--accent-text);
	text-decoration-thickness: 2px;
}

@media (min-width: 48rem) {
	.breadcrumbs__list {
		flex-wrap: wrap;
		overflow-x: visible;
		white-space: normal;
	}

	.breadcrumbs__item {
		flex: 0 1 auto;
	}
}

/* -------------------------------------------------------------------------
   Paginierung
   WordPress liefert zwei Formen: the_posts_pagination() mit div.nav-links
   und paginate_links( type => list ) mit ul.page-numbers. Beide gleich.
   ------------------------------------------------------------------------- */

.pagination {
	margin-top: var(--sp-7);
}

/* Die Überschrift „Beitragsnavigation“ (h2.screen-reader-text) blendet
   04-utilities.css aus (FIX aus dem alten Stand, dort nie versteckt). */

.pagination .nav-links,
.pagination ul.page-numbers {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* 44-px-Quadrate, Rand 1.5px --line-ui (3,59:1 auf Weiß, 3,18:1 auf Kreide) */
.pagination :is(a, span).page-numbers {
	display: inline-grid;
	place-items: center;
	min-width: 2.75rem;
	height: 2.75rem;
	padding-inline: .5rem;
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	color: var(--text);
	font: 600 var(--fs-small)/1 var(--font-text);
	font-variant-numeric: tabular-nums;
	text-decoration: none;
}

.pagination a.page-numbers:hover {
	border-color: var(--ghost-bg-h);
	background: var(--ghost-bg-h);
	color: var(--ghost-fg-h);
}

/* Aktuelle Seite: Studio, weiße Schrift, kein Rand (16,17:1) */
.pagination .page-numbers.current {
	border-color: transparent;
	background: var(--c-studio);
	color: var(--c-white);
}

/* Auf Studio- und Teal-Flächen kippt die Tafel, sonst verschwände sie im Grund. */
.pagination:where([data-theme="dark"] *, .theme-studio *) .page-numbers.current {
	background: var(--c-white);
	color: var(--c-studio);
}

/* Auslassung: Text ohne Rand */
.pagination .page-numbers.dots {
	min-width: 0;
	padding-inline: .25rem;
	border-color: transparent;
}

.pagination .page-numbers svg {
	display: block;
	width: 18px;
	height: 18px;
}

/* ===== 40-hero.css ===== */
/* =========================================================================
   40-hero.css – Hero (Spezifikation 6.3). Besitzer: Team B1.
   Markup: template-parts/sections/hero.php

   Der Hero ist die Sendefassung selbst: Untertitel-Tafel in der H1 und
   Sucherrahmen am Medium. Beides kommt vom Fundament (06-highlight.css,
   12-frame.css), hier stehen nur Raster, Typografie der Textspalte,
   Vertrauenszeile, Varianten und der Pausenknopf.

   Layouts (Klasse aus hero.php):
     .hero--split    Text links, Medium rechts (auch Variante reels)
     .hero--wide     ohne Medium bzw. centered (nichts wird zentriert)
     .hero--bgvideo  Video vollflächig unter einer Studio-Tafel

   Keine Einblendung an H1, Intro, Buttons oder Poster: Sie stehen ab dem
   ersten Bild (LCP). Bewegung nur als Wortauftakt (4.4) und Rahmenmarken (5.4).
   ========================================================================= */

/* Kein overflow: hidden am Hero (alter Stand): Die Rahmenmarken liegen außen
   um das Medium und dürfen nicht abgeschnitten werden (5.4). */
.hero {
	position: relative;
}

/* Standardabstand des Heros. Eine bewusste Wahl im Backend (tight, loose,
   none) bleibt über die Abstandsklassen aus 03-layout.css bestehen. */
.hero.section--space-default {
	padding-block: clamp(3rem, 6vw, 6rem) clamp(3.5rem, 6vw, 5.5rem);
}

.hero__inner {
	row-gap: clamp(2.5rem, 6vw, 3.5rem);
	align-items: center;
}

/* FIX: Struktur-Container dürfen in Grid-Eltern schrumpfen. Sonst sprengt ein
   langes Wort oder das Poster die Spalte (alter Stand „.hero__media-wrap {
   min-width: 0 }“, minmax(0, 1fr)-Thema). */
.hero__text,
.hero__media-wrap {
	min-width: 0;
}

/* ---------- Typografie der Textspalte ---------- */

/* H1 Split-Hero (3.4): Archivo 800, stretch 94 %, unter 24rem 86 %,
   --fs-h1-split / 1.1, höchstens 15ch (ab 75rem 20ch bei höchstens 56 px,
   siehe Block „Split“). Die H1 trennt nicht (02-base.css);
   unter 30rem bleibt dort nur overflow-wrap: anywhere als Sicherung. Die Zeilenhöhe 1.16 bei Tafeln setzt
   06-highlight.css mit höherer Spezifität.
   FIX: Die Breite kommt aus dem Token --stretch-title (00-tokens.css). Ein
   festes 94 % überstimmte die 24rem-Regel aus 02-base.css in jeder Breite:
   „Straßenumfragen,“ wurde bei 320 px getrennt. Die Deklaration bleibt
   stehen, weil smm_heading_tag() den Titel auch als h2 ausgibt (zweite
   Sektion, Einzelbeitrag), und die h2-Basis hätte 96 %. */
.hero__title {
	max-width: 15ch;
	font-size: var(--fs-h1-split);
	font-weight: 800;
	font-stretch: var(--stretch-title);
	line-height: 1.1;
	letter-spacing: -.015em;
	/* Befund titel-umbruch-tafel: ohne balance blieben Einzelwörter allein auf
	   der letzten Zeile („sehen“, „bringen“). Die geschützten Leerzeichen in der
	   Tafel setzt smm_highlight() (inc/helpers.php, smm_plate_bind). */
	text-wrap: balance;
}

/* FIX: Intro 17 px bis 48rem (6.3: „375 px … Intro 17 px“), darüber 19 px –
   wie Sektionskopf, Seitenkopf und 404. Vorher stand das Hero-Intro am Handy
   größer als jedes folgende Intro. */
.hero__intro {
	max-width: 34rem;
	margin: 1.5rem 0 0;
	font-size: var(--fs-body);
	line-height: 1.55;
	color: var(--text-soft);
}

@media (min-width: 48rem) {
	.hero__intro {
		font-size: var(--fs-lead);
	}
}

/* Buttons und Vertrauenszeile. 2rem unter dem Intro (6.3); ohne Intro
   derselbe Abstand unter der H1. */
.hero__actions {
	margin-top: 2rem;
}

/* ---------- Vertrauenszeile (Pflicht, die Haken bleiben) ----------
   Das Quadrat .tick (20 px, Teal, weißer Haken 12 px; Signal auf Studio,
   Weiß auf Sektion teal) kommt aus 16-lists-checks-stars.css. */

.hero__trustline {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem 1.75rem;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
}

/* Zwei Spalten statt Inline-Fluss: Bricht ein langer Beleg um („über 250
   Millionen Videoaufrufe auf unseren eigenen Kanälen“), hängt die zweite
   Zeile unter dem Text und nicht unter dem Haken. */
.hero__trust-item {
	display: grid;
	/* auto statt 20px: Mit anderen Symbolen als dem Haken ist das Quadrat
	   größer (.tick--glyph, 16-lists-checks-stars.css). */
	grid-template-columns: auto minmax(0, 1fr);
	align-items: start;
	column-gap: .5rem;
	min-width: 0;
	font: 600 var(--fs-small)/1.35 var(--font-text);
	color: var(--text);
}

/* Quadrat mittig auf der ersten Zeile (15 px × 1.35 ≈ 20 px). Die Größe
   liest die Regel aus dem Token des Quadrats (--tick-size, 20 bzw. 24 px). */
.hero__trust-item .tick {
	margin-top: calc((1lh - var(--tick-size, 20px)) / 2);
}

/* Befund text-wrap-einzelwoerter: Bricht ein Beleg um, stehen beide Zeilen
   ähnlich lang da statt eines einzelnen Worts in der zweiten Zeile. */
.hero__trust-text {
	overflow-wrap: break-word;
	text-wrap: balance;
}

/* Redaktionshinweis (nur angemeldete Redakteure, hero.php): Medium gewählt,
   aber keine Datei gepflegt. Wie .video-testimonials__note; --text-soft kippt
   auf Studio mit. */
.hero__note {
	max-width: 60ch;
	margin: 1.5rem 0 0;
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.5 var(--font-text);
}

/* ---------- 375 px bis Tablet ---------- */

@media (max-width: 47.99rem) {
	/* Trustline als Spalte (6.3). */
	.hero__trustline {
		flex-direction: column;
		gap: .5rem;
	}
}

/* Ab 48rem stehen die Buttons nebeneinander. Unter 48rem gilt .btn--block
   aus 10-buttons.css: volle Breite, untereinander, Primär zuerst (4.5). */
@media (min-width: 48rem) {
	.hero__actions .btn--block {
		display: inline-flex;
		width: auto;
	}
}

/* Tablet und 375 px: einspaltig, Medium unter den Texten, höchstens 40rem. */
@media (max-width: 61.99rem) {
	.hero__media-wrap {
		max-width: 40rem;
	}
}

/* ---------- Split ---------- */

/* Ab 62rem: Text in Spalte 1–7, Medium in 8–12. Diese Aufteilung gilt seit
   dem Befund hero-zeilen-poster in jeder Breite ab 62rem; der frühere
   Wechsel auf 6/6 ab 75rem entfällt (Begründung im Block darunter). */
@media (min-width: 62rem) {
	.hero--split .hero__text {
		grid-column: 1 / span 7;
		/* Die Rahmenmarken ragen 10 px in den Spaltenabstand; die H1-Tafel
		   bekommt davor etwas Luft. */
		padding-inline-end: 1.5rem;
	}

	.hero--split .hero__media-wrap {
		grid-column: 8 / -1;
	}
}

/* ABWEICHUNG von 6.3 („Layout ab 75rem: Text in den Spalten 1 bis 6, Medium
   in 7 bis 12“) und von 3.4 („H1 Split-Hero … max 15ch“), Befund
   hero-zeilen-poster: Die H1 der Startseite stand in vier Zeilen, davon eine
   mit dem Waisenwort „Virale“. Gemessen bei 1512 px: Textspalte 592 px,
   Schrift 60 px, 15ch = 534 px — „Virale Straßenumfragen,“ braucht 11,27 em
   und passte damit nie in eine Zeile.

   Die Textspalte bleibt deshalb auch ab 75rem sieben Spalten breit (696 px
   bei vollem Container, abzüglich 1.5rem Innenabstand 672 px nutzbar), die
   H1 darf 20ch laufen und die Schrift hört bei 3.5rem = 56 px auf. Dann
   steht der Titel in zwei Zeilen: „Virale Straßenumfragen,“ / „die dir
   Anfragen bringen“.

   Warum genau diese drei Werte:
   - 20ch sind 11.875 em und damit bei 56 px 665 px. Die Zeilenlänge hängt so
     an der erklärten Maximalbreite und nicht an der zufälligen Spaltenbreite
     (672 px); die Spalte bleibt Reserve.
   - Die längste Zeile braucht 11.27 em, bei 56 px also 631 px. Gegenüber den
     672 px der Spalte sind das 6,5 % Luft. Im metrischen Fallback
     („Archivo Fallback“, 01-fonts.css) ist genau diese Zeile 2,5 % schmaler,
     der Schriftwechsel kann also keine dritte Zeile erzeugen (kein CLS).
   - Mehr als 56 px kippt: bei 60 px braucht die Zeile 676 px und passt nicht
     mehr in die Spalte — bei 1512 px wären es wieder drei Zeilen.
   - Am knappsten sitzt es direkt an der Grenze: bei 1200 px sind 609 px
     nutzbar und 595 px nötig, also 2,3 % Luft. Von 1280 px an sind es wieder
     über 6 %. Geprüft bei 1200, 1216, 1280, 1333, 1366, 1440, 1512, 1600 und
     1920 px — überall zwei Zeilen.

   Die Obergrenze steht hier und nicht am Token --fs-h1-split (00-tokens.css),
   weil dieser Token auch den 404-Titel trägt (75-404-search.css), der die
   volle Breite behalten soll.

   Das Medium bekommt dadurch fünf statt sechs Spalten (488 px statt 592 px
   bei 1512 px). Sucherrahmen, Abspieltafel und Marken bleiben unverändert
   maßstäblich, geprüft bei 1512, 1440, 1280 und 1200 px.

   Die Reel-Reihe behält ihre sechs Spalten (Regel unten, höhere
   Spezifität): In fünf Spalten schrumpfen vier Reels bei 992 px auf rund
   85 px, weit unter die Mindestbreite 8rem aus 6.3. */
@media (min-width: 75rem) {
	.hero--split .hero__title {
		max-width: 20ch;
		font-size: min(var(--fs-h1-split), 3.5rem);
	}
}

@media (min-width: 62rem) {
	.hero--media-reels.hero--split .hero__text {
		grid-column: 1 / span 6;
	}

	.hero--media-reels.hero--split .hero__media-wrap {
		grid-column: 7 / -1;
	}
}

/* ---------- Wide: Titelkarte (ohne Medium, auch centered) ----------
   Ein Sendetitel steht formatfüllend im Bild und nicht als Absatz neben
   einer Buttonsäule (Art-Director-Verbesserung „Titelkarte“). Die H1 läuft
   deutlich größer über die Spalten 1–11. Darunter liegt die Bandleiste mit
   1px-Linie oben: Intro, Buttons und Vertrauenszeile auf einer gemeinsamen
   Oberkante. Damit entfallen die schwebende Buttonspalte mit Überhang unter
   dem Intro und die leere rechte Fläche (Befunde hero-wide-aktionsspalte,
   hero-ohne-medium-rueckfall).

   ABWEICHUNG von 6.3 (H1 in --fs-h1-wide über 1–10, Intro 1–6, Buttons plus
   Vertrauenszeile gestapelt in 8–12, align-self: end): Primär- und
   Ghost-Button brauchen nebeneinander bis 570 px, Spalte 8–12 hat bei 1440 px
   nur 488 px; die Buttons stapelten sich mit flatternder Kante, und der
   Block hing 36–144 px unter dem Intro. Die Titelkarte löst das über das
   Raster statt über Einzelkorrekturen. */

/* ABWEICHUNG von --fs-h1-wide (höchstens 4.75rem): Die Titelkarte trägt den
   ersten Bildschirm allein, ohne Medium. 1440 px ergibt rund 91 px, 1920 px
   104 px (6.5rem). Unter 48rem bleibt es bei rund 34–36 px wie im Split-Hero
   (6.3), das Minimum 2.125rem hält „Straßenumfragen,“ bei 320 px in der
   Satzbreite (86 % aus --stretch-title; keine Silbentrennung, unter 30rem
   nur overflow-wrap als Sicherung aus 02-base.css). */
.hero--wide .hero__title {
	max-width: 18ch;
	font-size: clamp(2.125rem, 1rem + 5.2vw, 6.5rem);
}

@media (min-width: 48rem) {
	/* 1.06 nur ohne Tafel; mit Tafel bleibt 1.16 aus 06-highlight.css. */
	.hero--wide .hero__title:not(:has(.hl--plate)) {
		line-height: 1.06;
	}

	/* Gelöste Tafelbindung (span.hl__nb aus smm_highlight): In der breiten
	   Titelzeile ab 48rem ist Platz für den ganzen Lauf, also bleibt er
	   zusammen und „rund“ steht nicht allein am Zeilenende vor
	   „20 Kurzvideos“. Die Läufe haben höchstens 21 Zeichen; die schmalste
	   Titelzeile hier (768 px, 56 px Schrift) trägt rund 25. */
	.hero--wide .hero__title .hl__nb {
		white-space: nowrap;
	}

	/* Bandleiste ab Tablet mit Linie. Unter 48rem steht alles ohne Linie
	   untereinander wie im Split-Hero (6.3, 375 px). */
	.hero--wide .hero__band {
		margin-top: clamp(2rem, 4vw, 3.5rem);
		padding-top: clamp(1.5rem, 2.4vw, 2.25rem);
		border-top: 1px solid var(--line);
	}

	.hero--wide .hero__band > :first-child {
		margin-top: 0;
	}

	/* Die Vertrauenszeile ist im Band immer eine gestapelte Datenzeile, nie
	   1+2 oder 2+1 (Befund hero-wide-aktionsspalte, auch auf Tablet). */
	.hero--wide .hero__trustline {
		flex-direction: column;
		gap: .625rem;
	}
}

@media (min-width: 62rem) {
	.hero--wide .hero__text {
		grid-column: 1 / -1;
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--gap);
		align-items: start;
	}

	.hero--wide .hero__text > * {
		grid-column: 1 / span 10;
		min-width: 0;
	}

	/* Über die Spalten 1–11. 21ch statt 18ch: Bei rund 91 px trennte 18ch
	   kurze Titel an unglücklicher Stelle („Danke. Wir / haben deine /
	   Anfrage erhalten“); balance verteilt die Zeilen danach gleichmäßig. */
	.hero--wide .hero__title {
		grid-column: 1 / span 11;
		max-width: 21ch;
	}

	/* Das Band nutzt dasselbe 12er-Raster über die volle Containerbreite. */
	.hero--wide .hero__band {
		grid-column: 1 / -1;
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--gap);
		align-items: start;
	}

	.hero--wide .hero__band > * {
		min-width: 0;
		margin-top: 0;
	}

	/* 62–75rem: Intro links (1–7), rechts die Buttons über der
	   Vertrauenszeile (8–12). Drei Spalten wären hier zu schmal: Spalte 7–9
	   hat bei 992 px 209 px, der Primärbutton braucht 306 px. */
	.hero--wide .hero__intro {
		grid-column: 1 / span 7;
		grid-row: 1 / span 2;
	}

	.hero--wide .hero__actions {
		grid-column: 8 / -1;
		grid-row: 1;
	}

	.hero--wide .hero__trustline {
		grid-column: 8 / -1;
		grid-row: 2;
		margin-top: 1.75rem;
	}

	/* Zwei Buttons gleich breit untereinander, Primär zuerst (4.5). Das Label
	   wächst, das Pfeilsegment bleibt rechts; keine flatternde Kante. */
	.hero--wide .hero__actions--pair .btn-row {
		flex-direction: column;
		align-items: stretch;
	}

	/* Ohne Vertrauenszeile: Intro 1–7, Buttons 8–12 auf derselben Oberkante. */
	.hero--wide .hero__band--no-trust .hero__intro {
		grid-row: 1;
	}

	/* Ohne Intro: Buttons in natürlicher Breite links unter der Linie, die
	   Vertrauenszeile rechts daneben. */
	.hero--wide .hero__band--no-intro .hero__actions {
		grid-column: 1 / span 7;
	}

	.hero--wide .hero__band--no-intro .hero__trustline {
		grid-row: 1;
		margin-top: 0;
	}

	.hero--wide .hero__band--no-intro .hero__actions--pair .btn-row {
		flex-direction: row;
	}

	/* centered mit Medium: Das Medium steht unter dem Text in Spalte 1–8. */
	.hero--wide .hero__media-wrap {
		grid-column: 1 / span 8;
	}
}

/* Ab 75rem: drei Bandspalten auf einer Oberkante. Intro 1–5, Buttons 6–9,
   Vertrauenszeile 10–12.
   ABWEICHUNG vom Vorschlag „Buttons in 7–9“: 7–9 sind bei 1440 px 280 px
   breit, der Primärbutton „Kostenloses Erstgespräch“ braucht 306 px. Vier
   Spalten (384 px bei 1440, 350 px bei 1200) tragen beide Buttons gleich
   breit ohne Umbruch im Label. */
@media (min-width: 75rem) {
	.hero--wide .hero__intro {
		grid-column: 1 / span 5;
		grid-row: 1;
		/* Luft zur Buttonspalte: Der Flattersatz läuft sonst bis an den
		   Spaltenabstand. */
		padding-inline-end: 1rem;
	}

	.hero--wide .hero__actions {
		grid-column: 6 / span 4;
	}

	.hero--wide .hero__trustline {
		grid-column: 10 / -1;
		grid-row: 1;
		margin-top: 0;
	}

	/* Ohne Vertrauenszeile: Intro 1–6, Buttons 8–11. */
	.hero--wide .hero__band--no-trust .hero__intro {
		grid-column: 1 / span 6;
	}

	.hero--wide .hero__band--no-trust .hero__actions {
		grid-column: 8 / span 4;
	}

	/* Ohne Intro: Buttons 1–7 nebeneinander, Vertrauenszeile 9–12. */
	.hero--wide .hero__band--no-intro .hero__actions {
		grid-column: 1 / span 7;
	}

	.hero--wide .hero__band--no-intro .hero__trustline {
		grid-column: 9 / -1;
	}
}

/* ---------- Medium: eigene Videodatei ----------
   9:16 höchstens 22rem breit und linksbündig in der Spalte (6.3). Ein
   Querformat-Film (Maße aus der Datei) füllt die Spalte in 16:9. */

.hero__frame--9x16 {
	width: min(100%, 22rem);
}

/* ---------- Medium: Einbettung eines YouTube-Shorts (9:16) ----------
   ABWEICHUNG von 6.3 (embed nur 16:9): hero.php erkennt eine shorts/-URL und
   gibt den Zwei-Klick-Bildschirm hochkant aus (.hero__frame--9x16). Ab 62rem
   bekommt der Text die Spalten 1–7 und der schmale Rahmen steht rechts in
   8–12, bündig an der rechten Satzkante, sonst läge neben dem Bildschirm
   ein leerer Streifen zwischen Rahmen und Satzkante. Breite höchstens
   18.5rem statt 22rem: Mit 22rem war der Rahmen bei 1440 px 650 px hoch,
   höher als die Textspalte, und die oberen Marken stießen an die Leiste
   über dem Hero. Unter 62rem steht er unter der Vertrauenszeile, höchstens
   18rem breit. */
@media (min-width: 62rem) {
	.hero--split:has(.hero__media-wrap--vertical) .hero__text {
		grid-column: 1 / span 7;
	}

	.hero--split .hero__media-wrap--vertical {
		grid-column: 8 / -1;
		justify-self: end;
		width: min(100%, 18.5rem);
	}
}

@media (max-width: 61.99rem) {
	.hero__media-wrap--vertical .hero__frame--9x16 {
		width: min(100%, 18rem);
	}
}

.hero__video-media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--r-media);
	/* FIX: kein weißer Streifen, solange Poster oder erstes Bild fehlen. */
	background: var(--c-studio);
}

/* ---------- Medium: Reels ----------
   Bis zu vier .reel (Team B2, overlays false) nebeneinander, vertikal
   versetzt 0 / 2.5rem / 1rem / 3.5rem, keine Rotation. Die Breite schrumpft
   mit, wenn die Spalte schmaler ist als vier Reels (62–75rem). */

.hero__reels {
	display: flex;
	align-items: flex-start;
	gap: .75rem;
}

.hero__reels > .reel {
	flex: 0 1 clamp(8rem, 11vw, 12rem);
	width: auto;
	min-width: 0;
}

.hero__reels > .reel:nth-child(2) { margin-top: 2.5rem; }
.hero__reels > .reel:nth-child(3) { margin-top: 1rem; }
.hero__reels > .reel:nth-child(4) { margin-top: 3.5rem; }

/* 375 px: Scroll-Snap-Reihe mit 44vw ohne Versatz. Negativer Rand plus
   Innenabstand halten den Fokusring des Scrollers im Gutter. */
@media (max-width: 47.99rem) {
	.hero__reels {
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		scroll-padding-inline: .375rem;
		margin-inline: -.375rem;
		padding: .375rem;
	}

	.hero__reels > .reel {
		flex: 0 0 44vw;
		scroll-snap-align: start;
	}

	.hero__reels > .reel:nth-child(n) {
		margin-top: 0;
	}
}

/* ---------- Pausenknopf (Autoplay nur ohne reduzierte Bewegung) ----------
   44 px, Studio 88 %, weißes Symbol, aria-pressed. 21-autoplay.js zeigt ihn
   erst, wenn das Video wirklich läuft. */

.hero__pause {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: var(--r-control);
	background: rgb(13 36 39 / 88%);
	color: var(--c-white);
	cursor: pointer;
	transition: background-color var(--dur-1) var(--ease-cut);
}

/* FIX: [hidden] muss gegen display: grid gewinnen, sonst bleibt der Knopf
   ohne JavaScript sichtbar und wirkungslos (alter Grundsatz-Fix, hier lokal
   abgesichert). */
.hero__pause[hidden] {
	display: none;
}

.hero__pause:hover {
	background: var(--c-studio);
}

.hero__pause-icon {
	width: 1.125rem;
	height: 1.125rem;
	fill: currentColor;
}

/* Gedrückt heißt pausiert: dann zeigt der Knopf das Abspieldreieck. */
.hero__pause-icon--play,
.hero__pause[aria-pressed="true"] .hero__pause-icon--pause {
	display: none;
}

.hero__pause[aria-pressed="true"] .hero__pause-icon--play {
	display: block;
}

/* Im Bildschirm unten rechts. */
.hero__pause--screen {
	position: absolute;
	right: .75rem;
	bottom: .75rem;
	z-index: var(--z-raised);
}

/* Beide Knöpfe über bewegtem Bild (Poster bzw. Hintergrundvideo) sind
   beliebig hell oder dunkel unterlegt. Der Standardring aus 02-base.css
   (--focus #2FAFAF auf Studio) käme rechts im Hintergrundvideo, wo das
   Overlay nur 70 % deckt, über einem weißen Pixel auf 2,26:1. Der Ring
   liegt deshalb auf einem eigenen Tinten-Band: Weiß auf #101B1C 17,56,
   Tinte gegen helle Stellen, Weiß gegen dunkle (9.1). */
.hero__pause--screen:focus-visible,
.hero__pause--bg:focus-visible {
	outline: 2px solid var(--c-white);
	outline-offset: 3px;
	box-shadow: 0 0 0 5px var(--c-ink);
}

/* Unter den Reels im Fluss, auf dem Sektionsgrund: normaler Fokusring. */
.hero__pause--flow {
	margin-top: 1.25rem;
}

/* ---------- Bgvideo ----------
   Video vollflächig, Studio-Tokens über .theme-studio. Text in Spalte 1–7. */

.hero--bgvideo {
	display: grid;
	align-items: center;
	min-height: min(88vh, 760px);
	min-height: min(88svh, 760px);
	isolation: isolate;
}

.hero__bg {
	position: absolute;
	inset: 0;
	z-index: -1;
	overflow: hidden;
	background: var(--bg);
}

.hero__bg-media {
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: cover;
}

/* Overlay. Maßstab ist die schwächste Textfarbe darüber, --accent-text
   #2FAFAF (Kicker), gerechnet über einem weißen Videopixel. Bei 90 % Studio
   ergibt die Mischfläche rgb(37 58 61) und der Kicker nur 4,495:1, deshalb
   92 %: Mischfläche rgb(32 54 56), #2FAFAF 4,78:1, Sekundärtext #A7C0C2
   6,66:1, Weiß 12,76:1, Ghost-Rand #869293 3,98:1.
   Unter 62rem läuft der Text über die volle Breite, dort deckt die Tafel
   gleichmäßig. Mit dem Verlauf aus 6.3 (70 % rechts) käme der Sekundärtext
   dort nur auf 3,2:1. */
.hero__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: rgb(13 36 39 / 92%);
}

@media (min-width: 62rem) {
	/* Abweichung vom Verlauf aus 6.3 (90 % bis 45 %), begründet mit 9.1: Die
	   Textspalte (Spalten 1–7) endet bei 62rem und bis 1280 px bei rund 57 %
	   der Breite, darüber weiter links. Der Verlauf aus 6.3 deckt dort nur noch
	   85,8 %, der Kicker fiele dort auf 3,9:1. Deshalb bleibt die volle Deckung
	   von 92 % bis 60 % stehen und läuft erst rechts der Textspalte auf 70 %
	   aus. Alle Werte der Textspalte wie oben. */
	.hero__bg::after {
		background: linear-gradient(90deg, rgb(13 36 39 / 92%) 0 60%, rgb(13 36 39 / 70%));
	}

	.hero--bgvideo .hero__text {
		grid-column: 1 / span 7;
	}
}

.hero__pause--bg {
	position: absolute;
	right: var(--gutter);
	bottom: 1.25rem;
	z-index: var(--z-raised);
}

/* ---------- Druck ---------- */

@media print {
	.hero__pause {
		display: none;
	}
}

/* ---------- Lange H1 (hero__title--long, ab 64 Zeichen) ----------
   Kundenfeedback 02.10.2026: Die neue Startseiten-H1 hat 81 Zeichen. In der
   Standardstufe stand sie bei 1440 px auf vier, bei 375 px auf sechs Zeilen,
   „Full-“ brach am Bindestrich aus der Tafel. Kleinere Stufe, breitere
   Satzspalte, Tafelwörter brechen nicht am Bindestrich. Mit Hochkant-Video
   bekommt der Text ab 75rem acht Spalten, der Rahmen bleibt 18.5rem breit. */
.hero__title--long {
	max-width: 24ch;
	font-size: clamp(1.75rem, 1.25rem + 2.2vw, 3.125rem);
}

.hero__title--long .hl__w {
	white-space: nowrap;
}

@media (min-width: 75rem) {
	.hero--split .hero__title--long {
		max-width: 27ch;
		font-size: min(var(--fs-h1-split), 3.125rem);
	}

	/* Feedback 15.10.2026: Die Hervorhebung „Full-Service Social Media
	   Agentur“ steht am Desktop in einer Zeile. Neben dem Hochkant-Video
	   bekommt der Text 9 von 12 Spalten (der Rahmen braucht 16.5rem, drei
	   Spalten sind ab 75rem mindestens 17rem breit). Die Schrift richtet sich
	   nach der Spaltenbreite (Container-Einheit cqi): Gemessen sind Zeile 1
	   „Deine“ + Tafel 18,42em und Zeile 2 „für Deutschland, Österreich & die
	   Schweiz“ 19,24em; die Titelbox ist 97 % der Spalte breit. 4.9cqi hält
	   beide Zeilen mit rund 2 % Luft, 2.8rem deckelt. Ohne balance, sonst
	   stellt der Browser „Deine“ allein in die erste Zeile. */
	.hero--split:has(.hero__media-wrap--vertical):has(.hero__title--long) .hero__text {
		grid-column: 1 / span 9;
		container-type: inline-size;
	}

	.hero--split:has(.hero__title--long) .hero__media-wrap--vertical {
		grid-column: 10 / -1;
	}

	.hero--split:has(.hero__media-wrap--vertical) .hero__title--long {
		max-width: none;
		font-size: 2.75rem;
		font-size: min(2.8rem, 4.9cqi);
		text-wrap: wrap;
	}

	.hero--split:has(.hero__media-wrap--vertical) .hero__title--long .hl {
		white-space: nowrap;
	}
}

/* ---------- Kennzahlen (hero__stats) ----------
   Loom vom 06.10.2026, Referenz Hashtag Hamburg: große Zahlen mit kurzer
   Beschriftung unter den Buttons statt Haken-Zeile. Zahl in der
   Display-Schrift mit Tabellenziffern, Beschriftung klein in --text-soft.
   Auf Studio (Hero mit Grund deep) kippen beide Farben über die Tokens. */
.hero__stats {
	list-style-type: "";
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: max-content;
	justify-content: start;
	gap: 1.25rem clamp(1.25rem, 3vw, 3rem);
	margin: clamp(1.75rem, 3vw, 2.5rem) 0 0;
	padding: 0;
}

.hero__stat {
	display: grid;
	gap: .25rem;
	min-width: 0;
}

.hero__stat-value {
	font: 700 clamp(1.375rem, .6rem + 1.8vw, 2.5rem)/1 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums;
	letter-spacing: -.01em;
	color: var(--text);
}

.hero__stat-label {
	max-width: 14ch;
	font-size: var(--fs-xs);
	line-height: 1.35;
	color: var(--text-soft);
}

/* Unter 30rem drei Zahlen in einer Reihe, kleiner gesetzt. */
@media (max-width: 29.99rem) {
	.hero__stats {
		grid-auto-flow: row;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 1rem;
	}

	.hero__stat-value {
		font-size: clamp(1.125rem, .55rem + 3vw, 1.375rem);
	}
}

/* Loom vom 06.10.2026: „Auf einen Blick alles sehen“. Split-Hero mit
   Hochkant-Video und Kennzahlen kompakter, damit bei 1440 x 900 die
   Logoleiste noch im ersten Bildschirm beginnt: weniger Polster, Rahmen
   ab 62rem 16.5rem statt 18.5rem breit. */
.hero--split.section--space-default:has(.hero__media-wrap--vertical):has(.hero__stats) {
	padding-block: clamp(2.5rem, 4vw, 3.75rem);
}

@media (min-width: 62rem) {
	.hero--split:has(.hero__stats) .hero__media-wrap--vertical {
		width: min(100%, 16.5rem);
	}
}

/* ===== 41-logo-bar.css ===== */
/* =========================================================================
   41-logo-bar.css – Absender-Bauchbinde (Spezifikation 6.4, nach
   Sichtprüfung neu gefasst). Markup: template-parts/sections/logo_bar.php

   ABWEICHUNG von 6.4 (Mikrofonwürfel): Die gezeichneten Würfel sahen auf
   375 und 1440 px wie Schilder auf Pfosten aus; ohne Kopf und Stiel blieb
   eine generische Trusted-by-Leiste mit Haarlinien und einem leeren Drittel
   rechts. Die Absenderzeile ist jetzt eine Bauchbinde (5.3, Grammatik):
   - Namenstafel (.l3__name) mit der gepflegten Zeile, etwas größer als an
     einer Person, weil sie eine ganze Sektion beschriftet,
   - darunter die helle Rollentafel (.l3__role) als Liste der Logos. Sie
     wächst mit der Zahl der Logos (--n Zellen je Zeile, aus logo_bar.php)
     und ist ab vier Zellen containerbreit. Kein leeres Drittel, keine
     Trennlinien, keine Kacheln.
   Farben kommen aus den Bauchbinden-Tokens: Rollentafel Kreide auf Weiß,
   Weiß auf Kreide und auf Studio. Die Logos stehen darauf in Originalfarbe,
   ohne Graustufen, ohne Opacity, ohne Hover-Kippung, ohne Schatten.

   Gleiche sichtbare Fläche je Logo: logo_bar.php ordnet jedem Logo eine
   Seitenverhältnis-Stufe (r*) und eine Randstufe (p*) zu. Die Box wird
   s · q · p breit und s / q · p hoch; q = √Seitenverhältnis der Stufe,
   p gleicht transparenten Rand in der Datei aus. Damit hat jedes Logo die
   Fläche s², Matari Solar (1,56:1) ist so groß wie Gymside (3,9:1) schwer.

   Einzige zentrierte Stelle der Website (8.4): Jedes Logo steht mittig in
   seiner Zelle, weil es schmaler ist als die Zelle.
   ========================================================================= */

/* ---------- Bauchbinde ---------- */

/* Namenstafel: l3__name-Optik aus 13-lower-third.css, eine Stufe größer. */
.sender__label {
	font-size: clamp(1.0625rem, .95rem + .45vw, 1.3125rem);
	padding: .45rem .875rem .4rem;
}

/* Rollentafel als Liste. Die Grundregel von .l3__role (Tafelgrund, Radius,
   Umbruch) bleibt, Schrift und Innenabstand übernimmt die Liste. */
.sender__list {
	display: flex;
	flex-wrap: wrap;
	width: min(100%, calc(var(--n, 4) * 19rem));
	margin: 0;
	padding: .25rem;
	list-style: none;
}

/* ---------- Logozellen ---------- */

/* Unter 48rem zwei Zellen je Zeile, darüber --n. Die Basis liegt 1 px unter
   dem rechnerischen Anteil, damit Rundung nie eine Zelle zu viel in die
   nächste Zeile schiebt; flex-grow füllt den Rest. Eine kürzere letzte
   Zeile (ungerade Anzahl mobil, 5 oder 7 Logos ab 48rem) füllt sich
   dadurch ganz, es bleibt keine leere Zelle (9.9). */
.sender__item {
	--sender-cols: 2;
	--sender-s: 3.75rem;
	--sender-q: 1.5;
	--sender-p: 1;
	display: grid;
	flex: 1 1 calc(100% / var(--sender-cols) - 1px);
	place-items: center;
	min-width: 0;
	padding: .75rem .5rem;
}

@media (min-width: 48rem) {
	.sender__item {
		--sender-cols: var(--n, 4);
		--sender-s: 4.5rem;
	}
}

/* Grundfläche s aus der Zellbreite: Das breiteste übliche Logo (q · p rund
   2,3) passt mit 1rem Zellabstand in seine Zelle. Höchstens 4.75rem, damit
   die Tafel ruhig bleibt; mindestens 3rem, damit Matari Solar lesbar ist.
   In @supports, weil eine unbekannte Einheit in der Variablen erst beim
   Einsetzen ungültig würde und die Logos dann ohne Größe stünden. */
@supports (width: 1cqi) {
	.sender__list {
		container-type: inline-size;
	}

	.sender__item {
		--sender-s: clamp(3rem, (100cqi / var(--sender-cols) - 1rem) / 2.35, 4.75rem);
	}
}

/* Seitenverhältnis-Stufen: q = √(1 · 1,5 · 2,25 · 3,4 · 5 · 7,5) */
.sender__item--r1 { --sender-q: 1; }
.sender__item--r15 { --sender-q: 1.225; }
.sender__item--r22 { --sender-q: 1.5; }
.sender__item--r34 { --sender-q: 1.844; }
.sender__item--r5 { --sender-q: 2.236; }
.sender__item--r75 { --sender-q: 2.739; }

/* Randstufen: Kehrwert der Wurzel des gezeichneten Flächenanteils */
.sender__item--p1 { --sender-p: 1.12; }
.sender__item--p2 { --sender-p: 1.25; }
.sender__item--p3 { --sender-p: 1.4; }

/* Feste Box je Logo. FIX: Ein SVG-Logo ohne brauchbare width/height-
   Attribute (WordPress liefert 1 × 1) hat keine eigene Breite; die feste
   Box plus object-fit gibt ihm eine Größe (früher war Holistic unsichtbar). */
.sender__logo {
	display: block;
	width: calc(var(--sender-s) * var(--sender-q) * var(--sender-p));
	height: calc(var(--sender-s) / var(--sender-q) * var(--sender-p));
	max-width: 100%;
	border-radius: var(--r-plate);
}

.sender__logo img {
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: contain;
}

a.sender__logo:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 4px;
}

/* Logo, das nur auf dunklem Grund funktioniert (Feld „Auf dunklem Grund
   aufhellen“): Tintenfläche in der Zelle, Logo in Originalfarbe (wie
   .cube--invert in 6.4). */
.sender__item--invert {
	border-radius: var(--r-plate);
	background: var(--c-ink);
}

/* ---------- Ab 9 Logos: horizontaler Scroller ----------
   Die Rollentafel scrollt in sich. Scroll-Snap proximity statt mandatory,
   damit das Scrollen per Tastatur nicht an jedem Logo hängen bleibt. Die
   Zellen haben eine feste Breite, die Grundfläche bleibt fest. */
.sender__list--scroll {
	flex-wrap: nowrap;
	width: 100%;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x proximity;
	scroll-padding-inline: .25rem;
}

.sender__list--scroll > .sender__item {
	--sender-s: 3.75rem;
	flex: none;
	width: 10.5rem;
	scroll-snap-align: start;
}

.sender__list--scroll:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 3px;
}

/* Direkt nach dem Hero rückt die Absenderzeile heran (6.4). */
.section--hero + .section--logo-bar {
	padding-top: 1.5rem;
}

/* ---------- Laufband (Kundenwunsch 02.10.2026) ----------
   Markup: .sender--marquee > .sender__label + .sender__window > .sender__track
   > zwei gleiche .sender__list--roll. Das Band läuft nur, wenn JavaScript
   läuft (dann gibt es den Pausenknopf, WCAG 2.2.2) und keine reduzierte
   Bewegung eingestellt ist. Sonst steht die erste Reihe still im Fenster und
   lässt sich wischen; die Kopie bleibt ausgeblendet.
   Die Zellen haben eine feste Breite und keinen gap: Eine Reihe ist damit
   exakt halb so breit wie die Spur, translateX(-50 %) schließt nahtlos. */
.sender--marquee {
	position: relative;
	display: block;
}

.sender__window {
	display: block;
	width: 100%;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scrollbar-width: thin;
}

.sender__window:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 3px;
}

.sender__track {
	display: flex;
	width: max-content;
}

.sender__list--roll {
	flex-wrap: nowrap;
	width: auto;
	padding: .25rem 0;
}

.sender__list--roll > .sender__item {
	--sender-s: 3.5rem;
	flex: none;
	width: 10rem;
	padding-inline: 1rem;
}

@media (min-width: 48rem) {
	.sender__list--roll > .sender__item {
		--sender-s: 4rem;
		width: 12.5rem;
		padding-inline: 1.5rem;
	}
}

.sender__list--copy {
	display: none;
}

@media (prefers-reduced-motion: no-preference) {
	html.smm-js .sender__window {
		overflow: hidden;
	}

	html.smm-js .sender__list--copy {
		display: flex;
	}

	/* Etwa 3,5 s je Logo: ruhig genug zum Lesen, schnell genug als Bewegung. */
	html.smm-js .sender__track {
		animation: sender-roll calc(var(--n, 8) * 3.5s) linear infinite;
	}

	html.smm-js .sender__window:is(:hover, :focus-within) .sender__track,
	html.smm-js .sender__window.is-paused .sender__track {
		animation-play-state: paused;
	}
}

@keyframes sender-roll {
	to {
		transform: translateX(-50%);
	}
}

/* Pausenknopf (von 35-marquee.js eingefügt), rechts auf Höhe der Namenstafel. */
.sender__pause {
	position: absolute;
	top: 0;
	right: 0;
	display: grid;
	place-items: center;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	border: 0;
	border-radius: var(--r-plate);
	background: transparent;
	color: var(--text);
	box-shadow: inset 0 0 0 1.5px var(--line-ui);
	cursor: pointer;
}

.sender__pause:hover {
	background: var(--text);
	color: var(--bg);
	box-shadow: none;
}

.sender__pause:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}

.sender__pause svg {
	width: 14px;
	height: 14px;
	fill: currentColor;
}

@media (prefers-reduced-motion: reduce) {
	.sender__pause {
		display: none;
	}
}

/* ===== 42-video-embed.css ===== */
/* =========================================================================
   42-video-embed.css – Video mit Zwei-Klick-Lösung (Spezifikation 5.4, 6.3).
   Besitzer: Team B1. Markup: template-parts/components/video-embed.php,
   Verhalten: assets/js/src/20-video-embeds.js

   div.video-embed ist der Bildschirm: Poster (bzw. eigene Videodatei) und
   darüber der Abspielknopf mit mittiger Tafel aus Segment und Label. Den
   Sucherrahmen (Marken, Hinweiszeile) liefert .frame aus 12-frame.css.

   Die Tafel steht über einem Bild, nicht über dem Sektionsgrund. Ihre Farben
   kippen deshalb nicht mit data-theme: Segment #156A72 mit weißem Dreieck,
   Label Weiß auf #1C818B (4,60, Archivo 650 17 px), Hover Label #156A72 und
   Segment #0F4E54 (6.3, Rohfarben dort ausdrücklich genannt).
   ========================================================================= */

/* Kein overflow: hidden am Bildschirm: Die Rahmenmarken liegen außen (5.4),
   und der Radius wird an Poster, Video und Iframe selbst gesetzt.
   Die Studio-Fläche steht, solange kein Poster da ist; ein weißer Streifen
   entsteht so auch ohne Bild nicht (9.2). */
.video-embed {
	position: relative;
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	border-radius: var(--r-media);
	background: var(--c-studio);
}

.video-embed--vertical {
	aspect-ratio: 9 / 16;
}

/* FIX: Poster, Video und Iframe füllen den Bildschirm vollständig und
   randlos. display: block verhindert die Unterlängen-Lücke unter
   Inline-Medien, die als weißer Rand unter dem Video sichtbar war. */
.video-embed__poster,
.video-embed__video,
.video-embed > iframe {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	margin: 0;
	border: 0;
	border-radius: inherit;
	object-fit: cover;
	background: var(--c-studio);
}

/* ---------- Abspielknopf ---------- */

/* Die ganze Fläche ist der Knopf (inset 0), sichtbar ist nur die Tafel. */
.video-embed__play {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: grid;
	place-items: center;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: .75rem;
	border: 0;
	border-radius: inherit;
	background: transparent;
	color: var(--c-white);
	font: inherit;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
}

.video-embed__plate {
	display: inline-flex;
	align-items: stretch;
	max-width: 100%;
	min-height: 3.25rem;
	border-radius: var(--r-control);
	overflow: hidden;
}

.video-embed__go {
	display: grid;
	flex: none;
	place-items: center;
	width: 3.25rem;
	background: var(--c-teal-ink);
	color: var(--c-white);
	transition: background-color var(--dur-1) var(--ease-cut);
}

.video-embed__go svg {
	width: 18px;
	height: 18px;
	margin-inline-start: 2px;
	fill: currentColor;
}

.video-embed__label {
	display: flex;
	align-items: center;
	min-width: 0;
	padding: .5rem 1.25rem;
	background: var(--c-teal);
	color: var(--c-white);
	font: 650 1.0625rem/1.2 var(--font-display);
	font-stretch: 100%;
	text-align: start;
	transition: background-color var(--dur-1) var(--ease-cut);
}

.video-embed__play:hover .video-embed__label {
	background: var(--c-teal-ink);
}

.video-embed__play:hover .video-embed__go {
	background: var(--c-teal-press);
}

/* ABWEICHUNG von 6.3 („mittige Tafel“) im Hochformat (Befund Runde 3, Team
   medien): Shorts-Vorschaubilder tragen Gesichter und Interviewer im
   mittleren Drittel, oben die eingeblendete Frage. Mittig verdeckte die Tafel
   genau die Gesichter. Unten stehen Oberkörper, Mikrofon oder Schwarzfläche.
   Die ganze Fläche bleibt der Knopf, nur die sichtbare Tafel sitzt unten. */
.video-embed--vertical .video-embed__play {
	place-items: end center;
	padding-bottom: 2rem;
}

/*
 * Fokus: Der Knopf liegt über einem beliebig hellen oder dunklen Poster, und
 * ein umgebender Scroll- oder Reel-Container (overflow: hidden) würde einen
 * äußeren Ring abschneiden. Der Ring liegt deshalb innen auf einem eigenen
 * Studio-Band: Weiß auf #0D2427 16,17:1, das Band trennt ihn von jedem Poster.
 * Nach demselben Muster wie .reel__play (43-reel.css).
 */
.video-embed__play:focus-visible {
	outline: 2px solid var(--c-white);
	outline-offset: -6px;
	box-shadow: inset 0 0 0 6px var(--c-studio);
}

/* 375 px: Abspieltafel 48 px hoch (6.3). */
@media (max-width: 47.99rem) {
	.video-embed__plate {
		min-height: 3rem;
	}

	/* Befund hero-poster-abspieltafel: Auf dem rund 190 px hohen Querformat-
	   Poster lag die 48 px hohe Tafel mittig über Kinn und Hals des Sprechers.
	   Unten links verdeckt sie kein Gesicht; die ganze Fläche bleibt der Knopf.
	   ABWEICHUNG von 6.3 („mittige Tafel“) nur unter 48rem und nur im
	   Querformat: Ein Hochkant-Poster ist hoch genug für die Mitte. */
	.video-embed--horizontal .video-embed__play {
		place-items: end start;
	}

	.video-embed__go {
		width: 3rem;
	}

	.video-embed__label {
		padding-inline: 1rem;
		font-size: 1rem;
	}
}

/* ---------- Rahmen aus output „frame“ ---------- */

/* Hochkant im Fließtext (Artikel, nackte YouTube-Shorts-URL): höchstens
   22rem breit, linksbündig. Sonst wäre ein 9:16-Video in einer 44rem-Spalte
   über 1.200 px hoch. */
.video-embed-frame--vertical {
	width: min(100%, 22rem);
}

/* Bildunterschrift vor dem Zwei-Klick-Hinweis: Inhalt in Textfarbe, der
   Hinweis bleibt in --text-soft (.frame__note). */
.video-embed__caption {
	display: block;
	margin-bottom: .25rem;
	color: var(--text);
}

/* ---------- Druck ---------- */

@media print {
	.video-embed__play {
		display: none;
	}
}

/* ===== 43-reel.css ===== */
/* =========================================================================
   43-reel.css – Reel: Hochkant-Video 9:16 (Spezifikation 5.9, 6.12)
   Besitzer: Team B2. Markup: template-parts/components/reel.php,
   Verhalten: assets/js/src/22-reels.js.

   Der Bildschirm ist immer eine Studio-Fläche. Er trägt deshalb im Markup
   .theme-studio, damit Fokus, Bauchbinde und Segmentfarben unabhängig vom
   Sektionsgrund (white, mist, deep, teal) die dunklen Werte aus 2.1 lesen.
   Rohfarben stehen nur dort, wo 5.9 sie ausdrücklich nennt; sie liegen als
   lokale Variablen mit Präfix --reel- vorn.
   ========================================================================= */

.reel {
	--reel-osd-bg: rgb(13 36 39 / 88%);   /* 5.9: OSD- und Zitat-Tafel, Weiß darauf ≥ 11,27:1 */
	--reel-mark: rgb(255 255 255 / 55%);  /* 5.9: Innenmarken */
	--reel-safe: rgb(255 255 255 / 16%);  /* 5.9: Title-Safe-Linie im Platzhalter */
	--reel-mark-len: 14px;
	--reel-mark-w: 1.5px;
	--reel-mark-off: 10px;
	--reel-pad: 1.25rem;                  /* Tafeln liegen innerhalb der Innenmarken (10 + 14 px) */
	--reel-plate: 1;                      /* Abspieltafel, Zitat und Bauchbinde sichtbar; 0 während das Video läuft */
	position: relative;
	width: 100%;
	/* FIX: Flex- und Grid-Kinder sind sonst mindestens so breit wie ihr Inhalt
	   und sprengen bei 320 px den Slider bzw. die Spalte. */
	min-width: 0;
	margin: 0;
}

/* ---------- Bildschirm ---------- */

.reel__screen {
	position: relative;
	/* Das 9:16-Format hängt am Bildschirm selbst. Alle Kinder liegen absolut;
	   die Breite muss deshalb von außen kommen (Slide, Spalte), sonst wäre der
	   Bildschirm 0 Pixel breit (bekannter Fehler des alten video-embed--vertical). */
	aspect-ratio: 9 / 16;
	overflow: hidden;
	border-radius: var(--r-reel);
	background: var(--c-studio-2);
	color: var(--text);
	/* Safari schneidet Videos an abgerundeten Ecken nur mit eigenem Stapelkontext sauber ab. */
	isolation: isolate;
}

.reel__media {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* FIX: kein weißer Streifen oben/unten, egal ob Poster fehlt oder anders geschnitten ist. */
	background: var(--c-studio-2);
}

/* Reel-Rahmen um die Zwei-Klick-Einbettung (video_gallery 9:16, text_media):
   Die Einbettung füllt den Bildschirm randlos, auch nachdem 20-video-embeds.js
   das Poster durch das Iframe ersetzt hat. */
.reel__screen > .video-embed {
	position: absolute;
	inset: 0;
	width: 100%;
	max-width: none;
	height: 100%;
	margin: 0;
	aspect-ratio: auto;
	border-radius: 0;
}

/* Innenmarken: Sucherrahmen nach innen gelegt, weil Reels im Slider dicht
   an dicht stehen und außen kein Platz für Marken bleibt (5.4, 5.9). */
.reel__screen::after {
	content: "";
	position: absolute;
	inset: var(--reel-mark-off);
	z-index: 1;
	pointer-events: none;
	background:
		linear-gradient(var(--reel-mark) 0 0) top left / var(--reel-mark-len) var(--reel-mark-w),
		linear-gradient(var(--reel-mark) 0 0) top left / var(--reel-mark-w) var(--reel-mark-len),
		linear-gradient(var(--reel-mark) 0 0) top right / var(--reel-mark-len) var(--reel-mark-w),
		linear-gradient(var(--reel-mark) 0 0) top right / var(--reel-mark-w) var(--reel-mark-len),
		linear-gradient(var(--reel-mark) 0 0) bottom left / var(--reel-mark-len) var(--reel-mark-w),
		linear-gradient(var(--reel-mark) 0 0) bottom left / var(--reel-mark-w) var(--reel-mark-len),
		linear-gradient(var(--reel-mark) 0 0) bottom right / var(--reel-mark-len) var(--reel-mark-w),
		linear-gradient(var(--reel-mark) 0 0) bottom right / var(--reel-mark-w) var(--reel-mark-len);
	background-repeat: no-repeat;
}

/* ---------- OSD-Tafeln: Kennzahl, Plattform, Timecode ---------- */

.reel__osd {
	position: absolute;
	top: var(--reel-pad);
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	min-height: 1.75rem;                  /* 28 px, wächst mit dem Textzoom */
	padding: .25rem .5rem;
	border-radius: var(--r-plate);
	background: var(--reel-osd-bg);
	color: var(--c-white);
	/* Echte Daten (Aufrufe, Laufzeit): Plex Mono nach Regel 3 */
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	pointer-events: none;
}

/* FIX (übernommen, liegt in 02-base.css): [hidden] gewinnt mit !important gegen
   jedes display. Timecode, Tonknopf, Symbole und .reel__bottom setzen display
   und werden von 22-reels.js per hidden geschaltet. */

.reel__osd svg {
	flex: none;
	width: 14px;
	height: 14px;
}

.reel__metric {
	inset-inline-start: var(--reel-pad);
	/* Platz für die Plattform-Tafel rechts lassen; lange Kennzahlen brechen um statt abzuschneiden. */
	max-width: calc(100% - 2 * var(--reel-pad) - 2.25rem);
}

.reel__platform {
	inset-inline-end: var(--reel-pad);
	justify-content: center;
	width: 1.75rem;
	padding: 0;
}

.reel__platform svg {
	width: 16px;
	height: 16px;
}

.reel__timecode {
	top: auto;
	/* auf Mitte des 44-px-Tonknopfs ausgerichtet */
	bottom: calc(var(--reel-pad) + .5rem);
	inset-inline-start: var(--reel-pad);
	font-variant-numeric: tabular-nums;
}

/* Schmale Reels (320 px: 230 px breit) rücken die Tafeln näher an die
   Innenmarken, damit „2,1 Mio. Aufrufe“ neben der Plattform in eine Zeile
   passt. 16 px liegen noch außerhalb der Marken (10 px + 1,5 px Stärke).
   Die Regel steht nach .reel__osd, damit das schmalere Padding gewinnt. */
.reel { container-type: inline-size; }

@container (max-width: 15.99rem) {
	.reel__screen { --reel-pad: 1rem; }
	.reel__metric { padding-inline: .375rem; }
}

/* ---------- Untertitel-Zitat und Bauchbinde ---------- */

.reel__bottom {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .75rem;
	padding: 0 var(--reel-pad) var(--reel-pad);
	/* Klicks gehen an die Abspielfläche darunter */
	pointer-events: none;
	/* Läuft das Video (auch als stumme Vorschau), weicht die Tafel optisch dem
	   Bild, Timecode und Tonknopf. Nur beim Abspielen durch den Nutzer setzt
	   22-reels.js zusätzlich hidden (5.9); in der Vorschau bleibt der Text so
	   für Screenreader erreichbar. */
	opacity: var(--reel-plate);
	transition: opacity var(--dur-1) var(--ease-cut);
}

.reel__quote {
	align-self: stretch;
	margin: 0;
	font: 700 .9375rem/1.55 var(--font-text);
	/* 5.9: Das Zitat steht wie ein eingebrannter Untertitel mittig im Bild.
	   Einzige zentrierte Textstelle des Bausteins, Begründung Spez. 5.9. */
	text-align: center;
	/* 5.9: höchstens drei Zeilen, der volle Text steht im Transkript */
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
	overflow-wrap: anywhere;
}

/* Die Tafel selbst (Grund 88 % Studio, Untertitelgelb) liefert
   .caption-plate--oton aus dem Fundament. Gelb steht hier nur auf Studio. */

/* Platzhalter: Title-Safe-Linie bei 10 % Einzug, Untertitel innerhalb davon */
.reel__screen--safe::before {
	content: "";
	position: absolute;
	inset: 10%;
	z-index: 1;
	border: 1px solid var(--reel-safe);
	pointer-events: none;
}

.reel__bottom--safe {
	bottom: calc(10% + .75rem);
	padding-inline: calc(10% + .75rem);
	padding-bottom: 0;
}

/* ---------- Abspielfläche ---------- */

.reel__play {
	position: absolute;
	inset: 0;
	z-index: 3;
	/* Raster statt Flex: Die Zeile ist so hoch wie die Beschriftung, und das
	   Segment streckt sich mit, auch wenn „Video abspielen“ bei 320 px umbricht. */
	display: grid;
	grid-auto-flow: column;
	place-content: center;
	margin: 0;
	padding: .75rem;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--text);
	font: inherit;
	text-decoration: none;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
}

/* Tafel aus Segment (Dreieck) und Beschriftung, flach wie ein Button (4.5) */
.reel__play-go {
	display: grid;
	flex: none;
	place-items: center;
	width: 3rem;
	min-height: 3rem;
	border-radius: var(--r-control) 0 0 var(--r-control);
	/* Die Segmentfarben werden erst hier gelesen, also innerhalb von .theme-studio.
	   Als Variable auf .reel stünden sie noch auf den Werten des Sektionsgrunds. */
	background: var(--reel-go-bg, var(--btn-go-bg));
	color: var(--btn-go-fg);
	opacity: var(--reel-plate);
	transition: opacity var(--dur-1) var(--ease-cut);
}

.reel__play-go svg {
	width: 18px;
	height: 18px;
	margin-inline-start: 2px;
	fill: currentColor;
}

.reel__play-label {
	display: flex;
	align-items: center;
	min-height: 3rem;
	padding: .5rem .875rem;
	border-radius: 0 var(--r-control) var(--r-control) 0;
	background: var(--reel-label-bg, var(--reel-osd-bg));
	color: var(--c-white);
	font: 650 .9375rem/1.2 var(--font-display);
	font-stretch: 100%;
	opacity: var(--reel-plate);
	transition: opacity var(--dur-1) var(--ease-cut);
}

@media (hover: hover) {
	.reel__play:hover {
		--reel-go-bg: var(--btn-go-bg-h);
		--reel-label-bg: var(--c-studio);
	}
}

/*
 * Fokus: Das Poster ist beliebig hell oder dunkel. Ein einfarbiger Ring hätte
 * darauf keinen gesicherten Kontrast. Deshalb liegt innen ein Studio-Band
 * (6 px) und darauf der Ring in --focus: #2FAFAF auf #0D2427 = 6,06:1.
 * Der Ring umschließt das ganze Reel, weil die Tafel beim Abspielen verschwindet.
 */
.reel__play:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: -5px;
	box-shadow: inset 0 0 0 6px var(--c-studio);
}

/* Während das Video läuft, verschwindet die Tafel; die Fläche bleibt zum Anhalten klickbar. */
.reel.is-playing { --reel-plate: 0; }

/* ---------- Tonknopf ---------- */

.reel__sound {
	position: absolute;
	inset-inline-end: var(--reel-pad);
	bottom: var(--reel-pad);
	z-index: 4;
	display: grid;
	place-items: center;
	width: 2.75rem;                       /* 44 px Zielgröße */
	height: 2.75rem;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: var(--r-control);
	background: var(--reel-osd-bg);
	color: var(--c-white);
	cursor: pointer;
}

.reel__sound-icon {
	display: grid;
	place-items: center;
}

.reel__sound svg {
	width: 20px;
	height: 20px;
}

/* Ton an: Segmentfarbe wie im hellen Button auf Studio (#2FAFAF / #0D2427 = 6,06:1) */
.reel__sound[aria-pressed="true"] {
	background: var(--btn-go-bg);
	color: var(--btn-go-fg);
}

@media (hover: hover) {
	.reel__sound:hover {
		background: var(--c-studio);
		color: var(--c-white);
	}
}

/* Ring auf eigenem Studio-Band, damit er auf jedem Poster ≥ 3:1 hat */
.reel__sound:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
	box-shadow: 0 0 0 4px var(--c-studio);
}

/* ---------- Unter dem Bildschirm: Titel, Kennzahl, Hinweis (Reel um Einbettung) ---------- */

.reel__cap {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .375rem;
	margin-top: .75rem;
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.5 var(--font-text);
}

.reel__meta,
.reel__note {
	display: block;
	max-width: 60ch;
}

.reel__note a { color: inherit; }

/* ---------- Transkript (unter dem Bildschirm, auf dem Sektionsgrund) ---------- */

.reel__transcript {
	margin-top: .375rem;
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.55 var(--font-text);
}

.reel__transcript-toggle {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	min-height: 2.75rem;                  /* 6.12: Zielhöhe 44 px */
	color: var(--accent-text);
	font: 600 var(--fs-xs)/1.3 var(--font-text);
	list-style: none;
	cursor: pointer;
}

.reel__transcript-toggle::-webkit-details-marker { display: none; }

.reel__transcript-toggle svg {
	flex: none;
	width: 16px;
	height: 16px;
	transition: transform var(--dur-1) var(--ease-cut);
}

@media (hover: hover) {
	.reel__transcript-toggle:hover {
		text-decoration: underline;
		text-decoration-thickness: 1px;
		text-underline-offset: .2em;
	}
}

.reel__transcript[open] > summary svg { transform: rotate(180deg); }

.reel__transcript-text {
	max-width: 60ch;
	padding-bottom: .5rem;
	overflow-wrap: anywhere;
}

.reel__transcript-text > p { margin: 0 0 .75em; }
.reel__transcript-text > p:last-child { margin-bottom: 0; }

/* Druck: Abspielfläche und Tonknopf blendet 99-print.css aus. */

/* ===== 44-slider.css ===== */
/* =========================================================================
   44-slider.css – Slider mit Scroll-Snap und Segmentleiste (Spezifikation 6.12)
   Besitzer: Team B2. Genutzt von video_testimonials, video_gallery (9:16),
   testimonials (layout slider) und single-smm_case. Verhalten: 23-sliders.js.

   Markup-Vertrag:
     .slider[data-slider][data-slider-center]      (--slider-w optional überschreiben)
       .slider__viewport > .slider__track > .slider__slide …
       .slider__nav                                 (ohne JS verborgen, JS blendet aus, wenn nichts zu blättern ist)
         .slider__segments[data-slider-dots]        (JS erzeugt button.slider__seg)
         button.slider__arrow[data-slider-prev]
         button.slider__arrow[data-slider-next]
   ========================================================================= */

.slider {
	/* Slide-Breite. Sektionen können sie am .slider überschreiben
	   (testimonials: 22rem laut 6.11). */
	--slider-w: min(22rem, 82vw);
	/* Reels: 72vw bei 375 px (6.12), gedeckelt, damit große Telefone im
	   Querformat keine 1000 px hohen Reels bekommen. */
	--slider-reel-w: min(72vw, 18rem);
	--slider-gap: 1rem;
	--slider-snap: start;
	/* Luft für Fokusringe am Rand des Scrollbereichs: Der Basisring aus
	   02-base.css (2px Linie, 3px Abstand) ragt 5 px über das Element hinaus,
	   etwa beim Transkript-Knopf an der linken und unteren Slide-Kante. 6 px
	   lassen ihn ganz stehen und liegen weiter im 18-px-Gutter. Oben und unten
	   gilt sie immer, seitlich nur bei Tastaturfokus in einem Slide (siehe
	   .slider__viewport). */
	--slider-ring: 6px;
	position: relative;
	/* FIX: Als Grid- oder Flex-Kind darf der Slider nie breiter werden als seine Spalte. */
	min-width: 0;
}

.slider--reels { --slider-w: var(--slider-reel-w); }

/* data-slider-center: Unter 48rem rastet der Slide mittig ein (6.12, 375 px).
   Der erste Slide bleibt trotzdem bündig, weil der Browser die Einrastposition
   auf den Scrollanfang begrenzt. */
@media (max-width: 47.99rem) {
	.slider[data-slider-center] { --slider-snap: center; }
}

@media (min-width: 48rem) {
	.slider { --slider-reel-w: 16rem; }  /* Tablet (6.12) */
}

@media (min-width: 62rem) {
	.slider { --slider-reel-w: clamp(15rem, 20vw, 18rem); }
}

.slider__viewport {
	overflow-x: auto;
	overflow-y: hidden;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	/* Die Scrollfläche bleibt im Container (kein Anschnitt bis an den
	   Viewportrand, keine Kantenmaske).
	   FIX (Sichtprüfung „slider-kantenstreifen“): Der Ring-Überstand steht nur
	   noch oben und unten. Seitlich endet der Scrollbereich exakt an der
	   Containerkante (Spez. 1 „Medien bleiben im Container“, 6.12 „erster
	   Slide an der Containerkante“). Vorher ragte er an beiden Seiten 6 px in
	   den Gutter: Bei 1440 px stand dort ein abgerundeter Streifen des fünften
	   Reels (am Scrollende links des ersten), bei 375 px endete der Anschnitt
	   weder an der Gutterkante noch am Viewportrand. Nur an der Endseite
	   zurückzunehmen reicht nicht, dann bleibt der Streifen am Scrollende
	   links, und die mittige Einrastposition wird mobil asymmetrisch. */
	margin-block: calc(var(--slider-ring) * -1);
	padding-block: var(--slider-ring);
	margin-inline: 0;
	padding-inline: 0;
	scroll-padding-inline: 0;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

/*
 * Fokusringe an der Slide-Kante (Transkript-summary, Hinweis-Link unter einem
 * Reel um die Einbettung): Der Basisring aus 02-base.css ragt 5 px über das
 * Element hinaus und würde an der Containerkante angeschnitten (WCAG 2.4.7).
 * Die seitliche Luft kommt deshalb zurück, solange ein Tastaturfokus in einem
 * Slide steht. Margin −6 px und Padding +6 px heben sich auf: Die Slides
 * bewegen sich nicht, scrollLeft, Einrastpunkte und die Zielrechnung in
 * 23-sliders.js (liest scroll-padding) bleiben gleich. Ein 6-px-Streifen des
 * Nachbarn ist nur in diesem Zustand sichtbar, der Ring hat Vorrang.
 * Ohne :has() bleibt es beim angeschnittenen Ring, der Inhalt bleibt bedienbar.
 * :has(:focus-visible) trifft nur Nachkommen, also nie den Fokus auf dem
 * Scrollbereich selbst; Spezifität eine Klasse plus ein Zustand (8.5).
 */
.slider__viewport:has(:focus-visible) {
	margin-inline: calc(var(--slider-ring) * -1);
	padding-inline: var(--slider-ring);
	scroll-padding-inline: var(--slider-ring);
}

.slider__viewport::-webkit-scrollbar { display: none; }

/* Wird der Scrollbereich selbst fokussierbar (nur ohne bedienbare Inhalte, setzt JS), braucht er einen Ring. */
.slider__viewport:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 0;
}

.slider__track {
	display: flex;
	align-items: flex-start;              /* ein geöffnetes Transkript streckt die Nachbarn nicht */
	gap: var(--slider-gap);
	width: max-content;
	margin: 0;
	padding: 0;
	list-style: none;
}

.slider__slide {
	flex: none;
	/* Feste Breite ist Pflicht: Reels haben nur absolut liegende Kinder und
	   wären als inhaltsbreite Slides 0 Pixel breit. */
	width: var(--slider-w);
	min-width: 0;
	scroll-snap-align: var(--slider-snap);
}

/* Reels in Slidern, deren Markup kein .slider--reels trägt (z. B. single-smm_case). */
.slider__slide:has(> .reel) { width: var(--slider-reel-w); }

/* ---------- Navigation unter dem Slider, linksbündig ---------- */

.slider__nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin-top: 2rem;
}

/* FIX (übernommen, liegt in 02-base.css): [hidden] schlägt display: flex, so
   blendet 23-sliders.js die Leiste aus, wenn alle Slides in den Blick passen. */

/*
 * Ohne JavaScript tun Pfeile und Segmente nichts, also stehen sie gar nicht
 * erst da. Mit JavaScript steht die Leiste schon beim ersten Rendern
 * (smm-js setzt das Inline-Skript im head), damit sie beim späteren Laden
 * von app.js nichts nach unten schiebt. 23-sliders.js blendet sie nur aus,
 * wenn alle Slides in den Blick passen.
 */
/* :where() hält die Spezifität bei 0,1,0; die [hidden]-Regel bleibt unberührt. */
.slider__nav:where(html:not(.smm-js) *) { display: none; }

/* FIX: Die Regeln für das alte Markup (ul.slider__dots, .slider__btn) sind
   entfernt. Kein Template und kein Modul gibt diese Klassen noch aus; sie
   hielten nur Selektoren doppelt und mussten bei jeder Korrektur mitgezogen
   werden. */
.slider__segments {
	display: flex;
	flex: 1 1 auto;
	flex-wrap: wrap;
	column-gap: 4px;
	min-height: 24px;                     /* Platz ist reserviert, bevor JS die Segmente einsetzt */
	max-width: 32rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * FIX Trefferfläche (WCAG 2.5.8): Die sichtbare Leiste ist 3 px hoch, die
 * Schaltfläche 24 px. Mindestens 20 px breit bei 4 px Abstand ergibt 24 px
 * Mittenabstand; bei vielen Slides bricht die Leiste um statt überzulaufen.
 */
.slider__seg {
	position: relative;
	flex: 1 0 1.25rem;
	min-height: 24px;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.slider__seg::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: 50%;
	height: 3px;
	background: var(--seg-off);        /* #707677 auf Weiß 4,62:1, #869293 auf Studio 5,04:1 */
	transform: translateY(-50%);
}

/*
 * Aktueller Slide: Farbe (#101B1C bzw. Weiß) und doppelte Stärke. Die Stärke
 * ist das zweite Signal neben der Farbe (WCAG 1.4.1); auf Sektion teal
 * unterscheiden sich Weiß und #869293 nur mit 1,96:1. Sie entsteht per
 * scaleY, die Höhe selbst bleibt fest.
 */
.slider__seg[aria-current="true"]::before {
	background: var(--seg-on);
	transform: translateY(-50%) scaleY(2);
}

@media (hover: hover) {
	.slider__seg:hover::before { transform: translateY(-50%) scaleY(2); }
}

.slider__seg:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 1px;
}

/* ---------- Pfeile ---------- */

.slider__arrow {
	position: relative;                   /* Bezug für den gedimmten Rand im Endzustand (::before) */
	display: grid;
	flex: none;
	place-items: center;
	width: 3rem;                          /* 48 px, bei 375 px 44 px */
	height: 3rem;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: var(--r-control);
	background: none;
	color: var(--text);
	box-shadow: inset 0 0 0 1.5px var(--line-ui);
	cursor: pointer;
}

.slider__arrow svg {
	width: 20px;
	height: 20px;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
}

@media (hover: hover) {
	.slider__arrow:hover {
		background: var(--text);
		color: var(--bg);
		box-shadow: none;
	}
}

/* Ende erreicht. Die Regeln stehen nach :hover und übersteuern es bei
   gleicher Spezifität. Native :disabled-Knöpfe sind nicht fokussierbar und
   dürfen als Ganzes gedimmt werden (4.5). */
.slider__arrow:disabled {
	background: none;
	color: var(--text);
	box-shadow: inset 0 0 0 1.5px var(--line-ui);
	opacity: .45;
	cursor: not-allowed;
}

/* FIX: 23-sliders.js setzt aria-disabled statt disabled, damit der
   Tastaturfokus auf dem Pfeil bleibt. opacity am Element dimmte dann auch
   den Fokusring (Outline aus 02-base.css) auf 2,0 bis 2,55:1, gefordert sind
   3:1 (9.1). Deshalb werden nur Rand (::before) und Icon gedimmt; der Ring
   steht in voller --focus-Farbe (6,29 Weiß, 5,58 Kreide, 6,06 Studio,
   6,29 Sektion teal), der Pfeil sieht im Fokus weiter „nicht verfügbar“ aus. */
.slider__arrow[aria-disabled="true"] {
	background: none;
	color: var(--text);
	box-shadow: none;
	cursor: not-allowed;
}

.slider__arrow[aria-disabled="true"]::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1.5px var(--line-ui);
	opacity: .45;
	pointer-events: none;
}

.slider__arrow[aria-disabled="true"] svg {
	opacity: .45;
}

/* ---------- 375 px: Segmentleiste in voller Breite über den Pfeilen ---------- */

@media (max-width: 47.99rem) {
	.slider__segments {
		flex-basis: 100%;
		max-width: none;
	}

	.slider__arrow {
		width: 2.75rem;
		height: 2.75rem;
	}
}

/* ---------- Druck: alle Slides untereinander (die Leiste blendet 99-print.css aus) ---------- */

@media print {
	.slider__viewport { overflow: visible; }
	.slider__track { flex-wrap: wrap; width: auto; }
}

/* ===== 45-video-sections.css ===== */
/* =========================================================================
   45-video-sections.css – video_testimonials, video_gallery, smm-video-block
   (Spezifikation 6.12, 6.23). Besitzer: Team B2.

   Reel und Slider stehen in 43-reel.css und 44-slider.css, Sucherrahmen und
   Bauchbinde im Fundament (12-frame.css, 13-lower-third.css). Hier nur, was
   die Sektionen selbst anordnen. Keine eigenen Hintergründe: Weiß, Kreide,
   Studio und Teal kommen über die Tokens der Sektion.
   ========================================================================= */

/* ---------- video_testimonials ---------- */

/* Hinweis nur für angemeldete Redakteure (Platzhalter sichtbar). Besucher
   sehen Platzhalter nie; besteht die Sektion nur aus ihnen, gibt
   video_testimonials.php gar nichts aus. */
.video-testimonials__note {
	max-width: 60ch;
	margin: 1.5rem 0 0;
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.5 var(--font-text);
}

/* CTA linksbündig unter der Leiste (btn-row--center entfällt laut 4.5).
   Ersetzt das frühere Inline-Style margin-top. */
.video-testimonials__cta {
	margin-top: 2.5rem;
}

/* FIX (Sichtprüfung „sektions-cta-uneinheitlich“): Sektions-CTAs sind
   einheitlich btn--lg btn--block (Markup). Unter 48rem steht der Button in
   voller Breite, ab 48rem in natürlicher Breite – derselbe Umschaltpunkt wie
   hero, channel_proof und cta_band. :where hält die Spezifität bei einer
   Klasse; Label und Segment bleiben Sache von 10-buttons.css. */
@media (min-width: 48rem) {
	.video-testimonials__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* Befund sektions-cta-dichte-ausrichtung: Schließt ein Sektions-CTA eine
   vollbreite Reihe ab (pain_points, channel_proof, services, process,
   comparison, video_testimonials, cases), steht er ab 62rem rechtsbündig an
   der Containerkante. Vorher sprang der Button auf Seiten wie
   kundenstimmen-video von Sektion zu Sektion zwischen rechts und links.
   CTAs in einer Textspalte (hero, text_media, cta_band) bleiben an deren
   Textkante. ABWEICHUNG von 6.12 (dort „linksbündig“), Regel in 4.5. */
@media (min-width: 62rem) {
	.video-testimonials__cta {
		justify-content: flex-end;
	}
}

/* ---------- video_gallery: 16:9-Raster ---------- */

.video-gallery__grid {
	display: grid;
	/* FIX: minmax(0, 1fr) statt 1fr – ein Poster mit großer Eigenbreite
	   sprengt sonst die Spalte und erzeugt bei 320 px horizontalen Überlauf. */
	grid-template-columns: minmax(0, 1fr);
	align-items: start;
	/* Spaltenabstand größer als zweimal der Markenversatz (10 px), damit sich
	   die Rahmenmarken benachbarter Videos nie berühren. */
	gap: 3rem clamp(2rem, 4vw, 3rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 48rem) {
	.video-gallery__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* Ungerade Anzahl: das erste Video über beide Spalten (9.9, kein leeres Feld). */
	.video-gallery__item--wide {
		grid-column: 1 / -1;
	}
}

.video-gallery__item {
	min-width: 0;
}

/* Kennzahl in der Hinweiszeile des Rahmens: eigene Zeile vor dem
   Datenschutzhinweis. Schriftgrad und Farbe (Schibsted 14 px, --text-soft)
   erbt sie von .frame__note. */
.video-gallery__meta {
	display: block;
}

.video-gallery__meta:not(:last-child) {
	margin-bottom: .25rem;
}

/* ---------- smm-video-block im Artikel ---------- */

/* Abstand im Fließtext; die Marken liegen 10 px außerhalb und brauchen Luft. */
.video-block {
	margin-block: var(--sp-7);
}

/* Hochkant in der 44rem-Spalte: so schmal wie ein Reel statt 1200 px hoch. */
.video-block--vertical {
	width: min(100%, 22rem);
}

/* ===== 50-pain-points.css ===== */
/* =========================================================================
   50 pain_points: Probleme mit Brückensatz (Besitz: Team C1, Spez. 6.6)

   Keine Karten, keine Icon-Kacheln, keine Nummern. Die Probleme stehen als
   Registerzeilen rechts neben dem klebenden Sektionskopf. Einziges
   Signaturelement ist die Untertitel-Tafel des Brückensatzes (5.1).
   Alle Farben kommen aus den semantischen Tokens, dadurch funktionieren
   white, mist, deep und teal ohne eigene Varianten.
   ========================================================================= */

/* FIX: Spalten mit minmax(0, …) statt 1fr. Ein langes Wort oder ein breites
   Kind kann eine 1fr-Spalte sonst über ihre Breite hinaus aufdrücken, und die
   Seite schiebt sich auf dem Handy seitlich. */
.pain__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
}

/* ---------- Zeilen ---------- */

/* list-style-type "" statt none: Safari/VoiceOver nimmt einer Liste mit
   list-style none die Listen-Semantik. role="list" im Markup sichert das
   zusätzlich ab. */
.problems {
	list-style-type: "";
	margin: 0;
	padding: 0;
}

.problem {
	/* Titelgröße als lokale Variable, weil das Symbol daran ausgerichtet wird. */
	--problem-fs: clamp(1.25rem, 1rem + .9vw, 1.75rem);
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	row-gap: .625rem;
	padding-block: 1.5rem;
	border-top: 1px solid var(--line);
}

/* Die erste Zeile hat keine Linie, das Padding bleibt (6.6). :where hält
   die Spezifität bei einer Klasse, damit das Raster ab 62rem die Linie
   zurückgeben kann. */
.problem:where(:first-child) {
	border-top: 0;
}

.problem__icon {
	display: block;
	width: 24px;
	height: 24px;
	color: var(--accent-text);
}

/* smm_icon gibt das SVG ohne width/height aus, die Basisregel setzt nur
   max-width. Ohne feste Größe wäre es so breit wie die Spalte. */
.problem__svg {
	width: 24px;
	height: 24px;
}

.problem__title {
	margin: 0;
	font: 700 var(--problem-fs)/1.2 var(--font-display);
	font-stretch: 100%;
	letter-spacing: normal;
	color: var(--text);
}

.problem__text {
	max-width: 58ch;
	margin: 0;
	font-size: var(--fs-body);
	line-height: 1.6;
	color: var(--text-soft);
}

/* Ab 30rem steht das Symbol links neben Titel und Text. Darunter (375 px)
   steht es über dem Titel, damit der Text die ganze Breite behält. */
@media (min-width: 30rem) {
	.problem {
		grid-template-columns: [icon] 2.5rem [body] minmax(0, 1fr);
		padding-block: 2rem;
	}

	/* Liste ganz ohne Symbole: Beide Namen liegen auf derselben Linie, Titel
	   und Text beginnen ganz links, ohne leere Symbolspalte. Fehlt das Symbol
	   nur einzelnen Zeilen, bleibt die Spalte stehen (gemeinsame Titelkante).
	   :where hält die Spezifität bei einer Klasse, die Reihenfolge entscheidet. */
	.problems--bare > :where(.problem) {
		grid-template-columns: [icon body] minmax(0, 1fr);
	}

	.problem__icon {
		grid-column: icon;
		grid-row: 1 / span 2;
		/* Mittig zur ersten Titelzeile (Zeilenhöhe 1.2 × Titelgröße). */
		margin-top: calc((1.2 * var(--problem-fs) - 24px) / 2);
	}

	.problem__title,
	.problem__text {
		grid-column: body;
	}
}

/* ABWEICHUNG von 6.6 (Kopf links als klebende Randspalte, Liste rechts):
   Art-Director-Befund „gleiches Zwei-Spalten-Schema auf jeder Sektion“.
   pain_points stand auf sieben Seiten direkt neben text_media, beide mit
   Kopf links und Text rechts. Jetzt: Kopf oben (stack), darunter ab 62rem
   ein Befund-Raster in zwei Spalten. Der Brückensatz schließt das Raster
   ab: Bei ungerader Anzahl steht er in der freien Zelle neben dem letzten
   Problem (.pain__close--cell), bei gerader als Zeile darunter.
   Technik: Kopf, Liste und Schluss liegen im selben Raster. Die Liste
   belegt ab Reihe 2 so viele Reihen, wie sie Paare hat (problems--rows-N),
   und gibt ihre Spalten und Reihen per subgrid an die Zeilen weiter. Der
   Schluss liegt in der letzten Reihe über der freien Zelle der Liste
   (pain__close--at-N). Ohne subgrid bleibt die Liste untereinander. Ohne
   Kopf bleibt Reihe 1 leer und null hoch (kein row-gap im Raster). */
@supports (grid-template-rows: subgrid) {
	@media (min-width: 62rem) {
		.pain__inner--grid {
			grid-template-columns: repeat(2, minmax(0, 1fr));
			column-gap: clamp(2.5rem, 6vw, 6rem);
		}

		.pain__inner--grid > * {
			grid-column: 1 / -1;
		}

		.problems--rows-1,
		.problems--rows-2,
		.problems--rows-3,
		.problems--rows-4,
		.problems--rows-5,
		.problems--rows-6,
		.problems--rows-7,
		.problems--rows-8 {
			display: grid;
			grid-template-columns: subgrid;
			grid-template-rows: subgrid;
		}

		.problems--rows-1 { grid-row: 2 / span 1; }
		.problems--rows-2 { grid-row: 2 / span 2; }
		.problems--rows-3 { grid-row: 2 / span 3; }
		.problems--rows-4 { grid-row: 2 / span 4; }
		.problems--rows-5 { grid-row: 2 / span 5; }
		.problems--rows-6 { grid-row: 2 / span 6; }
		.problems--rows-7 { grid-row: 2 / span 7; }
		.problems--rows-8 { grid-row: 2 / span 8; }

		/* Jede Zelle beginnt unter einer Linie, auch die beiden ersten: Das
		   Raster liest sich als Paare, nicht als Liste mit fehlender Kopflinie.
		   Die Zelle ist so hoch wie ihre Reihe; start hält Titel und Text
		   zusammen, statt die Differenz zwischen sie zu verteilen. */
		.pain__inner--grid :where(.problem) {
			align-content: start;
			border-top: 1px solid var(--line);
			padding-block: 1.75rem 2.75rem;
		}

		/* Der Titel steht als Befund über dem ganzen Raster: breiter als die
		   22ch der übrigen Sektionsköpfe (zwei Zeilen statt drei bei 1440 px),
		   das Intro im Maß des langen Leads (46ch wie section__header--lead). */
		.pain__inner--grid :where(.section__title) {
			max-width: 26ch;
		}

		.pain__inner--grid :where(.section__intro) {
			max-width: 46ch;
		}

		.pain__close--at-2 { grid-row: 2; }
		.pain__close--at-3 { grid-row: 3; }
		.pain__close--at-4 { grid-row: 4; }
		.pain__close--at-5 { grid-row: 5; }
		.pain__close--at-6 { grid-row: 6; }
		.pain__close--at-7 { grid-row: 7; }
		.pain__close--at-8 { grid-row: 8; }
		.pain__close--at-9 { grid-row: 9; }
	}
}

/* ---------- Brückensatz und Button ---------- */

.pain__close {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 2rem;
	margin-top: clamp(3rem, 6vw, 5rem);
}

@media (min-width: 62rem) {
	.pain__close {
		grid-template-columns: minmax(0, 1fr) auto;
		column-gap: clamp(2rem, 6vw, 6rem);
		align-items: end;
	}

	/* Nur Button, kein Brückensatz: Er bleibt links (keine zentrierte
	   oder rechts verwaiste Button-Reihe). */
	.pain__close--cta {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Schluss in der freien Zelle des Befund-Rasters (ungerade Anzahl): Vorlauf,
   Tafel und Button untereinander, oben bündig mit dem Titel des Problems
   daneben. Die Linie darüber fehlt bewusst: Die Zelle ist die Antwort, kein
   weiterer Befund. Nur innerhalb des Rasters (subgrid, ab 62rem). */
@supports (grid-template-rows: subgrid) {
	@media (min-width: 62rem) {
		/* Die halbe Breite trägt die volle Tafelgröße nicht: Bei 992 px lief
		   eine Kernaussage von 85 Zeichen über vier Tafelzeilen. Eine lange
		   Brücke (pain__bridge--long) setzt ihre Größe am Absatz selbst. */
		.pain__close--cell {
			--fs-bridge: clamp(1.25rem, .6rem + 1.5vw, 1.875rem);
			grid-column: 2;
			grid-template-columns: minmax(0, 1fr);
			align-content: start;
			align-items: start;
			row-gap: 1.75rem;
			margin-top: 0;
			padding-block: 1.75rem 2.75rem;
		}
	}
}

/* Untertitel-Tafel (5.1). Die Tafel selbst (.caption-plate) liefert F. */
/* ABWEICHUNG: 5.1/6.6 setzen die Tafel über den ganzen Satz mit 32ch.
   Hier trägt sie nur die Kernaussage, die Sätze davor stehen als
   .pain__lead ruhig darüber (Aufteilung in pain_points.php). So wird die
   Tafel ein bis vier Zeilen hoch statt fünf bis acht. */
.pain__bridge {
	/* 36ch statt 32ch: Mit balance und der kürzeren Tafel ergibt das bei
	   1440 px zwei bis drei gleich lange Zeilen statt vier. */
	max-width: 36ch;
	margin: 0;
	/* Chrome reserviert die rechte Tafelpolsterung (.35em, clone) beim
	   Umbruch nicht. Ohne diesen Abstand ragte die Tafel bei 375 px bis zu
	   6 px über die Satzkante in den Gutter. */
	padding-inline-end: .35em;
	font: 700 var(--fs-bridge)/1.5 var(--font-display);
	font-stretch: 96%;
	color: var(--text);
	/* Gleich lange Tafelzeilen, keine Einzelwort-Tafel („dich.“). Chrome
	   balanciert bis sechs Zeilen; die Tafel hat höchstens vier. */
	text-wrap: balance;
}

/* Vorlauf vor der Kernaussage: Programmtext, keine Einblendung (Kapitel 1:
   Programm ruhig in Schibsted, Grafik nur an der Kernaussage). Eigene
   Zeile, damit die Tafel als geschlossener Untertitel darunter steht und
   ab 62rem auf der Grundlinie des Buttons endet. Farbe --text statt
   --text-soft: Vorlauf und Tafel sind ein Satzgefüge, kein Nebentext. */
.pain__lead {
	display: block;
	max-width: 46ch;
	margin-bottom: .75rem;
	font: 500 var(--fs-lead)/1.55 var(--font-text);
	font-stretch: 100%;
	/* Mehrzeiliger Fließtext: pretty statt balance (keine Waise, aber volle
	   Zeilen). Die Eigenschaft setzt der Block selbst, weil er sonst das
	   balance der Brücke erbt. */
	text-wrap: pretty;
}

/* Unter 48rem steht der Button als Block direkt unter der Brücke, und der
   Gutter ist nur 18 px breit. Der Tafelausgleich aus 06-highlight.css
   (margin-inline-start: -.35em, Tafeltext auf der Satzkante) schob die
   Tafelfläche dort 7 px in den Gutter und links vor die Button-Kante. Hier
   schließt die Fläche deshalb bündig mit Vorlauf und Button ab. Ab 48rem
   gilt der Ausgleich wieder, der Gutter trägt ihn. :where hält die
   Spezifität bei einer Klasse, die Reihenfolge im Build (50 nach 06)
   entscheidet. */
@media (max-width: 47.99rem) {
	.pain__bridge :where(.caption-plate) {
		margin-inline-start: 0;
	}
}

/* Neben der 34-px-Tafel wirkt 19 px am Desktop zu klein. */
@media (min-width: 62rem) {
	.pain__lead {
		font-size: 1.3125rem;
	}
}

/* Lange Kernaussage (ab 90 Zeichen, Klasse aus pain_points.php): kleinere
   Tafelschrift, breiteres Maß. Ziel: auch bei 320 px höchstens vier
   Tafelzeilen (18 px bei 320, 19 px bei 375, 28 px ab 1024 px). */
.pain__bridge--long {
	--fs-bridge: clamp(1.125rem, .75rem + 1.9vw, 1.75rem);
	max-width: 44ch;
}

/* FIX: Fokusring eines Links im Brückensatz (smm_allowed_inline_tags erlaubt
   <a>). --focus (Teal-Ink) hätte auf der Studio-Tafel nur 2,57:1, deshalb
   die Schriftfarbe der Tafel (mindestens 16:1 auf der Tafel).
   Der Basis-Offset von 3px reicht aber nicht: Die Tafel hat oben und unten
   nur .08em Padding (1,8 px bei 22 px), die waagerechten Striche lägen auf
   dem Sektionsgrund (weiß auf Weiß, Studio auf deep, 2,57:1 auf teal). Der
   Ring sitzt deshalb direkt am Link, und ein Schatten in Tafelfarbe
   verlängert die Tafel um .2em. So liegt der Ring auf jeder Seite vollständig
   auf der Tafel. clone zeichnet den Schatten bei einem umbrechenden Link auf
   jeder Zeile ganz. Im Kontrastmodus entfällt der Schatten, der Ring nimmt
   dort die Systemfarbe. */
.pain__bridge a:focus-visible {
	outline-color: var(--bridge-fg);
	outline-offset: 0;
	box-shadow: 0 0 0 .2em var(--bridge-bg);
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
}

/* FIX: Silbentrennung nur auf schmalen Bildschirmen (siehe 02-base.css).
   Der Brückensatz ist keine Überschrift und fällt nicht unter die
   Basisregel, steht aber in 22 px Display-Schrift auf 284 px Satzbreite.
   FIX: 22.49rem statt 29.99rem. Seit die Tafel nur die Kernaussage trägt
   und balance setzt, reicht die Zeile bei 375 px für jedes Wort; dort
   trennte die Regel ohne Not („zusätz-lich“), und ein Untertitel trennt
   nicht. Unter 360 px (284 px Satzbreite bei 320 px) bleibt sie. */
@media (max-width: 22.49rem) {
	.pain__bridge {
		-webkit-hyphens: auto;
		hyphens: auto;
		-webkit-hyphenate-limit-before: 4;
		-webkit-hyphenate-limit-after: 4;
		hyphenate-limit-chars: 8 4 4;
		overflow-wrap: break-word;
	}
}

.pain__cta {
	margin: 0;
}

/* Sektions-CTA (einheitlich für alle Sektionen): btn--lg, unter 48rem in
   voller Breite (btn--block im Markup), ab 48rem in natürlicher Breite.
   FIX: 48rem statt 30rem, derselbe Umschaltpunkt wie hero, channel_proof,
   process und cta_band; zwischen 480 und 767 px wechselte die Breite sonst
   von Sektion zu Sektion. :where hält die Spezifität bei einer Klasse, die
   Reihenfolge im Build (50 nach 10) entscheidet. */
@media (min-width: 48rem) {
	.pain__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* ---------- Bewegung (7.3, Inventar Nr. 3) ----------
   Die Listen-Einblendung der Zeilen (opacity, 8 px, 420 ms) steht zentral in
   90-motion.css an [data-reveal], nur unter html.smm-motion. Vertrag dort:
   .problem trägt deshalb selbst keine transition. */

/* ===== 51-text-media.css ===== */
/* =========================================================================
   51 text_media: Text mit Medium im Sucherrahmen (Besitz: Team C1, Spez. 6.7)

   Signaturelement ist der Sucherrahmen des Fundaments (.frame, 5.4). Diese
   Datei setzt nur Raster, Textspalte, Aufzählung und die Maße des Mediums.
   Rahmen, Marken, Bauchbinde und Reel-Rahmen gehören F bzw. B.
   ========================================================================= */

/* ---------- Raster ---------- */

/* Die Spalten kommen aus .grid-12 (FIX dort: minmax(0, 1fr) statt 1fr).
   Unter 62rem steht das Medium einspaltig nach dem Text. */
.text-media__inner {
	row-gap: var(--sp-7);
	align-items: start;
}

@media (min-width: 62rem) {
	.text-media__text {
		grid-column: 1 / span 6;
		grid-row: 1;
	}

	.text-media__media {
		grid-column: 8 / span 5;
		grid-row: 1;
	}

	/* Medium links: Die Seite wechselt über die Platzierung, nicht über
	   order. Die DOM-Reihenfolge Text vor Medium bleibt, damit Lese- und
	   Tabreihenfolge in jeder Breite übereinstimmen. :where hält die
	   Spezifität bei einer Klasse, die Reihenfolge in der Datei entscheidet. */
	.text-media--left :where(.text-media__text) {
		grid-column: 7 / span 6;
	}

	.text-media--left :where(.text-media__media) {
		grid-column: 1 / span 5;
	}
}

/* Das Medium klebt, solange der Text daneben weiterläuft. Nur bei
   ausreichender Fensterhöhe: Auf einem niedrigen Querformat-Laptop wäre ein
   hohes Porträt sonst nie ganz zu sehen. */
@media (min-width: 62rem) and (min-height: 44rem) {
	.text-media__media {
		position: sticky;
		top: calc(var(--header-h) + 2rem);
		align-self: start;
	}
}

/* Hochkant an der äußeren Rasterkante (Befund Runde 3 „Hochkant-Reels in
   text_media hängen links in der Medienspalte“): Das schmale Medium stand
   linksbündig in den Spalten 8–12, rechts davon blieb bei 1440 px ein
   136 px breiter toter Streifen bis zur Rasterkante, anders als im Hero.
   Jetzt wie im Hero (40-hero.css): Text in sieben Spalten, das Medium in
   den übrigen fünf bündig an der Außenkante, bei „Medium rechts“ an der
   rechten, bei „Medium links“ an der linken. Die Lücke zwischen Text und
   Medium ist damit auf beiden Seiten gleich. Die Seite wechselt weiter über
   die Grid-Platzierung, die DOM-Reihenfolge Text vor Medium bleibt.
   ABWEICHUNG von 6.7 (Text 1–6, Medium 8–12 bzw. 1–5 und 7–12) nur für
   Hochkant. :where hält die Spezifität bei einer bzw. zwei Klassen, damit
   die Regeln die Grundplatzierung oben über die Reihenfolge übersteuern. */
@media (min-width: 62rem) {
	.text-media--portrait :where(.text-media__text) {
		grid-column: 1 / span 7;
	}

	.text-media--portrait :where(.text-media__media) {
		grid-column: 8 / -1;
		justify-self: end;
		/* Mit justify-self schrumpft das Rasterelement auf seinen Inhalt. Der
		   9:16-Bildschirm hat keine eigene Breite (Kinder absolut), deshalb
		   braucht der Wrapper eine feste Breite, sonst wäre er 0 px breit. */
		width: 100%;
	}

	.text-media--portrait.text-media--left :where(.text-media__text) {
		grid-column: 6 / -1;
	}

	.text-media--portrait.text-media--left :where(.text-media__media) {
		grid-column: 1 / span 5;
		justify-self: start;
	}
}

/* ---------- Textspalte ---------- */

/* Ohne Medium: schmale Spalte, linksbündig an der Containerkante. Die Klasse
   .container--narrow sitzt dafür innerhalb von .container, so bleibt der
   seitliche Gutter erhalten (am Container selbst läge die Spalte mit
   margin-inline-start: 0 direkt am Viewportrand). */
.text-media__text--solo {
	margin-inline-start: 0;
}

/* Kopf über dem Text (stack): höchstens 2.5rem bis zur Prosa. Überschrift
   und Absätze sind hier ein Textblock; --head-gap (bis 4rem) ist für Köpfe
   über Rastern gedacht und riss bei 1440 px eine 64-px-Lücke zwischen Titel
   und ersten Satz. 2.5rem entspricht dem Wert aus 4.3 für 375 px.
   ABWEICHUNG von --head-gap ab 48rem. */
.text-media__text > :where(.section__header--stack) {
	margin-bottom: min(var(--head-gap), 2.5rem);
}

/* ---------- Ohne Medium: Lead über die Breite ----------
   ABWEICHUNG von 6.7 (schmale Spalte) und vom Stand der Abnahme (Kopf links
   als aside, Text rechts): Art-Director-Befund „gleiches Zwei-Spalten-
   Schema auf jeder Sektion“ und „text_media ohne Medium mit leerer Spalte“.
   Jetzt: Kopf oben, darunter ein großer Lead-Satz über die Breite (das Intro
   oder der erste Satz des Textes, Auswahl in text_media.php), danach der
   Text in einer Lesespalte. Ab 62rem steht die Aufzählung samt Button in
   den Spalten 9–12 neben dem Text (.text-media__aside), sonst folgt sie
   darunter. So bleibt neben der Lesespalte keine leere Hälfte, und die
   Sektion unterscheidet sich vom Befund-Raster in pain_points, das auf
   sieben Seiten direkt davor oder danach steht.
   Unter 62rem: alles untereinander, der Lead eine Stufe kleiner. */

.text-media__lead,
.text-media__text--intro-lead :where(.section__header > .section__intro) {
	max-width: 36ch;
	margin: 0;
	font: 500 clamp(1.3125rem, .95rem + 1.4vw, 2.125rem)/1.32 var(--font-text);
	color: var(--text);
	text-wrap: pretty;
}

/* Langer Lead (ab 120 Zeichen): eine Stufe kleiner, breiteres Maß. */
.text-media__text--long-lead > :where(.text-media__lead),
.text-media__text--long-lead :where(.section__header > .section__intro) {
	max-width: 46ch;
	font-size: clamp(1.25rem, 1rem + 1vw, 1.75rem);
	line-height: 1.38;
}

/* Intro als Lead: sitzt im Kopf, der Abstand zum Titel wie beim Kopf. */
.text-media__text--intro-lead :where(.section__header > .section__intro) {
	margin-top: 1.25rem;
}

.text-media__lead {
	margin-bottom: 2.5rem;
}

@media (min-width: 62rem) {
	.text-media__text--solo {
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--gap);
		max-width: none;
	}

	.text-media__text--solo > * {
		grid-column: 1 / -1;
	}

	.text-media__text--solo > :where(.text-media__body) {
		display: grid;
		grid-template-columns: subgrid;
		align-items: start;
	}

	.text-media__text--solo :where(.text-media__body > *) {
		grid-column: 1 / span 7;
	}

	/* Aufzählung und Button neben dem Text, oben bündig mit der ersten
	   Textzeile, an der Kante von Spalte 8 wie das Intro im split-Kopf. */
	.text-media__text--solo :where(.text-media__body > .text-media__aside) {
		grid-column: 8 / -1;
		grid-row: 1;
	}

	/* Ohne Aufzählung und Button: Lead links (1–5), Text rechts (7–12). */
	.text-media__text--lead-beside > :where(.text-media__lead) {
		grid-column: 1 / span 5;
		grid-row: 2;
		margin-bottom: 0;
	}

	.text-media__text--lead-beside > :where(.text-media__body) {
		display: block;
		grid-column: 7 / -1;
		grid-row: 2;
	}

	.text-media__lead {
		margin-bottom: 3rem;
	}

	.text-media__text--intro-lead > :where(.section__header) {
		margin-bottom: 3rem;
	}
}

/* Prosa in text_media: 17 px/1.65 in jeder Breite, schmaler als im Artikel.
   Die Regel steht nach 02-base.css und übersteuert dort die größere Stufe
   ab 48rem bei gleicher Spezifität. */
.text-media__prose {
	max-width: 60ch;
	font-size: var(--fs-body);
	line-height: 1.65;
	color: var(--text);
}

/* ---------- Aufzählung: Pixelquadrate (4.1) ---------- */

/* Die Liste selbst liefert F (.bullets in 16-lists-checks-stars.css):
   Quadrat, Einzug, gap .75rem, list-style-type "" (FIX dort gegen den
   Verlust der Listen-Semantik in Safari/VoiceOver) und die Regel für den
   Windows-Kontrastmodus. Die Kreis-Haken des alten Stands entfallen.
   Hier stehen nur die Abweichungen der Sektion. Die Klasse der Sektion statt
   .bullets, weil .bullets auch im Formular (D) und im Takeaway-Block steht
   und diese Datei im Build nach F kommt: Eine Regel an .bullets würde dort
   Abstand, Schrift und Breite mitändern (8.5, Regel 3).
   Der obere Abstand kollabiert mit dem Rand des Sektionskopfs, wenn kein
   Fließtext davor steht. */
.text-media__bullets {
	margin-top: 1.5rem;
}

.text-media__bullets > li {
	max-width: 60ch;
	font: 600 1rem/1.5 var(--font-text);
	color: var(--text);
}

.text-media__cta {
	margin-top: 2rem;
}

/* 375 px: Button in voller Breite (btn--block im Markup), ab 48rem in
   natürlicher Breite. Einheitliche Regel aller Sektions-CTAs (Befund
   sektions-cta-uneinheitlich): btn--lg, unter 48rem btn--block, derselbe
   Umschaltpunkt wie Hero, channel_proof und cta_band. :where hält die
   Spezifität bei einer Klasse. */
@media (min-width: 48rem) {
	.text-media__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* ---------- Medium ---------- */

/* Tablet und Handy: Medium unter dem Text, nicht breiter als 36rem. Die
   Rahmenmarken liegen 6 px außerhalb und damit im 18-px-Gutter. */
.text-media__media {
	min-width: 0;
	max-width: 36rem;
}

@media (min-width: 62rem) {
	.text-media__media {
		max-width: none;
	}
}

/* Hochkant (Reel oder hochformatige Videodatei): unter 62rem linksbündig
   unter dem Text, 20rem auf dem Handy, 22rem ab Tablet. Ab 62rem steht es an
   der äußeren Rasterkante (Platzierung oben unter „Raster“). */
.text-media__media--portrait {
	max-width: 20rem;
}

@media (min-width: 48rem) {
	.text-media__media--portrait {
		max-width: 22rem;
	}
}

/* Kleben mit Hochkant: Ein Reel ist bei 22rem Breite rund 39rem hoch, dazu
   Hinweiszeile und Header-Abstand. Bisher klebte es deshalb erst ab 52rem
   Fensterhöhe, darunter stand es still, und neben dem langen Text blieb ein
   Loch. Jetzt richtet sich die Breite nach der Fensterhöhe, damit Bildschirm
   samt Datenschutzhinweis ab 44rem Fensterhöhe ganz im Fenster bleiben:
   Fensterhöhe minus Kleberand (Header + 2rem) minus 7rem für die
   Hinweiszeile (.75rem Abstand, bis vier Zeilen zu je 1.3125rem) und etwa
   1rem Luft unten, davon 9/16. Bei 1440 × 900 bleibt es bei 22rem, bei
   44rem Fensterhöhe rund 17rem. Die rem-Reserve wächst mit dem Textzoom mit.
   vh zuerst als Fallback, dann svh, damit eine ein- und ausfahrende
   Browserleiste die Breite nicht springen lässt. */
@media (min-width: 62rem) and (min-height: 44rem) {
	.text-media__media--portrait {
		--text-media-reserve: 7rem;
		max-width: min(22rem, (100vh - var(--header-h) - 2rem - var(--text-media-reserve)) * 9 / 16);
		max-width: min(22rem, (100svh - var(--header-h) - 2rem - var(--text-media-reserve)) * 9 / 16);
	}
}

/* Unter 84rem Fensterbreite ist der rechte Gutter schmaler als der
   Nach-oben-Knopf samt Abstand (1.25rem + 2.75rem, 34-floating.css). Ein
   rechts klebendes Reel hätte dort das Ende der Hinweiszeile dauerhaft unter
   dem Knopf. Die Reserve wächst deshalb um die Knopfhöhe samt Abstand, das
   Medium endet über dem Knopf. Links klebt es fern vom Knopf. */
@media (min-width: 62rem) and (max-width: 83.99rem) {
	.text-media:not(.text-media--left) .text-media__media--portrait {
		--text-media-reserve: 10.5rem;
	}
}

/* Überhängende Bauchbinde: Den Platz darunter hält .frame--overlap (F).
   Reel-Rahmen und Datenschutzhinweis darunter kommen aus components/reel.php
   (B), die Breite aus --portrait oben.
   FIX aus dem alten Stand („.text-media__media .blk-video { margin-block: 0 }“
   gegen weiße Streifen im Rahmen): liegt jetzt in 12-frame.css und in der
   Ausgabe screen/frame von video-embed, hier also keine eigene Regel mehr. */

/* Aufzählung neben dem Text (ohne Medium, ab 62rem): oben bündig mit der
   ersten Textzeile statt 1.5rem darunter. Steht nach der Grundregel der
   Aufzählung und gewinnt über die Reihenfolge. */
@media (min-width: 62rem) {
	.text-media__aside > :where(.text-media__bullets) {
		margin-top: .3em;
	}
}

/* ===== 52-channel-proof.css ===== */
/* =========================================================================
   52 · channel_proof: Leitkennzahl und Kanal-Zeilen (Spezifikation 6.5)
   Besitz: Team C. Signatur der Sektion: Walzenzähler (5.7, von F).
   Markup: template-parts/sections/channel_proof.php,
           template-parts/components/channel-row.php

   Alle Farben kommen aus den semantischen Tokens. Auf deep und teal kippt
   data-theme="dark" die Werte, auf white und mist bleibt alles hell.
   Keine Karten, kein Akzentbalken, kein Hover-Lift.

   ABWEICHUNG von 6.5 (Art-Director-Verbesserung „Aufrufzähler als Plakat“):
   Die Leitkennzahl steht nicht mehr in den Spalten 1 bis 7 mit der dl
   rechts daneben, sondern füllt die ganze Containerbreite. Rechts neben
   „250 Mio.“ blieb sonst ein großer toter Raum, und die Sektion las sich wie
   eine Datentabelle statt wie ein Aufrufzähler. Die übrigen Kennzahlen stehen
   als Streifen darunter, die Kanal-Zeilen sind flacher (Kennzahlen nebenein-
   ander, Startdatum im Kopf). Die Leitkennzahl ist eine der vier lauten
   Stellen aus Kapitel 1, deshalb darf sie hier plakatgroß sein.
   ========================================================================= */

/* ---------- Leitkennzahl ---------- */

/* Container für cqi: Die Plakatgröße hängt an der Containerbreite, nicht am
   Viewport. So läuft die Zahl weder auf 320 px noch bei 200 % Zoom über. */
.proof__lead {
	container-type: inline-size;
	align-items: start;
}

.proof__lead > * {
	grid-column: 1 / -1;
}

/* Stand der Zahlen: echtes Datum, deshalb Plex Mono. */
.proof__stand {
	margin: 0;
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text-soft);
}

/* Rückfall ohne Container-Einheiten: die Stufe aus den Tokens. nowrap hält
   Zahl und Einheit in einer Zeile; die Breite stimmt über die Stufenklasse.
   Gemessen an Archivo: In der 1em hohen Walzenzeile beginnen die Ziffern
   .135em unter der Oberkante, das Komma von „35,1“ endet .016em unter der
   Unterkante. Der Rand unten hält das Komma vom Label frei (in em, damit er
   mit der Zahl skaliert). Oben bleibt der Leerraum bewusst stehen: Ein
   negativer Rand zöge das Walzenfenster über die Stand-Zeile, und während
   des Rollens lägen Ziffernteile auf dem Text. Der Leerraum ersetzt deshalb
   den Abstand unter dem Stand. */
.proof__lead-value {
	margin: 0 0 .04em;
	font: 820 var(--fs-num-lead)/.9 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums lining-nums;
	letter-spacing: -.01em;
	white-space: nowrap;
	color: var(--text);
}

/* Die Einheit spricht in der O-Ton-Stimme (schmal und schwer, 5.2). Sie
   dreht sich nicht mit, die Walze bleibt bei den Ziffern. */
.proof__lead-unit {
	font-stretch: var(--w-oton);
	font-weight: 850;
}

/* Formatfüllend: Containerbreite geteilt durch die geschätzte Breite des
   Werts in em (Stufe aus channel_proof.php, immer aufgerundet; dazu spart
   letter-spacing rund .08em). Die Obergrenze 20rem greift nur bei sehr
   kurzen Werten auf breiten Bildschirmen. */
@supports (width: 1cqi) {
	.proof__lead-value {
		font-size: min(20rem, calc(100cqi / var(--proof-fit, 4.9)));
	}
}

.proof__lead-value--fit-200 { --proof-fit: 2; }
.proof__lead-value--fit-225 { --proof-fit: 2.25; }
.proof__lead-value--fit-250 { --proof-fit: 2.5; }
.proof__lead-value--fit-275 { --proof-fit: 2.75; }
.proof__lead-value--fit-300 { --proof-fit: 3; }
.proof__lead-value--fit-325 { --proof-fit: 3.25; }
.proof__lead-value--fit-350 { --proof-fit: 3.5; }
.proof__lead-value--fit-375 { --proof-fit: 3.75; }
.proof__lead-value--fit-400 { --proof-fit: 4; }
.proof__lead-value--fit-425 { --proof-fit: 4.25; }
.proof__lead-value--fit-450 { --proof-fit: 4.5; }
.proof__lead-value--fit-475 { --proof-fit: 4.75; }
.proof__lead-value--fit-500 { --proof-fit: 5; }
.proof__lead-value--fit-550 { --proof-fit: 5.5; }
.proof__lead-value--fit-600 { --proof-fit: 6; }
.proof__lead-value--fit-650 { --proof-fit: 6.5; }
.proof__lead-value--fit-700 { --proof-fit: 7; }
.proof__lead-value--fit-800 { --proof-fit: 8; }
.proof__lead-value--fit-900 { --proof-fit: 9; }
.proof__lead-value--fit-1000 { --proof-fit: 10; }

/* Kein Zahlwert, sondern ein ganzer Satz (über 10 em): umbrechen statt
   einzeilig riesig. .odo (F) setzt selbst nowrap und muss mit. */
.proof__lead-value--wrap {
	margin-block: 0;
	font-size: clamp(2.25rem, 1rem + 4vw, 4.5rem);
	line-height: 1.05;
	white-space: normal;
}

.proof__lead-value--wrap > :where(.odo) {
	white-space: normal;
}

.proof__lead-label {
	margin: .75rem 0 0;
	max-width: 44ch;
	font: 600 clamp(var(--fs-lead), 1rem + .6vw, 1.5rem)/1.4 var(--font-text);
	color: var(--text-soft);
}

/* ---------- Weitere Kennzahlen als Streifen ----------
   Unter der Zahl statt rechts daneben. auto-fit verteilt 1 bis 3 Werte auf
   gleich breite Spalten über die volle Breite; bei 375 px wird daraus eine
   Spalte. 12rem Mindestbreite hält „35.076.799“ bei 768 px in der Zelle.
   Die DOM-Reihenfolge bleibt dt vor dd (Screenreader lesen „Follower und
   Abonnenten: 300.000“); der Wert steht optisch über dem Label. */
.proof__more {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
	column-gap: var(--gap);
	margin: clamp(2rem, 4vw, 3.5rem) 0 0;
}

.proof__more-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-content: start;
	padding-block: 1rem;
	border-top: 1px solid var(--line);
}

.proof__more-row dd {
	grid-row: 1;
	margin: 0;
	font: 820 clamp(1.75rem, 1rem + 2vw, 2.75rem)/1 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums lining-nums;
	color: var(--text);
}

/* Silbentrennung nur schmal (02-base.css); breiter bricht das Label an
   Wortgrenzen. overflow-wrap bleibt die letzte Sicherung. */
.proof__more-row dt {
	grid-row: 2;
	margin: .5rem 0 0;
	max-width: 30ch;
	font: 400 1rem/1.4 var(--font-text);
	color: var(--text-soft);
	overflow-wrap: anywhere;
}

@media (min-width: 48rem) {
	.proof__more-row {
		padding-block: 1.25rem 0;
	}
}

/* ---------- Kanal-Zeilen ---------- */

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

.proof__lead + .channels {
	margin-top: clamp(3rem, 6vw, 5rem);
}

.channel-row {
	row-gap: 1.25rem;
	padding-block: clamp(1.25rem, 2.2vw, 1.75rem);
	border-top: 1px solid var(--line);
}

/* FIX: Rasterkinder mit langem Inhalt dürfen ihre Spalte nicht aufdrücken
   (früher min-width: 0 an .channels__summary-item). */
.channel-row > * {
	min-width: 0;
}

/* Kopf: Avatar links (nur mit Beitragsbild), Bauchbinde, Nische und
   Startdatum untereinander. Ohne Bild fällt die Avatarspalte weg. */
.channel-row__head {
	display: grid;
	grid-template-columns: 3.5rem minmax(0, 1fr);
	column-gap: 1rem;
	align-items: center;
	align-self: start;
}

.channel-row__head--plain {
	grid-template-columns: minmax(0, 1fr);
}

/* Ring in der Akzentfarbe des Kanals (ACF), sonst in der Markenfarbe.
   Der Ring ist Dekoration, keine UI-Grenze. */
.channel-row__avatar {
	display: block;
	width: 3.5rem;
	height: 3.5rem;
	border: 2px solid var(--accent, var(--mark));
	border-radius: var(--r-round);
	object-fit: cover;
}

.channel-row__niche,
.channel-row__since {
	grid-column: 2;
}

.channel-row__head--plain :is(.channel-row__niche, .channel-row__since) {
	grid-column: 1;
}

.channel-row__niche {
	margin: .625rem 0 0;
	font: 400 .9375rem/1.5 var(--font-text);
	color: var(--text-soft);
}

/* Startdatum: Datum in Plex Mono 13 px (echte Daten), Bezeichnung dahinter.
   Im DOM steht dt vor dd wie bei den Kennzahlen, optisch das Datum zuerst. */
.channel-row__since {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0 .5rem;
	margin: .25rem 0 0;
}

.channel-row__since dd {
	order: -1;
	margin: 0;
	font: 500 var(--fs-mono)/1.5 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text);
}

.channel-row__since dt {
	font: 400 .875rem/1.5 var(--font-text);
	color: var(--text-soft);
}

/* Plattformliste: Linien nur zwischen den Plattformen. Die erste Zeile
   beginnt auf der Oberkante der Kanalzeile, eine zweite Linie direkt unter
   der Zeilenlinie wirkte doppelt. */
.channel-row__platforms {
	list-style: none;
	margin: 0;
	padding: 0;
	align-self: start;
}

.channel-row__platform {
	display: grid;
	grid-template-columns: 1.25rem minmax(0, 1fr) auto;
	column-gap: .75rem;
	align-items: center;
	min-height: 2.75rem;
}

.channel-row__platform + .channel-row__platform {
	border-top: 1px solid var(--line);
}

.channel-row__platform svg {
	display: block;
	width: 1rem;
	height: 1rem;
	color: var(--text-soft);
}

/* Netzwerkname als Link zum Profil: Textfarbe plus Unterstreichung (nicht
   nur Farbe als Signal). Die Fläche füllt die 44 px hohe Zeile, damit die
   Zielgröße auch für den kurzen Text „TikTok“ reicht.
   Das frühere Inline-Style text-decoration:none entfällt. */
.channel-row__network {
	display: flex;
	align-items: center;
	align-self: stretch;
	min-height: 2.75rem;
	font: 400 .9375rem/1.3 var(--font-text);
	color: var(--text);
}

a.channel-row__network {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

a.channel-row__network:hover {
	color: var(--text);
	text-decoration-thickness: 2px;
}

.channel-row__followers {
	font: 500 .9375rem/1.3 var(--font-mono);
	letter-spacing: .02em;
	font-variant-numeric: tabular-nums;
	color: var(--text);
	white-space: nowrap;
}

/* Kennzahlen (Aufrufe, stärkstes Video) in jeder Breite nebeneinander.
   grid-auto-flow: column verteilt 1 oder 2 Werte auf gleich breite Spalten,
   ohne leere Zellen zu reservieren. */
.channel-row__stats {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(0, 1fr);
	column-gap: 1rem;
	align-self: start;
	margin: 0;
}

.channel-row__stat {
	display: grid;
	align-content: start;
	min-width: 0;
}

.channel-row__stat dd {
	grid-row: 1;
	margin: 0;
	font: 720 1.25rem/1.2 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums lining-nums;
	color: var(--text);
	overflow-wrap: anywhere;
}

.channel-row__stat dt {
	grid-row: 2;
	margin-top: .25rem;
	font: 400 .875rem/1.35 var(--font-text);
	color: var(--text-soft);
	overflow-wrap: anywhere;
}

/* Tablet: Kopf über volle Breite, darunter Plattformen und Kennzahlen
   nebeneinander. .grid-12 ist hier noch einspaltig und wird überschrieben. */
@media (min-width: 48rem) and (max-width: 61.99rem) {
	.channel-row {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: clamp(2rem, 5vw, 3rem);
	}

	.channel-row__head {
		grid-column: 1 / -1;
	}

	.channel-row__platforms {
		grid-column: 1;
	}

	.channel-row__stats {
		grid-column: 2;
	}
}

/* Desktop: Kopf 1–4, Plattformen 5–8, Kennzahlen 9–12. Fehlt die
   Plattformliste oder fehlen Kennzahlen, bleiben die übrigen Blöcke in ihrer
   Spalte, damit mehrere Kanäle untereinander vergleichbar ausgerichtet sind.
   Die Kennzahlen rücken mit ihrer Wertzeile auf die Mitte der ersten
   Plattformzeile (2.75rem hoch, Wert 1.25rem × 1.2). */
@media (min-width: 62rem) {
	.channel-row__head {
		grid-column: 1 / 5;
	}

	.channel-row__platforms {
		grid-column: 5 / 9;
	}

	.channel-row__stats {
		grid-column: 9 / 13;
		padding-top: .625rem;
	}
}

/* ---------- Fazit, Button, Hinweis ---------- */

.proof__close {
	row-gap: 1.5rem;
	margin-top: clamp(2.5rem, 5vw, 4rem);
}

/* FIX: Unter 48rem 17 px wie .section__intro (4.3: „375 px … Intro 17 px“).
   Vorher lief das Fazit bei 375 px in 20 px über 11 bis 12 Zeilen und stand
   über dem Intro. Die 1.25rem aus 6.5 gelten ab 48rem, wo auch das Intro auf
   --fs-lead wächst. */
.proof__conclusion {
	margin: 0;
	max-width: 60ch;
	font: 400 var(--fs-body)/var(--lh-body) var(--font-text);
	color: var(--text);
}

/* 375 px: Button über die volle Breite über .btn--block aus 10-buttons.css
   (Klasse im Markup, Regel für Sektions-CTAs). Ab 48rem steht er in
   natürlicher Breite. :where hält die Spezifität bei einer Klasse, das
   Innenleben des Buttons (Label, Segment) bleibt allein Sache von F. */
@media (min-width: 48rem) {
	.proof__conclusion {
		font-size: 1.25rem;
	}

	.proof__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* FIX: Der Button in Spalte 9–12 begann bei Spalte 9 und endete irgendwo
   davor; er fluchtete mit keiner Kante. Jetzt schließt er rechts an der
   Containerkante ab, wie die Sektions-CTAs in pain_points und services. */
@media (min-width: 62rem) {
	.proof__conclusion {
		grid-column: 1 / 8;
	}

	.proof__cta {
		grid-column: 9 / 13;
		align-self: end;
		justify-content: flex-end;
	}

	.proof__cta:only-child {
		grid-column: 1 / -1;
	}
}

.proof__disclaimer {
	margin: 2rem 0 0;
	max-width: 70ch;
	font: 400 .875rem/1.6 var(--font-text);
	color: var(--text-soft);
}

/* ---------- Kompaktfassung (.proof--compact) ----------
   ABWEICHUNG von 6.5 (Art-Director-Befund Runde 2 „channel_proof bis zur
   Abnutzung wiederholt“): Außer auf Startseite und /unsere-kanaele/ steht der
   Beleg als Kompaktfassung (Begründung in channel_proof.php). Aufbau ab 62rem:
   Kopf gestapelt in den Spalten 1 bis 7, die Leitzahl in 8 bis 12 auf der
   Unterkante des Kopfs, darunter die stärkste Kanalzeile über die volle
   Breite, zum Schluss Hinweis links und Button rechts in einer Zeile.
   Darunter alles untereinander. Die Leitzahl bleibt die laute Stelle der
   Sektion, aber nicht mehr plakatbreit: Sie rechnet ihre Größe weiter über
   die Stufenklasse aus der eigenen Spaltenbreite (cqi). */

.proof__top {
	row-gap: clamp(2rem, 4vw, 2.5rem);
	align-items: end;
}

.proof__top > * {
	grid-column: 1 / -1;
	min-width: 0;
}

/* Der Abstand zum Inhalt kommt vom Raster, nicht vom Kopf. */
.proof__top-head > :where(.section__header) {
	margin-bottom: 0;
}

/* Kompakt mit Obergrenze 7rem statt 20rem: Neben dem Kopf bleibt die Zahl
   die lauteste Stelle, ohne zum Plakat zu werden (bei 375 px greift ohnehin
   die Spaltenbreite). */
@supports (width: 1cqi) {
	.proof--compact .proof__lead-value {
		font-size: min(7rem, calc(100cqi / var(--proof-fit, 4.9)));
	}
}

.proof--compact .proof__lead-label {
	margin-top: .5rem;
	font-size: var(--fs-lead);
}

@media (min-width: 62rem) {
	.proof__top-head {
		grid-column: 1 / 8;
	}

	.proof__top > .proof__lead {
		grid-column: 8 / -1;
	}

	/* Ohne Kopf steht die Zahl links. */
	.proof__top--solo > .proof__lead {
		grid-column: 1 / 8;
	}
}

.proof__top + .channels {
	margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

/* Eine einzelne Zeile schließt unten mit derselben Linie ab, mit der sie
   oben beginnt: So steht sie als Registerzeile, nicht als Rest einer Tabelle. */
.channels--single {
	border-bottom: 1px solid var(--line);
}

/* Mittig statt auf der Grundlinie: Bricht der Textlink neben einem langen
   Button in eine zweite Zeile, bleibt der Hinweis trotzdem auf den Block
   bezogen. */
.proof--compact .proof__close {
	align-items: center;
	margin-top: clamp(1.5rem, 3vw, 2rem);
}

.proof--compact .proof__disclaimer {
	margin: 0;
}

/* Zweiter Weg zu allen Kanälen neben einem Button, der zum Erstgespräch
   führt: Textlink mit Pfeil, 44 px hohe Trefferfläche. */
.proof__cta {
	align-items: center;
	column-gap: 1.5rem;
}

.proof__all {
	min-height: 2.75rem;
}

@media (min-width: 62rem) {
	.proof--compact .proof__disclaimer {
		grid-column: 1 / 7;
	}

	/* Hinweis und Button teilen die Zeile, der Button steht rechts. Ab
	   Spalte 7, damit Button und Textlink bei 1440 px nebeneinander passen. */
	.proof--compact .proof__cta {
		grid-column: 7 / -1;
	}
}

/* Listen-Einblendung (Inventar 7.3, Nr. 3): .channel-row und .proof__lead
   tragen data-reveal. Ausgangszustand und Übergang liefert 90-motion.css (F)
   nur unter html.smm-motion; eigene transitions an diesen Elementen gibt es
   deshalb bewusst nicht. */

/* ===== 53-process.css ===== */
/* =========================================================================
   53 · process: Schnitt-Spur mit Playhead (Spezifikation 5.6, 6.9)
   Besitz: Team C. Signatur der Sektion ist die Spur selbst.

   Grundzustand ist die vertikale Spur. Sie ist ohne JavaScript, ohne
   animation-timeline und bei reduzierter Bewegung vollständig lesbar.
   Horizontal wird sie nur über die Modifier aus process.php:
     .timeline-wrap--cols       2 bis 4 Schritte, ab 62rem
     .timeline-wrap--cols-wide  5 Schritte, ab 75rem
   1 Schritt und 6+ Schritte bleiben vertikal (keine gestauchten Spalten).
   Horizontal zeigt die Spur im Ruhezustand ihr Schlussbild (Clips gefüllt,
   Playhead am Ende); unter html.smm-motion läuft der Playhead einmal durch
   (Block „Playhead“ unten).
   ========================================================================= */

.timeline-wrap {
	/* Höhe des Playheads: Lineal 10px, Abstand 6px, Clip-Reihe 3rem. */
	--tl-head: calc(10px + 6px + 3rem);
	/* Durchlauf: 450 ms je Clip, Start kurz nach der Listen-Einblendung. */
	--tl-run: calc(var(--steps, 4) * 450ms);
	--tl-lead: 240ms;
	position: relative;
}

.timeline {
	/* Schrittabstand (6.9: 2rem) als lokale Variable, weil die Spurlinie
	   ihn überbrücken muss (siehe .timeline__step::before). */
	--tl-gap: 2rem;
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--tl-gap);
}

/* Vertikale Spur: 2px-Linie links, der Clip steht als Inline-Tafel daneben. */
.timeline__step {
	position: relative;
	min-width: 0;
	padding-inline-start: 1.75rem;
}

.timeline__step::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: .5rem;
	width: 2px;
	background: var(--line);
}

/* ABWEICHUNG: 5.6 zieht die Linie „über die volle Höhe“ des li. Hier
   reichen Linie und Füllung durch den Schrittabstand bis zum nächsten
   Schritt. Mit 2rem Lücke zerfiel die Spur in einzelne Balken links an
   jedem Textblock, die wie Akzentleisten wirkten (9.6), statt als eine
   durchgehende Spur. Der letzte Schritt endet an seinem Text. Gilt auch
   für ::after aus dem @supports-Block unten (höhere Spezifität); scaleY mit
   transform-origin top füllt Schritt und Abstand dann gemeinsam.
   Horizontal setzen die Modifier content: none, dort wirkt die Regel
   nicht. */
.timeline__step:not(:last-child)::before,
.timeline__step:not(:last-child)::after {
	bottom: calc(-1 * var(--tl-gap));
}

/* Clip: Nummer und Dauer sind echter Text (ol-Semantik bleibt).
   Abweichung von 5.6: Die Spezifikation setzt line-height 1 und eine feste Höhe. Lange
   Dauern wie „vor dem Termin, ohne dein Zutun“ brechen in schmalen Spalten
   aber um; mit Zeilenhöhe 1 kleben die Zeilen aneinander, mit fester Höhe
   laufen sie aus der Tafel. Deshalb min-height, 1.25 und etwas Innenabstand.

   ABWEICHUNG: 5.6 setzt alle Clips in Plex Mono, die Nachträge dort
   stellten einzelne Angaben in Worten auf Schibsted. In einer Spur standen
   dadurch zwei Schriften nebeneinander („30 Minuten“ neben „laufend, Bericht
   monatlich“), das wirkte unfertig. Jetzt hat jede Spur genau eine Schrift:
   Grundfall ist Schibsted 600 für Nummer und Label. Nur wenn jede Dauer
   der Spur eine echte Zeitangabe ist, setzt process.php --timecode, dann
   steht die ganze Spur in Plex Mono (Regel 1.3). Tabellarische Ziffern
   trägt die Nummer (.timeline__no): Die Schnittkante steht so in jedem
   Clip an derselben Stelle. Im Label bleiben sie aus, Schibsted setzt mit
   tnum auch das Komma auf Ziffernbreite („laufend , Bericht“). */
.timeline__clip {
	display: inline-flex;
	/* .625rem statt .75rem: Die Schnittkante an der Nummer bringt eigenen
	   Innenabstand mit, der Clip wird dadurch nicht breiter. */
	gap: .625rem;
	align-items: center;
	max-width: 100%;
	min-height: 2.25rem;
	padding: .375rem .875rem;
	background: var(--clip-bg);
	color: var(--clip-fg);
	border-radius: 2px;
	font: 600 var(--fs-xs)/1.25 var(--font-text);
}

.timeline-wrap--timecode .timeline__clip {
	font: 500 var(--fs-mono)/1.2 var(--font-mono);
	letter-spacing: .02em;
}

.timeline__no {
	flex: none;
	color: var(--text-soft);
	font-variant-numeric: tabular-nums lining-nums;
}

/* ABWEICHUNG: 5.6 trennt Nummer und Dauer nur durch .75rem. In derselben
   Mono-Schrift lasen sie sich als eine Angabe („1 1 bis 2 Wochen“,
   „3 30 Minuten“). Eine Schnittkante trennt sie. Sie nimmt die
   Schriftfarbe (currentColor) und geht dadurch in jedem Zustand mit:
   ungefüllt, gefüllt, auf Studio und im Kontrastmodus. Nur wenn
   eine Dauer folgt. */
.timeline__no:not(:last-child) {
	padding-inline-end: .625rem;
	border-inline-end: 1px solid;
}

/* 6.9: Ohne Dauer steht nur die Nummer. Größer, damit der Clip nicht wie
   ein leerer Platzhalter mit winziger Ziffer wirkt.
   Farbe bewusst nur inherit: Eine feste Farbe kippte im gefüllten Clip
   den Kontrast (Tinte auf #156A72 = 2,75:1). */
.timeline__no:only-child {
	font-size: 1rem;
	color: inherit;
}

.timeline__dur {
	min-width: 0;
	overflow-wrap: anywhere;
}

/* Optionales Bild: 3:2, Radius 2px, bewusst ohne Sucherrahmen-Marken. */
.timeline__media {
	margin-top: 1rem;
	max-width: 36rem;
}

.timeline__media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: 2px;
}

.timeline__title {
	margin: .875rem 0 0;
	font: 700 1.25rem/1.2 var(--font-display);
	color: var(--text);
	/* Keine Einzelwort-Zeile („Reportings“, „André“), auch in den
	   schmalen Spalten der horizontalen Spur. */
	text-wrap: balance;
}

.timeline__text {
	margin: .5rem 0 0;
	max-width: 58ch;
	font: 400 1rem/1.6 var(--font-text);
	color: var(--text-soft);
}

.timeline__ruler,
.timeline__playhead {
	display: none;
}

.process__cta {
	margin-top: 3rem;
}

/* Sektions-CTA (einheitlich für alle Sektionen): btn--lg, unter 48rem in
   voller Breite (btn--block im Markup), ab 48rem in natürlicher Breite wie
   pain_points, text_media, hero und cta_band. Vorher endete der Button bei
   375 px je nach Labellänge 5 px vor der Satzkante. :where hält die
   Spezifität bei einer Klasse, die Reihenfolge im Build (53 nach 10)
   entscheidet. */
@media (min-width: 48rem) {
	.process__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* Befund sektions-cta-dichte-ausrichtung: Schließt ein Sektions-CTA eine
   vollbreite Reihe ab (pain_points, channel_proof, services, process,
   comparison, video_testimonials, cases), steht er ab 62rem rechtsbündig an
   der Containerkante. Vorher sprang der Button auf Seiten wie
   kundenstimmen-video von Sektion zu Sektion zwischen rechts und links.
   CTAs in einer Textspalte (hero, text_media, cta_band) bleiben an deren
   Textkante. ABWEICHUNG von 6.9 (dort „linksbündig“), Regel in 4.5. */
@media (min-width: 62rem) {
	.process__cta {
		justify-content: flex-end;
	}
}

@media (min-width: 48rem) {
	.timeline__title {
		font-size: 1.375rem;
	}
}

/* ---------- Horizontal: 2 bis 4 Schritte ab 62rem ---------- */
@media (min-width: 62rem) {
	.timeline-wrap--cols .timeline {
		grid-template-columns: repeat(var(--steps), minmax(0, 1fr));
		column-gap: 4px;
		row-gap: 0;
	}

	.timeline-wrap--cols .timeline__ruler {
		display: block;
		height: 10px;
		margin-bottom: 6px;
		background: repeating-linear-gradient(to right, var(--line-ui) 0 1px, transparent 1px 1.5rem);
	}

	.timeline-wrap--cols .timeline__step {
		padding-inline-start: 0;
	}

	.timeline-wrap--cols .timeline__step::before,
	.timeline-wrap--cols .timeline__step::after {
		content: none;
	}

	.timeline-wrap--cols .timeline__clip {
		display: flex;
		min-height: 3rem;
		background: var(--clip-on-bg);
		color: var(--clip-on-fg);
	}

	.timeline-wrap--cols .timeline__no {
		color: inherit;
	}

	/* Playhead im Ruhezustand: am Ende der Spur (siehe Block „Playhead“). */
	.timeline-wrap--cols::after {
		content: "";
		position: absolute;
		z-index: var(--z-raised);
		top: -4px;
		right: -4px;
		width: 10px;
		height: calc(4px + var(--tl-head));
		background:
			linear-gradient(var(--playhead) 0 0) left top / 10px 10px no-repeat,
			linear-gradient(var(--playhead) 0 0) 4px top / 2px 100% no-repeat;
		pointer-events: none;
	}

	.timeline-wrap--cols .timeline__media {
		max-width: none;
	}

	.timeline-wrap--cols .timeline__title {
		margin-top: 1.5rem;
		padding-inline-end: 1.5rem;
	}

	.timeline-wrap--cols .timeline__text {
		padding-inline-end: 1.5rem;
	}
}

/* Gemeinsames Zeilenraster der Spalten: Clip, Bild, Titel und Text liegen
   je Zeile auf einer Höhe. Ein zweizeiliger Titel („Veröffentlichung und
   Auswertung“) schob seinen Text sonst rund 26 px tiefer als die Nachbarn,
   unter der strengen Clip-Reihe entstand eine Stufe. Ohne subgrid bleibt es
   beim bisherigen Satz untereinander. */
@supports (grid-template-rows: subgrid) {
	@media (min-width: 62rem) {
		.timeline-wrap--cols .timeline__step {
			display: grid;
			grid-row: span 4;
			grid-template-rows: subgrid;
			row-gap: 0;
		}

		.timeline-wrap--cols .timeline__clip {
			grid-row: 1;
		}

		.timeline-wrap--cols .timeline__media {
			grid-row: 2;
		}

		/* Titel unten in ihrer Zeile: Jeder Titel bleibt direkt über seinem
		   Text, die Titel enden auf einer Linie, die Texte beginnen auf einer.
		   Der Ausgleich fällt in den Abstand unter der Clip-Reihe. */
		.timeline-wrap--cols .timeline__title {
			grid-row: 3;
			align-self: end;
		}

		.timeline-wrap--cols .timeline__text {
			grid-row: 4;
		}
	}
}

/* ---------- Horizontal: 5 Schritte erst ab 75rem ---------- */
@media (min-width: 75rem) {
	.timeline-wrap--cols-wide .timeline {
		grid-template-columns: repeat(var(--steps), minmax(0, 1fr));
		column-gap: 4px;
		row-gap: 0;
	}

	.timeline-wrap--cols-wide .timeline__ruler {
		display: block;
		height: 10px;
		margin-bottom: 6px;
		background: repeating-linear-gradient(to right, var(--line-ui) 0 1px, transparent 1px 1.5rem);
	}

	.timeline-wrap--cols-wide .timeline__step {
		padding-inline-start: 0;
	}

	.timeline-wrap--cols-wide .timeline__step::before,
	.timeline-wrap--cols-wide .timeline__step::after {
		content: none;
	}

	.timeline-wrap--cols-wide .timeline__clip {
		display: flex;
		min-height: 3rem;
		background: var(--clip-on-bg);
		color: var(--clip-on-fg);
	}

	.timeline-wrap--cols-wide .timeline__no {
		color: inherit;
	}

	.timeline-wrap--cols-wide::after {
		content: "";
		position: absolute;
		z-index: var(--z-raised);
		top: -4px;
		right: -4px;
		width: 10px;
		height: calc(4px + var(--tl-head));
		background:
			linear-gradient(var(--playhead) 0 0) left top / 10px 10px no-repeat,
			linear-gradient(var(--playhead) 0 0) 4px top / 2px 100% no-repeat;
		pointer-events: none;
	}

	.timeline-wrap--cols-wide .timeline__media {
		max-width: none;
	}

	.timeline-wrap--cols-wide .timeline__title {
		margin-top: 1.5rem;
		padding-inline-end: 1.5rem;
	}

	.timeline-wrap--cols-wide .timeline__text {
		padding-inline-end: 1.5rem;
	}
}

/* Gemeinsames Zeilenraster der Spalten: Clip, Bild, Titel und Text liegen
   je Zeile auf einer Höhe. Ein zweizeiliger Titel („Veröffentlichung und
   Auswertung“) schob seinen Text sonst rund 26 px tiefer als die Nachbarn,
   unter der strengen Clip-Reihe entstand eine Stufe. Ohne subgrid bleibt es
   beim bisherigen Satz untereinander. */
@supports (grid-template-rows: subgrid) {
	@media (min-width: 75rem) {
		.timeline-wrap--cols-wide .timeline__step {
			display: grid;
			grid-row: span 4;
			grid-template-rows: subgrid;
			row-gap: 0;
		}

		.timeline-wrap--cols-wide .timeline__clip {
			grid-row: 1;
		}

		.timeline-wrap--cols-wide .timeline__media {
			grid-row: 2;
		}

		/* Titel unten in ihrer Zeile: Jeder Titel bleibt direkt über seinem
		   Text, die Titel enden auf einer Linie, die Texte beginnen auf einer.
		   Der Ausgleich fällt in den Abstand unter der Clip-Reihe. */
		.timeline-wrap--cols-wide .timeline__title {
			grid-row: 3;
			align-self: end;
		}

		.timeline-wrap--cols-wide .timeline__text {
			grid-row: 4;
		}
	}
}

/* ---------- Scroll-getriebene Linie der vertikalen Spur (Inventar 7.3, Nr. 5)
   Nur mit animation-timeline und ohne reduzierte Bewegung. Fallback: graue
   Linie. Playhead und Clip-Füllung der horizontalen Spur siehe unten. */
@supports (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) {
		/* Vertikal: Die Linie füllt sich je Schritt von oben. Die benannte
		   Timeline am li ist robuster als view() direkt am Pseudo-Element. */
		.timeline__step {
			view-timeline-name: --tl-step;
		}

		.timeline__step::after {
			content: "";
			position: absolute;
			top: 0;
			bottom: 0;
			left: .5rem;
			width: 2px;
			background: var(--clip-on-bg);
			transform-origin: top;
			animation: tl-rail linear both;
			animation-timeline: --tl-step;
			animation-range: entry 40% cover 50%;
		}
	}
}

/* ---------- Playhead (Befund „Spur-Elemente wirken unfertig“) ----------
   ABWEICHUNG: 5.6 und Inventar 7.3 Nr. 4 koppeln Playhead und Clip-Füllung
   an die Scrollposition. Im Ruhezustand eines Screenshots und in Browsern
   ohne animation-timeline blieb davon nur ein Quadrat am Anfang des Lineals
   stehen. Jetzt läuft der Playhead einmal durch die Spur:
     - Ruhezustand (ohne JS, ohne IntersectionObserver, reduzierte Bewegung):
       Der Playhead steht am Ende der Spur (::after an .timeline-wrap), alle
       Clips sind gefüllt. Das ist das Schlussbild des Durchlaufs.
     - html.smm-motion: Bis die Spur ins Bild kommt, steht der Playhead
       (.timeline__playhead) am Anfang, die Clips sind leer. Mit is-revealed
       (30-reveal.js, data-reveal an .timeline-wrap) fährt er in 450 ms je
       Clip linear ans Ende. Jeder Clip wechselt hart auf --clip-on, wenn der
       Playhead seine Vorderkante erreicht (Übergang 0 s mit Verzögerung,
       kein Zwischenzustand, 5.6 Barrierefreiheit).
   Animiert wird nur transform, die Füllung ist ein harter Farbwechsel (7.1).
   Das ::after bleibt vom Netz in 90-motion.css unberührt, das dort
   .timeline__playhead unter reduce ausblendet; so steht der Playhead auch
   dann am Ende. Der Playhead liegt mit --z-raised über den Schritten, die
   während der Einblendung einen transform tragen. */
@media (prefers-reduced-motion: no-preference) and (min-width: 62rem) {
	html.smm-motion .timeline-wrap--cols {
		container-type: inline-size;
	}

	html.smm-motion .timeline-wrap--cols::after {
		content: none;
	}

	html.smm-motion .timeline-wrap--cols .timeline__playhead {
		display: block;
		position: absolute;
		z-index: var(--z-raised);
		top: -4px;
		left: -4px;
		width: 10px;
		height: calc(4px + var(--tl-head));
		background:
			linear-gradient(var(--playhead) 0 0) left top / 10px 10px no-repeat,
			linear-gradient(var(--playhead) 0 0) 4px top / 2px 100% no-repeat;
		pointer-events: none;
		transform: translateX(calc(100cqw - 2px));
	}

	html.smm-motion .timeline-wrap--cols:not(.is-revealed) .timeline__playhead {
		transform: none;
	}

	/* Übergang nur im Zustand is-revealed (siehe Clip-Füllung unten). */
	html.smm-motion .timeline-wrap--cols.is-revealed .timeline__playhead {
		transition: transform var(--tl-run) linear var(--tl-lead);
	}

	html.smm-motion .timeline-wrap--cols:not(.is-revealed) .timeline__clip {
		background-color: var(--clip-bg);
		color: var(--clip-fg);
	}
}

@media (prefers-reduced-motion: no-preference) and (min-width: 75rem) {
	html.smm-motion .timeline-wrap--cols-wide {
		container-type: inline-size;
	}

	html.smm-motion .timeline-wrap--cols-wide::after {
		content: none;
	}

	html.smm-motion .timeline-wrap--cols-wide .timeline__playhead {
		display: block;
		position: absolute;
		z-index: var(--z-raised);
		top: -4px;
		left: -4px;
		width: 10px;
		height: calc(4px + var(--tl-head));
		background:
			linear-gradient(var(--playhead) 0 0) left top / 10px 10px no-repeat,
			linear-gradient(var(--playhead) 0 0) 4px top / 2px 100% no-repeat;
		pointer-events: none;
		transform: translateX(calc(100cqw - 2px));
	}

	html.smm-motion .timeline-wrap--cols-wide:not(.is-revealed) .timeline__playhead {
		transform: none;
	}

	/* Übergang nur im Zustand is-revealed (siehe Clip-Füllung unten). */
	html.smm-motion .timeline-wrap--cols-wide.is-revealed .timeline__playhead {
		transition: transform var(--tl-run) linear var(--tl-lead);
	}

	html.smm-motion .timeline-wrap--cols-wide:not(.is-revealed) .timeline__clip {
		background-color: var(--clip-bg);
		color: var(--clip-fg);
	}
}

/* Clip-Füllung: harter Wechsel, wenn der Playhead die Vorderkante des Clips
   erreicht (Übergang 0 s, Verzögerung nach --i).
   - Nur im Zustand is-revealed: Stünde der Übergang auch davor, liefe beim
     Setzen von smm-motion der Wechsel gefüllt → leer mit denselben
     Verzögerungen, und ein früher Eintritt kehrte ihn halb abgelaufen um.
   - Bewusst ohne Breitenabfrage: Kippt die Breite kurz unter 62rem und
     zurück (Fenstergröße, Bildschirmfoto über die volle Seitenhöhe), bleibt
     der Wechsel zur vertikalen Spur in seiner Verzögerung hängen und wird
     beim Zurückkippen verworfen. Mit dem Übergang nur in der breiten Fassung
     lief die Füllung dort erneut los, während der Playhead schon am Ende
     stand. */
@media (prefers-reduced-motion: no-preference) {
	html.smm-motion :is(.timeline-wrap--cols, .timeline-wrap--cols-wide).is-revealed .timeline__clip {
		transition:
			background-color 0s linear calc(var(--tl-lead) + var(--tl-run) * var(--i, 0) / var(--steps, 4)),
			color 0s linear calc(var(--tl-lead) + var(--tl-run) * var(--i, 0) / var(--steps, 4));
	}
}

/* Windows-Kontrastmodus ersetzt die Clipfläche durch Canvas. Ein Rand hält
   den Clip als Tafel erkennbar, die Spurlinie bekommt Systemfarbe.
   FIX: Der Block steht nach @supports, damit er die Linienfüllung sicher
   übersteuert. Der Browser erzwingt dort background-color auf Canvas: Die
   Füllung (::after) malte sich deshalb deckend über die Linie, und
   CanvasText als Hintergrund der Linie selbst wurde ebenfalls zu Canvas.
   Die Füllung entfällt, forced-color-adjust none hält die Linie sichtbar. */
@media (forced-colors: active) {
	.timeline__clip {
		border: 1px solid CanvasText;
	}

	.timeline__step::before {
		forced-color-adjust: none;
		background: CanvasText;
	}

	.timeline__step::after {
		content: none;
	}

	/* Playhead in Systemfarbe; Hintergrundbilder behalten sonst die
	   Tintenfarbe, die auf dunklem Canvas verschwände. */
	.timeline-wrap::after,
	.timeline__playhead {
		forced-color-adjust: none;
		background:
			linear-gradient(CanvasText 0 0) left top / 10px 10px no-repeat,
			linear-gradient(CanvasText 0 0) 4px top / 2px 100% no-repeat;
	}
}

/* Reduzierte Bewegung: Die Linienfüllung schaltet 90-motion.css (F) zentral
   mit animation: none ab (7.1.6), dort wird auch .timeline__playhead
   ausgeblendet. Der Durchlauf des Playheads und die Clip-Füllung hängen hier
   ohnehin an html.smm-motion und no-preference; ohne sie zeigt die Spur das
   Schlussbild (Playhead am Ende als ::after, Clips gefüllt). */

@keyframes tl-rail {
	from { transform: scaleY(0); }
	to { transform: scaleY(1); }
}

/* Listen-Einblendung (Inventar 7.3, Nr. 3): Die li tragen data-reveal und
   data-reveal-delay. Ausgangszustand und Übergang liefert 90-motion.css (F)
   nur unter html.smm-motion; deshalb hat .timeline__step hier bewusst keine
   eigene transition (Vertrag aus 90-motion.css). */

/* ---------- Schlichte Darstellung (process, style simple) ----------
   Loom vom 06.10.2026: Nummer, Titel, kurzer Text. Jede Spalte beginnt
   unter einer Haarlinie, die Nummer steht in der Display-Schrift im
   Akzent. Ab 62rem alle Schritte nebeneinander (--steps). */
.steps {
	list-style-type: "";
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 2rem var(--gap);
	margin: 0;
	padding: 0;
}

.steps__item {
	display: grid;
	align-content: start;
	gap: .5rem;
	padding-top: 1.25rem;
	border-top: 1px solid var(--line);
}

.steps__no {
	font: 700 clamp(1.75rem, 1.3rem + 1.2vw, 2.25rem)/1 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums;
	color: var(--accent-text);
}

.steps__title {
	margin: .25rem 0 0;
	font: 700 var(--fs-h4)/1.25 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
}

.steps__text {
	max-width: 36ch;
	margin: 0;
	font-size: var(--fs-small);
	line-height: 1.55;
	color: var(--text-soft);
}

@media (min-width: 48rem) {
	.steps {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 62rem) {
	.steps {
		grid-template-columns: repeat(var(--steps, 4), minmax(0, 1fr));
	}
}

/* ===== 54-services.css ===== */
/* =========================================================================
   54 · services: Leistungsregister (Spezifikation 6.10)
   Besitz: Team C. Markup: template-parts/sections/services.php

   Stil „card“ und „list“: eine Registerzeile je Leistung über die volle
   Breite. Kein Kartenraster, deshalb keine verwaiste Einzelkarte bei 7
   oder 11 Einträgen. Hover und Fokus: Fläche --surface von links,
   Trim-Griffe (5.5, von F), Titel +.375rem, Pfeilquadrat gefüllt.
   Stil „image“: horizontale Scroll-Snap-Reihe (.register--image).

   Varianten der Liste (aus den Daten abgeleitet, kein Feld):
     .register            jede Zeile ist ein Link mit Pfeilquadrat
     .register--static    nicht jede Zeile hat ein Ziel: keine Zeilen-Links,
                          keine Pfeilspalte, vorhandene Links als Textlink
     .register--lead      ab 5 verlinkten Einträgen: erste Zeile als
                          Aufmacher (.register__item--lead)

   ABWEICHUNG von 6.10: keine Symbolspalte mehr (Begründung in services.php).
   Die Zeile benutzt benannte Rasterflächen, damit Titel, Text und Pfeil in
   ihrer Spalte bleiben, auch wenn einer Zeile der Text fehlt.
   ========================================================================= */

.register {
	list-style: none;
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--line);
}

.register__item {
	margin: 0;
	min-width: 0;
}

/* 375 px (Grundzustand): Titel · Pfeil, Text in Zeile 2 über die volle
   Breite. Titelgröße als lokale Variable, weil Pfeilquadrat und Titelzeile
   daran ausgerichtet werden. */
.register__link {
	--register-title-fs: clamp(1.25rem, 1rem + .8vw, 1.625rem);
	--register-title-lh: calc(var(--register-title-fs) * 1.15);
	--register-go: 2.75rem;
	--notch: var(--surface); /* Kerbe im Trim-Griff passt zur Hover-Fläche */
	position: relative;
	isolation: isolate;
	display: grid;
	grid-template-columns: minmax(0, 1fr) var(--register-go);
	grid-template-areas:
		"title go"
		"text  text";
	align-items: start;
	column-gap: .75rem;
	padding: 1.25rem .25rem;
	border-bottom: 1px solid var(--line);
	color: var(--text);
	text-decoration: none;
}

/* FIX: Früher wurde die Hover-Fläche hell eingefärbt und der Text blieb
   var(--text) – auf dunklen Abschnitten also Weiß auf Hell, unlesbar. Die
   Fläche ist jetzt --surface und kippt mit dem Theme, der Text bleibt lesbar. */
.register__link::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: var(--surface);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--dur-2) var(--ease-cut);
}

.register__title {
	grid-area: title;
	font: 700 var(--register-title-fs)/1.15 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
	transition: transform var(--dur-1) var(--ease-cut);
}

/* FIX: Zeilenrhythmus mobil. Früher zentrierte eine Mindesthöhe der ersten
   Zeile den Titel auf das Pfeilquadrat: Einzeilige Titel standen 17 px über
   dem Text, zweizeilige klebten mit 6 px daran. Jetzt steht der Text immer
   gleich weit unter dem Titel; das Pfeilquadrat sitzt auf der Mitte der
   ersten Titelzeile und ragt nach unten über, daher 1rem Abstand. */
.register__text {
	grid-area: text;
	margin-top: 1rem;
	font: 400 1rem/1.55 var(--font-text);
	color: var(--text-soft);
}

/* Rahmen in --line-ui (≥3:1). Auf Sektion teal setzt 00-tokens.css den Wert
   auf #D5E4E6 (4,82:1 auf #156A72), eine eigene Überschreibung entfällt.
   Der negative Rand oben und unten zählt das Quadrat nur mit der Höhe einer
   Titelzeile, zentriert auf deren Mitte. */
.register__go {
	grid-area: go;
	display: grid;
	place-items: center;
	width: var(--register-go);
	height: var(--register-go);
	margin-block: calc((var(--register-title-lh) - var(--register-go)) / 2);
	border-radius: var(--r-control);
	box-shadow: inset 0 0 0 1.5px var(--line-ui);
	color: var(--text);
	transition: background-color var(--dur-1) var(--ease-cut), color var(--dur-1) var(--ease-cut);
}

.register__go svg {
	display: block;
	width: 18px;
	height: 18px;
}

/* Windows-Kontrastmodus entfernt box-shadow und Hintergründe: Das
   Pfeilquadrat bekommt einen echten Rand, damit es als Einheit sichtbar bleibt. */
@media (forced-colors: active) {
	.register__go {
		border: 1px solid CanvasText;
	}
}

/* Statisches Register: Titel, Text, Textlink untereinander, keine
   Pfeilspalte. Der Abstand Titel–Text ist kleiner, weil kein Quadrat
   überragt. */
.register--static .register__link {
	grid-template-columns: minmax(0, 1fr);
	grid-template-areas:
		"title"
		"text"
		"more";
}

.register--static .register__text {
	margin-top: .5rem;
}

.register__more {
	grid-area: more;
	justify-self: start;
	margin-top: .625rem;
}

/* Leistungstitel trennen nicht (Befund silbentrennung-leistungstitel:
   „vorhan-/denem“ auf reels-agentur bei 375 px). Ein Titel ist eine
   Überschrift, keine Fließtextzeile; wie bei H1 bis H3 (02-base.css) brechen
   Bindestrich-Komposita wie „Kundenstimmen-Video“ weiter am Strich.
   manual ist der Startwert und steht hier ausdrücklich, weil die Zeile
   vorher unter 30rem trennte. Eine kleinere Schrift ist nicht nötig: Gemessen
   auf allen Seiten von 320 bis 479 px ist das breiteste Einzelwort
   („Straßenumfragen“ auf ugc-agentur, „Fahrtkostenzuschuss“ auf karriere)
   bei 320 px höchstens 76 % der Titelspalte breit. overflow-wrap: anywhere
   bleibt als letzte Sicherung für ein längeres Wort aus der Redaktion
   (29.99rem wie in 02-base.css, damit bei 480 px nur eine Stufe gilt). */
.register__title {
	-webkit-hyphens: manual;
	hyphens: manual;
}

@media (max-width: 29.99rem) {
	.register__title {
		overflow-wrap: anywhere;
	}
}

/* Tablet: Pfeilspalte 3rem, Text weiter in Zeile 2. */
@media (min-width: 48rem) {
	.register__link {
		--register-go: 3rem;
		column-gap: 1.5rem;
		padding: 1.5rem .75rem;
	}
}

/* Desktop: Titel · Text · Pfeil in einer Zeile auf gemeinsamer Grundlinie,
   das Pfeilquadrat senkrecht mittig (Spezifikation).
   ABWEICHUNG von 6.10 (Befund split-kopf-raster): Statt 4fr/6fr liegt die
   Zeile auf dem 12er-Raster des Containers. Der Text beginnt auf Spalte 8,
   genau wie das Intro im split-Kopf darüber (05-section-header.css); vorher
   stand er rund 215 px links davon. Dafür hat die Zeile seitlich kein
   Padding mehr (sonst wären die Spalten um 2rem schmaler als die des
   Kopfs); der Einzug von 1rem sitzt an Titel und Pfeil. */
@media (min-width: 62rem) {
	/* .register--static steht mit, weil dessen Grundregel (einspaltig, zwei
	   Klassen) die einfache Klasse sonst überstimmt: Titel und Text lagen
	   dann übereinander. */
	.register__link,
	.register--static .register__link {
		grid-template-columns: repeat(12, minmax(0, 1fr));
		grid-template-areas: none;
		column-gap: var(--gap);
		align-items: baseline;
		padding: 1.5rem 0;
	}

	.register__title {
		grid-column: 1 / 8;
		grid-row: 1;
		padding-inline-start: 1rem;
	}

	.register__text {
		grid-column: 8 / 12;
		grid-row: 1;
		align-self: baseline;
		margin-top: 0;
	}

	/* Das Quadrat steht rechtsbündig in Spalte 12 und darf bei 62rem (Spalte
	   rund 55 px) etwas in den Spaltenabstand ragen. */
	.register__go {
		grid-column: 12 / 13;
		grid-row: 1;
		justify-self: end;
		align-self: center;
		margin-block: 0;
		margin-inline-end: 1rem;
	}

	.register--static .register__text {
		grid-column: 8 / -1;
		margin-top: 0;
		padding-inline-end: 1rem;
	}

	.register--static .register__more {
		grid-column: 8 / -1;
		grid-row: 2;
	}
}

/* ---------- Hover, Fokus, Antippen (Inventar 7.3, Nr. 7) ----------
   FIX: Auf Touchgeräten bleibt :hover nach dem Antippen „kleben“; die Zeile
   sähe danach dauerhaft ausgewählt aus. Wie beim Trim in 14-trim.css (F)
   hängen Fläche, Pfeilquadrat und Titelverschiebung deshalb nur mit echtem
   Zeiger an :hover. Fläche und Pfeil erscheinen immer bei :focus-visible und
   :active; die Titelverschiebung entfällt unter (hover: none) ganz (6.10).

   Das gefüllte Pfeilquadrat ist der Hover-Zustand eines Ghost-Knopfs und
   liest deshalb die Ghost-Tokens: Tinte mit weißem Pfeil auf Hell, Weiß mit
   Studio-Pfeil auf deep und teal (6.10: #101B1C bzw. #fff). Früher standen
   hier Rohfarben plus eine [data-theme="dark"]-Kopie der Regel; über die
   Tokens folgt das Quadrat auch der Aufmacherzeile, wenn sie hell wird. */

a.register__link:is(:focus-visible, :active)::before {
	transform: scaleX(1);
}

a.register__link:is(:focus-visible, :active) .register__go {
	background: var(--ghost-bg-h);
	color: var(--ghost-fg-h);
	box-shadow: none;
}

@media (hover: hover) {
	a.register__link:hover::before {
		transform: scaleX(1);
	}

	a.register__link:is(:hover, :focus-visible) .register__title {
		transform: translateX(.375rem);
	}

	a.register__link:hover .register__go {
		background: var(--ghost-bg-h);
		color: var(--ghost-fg-h);
		box-shadow: none;
	}
}

/* Eigener Fokusring: Trim ist nie das einzige Signal (5.5). */
a.register__link:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}

/* ---------- Aufmacherzeile ----------
   Art-Director-Verbesserung „Leistungsregister mit Aufmacherzeile“: Der
   erste Eintrag eines verlinkten Registers mit 5 oder mehr Zeilen steht als
   ausgewählter Clip über die volle Breite. Dauerhafte Trim-Griffe
   (.is-trimmed, 5.5), Titel in der O-Ton-Stimme (schmal, schwer).

   ABWEICHUNG von 6.10 (Art-Director-Befund Runde 2 „Gelber Rahmen um die
   Aufmacherzeile“):
   - Die Griffe liegen innen in der Fläche (.trim--inset aus 14-trim.css),
     links und rechts, ohne Linien oben und unten. Vorher lief Gelb als 2 px
     breiter Rahmen außen auf Kreide (Regel 4) und las sich wie ein Fokusrahmen.
   - Kein Pfeilsegment über die volle Zeilenhöhe mehr, sondern dasselbe
     Pfeilquadrat wie in den Zeilen darunter, innerhalb der Griffe. Die
     senkrechte Segmentlinie stand sonst direkt neben dem rechten Griff.
   - Titel deutlich größer (bis 4.5rem statt 2.75rem), damit die Zeile als
     gewollter Aufmacher liest und nicht als etwas größere Registerzeile. Die
     Größe hängt an der Zeilenbreite (cqi), nicht am Viewport: So passt
     „Straßenumfragen“ auch bei 320 px in eine Zeile.

   Flächen:
     .register__item--studio  Studio-Dunkel über data-theme="dark" an der
                              Zeile (Sektion white/mist): Grund --bg,
                              Hover-Fläche Studio-2, Griffe gelb (9,97:1)
     hell                     --surface (Weiß auf Kreide, Kreide auf Weiß,
                              Studio-2 auf deep), Griffe in --trim
   --register-lead-bg trägt die Fläche, damit Griffkerbe und Grund gleich
   bleiben, egal welche Variante greift. */

.register--lead {
	border-top: 0;
}

.register__item--lead {
	--register-lead-bg: var(--surface);
	container-type: inline-size;
}

.register__item--studio {
	--register-lead-bg: var(--bg);
}

/* 375 px: Titel und Text über die volle Breite, das Pfeilquadrat rechts
   darunter. Neben dem Text blieben bei 320 px nur rund 150 px Satzbreite.
   Innenabstand links = Einzug des Griffs (.75rem) + Griff (6 px) + Luft;
   rechts hält das Pfeilquadrat denselben Abstand zum rechten Griff. */
.register__item--lead .register__link {
	--register-title-fs: clamp(1.75rem, 10.5cqi, 3rem);
	--register-title-lh: calc(var(--register-title-fs) * 1.02);
	--register-go: 2.75rem;
	--notch: var(--register-lead-bg);
	--trim-inset-block: .75rem;
	--trim-inset-start: .75rem;
	--trim-inset-end: .75rem;
	grid-template-columns: minmax(0, 1fr) var(--register-go);
	grid-template-areas:
		"title title"
		"text  text"
		".     go";
	column-gap: 1rem;
	padding: 1.75rem 2rem 1.5rem 2.125rem;
	border-bottom: 0;
	background: var(--register-lead-bg);
}

/* Die Hover-Fläche wäre auf der hellen Zeile gleich ihrem Grund. Dort
   tragen Pfeilquadrat und Titelversatz den Zustand, auf Studio zusätzlich
   die Fläche Studio-2. */
.register__item--lead .register__link::before {
	content: none;
}

.register__item--studio .register__link::before {
	content: "";
}

.register__item--lead .register__title {
	font-size: var(--register-title-fs);
	font-weight: 850;
	font-stretch: var(--w-oton);
	line-height: 1.02;
	letter-spacing: -.01em;
	overflow-wrap: break-word;
}

/* Kein Trennen im Aufmacher: Der Titel ist über cqi so bemessen, dass ein
   Wort wie „Straßenumfragen“ auch bei 320 px in die Zeile passt. */
@media (max-width: 29.99rem) {
	.register__item--lead .register__title {
		-webkit-hyphens: manual;
		hyphens: manual;
	}
}

.register__item--lead .register__text {
	max-width: 48ch;
	margin-top: 1rem;
	font-size: 1.0625rem;
	line-height: 1.6;
}

/* Pfeilquadrat wie in den übrigen Zeilen. */
.register__item--lead .register__go {
	margin-block: .75rem 0;
}

.register__item--lead .register__go svg {
	width: 20px;
	height: 20px;
}

/* Der Fokusring liegt innen, knapp innerhalb der Flächenkante und außerhalb
   der Griffe (die bei .75rem Einzug beginnen). Außen stünde er in der
   Fokusfarbe der Zeile auf dem Sektionsgrund (Studio-Teal #2FAFAF auf
   Kreide 2,4:1). Innen hat er 6,06:1 auf Studio bzw. ≥5,9:1 auf Hell. */
.register__item--lead a.register__link:focus-visible {
	outline-offset: -5px;
}

/* Tablet: Titel und Pfeilquadrat in einer Zeile, der Text darunter. */
@media (min-width: 48rem) {
	.register__item--lead .register__link {
		--register-title-fs: clamp(2.5rem, 8cqi, 4rem);
		--register-go: 3.5rem;
		--trim-inset-block: 1rem;
		--trim-inset-start: 1rem;
		--trim-inset-end: 1rem;
		grid-template-areas:
			"title go"
			"text  go";
		column-gap: 2rem;
		padding: 2.25rem 2.5rem 2.25rem 2.75rem;
	}

	.register__item--lead .register__go {
		align-self: center;
		margin-block: 0;
	}
}

/* Desktop: dasselbe 12er-Raster wie die Zeilen darunter. Der Titel steht in
   1 bis 7 (Einzug für den Griff), der Text ab Spalte 8 auf der Kante des
   Intros, das Pfeilquadrat rechtsbündig in 12 vor dem rechten Griff. */
@media (min-width: 62rem) {
	.register__item--lead .register__link {
		/* Die Grundregel der Aufmacherzeile (zwei Klassen) überstimmt sonst
		   das Raster der einfachen Zeilen, der Text begann dann vor Spalte 8. */
		--register-title-fs: clamp(2.75rem, 6cqi, 4.5rem);
		--register-go: 3.5rem;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		grid-template-areas: none;
		align-items: center;
		column-gap: var(--gap);
		padding: clamp(2.25rem, 3.4vw, 3.25rem) 0;
	}

	.register__item--lead .register__title {
		padding-inline-start: 2.75rem;
	}

	/* Der Text beginnt auf Spalte 8 und reicht bis an die Kante; rechts hält
	   er Platz für Pfeilquadrat, dessen Abstand zum Griff und einen
	   Spaltenabstand frei. In Spalte 12 allein passte das Quadrat zwischen
	   62 und 75rem nicht, der Text lief bei 992 px darunter. */
	.register__item--lead .register__text {
		grid-column: 8 / -1;
		margin-top: 0;
		padding-inline-end: calc(var(--register-go) + 2.75rem + var(--gap));
	}

	.register__item--lead .register__go {
		margin-inline-end: 2.75rem;
	}
}

/* Hell neben dunklen Abschnitten: Folgt die Sektion direkt auf deep oder
   teal, geht ihr direkt voraus oder schließt sie die Seite vor dem dunklen
   Footer ab, stünden zwei Studio-Flächen dicht hintereinander (etwa auf
   Leistungen direkt unter dem dunklen Hero). Dann erbt die Zeile die Tokens
   der Sektion zurück, die sie liest, und steht auf --surface mit Griffen in
   --trim (Teal auf Hell). Geprüft wird im CSS, was tatsächlich ausgegeben
   wurde: Eine Sektion kann leer bleiben, die Baukasten-Daten allein sagen
   nicht, was daneben steht. :where hält die Spezifität bei einer Klasse;
   ohne :has() (ältere Browser) bleibt der Nachfolger-Fall Studio. */
:where(
	.section--bg-deep + .section--services,
	.section--bg-teal + .section--services,
	.section--services:has(+ :is(.section--bg-deep, .section--bg-teal)),
	.section--services:last-child
) .register__item--studio {
	--bg: inherit;
	--surface: inherit;
	--text: inherit;
	--text-soft: inherit;
	--line-ui: inherit;
	--focus: inherit;
	--trim: inherit;
	--ghost-bg-h: inherit;
	--ghost-fg-h: inherit;
	--register-lead-bg: var(--surface);
}

:where(
	.section--bg-deep + .section--services,
	.section--bg-teal + .section--services,
	.section--services:has(+ :is(.section--bg-deep, .section--bg-teal)),
	.section--services:last-child
) .register__item--studio .register__link::before {
	content: none;
}

/* ---------- Stil „image“: Scroll-Snap-Reihe ----------
   Bleibt im Container (kein Anschnitt bis an den Viewportrand). Der Scroller
   ist per tabindex="0" mit der Tastatur scrollbar und trägt ein aria-label. */

.register--image {
	display: flex;
	gap: var(--gap);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	padding-block: .25rem 1rem;
	border-top: 0;
}

.register--image:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 4px;
}

.register__item--image {
	position: relative;
	flex: 0 0 min(22rem, 85%);
	scroll-snap-align: start;
}

.register__media {
	margin: 0 0 1rem;
}

.register__media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	border-radius: var(--r-media);
}

.register__card-title {
	margin: 0;
	font: 700 1.25rem/1.2 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
}

.register__item--image .register__text {
	display: block;
	margin: .5rem 0 0;
}

/* Der Titel-Link ist über den ganzen Eintrag gestreckt. Der Fokusring liegt
   deshalb am gestreckten Pseudo-Element, nach innen versetzt, damit der
   Scroller ihn nicht abschneidet. */
/* FIX: Linienwerte am Link, Linie in --accent-text wie bei Fallstudien-
   Zeile, Post-Karte und Suchtreffer (66, 71, 75); der Zustand schaltet nur
   die Linie ein. */
.register__card-link {
	color: var(--text);
	text-decoration: none;
	text-decoration-color: var(--accent-text);
	text-decoration-thickness: 2px;
	text-underline-offset: .2em;
}

.register__card-link::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--r-media);
}

/* FIX: Hover nur mit echtem Zeiger (auf Touch bliebe die Linie kleben). */
@media (hover: hover) {
	.register__card-link:hover {
		text-decoration-line: underline;
	}
}

.register__card-link:focus-visible {
	outline: none;
	text-decoration-line: underline;
}

.register__card-link:focus-visible::after {
	outline: 2px solid var(--focus);
	outline-offset: -2px;
}

/* ---------- Button unter dem Register ----------
   Regel für Sektions-CTAs: btn--lg, unter 48rem btn--block über die volle
   Breite, ab 48rem in natürlicher Breite. Ab 62rem rechtsbündig unter der
   Liste an der Containerkante (wie pain_points und channel_proof), darunter
   linksbündig. :where hält die Spezifität bei einer Klasse. */
.register__cta {
	margin-top: clamp(2rem, 4vw, 3rem);
}

@media (min-width: 48rem) {
	.register__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

@media (min-width: 62rem) {
	.register__cta {
		justify-content: flex-end;
	}
}

/* ===== 55-stats.css ===== */
/* =========================================================================
   55 stats: Kennzahlen mit Walzenzähler (Besitz: Team C1, Spez. 6.8)

   Keine Kästen, keine Zentrierung: jede Zahl steht linksbündig unter einer
   Haarlinie. Die Walze selbst (.odo, .odo__*) liefert F in 15-odometer.css.
   Farben nur über Tokens; auf Sektion teal sind Wert und Label damit weiß,
   der Text #D5E4E6 (4,82:1).
   FIX aus dem alten Stand: Dort stand der Wert auf teal zuerst in hellem
   Teal (#2FAFAF auf #156A72 = 2,36:1). --text kippt jetzt mit dem Grund.
   ========================================================================= */

/* ---------- Raster ---------- */

/*
 * Spaltenzahl nach Anzahl statt auto-fit: auto-fit mit 14rem ergab zwischen
 * 62 und 75rem drei Spalten und damit bei vier Werten eine verwaiste vierte
 * Zelle (9.9). Die Klasse --count-N setzt das Template.
 *
 * Der Raster ist Größen-Container. Daraus rechnet .stat__value die Breite
 * einer Spalte und begrenzt die Schriftgröße (siehe unten).
 */
.stats__grid {
	--stats-cols: 1;
	--stats-gap: clamp(1.5rem, 3vw, 3rem);
	--stats-fit: 3.5;
	container-type: inline-size;
	display: grid;
	/* FIX: minmax(0, 1fr) statt 1fr, damit keine Zelle vom Inhalt aufgedrückt wird. */
	grid-template-columns: repeat(var(--stats-cols), minmax(0, 1fr));
	column-gap: var(--stats-gap);
	row-gap: 3rem;
	/* list-style-type "" statt none: Safari/VoiceOver behält so die Listenrolle. */
	list-style-type: "";
	margin: 0;
	padding: 0;
}

@media (min-width: 48rem) {
	.stats__grid--count-2,
	.stats__grid--count-4,
	.stats__grid--many {
		--stats-cols: 2;
	}

	/* Drei Werte: drei Spalten statt 2 + 1. */
	.stats__grid--count-3 {
		--stats-cols: 3;
	}
}

/* Ungerade Anzahl über vier im Zweier-Raster: Die letzte Zelle nimmt die
   ganze Zeile, statt allein neben einem leeren Feld zu stehen. */
@media (min-width: 48rem) and (max-width: 74.99rem) {
	.stats__grid--odd > :last-child {
		grid-column: 1 / -1;
	}
}

@media (min-width: 75rem) {
	.stats__grid--count-4 {
		--stats-cols: 4;
	}

	.stats__grid--many {
		--stats-cols: 3;
	}

	/*
	 * Mehr als vier Werte, deren Anzahl nicht durch drei teilbar ist: Ein
	 * reiner Dreier-Raster ließe leere Felder (5, 8, 11) oder eine einzelne
	 * Zelle in der letzten Reihe (7, 10) stehen (9.9). Der Raster bekommt
	 * deshalb sechs Spuren. Eine Zelle belegt zwei davon (Drittel), die
	 * letzten Zellen belegen drei (Hälfte):
	 *   Rest 2 (5, 8, 11): die letzten zwei, also eine Zweierreihe am Ende.
	 *   Rest 1 (7, 10):    die letzten vier, also zwei Zweierreihen am Ende.
	 * Eine Drittelzelle ist so breit wie im Dreier-Raster, --stats-cols
	 * bleibt 3. Die Schriftgröße richtet sich damit nach der schmalsten Zelle
	 * und ist in der ganzen Sektion gleich. Die Reihenfolge der Zellen bleibt
	 * die des Markups (keine dichte Platzierung).
	 */
	.stats__grid--r3-1,
	.stats__grid--r3-2 {
		grid-template-columns: repeat(6, minmax(0, 1fr));
	}

	.stats__grid--r3-1 > *,
	.stats__grid--r3-2 > * {
		grid-column: span 2;
	}

	.stats__grid--r3-1 > :nth-last-child(-n + 4),
	.stats__grid--r3-2 > :nth-last-child(-n + 2) {
		grid-column: span 3;
	}
}

/* Breite der breitesten Wertzeile in em, vom Template geschätzt (Stufen).
   Die Stufen reichen bis 12 em (bei 320 px noch rund 24 px Schrift). Eine
   noch längere Zeile bekommt keine Stufe, sondern .stat__value--wrap. */
.stats__grid--fit-40 { --stats-fit: 4; }
.stats__grid--fit-45 { --stats-fit: 4.5; }
.stats__grid--fit-50 { --stats-fit: 5; }
.stats__grid--fit-55 { --stats-fit: 5.5; }
.stats__grid--fit-60 { --stats-fit: 6; }
.stats__grid--fit-70 { --stats-fit: 7; }
.stats__grid--fit-80 { --stats-fit: 8; }
.stats__grid--fit-90 { --stats-fit: 9; }
.stats__grid--fit-100 { --stats-fit: 10; }
.stats__grid--fit-120 { --stats-fit: 12; }

/* ---------- Zelle ---------- */

.stat {
	min-width: 0;
	padding-top: 1.5rem;
	border-top: 1px solid var(--line);
}

.stat__value {
	margin: 0;
	font: 820 var(--fs-num)/1 var(--font-display);
	/*
	 * Obergrenze: Spaltenbreite geteilt durch die Breite der längsten Zeile.
	 * „300.000“ misst 4,13 em und wäre bei 72 px im Vierer-Raster ab 75rem
	 * (Zelle rund 250 px) breiter als seine Spalte. Ohne Container-Einheiten
	 * bleibt die erste Deklaration stehen.
	 */
	font-size: min(var(--fs-num), (100cqi - (var(--stats-cols) - 1) * var(--stats-gap)) / var(--stats-cols) / var(--stats-fit));
	font-stretch: var(--w-num);
	font-variant-numeric: tabular-nums lining-nums;
	color: var(--text);
	/* Die Zahl bricht nie um, auch nicht zwischen „+“ und Ziffer. */
	white-space: nowrap;
}

/*
 * FIX: Wertzeile länger als die höchste Stufe (12 em, praktisch nur ein Satz
 * im Zahlenfeld). Schrift nach ihrer Breite zu begrenzen, ergäbe winzige
 * Zahlen, nowrap ohne Begrenzung einen seitlichen Überlauf (9.2). Sie darf
 * deshalb umbrechen. .odo (F) setzt selbst nowrap und muss mit. anywhere
 * statt break-word: Nur so zählt die Umbruchstelle für die Mindestbreite des
 * inline-block, sonst bliebe er so breit wie sein längstes Wort. Das
 * Template schaltet für diesen Wert die Walze ab, weil sie eine Zeile
 * braucht. :where hält die Spezifität bei einer Klasse.
 */
.stat__value--wrap,
.stat__value--wrap > :where(.odo) {
	white-space: normal;
	overflow-wrap: break-word;
	overflow-wrap: anywhere;
}

/* Präfix-Zeichen und Suffix in halber Größe auf der Grundlinie der Zahl. */
.stat__affix {
	font-size: .5em;
	font-weight: 700;
	vertical-align: baseline;
}

/* Präfix mit Wort („über “): eigene Zeile über der Zahl (6.8). */
.stat__affix--word {
	display: block;
	margin-bottom: .5rem;
	font: 600 var(--fs-small)/1.35 var(--font-text);
	color: var(--text-soft);
	white-space: normal;
}

/* Hat eine Zelle der Sektion eine Präfixzeile, rücken die Zahlen ohne
   Präfix im Mehrspalter um genau diese Zeile nach unten. So stehen alle
   Zahlen einer Reihe auf derselben Grundlinie. Einspaltig entfällt das. */
@media (min-width: 48rem) {
	.stat__value--pad::before {
		content: "";
		display: block;
		height: calc(var(--fs-small) * 1.35 + .5rem);
	}
}

.stat__label {
	margin: .75rem 0 0;
	font: 650 1.125rem/1.3 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
	/* FIX: Ein langes zusammengesetztes Wort darf die schmale Zelle nicht
	   sprengen. overflow-wrap setzt keinen Trennstrich und greift nur, wenn
	   ein Wort wirklich nicht in die Zeile passt. */
	overflow-wrap: break-word;
}

.stat__text {
	max-width: 32ch;
	margin: .5rem 0 0;
	font-size: 1rem;
	line-height: 1.55;
	color: var(--text-soft);
}

/* ---------- Gemeinsames Zeilenraster im Mehrspalter ----------
   Wert, Label und Text einer Reihe liegen je auf einer Höhe. Ein
   zweizeiliges Label („Follower bei Herr Neugierig auf Instagram“) schob
   seinen Text sonst eine Zeile tiefer als die Nachbarn. Das Label bleibt
   oben in seiner Zeile, direkt unter der Zahl; der Ausgleich fällt unter
   das kürzere Label. Einspaltig (unter 48rem) und ohne subgrid bleibt es
   beim Satz untereinander.
   Der Reihenabstand wandert vom row-gap des Rasters in einen Außenabstand
   der Zellen: Ein Subgrid erbt das row-gap auch zwischen Wert, Label und
   Text. Mit row-gap 0 nur im Subgrid verteilte Chrome die Differenz auf
   die Spuren, das Label rückte rund 20 px vom Text ab. Der negative
   Außenabstand des Rasters hebt den Abstand unter der letzten Reihe auf. */
@supports (grid-template-rows: subgrid) {
	@media (min-width: 48rem) {
		.stats__grid {
			row-gap: 0;
			margin-bottom: -3rem;
		}

		.stat {
			display: grid;
			grid-row: span 3;
			grid-template-rows: subgrid;
			align-content: start;
			margin-bottom: 3rem;
		}

		/* Zahlen stehen unten in ihrer Zeile und damit je Reihe auf einer
		   Grundlinie, auch neben einer Präfixzeile („über“). Das ersetzt den
		   Platzhalter aus .stat__value--pad: Der rückte bisher im 2 × 2-Raster
		   auch Reihen ohne jedes Präfix um eine Zeile nach unten. */
		.stat__value {
			grid-row: 1;
			align-self: end;
		}

		.stat__value--pad::before {
			content: none;
		}

		.stat__label {
			grid-row: 2;
		}

		.stat__text {
			grid-row: 3;
		}
	}
}

/* ---------- Vier Werte: Leitzahl plus drei Belegzeilen ----------
   ABWEICHUNG von 6.8 (Raster mit vier gleichen Spalten): Art-Director-Befund
   „gleiches Schema auf jeder Sektion“. Vier gleiche Spalten standen auf
   ueber-uns, recruiting-videos, reels-agentur, messe-content und
   unsere-kanaele, dort direkt nach channel_proof mit der großen Leitkennzahl
   und drei Zahlen in Spalten darunter. Jetzt steht die erste Zahl als
   Leitzahl links, die übrigen drei als Zeilen rechts (Zahl, daneben
   Bezeichnung und Text). Die Klassen setzt stats.php nur bei genau vier
   Werten.
   Aufbau je Breite:
     unter 48rem  alles untereinander, Leitzahl groß, Zeilenzahlen kleiner
     48–62rem     Leitzahl über die Breite, darunter die drei Zeilen
     ab 62rem     Leitzahl links (5 Teile), Zeilen rechts (Zahl + 6 Teile)
   Walzen, Präfix- und Suffixregeln gelten unverändert. :where hält jede
   Regel bei einer Klasse (8.5, Regel 4); sie stehen nach dem Spaltenraster
   und gewinnen über die Reihenfolge. */

.stats__grid--lead {
	row-gap: 2rem;
}

/* Die Leitzahl ist ihr eigener Größen-Container: Die Obergrenze der
   Schriftgröße rechnet mit ihrer Spalte, nicht mit dem ganzen Raster. */
.stat--lead {
	--stat-fit: 3.5;
	container-type: inline-size;
}

.stat--fit-15 { --stat-fit: 1.5; }
.stat--fit-20 { --stat-fit: 2; }
.stat--fit-25 { --stat-fit: 2.5; }
.stat--fit-30 { --stat-fit: 3; }
.stat--fit-35 { --stat-fit: 3.5; }
.stat--fit-40 { --stat-fit: 4; }
.stat--fit-45 { --stat-fit: 4.5; }
.stat--fit-50 { --stat-fit: 5; }
.stat--fit-55 { --stat-fit: 5.5; }
.stat--fit-60 { --stat-fit: 6; }
.stat--fit-70 { --stat-fit: 7; }
.stat--fit-80 { --stat-fit: 8; }
.stat--fit-90 { --stat-fit: 9; }
.stat--fit-100 { --stat-fit: 10; }
.stat--fit-120 { --stat-fit: 12; }

/* Unter 48rem mindestens 4.5rem (Token --fs-num-lead beginnt bei 3.5rem),
   damit die Leitzahl neben den gestapelten Zeilenzahlen (2rem) klar führt.
   Die Obergrenze aus der Spaltenbreite gilt immer. */
.stat--lead > :where(.stat__value) {
	font-size: min(max(var(--fs-num-lead), 4.5rem), 100cqi / var(--stat-fit));
}

.stat--lead > :where(.stat__label) {
	margin-top: 1rem;
	font-size: clamp(1.1875rem, 1rem + .6vw, 1.5rem);
	line-height: 1.25;
}

.stat--lead > :where(.stat__text) {
	max-width: 38ch;
	font-size: var(--fs-body);
}

/* Zeilenzahlen: kleiner als die Leitzahl, aber noch Zahl, nicht Fließtext.
   Gestapelt (unter 48rem) begrenzt die Rasterbreite, daneben (ab 48rem)
   höchstens ein Drittel davon, damit die Bezeichnung Platz behält. */
.stat--row > :where(.stat__value) {
	font-size: min(var(--fs-num-s), 100cqi / var(--stats-fit));
}

.stat--row > :where(.stat__label) {
	margin-top: .625rem;
}

@media (min-width: 48rem) {
	.stats__grid--lead {
		grid-template-columns: minmax(0, calc(var(--stats-fit) * var(--fs-num-s))) minmax(0, 1fr);
		column-gap: clamp(1.5rem, 3vw, 2.5rem);
		row-gap: 0;
		margin-bottom: 0;
	}

	.stats__grid--lead > :where(.stat) {
		grid-row: auto;
		margin-bottom: 0;
	}

	.stats__grid--lead > :where(.stat--lead) {
		display: block;
		grid-column: 1 / -1;
		padding-bottom: 2.5rem;
	}

	/* Zeile: Zahl links, Bezeichnung auf der Grundlinie der Zahl daneben, der
	   Text darunter. Ohne subgrid ist die Zahlenspalte so breit wie die
	   breiteste Zahl der Sektion laut Schätzung (--stats-fit). */
	.stats__grid--lead > :where(.stat--row) {
		display: grid;
		grid-column: 1 / -1;
		grid-template-columns: minmax(0, calc(var(--stats-fit) * var(--fs-num-s))) minmax(0, 1fr);
		grid-template-rows: auto auto;
		column-gap: clamp(1.5rem, 3vw, 2.5rem);
		padding-block: 1.25rem 1.5rem;
	}

	.stat--row > :where(.stat__value) {
		grid-column: 1;
		grid-row: 1 / span 2;
		align-self: start;
		font-size: min(var(--fs-num-s), 100cqi * .3 / var(--stats-fit));
	}

	.stat--row > :where(.stat__label) {
		grid-column: 2;
		grid-row: 1;
		margin: 0;
	}

	.stat--row > :where(.stat__text) {
		grid-column: 2;
		grid-row: 2;
		max-width: 44ch;
	}
}

/* Mit subgrid teilen sich die drei Zeilen die Zahlenspalte des Rasters:
   Sie ist genau so breit wie die breiteste Zeilenzahl, einstellige Werte
   („5 Mitarbeitende“) stehen nicht vor einer Lücke. Die Bezeichnung sitzt
   auf der letzten Grundlinie der Zahl, auch unter einer Präfixzeile
   („über“). Ohne last baseline gilt end, das trifft die Grundlinie bis auf
   die Unterlänge. */
@supports (grid-template-columns: subgrid) {
	@media (min-width: 48rem) {
		.stats__grid--lead {
			grid-template-columns: max-content minmax(0, 1fr);
		}

		.stats__grid--lead > :where(.stat--row) {
			grid-template-columns: subgrid;
		}

		.stat--row > :where(.stat__value) {
			grid-row: 1;
			align-self: end;
			align-self: last baseline;
		}

		.stat--row > :where(.stat__label) {
			align-self: end;
			align-self: last baseline;
		}
	}
}

/* Ab 62rem liegt alles auf dem 12er-Raster des Sektionskopfs (ohne subgrid,
   gleiche Spuren wie .grid-12): Leitzahl in den Spalten 1–4, Zeilen in
   5–12. In der Zeile stehen die Zahlen rechtsbündig in 5–7 (tabellarische Ziffern, Einer unter Einern) und
   hängen an der Kante von Spalte 8. Dort beginnen Bezeichnung und Text,
   bündig mit dem Intro des split-Kopfs darüber (4.3). */
@media (min-width: 62rem) {
	.stats__grid--lead {
		grid-template-columns: repeat(12, minmax(0, 1fr));
		grid-template-rows: repeat(3, auto);
		column-gap: var(--gap);
	}

	.stats__grid--lead > :where(.stat--lead) {
		grid-column: 1 / span 4;
		grid-row: 1 / span 3;
		padding-bottom: 0;
	}

	.stats__grid--lead > :where(.stat--row) {
		grid-column: 5 / -1;
		grid-template-columns: repeat(8, minmax(0, 1fr));
		column-gap: var(--gap);
	}

	.stat--row > :where(.stat__value) {
		grid-column: 1 / span 3;
		justify-self: end;
		text-align: end;
	}

	.stat--row > :where(.stat__label),
	.stat--row > :where(.stat__text) {
		grid-column: 4 / -1;
	}
}

/* Nur kurze Zeilenzahlen (Klasse aus stats.php): Leitzahl in 1–5, Zeilen in
   6–12, Zahl rechtsbündig in 6–7. Die Kante von Spalte 8 bleibt. :where hält
   die Spezifität bei einer Klasse, die Regel steht nach der allgemeinen. */
@media (min-width: 62rem) {
	.stats__grid--short-rows > :where(.stat--lead) {
		grid-column: 1 / span 5;
	}

	.stats__grid--short-rows > :where(.stat--row) {
		grid-column: 6 / -1;
		grid-template-columns: repeat(7, minmax(0, 1fr));
	}

	.stats__grid--short-rows :where(.stat--row > .stat__value) {
		grid-column: 1 / span 2;
	}

	.stats__grid--short-rows :where(.stat--row > .stat__label, .stat--row > .stat__text) {
		grid-column: 3 / -1;
	}
}

/* ===== 56-versus.css ===== */
/* =========================================================================
   56 · versus: Gegenüberstellung Firma 1 / Firma 2 (Kundenfeedback 02.10.2026)
   Oben das Vergleichsbild, darunter je Seite eine Liste. Links roter Punkt
   (was schiefläuft), rechts grüner Haken (was funktioniert). Die rechte
   Spalte ist der „ausgewählte Clip“ wie Spalte B im Vergleich (61): Fläche
   --surface, Text in voller Stärke. Farbe ist nie allein das Signal: Punkt
   und Haken unterscheiden sich in der Form, die Spalten tragen Titel.
   Genutzt von: sections/versus.php
   ========================================================================= */

.versus__figure {
	margin: 0 0 clamp(2rem, 4vw, 3rem);
}

.versus__img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--r-media);
}

.versus__cols {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 1rem;
}

.versus__col {
	padding: clamp(1.25rem, 3vw, 2rem);
	border-top: 2px solid var(--line);
}

.versus__col--bad {
	border-top-color: var(--error);
}

.versus__col--good {
	background: var(--surface);
	border-top-color: var(--ok);
}

.versus__label {
	margin: 0 0 1rem;
	font: 700 var(--fs-h3)/1.15 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
}

.versus__list {
	list-style-type: "";
	margin: 0;
	padding: 0;
	display: grid;
	gap: .875rem;
}

.versus__point {
	display: grid;
	grid-template-columns: 1.25rem minmax(0, 1fr);
	column-gap: .75rem;
	align-items: start;
	font-size: var(--fs-body);
	line-height: 1.5;
}

.versus__col--bad .versus__point {
	color: var(--text-soft);
}

.versus__col--good .versus__point {
	color: var(--text);
	font-weight: 500;
}

/* Symbol mittig zur ersten Zeile (1.5 × 17 px ≈ 25,5 px Zeilenhöhe). */
.versus__mark {
	width: 1.25rem;
	height: 1.25rem;
	margin-top: calc((1.5em - 1.25rem) / 2);
}

.versus__mark--bad {
	fill: var(--error);
}

.versus__mark--good {
	color: var(--ok);
}

.versus__cta {
	margin-top: clamp(2rem, 4vw, 3rem);
}

/* Ab 48rem nebeneinander, jede Liste unter ihrer Bildhälfte. */
@media (min-width: 48rem) {
	.versus__cols {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: clamp(1.5rem, 4vw, 4rem);
	}

	.versus__cta .btn--block {
		width: auto;
	}
}

/* ===== 57-formats.css ===== */
/* =========================================================================
   57 · formats: Erfolgsformate (Kundenfeedback 02.10.2026, OnePager 2026)
   Hochformatbild in Farbe, Titel, ein Satz, zwei Links. Loom vom
   06.10.2026: Slider statt langer Liste (Komponente 44-slider.css), die
   Details stehen auf den Leistungsseiten.
   Genutzt von: sections/formats.php
   ========================================================================= */

/* Slide-Breite: bei 1440 px stehen gut vier Formate im Blick, das fünfte
   ist angeschnitten und zeigt, dass es weitergeht. */
.formats__slider {
	--slider-w: min(17rem, 78vw);
	--slider-gap: var(--gap);
}

.formats__item {
	display: flex;
	flex-direction: column;
	align-self: stretch;
}

.formats__media {
	margin: 0 0 1.125rem;
}

.formats__media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	border-radius: var(--r-media);
}

/* Kachel ohne Foto: Studio-Grund, die drei Pixelquadrate aus dem Logo oben
   links, das Symbol groß in Signal-Teal (6,06:1 auf Studio). Gleiches 4:5
   wie die Fotos, damit die Reihe geschlossen bleibt. */
.formats__tile {
	position: relative;
	display: grid;
	place-items: center;
	aspect-ratio: 4 / 5;
	border-radius: var(--r-media);
	background:
		radial-gradient(120% 90% at 85% 100%, var(--c-studio-2) 0%, transparent 60%),
		var(--c-studio);
	color: var(--c-signal);
}

.formats__tile-pixels {
	position: absolute;
	top: 1.25rem;
	left: 1.25rem;
	display: grid;
	grid-template-columns: repeat(2, 8px);
	gap: 4px;
}

.formats__tile-pixels i {
	display: block;
	width: 8px;
	height: 8px;
	border-radius: 1px;
	background: var(--c-signal);
}

.formats__tile-pixels i:first-child {
	grid-column: 2;
}

.formats__tile-icon {
	width: 38%;
	height: auto;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.25;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.formats__title {
	margin: 0;
	font: 700 1.25rem/1.2 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
}

.formats__text {
	margin: .5rem 0 0;
	font-size: var(--fs-small);
	line-height: 1.55;
	color: var(--text-soft);
}

.formats__incl {
	margin: 1.125rem 0 .5rem;
	font: 500 var(--fs-mono)/1.3 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text);
}

.formats__bullets {
	list-style-type: "";
	display: grid;
	gap: .375rem;
	margin: 0;
	padding: 0;
	font-size: var(--fs-small);
	line-height: 1.45;
	color: var(--text);
}

/* Pixelquadrat statt Aufzählungspunkt (Rahmenmarken-Farbe, 5.4). */
.formats__bullets li {
	position: relative;
	padding-inline-start: 1rem;
}

.formats__bullets li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: calc((1.45em - 6px) / 2);
	width: 6px;
	height: 6px;
	background: var(--mark);
}

/* Links unten bündig, auch wenn Texte unterschiedlich lang sind. */
.formats__links {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .5rem;
	margin: auto 0 0;
	padding-top: 1.25rem;
	font-size: var(--fs-small);
}

.formats__example {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	min-height: 1.5rem; /* Zielgröße 24 px (WCAG 2.5.8) */
	color: var(--text);
	font-weight: 500;
	text-decoration: underline;
	text-decoration-color: var(--line-ui);
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

.formats__example:hover {
	text-decoration-color: currentColor;
}

.formats__example svg {
	flex: none;
	width: 14px;
	height: 14px;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* Abschluss: Satz links, Button daneben (ab 62rem), darunter gestapelt. */
.formats__close {
	display: grid;
	gap: 1.25rem;
	margin-top: clamp(2.5rem, 5vw, 3.5rem);
	padding-top: clamp(1.5rem, 3vw, 2rem);
	border-top: 1px solid var(--line);
}

.formats__close-text {
	max-width: 46ch;
	margin: 0;
	font: 600 var(--fs-lead)/1.45 var(--font-text);
	color: var(--text);
}

@media (min-width: 62rem) {
	.formats__close--text {
		grid-template-columns: minmax(0, 1fr) auto;
		align-items: center;
		column-gap: var(--gap);
	}
}

@media (min-width: 48rem) {
	.formats__cta .btn--block {
		width: auto;
	}
}

/* Abzeichen am Titel („Neu“ bei Influencer Collaborations), wie im
   Megamenü (31-megamenu.css). */
.formats__badge {
	display: inline-block;
	margin-left: .25rem;
	padding: .15rem .4rem;
	border-radius: var(--r-plate);
	background: var(--c-teal-ink);
	color: var(--c-white);
	font: 500 .6875rem/1.3 var(--font-mono);
	letter-spacing: .04em;
	vertical-align: .2em;
}

/* ===== 58-locations.css ===== */
/* =========================================================================
   58 · locations: Standorte (Kundenfeedback 02.10. und 15.10.2026)
   Je Land eine Fläche mit Flagge, Name und Anzahl, darin die Städte im
   Spaltensatz. Jede Stadt trägt ein kleines Pixelquadrat aus dem Logo,
   der Sitz (Hamburg) ist als „Unser Sitz“ markiert und verlinkt.
   Linksbündig wie alle Köpfe der Startseite. Farben aus den Tokens.
   Genutzt von: sections/locations.php
   ========================================================================= */

.locations {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--gap);
}

.locations__group {
	padding: clamp(1.5rem, 3vw, 2.25rem);
	border-radius: var(--r-panel);
	background: var(--surface);
}

.locations__country {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem .75rem;
	margin: 0 0 1.25rem;
	padding-bottom: 1rem;
	border-bottom: 1px solid var(--line);
	font: 700 var(--fs-h3)/1.15 var(--font-display);
	font-stretch: 100%;
	color: var(--text);
}

/* Flaggen mit feiner Kontur, damit das Weiß der Schweizer Flagge und das
   Schwarz der deutschen auf jedem Grund eine Kante haben. */
.locations__flag {
	flex: none;
	width: 2.25rem;
	height: auto;
	aspect-ratio: 5 / 3;
	border-radius: 2px;
	box-shadow: 0 0 0 1px var(--line);
}

.locations__flag--square {
	width: 1.6rem;
	aspect-ratio: 1;
}

.locations__count {
	margin-left: auto;
	font: 500 var(--fs-mono)/1.3 var(--font-mono);
	letter-spacing: .04em;
	color: var(--text-soft);
}

.locations__list {
	list-style-type: "";
	margin: 0;
	padding: 0;
	columns: 2;
	column-gap: var(--gap);
}

.locations__city {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .25rem .5rem;
	break-inside: avoid;
	padding: .45rem 0;
	font: 500 var(--fs-body)/1.35 var(--font-text);
	color: var(--text);
}

/* Pixelquadrat vor jeder Stadt (Markenmotiv aus dem Logo). */
.locations__city::before {
	content: "";
	flex: none;
	width: 6px;
	height: 6px;
	border-radius: 1px;
	background: var(--mark);
}

.locations__link {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	min-height: 1.5rem;
	color: var(--accent-text);
	font-weight: 600;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

.locations__link:hover {
	text-decoration-thickness: 2px;
}

.locations__link svg {
	flex: none;
	width: 16px;
	height: 16px;
}

.locations__badge {
	display: inline-block;
	padding: .125rem .4rem;
	border-radius: var(--r-plate);
	background: var(--l3-name-bg);
	color: var(--l3-name-fg);
	font: 500 .75rem/1.3 var(--font-mono);
	letter-spacing: .02em;
}

/* Kleine Gruppen (Schweiz, Österreich): Städte untereinander. */
.locations__group:not(.locations__group--de) .locations__list {
	columns: 1;
}

@media (min-width: 48rem) {
	.locations__group--de .locations__list {
		columns: 3;
	}
}

@media (min-width: 62rem) {
	.locations:has(.locations__group:nth-child(2)) {
		grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
		align-items: start;
	}

	.locations__group--de .locations__list {
		columns: 4;
	}
}

/* ===== 60-testimonials.css ===== */
/* =========================================================================
   60 · testimonials: O-Ton-Satz (Spez. 6.11)
   Kundenstimmen stehen wie O-Töne im Satz, nicht als Karten: kein Rahmen,
   kein Schatten, keine Sprechblasenspitze. Name und Rolle kommen als
   Bauchbinde (.l3, Team F). Grammatik: Bauchbinde. Kein Signaturelement.
   Genutzt von: sections/testimonials.php, components/testimonial-card.php
   (auch im Formular und in der Fallstudie).
   ========================================================================= */

/* ---------- Bewertungssiegel unter dem Intro ----------
   smm_section_header() gibt den Kopf geschlossen aus, die Siegel können also
   nicht in dessen Intro-Spalte stehen. Sie folgen dem Kopf und rücken per
   negativem Rand an das Intro heran: Die Ränder fallen zusammen
   (--head-gap + 1.25rem − --head-gap = 1.25rem), darunter bleibt der
   normale Abstand zum Inhalt. Ab 62rem legt dasselbe 12er-Raster wie
   im split-Kopf (05-section-header.css: Titel 1–7, Intro 8–12, --gap) die
   Siegel exakt unter die Intro-Spalte. */
.testimonials__badges {
	margin-top: calc(1.25rem - var(--head-gap));
	margin-bottom: var(--head-gap);
}

/* Ohne Kopf gibt es keinen Rand, mit dem der negative zusammenfallen könnte. */
.testimonials__badges--top {
	margin-top: 0;
}

.testimonials__badges .review-badges {
	display: flex;
	flex-wrap: wrap;
	gap: .25rem 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.testimonials__badges .review-badges__item,
.testimonials__badges .review-badges__item > a {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .25rem .5rem;
	color: var(--text-soft);
	font: 400 var(--fs-small)/1.35 var(--font-text);
}

/* FIX: Das Siegel ist ein eigenständiger Link. 44 px Zielhöhe statt der
   Zeilenhöhe von rund 20 px (WCAG 2.5.8). */
.testimonials__badges .review-badges__item > a {
	min-height: 2.75rem;
	text-decoration: none;
}

.testimonials__badges .review-badges__platform {
	color: var(--text);
	font-weight: 700;
}

/* Klein und sachlich, aber als Link erkennbar: Unterstreichung am Namen.
   Nicht am Link selbst: Eine Unterstreichung am Link erbt jedes Kind, ein
   Kind kann sie nicht zurücknehmen, sie liefe also auch unter Sternen und
   Wert. :where(:hover) hält die Spezifität bei zwei Klassen (Spez. 8.5,
   Regel 4); die Hover-Regel steht deshalb nach der Grundregel. */
.testimonials__badges a .review-badges__platform {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

.testimonials__badges a:where(:hover) .review-badges__platform {
	text-decoration-thickness: 2px;
}

/* FIX: Die Regeln für .stars svg und .review-badges__score sind entfallen.
   Das Siegel nennt keine Durchschnittsnote mehr und zeigt keine Sterne: In
   einer Sammelanzeige stünden beide für einen Durchschnitt, der nirgends
   belegt ist. Die echten fünf Sterne stehen an jeder einzelnen Stimme. */

/* Ruhiger Trenner zwischen Portalname und Anzahl, rein dekorativ. */
.testimonials__badges .review-badges__count::before {
	content: "·";
	margin-inline-end: .5rem;
}

/* Die Anzahl ist ein echter Wert, deshalb Mono (Spez. 1, Regel 3). Das Wort
   daneben bleibt Schibsted. */
.testimonials__badges .review-badges__num {
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	font-variant-numeric: tabular-nums;
	color: var(--text);
}

@media (min-width: 62rem) {
	.testimonials__badges {
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--gap);
	}

	.testimonials__badges > .review-badges {
		grid-column: 8 / -1;
	}

	/* Kopf ohne Intro oder gar kein Kopf: Siegel unter den Titel, sonst
	   stünden sie rechts neben einer leeren Spalte. */
	.testimonials__badges--under-title > .review-badges,
	.testimonials__badges--top > .review-badges {
		grid-column: 1 / span 7;
	}
}

/* ---------- Satz ----------
   ABWEICHUNG von 6.11 (columns: 1/2/3), nach Sichtprüfung: Der Spaltensatz
   mit break-inside: avoid gleicht die Spalten auf die kleinste Höhe aus und
   ließ bei 4, 5, 7, 8 oder 10 Stimmen ein Loch von rund einer Stimmenhöhe
   stehen (5 Stimmen bei 1440 px: 2/1/2, Loch unter der Mittelspalte). Das
   verstößt gegen 9.9. Stattdessen ein Raster, dessen Zeilen immer voll sind:
   - unter 48rem eine Spalte,
   - 48 bis 75rem zwei Spalten; bei ungerader Anzahl steht die erste Stimme
     als Aufmacher über beiden Spalten, darunter nur volle Zweierzeilen,
   - ab 75rem drei Stimmen je Zeile auf sechs Rasterspalten; bleiben am Ende
     zwei übrig, teilen sie sich die Zeile, bleibt eine übrig, stehen die
     letzten vier als 2 + 2.
   Die Aufteilung folgt allein aus :nth-child/:nth-last-child, das Template
   braucht keinen Zähl-Modifier. DOM-Reihenfolge = Lesefolge zeilenweise.
   :where() hält jede Regel bei einer Klasse (Spez. 8.5, Regel 4); wo Regeln
   gleich schwer sind, entscheidet die Reihenfolge. */
.oton-set {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	row-gap: 2rem;
	align-items: start;
}

/* Eine einzelne Stimme liefe sonst über die volle Containerbreite. */
.oton-set > :only-child {
	max-width: var(--measure);
}

@media (min-width: 48rem) {
	.oton-set {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 3.5rem clamp(2rem, 4vw, 4rem);
	}

	/* Ungerade Anzahl (die erste ist von hinten gezählt ungerade): Aufmacher
	   über beide Spalten, auf Lesebreite begrenzt. So bleibt weder ein Loch
	   noch eine verwaiste Stimme am Ende. */
	.oton-set > :where(:first-child:nth-last-child(odd)) {
		grid-column: 1 / -1;
		max-width: var(--measure);
	}
}

@media (min-width: 75rem) {
	.oton-set {
		grid-template-columns: repeat(6, minmax(0, 1fr));
	}

	.oton-set > :where(.oton) {
		grid-column: span 2;
		max-width: none;
	}

	/* Rest 2 (2, 5, 8, 11 Stimmen): die letzten zwei teilen sich die Zeile.
	   Rest 1 (4, 7, 10 Stimmen): die letzten vier stehen als 2 + 2. */
	.oton-set > :where(
		:nth-child(3n+1):nth-last-child(2),
		:nth-child(3n+1):nth-last-child(2) ~ *,
		:nth-child(3n+1):nth-last-child(4),
		:nth-child(3n+1):nth-last-child(4) ~ *
	) {
		grid-column: span 3;
	}

	.oton-set > :where(:only-child) {
		grid-column: 1 / -1;
	}
}

/* Bauchbinden auf einer Linie: Ab 48rem übernimmt jede Stimme die Zeilen
   des Satzes (subgrid) für Sterne, Zitat, Ergebnis und Fuß. Das längste
   Zitat einer Zeile bestimmt die Zitatzeile, alle Bauchbinden der Zeile
   stehen damit auf derselben Oberkante wie ein eingeblendeter Namenszug.
   Der Satz hat dafür keinen Zeilenabstand: Ein Subgrid erbt die Fugen
   zwischen seinen Spuren, jede (auch leere) Spur trüge sonst 3.5rem in die
   Stimme hinein. Den Abstand zwischen den Stimmen trägt deshalb ihr
   unterer Rand, den der Satz am Ende per negativem Rand wieder abgibt.
   Ohne subgrid-Unterstützung gilt das Raster oben mit row-gap, die Stimmen
   stehen oben bündig. */
@supports (grid-template-rows: subgrid) {
	@media (min-width: 48rem) {
		.oton-set {
			row-gap: 0;
			margin-bottom: -3.5rem;
		}

		.oton-set > .oton {
			display: grid;
			grid-template-rows: subgrid;
			grid-row: span 4;
			row-gap: 0;
			margin-bottom: 3.5rem;
		}

		.oton-set .stars {
			grid-row: 1;
		}

		.oton-set .oton__quote {
			grid-row: 2;
		}

		.oton-set .oton__result {
			grid-row: 3;
		}

		.oton-set .oton__foot {
			grid-row: 4;
			align-self: start;
		}
	}
}

/* 375 px: eine Spalte, zwischen den Stimmen eine Linie. Nur unterhalb von
   48rem: Im mehrspaltigen Raster stünde die Linie versetzt über einzelnen
   Stimmen. Nebeneinander stehende .oton gibt es nur im Satz; Slider,
   Formular und Fallstudie setzen jede Stimme einzeln. */
@media (max-width: 47.99rem) {
	.oton + .oton {
		padding-top: 2rem;
		border-top: 1px solid var(--line);
	}
}

/* ---------- Stimme ---------- */
.oton {
	/* FIX: figure bringt im Browser 40 px Seitenrand mit (alte Basisregel). */
	margin: 0;
	/* FIX: Ohne min-width: 0 dehnt ein langes Wort das Raster-Element auf. */
	min-width: 0;
	color: var(--text);
}

.oton > .stars {
	display: flex;
	width: fit-content;
	margin-bottom: 1rem;
}

.oton > .stars svg {
	width: 16px;
	height: 16px;
}

/* Zitat mit hängendem „: Der Textblock fluchtet mit Sternen und Bauchbinde,
   das Anführungszeichen steht davor im Spaltenabstand. */
.oton__quote {
	margin: 0;
	font: 400 var(--fs-body)/1.6 var(--font-text);
	text-indent: -.42em;
	text-wrap: pretty;
	/* FIX: bricht nur, wenn ein Wort wirklich nicht in die Spalte passt. */
	overflow-wrap: break-word;
}

.oton__quote::before {
	content: "„";
}

.oton__quote::after {
	content: "“";
}

/* kurz: der O-Ton selbst, schmal und schwer */
.oton--kurz .oton__quote {
	font: 650 clamp(1.375rem, 1.1rem + 1vw, 1.875rem)/1.2 var(--font-display);
	font-stretch: 88%;
	letter-spacing: -.005em;
}

.oton--mittel .oton__quote {
	font: 500 1.1875rem/1.5 var(--font-text);
}

.oton--lang .oton__quote {
	font: 400 1.0625rem/1.6 var(--font-text);
}

/* Im Slider liegt die Stimme in einem Scroll-Container, der das hängende
   Zeichen am Rand abschneiden würde. */
.oton--no-hang .oton__quote {
	text-indent: 0;
}

/* 375 px: Das hängende „ stand nur rund 11 px vom Bildschirmrand, halb im
   18-px-Gutter. Unter 48rem steht es deshalb im Satz. */
@media (max-width: 47.99rem) {
	.oton__quote {
		text-indent: 0;
	}
}

/* Ergebnis: echte Zahl, deshalb Mono auf einer kleinen Tafel. */
.oton__result {
	display: flex;
	align-items: center;
	gap: .375rem;
	width: fit-content;
	max-width: 100%;
	margin-top: 1rem;
	padding: .25rem .5rem;
	border-radius: var(--r-plate);
	background: var(--surface);
	color: var(--text);
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
}

/* Trend-Icon per Klasse statt Inline-Style */
.oton__trend {
	flex: none;
	width: 13px;
	height: 13px;
	color: var(--accent-text);
}

/* Fuß: Avatar · Bauchbinde · Logo, darunter die Quelle.
   Flex statt des Rasters „auto 1fr auto“: Avatar und Logo sind optional,
   ein Raster hätte bei fehlendem Avatar die Bauchbinde in die schmale
   auto-Spalte geschoben und eine leere Lücke stehen lassen. */
.oton__foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .75rem;
	margin-top: 1.25rem;
}

.oton__avatar {
	flex: none;
	width: 44px;
	height: 44px;
	border-radius: var(--r-round);
	object-fit: cover;
}

/* Die Bauchbinde ist so breit wie ihr Text. Mit flex: 1 1 11rem dehnte
   sie sich auf den freien Platz links vom Logo; brach die Rolle um, lief die
   helle Rollentafel dann mit 30 bis 80 px Leerfläche bis ans Logo. */
.oton__foot > .l3 {
	flex: 0 1 auto;
	min-width: 0;
}

/* Rolle und Firma stehen je in einer Zeile (testimonial-card.php trennt
   sie mit einem Zeilenumbruch). Ein umbrechender Kasten wird so breit wie
   der verfügbare Platz, nicht wie seine längste Zeile; mit festem Umbruch
   ist die Tafel genau so breit wie die längere der beiden Zeilen, und alle
   Füße einer Zeile haben dieselbe Form. Screenreader lesen den Umbruch als
   Leerzeichen. */
.oton__foot .l3__role {
	white-space: pre-line;
}

/* Logo in Originalfarbe, ohne Graustufen und ohne Opacity.
   ABWEICHUNG von 6.11 (Logo max-height 24 px), nach Sichtprüfung: Eine
   feste Höhe ließ kompakte Logos (Matari Solar, 1,56:1) auf rund 37 × 24 px
   schrumpfen, breite (Gymside, 3,9:1) liefen dreimal so breit. Jetzt hat
   jedes Logo dieselbe Fläche: testimonial-card.php ordnet das
   Seitenverhältnis einer Stufe zu, die Stufe setzt q = √Seitenverhältnis,
   die Box wird s · q breit und s / q hoch (Fläche immer s²). Trägt die
   Datei transparenten Rand, vergrößert p die Box, bis das Gezeichnete
   wieder die Fläche s² hat (Messung siehe testimonial-card.php). object-fit
   hält das Bild in der Box, die feste Box gibt auch SVGs ohne Maße eine
   Größe. Das Logo steht direkt neben der Bauchbinde, nicht an der
   Spaltenkante: Es gehört zur Person, nicht zur Spalte. */
.oton__logo {
	--oton-logo-s: 3.5rem;
	--oton-logo-q: 1.5;
	--oton-logo-p: 1;
	flex: none;
	width: calc(var(--oton-logo-s) * var(--oton-logo-q) * var(--oton-logo-p));
	height: calc(var(--oton-logo-s) / var(--oton-logo-q) * var(--oton-logo-p));
	max-width: 100%;
	margin-inline-start: .25rem;
	object-fit: contain;
	object-position: left center;
}

.oton__logo--r1 { --oton-logo-q: 1; }
.oton__logo--r15 { --oton-logo-q: 1.225; }
.oton__logo--r22 { --oton-logo-q: 1.5; }
.oton__logo--r34 { --oton-logo-q: 1.844; }
.oton__logo--r5 { --oton-logo-q: 2.236; }
.oton__logo--r75 { --oton-logo-q: 2.739; }
.oton__logo--p1 { --oton-logo-p: 1.12; }
.oton__logo--p2 { --oton-logo-p: 1.25; }
.oton__logo--p3 { --oton-logo-p: 1.4; }

/* Schmale Spalten (375 px, 3 Spalten bei 1200 px): Die Grundfläche s
   schrumpft mit der Breite des Fußes, bis Bauchbinde (rund 13 rem mit
   Abstand) und das breiteste übliche Logo (q · p ≈ 2,3) nebeneinander
   passen. Der Faktor gilt für alle Logos gleich, die Flächen bleiben also
   gleich. Unter 2.75rem bricht das Logo lieber um, statt unleserlich zu
   werden. In @supports, weil eine unbekannte Einheit in der Variablen erst
   beim Einsetzen ungültig würde und das Logo dann in Originalgröße stünde. */
@supports (width: 1cqi) {
	.oton__foot {
		container-type: inline-size;
	}

	.oton__logo {
		--oton-logo-s: clamp(2.75rem, (100cqi - 14rem) / 2.4, 3.5rem);
	}
}

.oton__source {
	flex-basis: 100%;
	margin: 0;
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.45 var(--font-text);
}

/* ---------- Slider-Variante ----------
   Gleiche Stimme, 22rem breit (Vertrag von 44-slider.css: Breite über
   --slider-w am .slider). Auf dem Handy 82vw, damit die nächste Stimme
   anschneidet. Ersetzt das alte Inline-Style width:min(100%,22rem). */
.testimonials__slider {
	--slider-w: min(22rem, 82vw);
}

/* Bewegung: Die Listen-Einblendung der Stimmen (Spez. 7.3, Nr. 3) steht
   zentral in 90-motion.css ([data-reveal], Staffelung per
   data-reveal-delay aus 30-reveal.js). Deshalb trägt .oton hier bewusst
   keine eigene transition. */

/* ===== 61-comparison.css ===== */
/* =========================================================================
   61 · comparison: Vergleichstabelle (Spez. 6.13)
   Spalte B ist der ausgewählte, „zugeschnittene“ Clip: durchgehende Spur auf
   --surface mit Trim-Griffen (.trim.is-trimmed, Team F). Ab 48rem echte
   Tabelle, darunter zwei Spuren mit dem Tabellenkopf als Legende.
   Genutzt von: sections/comparison.php
   ========================================================================= */

/* FIX: Die alte Tabelle hatte min-width 34rem in einem Scroll-Container.
   Die gestapelte Mobilfassung ersetzt beides; es gibt keinen Querscroll mehr,
   und Fokusringe von Links in Randzellen werden nicht mehr abgeschnitten. */
.compare {
	position: relative;
	min-width: 0;
}

.compare__table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
	color: var(--text);
}

.compare__table th,
.compare__table td {
	text-align: start;
	/* FIX: bricht nur, wenn ein Wort wirklich nicht in die Zelle passt. */
	overflow-wrap: break-word;
}

/* Kopf B als Namenstafel. Tokens statt fester #156A72: auf white und mist
   ergibt das genau #156A72, auf deep die Studio-Tafel (#1C818B, 4,60) und
   auf Sektion teal eine dunkle Tafel, die sich vom Grund abhebt. */
.compare__name {
	display: inline-block;
	padding: .5rem .875rem;
	border-radius: var(--r-plate);
	background: var(--l3-name-bg);
	color: var(--l3-name-fg);
	font: 700 1.0625rem/1.2 var(--font-display);
}

/* Spur B: Die Kerben der Griffe haben die Farbe der Zelle, nicht des Grundes.
   Nach Sichtprüfung auch im Kopf: Dort stand die Namenstafel auf dem
   Sektionsgrund, die Zellen darunter auf --surface. Der Trim-Rahmen um
   Spalte B wirkte dadurch zweifarbig, die Kerben saßen oben auf dem Grund.
   Der ausgewählte Clip hat jetzt von oben bis unten eine Fläche. */
.compare__b {
	--notch: var(--surface);
}

.compare__table .compare__b {
	background: var(--surface);
}

.compare__table td.compare__b {
	color: var(--text);
	font: 500 1rem/1.5 var(--font-text);
}

.compare__table td.compare__a {
	color: var(--text-soft);
	font: 400 1rem/1.5 var(--font-text);
}

.compare__criterion {
	color: var(--text);
	font: 650 1rem/1.35 var(--font-display);
}

/* Kopf A: Schibsted 600 14 px --text-soft, in beiden Fassungen. */
.compare__table thead th.compare__a {
	color: var(--text-soft);
	font: 600 var(--fs-xs)/1.35 var(--font-text);
}

/* Trim-Griffe um die ganze Spalte B, in Tabelle und Spurfassung gleich.
   Jede Zelle trägt .trim.is-trimmed; das ::after von Team F hat sechs
   Ebenen: Kerbe links, Kerbe rechts, Griff links, Griff rechts, Linie
   oben, Linie unten. Über background-size werden Ebenen abgeschaltet,
   damit die Einzelzellen zu einem Clip verschmelzen: senkrechte Griffe
   überall, Linie oben und Kerben nur im Kopf, Linie unten und Kerben nur
   in der letzten Zeile. Zwei Klassen, damit die Regel auch dann greift,
   wenn Team F die Griffe an .trim.is-trimmed::after zeichnet. */
.compare__table .compare__b::after {
	background-size: 0 0, 0 0, var(--tw, 6px) 100%, var(--tw, 6px) 100%, 0 0, 0 0;
}

.compare__table .compare__b--head::after {
	background-size: 2px 32%, 2px 32%, var(--tw, 6px) 100%, var(--tw, 6px) 100%, 100% 2px, 0 0;
}

.compare__table .compare__b--last::after {
	background-size: 2px 32%, 2px 32%, var(--tw, 6px) 100%, var(--tw, 6px) 100%, 0 0, 100% 2px;
}

/* ---------- ab 48rem: Tabelle ---------- */
@media (min-width: 48rem) {
	.compare__table {
		table-layout: fixed;
	}

	/* Grundlinie statt Unterkante: Kopf A (Schibsted 14 px) steht auf
	   derselben Grundlinie wie der Text in der Namenstafel B (Archivo 17 px
	   mit .5rem Tafelabstand). Mit bottom lag A rund 9 px tiefer. */
	.compare__table thead th {
		padding: .75rem 1.25rem .875rem;
		vertical-align: baseline;
	}

	/* Spaltenbreiten 26 / 37 / 37 % */
	.compare__table thead th:first-child {
		width: 26%;
		padding-inline-start: 0;
	}

	.compare__table thead th.compare__a {
		width: 37%;
	}

	.compare__table thead th.compare__b {
		width: 37%;
	}

	.compare__row > th,
	.compare__row > td {
		padding: 1.125rem 1.25rem;
		vertical-align: top;
		border-bottom: 1px solid var(--line);
	}

	.compare__row > .compare__criterion {
		padding-inline-start: 0;
	}

	/* Das ::after (inset: 0) endet an der Padding-Box, also über der 1px-Linie
	   jeder Zelle. Ohne Verlängerung hätten die senkrechten Griffe an jeder
	   Zeilengrenze eine Lücke. In der letzten Zeile liegt die untere
	   Trim-Linie dadurch bündig auf der Zeilenlinie statt darüber. Der Kopf
	   hat keine Linie und bleibt bei 0. */
	.compare__row > .compare__b::after {
		inset-block-end: -1px;
	}
}

/* ---------- unter 48rem: zwei Spuren ----------
   Befund vergleich-mobil-formular: Die gestapelten Blöcke wiederholten das
   Mono-Label beider Spalten in jeder Zeile, jede Gewinnerzelle stand als
   eigener Rahmenkasten; bei 375 px rund 1.800 px lang, gelesen wie ein
   Formular. Jetzt bleibt es eine Tabelle mit zwei Spuren:

   - Der Tabellenkopf steht einmal als Legende über der Liste: Kopf A über
     der linken Spur, Namenstafel B über der Spur B. Kein zusätzliches
     Markup, keine wiederholten Labels.
   - Jede Zeile: links Kriterium und gedämpfter Wert A, rechts der Wert B.
   - Spalte B ist wie ab 48rem ein einziger zugeschnittener Clip: Fläche
     --surface und Trim-Griffe laufen ohne Lücke vom Kopf bis zur letzten
     Zeile. Das ist die Spaltenmarkierung der Tabelle, keine Akzentleiste an
     Karten (9.6): Es gibt keine Karten, und die Griffe gehören zur Spalte.

   Gemessen: strassenumfragen 375 px Tabelle 766 px statt rund 1.500 px,
   ugc-agentur (längste Texte) 1.028 px. Tabellensemantik: Die role-Attribute
   aus comparison.php tragen Zeilen- und Spaltenbezug, der Kopf bleibt im
   Barrierefreiheitsbaum wie bisher. */
@media (max-width: 47.99rem) {
	.compare__table,
	.compare__table > thead,
	.compare__table > tbody {
		display: block;
	}

	/* Spur B etwas breiter: Sie trägt Griffe und Innenabstand. Kopfzeile und
	   Zeilen nutzen dieselbe Teilung, damit die Spur senkrecht durchläuft. */
	.compare__table tr {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
	}

	.compare__table th,
	.compare__table td {
		display: block;
	}

	/* Kopf A auf der letzten Grundlinie der Namenstafel, wie ab 48rem. */
	.compare__table > thead > tr {
		align-items: last baseline;
	}

	/* „Kriterium“ bleibt Spaltenkopf für Screenreader (sr-only-Muster),
	   belegt aber keine Spur. */
	.compare__table > thead th:first-child {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip: rect(0 0 0 0);
		clip-path: inset(50%);
		white-space: nowrap;
		border: 0;
	}

	.compare__table > thead th.compare__a {
		padding: 0 .75rem .875rem 0;
	}

	.compare__table > thead th.compare__b {
		padding: .75rem .875rem;
	}


	/* Wert B belegt beide Zeilen der Spur, damit die Fläche ohne Lücke
	   unter dem Kriterium weiterläuft. */
	.compare__row {
		grid-template-areas:
			"crit b"
			"a    b";
		grid-template-rows: auto 1fr;
	}

	/* Die Zeilenlinie sitzt oben an Kriterium und Spur B und läuft damit
	   durch beide Spuren. */
	.compare__row > .compare__criterion {
		grid-area: crit;
		padding: .875rem .75rem .375rem 0;
		border-top: 1px solid var(--line);
		font-size: .9375rem;
	}

	.compare__row > .compare__a {
		grid-area: a;
		padding: 0 .75rem 1.125rem 0;
	}

	.compare__row > .compare__b {
		grid-area: b;
		padding: .875rem .875rem 1.125rem;
		border-top: 1px solid var(--line);
	}

	.compare__table .compare__row > td {
		font-size: .9375rem;
	}

	/* Das ::after (inset: 0) endet an der Padding-Box, also unter der
	   1px-Linie oben. Ohne Verlängerung hätten die Griffe an jeder
	   Zeilengrenze eine Lücke. */
	.compare__row > .compare__b::after {
		inset-block-start: -1px;
	}

	/* Leere Zelle A: bleibt im Barrierefreiheitsbaum (kein display: none),
	   sonst sagte der Screenreader den Wert von B mit dem Kopf von A an
	   (Spez. 9.5). Eine leere Zelle B behält ihre Spur, damit der Clip
	   nicht unterbrochen wird. */
	.compare__row > .compare__a:empty {
		padding: 0;
	}
}

/* Namenstafel kleiner, solange die Spur schmal ist: „Straßenumfrage“ passt
   so bei 320 px in die Spur, ab 30rem trägt sie die Tafel in voller Größe. */
@media (max-width: 29.99rem) {
	.compare__name {
		padding: .375rem .5rem;
		font-size: .875rem;
	}
}

/* Schmale Spalten bis 62rem: lange Wörter („Kennzeichnungspflicht“,
   „Werbekennzeichnung“) trennen mit Strich, statt über overflow-wrap ohne
   Strich zu brechen. Gemessen brach „Kennzeichnungspflicht“ in der
   Kriteriumsspalte der Tabelle bei 768 px, in den Spuren bis 414 px.
   Erst ab 15 Zeichen, sechs vor und nach dem Strich; Safari kennt dafür nur
   die -webkit-Einzelwerte. Der Kopf trennt nicht (Namenstafel). */
@media (max-width: 61.99rem) {
	.compare__row > :is(th, td) {
		-webkit-hyphens: auto;
		hyphens: auto;
		-webkit-hyphenate-limit-before: 6;
		-webkit-hyphenate-limit-after: 6;
		hyphenate-limit-chars: 15 6 6;
	}
}

/* ---------- CTA ----------
   Einheitliche Sektions-CTAs (Befund sektions-cta-uneinheitlich): btn--lg,
   unter 48rem btn--block über die volle Breite, ab 48rem natürliche Breite.
   Derselbe Umschaltpunkt wie hero, channel_proof und cta_band. Keine
   globale Regel an .btn--block (Paketkarten, mobiles Menü bleiben voll
   breit); :where hält die Regel bei einer Klasse, 61 steht nach 10. */
.compare__cta {
	margin-top: clamp(2rem, 4vw, 3rem);
}

@media (min-width: 48rem) {
	.compare__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* Befund sektions-cta-dichte-ausrichtung: Schließt ein Sektions-CTA eine
   vollbreite Reihe ab (pain_points, channel_proof, services, process,
   comparison, video_testimonials, cases), steht er ab 62rem rechtsbündig an
   der Containerkante. Vorher sprang der Button auf Seiten wie
   kundenstimmen-video von Sektion zu Sektion zwischen rechts und links.
   CTAs in einer Textspalte (hero, text_media, cta_band) bleiben an deren
   Textkante. ABWEICHUNG von 6.13 (dort „linksbündig“), Regel in 4.5. */
@media (min-width: 62rem) {
	.compare__cta {
		justify-content: flex-end;
	}
}

/* ===== 62-faq.css ===== */
/* =========================================================================
   62 · faq: Häufige Fragen (Spez. 6.15) und Block smm-faq-block
   Ab 62rem: Kopf links als klebende Randspalte (aside, Team F), Fragen
   rechts. Keine Karten, nur Linien zwischen den Fragen. Das einzige Stück
   Höhen-Animation der Seite (Spez. 1 und 7.1).
   Genutzt von: sections/faq.php, blocks/smm-faq-block.php, JS 41-faq.js
   ========================================================================= */

/* ---------- Aufbau ---------- */

/* FIX: Als Grid- oder Flex-Kind (Artikelspalte, Sektionsraster) darf eine
   lange Frage die Spalte nicht über ihre min-content-Breite aufsprengen. */
.faq {
	min-width: 0;
}

/* ABWEICHUNG von 6.15 (Grid 4fr 8fr), nach Sichtprüfung: Die 4fr-Spalte
   war 284 bis 381 px breit, die H2 in voller --fs-h2 stapelte sich dort
   zu 3 bis 4 Zeilen („Was / Unternehmer / uns vor dem / Start fragen“),
   und „Empfehlungsprogramm“ (.hl, rund 451 px) brach ohne Trennstrich
   mitten im Wort. 5/7 wie pain_points (6.6). */
@media (min-width: 62rem) {
	.faq--aside {
		display: grid;
		grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
		column-gap: clamp(2rem, 5vw, 5rem);
		/* Ohne start wäre der Kopf so hoch wie die Liste und könnte nicht kleben. */
		align-items: start;
	}
}

/* Zwischen 62 und 72rem ist auch die 5fr-Spalte (355 bis 416 px) zu schmal
   für das längste Wort in voller --fs-h2. Oberhalb von 30rem gibt es
   bewusst keine Silbentrennung (02-base.css), deshalb eine kleinere H2.
   :where hält die Spezifität bei einer Klasse (8.5, Regel 4); 62 steht im
   Build nach 05 und gewinnt. */
@media (min-width: 62rem) and (max-width: 71.99rem) {
	.faq--aside :where(.section__title) {
		font-size: min(var(--fs-h2), 2.25rem);
	}
}

/* ---------- Randspalte: Kopf und Anzahl der Fragen ----------
   ABWEICHUNG von 6.15 (Art-Director-Befund „linke Spalte leer“): Unter dem
   Kopf steht die echte Anzahl der Fragen als Datum in Plex Mono (Regel 3:
   Mono nur für echte Daten, hier eine Zählung aus den Einträgen). Ab 62rem
   kleben Kopf und Anzahl als Einheit neben der Liste; der Kopf selbst klebt
   im Modus aside zusätzlich (05-section-header.css), innerhalb der gleich
   hohen Hülle hat das keine Wirkung. Unter 62rem steht die Anzahl zwischen
   Kopf und Liste, der Abstand des Kopfs wandert unter die Anzahl. */
.faq__side {
	min-width: 0;
	margin-bottom: var(--head-gap);
}

.faq__side > :where(.section__header) {
	margin-bottom: 1.25rem;
}


@media (min-width: 62rem) {
	.faq__side {
		align-self: start;
		margin-bottom: 0;
	}

	.faq__side > :where(.section__header) {
		margin-bottom: 0;
	}

}

@media (min-width: 62rem) and (min-height: 44rem) {
	.faq__side {
		position: sticky;
		top: calc(var(--header-h) + 2rem);
	}
}

/* Blocktitel im Beitrag: Größe und Schrift kommen aus der Artikeltypografie. */
.faq__title {
	margin-bottom: 1.25rem;
}

/* ---------- Liste ---------- */
.faq__list {
	min-width: 0;
}

.faq__item {
	border-bottom: 1px solid var(--line);
}

.faq__item:first-child {
	border-top: 1px solid var(--line);
}

/* ---------- Frage ---------- */
.faq__q {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 2rem;
	column-gap: 1.5rem;
	align-items: start;
	padding-block: 1.375rem;
	color: var(--text);
	font: 650 clamp(1.0625rem, .95rem + .5vw, 1.3125rem)/1.3 var(--font-display);
	list-style: none;
	cursor: pointer;
	transition: color var(--dur-1) var(--ease-cut);
}

/* Keine Einzelwort-Zeile am Ende einer Frage („… / euch?“), vor allem mobil. */
.faq__q > span {
	text-wrap: balance;
}

/* Safari zeigt sonst weiterhin sein Dreieck. */
.faq__q::-webkit-details-marker {
	display: none;
}

.faq__q::marker {
	content: "";
}

/* Offener Zustand: :where([open]) hält jeden Selektor bei zwei Klassen
   (Spez. 8.5, Regel 4). Die Zustandsregeln stehen deshalb jeweils nach den
   Grundregeln, die sie überschreiben. */
.faq__item:where([open]) > .faq__q {
	color: var(--accent-text);
}

/* FIX: Auf Touchgeräten bleibt :hover nach dem Antippen stehen; eine
   geschlossene Frage sähe dann geöffnet aus. Hover nur mit echtem Zeiger. */
@media (hover: hover) {
	.faq__q:hover {
		color: var(--accent-text);
	}
}

.faq__q:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 4px;
}

/* ---------- Toggle ----------
   Loom vom 06.10.2026 („schlichtere Dropdowns“): Plus ohne Rahmenquadrat
   und ohne Füllung, in der Akzentfarbe. Offen fällt der senkrechte Balken
   weg (Minus). Der Zustand hängt nicht an der Farbe: Plus und Minus
   unterscheiden sich in der Form. Die 32-px-Fläche bleibt als Zielgröße. */
.faq__toggle {
	position: relative;
	width: 2rem;
	height: 2rem;
	/* Toggle oben ausgerichtet, aber mittig zur ersten Fragezeile. */
	margin-top: calc((1.3em - 2rem) / 2);
	color: var(--accent-text);
	/* Nur Farben laufen weich (Spez. 7.1, Nr. 2). Der Ring wechselt hart; im
	   offenen Zustand hat er die Farbe der Füllung, der Wechsel fällt also
	   nicht auf. */
	transition: background-color var(--dur-1) var(--ease-cut), color var(--dur-1) var(--ease-cut);
}

.faq__toggle::before,
.faq__toggle::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	background: currentColor;
	transition: transform var(--dur-1) var(--ease-cut);
}

.faq__toggle::before {
	width: 16px;
	height: 2px;
	margin: -1px 0 0 -8px;
}

.faq__toggle::after {
	width: 2px;
	height: 16px;
	margin: -8px 0 0 -1px;
}

.faq__item:where([open]) .faq__toggle::after {
	transform: scaleY(0);
}

@media (min-width: 48rem) {
	.faq__q {
		align-items: center;
	}

	.faq__toggle {
		margin-top: 0;
	}
}

/* ---------- Antwort ---------- */
.faq__a {
	max-width: 64ch;
	padding-bottom: 1.75rem;
	color: var(--text-soft);
	font: 400 1.0625rem/1.65 var(--font-text);
}

/* FIX: Der Absatzrand am Ende hätte den unteren Abstand verdoppelt. */
.faq__a > :last-child {
	margin-bottom: 0;
}

.faq__a a {
	color: var(--accent-text);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

.faq__a a:hover {
	text-decoration-thickness: 2px;
}

/* ---------- Öffnen (Spez. 7.3, Nr. 9) ----------
   Nur mit interpolate-size und ohne reduzierte Bewegung. Firefox und ältere
   Safari öffnen sofort, ohne Übergang. Ohne JavaScript funktioniert beides. */
@media (prefers-reduced-motion: no-preference) {
	@supports (interpolate-size: allow-keywords) {
		.faq__list {
			interpolate-size: allow-keywords;
		}

		.faq__item::details-content {
			block-size: 0;
			overflow: clip;
			/* Fokusringe von Links am Zeilenanfang (Offset 3 px) bleiben sichtbar. */
			overflow-clip-margin: 6px;
			transition: block-size var(--dur-2) var(--ease-cut), content-visibility var(--dur-2) allow-discrete;
		}

		.faq__item[open]::details-content {
			block-size: auto;
		}
	}
}

/* ===== 63-cta-band.css ===== */
/* =========================================================================
   63 · cta_band: Schluss-Panel (Besitz: Team D2, Spezifikation 6.16)
   Markup: template-parts/sections/cta_band.php
   Mitgenutzt von: footer.php (footer-cta, Team A). Der footer-cta steht ohne
   Panel auf Studio und ergänzt seine eigenen Regeln in 33-footer.css; alles
   hier ohne Varianten-Modifier gilt deshalb für beide.

     .cta-band__inner[--panel|--deep|--teal][--split|--solo][--mark]
       .cta-band__main   Kicker · Titel mit Tafel · Intro · Buttons · Beruhigung
       .cta-band__side   Zeitmarke (Signatur), Bild im Sucherrahmen oder
                         .cta-band__hosts (Gesichter am Absender)

   Signatur: Zeitmarke. Die Untertitel-Tafel im Titel zählt zur Seitenregel
   (höchstens drei Tafeln). Kein Verlauf, kein Radial-Blob, kein Schatten,
   keine Mikrofon-Illustration, keine Einblendung. --mark: Die Seitenspalte
   ist die Zeitmarke (nur wenn der Titel die Minuten nennt, cta_band.php);
   Anordnung siehe „Zeitmarke als Einheit“ unten, der Zeitraffer steht in
   17-timemark.css und 34-timemark.js.

   Spezifität (8.5.4): höchstens eine Klasse plus ein Zustand. Fremde Klassen
   im Inneren (.btn, .frame, .timemark__value) stehen in :where() und zählen
   nicht mit. Die Regeln gewinnen über die spätere Position im Build, und der
   footer-cta (Team A) kann sie mit einer einfachen Regel überschreiben.
   ========================================================================= */

/* ---------- Aufbau ---------- */

.cta-band__inner {
	/* Weiß 78 % (#CACFCF, 10,27:1) und Weiß 70 % (#B6BDBE, 8,48:1) nennt 6.16
	   ausdrücklich für Intro und Beruhigungszeile auf Studio. Auf Sektion teal
	   kämen sie nur auf 4,51 bzw. 3,97:1, dort gilt --text-soft (siehe unten). */
	--cta-band-intro: rgb(255 255 255 / 78%);
	--cta-band-note: rgb(255 255 255 / 70%);
	display: grid;
	/* FIX: minmax(0, 1fr) statt auto: Ohne Deckelung wird die Spur so breit
	   wie der breiteste Inhalt (lange Wörter im Titel, Buttons) und schiebt
	   den Text auf dem Handy aus dem Bild. */
	grid-template-columns: minmax(0, 1fr);
	row-gap: 2.5rem;
	align-items: end;
	color: var(--text);
}

/* FIX: Rasterkinder dürfen schrumpfen, sonst sprengt ein langes Wort die Spalte. */
.cta-band__main,
.cta-band__side {
	min-width: 0;
}

/* Ohne Seitenspalte: einspaltig mit Lesebreite 48rem (6.16, Punkt 3). */
.cta-band__inner--solo {
	grid-template-columns: minmax(0, 48rem);
}

/* FIX (Befund cta-band-solo-leerflaeche): 6.16 Punkt 3 meint das Panel,
   nicht nur die Spur. Das Studio-Panel blieb 1216 px breit und rahmte eine
   zu 41 % leere rechte Hälfte. Ohne Seitenspalte ist das Panel deshalb
   höchstens 48rem Satzbreite plus Padding breit (border-box, 02-base.css),
   linksbündig im Container. Auf Sektion teal und deep gibt es kein Panel,
   dort läuft der Grund ohnehin über die volle Breite. */
@media (min-width: 48rem) {
	.cta-band__inner--solo:where(.cta-band__inner--panel) {
		max-width: calc(48rem + 2 * clamp(2.5rem, 5vw, 4.5rem));
	}
}

/* ---------- Grund je Hintergrund ---------- */

/* white und mist: Studio-Panel. Die Tokens und die Grundfarbe liefert
   .theme-studio (00-tokens.css, 03-layout.css); hier nur Form und Luft.
   375 px: 2rem 1.25rem. */
.cta-band__inner--panel {
	padding: 2rem 1.25rem;
	border-radius: var(--r-panel);
}

@media (min-width: 48rem) {
	.cta-band__inner--panel {
		padding: clamp(2.5rem, 5vw, 4.5rem);
	}
}

/* deep: kein Panel, Inhalt direkt auf Studio.
   ABWEICHUNG von 6.16 („oben 1px Weiß 12 %“), begründet (Befund
   cta-deep-footer-uebergang): Nach einer hellen Sektion trennt schon der
   Wechsel von Weiß/Kreide zu Studio. Die Linie stand dann 64 bis 115 px tief
   im Dunkel und trennte nichts. Sie erscheint deshalb nur, wo zwei
   Studio-Flächen aneinanderstoßen, also nach einer deep-Sektion; dort
   halbiert 03-layout.css den oberen Abstand ohnehin. :where() hält die
   Spezifität bei einer Klasse (8.5.4). */
.cta-band__inner--deep:where(.section--bg-deep + .section--cta-band *) {
	padding-top: clamp(2.5rem, 5vw, 4rem);
	border-top: 1px solid var(--line);
}

/* teal: kein Panel. Titeltafel weiß mit #156A72-Schrift und Primärbutton
   kommen aus den Tokens von .section--bg-teal. Weiß 78 %/70 % wären hier zu
   schwach, --text-soft (#D5E4E6) hält 4,82:1. */
.cta-band__inner--teal {
	--cta-band-intro: var(--text-soft);
	--cta-band-note: var(--text-soft);
}

/* ---------- Text ---------- */

/* Archivo 800, --fs-cta (30 px bei 375). line-height 1.16 setzt
   06-highlight.css, damit Tafeln keine Unterlängen der Zeile darüber
   verdecken.
   FIX: Breite über --stretch-title (94 %, unter 24rem 86 %, 00-tokens.css)
   statt fest 94 % plus eigener 24rem-Regel. „30-Minuten-Gespräch“ oder
   „Herumprobieren“ passen bei 320 px im Panel (Satzbreite 244 px) nur mit
   86 %; so gilt dieselbe Stufe wie für alle anderen Titel. */
.cta-band__title {
	margin: 0;
	color: var(--text);
	font-size: var(--fs-cta);
	font-weight: 800;
	font-stretch: var(--stretch-title);
	letter-spacing: -.01em;
}

.cta-band__intro {
	max-width: 40rem;
	margin: 1.25rem 0 0;
	color: var(--cta-band-intro);
	font: 400 1.125rem/1.55 var(--font-text);
}

.cta-band__actions {
	margin-top: 2rem;
}

.cta-band__reassurance {
	max-width: 40rem;
	margin: 1rem 0 0;
	color: var(--cta-band-note);
	font: 400 var(--fs-xs)/1.5 var(--font-text);
}

/* 375 px: Buttons untereinander über die volle Breite, Primär zuerst (4.5).
   Wirkt wie .btn--block, nur unterhalb von 48rem. Gilt auch im footer-cta,
   dessen Button-Reihe dieselbe Klasse trägt (footer.php).
   FIX (Befund button-label-umbruch-mobil): Bricht ein Label doch zweizeilig
   um, standen ein 66 px hoher Primärbutton und ein 56 px hoher Ghost
   untereinander. Das einspaltige Raster mit gleich hohen Zeilen (1fr) gleicht
   beide an. align-items: stretch hebt das center aus .btn-row auf,
   minmax(0, 1fr) dessen flex-start, sonst schrumpfte die Spalte auf die
   Breite des längsten Labels. */
@media (max-width: 47.99rem) {
	.cta-band__actions {
		display: grid;
		grid-template-columns: minmax(0, 1fr);
		grid-auto-rows: 1fr;
		align-items: stretch;
	}

	.cta-band__actions > :where(.btn) {
		display: flex;
		width: 100%;
	}

	.cta-band__actions :where(.btn__label) {
		flex: 1;
	}
}

/* ---------- Seitenspalte ---------- */

/* Bild im Sucherrahmen: höchstens 16rem breit, Marken aus --mark
   (#2FAFAF auf Studio 6,06, Weiß auf Sektion teal). */
.cta-band__side > :where(.frame) {
	max-width: 16rem;
}

/* ---------- Gesichter am Absender (.cta-band__hosts) ----------
   Zwei Fassungen, gewählt nach dem Platz, nicht nur nach dem Viewport:

   Zeilen: je Person ein 4rem-Porträt mit der Bauchbinde daneben (ein 64 px
   breites Bild trüge keine überhängende Tafel). Unter 62rem unter der
   Beruhigungszeile, bei 375 px untereinander, ab 48rem nebeneinander; ab
   62rem auch in einer Seitenspalte unter 22.75rem (Panel bei 992 bis
   1280 px). Marken 14 px mit 6 px Versatz, sonst wirkt der Rahmen schwerer als das Gesicht;
   1.5rem Zeilenabstand, damit die Ecken beider Rahmen (6 px außerhalb des
   Bildes) nicht aneinanderstoßen.

   Paar: ab 62rem und 22.75rem Spaltenbreite zwei 4:5-Porträts mit
   überhängender Bauchbinde. 22.75rem, weil erst dann jedes Porträt 165 px
   breit ist und der Name („Benjamin Schuler“, 149 px plus Einzug) in der
   Tafel einzeilig bleibt; darunter brach bei 1024 px sogar
   „Geschäftsfü-hrer“ mitten im Wort.

   Die Spaltenbreite fragt eine Container-Abfrage auf der Hülle ab
   (container-type nur hier, nicht am Header, 4.1). Farben ohne eigene Regel:
   Marken aus --mark, Bauchbinde aus --l3-* (Panel, deep und teal kippen die
   Tokens selbst). */
.cta-band__hosts {
	container: cta-band-hosts / inline-size;
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 1.5rem 2rem;
}

.cta-band__host {
	--mark-len: 18px;
	/* Basis 0 mit Obergrenze statt Basis 11rem: Mit flex-wrap bräche das Paar
	   sonst in zwei Zeilen um, bevor es schrumpft. */
	flex: 1 1 0;
	max-width: 11rem;
	margin: 0 0 1.5rem;
}

/* Das Paar: das zweite Porträt 1.5rem höher, damit die Bauchbinden nicht
   auf einer Linie stehen (wie das Gründer-Duo in 6.14, gespiegelt, weil die
   Spalte unten auf der Beruhigungszeile steht). frame--overlap hält unter
   jedem Bild 1.5rem für den Überhang frei. */
.cta-band__host:nth-child(2) {
	margin-bottom: 3rem;
}

/* Zeilen-Fassung. Zweimal notiert, weil eine Regel nicht zugleich an einer
   Media- und einer Container-Abfrage hängen kann. :where() hält die
   Spezifität bei einer Klasse (8.5.4); die Regeln gewinnen über die
   Reihenfolge im Build gegen 12-frame.css und 13-lower-third.css. */
@media (max-width: 61.99rem) {
	.cta-band__host,
	.cta-band__host:nth-child(2) {
		--mark-len: 14px;
		--mark-off: 6px;
		display: grid;
		flex: 1 1 100%;
		max-width: none;
		grid-template-columns: 4rem minmax(0, 1fr);
		column-gap: 1.25rem;
		align-items: center;
		margin: 0;
	}

	.cta-band__host > :where(.frame__cap) {
		margin: 0;
	}

	.cta-band__host :where(.l3--overlap) {
		position: static;
		max-width: 100%;
		transform: none;
	}
}

@media (min-width: 48rem) and (max-width: 61.99rem) {
	.cta-band__host,
	.cta-band__host:nth-child(2) {
		flex: 0 1 20rem;
	}
}

@media (min-width: 62rem) {
	@container cta-band-hosts (max-width: 22.74rem) {
		.cta-band__host,
		.cta-band__host:nth-child(2) {
			--mark-len: 14px;
			--mark-off: 6px;
			display: grid;
			flex: 1 1 100%;
			max-width: none;
			grid-template-columns: 4rem minmax(0, 1fr);
			column-gap: 1.25rem;
			align-items: center;
			margin: 0;
		}

		.cta-band__host > :where(.frame__cap) {
			margin: 0;
		}

		.cta-band__host :where(.l3--overlap) {
			position: static;
			max-width: 100%;
			transform: none;
		}
	}
}

/* ---------- Zeitmarke als Seitenspalte (.cta-band__inner--mark) ----------
   ABWEICHUNG von 6.16 („Tablet: Zeitmarke unter den Buttons“, „align-items:
   end“), begründet (Befund „Zeitmarke 30:00 ist statische Deko“): Unten
   rechts schwebte die Zahl ohne Bezug, rechts oben blieb Leere, und mobil
   hing sie als Nachklapp unter den Buttons.

   Unter 62rem: Kopfzeile über Kicker und Titel. Timecode und Clip stehen in
   einer Zeile wie die Zeitleiste eines Players; der Clip füllt die Breite
   neben der Zahl und sitzt auf ihrer Grundlinie. order verschiebt nur die
   Darstellung: Die Spalte ist aria-hidden und enthält nichts Fokussierbares,
   Lese- und Tabreihenfolge bleiben unberührt.
   Ab 62rem: Timecode und Leiste als Einheit mittig neben dem Text
   (siehe „Zeitmarke als Einheit“ unten).

   Gilt auch im footer-cta (footer.php setzt dieselbe Klasse), ergänzt in
   33-footer.css.
   :where() hält die Spezifität bei einer Klasse (8.5.4). */

@media (max-width: 61.99rem) {
	.cta-band__inner--mark {
		--timemark-fs: 3.5rem;
		row-gap: 1.75rem;
	}

	.cta-band__side:where(.cta-band__inner--mark > *) {
		order: -1;
	}

	.timemark:where(.cta-band__inner--mark *) {
		display: flex;
		align-items: baseline;
		column-gap: 1rem;
	}

	/* Ohne Text liegt die Grundlinie des Clips an seiner Unterkante: Die
	   Leiste steht damit auf der Schriftlinie der Ziffern. */
	.timemark__clip:where(.cta-band__inner--mark *) {
		flex: 1 1 0;
		min-width: 0;
		margin-top: 0;
	}
}

@media (min-width: 48rem) and (max-width: 61.99rem) {
	.cta-band__inner--mark {
		--timemark-fs: 4.5rem;
		row-gap: 2rem;
	}

	.timemark:where(.cta-band__inner--mark *) {
		column-gap: 1.5rem;
	}
}

/* ---------- Ab 62rem zweispaltig ---------- */

@media (min-width: 62rem) {
	.cta-band__inner--split {
		grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
		column-gap: 4rem;
		align-items: end;
	}
}

/* ---------- Zeitmarke als Einheit (ab 62rem, white/mist und teal) ----------
   ABWEICHUNG von 5.8 und 6.16 („Monitor“ und „Clip am Fuß“ aus Runde 3),
   begründet (Befund „Zeitmarke 30:00 fast überall in gleicher Komposition“,
   Abnahme Runde 3): Der Timecode stand oben rechts an der Titelzeile, die
   Trim-Leiste abgelöst am Fuß des Panels, dazwischen 250 bis 300 px leere
   Spalte. Jetzt bilden Timecode und Leiste eine Einheit wie die Anzeige
   eines Players:

     - Die Leiste steht direkt unter den Ziffern (Abstand in 17-timemark.css)
       und ist genau so breit wie der Timecode. .cta-band__side schrumpft
       dafür auf ihren Inhalt (justify-self); der Clip hat mit
       container-type keine eigene Breite und folgt der Zeile darüber.
     - Die Einheit steht vertikal mittig neben dem Text (align-items: center)
       und rechts bündig mit der Satzkante des Panels bzw. des Containers.
       So bleibt über und unter ihr gleich viel Luft, statt dass sich unten
       eine Leerfläche sammelt.
     - Das Panel braucht kein zusätzliches Padding mehr für eine Zeitleiste
       am Fuß; das Band ist so hoch wie sein Text.

   Die Zeitmarke erscheint nur noch, wo der Titel die Minuten nennt
   (cta_band.php); die übrigen Bänder tragen Gesichter oder stehen
   einspaltig. deep behält die breite Kopfzeile (unten), der footer-cta
   dieselbe Einheit (33-footer.css).
   :where() hält die Spezifität bei einer Klasse (8.5.4). */

@media (min-width: 62rem) {
	.cta-band__inner--mark {
		--timemark-fs: var(--fs-time);
		align-items: center;
	}

	.cta-band__side:where(.cta-band__inner--mark > *) {
		justify-self: end;
	}

	/* deep: Kopfzeile über die volle Breite, Timecode links, Clip daneben auf
	   seiner Grundlinie. Die Textspalte behält die Breite, die sie im Split
	   hätte (7 von 11 Teilen), damit Titel und Intro nicht zu langen Zeilen
	   auseinanderlaufen. */
	.cta-band__inner--deep:where(.cta-band__inner--mark) {
		grid-template-columns: minmax(0, 1fr);
		row-gap: 2.5rem;
	}

	.cta-band__main:where(.cta-band__inner--deep.cta-band__inner--mark > *) {
		max-width: calc((100% - 4rem) * 7 / 11);
	}

	.cta-band__side:where(.cta-band__inner--deep.cta-band__inner--mark > *) {
		order: -1;
		justify-self: stretch;
	}

	.timemark:where(.cta-band__inner--deep *) {
		display: flex;
		align-items: baseline;
		column-gap: 2rem;
	}

	.timemark__clip:where(.cta-band__inner--deep *) {
		flex: 1 1 0;
		min-width: 0;
		margin-top: 0;
	}
}

/* ===== 64-form-section.css ===== */
/* =========================================================================
   64 · form: Erstgespräch (Besitz: Team D2, Spezifikation 6.17)
   Markup: template-parts/sections/form.php

     .form-section__layout
       .form-section__head      Sektionskopf (stack), H1 mit Tafel
       .form-section__hosts     Gesichter am Absender (Sucherrahmen, Bauchbinde)
       .form-section__main      klebender Block der rechten Spalte
         .form-card             Contact Form 7 bzw. Ersatzdarstellung
           .form-section__trust Vertrauenspunkte als ruhige Zeile
         .form-section__alt     Kalender-Alternative, direkt unter der Karte
       .form-section__benefits  .checks
       .form-section__voice     Kundenstimme (oton--kurz)

   Feldoptik, Fehler, Antwortbox und Submit liefert 11-forms.css (F1).
   Hier stehen nur Raster, Karte und Abstände. Kein Schatten, kein Verlauf,
   nichts zentriert.

   Abstände über margin statt row-gap: Fehlt ein optionaler Block (Benefits,
   Stimme, Kalender), bleibt keine doppelte Lücke im Raster stehen.

   Abweichung zu 6.17, begründet (Einzelheiten in form.php): Karte und
   Kalender-Alternative teilen sich .form-section__main. Als eigenes
   Rasterelement stand die Alternative ab 62rem unter der ganzen linken
   Spalte statt unter der Karte, mit bis zu 530 px Leerraum dazwischen.
   Mobile Reihenfolge damit: Kopf, Gesichter, Karte, Kalender, Benefits,
   Stimme.

   Signatur: Sucherrahmen an den Porträts, sofern der Text Personen nennt.
   ========================================================================= */

.form-section__layout {
	display: grid;
	/* FIX: minmax(0, 1fr): Ein select ist so breit wie seine längste Option
	   und zöge eine 1fr-Spur samt Karte über den Bildschirmrand. */
	grid-template-columns: minmax(0, 1fr);
}

/* FIX: Rasterkinder dürfen schrumpfen, sonst sprengt ein langes Wort die Spalte. */
.form-section__head,
.form-section__hosts,
.form-section__main,
.form-section__voice {
	min-width: 0;
}

/* ---------- Gesichter am Absender ----------
   Zwei Fassungen, gewählt nach dem Platz (gleiches Muster wie
   .cta-band__hosts in 63-cta-band.css):

   Zeilen, unter 62rem: kompakt, damit der Weg zum Formular kurz bleibt. Je
   Person ein 4rem-Porträt mit der Bauchbinde daneben statt darüber (ein
   64 px breites Bild trüge keine überhängende Tafel). Bei 375 px zwei
   Zeilen von je 80 px, ab 48rem beide nebeneinander. Marken 14 px mit 6 px
   Versatz statt 16/22 px, sonst wirkt der Rahmen schwerer als das Gesicht. 1.5rem
   Zeilenabstand: Die Marken liegen 6 px außerhalb jedes Bildes, bei
   weniger Luft stießen die Ecken beider Rahmen aneinander.

   Paar, ab 62rem in der linken Spalte unter dem Intro: zwei 4:5-Porträts,
   höchstens 12rem breit, das zweite 1.5rem tiefer wie das Gründer-Duo im
   Team (6.14). Die Bauchbinde hängt über die Unterkante (frame--overlap
   hält 1.5rem frei) und deckt nur Jacke, nie Gesicht. Unter 22.75rem
   Spaltenbreite (992 px) fiele jedes Porträt unter 165 px, der Name brach
   in der Tafel um; dort bleibt die Zeilen-Fassung. Der Abstand von 2rem
   nimmt den 1rem-Überhang der zweiten Tafel nach links und die 10px-Marken
   beider Rahmen auf. */
.form-section__hosts {
	container: form-section-hosts / inline-size;
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 1.5rem 2rem;
	margin: 0 0 2.5rem;
}

.form-section__host {
	--mark-len: 18px;
	/* Basis 0 mit Obergrenze statt Basis 12rem: Mit flex-wrap bräche das Paar
	   sonst in zwei Zeilen um, bevor es schrumpft. */
	flex: 1 1 0;
	max-width: 12rem;
	margin: 0 0 1.5rem;
}

.form-section__host:nth-child(2) {
	margin-top: 1.5rem;
}

/* Zeilen-Fassung. Zweimal notiert, weil eine Regel nicht zugleich an einer
   Media- und einer Container-Abfrage hängen kann. :where() hält die
   Spezifität bei einer Klasse (8.5.4); die Regeln gewinnen über die
   Reihenfolge im Build gegen 12-frame.css und 13-lower-third.css. */
@media (max-width: 61.99rem) {
	.form-section__host,
	.form-section__host:nth-child(2) {
		--mark-len: 14px;
		--mark-off: 6px;
		display: grid;
		flex: 1 1 100%;
		max-width: none;
		grid-template-columns: 4rem minmax(0, 1fr);
		column-gap: 1.25rem;
		align-items: center;
		margin: 0;
	}

	.form-section__host > :where(.frame__cap) {
		margin: 0;
	}

	.form-section__host :where(.l3--overlap) {
		position: static;
		max-width: 100%;
		transform: none;
	}
}

@media (min-width: 48rem) and (max-width: 61.99rem) {
	.form-section__host,
	.form-section__host:nth-child(2) {
		flex: 0 1 20rem;
	}
}

@media (min-width: 62rem) {
	@container form-section-hosts (max-width: 22.74rem) {
		.form-section__host,
		.form-section__host:nth-child(2) {
			--mark-len: 14px;
			--mark-off: 6px;
			display: grid;
			flex: 1 1 100%;
			max-width: none;
			grid-template-columns: 4rem minmax(0, 1fr);
			column-gap: 1.25rem;
			align-items: center;
			margin: 0;
		}

		.form-section__host > :where(.frame__cap) {
			margin: 0;
		}

		.form-section__host :where(.l3--overlap) {
			position: static;
			max-width: 100%;
			transform: none;
		}
	}
}

/* ---------- Formularkarte ----------
   Grund --surface: auf Sektion white Kreide #EEF2F1, auf mist Weiß, auf
   deep #153438, auf teal #12545B. Die Felder bleiben überall weiß mit
   Tintenschrift (11-forms.css). Radius 4px, 1px --line, kein Schatten.
   375 px: Kartenpadding 1.25rem. */
.form-card {
	min-width: 0;
	padding: 1.25rem;
	background: var(--surface);
	color: var(--text);
	border: 1px solid var(--line);
	border-radius: var(--r-panel);
}

@media (min-width: 48rem) {
	.form-card {
		padding: clamp(1.5rem, 3vw, 2.5rem);
	}
}

/* ---------- Benefits ---------- */

/* .checks (Haken 18 px, --accent-text) aus 16-lists-checks-stars.css.
   Schibsted 16 px/1.5, Abstand .875rem. */
.form-section__benefits {
	gap: .875rem;
	margin: 2.5rem 0 0;
	color: var(--text);
	font: 400 1rem/1.5 var(--font-text);
}

/* ---------- Kundenstimme ---------- */

.form-section__voice {
	margin-top: 2.5rem;
}

/* ---------- Vertrauenspunkte in der Karte ----------
   Eine ruhige Zeile unter dem Absenden-Button: Schibsted 14 px --text-soft,
   Pixelquadrate aus .bullets (16-lists-checks-stars.css), abgesetzt durch
   1px --line wie die Kalender-Alternative. Die Punkte laufen nebeneinander
   und brechen als Ganzes um, statt als dritte Liste der Seite zu wirken.
   Kontrast --text-soft auf Kreide 6,9:1, auf Weiß 7,51:1. */
.form-section__trust {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem 1.5rem;
	margin: 1.5rem 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--line);
	color: var(--text-soft);
	font: 400 var(--fs-xs)/1.5 var(--font-text);
}

/* ---------- Kalender-Alternative ----------
   Vorhandener Satz in Schibsted 15 px --text-soft plus .arrow-link,
   oben 1px --line und 1.25rem Luft. Steht unter der Karte im selben Block. */
.form-section__alt {
	margin: 1.5rem 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--line);
	color: var(--text-soft);
	font: 400 var(--fs-small)/1.5 var(--font-text);
}

/* ---------- Ab 62rem: Kopf, Gesichter, Benefits und Stimme links, Karte rechts ----------
   Die letzte Zeile ist 1fr: Ist der Hauptblock höher als die linke Spalte,
   nimmt die Stimme-Zeile den Rest auf, und zwischen Kopf, Gesichtern und
   Benefits entsteht keine Lücke. Fehlen Gesichter, bleibt ihre Zeile 0 hoch
   (Abstände über margin). Die Kalender-Alternative wandert mit der Karte. */
@media (min-width: 62rem) {
	.form-section__layout {
		grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
		grid-template-rows: auto auto auto 1fr;
		grid-template-areas:
			"head     form"
			"hosts    form"
			"benefits form"
			"voice    form";
		column-gap: clamp(2rem, 5vw, 5rem);
	}

	.form-section__head {
		grid-area: head;
	}

	.form-section__hosts {
		grid-area: hosts;
		margin: 2.75rem 0 0;
	}

	/* Der Sektionskopf bringt seinen Abstand zum Inhalt mit (--head-gap);
	   neben der Karte zählt nur der Zeilenabstand von 2rem. :where() hält die
	   Spezifität bei einer Klasse (8.5.4), die Regel gewinnt über die
	   Reihenfolge gegen 05-section-header.css. */
	.form-section__head > :where(.section__header) {
		margin-bottom: 0;
	}

	.form-section__main {
		grid-area: form;
		/* Ohne start würde der Block auf die Höhe der linken Spalte gestreckt
		   und könnte nicht kleben. */
		align-self: start;
	}

	.form-section__benefits {
		grid-area: benefits;
		margin-top: 2rem;
	}

	.form-section__voice {
		grid-area: voice;
		margin-top: 2rem;
	}
}

/* Karte und Kalender-Alternative kleben gemeinsam unter dem Header, solange
   die linke Spalte weiterläuft.
   Abweichung zu 6.17 (min-height 44rem), begründet: Die Karte mit dem
   Standardformular ist bei 1280 px rund 42rem hoch (667 px gemessen), mit
   der Alternative darunter 46rem (736 px), bei 992 px 47,6rem (762 px). Bei
   44rem Fensterhöhe blieben nach Header und 2rem Luft nur 37,5rem; der
   Absenden-Button und die Alternative stünden dauerhaft unter dem
   Fensterrand, bis die Sektion endet. Ab 55rem (880 px) passt der Block
   samt Header und Luft (höchstens 866 px) vollständig ins Fenster. */
@media (min-width: 62rem) and (min-height: 55rem) {
	.form-section__main {
		position: sticky;
		top: calc(var(--header-h) + 2rem);
	}
}

/* ===== 65-packages.css ===== */
/* =========================================================================
   65 · packages: Pakete (Besitz: Team D2, Spezifikation 6.18)
   Markup: template-parts/sections/packages.php

     .packages__grid.packages__grid--count-N | --many
       article.package[.package--featured.trim.is-trimmed.theme-studio | .package--raised]
         h3.package__name · p.l3__name.package__label · p.package__price
         p.package__text · ul.checks.package__features · .package__cta

   Spalten mit Haarlinien statt Karten: kein Rahmen, kein Schatten, keine
   Akzentleiste, keine Pille. Das hervorgehobene Paket ist ein Studio-Panel
   mit festen Trim-Griffen (Grammatik, 5.5).

   Abweichung zu 6.18, begründet: Die Spec nennt
   repeat(auto-fit, minmax(min(100%, 19rem), 1fr)). auto-fit ergäbe bei drei
   Paketen zwischen 42 und 63rem zwei Spalten plus ein verwaistes drittes
   Paket, dessen linke Haarlinie am Zeilenanfang stünde (9.9). Die Spalten
   folgen deshalb der Anzahl, mit derselben Mindestbreite von rund 19rem:
     1 Paket    eine Spalte, höchstens 36rem
     2 Pakete   zwei Spalten ab 48rem
     3 Pakete   drei Spalten ab 62rem, auf dem Tablet gestapelt mit
                zweispaltigem Innenaufbau
     4 Pakete   2 × 2 ab 48rem, vier Spalten ab 82rem (erst dort ist der
                Container 76rem breit und jede Spalte 19rem)
     5 und mehr drei Spalten ab 62rem

   Spezifität (8.5.4): höchstens eine Klasse plus ein Zustand. Rasterzustand
   und Nachbarklasse stehen deshalb in :where() und zählen nicht mit; die
   Regeln setzen sich über ihre Reihenfolge in dieser Datei durch. So kann
   jede spätere einfache Klassenregel sie überschreiben.
   ========================================================================= */

/* ---------- Raster ---------- */

.packages__grid {
	display: grid;
	/* FIX: minmax(0, 1fr), damit kein langes Wort eine Spalte aufdrückt. */
	grid-template-columns: minmax(0, 1fr);
	gap: 0;
	align-items: stretch;
}

.packages__grid--count-1 {
	grid-template-columns: minmax(0, 36rem);
}

/* ---------- Spalte ----------
   375 px: gestapelt, Trenner oben (border-top). Die Linienbreiten setzen die
   Raster-Zustände unten; die Farbe steht einmal hier. */

.package {
	display: flex;
	flex-direction: column;
	/* FIX: Flex- und Rasterkinder ohne min-width: 0 dehnen die Spalte auf. */
	min-width: 0;
	padding: 2rem 0;
	border: 0 solid var(--line);
	color: var(--text);
}

.package + :where(.package) {
	border-top-width: 1px;
}

/* Name: Archivo 760 1.625rem. */
.package__name {
	margin: 0;
	color: var(--text);
	font: 760 1.625rem/1.15 var(--font-display);
	font-stretch: 100%;
	letter-spacing: -.005em;
	text-wrap: balance;
}

/* „Empfohlen“ als Namenstafel (.l3__name aus 13-lower-third.css) über dem
   Namen. Im DOM steht die Tafel hinter dem Namen, order holt sie optisch
   nach oben. Auf Studio Weiß auf #1C818B (4,60). */
.package__label {
	order: -1;
	align-self: flex-start;
	/* Im Tablet-Raster (unten) sonst spaltenbreit gestreckt. */
	justify-self: start;
	max-width: 100%;
	margin-bottom: 1rem;
}

/* Preis: Archivo 820, stretch 100 %, 2rem, tabellarische Ziffern.
   Text, keine Walze (5.7: nicht an Preisen). */
.package__price {
	margin: .75rem 0 0;
	color: var(--text);
	font: 820 2rem/1.1 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums lining-nums;
	overflow-wrap: break-word;
}

.package__text {
	margin: 1rem 0 0;
	color: var(--text-soft);
	font: 400 1rem/1.55 var(--font-text);
}

/* Haken aus .checks (16-lists-checks-stars.css); das ✓-Glyph fehlt in allen
   Theme-Schriften, der Haken ist deshalb eine CSS-Maske. */
.package__features {
	margin: 1.5rem 0 0;
	color: var(--text);
	font: 400 1rem/1.5 var(--font-text);
}

/* Button am Fuß der Spalte, alle Buttons einer Reihe auf einer Linie. */
.package__cta {
	margin-top: auto;
	padding-top: 2rem;
}

/* ---------- Hervorgehobenes Paket ----------
   Studio-Panel (.theme-studio) mit Radius 4px und festen Trim-Griffen in
   Gelb (9,97 auf Studio). 375 px: ohne Überstand, Padding 1.5rem. */

.package--featured {
	padding: 1.5rem;
	border-color: transparent;
	border-radius: var(--r-panel);
}

/* Die Haarlinie direkt neben dem Panel entfällt, das Panel trennt selbst.
   Aber nur die Linie, die tatsächlich am Panel anliegt. Nebeneinander ist
   das die Linie links. Die obere Linie des Nachfolgers bleibt, denn im
   2 × 2- und im Dreierraster beginnt er eine neue Zeile, wenn das Panel in
   der letzten Spalte steht, und trennt dort vom Paket darüber (9.9). Nur wo
   gestapelt wird, liegt die obere Linie direkt am Panel (siehe unten). */
.package--featured + :where(.package) {
	border-inline-start-color: transparent;
}

@media (max-width: 47.99rem) {
	.package--featured + :where(.package) {
		border-top-color: transparent;
	}
}

/* Die Griffe folgen dem Radius des Panels, statt als eckige Spitzen über die
   runden Ecken zu stehen. */
.package--featured::after {
	border-radius: inherit;
}

/* Auf Sektion deep: zweite dunkle Ebene statt Studio auf Studio. Die Kerbe im
   Griff nimmt dieselbe Fläche an. */
.package--raised {
	--notch: var(--surface);
	background: var(--surface);
}

/* ---------- Tablet: gestapelt mit zweispaltigem Innenaufbau ----------
   Drei (oder mehr) Pakete stehen zwischen 48 und 62rem untereinander. Eine
   Spalte über 700 bis 900 px wäre leer; Name, Preis, Text und Button
   stehen deshalb links, die Leistungen rechts. */

@media (min-width: 48rem) and (max-width: 61.99rem) {
	:where(.packages__grid--count-3, .packages__grid--many) > .package {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		grid-template-rows: auto auto auto 1fr auto;
		grid-template-areas:
			"label features"
			"name  features"
			"price features"
			"text  features"
			"cta   features";
		column-gap: 2rem;
		align-items: start;
	}

	:where(.packages__grid--count-3, .packages__grid--many) > .package--featured {
		padding: 2rem;
	}

	/* Gestapelt: Der Nachfolger steht direkt unter dem Panel. */
	:where(.packages__grid--count-3, .packages__grid--many) > .package--featured + :where(.package) {
		border-top-color: transparent;
	}

	.package__label {
		grid-area: label;
	}

	.package__name {
		grid-area: name;
	}

	.package__price {
		grid-area: price;
	}

	.package__text {
		grid-area: text;
	}

	.package__features {
		grid-area: features;
	}

	.package__cta {
		grid-area: cta;
	}

	:where(.packages__grid--count-3, .packages__grid--many) .package__features {
		margin-top: 0;
	}

	:where(.packages__grid--count-3, .packages__grid--many) .package__cta {
		align-self: end;
		padding-top: 1.5rem;
	}
}

/* ---------- Mehrspaltig: Haarlinien links, Überstand des Panels ---------- */

@media (min-width: 48rem) {
	.packages__grid--count-2,
	.packages__grid--count-4 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	:where(.packages__grid--count-2, .packages__grid--count-4) > .package {
		padding: 2rem;
	}

	:where(.packages__grid--count-2) > .package + :where(.package) {
		border-top-width: 0;
		border-inline-start-width: 1px;
	}

	/* 2 × 2: Paket 2 und 4 mit Linie links, Paket 3 und 4 mit Linie oben. */
	:where(.packages__grid--count-4) > .package:nth-child(2) {
		border-top-width: 0;
	}

	:where(.packages__grid--count-4) > .package:nth-child(even) {
		border-inline-start-width: 1px;
	}

	/* Ragt oben und unten 1rem heraus. Das Padding wächst um denselben Betrag,
	   damit die Inhalte mit den Nachbarspalten auf einer Höhe beginnen. */
	:where(.packages__grid--count-2, .packages__grid--count-4) > .package--featured {
		margin-block: -1rem;
		padding: 3rem 2rem;
	}
}

@media (min-width: 62rem) {
	.packages__grid--count-3,
	.packages__grid--many {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	:where(.packages__grid--count-3, .packages__grid--many) > .package {
		padding: 2rem;
	}

	:where(.packages__grid--count-3) > .package + :where(.package) {
		border-top-width: 0;
		border-inline-start-width: 1px;
	}

	:where(.packages__grid--many) > .package:nth-child(-n + 3) {
		border-top-width: 0;
	}

	:where(.packages__grid--many) > .package:not(:nth-child(3n + 1)) {
		border-inline-start-width: 1px;
	}

	:where(.packages__grid--count-3, .packages__grid--many) > .package--featured {
		margin-block: -1rem;
		padding: 3rem 2rem;
	}
}

@media (min-width: 82rem) {
	.packages__grid--count-4 {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	:where(.packages__grid--count-4) > .package + :where(.package) {
		border-top-width: 0;
		border-inline-start-width: 1px;
	}
}

/* ---------- Außenkanten auf der Containerkante ----------
   Befund split-kopf-raster: Nebeneinander hatte auch die erste und die
   letzte Spalte 2rem Innenabstand. Name, Preis und Button standen dadurch
   2rem rechts der Satzkante von Kopf und Intro darüber (werbevideo). Die
   Außenseite der Randspalten bekommt deshalb kein Padding; die Haarlinien
   stehen innen und bleiben, wo sie sind. Das Studio-Panel behält sein
   Padding, es ist eine Fläche und keine Textspalte.
   Rasterzustand und Position stehen in :where() (8.5.4), die Regeln
   setzen sich über ihre Reihenfolge durch.
   ABWEICHUNG von 6.18: nicht erst ab 82rem, sondern ab der Stufe, in der die
   Pakete jeweils nebeneinander stehen. */
@media (min-width: 48rem) {
	:where(.packages__grid--count-2) > .package:where(:first-child:not(.package--featured)) {
		padding-inline-start: 0;
	}

	:where(.packages__grid--count-2) > .package:where(:last-child:not(.package--featured)) {
		padding-inline-end: 0;
	}
}

@media (min-width: 62rem) {
	:where(.packages__grid--count-3, .packages__grid--many) > .package:where(:nth-child(3n + 1):not(.package--featured)) {
		padding-inline-start: 0;
	}

	:where(.packages__grid--count-3, .packages__grid--many) > .package:where(:nth-child(3n):not(.package--featured)) {
		padding-inline-end: 0;
	}
}

@media (min-width: 82rem) {
	:where(.packages__grid--count-4) > .package:where(:first-child:not(.package--featured)) {
		padding-inline-start: 0;
	}

	:where(.packages__grid--count-4) > .package:where(:last-child:not(.package--featured)) {
		padding-inline-end: 0;
	}
}

/* ===== 66-cases.css ===== */
/* =========================================================================
   66 · cases: Fallstudien-Zeilen und Einzelansicht (Besitz: Team D2,
   Spezifikation 6.19, Seitenkopf nach 6.22)
   Markup: template-parts/sections/cases.php, single-smm_case.php

     .cases__list[.cases__list--no-logos]
       article.case-row.trim.trim--hover
         .case-row__logo > img       Logo-Tafel auf --surface
         .case-row__body             h3.case-row__title > a.case-row__link · p.case-row__text
         dl.case-row__results > .case-row__result > dt.case-row__label + dd.odo.case-row__value

   Zeilen statt Karten: kein Rahmen, kein Schatten, kein Hover-Lift. Die
   Zeile ist über den gestreckten Titel-Link ein einziger Tabstopp. Hover und
   Fokus: Trim-Griffe (14-trim.css), Titel unterstrichen, Fokusring an der
   Zeile.
   ========================================================================= */

/* ---------- Liste und Zeile ---------- */

.cases__list {
	border-top: 1px solid var(--line);
}

/* 375 px: Logo-Tafel 8 × 4.5rem oben, darunter Titel, Text und Ergebnisse
   als 2er-Raster. Die seitliche Luft hält Text und Trim-Griffe (6 px)
   auseinander. Ohne Rasterbereiche: Fehlt einer Zeile das Logo oder die
   Ergebnisse, entsteht keine leere Rasterzeile mit Abstand. */
.case-row {
	display: grid;
	/* FIX: minmax(0, 1fr), sonst drückt ein langer Titel die Zeile auf. */
	grid-template-columns: minmax(0, 1fr);
	row-gap: 1.25rem;
	padding: 1.75rem .75rem;
	border-bottom: 1px solid var(--line);
	color: var(--text);
}

/* Flex statt Grid: Die Höhe der Tafel ist fest, damit greift max-height: 70 %
   am Logo. In einem Grid-Bereich mit auto-Zeile blieb die Prozentangabe
   wirkungslos, und ein quadratisches Logo ragte unten aus der Tafel. */
.case-row__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 8rem;
	height: 4.5rem;
	background: var(--surface);
	border-radius: var(--r-plate);
}

/* Logo in Originalfarbe, ohne Graustufen und ohne Opacity (6.19). */
.case-row__logo-img {
	width: auto;
	height: auto;
	max-width: 70%;
	max-height: 70%;
	object-fit: contain;
}

.case-row__body {
	min-width: 0;
}

/* Titel: Archivo 700 1.5rem. */
.case-row__title {
	margin: 0;
	color: var(--text);
	font: 700 1.5rem/1.2 var(--font-display);
	font-stretch: 100%;
}

/* Gestreckter Link: Das ::after deckt die ganze Zeile ab (.trim setzt
   position: relative und isolation, die Zeile ist damit der Stapelkontext).
   z-index 1 hebt die Fläche über positionierte Kinder. .odo bringt
   position: relative mit (15-odometer.css) und läge sonst in DOM-Reihenfolge
   über dem ::after: Ein Klick auf die Kennzahlen, die auffälligste Stelle der
   Zeile, ginge ins Leere. Die Trim-Griffe (.trim::after, ebenfalls z-index 1)
   folgen später im Baum, liegen darüber und fangen mit pointer-events: none
   keine Klicks ab.
   FIX: Die Unterstreichung lief in Textfarbe, in Post-Karten und Suchzeilen
   dagegen in --accent-text. Kundenerfolge und Ratgeber zeigten dieselbe Geste
   in zwei Farben. Gemeinsame Geste aller Zeilen und Karten mit gestrecktem
   Titel-Link (5.5, 6.10, 6.21): Unterstreichung 2px in --accent-text mit
   Offset .2em wie jeder Link (02-base.css), bei Hover mit echtem Zeiger und
   bei Tastaturfokus; dazu der Fokusring 2px mit Offset 2px am Container. */
.case-row__link {
	color: inherit;
	text-decoration: none;
	text-decoration-color: var(--accent-text);
	text-decoration-thickness: 2px;
	text-underline-offset: .2em;
}

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

.case-row__link:focus-visible {
	text-decoration-line: underline;
}

/* :where() hält die Spezifität bei einer Klasse plus Zustand (8.5.4). */
@media (hover: hover) {
	.case-row:hover :where(.case-row__link) {
		text-decoration-line: underline;
	}
}

/* Fokusring an der ganzen Zeile (6.19). Der Ring des Links selbst würde nur
   den Titel umrahmen; er entfällt nur dort, wo :has() den Zeilenring
   tatsächlich zeichnen kann. Der Titel-Link ist das einzige fokussierbare
   Element der Zeile, :has(:focus-visible) trifft also genau ihn. */
.case-row:has(:focus-visible) {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}

@supports selector(:has(*)) {
	.case-row__link:focus-visible {
		outline: none;
	}
}

.case-row__text {
	margin: .5rem 0 0;
	color: var(--text-soft);
	font: 400 1rem/1.55 var(--font-text);
}

/* ---------- Ergebnisse ----------
   dt vor dd im DOM, die Zahl steht optisch oben (column-reverse). */

.case-row__results {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem 1.5rem;
	margin: 0;
}

.case-row__result {
	display: flex;
	flex-direction: column-reverse;
	justify-content: flex-end;
	min-width: 0;
}

/* Archivo 820 2rem, tabellarische Ziffern (.odo ohne Walze). .odo hält die
   Zahl mit nowrap zusammen; in der halben Zeilenbreite darf ein Wert wie
   „über 5.000 Anfragen“ aber an Leerzeichen umbrechen, statt aus der Spalte
   zu ragen. Unter 48rem wächst die Größe von 1.5rem auf 2rem: „300.000“
   passt so bei 320 px in eine halbe Zeile (118 px). */
.case-row__value {
	margin: 0;
	color: var(--text);
	font: 820 clamp(1.5rem, 1rem + 2.5vw, 2rem)/1 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums lining-nums;
	white-space: normal;
	overflow-wrap: break-word;
}

.case-row__label {
	margin-top: .375rem;
	color: var(--text-soft);
	font: 400 var(--fs-small)/1.35 var(--font-text);
}

/* ---------- Tablet: Logo-Tafel links, Text und Ergebnisse rechts ---------- */

@media (min-width: 48rem) {
	.case-row {
		grid-template-columns: 9rem minmax(0, 1fr);
		grid-template-areas:
			"logo body"
			"logo results";
		gap: 0 2rem;
		align-items: start;
		padding: 2rem 1.25rem;
	}

	.case-row__logo {
		grid-area: logo;
		width: 9rem;
		height: 5.25rem;
	}

	.case-row__body {
		grid-area: body;
	}

	/* Abstand als Rand statt row-gap: ohne Ergebnisse bleibt unten nichts leer.
	   Auf dem Tablet ist die Textspalte rund 30rem breit: Drei Kennzahlen
	   passen nebeneinander, statt zwei plus eine verwaiste darunter. */
	.case-row__results {
		grid-area: results;
		grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
		margin-top: 1.25rem;
	}

	/* :where(): eine Klasse Spezifität (8.5.4), die Regel gewinnt über die
	   Reihenfolge gegen .case-row oben. */
	:where(.cases__list--no-logos) .case-row {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"body"
			"results";
	}
}

/* ---------- Ab 62rem: 12rem · Text · Ergebnisse (22rem) ---------- */

@media (min-width: 62rem) {
	.case-row {
		grid-template-columns: 12rem minmax(0, 1fr) minmax(0, 22rem);
		grid-template-areas: "logo body results";
		align-items: center;
		gap: 2rem;
	}

	.case-row__logo {
		width: 12rem;
		height: 7rem;
	}

	.case-row__results {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		margin-top: 0;
	}

	:where(.cases__list--no-logos) .case-row {
		grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
		grid-template-areas: "body results";
	}
}

.cases__cta {
	margin-top: 3rem;
}

/* Regel für Sektions-CTAs (4.5): btn--lg, unter 48rem btn--block über die
   volle Breite, ab 48rem in natürlicher Breite wie in allen anderen
   Sektionen. :where hält die Spezifität bei einer Klasse. */
@media (min-width: 48rem) {
	.cases__cta :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* Befund sektions-cta-dichte-ausrichtung: Schließt ein Sektions-CTA eine
   vollbreite Reihe ab (pain_points, channel_proof, services, process,
   comparison, video_testimonials, cases), steht er ab 62rem rechtsbündig an
   der Containerkante. Vorher sprang der Button auf Seiten wie
   kundenstimmen-video von Sektion zu Sektion zwischen rechts und links.
   CTAs in einer Textspalte (hero, text_media, cta_band) bleiben an deren
   Textkante. ABWEICHUNG von 6.19 (dort „linksbündig“), Regel in 4.5. */
@media (min-width: 62rem) {
	.cases__cta {
		justify-content: flex-end;
	}
}

/* =========================================================================
   Einzelansicht Kundenerfolg (single-smm_case.php)
   ========================================================================= */

/* Seitenkopf: etwas knapper als eine Sektion, wie der Hero (6.3). */
.section--case-head {
	--section-pad: clamp(2.5rem, 5vw, 4.5rem);
}

.case-head {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	row-gap: 1.5rem;
}

.case-head__text {
	min-width: 0;
}

/* Logo-Tafel wie in der Zeile. 375 px: 8 × 4.5rem über dem Kicker. */
.case-head__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 8rem;
	height: 4.5rem;
	background: var(--surface);
	border-radius: var(--r-plate);
}

.case-head__logo-img {
	width: auto;
	height: auto;
	max-width: 70%;
	max-height: 70%;
	object-fit: contain;
}

/* H1 Seitenkopf: Archivo 800, stretch 94 %, --fs-h1-page, höchstens 20ch
   (Größe und Gewicht aus 02-base.css). */
.case-head__title {
	max-width: 20ch;
}

/* FIX: Lead mobil in Fließtextgröße, erst ab 48rem in --fs-lead, wie
   .hero__intro (40-hero.css) und .section__intro (05-section-header.css).
   19 px auf 320 px wirkten neben der H1 wie eine zweite Überschrift. */
.case-head__lead {
	max-width: 42rem;
	margin: 1.5rem 0 0;
	color: var(--text-soft);
	font: 400 var(--fs-body)/1.55 var(--font-text);
}

@media (min-width: 48rem) {
	.case-head__lead {
		font-size: var(--fs-lead);
	}
}

/* Trennpunkt ist Dekoration (aria-hidden), deshalb die leise UI-Linienfarbe. */
.case-head__sep {
	color: var(--line-ui);
}

/* FIX: Branche und Zeitraum standen in Schibsted 600, die Metazeile mit
   gleicher Rolle im Artikelkopf, in Post-Karten und Suchtreffern (Inhaltstyp,
   Datum) aber in Plex Mono. Der Zeitraum ist eine echte Datenangabe (Regel 3,
   3.4 Mono-Daten), deshalb dieselbe Stimme wie .article__meta: Plex Mono 500
   13 px, ls .02em, Abstände und Grundlinie wie dort. */
.case-head__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: .25rem .5rem;
	margin: 1.25rem 0 0;
	color: var(--text-soft);
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
}

@media (min-width: 62rem) {
	/* Logo-Tafel rechts neben dem Kopf, obenbündig. */
	.case-head--logo {
		grid-template-columns: minmax(0, 1fr) 12rem;
		column-gap: 2rem;
	}

	:where(.case-head--logo) > .case-head__logo {
		grid-column: 2;
		grid-row: 1;
		width: 12rem;
		height: 7rem;
	}

	:where(.case-head--logo) > .case-head__text {
		grid-column: 1;
		grid-row: 1;
	}
}

/* ---------- Ergebnisse im Seitenkopf ----------
   Jede Zahl linksbündig unter einer Haarlinie, keine Kästen. Spalten nach
   Anzahl statt auto-fit, damit keine Zahl allein in einer Zeile steht. */

.case-results {
	--case-results-cols: 1;
	display: grid;
	grid-template-columns: repeat(var(--case-results-cols), minmax(0, 1fr));
	gap: 2rem clamp(1.5rem, 3vw, 3rem);
	margin: var(--head-gap) 0 0;
}

.case-results--count-2,
.case-results--count-4,
.case-results--many {
	--case-results-cols: 2;
}

@media (min-width: 48rem) {
	.case-results--count-3,
	.case-results--many {
		--case-results-cols: 3;
	}
}

@media (min-width: 62rem) {
	.case-results--count-4 {
		--case-results-cols: 4;
	}
}

.case-results--count-1 {
	max-width: 20rem;
}

.case-results__item {
	display: flex;
	flex-direction: column-reverse;
	justify-content: flex-end;
	min-width: 0;
	padding-top: 1rem;
	border-top: 1px solid var(--line);
}

/* --fs-num-s, auf dem Handy kleiner: Zwei Werte nebeneinander haben bei
   320 px je 130 px, „300.000“ in 2rem wäre 142 px breit. */
.case-results__value {
	margin: 0;
	color: var(--text);
	font: 820 min(var(--fs-num-s), 1rem + 3vw)/1 var(--font-display);
	font-stretch: 100%;
	font-variant-numeric: tabular-nums lining-nums;
	white-space: normal;
	overflow-wrap: break-word;
}

.case-results__label {
	margin-top: .5rem;
	color: var(--text-soft);
	font: 400 var(--fs-small)/1.35 var(--font-text);
}

/* ---------- Inhalt, Kundenstimme ---------- */

/* Prosa linksbündig an der Rasterkante (6.20); die Lesebreite 68ch setzt .prose. */
.case-body {
	margin-inline: 0;
}

.case-voice {
	max-width: var(--measure);
}

/* ===== 67-team.css ===== */
/* =========================================================================
   67 · team (Spez. 6.14)
   Porträts im Sucherrahmen (.frame--person.frame--4x5, Team F) mit dem Namen
   als Bauchbinde. Signatur: Sucherrahmen.
   Genutzt von: sections/team.php
   ========================================================================= */

/* ---------- Raster ----------
   375 px: untereinander. Ab 48rem auto-fit mit 20rem Mindestbreite, damit
   Tablet (768 px, Satzbreite rund 700 px) zwei Porträts nebeneinander zeigt;
   mit 22rem plus Fuge passte dort nur eins, als 700 px breites Hochformat.
   Ab 62rem die 22rem aus der Spezifikation.
   ABWEICHUNG von 6.14 (gap clamp(2rem, 5vw, 5rem) in allen Breiten): Bei
   375 px ergab das 32 px, abzüglich der Rahmenmarken 26 px zwischen den
   Profil-Knöpfen der einen und dem Porträt der nächsten Person, also nicht
   mehr als die Abstände innerhalb einer Person (24 bis 29 px). Untereinander
   deshalb 3rem (sichtbar rund 42 px, so viel wie --head-gap); 4rem wäre so
   groß wie der Sektionsabstand. */
.team__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	row-gap: 3rem;
	column-gap: clamp(2rem, 5vw, 5rem);
	align-items: start;
}

@media (min-width: 48rem) {
	.team__grid {
		grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
		row-gap: clamp(2rem, 5vw, 5rem);
	}
}

@media (min-width: 62rem) {
	.team__grid {
		grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
	}

	/* Genau zwei Personen: die zweite versetzt, wie zwei Einstellungen im
	   Schnitt. Nur ab 62rem, darunter stehen sie ohne Versatz. Die Anzahl
	   setzt team.php als Modifier; :nth-child(2):last-child läge über der
	   erlaubten Spezifität (Spez. 8.5, Regel 4). */
	.team__grid--duo > :last-child {
		margin-top: 4rem;
	}
}

/* ---------- Person ---------- */
.team-member {
	/* FIX: Struktur-Container ohne min-width: 0 dehnen das Raster auf. */
	min-width: 0;
	/* Eine einzelne Person würde sonst über die volle Containerbreite ein
	   fast 1500 px hohes Porträt ergeben. */
	max-width: 36rem;
}

/* Kopf und Kinn im Bild: object-position 50 % 20 % setzt 12-frame.css für
   .frame--person. Die Bauchbinde hängt per .l3--overlap über die
   Bildkante; .frame--overlap hält darunter 1.5rem frei. */

/* Bio: 2.5rem unter dem Porträt. Der Rand fällt mit den 1.5rem von
   .frame--overlap zusammen, der Abstand bleibt also 2.5rem. Ohne Foto
   (Modifier aus team.php) steht die Bauchbinde im Fluss, dann reicht 1.25rem. */
.team-member__bio {
	max-width: 56ch;
	margin: 2.5rem 0 0;
	color: var(--text-soft);
	font: 400 var(--fs-body)/1.65 var(--font-text);
}

.team-member--no-photo > .team-member__bio {
	margin-top: 1.25rem;
}

/* ---------- Profile ---------- */
/* Direkt unter dem Porträt (ohne Bio) gilt der Abstand der Bio, damit die
   überhängende Bauchbinde frei steht. Nach der Bio oder ohne Foto reicht
   1.5rem. */
.team-member__socials {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: 2.5rem 0 0;
	padding: 0;
	list-style: none;
}

.team-member__bio + .team-member__socials,
.team-member--no-photo > .team-member__socials {
	margin-top: 1.5rem;
}

/* FIX: Die Liste stand früher fest auf Weiß und war auf hellem Grund
   unsichtbar. Farben kommen jetzt ausschließlich aus Tokens, dadurch passt
   sie auf white, mist, deep und teal. 44 px Zielgröße (WCAG 2.5.8). */
.team-member__social {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: var(--r-control);
	box-shadow: inset 0 0 0 1.5px var(--line-ui);
	color: var(--text);
	text-decoration: none;
	/* Nur Farben laufen weich (Spez. 7.1, Nr. 2), der Ring wechselt hart. */
	transition: background-color var(--dur-1) var(--ease-cut), color var(--dur-1) var(--ease-cut);
}

/* Hover nur mit echtem Zeiger: Auf Touch bliebe die Füllung nach dem
   Antippen stehen, obwohl der Link in einem neuen Tab aufging.
   Der Ring nimmt sofort die Farbe der Füllung an, statt zu verschwinden:
   Das Ergebnis gleicht „ohne Ring“, aber während die Füllung einblendet,
   bleibt die Kante stehen. */
@media (hover: hover) {
	.team-member__social:hover {
		background: var(--text);
		box-shadow: inset 0 0 0 1.5px var(--text);
		color: var(--bg);
	}
}

.team-member__social svg {
	flex: none;
	width: 18px;
	height: 18px;
}

/* Mit Kontoname: gleiche Höhe (44 px Zielgröße), Breite nach Inhalt. */
.team-member__social--labeled {
	grid-auto-flow: column;
	gap: .5rem;
	width: auto;
	padding-inline: .75rem .875rem;
}

.team-member__handle {
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	white-space: nowrap;
}

/* ===== 70-content.css ===== */
/* =========================================================================
   70 content: Freier Text (Besitz: Team E, Redaktion) – Spezifikation 6.20
   Markup: template-parts/sections/content.php

   Zwei Rollen:
     .section--content              Textabschnitt in einer Seite (Karriere,
                                    Über uns, UGC, Kanäle)
     .section--content.content--doc Dokument als erste Sektion (AGB,
                                    Datenschutz, Impressum): h1, keine
                                    Signatur, kleinere h2, eng

   Typografie der Prosa (17 px/1.65 mobil, 17.5 px/1.7 ab 48rem, max 68ch,
   Listen mit Pixelquadrat, Mono-Ziffern in ol, Tabellenkopf auf --surface)
   kommt aus .prose in 02-base.css. Hier stehen nur Spalte, Dokumentmodus
   und der Scrollbehälter für Tabellen.
   Alle Farben über Tokens: gilt unverändert auf white, mist, deep und teal.
   ========================================================================= */

/* Lesespalte: linksbündig an der Rasterkante statt mittig (6.20). Unter
   44rem ist sie ohnehin so breit wie der Container. */
.content__col {
	margin-inline-start: 0;
	/* FIX: Als Kind eines Grid- oder Flex-Elternteils darf eine lange URL die
	   Spalte nicht über ihre min-content-Breite aufsprengen. */
	min-width: 0;
}

/* Breite „wide“ (6.20: max 56rem). Die Spalte begrenzt, die Prosa
   (.content__prose--wide, gesetzt in content.php) läuft bis an ihren Rand.
   Mit den 68ch aus .prose (bei Schibsted 17.5 px rund 727 px) läge „Breit“
   nur gut 20 px über „Schmal“ (44rem = 704 px), das Backend-Feld hätte
   praktisch keine Wirkung. Titel und Intro behalten ihre Satzbreiten aus
   05-section-header.css, weil kurze Zeilen dort gewollt sind. */
.content__col--wide {
	max-width: 56rem;
}

.content__prose--wide {
	max-width: none;
}

/* FIX: Rechtstexte enthalten lange, unbrechbare Zeichenketten (im Impressum
   die ODR-Adresse der EU als reiner Text, im Datenschutz E-Mail-Adressen und
   Links). Auf 320 px schoben sie die Zeile über den Rand; overflow-x: clip am
   Dokument hätte sie nur abgeschnitten. break-word bricht nur dort, wo ein
   Wort wirklich nicht passt, und setzt keinen Trennstrich. */
.content__prose {
	overflow-wrap: break-word;
}

/* ---------- Tabellen ----------
   content.php hüllt jede Tabelle ohne figure in .content__table. Der Behälter
   scrollt seitlich und ist per tabindex erreichbar; der Fokusring kommt aus
   02-base.css. Ohne Behälter setzte die alte Regel display: block an die
   Tabelle selbst, was in Safari/VoiceOver die Tabellensemantik kostet.
   Ab der dritten Spalte gilt die Mindestbreite aus 02-base.css (34rem). */
.content__table {
	max-width: 100%;
	margin-block: 0 1em;
	overflow-x: auto;
	/* Scrollleiste nur so dick wie nötig, damit sie die letzte Zeile nicht verdeckt. */
	scrollbar-width: thin;
}

.content__table > table {
	margin: 0;
}

/* Kopfzeile: Schibsted 600 14 px auf --surface (6.20). Die Fläche liefert
   02-base.css; hier nur die Zeile ohne thead (Tabellen aus dem klassischen
   Editor setzen th direkt in die erste Zeile). */
.content__table tr:first-child > th {
	background: var(--surface);
	font: 600 var(--fs-xs)/1.4 var(--font-text);
	color: var(--text);
}

/* ---------- Dokumentmodus (AGB, Datenschutz, Impressum) ----------
   Lange Prosa läuft ruhig: h2 klein (1.375rem statt bis 2.125rem), damit bei
   neun Paragrafen keine Plakatzeilen entstehen; Abstand nach oben bleibt
   groß, damit Abschnitte als Einheiten lesbar sind.
   FIX (Befund rechtstexte-markup): Die Zwischentitel standen als
   <p><strong>…</strong><br> im Inhalt und sind jetzt echte h3/h4
   (content/datenschutz.json). Mit der Prosa-Basis aus 02-base.css (h3 21 px
   gegen h2 22 px) wären die Stufen kaum zu unterscheiden, und eine h3 direkt
   unter ihrer h2 hinge 42 px tiefer, so weit wie nach einem Absatz. Daher
   h2 22/760 > h3 18/700 > h4 17/600 in Schibsted, eng an den eigenen Text
   gebunden.
   Keine Tafel, kein data-reveal (das Template setzt beides nicht). */

.content--doc .section__header {
	margin-bottom: clamp(2rem, 4vw, 3rem);
}

.content--doc .content__prose h2 {
	font-size: 1.375rem;
	font-stretch: 100%;
	line-height: 1.25;
	letter-spacing: 0;
	margin: 2.5em 0 .6em;
}

.content--doc .content__prose :is(h3, h4) {
	font-stretch: 100%;
	letter-spacing: 0;
	text-wrap: balance;
}

.content--doc .content__prose h3 {
	font-size: 1.125rem;
	line-height: 1.3;
	margin: 1.9em 0 .35em;
}

/* h4 (die Fragen unter „Datenerfassung auf dieser Website“) in der
   Textstimme: Schibsted 600 statt Archivo 700. Bei 17 gegen 18 px trüge die
   Größe allein die Stufe zur h3 nicht. */
.content--doc .content__prose h4 {
	font: 600 1.0625rem/1.4 var(--font-text);
	margin: 1.5em 0 .25em;
}

/* Titel direkt unter dem übergeordneten Titel gehört zu ihm, nicht zum
   Absatz davor. */
.content--doc .content__prose :is(h2, h3) + :is(h3, h4) {
	margin-top: .6em;
}

/* ---------- Stellenanzeige (Karriere) ----------
   FIX (Befund karriere-stellenanzeige): Beginnt die Prosa eines
   Textabschnitts mit einer h3, ist das der Titel des Inhalts (auf Karriere
   die Stellenbezeichnung). Mit 20 px stand er kaum über den h4 „Deine
   Aufgaben“ (18 px). Abgeleitet aus der Struktur, kein neues Feld; Dokumente
   haben ihre eigene Stufung oben. */
.section--content:not(.content--doc) .content__prose > h3:first-child {
	font-size: clamp(1.5rem, 1.3rem + .8vw, 1.875rem);
	/* Gewicht aus dem Token der H2-Stimme (02-base.css), nicht mehr fest 760. */
	font-weight: var(--wg-agency);
	font-stretch: var(--w-agency);
	line-height: 1.15;
	letter-spacing: -.01em;
	text-wrap: balance;
}

/* ---------- Satz nach Struktur: chapters und story ----------
   ABWEICHUNG von 6.20 (schmale Lesespalte, rechts daneben leer): Art-
   Director-Befund „content ohne Bild als halbleere Fläche“. content.php
   wählt den Satz aus dem vorhandenen Text (Begründung dort). Unter 62rem
   bleibt alles in der Lesespalte; nur der Aufmacher (story) ist dort schon
   eine Stufe größer. Ab 62rem nutzen beide Fassungen die volle
   Containerbreite auf dem 12er-Raster. */

/* Aufmacher: der erste Absatz in Lead-Größe, ruhig in der Textstimme. */
.content__lead {
	max-width: 44ch;
	margin: 0 0 1.5rem;
	font: 500 clamp(1.1875rem, .95rem + .9vw, 1.75rem)/1.42 var(--font-text);
	color: var(--text);
	text-wrap: pretty;
}

.content__columns > :last-child {
	margin-bottom: 0;
}

/* Intro in der Prosa (chapters): Unter 62rem steht es wie zuvor unter dem
   Titel, der Kopf rückt deshalb näher heran; der Abstand zum Text folgt
   unter dem Intro. */
.content__col--chapters > :where(.section__header) {
	margin-bottom: 1rem;
}

.content__prose > :where(.content__intro) {
	margin: 0 0 var(--head-gap);
}

@media (min-width: 62rem) {
	.content__col--chapters,
	.content__col--story {
		max-width: none;
	}

	.content__col--chapters > :where(.section__header) {
		margin-bottom: var(--head-gap);
	}

	/* chapters: Randspalte 1–3 für Intro und Zwischentitel, Text in 5–12
	   (Spalte 4 bleibt Bundsteg). Die automatische Platzierung legt jeden
	   Titel in eine neue Reihe und den folgenden Absatz daneben; die Reihe
	   richtet beide an der ersten Grundlinie aus. Ränder addieren sich im
	   Raster nicht, deshalb setzt jeder Block nur seinen unteren Abstand,
	   ein Kapitel beginnt mit gleichem Abstand über Titel und Absatz. */
	.content__prose--chapters {
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
		column-gap: var(--gap);
		align-items: baseline;
		max-width: none;
	}

	.content__prose--chapters > * {
		grid-column: 5 / -1;
		max-width: 68ch;
		margin-top: 0;
	}

	.content__prose--chapters > :where(h2, h3, h4, .content__intro) {
		grid-column: 1 / span 3;
		margin-bottom: 0;
	}

	.content__prose--chapters > :where(h2, h3, h4),
	.content__prose--chapters > :where(h2, h3, h4) + * {
		margin-top: 2.5rem;
	}

	.content__prose--chapters > :where(.content__intro) {
		max-width: none;
		font-size: var(--fs-lead);
	}

	/* Folgen dem Intro zwei Absätze, reicht es über beide Reihen: Der zweite
	   Absatz rückt direkt unter den ersten, statt unter das längere Intro.
	   Ein überspannendes Element nimmt nicht an der Grundlinie teil, es steht
	   oben bündig. */
	.content__prose--chapters > :where(.content__intro:has(+ p + p)) {
		grid-row: span 2;
		align-self: start;
	}

	/* Titel am Anfang der Prosa (Stellenbezeichnung auf karriere): über die
	   Breite, sonst stünde er vier Zeilen hoch in der Randspalte, und der
	   Text daneben begänne erst unter ihm. */
	.content__prose--chapters > :where(h2, h3, h4):first-child {
		grid-column: 1 / -1;
		max-width: 32ch;
		margin: 0 0 1.25rem;
	}

	.content__prose--chapters > :where(h2, h3, h4):first-child + * {
		margin-top: 0;
	}

	/* story: Aufmacher über 1–9, der Rest in zwei Spalten über die Breite.
	   Der Text ist höchstens 2.600 Zeichen lang, jede Spalte bleibt damit
	   bei 1440 px unter einer Fensterhöhe. Absätze brechen nur mit mindestens
	   zwei Zeilen auf jeder Seite um. */
	.content__prose--story {
		max-width: none;
	}

	.content__lead {
		max-width: 46ch;
		margin-bottom: 2.5rem;
	}

	.content__columns {
		columns: 2;
		column-gap: clamp(2.5rem, 5vw, 5rem);
		orphans: 2;
		widows: 2;
	}
}

/* ===== 71-posts.css ===== */
/* =========================================================================
   71 posts und post-card (Besitz: Team E, Redaktion) – Spezifikation 6.21
   Markup: template-parts/sections/posts.php,
           template-parts/components/post-card.php
   Genutzt auch von: index.php, archive.php, templates/template-blog.php,
                     single.php („Weiterlesen“)

     div.post-list
       article.post-card[.post-card--lead|--span][.post-card--media|--text]
         div.post-card__media > img.post-card__image
         div.post-card__body
           div.post-card__head
             p.post-card__cat
             h2|h3.post-card__title > a.post-card__link (gestreckt)
           div.post-card__info
             p.post-card__excerpt                       (Aufmacher und Karten ohne Bild)
             p.post-card__meta > time · span            (Plex Mono)

   Keine Rahmen, keine Schatten, kein Hover-Lift, kein Bildzoom, keine
   Einblendung. Hover und Fokus unterstreichen den Titel, Fokus zeigt dazu
   die Outline am ganzen article. Farben über Tokens (white, mist, deep, teal).
   ========================================================================= */

/* ---------- Liste ----------
   Einspaltig; ab 48rem zwei Spalten. Der Aufmacher läuft über beide. Bleibt
   eine Karte allein in ihrer Zeile, setzt das Template post-card--span. */

.post-list {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 2.5rem 2rem;
	margin: 0;
	padding: 0;
}

@media (min-width: 48rem) {
	.post-list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.post-list > .post-card--lead,
	.post-list > .post-card--span {
		grid-column: 1 / -1;
	}
}

/* Link zum Blog unter der Liste (posts-Sektion), linksbündig. */
.posts__cta {
	margin: 3rem 0 0;
}

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

/* FIX: min-width 0, sonst sprengt ein langer Titel ohne Trennstelle die
   Rasterspalte (minmax(0, 1fr)-Thema aus dem alten Stand). */
.post-card {
	position: relative;
	min-width: 0;
}

/* Ohne Beitragsbild steht oben eine Linie, damit Kategorie und Titel nicht
   frei im Raster schweben. Keine leere Bildfläche (9.9). */
.post-card--text {
	padding-top: 1.25rem;
	border-top: 1px solid var(--line);
}

.post-card__media {
	aspect-ratio: 16 / 9;
	margin-bottom: 1rem;
}

/* Beitragsbild 16:9, Radius 2px, ohne Rahmenmarken (5.4). */
.post-card__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--r-media);
}

.post-card__body {
	min-width: 0;
}

.post-card__cat {
	margin: 0 0 .5rem;
	font: 600 var(--fs-xs)/1.35 var(--font-text);
	color: var(--accent-text);
}

/* Titel unabhängig von der Überschriftenebene (h2 im Archiv, h3 unter einer
   Sektionsüberschrift): Archivo 700 1.25rem. */
.post-card__title {
	margin: 0;
	font: 700 1.25rem/1.25 var(--font-display);
	font-stretch: 100%;
	letter-spacing: 0;
	/* FIX (Befund posts-ohne-beitragsbild): balance statt pretty. pretty ließ
	   „nicht“ allein in der letzten Zeile stehen. */
	text-wrap: balance;
}

/* FIX: Gemeinsame Geste aller Zeilen und Karten mit gestrecktem Titel-Link
   (5.5, 6.10, 6.19, 6.21). Bisher Offset .18em und Fokusring 4 px, die
   Fallstudien-Zeilen hatten .2em und 2 px. Jetzt überall: Unterstreichung
   2px in --accent-text mit Offset .2em wie jeder Link (02-base.css), bei
   Hover mit echtem Zeiger und bei Tastaturfokus; Fokusring 2px, Offset 2px am
   Container. Die Linienwerte stehen am Link, der Zustand schaltet nur die
   Linie ein. */
.post-card__link {
	color: var(--text);
	text-decoration: none;
	text-decoration-color: var(--accent-text);
	text-decoration-thickness: 2px;
	text-underline-offset: .2em;
}

/* Die ganze Karte ist Klickfläche, bleibt aber ein einziger Tabstopp. */
.post-card__link::after {
	content: "";
	position: absolute;
	inset: 0;
}

/* Fokus unterstreicht den Titel wie Hover: Die Outline am article ist das
   eigene Fokussignal, die Linie macht die Geste gleich. */
.post-card__link:focus-visible {
	text-decoration-line: underline;
}

/* Nur mit echtem Zeiger: Auf Touch bliebe :hover nach dem Antippen kleben
   (wie der Trim, 14-trim.css). :where() hält die Spezifität bei einer Klasse
   plus Zustand (8.5.4). */
@media (hover: hover) {
	.post-card:hover :where(.post-card__link) {
		text-decoration-line: underline;
	}
}

/* Fokus als Outline am article (6.21). Nur dort, wo :has() greift, verliert
   der Link seinen eigenen Ring; ältere Browser behalten ihn. */
@supports selector(:has(*)) {
	.post-card:has(:where(.post-card__link):focus-visible) {
		outline: 2px solid var(--focus);
		outline-offset: 2px;
	}

	.post-card__link:focus-visible {
		outline: none;
	}
}

.post-card__excerpt {
	max-width: 52ch;
	margin: .875rem 0 0;
	font-size: var(--fs-body);
	line-height: 1.6;
	color: var(--text-soft);
}

/* Karten ohne Bild im Raster (Weiterlesen, Archiv): Auszug eine Stufe
   kleiner als beim Aufmacher, damit Titel und Text nicht gleich laut sind. */
.post-card--text:not(.post-card--lead) .post-card__excerpt {
	margin-top: .625rem;
	font-size: var(--fs-small);
}

/* Datum und Lesedauer: echte Daten, Plex Mono 13 px (Regel 1.3, 3.4). */
.post-card__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: .25rem .5rem;
	margin: .75rem 0 0;
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text-soft);
}

/* ---------- Aufmacher ----------
   375 px: wie die übrigen Karten (6.21), nur mit Auszug. Ab 48rem große
   Titelzeile; mit Bild zuerst Bild | Text zu gleichen Teilen (Tablet, kein
   gestauchtes Desktop-Raster), ab 62rem 7fr | 5fr. */

@media (min-width: 48rem) {
	.post-card--lead .post-card__title {
		font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);
		/* Breite und Gewicht der H2-Stimme aus den Tokens (02-base.css). */
		font-weight: var(--wg-agency);
		font-stretch: var(--w-agency);
		line-height: 1.1;
		letter-spacing: -.01em;
		text-wrap: balance;
	}

	.post-card--lead .post-card__meta {
		margin-top: 1.25rem;
	}

	/* Ohne Bild wäre die Zeile sonst über die ganze Containerbreite lang. */
	.post-card--lead.post-card--text .post-card__body,
	.post-card--span.post-card--text .post-card__body {
		max-width: 44rem;
	}

	/* Mit Bild: Bild und Text nebeneinander. Gilt auch für die allein
	   stehende letzte Karte, damit sie die Zeile füllt, ohne ein Riesenbild
	   zu werden. */
	.post-card--lead.post-card--media,
	.post-card--span.post-card--media {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: 2rem;
		align-items: start;
	}

	.post-card--lead.post-card--media {
		align-items: center;
	}

	.post-card--lead.post-card--media .post-card__media,
	.post-card--span.post-card--media .post-card__media {
		margin-bottom: 0;
	}
}

/* Gemeinsame Meta-Kante im 2er-Raster: Die Meta steckt im Body, deshalb eine
   Flex-Kette Karte → Body → Info. Ein zweizeiliger Titel neben einem
   einzeiligen verschob die Meta-Zeilen sonst um eine Zeile (25 px).
   Aufmacher und allein stehende Karte haben ihr eigenes Raster. */
@media (min-width: 48rem) {
	.post-list > .post-card:where(:not(.post-card--lead, .post-card--span)) {
		display: flex;
		flex-direction: column;
	}

	.post-list > .post-card:where(:not(.post-card--lead, .post-card--span)) > .post-card__media {
		flex: none;
	}

	.post-list > .post-card:where(:not(.post-card--lead, .post-card--span)) > .post-card__body {
		display: flex;
		flex: 1 0 auto;
		flex-direction: column;
	}

	.post-list > .post-card:where(:not(.post-card--lead, .post-card--span)) .post-card__info {
		margin-top: auto;
	}
}

/* Ab 62rem: Aufmacher mit Bild 7fr | Text 5fr, gap 2.5rem (6.21). */
@media (min-width: 62rem) {
	.post-card--lead.post-card--media {
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		column-gap: 2.5rem;
	}

	/* FIX (Befund posts-ohne-beitragsbild): Ohne Beitragsbild stand der
	   Aufmacher als 44rem-Block unter einer Linie über die ganze Breite,
	   rechts blieben rund 640 px leer. Jetzt dieselbe Aufteilung wie mit Bild:
	   Kategorie und Titel links (7fr), Auszug und Meta rechts (5fr), oben
	   bündig; bei der allein stehenden Karte ohne Auszug sitzt die Meta auf
	   der Grundlinie des Titels. */
	.post-card--text:is(.post-card--lead, .post-card--span) .post-card__body {
		display: grid;
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		column-gap: 2.5rem;
		align-items: start;
		max-width: none;
	}

	.post-card--lead.post-card--text .post-card__excerpt {
		margin-top: 0;
	}

	.post-card--span.post-card--text .post-card__info {
		align-self: end;
	}

	.post-card--span.post-card--text .post-card__meta {
		margin-top: 0;
	}

	/* Mit Auszug (Runde 3) steht die Info-Gruppe oben bündig mit der
	   Kategorie wie beim Aufmacher, die Meta folgt mit Abstand. */
	.post-card--span.post-card--text .post-card__info:has(.post-card__excerpt) {
		align-self: start;
	}

	.post-card--span.post-card--text .post-card__excerpt {
		margin-top: 0;
	}

	.post-card--span.post-card--text .post-card__excerpt + .post-card__meta {
		margin-top: .75rem;
	}
}

/* ===== 72-archive.css ===== */
/* =========================================================================
   72 Blog-Archiv (Besitz: Team E, Redaktion) – Spezifikation 6.22
   Markup: index.php (Ratgeber), archive.php, templates/template-blog.php;
           der Seitenkopf auch in search.php (75-404-search.css ergänzt)
           und als h1-Rückfall in page.php, front-page.php und
           templates/template-landing.php, wenn keine Baukasten-Zeilen
           gepflegt sind (9.5)

     section.section.page-head
       div.page-head__inner
         nav.breadcrumbs--inline      (Team A)
         p.eyebrow
         h1.page-head__title          (Tafel nur bei gepflegten {Klammern})
         p|div.page-head__intro
         nav.chip-nav > ul.chip-nav__list > li > a.chip[aria-current]
     section.section.post-archive
       div.post-list | div.result-list | div.post-archive__empty
       nav.pagination                 (Team A)

   Der Seitenkopf ist ein breiter Hero ohne Vertrauenszeile: linksbündig,
   H1 in Seitenkopf-Größe, Beschreibung höchstens 62ch. Keine Zentrierung.
   ========================================================================= */

/* ---------- Seitenkopf ---------- */

.page-head__inner {
	min-width: 0;
}

/* H1 Seitenkopf (3.4): Archivo 780, stretch 94 %, --fs-h1-page / 1.08,
   höchstens 20ch. Bis 30rem Silbentrennung (02-base.css). Mit Tafel gilt
   line-height 1.16 (06-highlight.css).
   FIX: Breite aus --stretch-title (94 %, unter 24rem 86 %, 00-tokens.css).
   Das feste 94 % überstimmte die 24rem-Regel aus 02-base.css in jeder
   Breite. */
.page-head__title {
	max-width: 20ch;
	font-size: var(--fs-h1-page);
	font-weight: 780;
	font-stretch: var(--stretch-title);
	line-height: 1.08;
}

/* Beschreibung: Archiv-Beschreibungen kommen als HTML mit <p>, die
   Ratgeber-Einleitung als reiner Text. Beide gleich. */
.page-head__intro {
	max-width: 62ch;
	margin: 1.25rem 0 0;
	font-size: var(--fs-body);
	line-height: 1.55;
	color: var(--text-soft);
}

.page-head__intro > :last-child {
	margin-bottom: 0;
}

@media (min-width: 48rem) {
	.page-head__intro {
		margin-top: 1.5rem;
		font-size: var(--fs-lead);
	}
}

/* ---------- Themen-Chips ----------
   .chip selbst (Rand, 40 px, aktiver Chip auf Studio, Trefferfläche 44 px)
   kommt aus 16-lists-checks-stars.css. */

.chip-nav {
	margin-top: 2rem;
}

.chip-nav__list {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.chip-nav__list > li {
	min-width: 0;
	max-width: 100%;
}

/* In der Ratgeber-Vorlage stehen die Chips über der Liste statt im Kopf. */
.post-archive__chips {
	margin: 0 0 clamp(2rem, 4vw, 3rem);
}

/* ---------- Liste und leerer Zustand ---------- */

.post-archive__empty {
	max-width: 44rem;
}

/* Lead-Satz (3.4 Lead): Schibsted, kein Überschriften-Look ohne
   Überschriften-Semantik. */
.post-archive__empty-lead {
	margin: 0 0 .75rem;
	font-size: var(--fs-lead);
	line-height: 1.55;
	color: var(--text);
}

.post-archive__empty p:not([class]) {
	max-width: 60ch;
	color: var(--text-soft);
}

.post-archive__empty .btn-row {
	margin-top: 1.5rem;
}

/* Unter 48rem Button über die volle Breite, wie alle CTAs unter Inhalten
   (Sektions-CTAs btn--lg, mobil btn--block, Umschaltpunkt 48rem wie Hero,
   channel_proof und cta_band). smm_main_cta() liefert schon btn--lg.
   Vorher galt die volle Breite nur bis 30rem, zwischen 480 und 767 px stand
   der Button als einziger CTA inhaltsbreit. */
@media (max-width: 47.99rem) {
	.post-archive__empty .btn {
		display: flex;
		width: 100%;
	}

	.post-archive__empty .btn__label {
		flex: 1;
	}
}

/* ===== 73-single.css ===== */
/* =========================================================================
   73 Einzelartikel (Besitz: Team E, Redaktion) – Spezifikation 6.23
   Markup: single.php

     article.article
       header.article__head > .container > .article__col
         nav.breadcrumbs--inline (Team A) · ul.article__cats (Chips klein)
         h1.article__title · p.article__lead · p.article__meta (Plex Mono)
       .container > figure.article__figure > img.article__image
       .container > .article__layout[.article__layout--track]
         nav.chapter-track.chapter-track--aside           (ab 75rem, klebt rechts)
         .article__col
           div.article__body.prose   (Fließtext, Blöcke 74-blocks.css)
             …Vorspann…
             details.chapter-track.chapter-track--inline   (unter 75rem)
             div.article__chapter × n  (je eine H2 und ihr Abschnitt)
           ul.article__tags          (Chips klein)
       div.article__cta > .container > div.inline-cta.theme-studio
     section.section--bg-mist.article-related (Karten ohne Aufmacher, 71-posts.css)

   Kopf und Text stehen linksbündig in einer 44rem-Spalte an der
   Rasterkante, das Beitragsbild in Containerbreite. Keine Rahmenmarken am
   Beitragsbild, keine Einblendung, kein Verlauf im Inline-CTA.
   ========================================================================= */

.article {
	display: block;
	/* FIX: Struktur-Container dürfen in Flex- und Grid-Eltern schrumpfen. */
	min-width: 0;
}

/* Lesespalte 44rem, linksbündig. */
.article__col {
	max-width: var(--container-narrow);
	min-width: 0;
}

/* ---------- Kopf ---------- */

.article__head {
	padding-top: clamp(1.5rem, 4vw, 3rem);
}

.article__cats {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: 0 0 1.25rem;
	padding: 0;
	list-style: none;
}

.article__cats > li,
.article__tags > li {
	min-width: 0;
	max-width: 100%;
}

/* H1 Artikel (6.23): Archivo 800, stretch 94 %, --fs-h1-page (32 px bei
   375 px), höchstens 20ch. Silbentrennung bis 30rem aus 02-base.css.
   FIX: Breite aus --stretch-title (94 %, unter 24rem 86 %, 00-tokens.css).
   Das feste 94 % überstimmte die 24rem-Regel aus 02-base.css in jeder
   Breite. */
.article__title {
	max-width: 20ch;
	font-size: var(--fs-h1-page);
	font-weight: 800;
	font-stretch: var(--stretch-title);
	line-height: 1.08;
	letter-spacing: -.015em;
}

.article__lead {
	max-width: 40em;
	margin: 1.25rem 0 0;
	font-size: 1.25rem;
	line-height: 1.55;
	color: var(--text-soft);
}

/* Datum, Aktualisierung, Lesedauer: echte Daten in Plex Mono 13 px. */
.article__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: .25rem .5rem;
	margin: 1.5rem 0 0;
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text-soft);
}

/* ---------- Beitragsbild ----------
   16:9 in Containerbreite, Radius 2px, ohne Marken (5.4). */

.article__figure {
	aspect-ratio: 16 / 9;
	margin: clamp(2rem, 4vw, 3rem) 0 0;
}

.article__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--r-media);
}

/* ---------- Fließtext ----------
   Typografie aus .prose (02-base.css): 17 px/1.65 mobil, 17.5 px/1.7 ab
   48rem, h2 24 px bei 375 px, h3 20 px, Listen mit Pixelquadrat. */

.article__body {
	margin-top: clamp(2rem, 4vw, 3rem);
	/* FIX: Lange URLs und zusammengesetzte Wörter schieben die Zeile auf dem
	   Handy sonst über den Rand; overflow-x: clip am Dokument schnitte sie ab. */
	overflow-wrap: break-word;
}

/* FIX (Befund artikel-tabelle-core-look): Auf Artikeln lädt WordPress die
   Block-Styles (wp-block-table, inc/performance.php). Deren Ränder
   (.wp-block-table td: 1px currentColor rundum, thead: 3px) stehen mit
   gleicher Spezifität vor app.css; .prose th/td aus 02-base.css überschreibt
   nur border-bottom. Übrig blieben dunkle Senkrechte, ein Kopfbalken und
   hellgraue Zeilentrenner. Mit einer Elementstufe mehr (0,1,2) gewinnt die
   ruhige Zeilenlinie unabhängig von der Ladereihenfolge. Die Kopffläche
   (--surface) kommt weiter aus 02-base.css. */
.article__body table :is(th, td) {
	border: 0;
	border-bottom: 1px solid var(--line);
}

.article__body table > :is(thead, tfoot) {
	border: 0;
}

/* Tabellen: figure.wp-block-table scrollt bereits (02-base.css); single.php
   gibt ihr und dem Behälter um eine Tabelle ohne figure einen Tabstopp. */
.article__table {
	max-width: 100%;
	margin-block: 0 1em;
	overflow-x: auto;
	scrollbar-width: thin;
}

.article__table > table {
	margin: 0;
}

.article__body .wp-block-table {
	scrollbar-width: thin;
}

.article__body .wp-block-table > table {
	margin: 0;
}

/* FAQ-Block (Team D) steht im Textfluss; ohne eigenen Abstand klebte er am
   Absatz davor. Mit Kapitel-Spur liegt er in einem Kapitel. */
.article__body > .faq--block,
.article__chapter > :where(.faq--block) {
	margin-block: 3rem;
}

/* Kapitel-Hülle: ohne eigene Abstände, die Ränder der Prosa fallen weiter
   zusammen. Nur der Schluss des letzten Kapitels verliert seinen Rand, wie
   .prose > :last-child ohne Hülle (02-base.css). */
.article__chapter:last-child > :last-child {
	margin-bottom: 0;
}

/* ---------- Mehrseitige Beiträge (wp_link_pages) ----------
   Wie die Paginierung (6.27): 44-px-Quadrate, aktuelle Seite auf Studio. */

.page-links {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem;
	margin-top: 2.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--line);
}

.page-links .post-page-numbers {
	display: inline-grid;
	place-items: center;
	min-width: 2.75rem;
	height: 2.75rem;
	padding-inline: .5rem;
	border: 1.5px solid var(--line-ui);
	border-radius: var(--r-control);
	color: var(--text);
	font: 600 var(--fs-small)/1 var(--font-text);
	font-variant-numeric: tabular-nums;
	text-decoration: none;
}

.page-links a.post-page-numbers:hover {
	border-color: var(--ghost-bg-h);
	background: var(--ghost-bg-h);
	color: var(--ghost-fg-h);
}

.page-links .current {
	border-color: transparent;
	background: var(--c-studio);
	color: var(--c-white);
}

/* ---------- Schlagwörter ---------- */

.article__tags {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: 3rem 0 0;
	padding: 1.5rem 0 0;
	border-top: 1px solid var(--line);
	list-style: none;
}

/* FIX (Befund artikel-details): Endet der Artikel mit dem FAQ-Block, liegt
   dessen Unterkante 3rem über der Linie der Schlagwörter; zwei parallele
   Linien mit Leere dazwischen. Dann trennt die FAQ-Linie allein. */
.article__body:where(:has(> .faq--block:last-child, > :last-child > .faq--block:last-child)) + .article__tags {
	padding-top: 0;
	border-top: 0;
}

/* ---------- Inline-CTA am Artikelende ----------
   Studio-Panel, Radius 4px, kein Verlauf, kein Schatten. Zeitmarke rechts
   mittig neben dem Text, wenn der Text eine Dauer nennt (5.8); unter 62rem als Kopfzeile über
   dem Titel (siehe unten). Der
   Primärbutton nimmt über .theme-studio die helle Variante. */

.article__cta {
	padding-block: clamp(3rem, 6vw, 5rem) var(--section-y);
}

.inline-cta {
	display: grid;
	/* FIX: minmax(0, 1fr) statt 1fr/auto. Ohne Deckelung wird die Spur so
	   breit wie der breiteste Inhalt und schiebt den Text auf dem Handy aus
	   dem Bild (alter Stand). */
	grid-template-columns: minmax(0, 1fr);
	gap: 2rem;
	padding: 2rem 1.25rem;
	border-radius: var(--r-panel);
}

.inline-cta__main,
.inline-cta__side {
	min-width: 0;
}

.inline-cta__title {
	max-width: 22ch;
	margin: 0 0 .875rem;
	font: 760 clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem)/1.1 var(--font-display);
	font-stretch: 96%;
	letter-spacing: -.01em;
	color: var(--text);
	text-wrap: balance;
}

.inline-cta__desc {
	max-width: 52ch;
	margin: 0;
	font-size: var(--fs-body);
	line-height: 1.6;
	color: var(--text-soft);
}

.inline-cta__actions {
	margin-top: 1.75rem;
}

/* Sektions-CTA-Regel: btn--lg btn--block aus single.php, ab 48rem wieder
   natürliche Breite. Unter 48rem stehen Primär- und Kalenderbutton
   untereinander. FIX (Befund button-label-umbruch-mobil): Bricht ein Label
   zweizeilig um, war der eine Button 66 px hoch und der andere 56 px. Das
   Raster gibt beiden Zeilen dieselbe Höhe; stretch und minmax(0, 1fr) heben
   align-items: center und justify-content: flex-start aus .btn-row auf. */
@media (max-width: 47.99rem) {
	.inline-cta__actions {
		display: grid;
		grid-template-columns: minmax(0, 1fr);
		grid-auto-rows: 1fr;
		align-items: stretch;
	}
}

@media (min-width: 48rem) {
	.inline-cta__actions :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

@media (min-width: 48rem) {
	.inline-cta {
		padding: clamp(2.5rem, 5vw, 4rem);
	}

	.inline-cta__desc {
		font-size: 1.125rem;
	}
}

/* ABWEICHUNG von 5.8/6.16 („unter 62rem unter den Buttons“, „gemeinsame
   Unterkante“), gleiche Regel wie .cta-band__inner--mark (63-cta-band.css,
   Befund „Zeitmarke 30:00 ist statische Deko“):
   Unter 62rem Kopfzeile über dem Titel, Timecode und Clip in einer Zeile,
   der Clip auf der Grundlinie der Ziffern. order verschiebt nur die
   Darstellung; die Seitenspalte ist aria-hidden und nicht fokussierbar.
   Ab 62rem Timecode und Leiste als Einheit mittig neben dem Text (unten). */
.inline-cta {
	--inline-cta-title-fs: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);
}

.inline-cta__title {
	font-size: var(--inline-cta-title-fs);
}

@media (max-width: 61.99rem) {
	.inline-cta--mark {
		--timemark-fs: 3.5rem;
		row-gap: 1.75rem;
	}

	.inline-cta__side:where(.inline-cta--mark > *) {
		order: -1;
	}

	.timemark:where(.inline-cta--mark *) {
		display: flex;
		align-items: baseline;
		column-gap: 1rem;
	}

	.timemark__clip:where(.inline-cta--mark *) {
		flex: 1 1 0;
		min-width: 0;
		margin-top: 0;
	}
}

@media (min-width: 48rem) and (max-width: 61.99rem) {
	.inline-cta--mark {
		--timemark-fs: 4.5rem;
		row-gap: 2rem;
	}

	.timemark:where(.inline-cta--mark *) {
		column-gap: 1.5rem;
	}
}

/* Ab 62rem: Text 7fr | Zeitmarke 4fr. Ohne Zeitmarke bleibt das Panel
   einspaltig mit begrenzter Breite.
   ABWEICHUNG (Abnahme Runde 4, gleiche Regel wie „Zeitmarke als Einheit“ in
   63-cta-band.css): Die Zeitmarke stand oben an der Titelzeile, die Leiste
   lief über die volle Spalte, darunter blieben rund 170 px Leere. Jetzt
   schrumpft die Seitenspalte auf den Timecode (justify-self), die Leiste ist
   so breit wie die Ziffern, und die Einheit steht vertikal mittig neben dem
   Text, rechts bündig an der Innenkante des Panels. Die Ausrichtungsrechnung
   an der Versalhöhe entfällt damit. */
@media (min-width: 62rem) {
	.inline-cta--mark {
		--timemark-fs: var(--fs-time);
		grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
		column-gap: 4rem;
		align-items: center;
	}

	.inline-cta__side:where(.inline-cta--mark > *) {
		justify-self: end;
	}

	.inline-cta:not(.inline-cta--mark) .inline-cta__main {
		max-width: 48rem;
	}
}

/* =========================================================================
   Kapitel-Spur (Art-Director-Verbesserung „Kapitel-Spur im Ratgeber“)

   ABWEICHUNG: 5.6 kennt die Schnitt-Spur nur in process. Artikel haben
   keinen process; auf der Seite gibt es weiter genau einen Playhead. Nur
   echte Daten: die H2 als Namen, die Wortzahl je Abschnitt (--n) als Länge,
   die vorhandene Lesedauer am Spurkopf.

   ABWEICHUNG (Befund „Spur-Elemente wirken unfertig“): Die Clips hatten eine
   Höhe nach Wortzahl. Lange Kapitel wurden hohe, leere Kacheln, kurze flache;
   das sah nach kaputten Boxen aus. Jetzt ist jedes Kapitel eine gleich
   gebaute Zeile: Name, darunter ein schmaler Längenstrich. Seine Breite ist
   das Verhältnis der Wortzahl zum längsten Kapitel (--n am li durch --n an
   der Liste). Der längste Abschnitt füllt die Zeile.

   Zustände:
     ohne JS                     gleichwertige Zeilen mit grauem Strich,
                                 vollständige Sprungliste
     JS (aria-current)           aktuelle Zeile auf Kreide, Name in Tinte,
                                 Strich in Teal; die übrigen Namen treten in
                                 --text-soft zurück
     animation-timeline und      der Strich jedes Kapitels füllt sich beim
     no-preference               Lesen von links (gelesen = voll), an der
                                 Füllkante des laufenden Kapitels steht der
                                 Playhead
   ========================================================================= */

/* Kopf: Name und Lesedauer auf einer Zeile, wie im Kopf der aufklappbaren
   Fassung. */
.chapter-track__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: .75rem;
	row-gap: .25rem;
	margin: 0;
}

.chapter-track__list {
	/* --n an der Liste: Wortzahl des längsten Kapitels (single.php). Hier
	   aufgelöst, damit die li mit ihrem eigenen --n darauf zugreifen. */
	--ch-max: var(--n, 1);
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
	list-style-type: "";
}

/* .prose li + li (02-base.css) greift in der mobilen Variante, die im
   Fließtext steht; gleiche Spezifität, spätere Regel. */
.chapter-track li + li {
	margin-top: 0;
}

.chapter-track__item {
	--ch-len: calc(var(--n, 1) / var(--ch-max, 1));
	display: block;
	min-width: 0;
	margin: 0;
	padding: 0;
}

/* Zeile: die ganze Zeile ist der Link, mindestens 44 px hoch (9.5).
   Schibsted, nicht Mono: der Name ist Text, keine Messgröße (Regel 1.3). */
.chapter-track__clip {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-content: start;
	row-gap: .5rem;
	min-width: 0;
	min-height: 2.75rem;
	padding: .625rem .75rem .75rem;
	border-radius: 2px;
	color: var(--text);
	font: 600 var(--fs-xs)/1.35 var(--font-text);
	text-decoration: none;
	overflow-wrap: break-word;
}

.chapter-track__label {
	min-width: 0;
	text-decoration-color: var(--accent-text);
	text-decoration-thickness: 2px;
	text-underline-offset: .2em;
	text-wrap: pretty;
}

/* Längenstrich: 4 px, Breite nach Wortzahl, mindestens so breit, dass auch
   ein kurzes Kapitel (FAQ) einen erkennbaren Strich hat. Rein dekorativ
   (aria-hidden), die Länge steckt nicht als Text in der Navigation. */
.chapter-track__len {
	position: relative;
	display: block;
	width: max(1rem, calc(var(--ch-len) * 100%));
	height: 4px;
	border-radius: 1px;
	background: var(--line);
}

/* Füllung des Strichs, von links. Ruhezustand leer. */
.chapter-track__len::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: var(--clip-on-bg);
	transform: scaleX(0);
	transform-origin: left center;
}

/* Hover nur mit echtem Zeiger (wie Post-Karte und Suchzeile). */
@media (hover: hover) {
	.chapter-track__clip:hover .chapter-track__label {
		text-decoration-line: underline;
	}
}

.chapter-track__clip:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}

.chapter-track__clip:focus-visible .chapter-track__label {
	text-decoration-line: underline;
}

/* Aktueller Abschnitt (aria-current, nur mit JS): Zeile auf Kreide, Name in
   Tinte, Strich voll in Teal (#156A72 auf Weiß 6,29, auf Kreide 5,6). Die
   übrigen Namen treten zurück (#4A5758, 7,5). Kein Balken an der Zeilenkante
   (Akzentleiste, 9.6). */
.chapter-track__clip[aria-current] {
	background: var(--surface);
	color: var(--text);
}

.chapter-track__list:has([aria-current]) .chapter-track__clip:not([aria-current]) {
	color: var(--text-soft);
}

.chapter-track__clip[aria-current] .chapter-track__len::before {
	transform: none;
}

@media (forced-colors: active) {
	.chapter-track__clip[aria-current] {
		outline: 2px solid CanvasText;
		outline-offset: -2px;
	}

	.chapter-track__len {
		forced-color-adjust: none;
		background: GrayText;
	}

	.chapter-track__len::before {
		background: CanvasText;
	}
}

/* Name „Inhalt“ und Lesedauer (echte Meta-Angabe, Plex Mono 13 px). */
.chapter-track__name {
	font: 600 var(--fs-xs)/1.35 var(--font-text);
}

.chapter-track__time {
	margin: 0;
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text-soft);
}

/* ---------- Unter 75rem: details vor der ersten H2 ----------
   Zu: Name, Lesedauer, Pfeil und darunter die Spur im Kleinen (Abschnitte
   nebeneinander, Breite nach Wortzahl). Auf: die Kapitelzeilen. Kein
   Öffnen-Übergang (7.3 kennt nur die FAQ-Höhe). */

.chapter-track--inline {
	margin-block: 2rem;
}

.chapter-track__summary {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	column-gap: .75rem;
	row-gap: .75rem;
	min-height: 2.75rem;
	padding-block: .5rem .75rem;
	color: var(--text);
	list-style: none;
	cursor: pointer;
}

.chapter-track__summary::-webkit-details-marker {
	display: none;
}

.chapter-track__summary:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 4px;
}

@media (hover: hover) {
	.chapter-track__summary:hover .chapter-track__name {
		text-decoration: underline;
		text-decoration-thickness: 2px;
		text-decoration-color: var(--accent-text);
		text-underline-offset: .2em;
	}
}

.chapter-track__chevron {
	width: 18px;
	height: 18px;
	color: var(--accent-text);
}

.chapter-track--inline[open] .chapter-track__chevron {
	transform: rotate(180deg);
}

/* Spur im Kleinen: Abschnitte mit Anteil nach Wortzahl, Schnitt 3 px. Rein
   dekorativ (aria-hidden), die Namen stehen in der Liste. */
.chapter-track__strip {
	grid-column: 1 / -1;
	display: flex;
	gap: 3px;
	height: .5rem;
}

.chapter-track__seg {
	flex: var(--n, 1) 1 0;
	min-width: .25rem;
	border-radius: 1px;
	/* Gleicher Ton wie die Längenstriche der Zeilen darunter. */
	background: var(--line);
}

/* Zeilen bündig mit dem Fließtext: der Innenabstand der Zeile steht links
   vor der Satzkante, wie die Tafel-Einzüge (.hl--plate, .caption-plate). */
.chapter-track--inline .chapter-track__nav {
	margin-inline: -.75rem;
	padding-bottom: .5rem;
}

/* ---------- Ab 75rem: klebende Spur rechts neben dem Text ----------
   Die Lesespalte behält ihre 44rem an der Rasterkante; die Spur steht an
   der rechten Containerkante und beginnt auf Höhe des Fließtexts. */

.chapter-track--aside {
	display: none;
}

@media (min-width: 75rem) {
	.chapter-track--inline {
		display: none;
	}

	.article__layout--track {
		display: grid;
		grid-template-columns: minmax(0, var(--container-narrow)) minmax(0, 1fr);
		column-gap: clamp(3rem, 5vw, 6rem);
	}

	/* Die Spur steht im DOM vor dem Text (Tab-Reihenfolge), sichtbar rechts. */
	.article__layout--track > .article__col {
		grid-row: 1;
		grid-column: 1;
	}

	.chapter-track--aside {
		grid-row: 1;
		grid-column: 2;
		position: sticky;
		top: calc(var(--header-h) + 2rem);
		display: flex;
		flex-direction: column;
		gap: .75rem;
		align-self: start;
		justify-self: end;
		width: min(100%, 18.5rem);
		/* Höhe nach Inhalt. Reicht der Platz nicht, scrollt die Spur in sich
		   (33-chapter-track.js holt die aktuelle Zeile in den Blick). Unten
		   bleiben 5.5rem frei: Bis etwa 1300 px läge der Nach-oben-Knopf
		   (34-floating.css, 44 px, 1.25rem vom Rand) sonst über der letzten
		   Zeile. */
		max-height: calc(100vh - var(--header-h) - 7.5rem);
		max-height: calc(100svh - var(--header-h) - 7.5rem);
		margin-top: clamp(2rem, 4vw, 3rem);
		overflow-y: auto;
		/* Platz für Fokusring und Playhead, die der Scrollbereich sonst
		   abschnitte. */
		padding: 4px;
		scrollbar-width: thin;
	}

	.chapter-track--aside .chapter-track__head {
		padding-inline: .75rem;
	}
}

@media (min-width: 75rem) and (max-height: 38rem) {
	.chapter-track--aside {
		position: static;
		max-height: none;
	}
}

/* ---------- Lese-Fortschritt (Inventar 7.3 Nr. 4 sinngemäß) ----------
   Jedes Kapitel ist eine View-Timeline (--ch1 … --ch12). timeline-scope an
   .article macht die Namen für die Spur sichtbar, die nicht im Kapitel
   steht. exit-crossing mit Einzug 30 %: Das Kapitel läuft, solange seine
   Ober- bis Unterkante die Leselinie bei 30 % der Fensterhöhe kreuzt
   (dieselbe Linie wie 33-chapter-track.js).
   - Füllung (::before am Strich): scaleX 0 → 1, bleibt gefüllt.
   - Playhead (::after am Strich): 2 px breiter Strich in --playhead, 12 px
     hoch, an der Füllkante. Die Ebene ist so breit wie der Strich, nur ihr
     rechter Rand ist gefärbt; translateX −100 % → 0 führt ihn mit der
     Füllung. Sichtbar nur, solange das Kapitel läuft (fill-mode none, sonst
     opacity 0); mit JS hält die aktuelle Zeile ihn auch in der Lücke
     zwischen zwei Kapiteln.
   Animiert werden nur transform und opacity (7.1). Ohne Unterstützung, bei
   reduzierter Bewegung und ab dem 13. Kapitel: kein Fortschritt, die
   aktuelle Zeile trägt den vollen Strich (siehe oben). */
@supports (animation-timeline: view()) and (timeline-scope: --a) {
	@media (prefers-reduced-motion: no-preference) {
		.article:has(.article__chapter) {
			timeline-scope: --ch1, --ch2, --ch3, --ch4, --ch5, --ch6, --ch7, --ch8, --ch9, --ch10, --ch11, --ch12;
		}

		.article__chapter {
			view-timeline-inset: 30% 0%;
		}

		.article__chapter:nth-child(1 of .article__chapter) { view-timeline-name: --ch1; }
		.article__chapter:nth-child(2 of .article__chapter) { view-timeline-name: --ch2; }
		.article__chapter:nth-child(3 of .article__chapter) { view-timeline-name: --ch3; }
		.article__chapter:nth-child(4 of .article__chapter) { view-timeline-name: --ch4; }
		.article__chapter:nth-child(5 of .article__chapter) { view-timeline-name: --ch5; }
		.article__chapter:nth-child(6 of .article__chapter) { view-timeline-name: --ch6; }
		.article__chapter:nth-child(7 of .article__chapter) { view-timeline-name: --ch7; }
		.article__chapter:nth-child(8 of .article__chapter) { view-timeline-name: --ch8; }
		.article__chapter:nth-child(9 of .article__chapter) { view-timeline-name: --ch9; }
		.article__chapter:nth-child(10 of .article__chapter) { view-timeline-name: --ch10; }
		.article__chapter:nth-child(11 of .article__chapter) { view-timeline-name: --ch11; }
		.article__chapter:nth-child(12 of .article__chapter) { view-timeline-name: --ch12; }

		/* Spezifität bewusst niedrig (:where): Die Kapitelregeln unten setzen
		   nur animation-timeline und müssen die Kurzschreibweise hier
		   überstimmen, sonst liefe die Füllung auf der Dokument-Zeitleiste
		   sofort ans Ende. Ab dem 13. Kapitel keine Animation, ohne Hülle
		   (.article__chapter) auch nicht. */
		:where(.article:has(.article__chapter) .chapter-track__item:nth-child(-n + 12)) .chapter-track__len::before {
			animation: chapter-fill linear both;
			animation-range: exit-crossing 0% exit-crossing 100%;
		}

		:where(.article:has(.article__chapter) .chapter-track__item:nth-child(-n + 12)) .chapter-track__len::after {
			content: "";
			position: absolute;
			z-index: var(--z-raised);
			top: -4px;
			left: 0;
			width: 100%;
			height: 12px;
			background: linear-gradient(var(--playhead) 0 0) right top / 2px 100% no-repeat;
			opacity: 0;
			pointer-events: none;
			animation: chapter-play linear none;
			animation-range: exit-crossing 0% exit-crossing 100%;
		}

		/* Zwischen zwei Kapiteln liegt der zusammengefallene Rand der nächsten
		   Überschrift (bis 85 px). Dort ist kein Kapitel „am Laufen“, der
		   Playhead verschwände kurz. Mit JS hält die aktuelle Zeile ihn deshalb
		   an der Füllkante, bis das nächste Kapitel übernimmt. */
		:where(.article:has(.article__chapter) .chapter-track__item:nth-child(-n + 12)) [aria-current] .chapter-track__len::after {
			animation-fill-mode: both;
		}

		:where(.chapter-track__item:nth-child(1)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(1)) .chapter-track__len::after { animation-timeline: --ch1; }
		:where(.chapter-track__item:nth-child(2)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(2)) .chapter-track__len::after { animation-timeline: --ch2; }
		:where(.chapter-track__item:nth-child(3)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(3)) .chapter-track__len::after { animation-timeline: --ch3; }
		:where(.chapter-track__item:nth-child(4)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(4)) .chapter-track__len::after { animation-timeline: --ch4; }
		:where(.chapter-track__item:nth-child(5)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(5)) .chapter-track__len::after { animation-timeline: --ch5; }
		:where(.chapter-track__item:nth-child(6)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(6)) .chapter-track__len::after { animation-timeline: --ch6; }
		:where(.chapter-track__item:nth-child(7)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(7)) .chapter-track__len::after { animation-timeline: --ch7; }
		:where(.chapter-track__item:nth-child(8)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(8)) .chapter-track__len::after { animation-timeline: --ch8; }
		:where(.chapter-track__item:nth-child(9)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(9)) .chapter-track__len::after { animation-timeline: --ch9; }
		:where(.chapter-track__item:nth-child(10)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(10)) .chapter-track__len::after { animation-timeline: --ch10; }
		:where(.chapter-track__item:nth-child(11)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(11)) .chapter-track__len::after { animation-timeline: --ch11; }
		:where(.chapter-track__item:nth-child(12)) .chapter-track__len::before,
		:where(.chapter-track__item:nth-child(12)) .chapter-track__len::after { animation-timeline: --ch12; }
	}
}

@keyframes chapter-fill {
	from { transform: scaleX(0); }
	to { transform: scaleX(1); }
}

@keyframes chapter-play {
	from { opacity: 1; transform: translateX(-100%); }
	to { opacity: 1; transform: translateX(0); }
}

/* ===== 74-blocks.css ===== */
/* =========================================================================
   74 Blöcke im Artikel (Besitz: Team E, Redaktion) – Spezifikation 6.23
   Markup: template-parts/blocks/smm-takeaway.php, smm-quote.php,
           smm-cta-box.php
   (smm-faq-block: 62-faq.css, Team D · smm-video-block: 45-video-sections.css, Team B)

   Keine Seitenleisten, keine Akzentlinien, keine Schatten, keine
   Untertitel-Tafel und keine Zeitmarke in Blöcken (5.1, 5.8, 9.6).
   375 px: Blöcke in voller Spaltenbreite mit Padding 1.25rem.
   ========================================================================= */

/* ---------- smm-takeaway: Das Wichtigste in Kürze ----------
   Ruhige Fläche (--surface: Kreide auf Weiß), Radius 4px. Liste mit den
   Pixelquadraten aus .bullets (16-lists-checks-stars.css). */

.blk-takeaway {
	margin-block: 2.5rem;
	padding: 1.25rem;
	border-radius: var(--r-panel);
	background: var(--surface);
	color: var(--text);
}

.blk-takeaway__title {
	margin: 0 0 1rem;
	font: 600 var(--fs-xs)/1.35 var(--font-text);
	color: var(--text-soft);
}

.blk-takeaway__list {
	margin: 0;
	font-size: var(--fs-body);
	line-height: 1.55;
}

/* .prose setzt Abstände zwischen Listenpunkten; hier regelt das gap der Liste. */
.blk-takeaway__list > li + li {
	margin-top: 0;
}

/* ---------- smm-quote: Hervorgehobenes Zitat ----------
   O-Ton: schmal und schwer (Leitidee 1), hängendes „ ohne Seitenlinie.
   Person und Position als Bauchbinde (13-lower-third.css). */

.blk-quote {
	margin-block: 3rem;
}

.blk-quote__text {
	margin: 0;
	padding: 0;
	font: 650 clamp(1.375rem, 1.1rem + 1vw, 1.875rem)/1.3 var(--font-display);
	font-stretch: 88%;
	letter-spacing: -.005em;
	color: var(--text);
	/* Das „ steht vor der Satzkante, der Text fluchtet mit dem Fließtext.
	   Der Überhang ist kleiner als der seitliche Gutter (18 px bei 320 px). */
	text-indent: -.42em;
	text-wrap: pretty;
}

.blk-quote > .blk-quote__author {
	/* FIX: Die Bildunterschrift-Regel aus 02-base.css gilt nur noch für
	   figcaption ohne Klasse bzw. mit Core-Klassen, der Autor erbt Größe und
	   Farbe also ohnehin; font-size/color: inherit entfallen. Der Abstand
	   bleibt: Die Bauchbinde braucht Luft unter dem Zitat. */
	margin-top: 1.25rem;
}

/* ---------- smm-cta-box: CTA-Kasten ----------
   Kompaktes Studio-Panel, Radius 4px. Titel Archivo 760 1.5rem weiß ohne
   Tafel, Text #A7C0C2 (--text-soft auf Studio, 8,44:1), Button hell über
   die Tokens von .theme-studio. */

.blk-cta {
	margin-block: 2.5rem;
	padding: 1.25rem;
	border-radius: var(--r-panel);
}

.blk-cta__title {
	margin: 0 0 .625rem;
	font: 760 1.5rem/1.2 var(--font-display);
	font-stretch: 96%;
	letter-spacing: -.005em;
	color: var(--text);
	text-wrap: balance;
}

.blk-cta__text {
	margin: 0;
	font-size: var(--fs-body);
	line-height: 1.6;
	color: var(--text-soft);
}

.blk-cta__actions {
	margin-top: 1.25rem;
}

/* 375 px: Button über die volle Kastenbreite (4.5), Beschriftung darf umbrechen. */
@media (max-width: 47.99rem) {
	.blk-cta__actions .btn {
		display: flex;
		width: 100%;
	}

	.blk-cta__actions .btn__label {
		flex: 1;
	}
}

@media (min-width: 48rem) {
	.blk-takeaway,
	.blk-cta {
		padding: 1.75rem;
	}
}

/* ===== 75-404-search.css ===== */
/* =========================================================================
   75 404 und Suche (Besitz: Team E, Redaktion) – Spezifikation 6.24, 6.25
   Markup: 404.php, search.php, searchform.php (Feldoptik: 11-forms.css, F)

   404:   section.notfound > .notfound__inner
            h1.notfound__title · p.notfound__text
            div.notfound__actions > div.notfound__search + a.btn--ghost
            div.notfound__popular > p.notfound__label + nav > ul.notfound__chips
            div.notfound__mark
              p.notfound__code                        echter Statuscode
              span.notfound__clip[aria-hidden]        Clip, Griffe, Playhead auf null
   Suche: section.page-head (Grundlage 72-archive.css)
            … h1.page-head__title · p.page-head__count · div.page-head__search
          div.result-list > article.result-row.trim.trim--hover
          div.search-empty

   Linksbündig, keine Zentrierung. ABWEICHUNG 404: Statuscode als Zeitmarke
   mit leerem Clip (siehe 404.php).
   ========================================================================= */

/* ---------- 404 ---------- */

/* Abstand wie der breite Hero (6.3), nicht wie eine Inhaltssektion. */
.notfound {
	padding-block: clamp(3rem, 6vw, 6rem) clamp(3.5rem, 6vw, 5.5rem);
}

.notfound__inner {
	max-width: 60rem;
	min-width: 0;
}

/* ---------- Statuscode als Zeitmarke ----------
   Grammatik aus 5.8 (17-timemark.css), hier nachgebaut statt die
   .timemark-Klassen zu leihen: Dort ist der Playhead an den Zeitraffer aus
   34-timemark.js gebunden und im Ruhezustand unsichtbar. Hier steht er fest
   am Einstiegspunkt, denn der Clip wurde nie abgespielt. Keine Bewegung,
   also auch ohne JS, bei reduzierter Bewegung und im Druck dasselbe Bild.

   Unter 62rem Schlusszeile unter den Chips wie die Kopfzeile im cta_band
   (63-cta-band.css): Ziffern und Clip in einer Zeile, der Clip steht auf der
   Grundlinie der Ziffern (ohne Text liegt seine Grundlinie an der
   Unterkante). Größe 3.5rem, ab 48rem 4.5rem wie dort.
   Farben über Tokens: 404 in --accent-text (#156A72 auf Weiß, 6,29),
   Clip --surface (Kreide), Griffe --trim (Teal), Playhead --playhead (Tinte). */
.notfound__mark {
	--notfound-mark-fs: 3.5rem;
	display: flex;
	align-items: baseline;
	column-gap: 1rem;
	margin-top: 3rem;
}

.notfound__code {
	flex: none;
	margin: 0;
	font: 800 var(--notfound-mark-fs)/.9 var(--font-display);
	font-stretch: 72%;
	/* Tabellarische Versalziffern wie im Timecode (tnum in archivo-var.woff2). */
	font-variant-numeric: tabular-nums lining-nums;
	letter-spacing: -.01em;
	color: var(--accent-text);
	white-space: nowrap;
}

/* Clip mit festen Trim-Griffen (5.5), 12 px hoch wie in 5.8. */
.notfound__clip {
	position: relative;
	display: block;
	flex: 1 1 0;
	min-width: 0;
	height: .75rem;
	background:
		linear-gradient(var(--trim) 0 0) left / 6px 100% no-repeat,
		linear-gradient(var(--trim) 0 0) right / 6px 100% no-repeat,
		var(--surface);
}

/* Playhead auf null, Grammatik wie in der Schnitt-Spur (5.6): 2 px Strich
   mit 10-px-Quadrat als Kopf über dem Clip. Mitte 7 px wie der Einstiegs-
   punkt in 17-timemark.css (--timemark-in): Innenkante des Griffs plus
   1 px, der Strich steht also neben dem Griff, nie darauf. */
.notfound__clip::before {
	content: "";
	position: absolute;
	top: -.625rem;
	bottom: -.25rem;
	left: 2px;
	width: 10px;
	background:
		linear-gradient(var(--playhead) 0 0) 50% 0 / 10px 10px no-repeat,
		linear-gradient(var(--playhead) 0 0) 50% 0 / 2px 100% no-repeat;
	pointer-events: none;
}

/* H1 wie im breiten Hero (3.4): Archivo 800, stretch 94 % (unter 24rem 86 %),
   höchstens 18ch. Unter 48rem 34 px wie der Hero, --fs-h1-wide begänne bei
   40 px. Keine Tafel.
   FIX: Breite aus --stretch-title (00-tokens.css). Das feste 94 % überstimmte
   die 24rem-Regel aus 02-base.css in jeder Breite. */
.notfound__title {
	max-width: 18ch;
	font-size: var(--fs-h1-split);
	font-weight: 800;
	font-stretch: var(--stretch-title);
	line-height: 1.1;
	letter-spacing: -.015em;
}

.notfound__text {
	max-width: 34rem;
	margin: 1.5rem 0 0;
	font-size: var(--fs-body);
	line-height: 1.55;
	color: var(--text-soft);
}

/* Suchformular und „Zur Startseite“ in einer Reihe; 375 px untereinander in
   voller Breite (6.24).
   FIX (Befund notfound-aktionen): Mobil stand der Button 12 px unter dem
   Suchfeld, mit derselben grauen Kante und 4 px niedriger; er las sich wie ein
   zweites Feld. 20 px Abstand trennen die beiden Handlungen, bleiben aber
   deutlich unter den 40 px bis „Häufig gesucht“. */
.notfound__actions {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 1.25rem;
	margin-top: 2rem;
}

.notfound__search {
	min-width: 0;
}

/* Gleiche Höhe wie Suchfeld und Lupe (11-forms.css) in jeder Breite. */
.notfound__actions .notfound__home {
	display: flex;
	width: 100%;
	min-height: 3.25rem;
}

.notfound__home .btn__label {
	flex: 1;
}

.notfound__popular {
	margin-top: 2.5rem;
}

.notfound__label {
	margin: 0 0 .75rem;
	font: 600 var(--fs-xs)/1.35 var(--font-text);
	color: var(--text);
}

.notfound__chips {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 48rem) {
	.notfound__title {
		font-size: var(--fs-h1-wide);
		line-height: 1.06;
	}

	.notfound__text {
		font-size: var(--fs-lead);
	}

	/* Am Desktop lagen Lupe und Button 12 px auseinander, fast so eng wie Feld
	   und Lupe (8 px); der Button wirkte wie ein zweiter Absende-Knopf. */
	.notfound__actions {
		flex-direction: row;
		flex-wrap: wrap;
		align-items: center;
		column-gap: 1.5rem;
	}

	.notfound__search {
		flex: 1 1 20rem;
		max-width: 28rem;
	}

	.notfound__actions .notfound__home {
		display: inline-flex;
		width: auto;
	}

	.notfound__home .btn__label {
		flex: 0 1 auto;
	}

	.notfound__mark {
		--notfound-mark-fs: 4.5rem;
		column-gap: 1.5rem;
	}
}

/* Ab 62rem: Text links (7fr), Zeitmarke rechts (5fr) wie im Schluss-Panel
   (5.8): oben der Timecode in --fs-time, direkt darunter der Clip in
   Ziffernbreite, Ziffern und Clip als eine Einheit.
   Ziffernoberkante bündig mit der Versalhöhe der ersten H1-Zeile. Archivo
   (1000 Einheiten): Ascender 878, Descender 210, Versalhöhe 686,
   Ziffernhöhe 698 (Messwerte aus 63-cta-band.css). Abstand zur Oberkante
   der Zeilenbox = (Zeilenhöhe − 1,088) / 2 + 0,878 − Höhe:
     H1, Zeilenhöhe 1.06 (ab 48rem, oben)   0,178 em von --fs-h1-wide
     404, Zeilenhöhe .9                     0,086 em von --notfound-mark-fs
   Die H1 hat keinen oberen Rand (02-base.css), beide Boxen beginnen also
   an der Oberkante der ersten Rasterzeile. */
@media (min-width: 62rem) {
	.notfound__inner {
		display: grid;
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		column-gap: clamp(2.5rem, 5vw, 5rem);
		max-width: none;
	}

	.notfound__inner > * {
		grid-column: 1;
	}

	.notfound__inner > .notfound__mark {
		--notfound-mark-fs: var(--fs-time);
		display: block;
		grid-column: 2;
		grid-row: 1 / span 4;
		align-self: start;
		/* Abnahme Runde 4: Einheit wie die Zeitmarke im Schluss-Panel
		   (63-cta-band.css) – die Spalte schrumpft auf die Ziffern, die
		   Leiste ist genau so breit wie „404“ und steht rechts bündig an der
		   Rasterkante statt über die ganze Spalte zu laufen. */
		justify-self: end;
		margin-top: calc(.178 * var(--fs-h1-wide) - .086 * var(--notfound-mark-fs));
	}

	/* Abstand wie .timemark__clip (17-timemark.css): sichtbar rund 21 px. */
	.notfound__clip {
		margin-top: .375rem;
	}
}

/* ---------- Suche: Kopf ---------- */

.page-head__count {
	margin: 1rem 0 0;
	font-size: var(--fs-body);
	line-height: 1.5;
	color: var(--text-soft);
}

.page-head__search {
	max-width: 32rem;
	margin-top: 1.5rem;
}

/* ---------- Suche: Trefferzeilen ----------
   Titel Archivo 700 1.25rem (gestreckter Link), Auszug Schibsted 16 px,
   Meta in Plex Mono 13 px, unten 1px --line, Padding-block 1.5rem.
   Hover und Fokus: Trim-Griffe (14-trim.css), Titel unterstrichen; Fokus
   zusätzlich mit eigener Outline an der Zeile. */

/* FIX (Befund suche-trefferliste): Die Linien liefen über 1216 px, der Text
   endete bei rund 790 px; beim Hover umrahmten die Trim-Griffe eine halb
   leere Fläche. 52rem fasst Titel (48rem) und Auszug (68ch) samt Innenabstand.
   Gilt auch für die Zeilen in archive.php. */
.result-list {
	max-width: 52rem;
	border-top: 1px solid var(--line);
}

.result-row {
	padding: 1.5rem 1rem;
	border-bottom: 1px solid var(--line);
	/* FIX: min-width 0 und break-word: Ein langer Titel oder eine URL im
	   Auszug darf die Zeile auf 320 px nicht aufsprengen. */
	min-width: 0;
	overflow-wrap: break-word;
}

.result-row__title {
	max-width: 48rem;
	margin: 0;
	font: 700 1.25rem/1.25 var(--font-display);
	font-stretch: 100%;
	letter-spacing: 0;
	/* FIX (Befund suche-trefferliste): pretty überschrieb balance aus
	   02-base.css (3.4) und ließ „nicht“ und „wirkt“ allein in der letzten
	   Zeile stehen. */
	text-wrap: balance;
}

/* FIX: Linienwerte am Link statt am Hover-Zustand, Offset .2em wie jeder
   Link (02-base.css) und wie Fallstudien-Zeile und Post-Karte (66, 71). Der
   Zustand schaltet nur noch die Linie ein; so sehen alle gestreckten
   Zeilen-Links bei Hover und Tastaturfokus gleich aus. */
.result-row__link {
	color: var(--text);
	text-decoration: none;
	text-decoration-color: var(--accent-text);
	text-decoration-thickness: 2px;
	text-underline-offset: .2em;
}

/* Die ganze Zeile ist Klickfläche und genau ein Tabstopp (9.5). Die
   Trim-Griffe liegen mit pointer-events: none darüber. */
.result-row__link::after {
	content: "";
	position: absolute;
	inset: 0;
}

/* FIX: Tastaturfokus unterstreicht den Titel wie Hover (wie 66 und 71). */
.result-row__link:focus-visible {
	text-decoration-line: underline;
}

/* FIX: Hover nur mit echtem Zeiger, sonst bleibt die Linie nach dem Antippen
   auf Touch stehen. :where() hält die Spezifität bei einer Klasse plus
   Zustand (8.5.4). */
@media (hover: hover) {
	.result-row:hover :where(.result-row__link) {
		text-decoration-line: underline;
	}
}

@supports selector(:has(*)) {
	.result-row:has(.result-row__link:focus-visible) {
		outline: 2px solid var(--focus);
		outline-offset: 2px;
	}

	.result-row__link:focus-visible {
		outline: none;
	}
}

.result-row__excerpt {
	max-width: 68ch;
	margin: .5rem 0 0;
	font-size: 1rem;
	line-height: 1.55;
	color: var(--text-soft);
}

.result-row__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: .25rem .5rem;
	margin: .75rem 0 0;
	font: 500 var(--fs-mono)/1.35 var(--font-mono);
	letter-spacing: .02em;
	color: var(--text-soft);
}

/* ---------- Suche: keine Treffer ----------
   Linksbündig, ohne die alte zentrierte .empty-state (6.25). */

.search-empty {
	max-width: 44rem;
}

.search-empty__lead {
	margin: 0 0 .75rem;
	font-size: var(--fs-lead);
	line-height: 1.55;
	color: var(--text);
}

.search-empty__text {
	max-width: 60ch;
	color: var(--text-soft);
}

.search-empty__actions {
	margin-top: 1.5rem;
}

/* Sektions-CTA-Regel: btn--lg btn--block aus search.php. Unter 48rem stehen
   die Buttons untereinander in voller Breite, primär zuerst (4.5), und in
   gleicher Höhe, auch wenn ein Label umbricht (Raster statt .btn-row-Flex,
   wie beim Inline-CTA). Ab 48rem natürliche Breite nebeneinander. */
@media (max-width: 47.99rem) {
	.search-empty__actions {
		display: grid;
		grid-template-columns: minmax(0, 1fr);
		grid-auto-rows: 1fr;
		align-items: stretch;
	}
}

@media (min-width: 48rem) {
	.search-empty__actions :where(.btn--block) {
		display: inline-flex;
		width: auto;
	}
}

/* ===== 90-motion.css ===== */
/* =========================================================================
   90 Bewegung (Besitz: Fundament F2) – docs/design-system.md 7

   1. Reduced-Motion-Netz (einzige Stelle mit !important)
   2. Scroll-getriebene Animationen unter reduce explizit aus
   3. Ausgangszustände der Einblendungen, nur unter html.smm-motion

   Grundsatz 7.1.3: Nichts startet unsichtbar ohne JavaScript. smm-motion
   setzt erst 30-reveal.js beim Boot, und nur ohne reduzierte Bewegung und
   mit IntersectionObserver. Vorher, ohne JS und bei „JavaScript verzögern“
   bleibt alles sichtbar. Das Inline-Skript im <head> setzt nur smm-js; daran
   hängt hier bewusst kein Ausgangszustand.
   ========================================================================= */

/* ---------- 1. Reduced-Motion-Netz (7.1.6) ---------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ---------- 2. Scroll-getriebene Animationen (Inventar 4 und 5) ----------
   Das Netz oben greift hier nicht: Bei animation-timeline: view() ist die
   Dauer bedeutungslos, die Animation folgt weiter dem Scrollen. Die
   Abschaltung liegt laut 7.1.6 zentral hier, damit sie auch greift, wenn eine
   Sektionsregel die Media-Query-Klammer vergisst.
   ABWEICHUNG von 9.4 (Runde 3, Schnitt-Spur): Der Playhead läuft nicht mehr
   scroll-getrieben, sondern einmal zeitgesteuert über .timeline-wrap.is-revealed
   (53-process.css). Unter reduce und ohne JavaScript zeigt die Spur das
   Schlussbild: Playhead am Ende (als ::after an .timeline-wrap gezeichnet,
   deshalb stört das display: none unten nicht), alle Clips gefüllt. Die
   beiden Regeln bleiben als Netz für scroll-getriebene Varianten stehen. */

@media (prefers-reduced-motion: reduce) {
	.timeline__playhead {
		display: none !important;
		animation: none !important;
	}

	.timeline__clip,
	.timeline__step::after {
		animation: none !important;
	}
}

/* ---------- 3. Einblendungen (Inventar 2 und 3) ----------
   Beide Zustände nur unter no-preference UND html.smm-motion. Die doppelte
   Klammer hält den Inhalt auch dann sichtbar, wenn die Einstellung wechselt,
   bevor das Skript smm-motion entfernt hat. */

@media (prefers-reduced-motion: no-preference) {

	/* Listen-Einblendung (problems, oton, channel-row, timeline__step):
	   opacity 0→1, translateY 8px→0, 420 ms. Die Staffelung über
	   data-reveal-delay (0, 60, 120) setzt 30-reveal.js zeitlich, nicht über
	   transition-delay, damit spätere Hover-Übergänge nicht verzögert werden.
	   Vertrag: Ein Element mit data-reveal trägt selbst keine eigene
	   transition; Hover-Übergänge gehören an ein Kindelement.

	   Die Selektoren nennen genau das Inventar 7.3 („mehr gibt es nicht“),
	   nicht jedes [data-reveal]. Sonst würde jedes data-reveal, das ein
	   Template zusätzlich setzt (Karten, Rechtstexte, Panels), sofort zu
	   einer Einblendung, und die transition-Regel überschriebe dort eigene
	   Hover-Übergänge. data-reveal an anderen Elementen bleibt so wirkungslos:
	   30-reveal.js setzt zwar is-revealed, sichtbar ändert sich nichts.
	   Neue Einblendungen brauchen eine Änderung am Inventar und hier.
	   Die Druck-Sicherung in 99-print.css nutzt dieselben Selektoren. */
	html.smm-motion :is(.problem, .oton, .channel-row, .timeline__step)[data-reveal] {
		transition:
			opacity var(--dur-3) var(--ease-cut),
			transform var(--dur-3) var(--ease-cut);
	}

	html.smm-motion :is(.problem, .oton, .channel-row, .timeline__step)[data-reveal]:not(.is-revealed) {
		opacity: 0;
		transform: translateY(8px);
	}

	/* Rahmenmarken rasten ein (5.4): Nur die Marken bewegen sich, Poster und
	   Video nie. Abweichung zu 5.4, begründet: Dort steht
	   .frame:not(.is-revealed) ohne [data-reveal]. Ein Rahmen mit
	   reveal => false bekommt kein data-reveal, das Skript setzt dort nie
	   is-revealed, und seine Marken blieben für immer unsichtbar. */
	.frame[data-reveal] .frame__screen::after {
		transition:
			opacity var(--dur-3) var(--ease-cut),
			transform var(--dur-3) var(--ease-cut);
	}

	html.smm-motion .frame[data-reveal]:not(.is-revealed) .frame__screen::after {
		opacity: 0;
		transform: scale(1.035);
	}
}

/* ===== 99-print.css ===== */
/* =========================================================================
   99 Druck (Besitz: Fundament F2)

   Ziel: Rechtstexte, Artikel und Leistungsseiten lassen sich lesbar drucken.
   Browser drucken Hintergründe standardmäßig nicht. Weiße Schrift auf
   Studio, Tafeln und Bauchbinden stünden dann weiß auf weißem Papier. Die
   Tokens kippen deshalb für den Druck auf die helle Variante, und Tafeln
   werden zu Text ohne Fläche.
   ========================================================================= */

@media print {
	@page {
		margin: 16mm 14mm;
	}

	/* Alle Gründe drucken hell: Tokens aus 00-tokens.css auf die Werte der
	   Sektion white zurücksetzen. Flächen-Tokens werden transparent, ihre
	   Schrift dunkel. */
	:root,
	[data-theme="dark"],
	.theme-studio,
	.section--bg-mist,
	.section--bg-teal {
		--bg: var(--c-white);
		--surface: transparent;
		--text: var(--c-ink);
		--text-soft: var(--c-ink-soft);
		--accent-text: var(--c-teal-ink);
		--line: var(--c-line);
		--line-ui: var(--c-line-ui);
		--mark: var(--c-teal);
		--trim: var(--c-teal);
		--plate-bg: transparent;
		--plate-fg: var(--c-ink);
		--bridge-bg: transparent;
		--bridge-fg: var(--c-ink);
		--l3-name-bg: transparent;
		--l3-name-fg: var(--c-ink);
		--l3-role-bg: transparent;
		--l3-role-fg: var(--c-ink-soft);
		--clip-bg: transparent;
		--clip-fg: var(--c-ink);
		--clip-on-bg: transparent;
		--clip-on-fg: var(--c-ink);
		--star: var(--c-ink);
		--star-off: var(--c-line-ui);
		--error: var(--c-error);
		--btn-label-bg: transparent;
		--btn-label-fg: var(--c-ink);
		--btn-go-bg: transparent;
		--btn-go-fg: var(--c-ink);
		--ghost-border: var(--c-line-ui);
		--ghost-fg: var(--c-ink);
		color: var(--c-ink);
		background: var(--c-white);
	}

	/* Bedienelemente und schwebende Leisten haben auf Papier keinen Zweck.
	   (Liste aus der alten app.css, ergänzt um Megamenü, Skip-Link und
	   Abspielknöpfe. Die Kapitel-Spur im Artikel ist Navigation für den
	   Bildschirm; die Überschriften stehen im Text.) */
	.chapter-track,
	.site-header,
	.topbar,
	.megamenu,
	.skip-link,
	.site-footer,
	.footer-cta,
	.sticky-cta,
	[data-sticky-cta],
	.to-top,
	[data-to-top],
	.slider__nav,
	.video-embed__play,
	.reel__play,
	.reel__sound {
		display: none;
	}

	.section {
		padding-block: 1rem;
	}

	/* FIX: Einblendungen. Druckt jemand, bevor er gescrollt hat, stünden alle
	   noch nicht eingeblendeten Elemente mit opacity 0 auf dem Papier.
	   30-reveal.js schaltet bei beforeprint alles frei; diese Regel ist die
	   Sicherung für Browser ohne beforeprint. Selektoren identisch zu
	   90-motion.css, damit die spätere Regel gewinnt. */
	html.smm-motion :is(.problem, .oton, .channel-row, .timeline__step)[data-reveal]:not(.is-revealed) {
		opacity: 1;
		transform: none;
	}

	html.smm-motion .frame[data-reveal]:not(.is-revealed) .frame__screen::after {
		opacity: 1;
		transform: none;
	}

	/* FIX: Walzen. Eine noch nicht gerollte Walze zeigt lauter Nullen
	   („000 Mio.“). Im Druck steht jede Ziffer sofort auf dem Endwert. */
	.odo .odo__s {
		transform: translateY(calc(var(--n, 0) * -1em));
		transition: none;
	}

	/* Aktiver Chip ohne gedruckte Fläche: dunkler Rand statt weißer Schrift.
	   FIX: Alias .chip.is-active entfernt wie in 16-lists-checks-stars.css. */
	.chip[aria-current="page"] {
		border-color: var(--c-ink);
		background: transparent;
		color: var(--c-ink);
	}

	/* Zusammenhalten, was zusammengehört. */
	.frame,
	.l3,
	.timemark,
	.checks > li,
	.bullets > li {
		break-inside: avoid;
	}

	.section__title,
	.section__header {
		break-after: avoid;
	}

	/* Externe Ziele in Fließtexten sind auf Papier sonst verloren. */
	.prose a[href^="http"]::after {
		content: " (" attr(href) ")";
		font-size: .875em;
		overflow-wrap: anywhere;
	}
}
