/* ============================================================
   haake.css — Der Hausmeister Haake, Gelsenkirchen
   Die einzige CSS-Datei der Site. Kein Framework, kein Build.
   Farbrichtung "Rittergut" (29.07.2026): Gold ist Handlungsfarbe,
   Wald-Grün ist nur noch Tiefe/Stimmung. Kein Dark Mode mehr —
   ein Theme, dafür sauber durchgezogen. WCAG 2.1 AA.
   Gliederung:
     01 Schrift (@font-face, self-hosted)
     02 Design-Tokens
     03 Reset & Basis
     04 Typografie
     05 Skip-Link & Fokus
     06 Kopfbereich: Infoleiste + Header (eine Sticky-Einheit)
     07 Navigation (Desktop ab 1100px, darunter Burger)
     08 Knöpfe & Textlinks
     09 Hero (Auftakt)
     10 Merkmale-Trio
     11 Abschnitte & Sektionsköpfe
     12 Leistungskarten
     13 Duo & Merkkasten (Über uns)
     14 Schritte (Festpreis-Ablauf)
     15 Referenzen (Sand + Ziegel-Akzent)
     16 Notdienst- & CTA-Band
     17 Kontakt-Karten
     18 Formular
     19 Footer
     20 Mobiler Anrufbalken
     21 Seitenkopf & Brotkrumen (Unterseiten)
     21b FAQ (Preise)
     22 Header-Scroll-Zustand
     23 Signet-Zeichnung (Header, einmalig beim Laden)
     24 Hero-Choreografie (Eintritt + Neigung zur Maus)
     25 Nav-Hover & Mobilmenü-Eintritt
     26 Knopf-Glanz (nur farbige Flächen — Karten/Sekundärknopf bleiben ohne,
        Weiß-auf-Weiß wäre unsichtbar; Icon-Bounce der Karten sitzt in §12)
     27 Scroll-Reveal & Zahlen-Zählanimation
     28 Lesefortschrittsbalken
     29 Seitenübergänge (View Transitions API)
     30 Bewegung reduzieren
   Regeln: null !important · genau ein Breakpoint (1100px) ·
   jede Schriftgröße ist ein Token · Sektionsrhythmus 2 Stufen.
   Animationen (22–29, plus Referenz-Vorhang in §15 und Schritt-Zahl-
   Pop in §14) sind vollautomatisch: neue Karten/Schritte/Zahlen/
   Kontakt-Karten/Footer-Spalten bekommen sie ohne Markup-Änderung,
   siehe KONVENTIONEN.md §10.
   ============================================================ */

/* ---------- 01 Schrift ---------- */
@font-face {
  font-family: "Figtree";
  src: url("/fonts/figtree-latin-wght.woff2") format("woff2-variations");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- 02 Design-Tokens ---------- */
:root {
  color-scheme: light;

  /* Farben — Gold ist Handlungsfarbe (Buttons, Links, Nav-aktiv, Kennzahlen),
     Wald ist Tiefe (Titel, Band, Footer), Grün als Signalfarbe existiert nicht mehr. */
  --gold: #A9813F;             /* Markenakzent: Signet-Blatt, Zierlinie, Karten-Icon/Strich */
  --gold-hell: #C9A25E;        /* Signet-Blatt 2, Band-Überzeile auf Dunkelgrund */
  --gold-text: #7C5E2C;        /* alle goldenen Klein-/Fließtexte, Links, Nav aktiv, Kennzahlen */
  --gold-cta: #8F6D35;         /* Primär-Button-Fläche: 4,77:1 mit Weiß (AA) */
  --gold-cta-hover: #7A5C2C;
  --wald-tief: #23301F;        /* Titel, Notdienst-Band, Footer */
  --wald-blass: #E7E9DC;       /* Infoleiste, Icon-Kreise */
  --wald-linie: #D6D6C2;       /* Zierlinien-Rahmen (Karten/Kasten-Border) */
  --bg: #EBEDE1;               /* Seitenhintergrund, gedecktes Salbei-Stein */
  --flaeche: #FFFFFF;          /* Karten, Header — voll deckend */
  --sand: #F6EFE2;             /* warmer Sektionshintergrund (max. 2 Flächen je Seite) */
  --ziegel: #B08055;           /* Ruhrgebiets-Akzent, nur dekorativ / ≥24px bold */
  --text: #262B21;
  --text-hell: #5C6152;        /* Nebentext — 5,4:1 auf --bg, 5,59:1 auf --sand (AA) */
  --titel: #23301F;
  --linie: #E1DFD0;
  --feld-rahmen: #8C7F52;      /* Formularfeld-Rahmen: 3,98:1 auf Weiß (1.4.11) */
  --fehler: #A33A2A;           /* Invalid-Zustand Formularfelder */

  --cta-schrift: #FFFFFF;      /* Schrift auf --gold-cta */
  --fokus: #7C5E2C;            /* Fokusring, Standardwert = --gold-text */

  /* Band/Footer (Grund immer --wald-tief) */
  --band-text: #D9CFAE;
  --fuss-text: #B7B49C;
  --fuss-meta: #A6A38C;

  /* Typo-Skala — 8 Stufen, keine freien rem-Werte */
  --font: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --fs-xs: 0.8125rem;  /* Überzeilen, Meta, Brotkrumen */
  --fs-s: 0.9375rem;   /* Kleintext, Footer, Plakette */
  --fs-0: 1rem;        /* Fließtext */
  --fs-1: 1.125rem;    /* Intro-/Hero-Absatz */
  --fs-2: 1.375rem;    /* H3, Kartentitel */
  --fs-3: 1.75rem;     /* H2 kompakt, Referenz-Zahlen */
  --fs-4: clamp(1.9rem, 3.2vw, 2.375rem);   /* H2 */
  --fs-5: clamp(2.125rem, 5vw, 3.25rem);    /* H1 */
  --lh-eng: 1.15;
  --lh-basis: 1.65;

  /* Spacing (8er-Raster) */
  --r0: 4px; --r1: 8px; --r2: 16px; --r3: 24px; --r4: 32px;
  --r5: 48px; --r6: 64px; --r7: 96px; --r8: 128px;
  --sektion: clamp(64px, 9vw, 112px);  /* Standard-Rhythmus */
  --sektion-kompakt: 48px;             /* Infobänder, Brotkrumen */
  --breite: 1200px;

  /* Radius & Schatten */
  --radius-s: 10px;
  --radius: 14px;
  --schatten: 0 2px 10px rgba(35, 48, 31, .07);
  --schatten-hoch: 0 10px 30px rgba(35, 48, 31, .14);
}

/* ---------- 03 Reset & Basis ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
/* scroll-padding = reale Sticky-Höhe + Luft:
   mobil klebt nur der Header (76px), Desktop die ganze Einheit (~120px). */
html { scroll-behavior: smooth; scroll-padding-top: 92px; }
@media (min-width: 1100px) { html { scroll-padding-top: 136px; } }
body {
  font-family: var(--font);
  font-size: var(--fs-0);
  line-height: var(--lh-basis);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
img { height: auto; }
ul[class], ol[class] { list-style: none; padding: 0; }
a { color: var(--gold-text); text-underline-offset: 3px; }
button { font: inherit; cursor: pointer; }
.wrap { max-width: var(--breite); margin-inline: auto; padding-inline: 20px; }
@media (min-width: 1100px) { .wrap { padding-inline: 40px; } }

/* ---------- 04 Typografie ---------- */
h1, h2, h3 { color: var(--titel); line-height: var(--lh-eng); font-weight: 800; text-wrap: balance; }
h1 { font-size: var(--fs-5); letter-spacing: -.015em; }
h2 { font-size: var(--fs-4); letter-spacing: -.01em; }
h3 { font-size: var(--fs-2); }
p, li { max-width: 62ch; }
.ueberzeile {
  font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .14em; color: var(--gold-text); margin-bottom: var(--r2);
  max-width: none;
}
.einleitung { font-size: var(--fs-1); color: var(--text-hell); }

/* ---------- 05 Skip-Link & Fokus ---------- */
.sprungmarke {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--gold-cta); color: var(--cta-schrift); padding: 12px 20px;
  border-radius: 0 0 var(--radius-s) 0; font-weight: 700; text-decoration: none;
}
.sprungmarke:focus { left: 0; }
:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; border-radius: 2px; }
/* Fokusring lokal umfärben, wo der Grund dunkel ist (1.4.11):
   Band + Footer liegen auf --wald-tief → Weiß (13,87:1);
   Anrufbalken liegt auf --gold-cta → CTA-Schriftfarbe (4,77:1). */
.band, .site-footer { --fokus: #FFFFFF; }
.anrufbalken { --fokus: var(--cta-schrift); }

/* ---------- 06 Kopfbereich: Infoleiste + Header ---------- */
/* Mobil: nur der Header klebt. Desktop: die ganze Einheit klebt —
   kein Magic-Number-Offset. */
.kopfbereich { position: relative; z-index: 50; }
.infoleiste { background: var(--wald-blass); font-size: var(--fs-s); }
.infoleiste .wrap {
  display: flex; justify-content: center; align-items: center;
  gap: var(--r2); min-height: 40px; flex-wrap: wrap; padding-block: 2px;
}
/* Mobil zählt nur der Notdienst-Link — der Ortszusatz käme sonst zweizeilig. */
.infoleiste .ort { display: none; align-items: center; gap: 7px; color: var(--text); }
.infoleiste .notdienst-link {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--titel); font-weight: 700; text-decoration: none;
  padding-block: 6px; /* Zielhöhe ≥ 24px */
}
.infoleiste .notdienst-link:hover { text-decoration: underline; }
.infoleiste svg { width: 17px; height: 17px; stroke: var(--gold-text); fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; flex: none; }

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--flaeche);
  border-bottom: 1px solid var(--linie);
  transition: box-shadow .3s ease;
}
.site-header .wrap { display: flex; align-items: center; gap: var(--r1); min-height: 76px; }
/* Header-Scroll-Zustand: siehe §22 — nur Schatten, keine Höhenänderung
   (Höhe bleibt fest, sonst kollidiert es mit dem sorgfältig vermessenen
   Mobil-Overflow-Fix aus der QA). */
/* Mobil eine Stufe kleiner (Marke + Signet), sonst läuft die nowrap-Zeile
   auf 360–400px-Phones über; Desktop zieht auf --fs-0/40px hoch. */
.marke {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 800; color: var(--titel); text-decoration: none;
  text-transform: uppercase; letter-spacing: .02em; white-space: nowrap;
  margin-right: auto;
}
.marke strong { font-size: var(--fs-xs); }
.marke .signet { width: 32px; height: 32px; flex: none; }
/* Signet: Hauslinien laufen über currentColor, Blätter über Token —
   kein path[stroke=…]-Hack mehr. */
.signet .haus { stroke: currentColor; }
.signet .blatt-1 { fill: var(--gold); }
.signet .blatt-2 { fill: var(--gold-hell); }
.site-footer .signet { color: #FFFFFF; }

@media (min-width: 1100px) {
  .kopfbereich { position: sticky; top: 0; }
  .site-header { position: static; }
  .site-header .wrap { gap: var(--r2); }
  .infoleiste .wrap { justify-content: space-between; }
  .infoleiste .ort { display: inline-flex; }
  .marke { gap: 10px; letter-spacing: .05em; }
  .marke strong { font-size: var(--fs-0); }
  .marke .signet { width: 40px; height: 40px; }
}

/* ---------- 07 Navigation ---------- */
.haupt-nav { display: none; }
.haupt-nav.offen {
  display: block; position: absolute; left: 0; right: 0; top: 100%;
  background: var(--flaeche); border-bottom: 1px solid var(--linie);
  box-shadow: var(--schatten-hoch); padding: var(--r2) 20px var(--r3);
}
.haupt-nav ul { display: flex; flex-direction: column; gap: var(--r0); }
.haupt-nav a {
  display: block; padding: 10px 14px; color: var(--titel);
  text-decoration: none; font-weight: 600; border-radius: var(--radius-s);
}
.haupt-nav a:hover { color: var(--gold-text); background: var(--wald-blass); }
.haupt-nav a[aria-current="page"] { color: var(--gold-text); }

/* Doppelklasse nötig: das spätere .knopf { display:inline-flex } (Sektion 08)
   würde ein einfaches .kopf-cta { display:none } überstimmen. */
.knopf.kopf-cta { display: none; }

.menue-schalter {
  display: inline-flex; flex-direction: column; justify-content: center; gap: 5px;
  width: 44px; height: 44px; padding: 10px;
  background: none; border: 1px solid var(--linie); border-radius: var(--radius-s);
}
.menue-schalter span {
  display: block; height: 2px; width: 100%; background: var(--titel);
  border-radius: 1px; transition: transform .25s, opacity .25s;
}
.menue-schalter[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menue-schalter[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menue-schalter[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (min-width: 1100px) {
  .haupt-nav, .haupt-nav.offen {
    display: block; position: static; background: none;
    border: 0; box-shadow: none; padding: 0;
  }
  .haupt-nav ul { flex-direction: row; gap: 2px; }
  .haupt-nav a { padding: 10px 13px; white-space: nowrap; position: relative; background: none; }
  .haupt-nav a:hover { background: none; }
  .haupt-nav a[aria-current="page"]::after {
    content: ""; position: absolute; left: 13px; right: 13px; bottom: 4px;
    height: 2px; background: var(--gold-text); border-radius: 1px;
  }
  .knopf.kopf-cta { display: inline-flex; }
  .menue-schalter { display: none; }
}

/* ---------- 08 Knöpfe & Textlinks ---------- */
/* Eine flache Button-Definition. Primär = .knopf,
   Sekundär = .knopf--sekundaer, reiner Textlink = .textlink */
.knopf {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 15px 26px; border: 0; border-radius: var(--radius-s);
  background: var(--gold-cta); color: var(--cta-schrift);
  font-size: var(--fs-0); font-weight: 700; text-decoration: none;
  box-shadow: var(--schatten);
  transition: background-color .2s, transform .2s, box-shadow .2s, border-color .2s, color .2s;
}
.knopf:hover { background: var(--gold-cta-hover); transform: translateY(-1px); box-shadow: var(--schatten-hoch); }
.knopf:active { transform: translateY(0); box-shadow: var(--schatten); }
.knopf svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.knopf--sekundaer { background: var(--flaeche); color: var(--titel); border: 1px solid var(--wald-linie); }
.knopf--sekundaer:hover { background: var(--flaeche); border-color: var(--gold-text); color: var(--gold-text); }
.textlink {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--gold-text); font-weight: 700; text-decoration: underline;
  text-decoration-thickness: 2px; text-underline-offset: 4px;
}
.textlink .pfeil { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; transition: transform .2s; }
.textlink:hover .pfeil { transform: translateX(3px); }
.knopf-zeile { display: flex; flex-wrap: wrap; gap: var(--r2) var(--r3); align-items: center; margin-top: var(--r4); }

/* ---------- 09 Hero (Auftakt) ---------- */
.auftakt { padding-block: var(--sektion); position: relative; }
/* Ast-Motiv als durchgehendes Element: taucht nicht nur im Hero auf, sondern
   an mehreren Stellen die Seite hinunter (§29b) — jede Instanz liegt als
   erstes Kind VOR .wrap im Markup und damit im Stapel HINTER dem Inhalt
   ihrer eigenen Sektion (die Sektion selbst braucht dafür position:relative
   — siehe .ast-traeger). KORREKTUR (30.07.): mix-blend-mode:screen war der
   falsche Blend-Modus — screen macht ALLES heller, gegen den hellen --bg
   wuschen damit auch die hellen Blätter zu Weiß aus (per Pixel-Simulation
   nachgewiesen und ersetzt). Jetzt: das Foto maskiert sich selbst über seine
   eigene Luminanz — dunkle Pixel werden transparent, helle Pixel (die
   Blätter) bleiben in echter Originalfarbe sichtbar. Keine Freistellung/
   Bildbearbeitung nötig, per Pixel-Simulation gegengeprüft. */
/* .wrap ist selbst nicht positioniert (statisch) — ohne eigenes
   position:relative würde es TROTZ späterer DOM-Position immer HINTER dem
   positionierten .ast-foto einsortiert (nicht-positionierte Inhalte malen
   sich per Spezifikation vor positionierten, unabhängig von der Reihenfolge
   im Markup). Nur für Sektionen mit Ast-Foto gesetzt, nicht global auf .wrap. */
.ast-traeger { position: relative; }
.ast-traeger > .wrap { position: relative; }
.ast-foto {
  position: absolute; z-index: 0; pointer-events: none;
  -webkit-mask-image: url("/images/ast-blaetter.jpg");
  mask-image: url("/images/ast-blaetter.jpg");
  -webkit-mask-mode: luminance;
  mask-mode: luminance;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.ast-foto img { width: 100%; height: auto; display: block; }
/* Hero-Instanz: lädt sofort mit der Seite, kein Scroll-Trigger nötig. */
.ast-foto--hero {
  top: -30px; left: -4%; width: 108%;
  opacity: 0; transform-origin: top center;
  animation: ast-eintritt 1.3s cubic-bezier(.16, 1, .3, 1) .15s both;
}
@keyframes ast-eintritt { from { opacity: 0; } to { opacity: 1; } }
/* Weitere Instanzen: wachsen erst beim Herunterscrollen ein (§29b/haake.js)
   und bekommen zusätzlich einen sanften Parallax-Versatz (JS, transform
   translateY on top of der scale-Eintrittsanimation — siehe dort, warum
   beides denselben transform ohne Konflikt teilen kann). */
.ast-foto--scroll {
  opacity: 0; transform: scale(.94);
  transition: opacity 1.1s cubic-bezier(.16, 1, .3, 1), transform 1.1s cubic-bezier(.16, 1, .3, 1);
}
.ast-foto--scroll.ist-sichtbar { opacity: 1; transform: scale(1); }
.ast-foto--leistungen { top: -15px; right: -4%; width: 60%; transform: scaleX(-1) scale(.94); }
.ast-foto--leistungen.ist-sichtbar { transform: scaleX(-1) scale(1); }
.ast-foto--ueberuns { top: -10px; left: -3%; width: 46%; }
.ast-foto--referenzen { top: -15px; right: -3%; width: 56%; transform: scaleX(-1) scale(.94); }
.ast-foto--referenzen.ist-sichtbar { transform: scaleX(-1) scale(1); }
@keyframes ast-eintritt { from { opacity: 0; } to { opacity: 1; } }
/* Wiegen im Wind + Mausnähe: haake.js setzt transform inline (rAF-Schleife,
   nur bei echtem Zeiger + ohne reduzierte Bewegung) — keine CSS-transition
   hier, die stetige rAF-Werte nur unnötig verzögern würde. */
.auftakt-raster { display: grid; gap: var(--r5); align-items: center; position: relative; }
.auftakt-text h1 { margin-top: 0; }
.auftakt-text .einleitung { margin-top: var(--r3); }
@media (min-width: 1100px) {
  .auftakt-raster { grid-template-columns: 1.05fr 1fr; gap: var(--r6); }
}
/* Signature-Moment #1: gekappter Eck-Anschnitt */
.auftakt-bild {
  position: relative;
  clip-path: polygon(56px 0, 100% 0, 100% 100%, 0 100%, 0 56px);
}
.auftakt-bild img { width: 100%; height: auto; }
.bild-plakette {
  position: absolute; left: var(--r2); bottom: var(--r2); z-index: 1;
  display: flex; align-items: center; gap: 12px;
  background: var(--flaeche); border-radius: var(--radius-s);
  box-shadow: var(--schatten-hoch); padding: 12px 18px 12px 12px;
  max-width: calc(100% - 32px);
}
.bild-plakette strong { display: block; color: var(--gold-text); font-size: var(--fs-s); }
.bild-plakette span { display: block; color: var(--text-hell); font-size: var(--fs-xs); }

/* ---------- 10 Merkmale-Trio ---------- */
.merkmale { display: flex; flex-wrap: wrap; gap: var(--r3) var(--r4); margin-top: var(--r5); }
.merkmal { display: flex; align-items: center; gap: 12px; font-size: var(--fs-s); font-weight: 600; color: var(--text); }
.kreis {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none;
  background: var(--wald-blass); border-radius: 50%;
}
.kreis svg { width: 22px; height: 22px; stroke: var(--gold-text); fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- 11 Abschnitte & Sektionsköpfe ---------- */
/* Genau zwei Rhythmus-Stufen — keine Nachbarschafts-Sonderfälle. */
.abschnitt { padding-block: var(--sektion); }
.abschnitt--kompakt { padding-block: var(--sektion-kompakt); }
/* Im Kompakt-Rhythmus keinen vollen Kopf-Abstand aufreißen —
   Folge-Elemente (z. B. .knopf-zeile) bringen ihre eigene margin-top mit. */
.abschnitt--kompakt .abschnitt-kopf { margin-bottom: 0; }
.abschnitt--weiss { background: var(--flaeche); }
.abschnitt--sand { background: var(--sand); }
.abschnitt-kopf { max-width: 46rem; margin-bottom: var(--r5); }
.abschnitt-kopf .nebentext { color: var(--text-hell); margin-top: var(--r2); }
.zierlinie { width: 56px; height: 4px; border-radius: 2px; background: var(--gold); margin-bottom: var(--r2); }
.zierlinie--ziegel { background: var(--ziegel); }

/* ---------- 12 Leistungskarten ---------- */
/* auto-fit + 280px Mindestbreite: max. 3 Spalten im Wrap —
   bei 5 Karten ergibt sich 3+2, nie 5 Stummel in einer Reihe. */
.karten { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--r3); }
.karte {
  display: flex; flex-direction: column;
  background: var(--flaeche); border: 1px solid var(--linie);
  border-radius: var(--radius); padding: var(--r4) var(--r3);
  text-decoration: none; color: var(--text);
  box-shadow: var(--schatten);
  transition: transform .25s, box-shadow .25s, border-color .25s;
}
.karte-kopf { display: flex; align-items: center; gap: 12px; }
.karte-kopf svg { width: 32px; height: 32px; flex: none; stroke: var(--gold); fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; transition: transform .3s cubic-bezier(.34, 1.56, .64, 1); }
.karte h3 { font-size: var(--fs-2); }
.karte .strich { width: 34px; height: 3px; background: var(--gold); border-radius: 2px; margin-block: var(--r2); transition: width .3s ease; }
.karte p { color: var(--text-hell); font-size: var(--fs-s); flex: 1; }
.karte .mehr { display: inline-flex; align-items: center; gap: 8px; margin-top: var(--r2); color: var(--gold-text); font-weight: 700; font-size: var(--fs-s); }
.karte .mehr .pfeil { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; transition: transform .2s; }
/* Signature-Moment #2: Karten-Hover-Lift (nur echte Zeiger) */
@media (hover: hover) {
  .karte:hover { transform: translateY(-3px); border-color: var(--gold); box-shadow: var(--schatten-hoch); }
  .karte:hover .karte-kopf svg { transform: scale(1.12) rotate(-4deg); }
  .karte:hover .strich { width: 56px; }
  .karte:hover .mehr .pfeil { transform: translateX(3px); }
  .karte:active { transform: translateY(-1px); }
}

/* ---------- 13 Duo & Merkkasten ---------- */
.duo { display: grid; gap: var(--r5); align-items: start; }
@media (min-width: 1100px) { .duo { grid-template-columns: 1.4fr 1fr; gap: var(--r7); } }
.team-bild { margin: 0 0 var(--r4); }
.duo h2 { margin-bottom: var(--r3); }
.duo p { margin-bottom: var(--r2); }
.punkte { margin-block: var(--r3); display: grid; gap: 10px; }
.punkte li { position: relative; padding-left: 30px; }
.punkte li::before {
  content: ""; position: absolute; left: 0; top: .35em;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--wald-blass);
}
/* Häkchen als Mask statt Data-URI-Bild: folgt so dem --gold-text-Token. */
.punkte li::after {
  content: ""; position: absolute; left: 0; top: .35em;
  width: 18px; height: 18px;
  background: var(--gold-text);
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M6 12.5l4 4 8-9"/></svg>') center / 11px no-repeat;
  mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M6 12.5l4 4 8-9"/></svg>') center / 11px no-repeat;
}
.merkkasten {
  background: var(--flaeche); border: 1px solid var(--wald-linie);
  border-radius: var(--radius); padding: var(--r4);
  box-shadow: var(--schatten); position: sticky; top: 140px;
}
.merkkasten .gross { font-size: var(--fs-1); font-weight: 600; color: var(--titel); margin-bottom: var(--r3); }

/* ---------- 14 Schritte (Festpreis-Ablauf) ---------- */
/* Mobil 1 Spalte, Tablet 2×2 (statt 3+1-Waise), Desktop wieder auto-fit
   (4 Schritte → 4 Spalten, 3 Schritte → 3 Spalten). */
.schritte { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: var(--r3); counter-reset: schritt; }
@media (min-width: 1100px) { .schritte { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); } }
.schritt {
  counter-increment: schritt;
  background: var(--flaeche); border: 1px solid var(--linie);
  border-radius: var(--radius); padding: var(--r4) var(--r3);
  box-shadow: var(--schatten);
}
.schritt::before {
  content: counter(schritt, decimal-leading-zero);
  display: block; font-size: var(--fs-3); font-weight: 800;
  color: var(--ziegel); /* Ziegel nur ≥24px bold — hier erlaubt */
  margin-bottom: var(--r1);
  transform-origin: left center;
}
.schritt h3 { font-size: var(--fs-2); margin-bottom: var(--r1); }
.schritt p { color: var(--text-hell); font-size: var(--fs-s); }
/* Nummer poppt kurz nach dem Karten-Eintritt nach — verstärkt das
   Sequenz-Gefühl ("Schritt für Schritt"), ohne eine geometrisch fragile
   Verbindungslinie über ein reflowendes Grid zu ziehen. */
.schritt[data-reveal]::before {
  transform: scale(.4);
  transition: transform .5s cubic-bezier(.34, 1.56, .64, 1) .15s;
}
.schritt[data-reveal].ist-sichtbar::before { transform: scale(1); }

/* ---------- 15 Referenzen ---------- */
.referenz { display: grid; gap: var(--r4); align-items: center; margin-top: var(--r5); }
/* Zwischen zwei Objekten mehr Abstand als innerhalb eines Objekts (Gestaltgesetz)
   plus feine Trennlinie — sonst laufen die Fallstudien ineinander. */
.referenz + .referenz { margin-top: var(--r7); padding-top: var(--r7); border-top: 1px solid var(--wald-linie); }
@media (min-width: 1100px) { .referenz { grid-template-columns: 1fr 1.1fr; gap: var(--r6); } }
.referenz h3 { margin-bottom: var(--r2); }
.referenz-bild img { border-radius: var(--radius); box-shadow: var(--schatten-hoch); width: 100%; height: auto; object-fit: cover; aspect-ratio: 4 / 3; }
.referenz-bilder { display: grid; gap: var(--r2); grid-template-columns: 1fr 1fr; }
.referenz-bilder img { border-radius: var(--radius); box-shadow: var(--schatten); width: 100%; height: auto; object-fit: cover; aspect-ratio: 4 / 3; }
.referenz-bilder .breit { grid-column: 1 / -1; }
/* Vorhang-Effekt: eigenes Reveal-Attribut (data-reveal-bild statt data-reveal),
   damit das Bild nicht zusätzlich über das generische Opacity/Translate der
   Eltern-.referenz doppelt einblendet — siehe haake.js. Bei mehreren Bildern
   zieht sich jedes einzeln auf, leicht versetzt. */
[data-reveal-bild] img {
  clip-path: inset(0 100% 0 0 round var(--radius));
  transform: scale(1.06);
  transition: clip-path .8s cubic-bezier(.16, 1, .3, 1), transform .9s cubic-bezier(.16, 1, .3, 1);
}
/* Direktkind-Kombinator, damit nicht auch das erste (in <picture> genestete)
   Bild fälschlich als "nth-child(2) seines Elternteils" mitgezählt wird. */
[data-reveal-bild] > img:nth-child(2) { transition-delay: .12s; }
[data-reveal-bild] > img:nth-child(3) { transition-delay: .24s; }
[data-reveal-bild].ist-sichtbar img { clip-path: inset(0 0 0 0 round var(--radius)); transform: scale(1); }
.zahlen { display: flex; flex-wrap: wrap; gap: var(--r3) var(--r5); margin-top: var(--r4); }
/* Kennzahlen in --gold-text statt --gold: die helle Akzentfarbe erreicht auf
   --sand nur ~3,1:1 (Großtext-Grenzwert, keine Sicherheitsmarge) — --gold-text
   bringt 5,25:1 auf --sand / 5,07:1 auf --bg. --gold bleibt für Deko (Icons,
   Zierlinie, Strich), die als dekorativ von 1.4.11 ausgenommen sind. */
.zahl strong { display: block; font-size: var(--fs-3); font-weight: 800; color: var(--gold-text); line-height: var(--lh-eng); font-variant-numeric: tabular-nums; }
.zahl--ziegel strong { color: var(--ziegel); }
.zahl span { display: block; font-size: var(--fs-s); color: var(--text-hell); margin-top: var(--r0); }

/* ---------- 16 Notdienst- & CTA-Band ---------- */
.band { background: var(--wald-tief); }
.band .wrap {
  display: grid; gap: var(--r4); align-items: center;
  padding-block: var(--sektion-kompakt);
}
@media (min-width: 1100px) { .band .wrap { grid-template-columns: 1fr auto; } }
.band .ueberzeile { color: var(--gold-hell); }
.band h2 { color: #FFFFFF; }
.band p { color: var(--band-text); margin-top: var(--r2); }
/* Große Tel-Schaltfläche im Notdienst-Band: heller Knopf auf Wald-Dunkel.
   Jetzt Token statt Festwerte (ein Theme, kein Kollisionsrisiko mehr). */
.band .knopf--band {
  background: var(--flaeche); color: var(--wald-tief);
  font-size: var(--fs-2); font-weight: 800; padding: 18px 30px;
}
.band .knopf--band:hover { background: var(--wald-blass); color: var(--wald-tief); }

/* ---------- 17 Kontakt-Karten ---------- */
.kontakt-raster { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--r3); }
.kontakt-feld {
  background: var(--flaeche); border: 1px solid var(--linie);
  border-radius: var(--radius); padding: var(--r4) var(--r3);
  box-shadow: var(--schatten);
}
.kontakt-feld .kreis { margin-bottom: var(--r2); }
.kontakt-feld h3 { font-size: var(--fs-1); margin-bottom: var(--r0); }
.kontakt-feld a { display: inline-block; color: var(--gold-text); font-weight: 700; padding-block: 2px; }
.kontakt-feld .wert { color: var(--text); font-weight: 600; }
.kontakt-feld small { display: block; color: var(--text-hell); font-size: var(--fs-xs); margin-top: var(--r0); }

/* ---------- 18 Formular ---------- */
.formular { display: grid; gap: var(--r3); max-width: 46rem; }
.feld { display: grid; gap: 6px; }
.feld-zeile { display: grid; gap: var(--r3); }
@media (min-width: 1100px) { .feld-zeile { grid-template-columns: 1fr 1fr; } }
.feld label { font-weight: 600; color: var(--titel); font-size: var(--fs-s); }
.feld input, .feld select, .feld textarea {
  font: inherit; color: var(--text);
  background: var(--flaeche); border: 1px solid var(--feld-rahmen);
  border-radius: var(--radius-s); padding: 12px 14px; width: 100%;
}
.feld input:focus-visible, .feld select:focus-visible, .feld textarea:focus-visible {
  outline: 3px solid var(--fokus); outline-offset: 1px; border-color: var(--gold-text);
}
/* Invalid erst nach Nutzer-Interaktion (:user-invalid), nicht schon beim Laden.
   Zweite Rahmenlinie via Schatten statt border-width — kein Layout-Sprung. */
.feld input:user-invalid, .feld textarea:user-invalid {
  border-color: var(--fehler); box-shadow: inset 0 0 0 1px var(--fehler);
}
.feld .hinweis { font-size: var(--fs-xs); color: var(--text-hell); }
/* Formular-Status (Ziel der Pages-Function-Redirects /kontakt#gesendet
   bzw. /kontakt#formular-fehler) — reines CSS via :target, kein JS. */
.formular-status { display: none; border: 1px solid var(--wald-linie); border-radius: var(--radius-s); background: var(--wald-blass); padding: var(--r2) var(--r3); margin-bottom: var(--r3); }
.formular-status:target { display: block; }
.formular-status--fehler { background: var(--flaeche); border-color: var(--fehler); }
/* Honeypot: für Menschen unsichtbar, für Bots ein normales Feld */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---------- 19 Footer ---------- */
.site-footer { background: var(--wald-tief); color: var(--fuss-text); }
.site-footer .wrap { padding-block: var(--r6) var(--r4); }
.footer-raster { display: grid; gap: var(--r5); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.footer-marke { display: flex; align-items: center; gap: 10px; color: #FFFFFF; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; margin-bottom: var(--r2); }
.footer-marke .signet { width: 36px; height: 36px; }
.site-footer p { font-size: var(--fs-s); max-width: 30rem; }
.fusstitel { color: #FFFFFF; font-weight: 700; font-size: var(--fs-0); margin-bottom: var(--r2); }
.site-footer ul { display: grid; gap: 2px; }
.site-footer ul a {
  display: inline-block; color: var(--fuss-text); text-decoration: none;
  font-size: var(--fs-s); padding-block: 5px; /* Zielhöhe ≥ 24px */
}
.site-footer ul a:hover { color: #FFFFFF; text-decoration: underline; }
.footer-unten {
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: space-between;
  border-top: 1px solid rgba(255, 255, 255, .14);
  margin-top: var(--r5); padding-top: var(--r3);
  color: var(--fuss-meta); font-size: var(--fs-s);
}
.footer-unten a { color: var(--fuss-meta); }
.footer-unten a:hover { color: #FFFFFF; }

/* ---------- 20 Mobiler Anrufbalken ---------- */
.anrufbalken {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex;
  background: var(--gold-cta);
  box-shadow: 0 -2px 12px rgba(0, 0, 0, .18);
  padding-bottom: env(safe-area-inset-bottom);
}
.anrufbalken a {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  color: var(--cta-schrift); text-decoration: none; font-weight: 700; font-size: var(--fs-s);
  padding: 14px 10px;
}
.anrufbalken a + a { border-left: 1px solid rgba(255, 255, 255, .25); }
.anrufbalken svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
body { padding-bottom: 52px; } /* Platz für den Balken */
@media (min-width: 1100px) {
  .anrufbalken { display: none; }
  body { padding-bottom: 0; }
}

/* ---------- 21 Seitenkopf & Brotkrumen (Unterseiten) ---------- */
.brotkrumen { padding-block: var(--sektion-kompakt) 0; font-size: var(--fs-xs); }
.brotkrumen ol { display: flex; flex-wrap: wrap; gap: var(--r1); }
.brotkrumen li { display: inline-flex; align-items: center; gap: var(--r1); color: var(--text-hell); }
.brotkrumen li + li::before { content: "/"; color: var(--text-hell); }
.brotkrumen a { color: var(--gold-text); }
.brotkrumen [aria-current="page"] { color: var(--text-hell); }
.seiten-kopf { padding-block: var(--r4) var(--sektion-kompakt); }
.seiten-kopf .einleitung { margin-top: var(--r3); max-width: 46rem; }
.rechtstext { max-width: 62ch; }
.rechtstext h2 { font-size: var(--fs-3); margin-top: var(--r5); margin-bottom: var(--r2); }
.rechtstext h3 { font-size: var(--fs-1); margin-top: var(--r3); margin-bottom: var(--r1); }
.rechtstext p, .rechtstext ul { margin-bottom: var(--r2); }

/* ---------- 21b FAQ (Preise) — funktioniert ohne JS via <details> ---------- */
.faq { display: grid; gap: var(--r2); max-width: 46rem; }
.faq details {
  background: var(--flaeche); border: 1px solid var(--linie);
  border-radius: var(--radius); box-shadow: var(--schatten);
}
.faq details[open] { border-color: var(--wald-linie); }
.faq summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--r2);
  padding: var(--r3); font-weight: 700; color: var(--titel);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; width: 11px; height: 11px; margin-right: var(--r0);
  border-right: 2px solid var(--gold-text); border-bottom: 2px solid var(--gold-text);
  transform: rotate(45deg) translateY(-2px); transition: transform .2s;
}
.faq details[open] summary::after { transform: rotate(-135deg) translateY(-2px); }
.faq summary:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; border-radius: var(--radius); }
.faq .faq-antwort { padding: 0 var(--r3) var(--r3); }
.faq .faq-antwort p + p { margin-top: var(--r2); }

/* ---------- 22 Header-Scroll-Zustand ---------- */
/* .ist-gescrollt setzt haake.js beim Scrollen (rAF-gedrosselt, throttled).
   Nur Schatten, keine Höhenänderung — siehe Begründung in §06. */
.site-header.ist-gescrollt { box-shadow: var(--schatten); }

/* ---------- 23 Signet-Zeichnung ---------- */
/* Nur der Header-Signet zeichnet sich beim Laden einmal nach — der
   Footer-Signet bleibt bewusst statisch (kein Effekt unterhalb der Falz,
   der beim tatsächlichen Hinscrollen längst vorbei wäre). Das Nachziehen
   selbst setzt haake.js über path.getTotalLength() (§23 dort) — verlässlich
   über alle Browser hinweg, ohne Grauzone zwischen SVG-Attribut pathLength
   und CSS-Property-Serialisierung. Ohne JS/bei reduzierter Bewegung bleibt
   der Strich einfach durchgezogen sichtbar. */
.site-header .signet .blatt-1,
.site-header .signet .blatt-2 {
  transform-origin: 24px 37px;
  animation: signet-blatt .5s ease-out .75s both;
}
@keyframes signet-blatt { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: scale(1); } }

/* ---------- 24 Hero-Choreografie ---------- */
/* Eintritt: Text-Kinder gestaffelt, Bild nur per Opacity (nicht Transform —
   das Neigen zur Maus unten braucht die transform-Eigenschaft frei/ungeklaut). */
@keyframes hero-eintritt { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }
@keyframes hero-bild-eintritt { from { opacity: 0; } to { opacity: 1; } }
.auftakt-text > * { opacity: 0; animation: hero-eintritt .7s cubic-bezier(.16, 1, .3, 1) both; }
.auftakt-text > .ueberzeile { animation-delay: .05s; }
.auftakt-text > h1 { animation-delay: .16s; }
.auftakt-text > .einleitung { animation-delay: .27s; }
.auftakt-text > .knopf-zeile { animation-delay: .38s; }
.auftakt-text > .merkmale { animation-delay: .49s; }
.auftakt-bild {
  animation: hero-bild-eintritt .9s ease-out .1s both;
  transition: transform .4s cubic-bezier(.16, 1, .3, 1);
}
/* Neigung zur Maus: haake.js setzt transform inline, nur bei echtem
   Zeiger + ohne reduzierte Bewegung (siehe JS). Ruht die Maus, federt
   die obige transition sanft auf 0 zurück. */

/* ---------- 25 Nav-Hover & Mobilmenü-Eintritt ---------- */
@media (min-width: 1100px) {
  .haupt-nav a:not([aria-current="page"])::after {
    content: ""; position: absolute; left: 13px; right: 13px; bottom: 4px;
    height: 2px; background: var(--gold-text); border-radius: 1px;
    transform: scaleX(0); transform-origin: left; transition: transform .25s ease;
  }
  .haupt-nav a:not([aria-current="page"]):hover::after { transform: scaleX(1); }
}
@keyframes menu-eintritt { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: translateX(0); } }
.haupt-nav.offen li { animation: menu-eintritt .35s ease-out both; }
.haupt-nav.offen li:nth-child(1) { animation-delay: .03s; }
.haupt-nav.offen li:nth-child(2) { animation-delay: .08s; }
.haupt-nav.offen li:nth-child(3) { animation-delay: .13s; }
.haupt-nav.offen li:nth-child(4) { animation-delay: .18s; }
.haupt-nav.offen li:nth-child(5) { animation-delay: .23s; }
.haupt-nav.offen li:nth-child(6) { animation-delay: .28s; }

/* ---------- 26 Knopf-Glanz ---------- */
/* Nur auf farbigen Flächen (Grundknopf): Sekundärknopf und Band-Knopf
   haben eine helle/weiße Fläche — ein weißer Glanzstreif wäre dort
   unsichtbar (Weiß auf Weiß). Deshalb explizit ausgeschlossen. */
.knopf:not(.knopf--sekundaer):not(.knopf--band) { position: relative; overflow: hidden; }
.knopf:not(.knopf--sekundaer):not(.knopf--band)::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, .4) 50%, transparent 65%);
  transform: translateX(-140%);
  transition: transform .65s ease;
}
.knopf:not(.knopf--sekundaer):not(.knopf--band):hover::before { transform: translateX(140%); }

/* ---------- 27 Scroll-Reveal & Zahlen-Zählanimation ---------- */
/* [data-reveal] wird ausschließlich von haake.js zur Laufzeit gesetzt —
   ohne JS existiert das Attribut nie, die Regel greift dann nie, Inhalt
   bleibt sofort sichtbar (progressive enhancement, kein <noscript> nötig). */
[data-reveal] {
  opacity: 0; transform: translateY(22px);
  transition: opacity .7s cubic-bezier(.16, 1, .3, 1), transform .7s cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--reveal-verzoegerung, 0s);
}
[data-reveal].ist-sichtbar { opacity: 1; transform: translateY(0); }

/* ---------- 28 Lesefortschrittsbalken ---------- */
/* Element wird von haake.js erzeugt und an body angehängt — kein Markup
   in den 12 Seiten nötig. scaleX statt width: kein Layout-Reflow. */
.scroll-fortschritt {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 70;
  background: transparent; pointer-events: none;
}
.scroll-fortschritt span {
  display: block; height: 100%; width: 100%; transform-origin: left; transform: scaleX(0);
  background: linear-gradient(90deg, var(--gold-text), var(--gold));
}

/* ---------- 29 Seitenübergänge ---------- */
/* Native View-Transitions-API: der Browser blendet beim Klick auf einen
   internen Link zwischen alter und neuer Seite über, statt hart zu schneiden.
   Reines Progressive Enhancement — Browser ohne Unterstützung navigieren
   ganz normal, kein Fallback nötig, keine Markup-Änderung. Nur Dauer/Kurve
   werden an die Seite angepasst; der UA-Standard-Crossfade (Opacity +
   plus-lighter-Blend) bleibt unangetastet, damit keine Geisterbilder durch
   zusätzliche Transform-Overrides entstehen. */
@media not (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: auto;
  }
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: .4s;
    animation-timing-function: cubic-bezier(.16, 1, .3, 1);
  }
}

/* ---------- 30 Bewegung reduzieren ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms; animation-iteration-count: 1;
    transition-duration: .01ms;
  }
}
