/* =====================================================
   website-relaunch-pro: Basis-CSS
   In den Projektordner kopieren als assets/css/style.css.
   WICHTIG: <html lang="de" class="no-js"> setzen; main.js
   entfernt die Klasse, so bleibt alles ohne JS sichtbar.

   STRUKTUR ist hier fertig. TOKENS sind es NICHT.
   ===================================================== */

/* =====================================================
   TOKEN-BLOCK — KOMPLETT ERSETZEN, NICHT ÜBERNEHMEN

   Die Werte unten sind BEISPIELWERTE, damit die Datei
   allein lauffähig ist. Sie sind KEINE Vorlage.

   Der Agent setzt in Phase 3/4 JEDEN dieser Werte selbst,
   abgeleitet aus Marke, Branche und der in DESIGN.md
   gewählten Design-Richtung.

   Die QA prüft als BLOCKER, ob --fs-hero, --fs-h2,
   --section, --gutter, --radius und --ease sich von den
   Werten unten unterscheiden. Identische clamp-Werte über
   mehrere Projekte hinweg sind der Hauptgrund dafür, dass
   alle gebauten Websites gleich aussehen.

   Pflicht laut design-system.md:
   - mindestens FÜNF Untergrund-Abstufungen
   - --font-head ist einer der vier erlaubten Sans-Stapel,
     NIEMALS eine Serifenschrift (R2)
   - --nav-h stimmt mit der echten Navigationshöhe überein,
     weil die Hero-Höhe darauf rechnet (R3)
   ===================================================== */

:root {
  /* FARBEN: fünf Untergrund-Stufen, nicht eine */
  --bg: #0b0c0e;
  --bg-2: #101216;
  --bg-3: #16181d;
  --surface: #141619;
  --surface-2: #1d2024;
  --text: #f4f5f7;
  --muted: #9aa1ab;
  --dim: #6b7280;
  --brand: #e0b352;
  --brand-ink: #101010;
  --brand-soft: rgba(224, 179, 82, .12);
  --brand-line: rgba(224, 179, 82, .38);
  --rare: #7aa2c2;                       /* Zweitakzent: maximal 2x auf der Seite */
  --line: rgba(255, 255, 255, .09);
  --line-2: rgba(255, 255, 255, .16);

  /* TYPO — Stapel und Skala projektspezifisch setzen */
  --font-head: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --fs-hero: clamp(2.6rem, 6.5vw, 4.8rem);
  --fs-h2: clamp(1.9rem, 3.6vw, 2.8rem);
  --fs-h3: clamp(1.2rem, 1.8vw, 1.45rem);
  --fs-body: clamp(1rem, 1.1vw, 1.125rem);
  --fs-label: .8rem;

  /* RHYTHMUS */
  --section: clamp(4.5rem, 10vw, 8rem);
  --container: 1200px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --radius: 16px;
  --radius-sm: 10px;
  --shadow: 0 20px 60px rgba(0, 0, 0, .35);
  --shadow-lg: 0 34px 84px rgba(0, 0, 0, .5);
  --ease: cubic-bezier(.2, .7, .2, 1);

  /* STAPEL-ORDNUNG (z-index): verbindliche Skala.
     EISERNE REGEL: Dekoration bekommt NIE einen hoeheren Wert als Inhalt.
     Keine rohen z-index-Zahlen im Projekt-CSS, immer diese Tokens.
     Der Fehler vom 28.07.2026 (Scroll-Kreis z-index 8 ueber Text z-index 7)
     ist mit dieser Skala nicht mehr baubar. */
  --z-media: 0;      /* Hero-Bild, Hintergrundmedium */
  --z-overlay: 1;    /* Vignette, Farbverlauf ueber dem Medium */
  --z-deco: 2;       /* Scroll-Pfeil, Ornamente, Muster */
  --z-content: 7;    /* JEDER lesbare Text und jeder Button */
  --z-nav: 100;      /* fixierte Navigation */
  --z-float: 90;     /* WhatsApp-Button */
  --z-modal: 300;    /* Zwei-Klick-Overlays, Dialoge */

  /* FARBFLÄCHEN-GESETZ (Fehler Nr. 4 vom 29.07.2026: grauer Untertext auf
     Markenblau). Auf Akzent-/Markenflächen existieren GENAU ZWEI Textfarben:
     --on-brand für Überschriften/Buttons, --on-brand-mute für den Untertext.
     --muted, --ink-mute, --ink-dim sind auf farbigen Flächen VERBOTEN, sie
     sind auf den neutralen Untergrund gerechnet und werden auf Farbe unlesbar.
     Projektspezifisch setzen (bei dunkler Markenfarbe i.d.R. Weiß-Töne): */
  --on-brand: #ffffff;
  --on-brand-mute: rgba(255, 255, 255, .85);

  /* Von main.js gemessen, niemals von Hand setzen:
     --nav-h  echte Hoehe der Navigation (unterscheidet sich mobil!)
     --sbw    Breite der Scrollleiste (fuer Vollbreite-Sektionen) */
  --sbw: 0px;

  /* NAVIGATIONSHÖHE — muss zur echten Leiste passen (R3) */
  --nav-h: 62px;
}
@media (min-width: 760px) { :root { --nav-h: 70px; } }

/* ---------- Scroll-Fortschrittsbalken (PFLICHT auf jeder Seite) ----------
   main.js setzt --p. 2px, .08s linear: ohne Übergang ruckelt er,
   ab 0.1s hinkt er nach. */
.progress { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: calc(var(--z-nav) + 1); pointer-events: none; }
.progress span {
  display: block; height: 100%; width: var(--p, 0%);
  background: linear-gradient(90deg, var(--brand), var(--brand), var(--rare) 70%, var(--brand));
  box-shadow: 0 0 12px var(--brand-line);   /* HELLES THEME: stattdessen 0 1px 4px */
  transition: width .08s linear;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; background: none; border: 0; color: inherit; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 4px; }

/* ---------- Layout ---------- */
.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section); }
.grid { display: grid; gap: 24px; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
/* .split NUR für Inhaltssektionen, NIEMALS für den Hero (R1).
   Text links plus Bild rechts im Hero ist ein QA-Blocker. */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 6vw, 5rem); align-items: center; }

/* ---------- Typo ---------- */
h1, h2, h3 { font-family: var(--font-head); line-height: 1.1; letter-spacing: -.02em; text-wrap: balance; }
h1 { font-size: var(--fs-hero); font-weight: 800; }
h2 { font-size: var(--fs-h2); font-weight: 800; }
h3 { font-size: var(--fs-h3); font-weight: 700; }
p { max-width: 65ch; }
.muted { color: var(--muted); }
.kicker {
  display: inline-block; font-size: var(--fs-label); font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--brand); margin-bottom: 14px;
}
/* R1 ZENTRIERUNG: Sektionsköpfe sind IMMER zentriert. Kein Sonderfall. */
.section-head { text-align: center; max-width: 64ch; margin: 0 auto clamp(2rem, 5vw, 3.5rem); }
.section-head .kicker { display: inline-block; margin-bottom: 14px; }
.section-head h2 { margin: 0; }
.section-head p { margin: 12px auto 0; max-width: 58ch; color: var(--muted); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 15px 28px; border-radius: 999px; font-weight: 700; line-height: 1;
  transition: transform .2s var(--ease), background .2s, border-color .2s, color .2s;
}
.btn:hover { transform: translateY(-2px); }
.btn-primary { background: var(--brand); color: var(--brand-ink); }
.btn-ghost { border: 1px solid var(--line); color: var(--text); }
.btn-ghost:hover { border-color: var(--brand); color: var(--brand); }

/* ---------- POLISH-FUNDAMENT: Press-Feedback ---------- ═══ GESPERRT ═══
   NICHT ENTFERNEN (Eiserne Regel 12, QA Pass 4). Feedback kommt beim
   RUNTERDRUECKEN, nicht erst beim Loslassen — der Unterschied zwischen
   "reagiert sofort" und "fuehlt sich tot an". Kurze .1s, damit es knackt.
   Auf Maus-Geraeten mischt main.js den Druck in den Magnet-Transform;
   diese Regeln greifen auf Touch und ueberall ohne JS.
   Neue eigene Komponenten bekommen ihre EIGENE :active-Regel dazu. */
.btn:active { transform: translateY(0) scale(.97); transition-duration: .1s; }
.tile:active { transform: perspective(900px) scale(.98); transition-duration: .1s; }
.card:active { transform: translateY(-1px) scale(.99); transition-duration: .1s; }
.nav-links a:active, .footer a:active, .faq-q:active { color: var(--brand); }
.burger:active span { background: var(--brand); }
.theme-toggle:active, .wa-float:active, .scroll-down:active { transform: scale(.94); transition-duration: .1s; }

/* ---------- Navigation ---------- */
.nav {
  position: fixed; inset-inline: 0; top: 0; z-index: var(--z-nav);
  transition: background .3s, border-color .3s;
  border-bottom: 1px solid transparent;
}
.nav.scrolled {
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}
/* ---------- BURGER-BUGFIX 13.08.2026 ---------- ═══ GESPERRT ═══
   Offenes Mobil-Menü: backdrop-filter der Leiste MUSS aus sein.
   Ein backdrop-filter (oder filter/transform) auf .nav macht .nav zum
   Containing Block für position:fixed-Kinder — das Vollbild-Overlay
   .nav-links saß dann in der ~70px-Leiste statt im Viewport: nach dem
   Scrollen (.scrolled aktiv) waren die oberen Menüpunkte unerreichbar
   (Kundenbug vt-marl.de, 13.08.2026). !important, damit auch spätere
   gleich-spezifische Regeln (.nav.scrolled, Projekt-CSS) das nie wieder
   einschalten. Solider Hintergrund: die Leiste verschmilzt mit dem
   Overlay darunter. Auf Desktop existiert .open nicht (Burger versteckt). */
.nav.open {
  background: var(--bg);
  backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
}
/* Das Overlay ist ein NACHFAHRE der Leiste — deren Hintergrund kann eigene
   Kinder nicht verdecken. Deshalb blendet eine Maske auf dem Overlay (im
   Mobil-Block unten) alles aus, was beim Scrollen unter die Leiste wandert. */
/* Niemals transform/filter auf .nav legen — gleicher Containing-Block-Bug. */
/* 3-Zonen-Leiste: Logo links, Links EXAKT mittig, Aktionen rechts.
   ═══ GESPERRT ═══ Dieses Grid NIEMALS im Projekt-CSS umdefinieren.
   "auto minmax(0,1fr) auto" oder Flex mit space-between schiebt die
   Linkgruppe aus der Mitte — Fehler Nr. 2 vom 29.07.2026, wird vom
   Prüfskript als NAVMITTE/STRUKTUR gemessen. Nur 1fr auto 1fr zentriert
   die Links auf die BILDSCHIRM-Mitte, unabhängig von Logo-Breite. */
.nav-inner { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px; padding-block: 14px; }
.nav-inner > .nav-logo, .nav-inner > .logo { justify-self: start; }
.nav-inner > nav { justify-self: center; }
.nav-actions { justify-self: end; display: flex; align-items: center; gap: 12px; }
.nav-logo img { height: 40px; width: auto; }
.nav-links { display: flex; align-items: center; gap: 28px; list-style: none; }
.nav-links a { font-weight: 600; font-size: .95rem; transition: color .2s; }
.nav-links a:hover, .nav-links a.active { color: var(--brand); }
.nav-cta { padding: 11px 22px; }
.burger { display: none; flex-direction: column; gap: 5px; padding: 10px; }
.burger span { width: 24px; height: 2px; background: var(--text); transition: transform .3s var(--ease), opacity .2s; }

/* ---------- Theme-Umschalter (optional) ----------
   Standard-Theme in :root. Gegen-Theme hier als Override,
   Attribut auf <html data-theme="...">. Beispiel für helles
   Gegen-Theme, Werte projektspezifisch setzen: */
[data-theme="light"] {
  --bg: #faf9f7;
  --surface: #ffffff;
  --surface-2: #f1efeb;
  --text: #17181a;
  --muted: #5c6470;
  --line: rgba(0, 0, 0, .1);
  --shadow: 0 20px 60px rgba(0, 0, 0, .1);
}
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--line);
  color: var(--text); transition: border-color .2s, color .2s;
}
.theme-toggle:hover { border-color: var(--brand); color: var(--brand); }
.theme-toggle svg { width: 18px; height: 18px; }


/* ---------- ANKER-LANDUNG (Pflicht) ---------- ═══ GESPERRT ═══
   Die Navigation ist fixiert und deckt die oberen --nav-h Pixel ab.
   Ohne die beiden Regeln landet JEDER #anker-Sprung und jeder Klick auf
   den Scroll-Pfeil so, dass die Kopfzeile der Zielsektion unter der
   Navigation verschwindet. Genau das ist der Eindruck "die Ebenen sind
   schlecht geschnitten". 18px Zugabe, damit die Sektion sichtbar atmet. */
html { scroll-padding-top: calc(var(--nav-h) + 18px); }
/* ACHTUNG (Messung 29.07.2026): scroll-padding-top und scroll-margin-top
   ADDIEREN sich im Browser. Beides zu setzen laesst jeden Sprung ~100px zu
   tief landen. Deshalb NUR scroll-padding-top — [id]{scroll-margin-top}
   bleibt 0 und wird NICHT gesetzt. */

/* ---------- HERO ---------- ═══ GESPERRT (Höhe, Anschluss, Ausbruch) ═══
   R1 + R3: IMMER zentriert, IMMER exakte Höhe. Es gibt keine
   linksbündige und keine ungefähre Variante mehr. Der Hero beginnt
   Pixel an Pixel an der Nav-Unterkante (margin-top: var(--nav-h)) —
   ein leeres Band dazwischen war Fehler Nr. 1 vom 29.07.2026 (LEERBLOCK). */
.hero {
  position: relative; overflow: hidden; isolation: isolate;
  /* Vollbreite-Ausbruch. --sbw ist die Scrollleisten-Breite, die main.js
     misst. Ohne sie ist die Sektion genau um die Scrollleiste zu breit
     und die ganze Seite scrollt seitlich (auf Windows immer sichtbar). */
  width: calc(100vw - var(--sbw));
  margin-left: calc(50% - (100vw - var(--sbw)) / 2);
  margin-right: calc(50% - (100vw - var(--sbw)) / 2);
  /* R3: genau Viewport minus Navigationshöhe. min-height statt height,
     mit voller Absicht: bei exakter Höhe plus overflow:hidden wird Hero-Text
     auf kleinen Handys ABGESCHNITTEN. Ein Hero, der im Ausnahmefall 40px
     mitwächst, ist ein Schönheitsfehler. Abgeschnittene Schrift ist ein
     verlorener Kunde. Im Normalfall greift die Höhe exakt wie vorher,
     weil das Text-Budget aus dem Design-System eingehalten wird. */
  min-height: calc(100vh - var(--nav-h));
  min-height: calc(100dvh - var(--nav-h));
  /* Die Navigation ist fixiert und liegt UEBER dem Inhalt. Ohne diesen
     Versatz beginnt das Hero unter der Leiste und der Hero-Text laeuft in
     sie hinein. Auf kleinen Handys verschwindet dadurch die halbe
     Ueberschrift. Der Versatz gehoert ins Fundament, nicht in jedes
     Projekt-CSS von Hand. */
  margin-top: var(--nav-h);
  display: flex; align-items: center; justify-content: center;
}
/* Sehr flache Fenster: 520px Mindesthöhe wuerde hier ueber den Bildschirm
   hinausragen, deshalb bewusst nur dort, wo genug Platz ist. */
@media (min-height: 560px) { .hero { min-height: max(520px, calc(100dvh - var(--nav-h))); } }
.hero .hero-content {
  position: relative; z-index: var(--z-content);
  display: flex; flex-direction: column; align-items: center; text-align: center;
  width: 100%; max-width: var(--container); margin-inline: auto;
  padding-inline: var(--gutter);
}
.hero .hero-content h1 { margin-inline: auto; max-width: 15ch; }
.hero .hero-content p.lead { margin-inline: auto; }
.hero .hero-actions { justify-content: center; align-self: center; }

/* R4 VIGNETTE: Pflicht, sobald Text über einem Bild liegt.
   Immer ZWEI Verläufe, nie einer. Variante je nach Lichtwelt. */
.hero-veil { position: absolute; inset: 0; z-index: var(--z-overlay); pointer-events: none; }
.hero-veil.dark {
  background:
    radial-gradient(ellipse at center, transparent 35%, rgba(0,0,0,.55) 78%, rgba(0,0,0,.95) 100%),
    linear-gradient(180deg, rgba(0,0,0,.55) 0%, transparent 22%, transparent 58%, rgba(0,0,0,.95) 100%);
}
/* Helle Variante: Projektfarbe für BG einsetzen (rgba des --bg-Werts). */
.hero-veil.light {
  background:
    radial-gradient(ellipse 76% 62% at 50% 48%,
      rgba(255,255,255,.94) 0%, rgba(255,255,255,.86) 34%,
      rgba(255,255,255,.52) 62%, rgba(255,255,255,0) 88%),
    linear-gradient(180deg, rgba(255,255,255,.88) 0%, transparent 18%, transparent 72%, rgba(255,255,255,.94) 100%);
}

/* Scroll-Pfeil: ersetzt Buttons im Hero. Drei Animationen mit
   UNTERSCHIEDLICHEN Laufzeiten, sonst entsteht ein Gleichtakt. */
.scroll-down {
  margin-top: 40px; align-self: center;
  width: 58px; height: 58px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-soft); border: 1.5px solid var(--brand); color: var(--brand);
  position: relative; cursor: pointer;
  transition: background .3s ease, transform .3s ease, box-shadow .3s ease, color .3s ease;
  animation: sdBounce 2.4s ease-in-out infinite;
}
.scroll-down::before {
  content: ""; position: absolute; inset: -1.5px; border-radius: 50%;
  border: 1.5px solid var(--brand); opacity: 0; pointer-events: none;
  animation: sdRing 2.4s ease-out infinite;
}
.scroll-down svg { width: 22px; height: 22px; animation: sdSlide 1.8s ease-in-out infinite; }
.scroll-down:hover {
  background: var(--brand); color: var(--brand-ink); transform: scale(1.08);
  animation-play-state: paused;
}
@keyframes sdBounce { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(8px) } }
@keyframes sdSlide  { 0%, 100% { transform: translateY(-2px); opacity: .85 } 50% { transform: translateY(3px); opacity: 1 } }
@keyframes sdRing   { 0% { opacity: .5; transform: scale(1) } 100% { opacity: 0; transform: scale(1.7) } }
/* ACHTUNG, TEURER FEHLER: Der Scroll-Pfeil steht im FLUSS (margin-top oben),
   nicht absolut am unteren Rand. Wer ihn auf
      position: absolute; bottom: 30px; z-index: 8
   umbaut, erzeugt den Fehler "Kreis liegt auf der Schrift", sobald der Hero-
   Text eine Zeile laenger wird oder das Fenster flacher ist. Genau so ist es
   am 28.07.2026 auf einer ausgelieferten Kundenseite passiert. Nicht aendern. */
.hero > .scroll-down, .hero .hero-content > .scroll-down { position: relative; z-index: var(--z-deco); }
.scroll-hint {
  position: relative; z-index: var(--z-deco);
  margin-top: 40px; align-self: center;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  min-width: 44px; min-height: 44px;
  color: var(--muted); font-size: .75rem; letter-spacing: .18em; text-transform: uppercase;
}
.scroll-hint::after {
  content: ""; width: 1px; height: 44px;
  background: linear-gradient(to bottom, var(--brand), transparent);
  animation: scrollhint 2s var(--ease) infinite;
}
@keyframes scrollhint {
  0% { transform: scaleY(0); transform-origin: top; }
  45% { transform: scaleY(1); transform-origin: top; }
  55% { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
.hero-media, .hero-media img, .hero-media video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: var(--z-media);
}
.hero-overlay {
  position: absolute; inset: 0; z-index: var(--z-overlay); pointer-events: none;
  background: linear-gradient(to top, var(--bg) 4%, color-mix(in srgb, var(--bg) 55%, transparent) 45%, color-mix(in srgb, var(--bg) 25%, transparent) 100%);
}
.hero-content { position: relative; z-index: var(--z-content); padding-block: clamp(2rem, 6vh, 4rem); }
.hero-content p.lead { font-size: clamp(1.05rem, 1.5vw, 1.3rem); color: var(--muted); margin-top: 18px; max-width: 55ch; }
/* Button-Paare: exakt gleich breit (1fr-Spalten am breitesten Kind) */
.hero-actions { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 14px; margin-top: 32px; }
@media (max-width: 560px) {
  .hero-actions { grid-auto-flow: row; width: 100%; }
}

/* ---------- Cards ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 32px; display: flex; flex-direction: column; gap: 14px;
  transition: transform .25s var(--ease), border-color .25s, background .25s;
}
.card:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--brand) 55%, var(--line)); background: var(--surface-2); }
.card .icon {
  width: 52px; height: 52px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--brand) 14%, transparent); color: var(--brand);
}
.card .icon svg { width: 26px; height: 26px; }
.card p { color: var(--muted); font-size: .98rem; }
/* R1: Karteninhalte zentriert. */
.card { text-align: center; align-items: center; }
.card .more { align-self: center; }
.card .more { margin-top: auto; font-weight: 700; color: var(--brand); display: inline-flex; gap: 8px; align-items: center; }

/* ---------- Bildkacheln mit Tempo-Kontrast ----------
   Das langsame Bild (1.6s) gegen die schnellen Details (0.25s) ist
   der wirksamste Luxus-Effekt. Gleiche Geschwindigkeiten wirken billig. */
.tile { position: relative; display: block; overflow: hidden; border-radius: calc(var(--radius) + 6px);
        min-height: 380px; border: 1px solid var(--line); background: var(--surface);
        isolation: isolate; transform-style: preserve-3d; will-change: transform;
        transform: perspective(900px) rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
        transition: transform .5s var(--ease), border-color .35s, box-shadow .35s; }
.tile:hover { border-color: var(--brand-line); box-shadow: var(--shadow-lg); }
.tile-bg { position: absolute; inset: 0; z-index: 0; background-size: cover; background-position: center;
           transform: scale(1.06); filter: saturate(.55) contrast(1.02);
           transition: transform 1.6s ease, filter .6s ease; }
.tile:hover .tile-bg { transform: scale(1.14); filter: saturate(1) contrast(1.06); }
.tile-veil { position: absolute; inset: 0; z-index: 1;
             background: linear-gradient(180deg, rgba(0,0,0,.10) 0%, rgba(0,0,0,.60) 55%, rgba(0,0,0,.95) 100%); }
/* R1: Kachelinhalt zentriert, unten sitzend. */
.tile-content { position: relative; z-index: 2; min-height: 380px; padding: 28px 26px 30px;
                display: flex; flex-direction: column; justify-content: flex-end;
                align-items: center; text-align: center; }
.tile-link { display: inline-flex; align-items: center; gap: 8px; align-self: center;
             font-weight: 700; padding-bottom: 6px; border-bottom: 1px solid transparent;
             transition: border-color .25s, color .25s, gap .25s; }
.tile:hover .tile-link { color: var(--brand); border-color: var(--brand); gap: 14px; }

/* ---------- Stats ---------- */
.stats { border-block: 1px solid var(--line); }
.stat { text-align: center; padding-block: 8px; }
.stat .num { font-size: clamp(2.2rem, 5vw, 3.6rem); font-weight: 800; letter-spacing: -.02em; color: var(--brand); }
.stat .label { color: var(--muted); font-size: .9rem; margin-top: 6px; }

/* ---------- FAQ ---------- */
.faq-item { border-bottom: 1px solid var(--line); }
.faq-q { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 16px; padding-block: 22px; font-weight: 700; text-align: left; }
.faq-q::after { content: "+"; font-size: 1.4rem; color: var(--brand); transition: transform .3s var(--ease); }
.faq-item.open .faq-q::after { transform: rotate(45deg); }
.faq-a { max-height: 0; overflow: hidden; transition: max-height .35s var(--ease); }
.faq-a p { padding-bottom: 22px; color: var(--muted); }

/* ---------- CTA-Band ----------
   Als volle Markenfläche (Clever-Formel Block 7): background auf var(--brand)
   setzen — dann greift automatisch das Farbflächen-Gesetz unten. */
.cta-band { background: var(--surface); border-block: 1px solid var(--line); text-align: center; }
.cta-band .hero-actions { justify-content: center; }

/* FARBFLÄCHEN-GESETZ, technisch erzwungen: auf einer Markenfläche werden alle
   Grau-Töne auf die On-Brand-Farben umgebogen. .band-brand an die Sektion. */
.band-brand { background: var(--brand); border-block: 0; }
.band-brand h1, .band-brand h2, .band-brand h3, .band-brand .kicker { color: var(--on-brand); }
.band-brand p, .band-brand .muted, .band-brand .lead, .band-brand li { color: var(--on-brand-mute); }
.band-brand .btn-primary { background: var(--on-brand); color: var(--brand); }
.band-brand .btn-ghost { border-color: var(--on-brand-mute); color: var(--on-brand); }
.band-brand .btn-ghost:hover { border-color: var(--on-brand); color: var(--on-brand); }

/* ---------- Kontakt ---------- */
.contact-item { display: flex; gap: 16px; align-items: flex-start; padding: 22px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.contact-item strong { display: block; margin-bottom: 4px; }
.contact-item a:hover { color: var(--brand); }

/* ---------- Zwei-Klick-Consent (Karte/Video) ---------- */
.consent-box {
  position: relative; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); min-height: 340px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; text-align: center; padding: 32px; overflow: hidden;
}
.consent-box p { color: var(--muted); font-size: .92rem; max-width: 46ch; }
.consent-box iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ---------- Footer ---------- */
.footer { border-top: 1px solid var(--line); padding-block: clamp(3rem, 6vw, 4.5rem) 2rem; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 40px; }
.footer h4 { font-size: .85rem; text-transform: uppercase; letter-spacing: .12em; color: var(--muted); margin-bottom: 16px; }
.footer ul { list-style: none; display: grid; gap: 10px; }
.footer a:hover { color: var(--brand); }
.footer-bottom { margin-top: 48px; padding-top: 24px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; color: var(--muted); font-size: .88rem; }

/* ---------- MOBIL-KOMPOSITION: Bausteine, die nur auf dem Handy erscheinen ----------
   ═══ GESPERRT ═══ (01.09.2026, Tim: "99% schauen mobil, es muss beides perfekt sein")
   .hero-cta    = GENAU EIN Primaer-Knopf im Hero (tel: oder wa.me), sitzt mobil
                  unter dem Untertext. Auf dem Desktop unsichtbar (dort bleibt
                  die Clever-Formel: kein Button, der Pfeil ist der CTA).
   .mobile-bar  = feste Kontaktleiste am unteren Rand (Daumenzone): Anrufen +
                  WhatsApp/E-Mail. Erscheint, sobald der Hero nach oben
                  weggescrollt ist (main.js setzt .on). Desktop: nie sichtbar.
   Beide Bausteine sind PFLICHT im Markup jeder Startseite (SKILL.md Phase 4)
   und werden mechanisch gemessen (gelernte Checks mobil-hero-komposition,
   mobil-cta). */
.hero-cta { display: none; }
.mobile-bar { display: none; }

/* ---------- WhatsApp-Float ---------- */
.wa-float {
  position: fixed; right: 20px; bottom: 20px; z-index: var(--z-float);
  width: 58px; height: 58px; border-radius: 50%; background: #25d366;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .3); transition: transform .2s var(--ease);
}
.wa-float:hover { transform: scale(1.07); }
.wa-float svg { width: 30px; height: 30px; fill: #fff; }

/* ---------- Rechtsseiten ---------- */
.legal { max-width: 75ch; }
.legal h1 { font-size: clamp(2rem, 4vw, 3rem); margin-bottom: 1.5rem; }
.legal h2 { font-size: 1.35rem; margin: 2.2rem 0 .8rem; }
.legal h3 { font-size: 1.1rem; margin: 1.6rem 0 .6rem; }
.legal p, .legal li { color: var(--muted); margin-bottom: .8rem; }
.legal ul { padding-left: 1.2rem; }
.legal a { color: var(--brand); }
.placeholder-block {
  border: 1px dashed var(--brand); border-radius: var(--radius-sm);
  padding: 18px; color: var(--brand); font-weight: 600; margin-block: 1rem;
}

/* ---------- Theme-Medien: Stills je Theme ----------
   Zwei <img> nebeneinander, CSS blendet je Theme genau eins ein. */
.img-light { display: none; }
[data-theme="light"] .img-dark { display: none; }
[data-theme="light"] .img-light { display: block; }

/* ---------- Reveal (JS setzt .in) ---------- */
/* Werte laut design-system.md Abschnitt 5: 28px und 0.9s.
   Kürzer wirkt hektisch, weiter wirkt träge. */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .9s var(--ease), transform .9s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- POLISH-FUNDAMENT: die zwei anderen Bedienungs-Signale ----------
   ═══ GESPERRT ═══ NICHT ENTFERNEN (Eiserne Regel 12, QA Pass 4).
   prefers-reduced-motion steht direkt darueber; diese zwei gehoeren dazu.
   Sie aendern im Normalfall NICHTS am Design, sie greifen nur, wenn der
   Besucher es in seinem System so eingestellt hat. */
@media (prefers-reduced-transparency: reduce) {
  .nav.scrolled { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  body { --muted: color-mix(in srgb, var(--text) 80%, var(--bg)); }
  .btn-ghost, .theme-toggle { border-width: 2px; border-color: currentColor; }
  .btn-primary { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--text); }
  .card, .tile, .contact-item, .consent-box { border-color: var(--line-2); }
}

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
  /* ---------- Mobil-Menü (Vollbild-Overlay) ---------- ═══ GESPERRT ═══
     BURGER-BUGFIX + REDESIGN 13.08.2026. Zwei Regeln, die bleiben MÜSSEN:
     1) KEIN justify-content:center auf .nav-links — bei vielen Menüpunkten
        schiebt Zentrieren die oberen Punkte über den Viewport-Rand hinaus,
        wo kein Scrollen sie erreicht. Stattdessen: flex-start + overflow-y
        + auto-Margins auf erstem/letztem li (zentriert, solange es passt,
        scrollt, sobald es nicht mehr passt).
     2) Der Containing-Block-Fix (.nav.open weiter oben) gehört dazu.
     Projekt-CSS darf Schriftgröße/Abstände/Farben anpassen, aber NIE
     position/justify-content/overflow dieses Blocks umdefinieren. */
  .nav-links {
    position: fixed; inset: 0; z-index: -1;
    flex-direction: column; align-items: center; justify-content: flex-start;
    gap: clamp(16px, 3.6vh, 30px);
    padding: calc(var(--nav-h, 76px) + 14px) 28px calc(26px + env(safe-area-inset-bottom, 0px));
    background: var(--bg); font-size: 1.4rem;
    overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
    /* Maske: Menüpunkte, die im Overlay unter die Leiste scrollen, lösen sich
       dort auf, statt durch Logo/Schließen-Kreuz zu scheinen (das Overlay ist
       ein Nachfahre der Leiste, deren Hintergrund kann es nicht verdecken). */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, transparent calc(var(--nav-h, 76px) - 30px), #000 calc(var(--nav-h, 76px) - 2px));
    mask-image: linear-gradient(to bottom, transparent 0, transparent calc(var(--nav-h, 76px) - 30px), #000 calc(var(--nav-h, 76px) - 2px));
    opacity: 0; pointer-events: none; visibility: hidden;
    transition: opacity .28s var(--ease), visibility 0s .28s;
  }
  .nav-links li:first-child { margin-top: auto; }
  .nav-links li:last-child { margin-bottom: auto; }
  .nav-links a { display: block; padding: 6px 18px; text-align: center; }
  /* Gestaffelte Einblendung: Punkte gleiten nacheinander hoch. */
  .nav-links li { opacity: 0; transform: translateY(14px); transition: opacity .3s var(--ease), transform .3s var(--ease); }
  .nav.open .nav-links {
    opacity: 1; pointer-events: auto; visibility: visible;
    transition: opacity .28s var(--ease);
    z-index: 0;
  }
  /* ═══ GESPERRT ═══ MENUE-X-FIX 01.09.2026 (Kundenbug tina-site, von Tim):
     Das Overlay ist ein NACHFAHRE der Leiste (.nav = eigener Stacking-Context).
     Sein z-index zaehlt darum nur gegen Logo, CTA und Burger. Der fruehere
     Wert calc(var(--z-nav) - 1) = 99 legte das Overlay UEBER Burger und Logo:
     das X war sichtbar, aber jeder Tipp traf das Overlay. Kunde kam aus dem
     Menue nicht mehr raus. Deshalb: Overlay auf 0, Leisteninhalt auf 1.
     Ein z-index auf .nav-inner reicht NICHT (das Overlay steckt darin).
     Wird vom Pruefskript gemessen (gelernter Check menue-x-klickbar). */
  .nav-inner > .nav-logo, .nav-inner > .logo, .nav-actions, .burger { position: relative; z-index: 1; }
  .nav.open .nav-links li { opacity: 1; transform: none; }
  .nav.open .nav-links li:nth-child(1) { transition-delay: .05s; }
  .nav.open .nav-links li:nth-child(2) { transition-delay: .09s; }
  .nav.open .nav-links li:nth-child(3) { transition-delay: .13s; }
  .nav.open .nav-links li:nth-child(4) { transition-delay: .17s; }
  .nav.open .nav-links li:nth-child(5) { transition-delay: .21s; }
  .nav.open .nav-links li:nth-child(6) { transition-delay: .25s; }
  .nav.open .nav-links li:nth-child(7) { transition-delay: .29s; }
  .nav.open .nav-links li:nth-child(8) { transition-delay: .33s; }
  .nav.open .nav-links li:nth-child(n+9) { transition-delay: .37s; }
  .nav.open .burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav.open .burger span:nth-child(2) { opacity: 0; }
  .nav.open .burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .burger { display: flex; }
  .nav-cta { display: none; }
  .split, .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; }

  /* =====================================================================
     MOBIL-KOMPOSITION ═══ GESPERRT ═══ (01.09.2026, Tims Mobil-Audit)
     Befund auf vier ausgelieferten Vorschauen: Querformat-Bilder wurden auf
     Hochkant gezogen, das Motiv lag GENAU unter dem zentrierten Text (nur
     noch dunkle Tapete), der 58px-Kreis-Pfeil stand mitten auf den Menschen,
     kein Anruf-Knopf im ersten Screen, naechste Ueberschrift ragte
     angeschnitten ins Bild. Ergebnis: "sieht billig aus, deshalb kauft
     keiner". Deshalb hat das Handy ab jetzt eine EIGENE Komposition, die
     nichts am Desktop aendert (alles in diesem Media-Block):

       ┌──────────────┐
       │ Navigation   │  60px, deckend
       ├──────────────┤
       │  BILD        │  44svh, echtes Motiv (object-position = --hero-focus),
       │   ~ fade ~   │  unten weich in den Seitenhintergrund aufgeloest
       ├──────────────┤
       │ Pille        │
       │ H1 (2-3 Z.)  │  zentriert, auf sauberem Untergrund, nie auf dem Motiv
       │ Untertext    │
       │ [ Anrufen ]  │  .hero-cta, 52px hoch, Daumenzone
       └──────────────┘  = exakt eine Bildschirmhoehe (svh: kein iOS-Sprung)
       ...
       [ Anrufen | WhatsApp ]  .mobile-bar, fest unten, ab dem 2. Screen

     Messbar gemacht: Hero-Hoehe = Viewport, Bild und Text ueberlappen nie,
     kein Kreis sichtbar, Nav <= 72px, CTA im ersten Screen, Leiste vorhanden.
     Projekt-CSS darf Farben/Schrift/Abstaende feinjustieren, aber NIE
     position/height/display dieser Regeln umdefinieren.
     ===================================================================== */
  :root { --section: clamp(3.75rem, 12vw, 5rem); }
  .nav-inner { padding-block: 10px; gap: 12px; }
  .nav-logo img { height: 36px; }
  h2 { font-size: clamp(1.7rem, 7.4vw, 2.3rem); }
  .section-head { margin-bottom: clamp(1.5rem, 6vw, 2.25rem); }

  /* Hero: Spalte, exakt eine Bildschirmhoehe (svh = kleinste Hoehe, keine
     Spruenge beim Ein-/Ausblenden der Browserleiste), waechst NUR, wenn der
     Inhalt wirklich mehr braucht (dann ist das Text-Budget verletzt). */
  .hero {
    min-height: calc(100vh - var(--nav-h));
    min-height: calc(100svh - var(--nav-h));
    flex-direction: column; align-items: stretch; justify-content: center;
  }
  .hero:has(.hero-media) { justify-content: flex-end; }
  /* Bild: KEIN Vollbild-Hintergrund mehr, sondern ein echtes Motiv oben.
     object-position aus --hero-focus (Projekt-CSS, aus dem Fokuspunkt des
     Bildes: Gesicht/Objekt), Standard 50% 32% = Motiv im oberen Drittel. */
  .hero-media {
    position: relative; inset: auto; z-index: var(--z-media);
    width: 100%; height: clamp(200px, 44svh, 560px); flex: 0 0 auto;
    overflow: hidden;
  }
  /* Flache Handys (iPhone SE 667px, Android 740px): Bild kleiner, damit
     Pille, H1, zwei Zeilen Untertext, Knopf und Pfeil ohne Wachsen passen. */
  @media (max-height: 760px) { .hero-media { height: clamp(180px, 33svh, 300px); } .hero-content p.lead { margin-bottom: 10px; } }
  .hero-media img, .hero-media video { object-position: var(--hero-focus, 50% 32%); }
  .hero-media::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 38%;
    z-index: var(--z-overlay); pointer-events: none;
    background: linear-gradient(to bottom, color-mix(in srgb, var(--bg) 0%, transparent) 0%, var(--bg) 100%);
  }
  /* Vignetten sind fuer Text AUF dem Bild gebaut; mobil liegt kein Text auf
     dem Bild, die Verlaeufe wuerden das Motiv nur verschlucken. */
  .hero-veil, .hero-overlay { display: none; }
  /* Text: DIREKT unter dem Bild auf dem sauberen Untergrund, zentriert (R1).
     V2 (Tim 02.09., Bauklotzheim): der Text klebte unten am Knopf, dazwischen
     ein leeres schwarzes Band. Jetzt: Pille/H1/Untertext sitzen oben am
     Bild, der Knopf und der kleine Pfeil sitzen unten, die Restluft liegt
     dazwischen (margin-top:auto auf dem Knopf). */
  .hero .hero-content {
    margin-top: 0; flex: 1 1 auto; display: flex; flex-direction: column; align-items: center;
    padding-block: clamp(.6rem, 1.6svh, 1rem) clamp(.6rem, 1.8svh, 1rem);
  }
  .hero-content p.lead { margin-bottom: 14px; }
  /* Ohne Bild (Farbflaechen-Hero): Restluft oben UND unten teilen. */
  .hero:not(:has(.hero-media)) .hero-content > :first-child { margin-top: auto; }
  .hero .hero-content h1 { font-size: clamp(2.05rem, 9vw, 2.8rem); max-width: 14ch; }
  .hero-content p.lead { font-size: clamp(1rem, 4.1vw, 1.1rem); margin-top: 12px; max-width: 36ch; }
  /* Scroll-Hinweis (Textvariante) und Vertrauenszeile: auf dem Handy weg.
     Der Kreis-Pfeil bleibt (Tim 02.09.: "will ich zurueck"), aber klein,
     direkt UEBER dem Knopf, nie mehr auf dem Motiv. */
  .scroll-hint, .hero .trust { display: none; }
  /* V3 (Tim 02.09.): Pfeil UEBER dem Knopf, der Knopf ist das Letzte im Screen.
     V4: der Pfeil sitzt MITTIG in der Luecke zwischen Untertext und Knopf
     (auto-Margins oben UND unten teilen die Restluft gleich auf). Ein Pfeil,
     der am Knopf klebt, wirkt unfertig; die aesthetischen Kleinigkeiten
     verkaufen. Gemessen: Luft oben == Luft unten (mobil-hero-komposition). */
  .scroll-down { width: 44px; height: 44px; margin-top: auto; margin-bottom: auto; order: 98; min-height: 44px; }
  .scroll-down svg { width: 18px; height: 18px; }
  /* Kachel-Links bleiben einzeilig, Pfeil klein (Befund HHS: "Mehr / erfahren"
     zweizeilig neben einem riesigen Pfeil). */
  .tile-link { white-space: nowrap; gap: 8px; }
  .tile-link svg { width: 20px; height: 20px; flex: 0 0 auto; }
  /* Pille bleibt IMMER einzeilig (gelernte Regel 31.08.): lieber gekuerzt,
     und mit Luft zur H1 (E2E-Befund 02.09.: Pille klebte an der Headline). */
  .hero .eyebrow, .hero .pill, .hero .badge { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 16px; }
  /* Der eine Knopf im ersten Screen: das Letzte im Screen, unter dem Pfeil. */
  .hero-cta {
    display: inline-flex; margin-top: 0; min-height: 52px; padding-inline: 28px;
    width: min(100%, 340px); font-size: 1.02rem; order: 99;
  }
  /* Ohne Pfeil im Markup nimmt der Knopf die Restluft selbst. */
  .hero-content:not(:has(.scroll-down)) .hero-cta { margin-top: auto; }
  /* Button-Paare im Hero gibt es mobil nicht: der eine .hero-cta reicht. */
  .hero .hero-actions { display: none; }

  /* Kontaktleiste unten (Daumenzone). WhatsApp-Float wird von ihr ersetzt. */
  .mobile-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-float);
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 10px;
    padding: 10px var(--gutter) calc(10px + env(safe-area-inset-bottom, 0px));
    background: color-mix(in srgb, var(--bg) 90%, transparent);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--line);
    transform: translateY(110%); transition: transform .35s var(--ease);
  }
  .mobile-bar.on { transform: none; }
  .mobile-bar .btn { min-height: 50px; padding-inline: 14px; width: 100%; white-space: nowrap; }
  body.bar-on { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
  .wa-float { display: none; }
}
@media (max-width: 480px) {
  .grid-4, .footer-grid { grid-template-columns: 1fr; }
  .hero-actions .btn { width: 100%; }
}
