/* ==========================================================================
   Edlerritter IT-Consulting · Startseite v3 Editorial
   Umsetzung des Claude-Design-Artboards „Startseite v3 Editorial.dc.html“.
   Palette = Variante B (Orangerot / Dunkelgrün), Poppins lokal (DSGVO).
   ========================================================================== */

/* ---------- Schriften (lokal, subset Latin + Latin-Ext) ---------- */
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 400; font-display: swap; src: url("../assets/fonts/poppins-400-subset.woff2?v=47e7ee2c") format("woff2"); }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 500; font-display: swap; src: url("../assets/fonts/poppins-500-subset.woff2?v=f7d122f0") format("woff2"); }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 700; font-display: swap; src: url("../assets/fonts/poppins-700-subset.woff2?v=c59210a1") format("woff2"); }

/* ---------- Tokens ---------- */
:root {
  --accent: #EA4227;        /* Orangerot: Flächenfarbe (Marker, Pills, Ziffern, Fokusring) */
  --accent-hover: #C93318;
  --accent-soft: #FFA391;   /* Label auf dunkler Fläche */
  --accent-ink: #C93318;    /* Abgedunkelter Akzent für kleinen Text auf hellem Grund (AA: 5.29:1 Weiß / 4.68:1 Surface) */
  --accent-surface: #D63A1F; /* Abgedunkelte Akzentfläche für weißen Text darauf (AA: 4.68:1) */
  --dark: #17281E;          /* Dunkelgrün: Text, dunkle Bänder */
  --dark-active: #0D1712;
  --ink: #17281E;
  /* 5.20:1 auf Weiss. Der fruehere Wert #6E7873 lag mit 4.568:1 so knapp
     ueber der AA-Grenze, dass die halbtransparenten Pill-Flaechen im Hero
     darunter genuegten, um ihn zu unterschreiten: gemessen 4.31:1 auf
     21 Prozent der Zeile .hero__eyebrow, und zwar im Ruhezustand nach
     Ende der Animation, nicht waehrend der Bewegung. Jetzt 4.91:1 selbst
     ueber dem dunkelsten Punkt einer Pill. Die Pills sind inzwischen in
     die Parallax-Ebene 1 gewandert (assets/hero/…-layer-1-glow.svg), mit
     denselben Deckkraeften — die Messung gilt unveraendert weiter. Alle --muted-Stellen liegen
     auf hellem Grund, das Abdunkeln verbessert also ueberall. */
  --muted: #656F6A;
  --muted-ink: #67706B;     /* Abgedunkeltes Grau für kleinen Text auf --surface (AA: 4.53:1) */
  --surface: #F1F1F1;
  --page: #F7F7F6;
  --paper: #FFFFFF;
  --line: #D9DBDA;
  --line-bedien: #7C857F;   /* Rahmen von Bedienelementen: --line erreicht auf --surface
                               nur 1.23:1, WCAG 1.4.11 verlangt 3:1 fuer die Umrandung eines
                               Bedienelements. Dieser Wert liefert 3.37:1 auf --surface und
                               3.55:1 auf --page und bleibt trotzdem ruhig. */
  --wa: #25D366;
  --font: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  --header-h: 80px;

  /* ---------- Große Bildschirme (ab 1500px, gestuft): Skalierungs-Tokens ----------
     Basiswerte = IST-Zustand bis 1499px (calc(72px * 1) usw. == 72px).
     Drei Stufen (1500 / 2000 / 2800px) heben in den @media-Bloecken am
     Dateiende an, damit auch ein 1920px-Bildschirm schon eine Stufe bekommt
     (vorher erst ab 2000px). Unterseiten mit eigener css/pages.css nutzen
     dieselben Tokens und wachsen mit. */
  --container-max: 1360px;  /* .frame / .site-header__inner */
  --wrap-max: 1080px;       /* .wrap (Ablauf/Person/Referenzen/FAQ/Kontakt) */
  /* Zeilenlaenge des Fliesstexts, mit Marvin entschieden am 07.09.2026.
     Vorher stand 47ch an sieben Stellen verstreut, real 517px bei 17px
     Poppins. Der Inhaltsbereich neben der Spur war zu dem Zeitpunkt schon
     760px breit (1043px auf 2560px), der Text nutzte also nur zwei Drittel
     davon und klebte links. 58ch ergibt gemessen 638 / 696 / 754px je
     Stufe. Bewusst in ch und nicht in px: ch waechst mit --fs-bump mit,
     die Zeichen je Zeile bleiben ueber alle Stufen gleich.
     ACHTUNG, teuer gelernt: der Wert stand zuerst als 58ch da. Das
     funktioniert am Absatz, aber NICHT am Container darum: ch rechnet
     immer gegen die Schriftgroesse des Elements, an dem es steht, und der
     Container erbt 16px vom body waehrend der Text auf 20 oder 22px
     steht. Der Container war damit auf jeder Stufe bei 620px, deckelte
     den Absatz, und auf 3840px standen dadurch WENIGER Zeichen in der
     Zeile als auf 1440px. Deshalb jetzt in px, mit denselben vier Stufen
     wie --fs-bump: die Werte sind die gemessenen 58ch bei 17, 20, 21 und
     22px Schrift. Wer die Lesespalte aendert, aendert vier Werte. */
  --lese: 640px;
  --space-scale: 1;         /* Innenabstand der Hauptabschnitte */
  --fs-bump: 0px;           /* additive Vergrößerung für Lesetext-Absätze: 17px Basis + Bump */
  --h2-scale: 1;            /* multiplikative Vergrößerung große Überschriften */
  /* Die folgenden vier Blöcke haben eigene, engere Maximalbreiten als --container-max.
     Sie MÜSSEN im gleichen Verhältnis mitwachsen, sonst kippt die Größenordnung:
     bei 3840px wäre der Hero (1120px) sonst schmaler als die Abschnitte unter ihm
     (1334px) und der Fuß (1080px) schmaler als der Kopf (1680px). Gemessen. */
  --hero-max: 1120px;       /* .hero__inner */
  --statement-max: 640px;   /* .statement__wrap, bewusst schmale Lesespalte */
  --card-max: 880px;        /* .angebot__card, einspaltig seit 11.09.2026 */
  --footer-max: 1080px;     /* .site-footer__inner, gleich breit wie .wrap */
  --portrait-w: 380px;      /* .person__grid, erste Spalte (Bildquelle ist 760px breit) */
  --hero-scale: 1;          /* nur der Hero-Bereich, oben auf den Stufen zusaetzlich */
}

/* ---------- Basis ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
html, body { overflow-x: clip; }
body {
  margin: 0;
  background: var(--page);
  font-family: var(--font);
  color: var(--ink);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: var(--accent-ink); }
a:hover { color: var(--accent-hover); }
button { font: inherit; color: inherit; }
img { max-width: 100%; }
/* Das hidden-Attribut setzt display:none nur ueber das Browser-Stylesheet,
   und jede eigene display-Regel schlaegt das. Genau das passierte bei
   .option (display:flex): der Termin-Eintrag im Erstgespraech-Dialog trug
   sein hidden brav, war aber auf JEDER Seite sichtbar und fuehrte auf
   /kontakt, obwohl TERMIN_URL in js/main.js leer ist und es noch gar
   keinen Kalender gibt. Aufgefallen am 07.09.2026 beim Umbau der
   Kontaktseite, gilt aber fuer den Bestand genauso. Die Regel gehoert zur
   Grundlage und nicht zu .option, sonst faellt derselbe Fehler beim
   naechsten Baustein mit eigener display-Regel wieder an. */
[hidden] { display: none !important; }
[id] { scroll-margin-top: calc(var(--header-h) + 16px); }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
/* Fokusring auf Akzentflächen gegen Fläche/Umgebung absetzen (f-54) */
.btn:focus-visible { outline-color: var(--dark); }
.angebot__card .btn:focus-visible, .kontakt .btn:focus-visible { outline-color: var(--accent); }
/* Auf WhatsApp-Gruen ergibt der orangerote Fokusring nur 2,0:1 und ist
   damit praktisch unsichtbar. Weiss ergibt dort 3,6:1 und erfuellt die
   Vorgabe fuer Nicht-Text-Kontrast (WCAG 1.4.11, 3:1). */
.wa-float:focus-visible, .option--wa:focus-visible { outline-color: #fff; }
/* Links in Adressbloecken hatten 23px Hoehe und lagen damit 1px unter der
   Zielgroesse aus WCAG 2.2 (SC 2.5.8, 24x24 CSS-Pixel). Sie tragen keine
   Knopfklasse und bekamen deshalb kein Innenabstands-Polster. */
address a { display: inline-block; min-height: 24px; line-height: 24px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip-link {
  position: absolute; left: 16px; top: -120px; z-index: 300;
  background: var(--dark); color: #fff; padding: 12px 16px;
  border-radius: 12px; text-decoration: none; font-weight: 500;
}
.skip-link:focus { top: calc(var(--header-h) + 12px); }

/* ---------- Rahmen ---------- */
.page { min-height: 100vh; background: var(--page); }
/* Randlos ab 07.09.2026 (mit Marvin entschieden). Vorher war .frame eine
   1360px breite Karte, die auf --page schwebte: auf einem 1920er Schirm
   lagen links und rechts je 168px tote Flaeche, und die farbigen Baender
   endeten mittendrin statt am Bildschirmrand. Jetzt traegt der Rahmen nur
   noch den Grund, die Begrenzung machen die Inhalte selbst
   (--wrap-max, --lese). Kopfzeile und Fuss behalten ihre Begrenzung ueber
   --container-max bzw. --footer-max, damit Logo und Navigation nicht an
   den Bildschirmkanten kleben. --page wird dadurch nirgends mehr sichtbar,
   die Variable bleibt aber fuer 404.html und den Fokus-Ring in Gebrauch. */
.frame {
  position: relative;
  width: 100%; margin: 0; min-height: 100vh;
  background: var(--paper);
}

/* ---------- Header ---------- */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  background: var(--paper);
  box-shadow: 0 4px 24px rgba(23, 40, 30, .10);
}
.site-header__inner {
  max-width: var(--container-max); margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 32px;
}
.site-header__logo { flex-shrink: 0; display: inline-flex; }
.site-header__logo img { height: 44px; width: auto; display: block; }
.nav { display: flex; align-items: center; gap: 2px; flex-wrap: nowrap; }
.nav a {
  font-size: 15px; font-weight: 500; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ink); text-decoration: none; padding: 11px 14px;
  border-radius: 12px; corner-shape: squircle; white-space: nowrap;
}
.nav a:hover { color: var(--ink); }
.nav .nav__cta { display: none; }   /* nur in der Burger-Klappe. Zwei Klassen,
   weil .btn weiter unten in der Datei display:inline-flex setzt und bei
   gleicher Spezifitaet die spaetere Regel gewinnen wuerde. */
.nav a:active { background: var(--surface); }

/* ---------- Burger-Menü (nur unter 1001px) ----------
   Unter 1001px war die Navigation bisher schlicht ausgeblendet: auf dem
   Handy gab es im Kopf gar keine, nur Logo und Knopf. Der Burger ersetzt
   das. Er steht im Markup VOR der Navigation, die er steuert, damit die
   geöffnete Liste in der Tabulator-Reihenfolge direkt danach kommt.

   Optik und Bewegung sind der Vorlage von 21st.dev nachgebaut (dort React
   mit Tailwind, Radix und class-variance-authority). Übernommen ist, was
   man sieht: der umrandete quadratische Knopf und die drei Striche, die
   sich zum Kreuz drehen. Nicht übernommen ist der Werkzeugkasten dahinter,
   denn diese Seite hat bewusst kein Framework und keinen Bauschritt. Die
   Übergänge stammen aus derselben Vorlage: 300ms, die äußeren Striche mit
   cubic-bezier(.5,.85,.25,1.1), der mittlere mit dem elastischeren
   cubic-bezier(.5,.85,.25,1.8). */
.nav-toggle {
  display: none;                      /* ab 1001px unsichtbar, siehe Media Query */
  align-items: center; justify-content: center; flex: 0 0 auto;
  width: 44px; height: 44px;          /* Vorlage hat 36px, hier 44px: das ist
                                         die bequeme Zielgröße für Finger und
                                         erfüllt WCAG 2.2 mit Reserve. */
  padding: 0; margin: 0; background: var(--paper); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px; corner-shape: squircle;
  box-shadow: 0 1px 2px rgba(23, 40, 30, .05);
  appearance: none; -webkit-appearance: none; cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.nav-toggle:hover { background: var(--surface); }
.nav-toggle:active { background: var(--surface); border-color: var(--muted); }

/* Drei deckungsgleiche Linien durch die Mitte. Zwei sind nach oben und
   unten versetzt, beim Öffnen fahren sie in die Mitte zurück und drehen
   sich zu einem Kreuz. Genau die Bewegung der Vorlage. */
.nav-toggle svg path { transform-origin: center; transition: transform .3s; }
.nav-toggle__oben   { transform: translateY(-7px); transition-timing-function: cubic-bezier(.5, .85, .25, 1.1); }
.nav-toggle__mitte  { transition-timing-function: cubic-bezier(.5, .85, .25, 1.8); }
.nav-toggle__unten  { transform: translateY(7px);  transition-timing-function: cubic-bezier(.5, .85, .25, 1.1); }
.nav-toggle[aria-expanded="true"] .nav-toggle__oben  { transform: translateY(0) rotate(315deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__mitte { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__unten { transform: translateY(0) rotate(135deg); }

/* ---------- Buttons ---------- */
.btn {
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--accent-surface); color: #fff; text-decoration: none;
  font-weight: 500; font-size: 17px; line-height: 1.2; padding: 16px 32px;
  border: 0; border-radius: 16px; corner-shape: squircle; white-space: nowrap;
  transition: background .25s ease, color .25s ease, transform .2s ease;
}
.btn:hover { background: var(--dark); color: #fff; }
.btn:active { background: var(--dark-active); }
.btn--small { font-size: 16px; letter-spacing: -.01em; padding: 13px 22px; border-radius: 14px; gap: 8px; min-height: 44px; }  /* f-14: Tap-Ziel */
/* Sekundaerer Knopf: gleiche Groesse, gleiches Tap-Ziel, gleiche Form wie
   .btn, nur ohne Fuellfarbe. Auf den drei Tuerseiten trugen "Leitfaden lesen"
   und "Erstgespraech buchen" beide den gefuellten .btn, also zwei
   VERSCHIEDENE Ziele mit identischem Gewicht. Der Leitfaden bleibt ein
   vollwertiger Weg und wird weder versteckt noch verkleinert, er fuehrt nur
   nicht mehr optisch gegen das Hauptziel an.
   Der Rahmen nutzt --line-bedien statt --line: ohne Fuellfarbe ist er die
   EINZIGE Begrenzung des Knopfes, und --line haette dort nur 1.23:1 erreicht.
   "Nicht verstecken" heisst auch, dass man den Knopf als Knopf erkennt. */
.btn--sekundaer { background: transparent; color: var(--ink); border: 1px solid var(--line-bedien); }
.btn--sekundaer:hover { background: var(--surface); color: var(--ink); border-color: var(--ink); }
.btn--sekundaer:active { background: var(--line); color: var(--ink); }
.btn--on-dark:hover { background: var(--surface); color: var(--dark); }
.btn--on-dark:active { background: var(--line); }

/* ---------- Typo-Bausteine ---------- */
.eyebrow {
  display: block; font-size: 12px; font-weight: 500; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent-ink); margin-bottom: 16px;
}
.eyebrow--soft { color: var(--accent-soft); }
.h2 {
  margin: 0; font-weight: 700; font-size: calc(30px * var(--h2-scale)); line-height: 1.05;
  letter-spacing: -.03em; color: var(--ink); text-wrap: pretty;
}
/* Silbentrennung freigeben, damit lange Wörter Karten/Zeilen nicht sprengen (f-01) */
/* overflow-wrap: break-word statt anywhere. Der Unterschied ist nicht
   kosmetisch: "anywhere" laesst Umbruchstellen INNERHALB von Woertern
   auch in die Mindestbreiten-Berechnung einfliessen, wodurch der Browser
   schon bricht, wenn noch Platz waere. Gemessen brach ".door h3" bei
   280px "Softw/are", obwohl das Wort in die Zeile gepasst haette.
   "break-word" verhindert einen Ueberlauf genauso, beeinflusst die
   Mindestbreite aber nicht. */
.h2, .angebot__fakt b, .door h3, .step h3 { hyphens: auto; overflow-wrap: break-word; }
.link-more {
  color: var(--accent-ink); font-weight: 500; font-size: 18px;
  text-decoration: underline; text-underline-offset: 4px;
  display: inline-block; padding: 10px 0; margin: -10px 0;  /* f-14: Tap-Ziel >=44px, Optik unverändert */
}

/* ---------- Layout-Helfer ---------- */
.screen { min-height: min(100vh, 1100px); display: flex; align-items: center; }  /* f-42: Deckel gegen Leerflächen auf 2560px+ */
.wrap { max-width: var(--wrap-max); margin: 0 auto; width: 100%; padding: calc(72px * var(--space-scale)) calc(64px * var(--space-scale)); }
.wrap--tight { padding: calc(48px * var(--space-scale)) calc(64px * var(--space-scale)); }

/* ---------- Hero / Türen ---------- */
.hero {
  position: relative; overflow: hidden; min-height: min(86vh, 950px); /* f-42 */
  display: flex; align-items: center;
}

.hero__inner { position: relative; max-width: var(--hero-max); margin: 0 auto; width: 100%; padding: calc(100px * var(--space-scale)) calc(64px * var(--space-scale)) calc(36px * var(--space-scale)); }
.hero__eyebrow { margin: 0 0 12px; font-size: calc(16px * var(--hero-scale)); line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.hero__title {
  margin: 0 0 40px; font-size: clamp(20px, 2.6vw, calc(30px * var(--h2-scale) * var(--hero-scale))); font-weight: 700;
  letter-spacing: -.02em; line-height: 1.3; color: var(--ink);
  white-space: normal; text-wrap: balance;
}
.doors { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; align-items: stretch; }
.door {
  display: flex; flex-direction: column; border-top: 2px solid var(--ink);
  padding: 28px 0 0; text-decoration: none; color: var(--ink);
}
.door:active { border-top-color: var(--accent); }
/* Positionierung v3, Abschnitt 4a: "grosse Ziffer 01/02/03 in Akzentfarbe".
   Gleiches Muster wie .step__num und .prozess__num, nur kleiner, weil die
   Karte oben schon eine 2px-Linie traegt und die Ueberschrift die
   Hauptlast tragen soll. aria-hidden im Markup: die Ziffer ordnet, sie
   traegt keine Information fuer die Sprachausgabe. */
/* Die Tuerkarten stehen unter der Parallax-Buehne und wachsen mit ihr. Auf
   /leistungen bleibt .door unveraendert, daher der Container-Vorsatz. */
.pxhero__content .door h3 { font-size: calc(22px * var(--hero-scale)); }
.pxhero__content .door p { font-size: calc((18px + var(--fs-bump)) * var(--hero-scale)); }
.pxhero__content .door__num { font-size: calc(28px * var(--hero-scale)); }
.door__num {
  display: block; font-weight: 700; font-size: 28px; line-height: .9;
  letter-spacing: -.04em; color: var(--accent); margin-bottom: 14px;
}
.door h3 {
  margin: 0 0 12px; font-weight: 700; font-size: 22px; line-height: 1.15;
  letter-spacing: -.02em; color: var(--ink); transition: color .25s ease;
  text-wrap: balance;  /* f-40: kein Waisenkind in der letzten Zeile */
}
.door:hover h3, .door:focus-visible h3 { color: var(--accent); }
.door p { margin: 0 0 24px; flex: 1; max-width: 44ch; font-size: calc(18px + var(--fs-bump)); line-height: 1.6; color: var(--muted); }
.door__more { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; font-size: 18px; color: var(--accent-ink); line-height: 1; }
.door__more .arrow { display: inline-block; font-size: 20px; animation: nudge 1.6s ease-in-out infinite; animation-iteration-count: 3; }
.hero__cta { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; margin-top: 56px; }
.hero__claim { flex: 1; min-width: min(280px, 100%); display: grid; gap: 6px; }
.hero__claim p { margin: 0; font-size: calc((17px + var(--fs-bump)) * var(--hero-scale)); line-height: 1.5; color: var(--ink); text-wrap: pretty; }
.hero__claim em { font-style: normal; color: var(--accent-ink); font-weight: 500; }

/* ---------- Baender (Richtung C, mit Marvin entschieden am 04.09.2026) ----------
   Ein Gedanke pro Band, wenig sichtbarer Text, Details hinter Aufklappen.
   Ersetzt die Parallax-Buehne auf der Startseite.
   Die Buehne ist NICHT geloescht: alle .pxhero-Regeln stehen direkt unter
   diesem Block weiter, die vier SVG-Ebenen liegen weiter unter
   assets/hero/, und der Parallax-Abschnitt in js/main.js findet einfach
   kein [data-parallax-layers] mehr und macht nichts. Zurueckholen heisst
   Markup wieder einsetzen, nicht neu bauen. 404.html nutzt .hero weiter. */
/* Ablauf, Kunden, Person und FAQ laufen ab dem 04.09.2026 im selben Band
   wie der Hero. Vorher trug jeder eine eigene Bauart: .screen zwang drei
   von ihnen auf min(100vh,1100px) und zentrierte den Inhalt darin, was auf
   grossen Schirmen leere Flaechen und harte Spruenge erzeugte; die
   Innenabstaende lagen bei 48 und 72px durcheinander; zwei Abschnitte
   trugen eine Trennlinie, die anderen nicht. Jetzt trennt der Wechsel des
   Grundes (hell, matt, hell, matt), und die Hoehe kommt vom Inhalt.
   .screen bleibt als Regel bestehen, wird auf der Startseite aber nicht
   mehr verwendet. */
.band { padding: calc(72px * var(--space-scale)) calc(64px * var(--space-scale)); }
/* Das erste Band der Seite liegt unter der FIXEN Kopfzeile, die keinen
   Platz im Fluss belegt. Ohne eigenen Ausgleich blieben von 72px
   Innenabstand genau 72 minus 80 uebrig, also nichts: der Text klebte an
   der Navigation. Der alte Parallax-Hero hatte den Ausgleich fest
   eingebaut (100px), beim Umbau auf Baender ist er verlorengegangen.
   Deshalb hier an --header-h gekoppelt und nicht als feste Zahl, damit er
   auf den kleinen Stufen mitwandert, wo die Kopfzeile 64 und 60px hoch ist. */
.band--kopf { padding-top: calc(var(--header-h) + 96px); }
.band--hell { background: var(--paper); }
.band--matt { background: var(--surface); }
.band__inhalt { max-width: var(--wrap-max); margin: 0 auto; width: 100%; }
/* Ortszeile und Haken bleiben in EINER h1: die erste traegt Angebot und
   Ort und damit die Suchbegriffe, die zweite den Haken. */
.band__heading { margin: 0; font: inherit; display: grid; gap: 22px; }
.band__eyebrow { font-size: calc(15px + var(--fs-bump)); line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.band__titel {
  font-weight: 700; font-size: clamp(28px, 4vw, calc(46px * var(--h2-scale)));
  line-height: 1.1; letter-spacing: -.035em; color: var(--ink);
  max-width: 17ch; text-wrap: balance;
}
.band__titel em { font-style: normal; color: var(--accent); }
.band__aktion { margin-top: 48px; }

/* Die drei Ausgangspunkte: sichtbar ist nur die Ueberschrift, der Rest
   kommt auf Wunsch. Marvins Ansage: "nur mit der Ueberschrift von den
   Tueren, unterhalb ist unnoetig, das ueberfuellt den Hero".
   Preis dieser Loesung, bewusst in Kauf genommen: der Weg auf die
   Tuerseite braucht jetzt zwei Klicks statt einem. Dafuer klickt nur, wer
   die Beschreibung gelesen hat. */
.tueren { margin-top: 60px; border-top: 1px solid var(--line); }
.tuer { border-bottom: 1px solid var(--line); }
.tuer summary {
  display: flex; align-items: center; gap: 16px; list-style: none;
  padding: 20px 0; min-height: 44px; cursor: pointer;
}
.tuer summary::-webkit-details-marker { display: none; }
.tuer summary h2 {
  margin: 0; font-weight: 700; font-size: calc(20px * var(--h2-scale));
  line-height: 1.25; letter-spacing: -.02em; color: var(--ink);
  transition: color .25s ease; text-wrap: pretty;
}
.tuer summary:hover h2, .tuer summary:focus-visible h2 { color: var(--accent); }
/* Chevron aus zwei Raendern gezeichnet: die Pfeilzeichen liegen nicht im
   Poppins-Subset, ein Zeichen wuerde in der Systemschrift rendern. */
.tuer summary::after {
  content: ""; flex: 0 0 auto; margin-left: auto; width: 10px; height: 10px;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: translateY(-3px) rotate(45deg); transition: transform .25s ease;
}
.tuer[open] summary::after { transform: translateY(2px) rotate(-135deg); }
.tuer p { margin: 0 0 14px; max-width: var(--lese); font-size: calc(17px + var(--fs-bump)); line-height: 1.6; color: var(--muted); }
.tuer .link-more { margin-bottom: 14px; }

/* ---------- Hero mit Parallax-Ebenen ----------
   Nachbau des Osmo/GSAP-Beispiels ohne GSAP und ohne Lenis. Die Bewegung
   macht Abschnitt 4 in js/main.js ueber transform: translate3d, gespeist aus
   getBoundingClientRect. Ebenenwerte wie im Original: 70/55/40/10 Prozent.
   Wer beim Scrollen wenig mitwandert, wirkt nah; wer viel mitwandert, fern.
   Lenis (Smooth-Scroll-Ersatz) bewusst weggelassen: es uebersteuert das
   native Scrollen inklusive Tastatur und Trackpad. html { scroll-behavior:
   smooth } oben leistet, was die Seite braucht.
   .hero/.hero__inner/.hero__eyebrow/.hero__title bleiben stehen — 404.html
   benutzt sie weiter. */
.pxhero { position: relative; overflow: hidden; background: var(--page); }

/* Die Buehne. Bewusst niedriger als der alte .hero (86vh): die drei Tueren
   stehen jetzt UNTER der Buehne und muessen am unteren Rand anschneiden,
   sonst verliert die Startseite ihren wichtigsten Einstieg unter die Falz.
   Auf 2560px passen so Hero, alle drei Tueren und der Aufruf in einen
   Bildschirm. Das ist der Hebel, an dem man hier dreht.

   68vh/740px gemessen auf 1920x1080: die Tuerenzeile lief von 739 bis 1143,
   also 84% sichtbar, die Ueberschrift "Weiterlesen" lag unter der Falz.
   60vh/660px zieht die Zeile auf 653..1057 und macht alle drei Tueren im
   ersten Viewport vollstaendig lesbar. min-height, nicht height: faellt der
   Wert unter die natuerliche Hoehe der H1, waechst die Buehne trotzdem mit. */
.pxhero__scene {
  position: relative; overflow: hidden;
  min-height: min(60vh, 660px);
  display: flex; align-items: center;
}

/* Alle Ebenen liegen deckungsgleich uebereinander und sind mittig ausgerichtet. */
.pxhero__layers { position: absolute; inset: 0; display: flex; align-items: center; }

/* Bildebenen sitzen am unteren Rand und wandern beim Scrollen nach unten. */
.pxhero__layer-img {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: auto; display: block;
  pointer-events: none; will-change: transform;
}
.pxhero__layer-img[data-parallax-layer="1"] { top: 0; bottom: auto; height: 100%; object-fit: cover; }
.pxhero__layer-img[data-parallax-layer="2"] { height: 46%; object-fit: fill; }
.pxhero__layer-img[data-parallax-layer="4"] { height: 34%; object-fit: fill; }

/* Weicher Uebergang von der Buehne in den Seitenhintergrund. */
.pxhero__fade {
  position: absolute; left: 0; right: 0; bottom: 0; height: 14%;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(247, 247, 246, 0), var(--page));
}

/* Ebene 3 = der Text. Steht in der DOM-Reihenfolge VOR Ebene 4, damit der
   nahe Grat ihn unten anschneidet — das ist der Tiefeneindruck. Kein
   z-index, sonst faellt genau der weg. */
.pxhero__layer-title {
  position: relative;
  max-width: var(--hero-max); margin: 0 auto; width: 100%;
  /* Der Kopfausgleich haengt jetzt an --header-h statt an festen 100px.
     Grund: die Kopfzeile ist fix und schrumpft auf schmalen Schirmen auf
     64px, im Querformat auf 60px. Mit 100px blieben bei 80px Kopfzeile nur
     20px Luft, und genau das hat Marvin am 04.09.2026 als "nach oben
     gedraengt" gemeldet, als der Hero kurzzeitig ein Band war. */
  padding: calc(var(--header-h) + 48px) calc(64px * var(--space-scale)) calc(36px * var(--space-scale));
  will-change: transform;
}
.pxhero__eyebrow { margin: 0 0 12px; font-size: calc(16px * var(--hero-scale)); line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.pxhero__title {
  margin: 0; font-weight: 700; color: var(--ink);
  /* Der Deckel wird auf grossen Schirmen ZWEIMAL hochskaliert (--h2-scale mal
     --hero-scale). Mit 64px Basis waren das auf 2560px 95px, zu wuchtig.
     52px ergeben dort 77px. Der vw-Wert liegt bewusst unter dem Deckel,
     damit 1440-2000px mitschrumpfen statt am Deckel zu kleben. */
  font-size: clamp(28px, 4.4vw, calc(52px * var(--h2-scale) * var(--hero-scale)));
  letter-spacing: -.03em; line-height: 1.1; text-wrap: balance;
  max-width: 20ch;
}
.pxhero__title em { font-style: normal; color: var(--accent); }
/* Beide Zeilen stecken in EINER <h1> (Angebot + Ort, dann der Hook). Die
   <h1> selbst bekommt keine eigene Optik, die tragen die beiden Spans. */
.pxhero__heading { margin: 0; font: inherit; }
.pxhero__eyebrow, .pxhero__title { display: block; }

/* Unter der Buehne: die drei Tueren und der Aufruf. Nutzen .doors/.door und
   .hero__cta/.hero__claim von oben unveraendert weiter. */
.pxhero__content {
  position: relative; z-index: 3;
  max-width: var(--hero-max); margin: 0 auto; width: 100%;
  padding: 0 calc(64px * var(--space-scale)) calc(72px * var(--space-scale));
}

/* ---------- Ablauf ---------- */
.ablauf .h2 { margin-bottom: 40px; }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; }
.step { border-top: 1px solid var(--line); padding-top: 24px; }

/* ---------- Die Ablaufspur (07.09.2026) ----------
   Idee aus einer 21st.dev-Komponente ("Scroll Reveal Content A": nummerierte
   Bloecke an einer mitwachsenden Fortschrittslinie), hier ohne deren Stack
   nachgebaut: kein React, kein GSAP, keine Abhaengigkeit, nur CSS.
   Statt drei getrennter Haarlinien ueber den Spalten laeuft eine durchgehende
   Linie ueber den ganzen Abschnitt, und darauf zeichnet sich beim Scrollen
   eine zweite in Signalorange. Der Abschnitt heisst "Vom ersten Gespraech bis
   zur Umsetzung", die Linie zeichnet also genau das, wovon die Ueberschrift
   spricht. Es ist der EINZIGE inszenierte Moment der Seite; alles andere
   bleibt beim ruhigen Einblenden.
   Nur ab 961px: darunter stehen die Schritte untereinander, dann waere eine
   waagrechte Fortschrittslinie ueber dem ersten Schritt sinnlos. Dort bleibt
   die Haarlinie je Schritt wie bisher.
   Ohne animation-timeline-Unterstuetzung bleibt die orange Linie bei
   scaleX(0), sichtbar ist dann nur die graue: exakt das heutige Bild.
   prefers-reduced-motion schaltet ueber den globalen Reset ab, mit demselben
   Ergebnis. Signalorange traegt hier eine Linie, keine Flaeche, bleibt also
   innerhalb der Wegmarken-Regel aus DESIGN.md. */
@media (min-width: 961px) {
  .steps { position: relative; }
  .step { border-top: 0; padding-top: 25px; }  /* 24 + 1px, damit die Optik gleich bleibt */
  .steps::before, .steps::after {
    content: ""; position: absolute; left: 0; right: 0; top: 0;
  }
  .steps::before { height: 1px; background: var(--line); }
  /* 2px statt 1px: die gezeichnete Linie liest sich sonst wie die graue
     darunter, gemessen ist sie zwar #EA4227, wirkt auf 1px aber nur dunkel.
     2px ist ausserdem die Vokabel, die das System fuer eine Kante mit
     Bedeutung schon kennt (Oberlinie der Tuerkarten, DESIGN.md). */
  .steps::after {
    height: 2px; background: var(--accent); transform: scaleX(0); transform-origin: left center;
  }
  @supports (animation-timeline: view()) {
    /* Zwei Fallen, beide beim Messen aufgefallen (die Linie stand auf jeder
       Scrollposition auf scaleX(1), animierte also gar nicht):
       1. Die Kurzform "animation: name linear both" setzt die Dauer auf 0s.
          Eine scrollgesteuerte Animation braucht "auto", sonst springt sie
          sofort ans Ende. Deshalb hier Langform.
       2. view() nimmt das Element selbst als Zeitgeber. Das Pseudoelement
          ist 1px hoch und damit in einem Wimpernschlag durchs Bild. Der
          Zeitgeber muss der Abschnitt sein, also traegt .steps ihn als
          benannte view-timeline und ::after greift sie ab. */
    .steps { view-timeline-name: --ablaufspur; view-timeline-axis: block; }
    .steps::after {
      animation-name: spur-waechst;
      animation-duration: auto;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: --ablaufspur;
      /* entry 30% bis cover 50%: gemessen zeichnet sich die Linie damit ueber
         rund 500px Scrollweg statt ueber 170px und ist fertig, wenn der
         Abschnitt mittig steht. Mit "entry 90%" als Ende war sie durch,
         bevor man die drei Schritte gelesen hatte. */
      animation-range: entry 30% cover 50%;
    }
  }
  /* Rueckfall fuer Firefox und alles andere ohne animation-timeline.
     Das war zuerst nicht da, und die Folge war, dass die Linie ausgerechnet
     in Marvins eigenem Browser gar nichts tat: in Firefox blieb sie auf
     scaleX(0) und man sah nur die graue Linie. In Chromium nachgemessen
     52,9% an derselben Scrollposition, in Firefox 0.
     js/reveal-init.js setzt html.js-reveal GENAU DANN, wenn der Browser
     animation-timeline nicht kann und keine reduzierte Bewegung eingestellt
     ist; js/main.js haengt per IntersectionObserver .is-in an die
     .reveal-Container. Beides ist schon da, die Linie klinkt sich nur ein.
     Sie zeichnet sich dann nicht am Scrollrad, sondern einmal in 1,2s,
     sobald der Abschnitt ins Bild kommt. Anderer Weg, gleiches Bild. */
  .js-reveal .reveal.is-in .steps::after {
    animation: spur-waechst 1.2s cubic-bezier(.22, 1, .36, 1) both;
  }
}
@keyframes spur-waechst { to { transform: scaleX(1); } }
.step__num {
  display: block; font-weight: 700; font-size: 56px; line-height: .85;
  letter-spacing: -.04em; color: var(--accent); margin-bottom: 20px;
}
.step h3 { margin: 0 0 12px; font-weight: 700; font-size: 22px; letter-spacing: -.02em; color: var(--ink); text-wrap: balance; }
.step p { margin: 0; max-width: 34ch; font-size: calc(16px + var(--fs-bump)); line-height: 1.65; color: var(--muted); text-wrap: pretty; }

/* ---------- Person ---------- */
.person__grid { display: grid; grid-template-columns: var(--portrait-w) 1fr; gap: 64px; align-items: start; }
.person__figure { margin: 0; }
.person__figure img {
  width: 100%; height: auto; display: block; filter: grayscale(1);
  border-radius: 20px; corner-shape: squircle; transition: filter .4s ease;
}
.person__figure:hover img { filter: grayscale(0); }
.person__figure figcaption {
  display: flex; justify-content: space-between; gap: 12px;
  border-top: 2px solid var(--ink); padding-top: 10px; margin-top: 12px;
  font-size: 12px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}
.person__title { margin: 0 0 28px; min-height: 46px; }
.tw-cursor { color: var(--accent); animation: twblink 1.1s steps(1) infinite; }
.person__text p { margin: 0 0 20px; max-width: var(--lese); font-size: calc(17px + var(--fs-bump)); line-height: 1.65; color: var(--ink); text-wrap: pretty; }
.person__text p:last-of-type { margin-bottom: 28px; }

/* ---------- Statement ---------- */
.statement__wrap {
  max-width: var(--statement-max); margin: 0 auto; width: 100%;
  padding: calc(48px * var(--space-scale)) calc(64px * var(--space-scale)) calc(72px * var(--space-scale));
}

/* Umrandeter Rahmen mit Punktraster und vier Eckquadraten, nach der Vorlage
   von 21st.dev (dort React mit Tailwind, dazu eine SVG-Musterkomponente).
   Übernommen ist das Bild: Haarlinie, feines Punktraster, vier gefüllte
   Quadrate, die auf den Ecken sitzen. Nicht übernommen ist der Aufbau:
   das Punktraster ist hier ein radial-gradient statt eines SVG-Musters,
   das spart ein zusätzliches Element und jedes Byte Abhängigkeit.
   Die Vorlage nutzt Rot und Schiefergrau. Hier trägt das Raster die
   Linienfarbe des Designs und die Ecken die Akzentfarbe: das Rot bleibt
   Akzent und nimmt nicht die ganze Fläche ein (Briefing 01_DESIGN.md,
   "nicht alles in der Akzentfarbe"). */
.statement__rahmen {
  position: relative;
  padding: calc(40px * var(--space-scale)) calc(36px * var(--space-scale));
  border: 1px solid var(--line);
  /* Punktraster: ein Punkt je 5px, wie in der Vorlage (width/height 5). */
  background-image: radial-gradient(var(--line) .5px, transparent .5px);
  background-size: 5px 5px;
}
/* Zwei Pseudoelemente, jedes traegt zwei Eckquadrate. Sie ragen um ihre
   halbe Groesse ueber den Rahmen hinaus, genau wie die -1.5 der Vorlage. */
.statement__rahmen::before,
.statement__rahmen::after {
  content: ""; position: absolute; left: -6px; right: -6px; height: 12px;
  background-image: linear-gradient(var(--accent), var(--accent)),
                    linear-gradient(var(--accent), var(--accent));
  background-size: 12px 12px;
  background-position: left center, right center;
  background-repeat: no-repeat;
  pointer-events: none;
}
.statement__rahmen::before { top: -6px; }
.statement__rahmen::after  { bottom: -6px; }
/* Der Text steht ueber dem Raster und bekommt Luft zum Rahmen. */
.statement__rahmen > * { position: relative; z-index: 1; }
.statement p { margin: 0; font-weight: 700; font-size: calc(26px * var(--h2-scale)); line-height: 1.5; letter-spacing: -.02em; color: var(--ink); text-wrap: pretty; }
/* ---------- Kostenblock ----------
   Stand bis 04.09.2026 in pages.css, also nur auf Unterseiten verfuegbar.
   Die Startseite laedt pages.css nicht (bewusst: ein Stylesheet weniger im
   Seitenkopf). Verschoben statt kopiert, weil zwei Definitionen desselben
   Bausteins garantiert auseinanderdriften. Unterseiten laden style.css
   ohnehin vor pages.css, dort aendert sich nichts. */
.kostenblock { background: var(--dark); color: #fff; border-radius: 16px; corner-shape: squircle; padding: 24px 28px; margin: 24px 0; }
.kostenblock__zeile { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 16px; border-bottom: 1px solid rgba(255, 255, 255, .2); padding: 10px 0; font-size: 15px; }
.kostenblock__zeile:last-child { border-bottom: 0; }
.kostenblock__wert { font-weight: 500; white-space: nowrap; }
.kostenblock__wert--stark { font-size: 17px; font-weight: 700; color: var(--accent-soft); }

/* ---------- Kosten-Band ----------
   Erster Versuch am 04.09.2026 war eine dunkle .kostenblock-Karte im
   Punktraster-Rahmen: Kasten im Kasten, vier Textsorten in einer 640px
   Spalte, und die Pointe stand als dritte Tabellenzeile in 15px.
   Jetzt nach dem Muster "Bold Stats" von uilayout.contact auf 21st.dev
   (dort React mit Tailwind): EINE herausgestellte Kennzahl, die Stuetzzahlen
   als Zeilen davor. Uebernommen ist diese Gewichtung, nichts vom Code.
   Kein Kasten mehr, die Haarlinie traegt die Rechnung.
   Die Zahl darf das volle Signalorange tragen, obwohl es in Lesegroesse
   auf Weiss nur 3,96:1 erreicht: ab 24px fett gilt die Grenze fuer grosse
   Schrift, also 3:1. Bei 46px aufwaerts ist das mit Reserve erfuellt.
   Die 12.400 Euro sind KEIN Preis von Marvin, sondern Kosten, die der
   Betrieb ohnehin traegt. Die Regel "Preise nur auf /standortbestimmung"
   ist damit nicht verletzt.
   .statement und .statement__rahmen bleiben als Regeln bestehen, werden
   aber nicht mehr verwendet. Der Punktraster-Rahmen ist damit nicht
   geloescht, nur nicht mehr im Einsatz. */
.kosten .band__inhalt { display: grid; gap: 26px; max-width: 46rem; }
.kosten__lead {
  margin: 0; font-weight: 700; font-size: calc(24px * var(--h2-scale));
  line-height: 1.4; letter-spacing: -.02em; color: var(--ink); text-wrap: pretty;
}
.kosten__annahme, .kosten__quelle {
  margin: 0; font-size: calc(15px + var(--fs-bump)); line-height: 1.6;
  color: var(--muted); max-width: var(--lese); text-wrap: pretty;
}
.kosten__quelle { font-size: 14px; }
/* Linie statt Kasten, wie ueberall sonst auf der Seite. */
.kosten__rechnung { display: grid; border-top: 1px solid var(--line); }
.kosten__zeile {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 24px;
  padding: 13px 0; border-bottom: 1px solid var(--line);
  font-size: calc(15px + var(--fs-bump)); line-height: 1.5; color: var(--muted);
}
/* Ziffern in gleicher Laufweite, damit die Werte untereinander stehen. */
.kosten__wert { font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Die Zahl steht IM Satz, nicht daneben. Grund: auf der Seite eines
   Beraters kann eine freistehende grosse Zahl als sein Honorar gelesen
   werden. "Das kostet Ihren Betrieb" benennt ausdruecklich, wessen Kosten
   gemeint sind, und raeumt die Verwechslung ab. */
.kosten__ergebnis {
  margin: 0; font-weight: 700; font-size: calc(24px * var(--h2-scale));
  line-height: 1.4; letter-spacing: -.02em; color: var(--ink); text-wrap: pretty;
}
/* Eigene Zeile statt inline. Zwei Schriftgroessen mit diesem Abstand auf
   EINER Zeile gehen nicht auf: die Zahl sitzt auf der Grundlinie, alles
   dahinter wird rechts danebengequetscht und bricht dann um. Der Satz ist
   deshalb so umgestellt, dass er auf der Zahl ENDET ("pro Jahr" steht
   jetzt davor) und die Zahl als Block darunter steht. Damit kann nichts
   mehr eingezwaengt werden, und die Zahl darf wieder groesser sein.
   Ohne nachgestelltes Wort braucht die Zeile auch keinen Punkt: eine
   Auszeichnungszeile, die auf einer Zahl endet, wird ohne gesetzt. */
.kosten__zahl {
  display: block; margin: 10px 0 0;
  font-size: clamp(46px, 8vw, calc(88px * var(--h2-scale)));
  line-height: 1; letter-spacing: -.04em; color: var(--accent);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.kosten__schluss {
  margin: 0; font-weight: 700; font-size: calc(22px * var(--h2-scale));
  line-height: 1.45; letter-spacing: -.02em; color: var(--ink); text-wrap: pretty;
}

.mark {
  background: var(--accent); color: #fff; padding: 2px 10px;
  border-radius: 10px; corner-shape: squircle;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
}

/* ---------- Angebot ---------- */
.angebot { background: var(--surface); min-height: min(100vh, 1100px); display: flex; align-items: center; padding: calc(72px * var(--space-scale)) calc(64px * var(--space-scale)); }  /* f-42 */
.angebot__card {
  max-width: var(--card-max); margin: 0 auto; width: 100%; padding: calc(48px * var(--space-scale));
  background: var(--dark); color: #fff; border-radius: 32px; corner-shape: squircle;
}
/* ---------- Angebotskarte, dritter Umbau am 11.09.2026 ----------
   Der zweite Umbau (07.09.) hatte zwei Zonen nebeneinander: links WAS es
   ist, rechts eine Liste "Im Massnahmenplan steht". Die rechte Zone
   wiederholte aber nur, was links als Eckdatum steht ("Ein Massnahmenplan,
   schriftlich, priorisiert, gehoert Ihnen") und was /standortbestimmung
   ausfuehrt. Jetzt eine Zone, dafuer eine Stufe groesser: Karte schmaler
   (880 statt 1000px, sonst werden die Zeilen zu lang), Titel 38 statt
   30px, Lead 22 statt 19px, Eckdaten 24 statt 19px.
   Die drei Fakten bleiben Datenliste: Begriff links, Wert rechts,
   Haarlinie dazwischen. Dieselbe Bauart wie .eckdaten auf /kontakt und
   /ueber-mich, nur auf dunklem Grund. Als <dl>, weil es genau das ist:
   Begriff und zugehoerige Angabe. */
.angebot__card .h2 { color: #fff; margin-bottom: 20px; font-size: calc(38px * var(--h2-scale)); }

.angebot__lead { margin: 0 0 40px; font-weight: 500; font-size: calc(22px + var(--fs-bump)); line-height: 1.5; letter-spacing: -.01em; color: rgba(255, 255, 255, .85); text-wrap: pretty; }

.angebot__fakten { margin: 0 0 40px; }
.angebot__fakt {
  display: flex; align-items: baseline; gap: 20px; flex-wrap: wrap;
  border-top: 1px solid rgba(255, 255, 255, .2); padding: 20px 0;
}
.angebot__fakt:last-child { border-bottom: 1px solid rgba(255, 255, 255, .2); }
/* Feste Breite fuer den Begriff, damit die drei Werte in einer Flucht
   beginnen. Ohne sie starteten sie bei 357, 485 und 425px, gemessen: drei
   verschiedene Kanten in einem Block, der Ordnung behaupten soll. Gleiche
   Bauart wie .eckdaten (dort 180px). 280px, weil "Ein Massnahmenplan" in
   24px sonst umbricht. */
.angebot__fakt dt { flex: 0 0 280px; font-weight: 700; font-size: calc(24px * var(--h2-scale)); line-height: 1.25; letter-spacing: -.02em; color: #fff; }
.angebot__fakt dd { flex: 1 1 0; margin: 0; font-size: 17px; line-height: 1.5; color: rgba(255, 255, 255, .7); text-wrap: pretty; }

.angebot__note { margin: 0; max-width: 30ch; font-size: 16px; line-height: 1.5; color: rgba(255, 255, 255, .65); text-wrap: pretty; }
.angebot__actions { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }

/* ---------- Referenzen ---------- */
.referenzen { }
.referenzen .h2 { margin-bottom: 40px; }
.refs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; align-items: stretch; }
.refs__stack { display: grid; gap: 24px; align-content: stretch; }
.ref {
  display: flex; flex-direction: column; gap: 32px;
  border-radius: 24px; corner-shape: squircle; padding: 32px;
}
.ref--accent { background: var(--accent-surface); color: #fff; }
.ref--dark { background: var(--dark); color: #fff; }
.ref--soft { background: var(--surface); border: 1px solid var(--line); gap: 24px; }
/* Wrapper um das Zitat, mit eigenem, engem Abstand: Inhalt darin soll nicht
   in der 32px-Luecke von .ref landen. */
.ref__oben { display: grid; gap: 12px; }
.ref__quote { margin: 0; text-wrap: pretty; }
.ref--accent .ref__quote, .ref--dark .ref__quote { font-weight: 500; font-size: calc(19px + var(--fs-bump)); line-height: 1.4; letter-spacing: -.02em; color: #fff; }
.ref--soft .ref__quote { font-size: calc(17px + var(--fs-bump)); line-height: 1.6; color: var(--ink); }
.ref__meta { display: flex; align-items: center; gap: 14px; margin-top: auto; }
.ref__logo {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; background: #fff; border-radius: 16px; corner-shape: squircle;
  padding: 7px; flex-shrink: 0;
}
.ref__logo img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.ref__logo--dark { background: var(--dark); border: 1px solid var(--line); }
.ref__logo--bordered { border: 1px solid var(--line); }
.ref__logo--mono img { filter: grayscale(1) brightness(.45); }
.ref__name { display: grid; gap: 2px; }
.ref__name b { font-weight: 700; font-size: 16px; letter-spacing: -.01em; }
.ref__name span { font-size: 13px; color: var(--muted); }
.ref--dark .ref__name span { color: rgba(255, 255, 255, .75); }
.ref--accent .ref__name span { color: #fff; }
.ref--soft .ref__name span { color: var(--muted-ink); }

/* ---------- FAQ ---------- */
.faq { }
.faq .h2 { margin-bottom: 40px; }
/* Zeilenweises Grid wie im Design-Artboard (Reihenfolge: 1+2, 3+4, 5+6 …).
   align-items:start verhindert, dass ein geöffneter Eintrag die Nachbarzelle
   in derselben Zeile auf seine Höhe streckt (f-17); border-bottom sitzt auf dem
   Container und damit unabhängig von der Zeilenzahl immer ganz unten. */
.faq__grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 56px; align-items: start; border-bottom: 1px solid var(--line); }
.faq details { border-top: 1px solid var(--line); }
.faq summary {
  font-weight: 700; font-size: 19px; letter-spacing: -.01em; color: var(--ink);
  padding: 18px 0; cursor: pointer; min-height: 44px; transition: color .25s ease;
}
.faq summary:hover { color: var(--accent); }
.faq details p { margin: 0 0 20px; max-width: var(--lese); font-size: calc(17px + var(--fs-bump)); line-height: 1.65; color: var(--ink); }

/* ---------- Abschluss + Footer ---------- */
.closing { min-height: min(100vh, 1100px); display: flex; flex-direction: column; }  /* f-42 */
.kontakt { background: var(--dark); flex: 1; display: flex; align-items: center; }
.kontakt h2 { margin: 0 0 16px; font-weight: 700; font-size: calc(36px * var(--h2-scale)); line-height: 1; letter-spacing: -.03em; color: #fff; text-wrap: balance; }  /* f-40: kein Waisenkind in der letzten Zeile */
.kontakt__sub { margin: 0 0 40px; font-size: calc(17px + var(--fs-bump)); line-height: 1.65; color: rgba(255, 255, 255, .8); }
.kontakt__row { display: flex; align-items: center; gap: 32px; flex-wrap: wrap; }
.kontakt__row p { margin: 0; font-size: calc(17px + var(--fs-bump)); line-height: 1.6; color: rgba(255, 255, 255, .8); }
.kontakt__row p a { color: #fff; display: inline-block; padding: 10px 0; }  /* f-14: Tap-Ziel >=44px */

.site-footer { border-top: 1px solid var(--line); background: var(--paper); }
.site-footer__inner { max-width: var(--footer-max); margin: 0 auto;
  padding: calc(56px * var(--space-scale)) calc(72px * var(--space-scale)) calc(32px * var(--space-scale)); }
.site-footer__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 48px; flex-wrap: wrap; margin-bottom: 40px; }
.site-footer__logo { display: inline-flex; }
.site-footer__logo img { height: 140px; width: auto; display: block; }
.site-footer__cols { display: flex; gap: 64px; flex-wrap: wrap; }
.site-footer__col { display: grid; gap: 0; align-content: start; }  /* f-14: gap durch Link-Padding ersetzt */
.footer-label { font-size: 12px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; }
.site-footer__col .footer-label:not(:first-child) { margin-top: 18px; }  /* "Zum Nachlesen" unter den Türen */
.site-footer__col a {
  font-size: 15px; color: var(--ink); text-decoration: none;
  display: inline-block; padding: 11px 0; margin: -5px 0;  /* f-14: Tap-Ziel >=44px, Optik unverändert */
}
.site-footer__col a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.site-footer__col .muted { font-size: 15px; color: var(--muted); }
.site-footer__bottom {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding-top: 24px; border-top: 1px solid var(--line);
}
.site-footer__bottom p { margin: 0; font-size: 13px; color: var(--muted); }

/* ---------- WhatsApp-Button ---------- */
.wa-float {
  position: fixed; right: 24px; bottom: 24px; z-index: 150;
  width: 60px; height: 60px; border-radius: 20px; corner-shape: squircle;
  background: var(--wa); display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 28px rgba(23, 40, 30, .28);
  transition: background .25s ease, transform .2s ease;
}
.wa-float:hover { transform: scale(1.07); background: var(--dark); }
/* Fixierter WA-Button verdeckt sonst die Footer-Schlusszeile (mobil bis 1120px, f-13) */
@media (max-width: 1120px) {
  .site-footer__inner { padding-bottom: 96px; }
  .site-footer__bottom { padding-right: 88px; }
}

/* ---------- Dialoge (natives <dialog>) ---------- */
dialog.modal {
  border: 0; margin: 0; padding: 24px; inset: 0;
  width: 100%; height: 100%; max-width: none; max-height: none;
  background: transparent; color: var(--ink);
}
dialog.modal[open] { display: flex; align-items: center; justify-content: center; }
dialog:not([open]) { display: none; }  /* Sicherheitsnetz für Browser ohne <dialog>-UA-Regel (f-60) */
dialog.modal::backdrop { background: rgba(23, 40, 30, .55); }
html:has(dialog[open]) { overflow: hidden; }
/* Breite der verschwundenen Scrollbar ausgleichen, damit Header/WA-Button beim
   Öffnen/Schließen nicht springen (f-23). --sbw wird in js/main.js VOR showModal()
   gesetzt: document.documentElement.style.setProperty('--sbw', (innerWidth - document.documentElement.clientWidth) + 'px').
   Ohne diesen JS-Anteil bleibt --sbw 0px und diese Regeln sind ein No-op. */
html:has(dialog[open]) body { padding-right: var(--sbw, 0px); }
html:has(dialog[open]) .site-header { right: var(--sbw, 0px); }
html:has(dialog[open]) .wa-float { right: calc(24px + var(--sbw, 0px)); }
.modal__box {
  position: relative; background: #fff; border-radius: 24px; corner-shape: squircle;
  padding: 48px; width: 480px; max-width: 100%;
  max-height: 90vh; max-height: min(90dvh, 100dvh - 48px); /* f-41: dvh statt vh gegen Browser-UI-Überlappung */
  overflow: auto;
}
.modal__close {
  position: absolute; top: 16px; right: 16px; width: 44px; height: 44px;
  border-radius: 14px; corner-shape: squircle; border: 1px solid var(--line);
  background: #fff; color: var(--ink); font-size: 18px; cursor: pointer;
  display: grid; place-items: center; padding: 0;
}
.modal__close:active { background: var(--surface); }
.modal h2 {
  margin: 0 0 8px; padding-right: 52px; font-weight: 700; font-size: 28px;
  letter-spacing: -.02em; color: var(--ink); hyphens: auto; overflow-wrap: break-word;
}  /* padding-right f-03: Platz vor dem ✕-Button; hyphens f-01 */
.modal__sub { margin: 0 0 28px; font-size: 16px; line-height: 1.6; color: var(--muted); }
.modal__options { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }  /* f-03: verhindert Content-getriebene Mindestbreite */
@media (max-width: 320px) {
  .modal__box { max-width: calc(100vw - 32px); }  /* f-03: 280px-Viewport ohne horizontalen Scroll */
}
.option {
  display: flex; align-items: center; gap: 16px; min-width: 0; text-decoration: none;
  border-radius: 16px; corner-shape: squircle; padding: 18px 22px;
  transition: background .25s ease, color .25s ease, transform .2s ease;
}
.option svg { flex-shrink: 0; }
.option--wa { background: var(--wa); color: var(--dark); }  /* f-09: dunkler Text auf Markengrün statt Weiß, 7.79:1 */
.option--wa svg { fill: var(--dark); }
.option--wa:hover, .option--wa:active { color: #fff; }
.option--wa:hover svg, .option--wa:active svg { fill: #fff; }
.option--wa:hover { background: var(--dark); }
.option--wa:active { background: var(--dark-active); }
.option--mail, .option--tel, .option--termin { border: 1px solid var(--line); color: var(--ink); }
.option--mail:hover, .option--tel:hover, .option--termin:hover { background: var(--dark); color: #fff; border-color: var(--dark); }
.option--mail:hover svg, .option--tel:hover svg, .option--termin:hover svg { stroke: #fff; }
.option--mail:active, .option--tel:active, .option--termin:active { background: var(--dark-active); }
.option__text { display: grid; gap: 2px; min-width: 0; }
.option__text b { font-weight: 500; font-size: 17px; }
.option__text span { font-size: 14px; overflow-wrap: anywhere; }  /* f-03: unumbrechbare E-Mail-Adresse darf brechen */
.option--wa .option__text span { opacity: 1; }  /* f-09: volle Deckkraft für ausreichenden Kontrast */
.option--mail .option__text span, .option--tel .option__text span, .option--termin .option__text span { color: var(--muted); }
.option--mail:hover .option__text span, .option--tel:hover .option__text span, .option--termin:hover .option__text span { color: rgba(255, 255, 255, .8); }


/* ---------- Animationen ---------- */
@keyframes reveal { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: none; } }
/* Eigene Keyframes ohne opacity nur für den Hero: das Element gilt so von Anfang an
   als sichtbar/gemalt und bleibt LCP-fähig, nur die Slide-up-Bewegung bleibt (f-18) */
@keyframes reveal-load { from { transform: translateY(28px); } to { transform: none; } }
@keyframes nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(6px); } }
@keyframes twblink { 50% { opacity: 0; } }

.reveal-load { animation: reveal-load .7s ease backwards; }  /* f-50: backwards statt both löst den Compositing-Layer nach Ende; f-18: kein opacity-Keyframe mehr */
.reveal { animation: reveal .7s ease both; }
/* Scroll-gesteuert wie im Design, wo der Browser es kann … */
@supports (animation-timeline: view()) {
  .reveal { animation-timeline: view(); animation-range: entry 0% entry 30%; }
}
/* … sonst IntersectionObserver-Fallback (Klasse kommt aus dem Head-Skript). */
.js-reveal .reveal { animation: none; opacity: 0; }
.js-reveal .reveal.is-in { animation: reveal .7s ease both; }

/* Typewriter-Cursor: main.js setzt diese Klasse, sobald die Schreibmaschine fertig
   ist, damit das Blinken nicht endlos weiterläuft (WCAG 2.2.2, f-31). */
.tw-cursor.tw-done { animation: none; }
html:not(.js) .tw-cursor { display: none; }  /* ohne JS läuft kein Typewriter, also kein Cursor */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .reveal, .js-reveal .reveal, .reveal-load { opacity: 1; transform: none; }
  /* main.js bindet den Scroll-Listener dann gar nicht erst; das hier ist die
     zweite Linie, falls doch je ein transform inline gesetzt wuerde. */
  .pxhero__layer-img, .pxhero__layer-title { transform: none !important; will-change: auto; }
  html { scroll-behavior: auto; }
}

/* ---------- Druck ---------- */
@media print {
  /* Scroll-Animationen greifen beim Drucken nie: ohne Reset bleiben 7 von 8
     .reveal-Containern bei opacity:0 hängen, der Ausdruck wirkt leer (f-32). */
  .reveal, .reveal-load, .js-reveal .reveal { animation: none !important; opacity: 1 !important; transform: none !important; }
  .wa-float, .pxhero__layers, .pxhero__fade, .skip-link, dialog, .nav-toggle { display: none !important; }
  .site-header { position: static; }
  .page, .frame, .screen, .hero, .pxhero__scene, .angebot, .closing { min-height: auto; }
}

/* ---------- Responsive ---------- */
@media (max-width: 1100px) {
  .person__grid { grid-template-columns: 320px 1fr; gap: 48px; }
}
/* Portrait-Tablets (z.B. 1024x1366): Screens sind höher als ihr Inhalt (f-16) */
@media (max-width: 1100px) and (orientation: portrait) {
  .screen, .hero, .angebot, .closing { min-height: auto; }
}
@media (max-width: 1100px) {
  .nav-toggle { display: inline-flex; }
  /* Ohne JS gibt es keine Klappe: Burger weg, Links sichtbar umbrechen,
     der Erstgespräch-Knopf bleibt als Nav-Eintrag erreichbar. */
  html:not(.js) .nav-toggle { display: none; }
  html:not(.js) .site-header__inner { flex-wrap: wrap; }
  html:not(.js) .nav { display: flex; flex-wrap: wrap; gap: 4px 12px; width: 100%; }
  html:not(.js) .nav .nav__cta { display: inline-flex; }
  /* Der Erstgespräch-Knopf wandert in die Klappe: bei 320px bleiben neben
     Logo und Knopf nur rund 32px übrig, zu wenig für ein 44px-Ziel.
     Erreichbar bleibt der Kontakt jederzeit über den WhatsApp-Knopf, der
     auf dem Handy dauerhaft sichtbar ist. */
  .site-header__inner > .btn--small { display: none; }
  .site-header__inner { justify-content: space-between; }

  /* Geschlossen: display:none nimmt die Liste auch aus dem
     Bedienungshilfen-Baum, nicht nur aus dem Bild. */
  .nav { display: none; }
  .nav[data-offen] {
    display: flex; flex-direction: column; align-items: stretch; gap: 4px;
    position: absolute; left: 0; right: 0; top: 100%;
    background: var(--paper);
    box-shadow: 0 12px 28px rgba(23, 40, 30, .14);
    border-top: 1px solid var(--line);
    padding: 12px 16px 20px;
    max-height: calc(100vh - var(--header-h)); overflow-y: auto;
  }
  .nav[data-offen] a {
    padding: 14px 12px; font-size: 16px; border-radius: 12px;
    border-bottom: 1px solid var(--line);
  }
  .nav[data-offen] a:last-of-type { border-bottom: 0; }
  .nav[data-offen] a[aria-current="page"] { color: var(--accent-ink); }
  /* Der Erstgespräch-Knopf als letzter, hervorgehobener Eintrag. */
  .nav[data-offen] .nav__cta { display: block; margin-top: 12px; text-align: center; }
}
@media (max-width: 960px) {
  .screen, .hero, .angebot, .closing { min-height: auto; }
  .wrap, .wrap--tight, .hero__inner, .band { padding-left: 32px; padding-right: 32px; }
  .band--kopf { padding-top: calc(var(--header-h) + 72px); }
  .hero__inner { padding-top: 112px; }
  .pxhero__scene { min-height: min(66vh, 660px); }
  .pxhero__layer-title { padding: 96px 32px 32px; }
  .pxhero__content { padding: 0 32px 56px; }
  .person__grid { grid-template-columns: 1fr; gap: 40px; }
  .person__figure { max-width: 380px; }
  .doors { grid-template-columns: 1fr; gap: 32px; }   /* f-44: 3 Spalten sind 841-960px zu eng */
  .steps { grid-template-columns: 1fr; gap: 32px; }
  .angebot { padding: 56px 32px; }
  .angebot__fakt { gap: 4px; }
  .angebot__fakt dt { flex-basis: 100%; }
  .refs { grid-template-columns: 1fr 1fr; }
  .refs__stack { display: contents; }
  .faq__grid { grid-template-columns: 1fr; }
  .site-footer__inner { padding: 48px 32px 24px; }
}
@media (max-width: 640px) {
  :root { --header-h: 64px; }
  .site-header__inner { padding: 12px 16px; gap: 12px; }
  .site-header__logo img { height: 30px; }
  .btn--small { font-size: 14px; padding: 11px 14px; }
  .wrap, .wrap--tight, .band { padding: 56px 20px; }
  .band--kopf { padding-top: calc(var(--header-h) + 48px); }
  .hero__inner { padding: 96px 20px 32px; }
  .hero__title { font-size: 22px; }
  .pxhero__layer-title { padding: 84px 20px 24px; }
  /* Ohne eigene Stufe erbte das Handy die 66vh/660px von 960px. Auf 390x844
     endete Tuer 01 dann bei 827px und Tuer 02 begann bei 859px, also 15px
     UNTER der Falz: sichtbar war genau eine Tuer, ohne jeden Hinweis, dass
     zwei weitere folgen. Die H1 verspricht aber "eines von drei Dingen".
     52vh/520px zieht Tuer 02 in den ersten Viewport hinein, der Anschnitt
     ist das Scroll-Signal. */
  .pxhero__scene { min-height: min(52vh, 520px); }
  .pxhero__content { padding: 0 20px 48px; }
  .hero__cta { gap: 20px; margin-top: 40px; }
  .btn:not(.btn--small) { width: 100%; white-space: normal; text-align: center; }
  .statement__wrap { padding: 32px 20px 64px; }
  .statement__rahmen { padding: 24px 18px; }
  .statement p { font-size: 22px; }
  .angebot { padding: 40px 16px; }
  .angebot__card { padding: 32px 24px; border-radius: 24px; }
  .refs { grid-template-columns: 1fr; }
  .ref { padding: 24px; }
  .kontakt h2 { font-size: 30px; }
  .site-footer__inner { padding: 40px 20px 24px; }
  .site-footer__logo img { height: 110px; }
  .site-footer__cols { gap: 32px 48px; }
  .modal__box { padding: 40px 24px 28px; }
  .wa-float { right: 16px; bottom: 16px; width: 56px; height: 56px; }
}

/* Silbentrennung in Ueberschriften nur dort, wo sie einen Ueberlauf
   verhindert. hyphens:auto ist bei schmalen Spalten die Rettung, bei
   breiten erzeugt es Trennstriche mitten im Wort, wo genug Platz waere:
   gemessen brach ".door h3" zwischen 2000 und 2799px "einge-/fuehrt",
   waehrend dieselbe Ueberschrift bei 1999px und ab 2800px sauber lief.
   Ab 700px ist jede dieser Ueberschriften-Spalten breit genug, dass
   Trennung nicht mehr noetig ist. overflow-wrap:anywhere bleibt als
   Notbremse fuer ein wirklich zu langes Wort bestehen. */
@media (min-width: 700px) {
  .h2, .angebot__fakt b, .door h3, .step h3, .modal h2 { hyphens: manual; }
}

/* Der Dialog-Titel "Erstgespraech gratis" brach bei 320 bis 339px in drei
   Zeilen, die erste mit Trennstrich als "Erstge-/spraech". Gleiche Loesung
   wie bei f-40 weiter oben: nicht die Trennung erzwingen, sondern die
   Schrift so weit zuruecknehmen, dass das Wort in eine Zeile passt.
   Per Playwright vermessen: bei 24px passt "Erstgespraech" ab 300px
   ungetrennt in eine Zeile, der Titel wird zweizeilig. */
@media (max-width: 360px) {
  .modal h2 { font-size: 24px; hyphens: manual; }
}
/* f-40: Bei <=364px reicht die Zeilenbreite nicht mehr für „Vom ersten Gespräch“
   in 30px, wodurch hyphens:auto das Wort zu „Ge-/spräch“ trennt bzw. „Umsetzung“
   nach dem harten <br> als Waisenkind in eine eigene Zeile fällt. Den <br> per CSS
   auszublenden ist keine Option: Im Markup steht zwischen „Gespräch“ und „bis“ kein
   Leerzeichen (nur der Zeilenumbruch trennt), display:none auf dem <br> würde die
   Wörter messbar zu „Gesprächbis“ verschmelzen (0px Abstand, per Playwright-Range
   nachgemessen). Stattdessen die Schriftgröße nur dieser Überschrift so weit
   reduzieren, dass beide Hälften bis 280px sauber in zwei Zeilen passen (per
   Playwright/getClientRects vermessen: 22px ist hyphenationsfrei bis 364px, ab
   365px reicht bereits die volle Größe). */
@media (max-width: 364px) {
  #ablauf-title { font-size: 22px; }
}
/* f-02: Logo + Header-CTA kollidieren unter ~400px (Button wird abgeschnitten) */
@media (max-width: 400px) {
  .site-header__inner { padding: 12px 12px; gap: 8px; }
  .site-header__logo { flex: 0 1 auto; min-width: 0; max-width: 140px; }
  .site-header__logo img { max-width: 100%; height: auto; max-height: 28px; }
  .btn--small {
    flex: 0 1 auto; white-space: normal; text-align: center; line-height: 1.1;
    padding: 8px 10px; min-height: 44px; font-size: 13px;
  }
}
/* Niedrige Viewports (Landscape-Handys): Header nimmt sonst >20% der Höhe ein (f-39),
   der Erstgespräch-Dialog braucht internes Scrollen (f-38) */
@media (max-height: 480px) {
  :root { --header-h: 60px; }
  .site-header__inner { padding: 8px 32px; }
  .site-header__logo img { height: 36px; }
  .btn--small { padding: 10px 18px; }
  .hero__inner { padding-top: 84px; }
  .modal__box { padding: 24px 24px 20px; }
  .modal h2 { font-size: 22px; }
  .modal__sub { margin-bottom: 14px; }
  .option { padding: 12px 16px; }
  .modal__close { top: 12px; right: 12px; }
}

/* ---------- Große Bildschirme: gestufte Vergrößerung ----------
   Drei Stufen (1500 / 2000 / 2800px) statt vormals zwei (2000 / 2800px):
   ein 1920px-Bildschirm bekam bisher gar keine Stufe (naechster Sprung erst
   bei 2000px). Alles laeuft ueber die Tokens aus :root (siehe dort).
   Unterhalb von 1500px aendert sich nichts (Tokens dort auf IST-Werte
   gesetzt). Lesetext-Grundgroesse laut 01_DESIGN.md ist 17-18px; --fs-bump
   traegt das zusammen mit den fuenf calc(17px + var(--fs-bump))-Regeln
   (.person__text p, .angebot__lead, .faq details p,
   .kontakt__sub) zu 17/18/19/20px je Stufe. Deren max-width in ch (ebenso
   .door p, das keine eigene fs-bump-Stufung hat) braucht KEINE eigene
   Override-Regel je Stufe mehr: ch skaliert automatisch mit der jeweils
   aktuellen Schriftgroesse des Elements mit, die Zeichenzahl/Zeile bleibt
   dadurch stufenuebergreifend konstant (per Playwright nachgemessen, siehe
   Bericht). --hero-max/--statement-max/--card-max/--footer-max wachsen im
   selben Verhaeltnis wie --container-max (1360 -> 1440/1560/1720) mit,
   --wrap-max ebenso (1080 -> 1144/1239/1366), sonst kippt die
   Groessenordnung zwischen Hero/Abschnitten/Fuss (siehe Kommentar oben
   bei den Tokens). */
@media (min-width: 1500px) {
  :root {
    --lese: 700px;   /* 58ch bei der Schriftgroesse dieser Stufe, gemessen */
    --container-max: min(1584px, calc(100vw - 96px));
    --wrap-max: 1258px;
    --space-scale: 1.17;
    --fs-bump: 3px;
    --h2-scale: 1.14;
    /* gleiches Verhältnis wie --container-max (1360 -> 1584) */
    --hero-max: 1305px;
    --statement-max: 746px;
    --card-max: 1165px;
    --footer-max: 1258px;
    --portrait-w: 462px;
    --hero-scale: 1.25;
  }
}
@media (min-width: 2000px) {
  :root {
    --lese: 755px;   /* 58ch bei der Schriftgroesse dieser Stufe, gemessen */
    --container-max: min(1716px, calc(100vw - 96px));
    --wrap-max: 1363px;
    --space-scale: 1.23;
    --fs-bump: 4px;
    --h2-scale: 1.19;
    /* gleiches Verhältnis wie --container-max (1360 -> 1716) */
    --hero-max: 1414px;
    --statement-max: 807px;
    --card-max: 1262px;
    --footer-max: 1363px;
    --portrait-w: 517px;
    --hero-scale: 1.25;
  }
}
@media (min-width: 2800px) {
  :root {
    --lese: 790px;   /* 58ch bei der Schriftgroesse dieser Stufe, gemessen */
    --container-max: min(1892px, calc(100vw - 96px));
    --wrap-max: 1503px;
    --space-scale: 1.38;
    --fs-bump: 5px;
    --h2-scale: 1.28;
    /* gleiches Verhältnis wie --container-max (1360 -> 1892) */
    --hero-max: 1558px;
    --statement-max: 890px;
    --card-max: 1392px;
    --footer-max: 1503px;
    --portrait-w: 572px;
    --hero-scale: 1.25;
  }
}
