/* ===========================================================
   IMMO LUCHIAN — Website
   Monochrom-Konzept nach Kundenvorgabe: mehrere Weiß-Töne (hell,
   sehr hell, mittel-hell — kein Grau) plus Schwarz in zwei
   Texturen (matt = flach, glänzend = mit Verlauf/Lichtkante),
   mit weichen Verläufen an den Übergängen zwischen den Flächen.
   Schrift kommt ausschließlich aus design-system/fonts.css
   (Bodoni Moda).
   =========================================================== */

:root {
  --white-bright: #ffffff;
  --white-soft: #f7f7f6;
  --white-mid: #ededeb;

  --black-matte: #0d0d0d;
  --black-glossy: #000000;

  /* Rückwärtskompatible Aliase, damit bestehende Regeln weiter funktionieren */
  --white: var(--white-bright);
  --ink: var(--black-matte);
  --gray-900: #1a1a1a;
  --gray-700: #4d4d4d;
  --gray-500: #7a7a7a;
  --gray-300: var(--white-mid);
  --gray-100: var(--white-soft);

  --maxw: 1180px;
  --pad: clamp(1.25rem, 4vw, 3rem);
}

/* Glänzende Schwarzfläche: dunkler Grundton mit diagonaler Lichtkante,
   wie glänzend lackiertes Schwarz statt eines flachen Blocks. */
.surface--glossy-black {
  background:
    linear-gradient(135deg,
      #000 0%, #000 30%,
      #232323 46%, #000 62%,
      #000 100%);
}

/* Weicher Übergang zwischen einer dunklen und einer hellen Fläche:
   automatisch an jeder Nahtstelle im Seitenverlauf, ohne harte Kante.
   Wichtig: als zusätzliche Verlaufsebene VOR dem jeweiligen Grundton
   in derselben "background"-Deklaration, damit sich die Ebenen
   überlagern statt sich gegenseitig zu überschreiben. */
.section--dark + section:not(.section--dark),
.hero + section:not(.section--dark),
.ba-hero + section:not(.section--dark),
.testimonial-hero + section:not(.section--dark) {
  background-image: linear-gradient(to bottom, #000 0%, transparent 130px);
  background-repeat: no-repeat;
}
section:not(.section--dark):not(.hero) + .section--dark {
  background:
    linear-gradient(to bottom, var(--white-bright) 0%, transparent 130px),
    linear-gradient(135deg, #000 0%, #000 30%, #242424 46%, #000 62%, #000 100%);
  background-repeat: no-repeat;
}
/* .ba-hero/.testimonial-hero sind randlose Bild-Sections — ihr
   eigener "background" liegt unter dem Vollbild-Foto und wäre daher
   unsichtbar. Der Schwarz-Streifen der Naht liegt deshalb VOR dem
   Foto, am unteren Rand der hellen Section davor (::after unten) —
   nicht mehr auf dem Foto selbst. Sonst würde er obere Bildpartien
   wie eine abgehängte Decke mit indirekter Beleuchtung mit abdunkeln.
   Auf dem Foto bleibt nur noch ein kurzes Schwarz→Transparent-
   Ausklingen als weicher Anschluss an die Naht. */
section:not(.section--dark):not(.hero):not(.ba-hero):not(.testimonial-hero):has(+ .ba-hero),
section:not(.section--dark):not(.hero):not(.ba-hero):not(.testimonial-hero):has(+ .testimonial-hero) {
  position: relative;
}
section:not(.section--dark):not(.hero):not(.ba-hero):not(.testimonial-hero):has(+ .ba-hero)::after,
section:not(.section--dark):not(.hero):not(.ba-hero):not(.testimonial-hero):has(+ .testimonial-hero)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 160px;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 0%, #000 100%);
}
section:not(.section--dark):not(.hero):not(.ba-hero):not(.testimonial-hero) + .ba-hero::before,
section:not(.section--dark):not(.hero):not(.ba-hero):not(.testimonial-hero) + .testimonial-hero::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 90px;
  z-index: 5;
  pointer-events: none;
  background: linear-gradient(to bottom, #000 0%, transparent 100%);
}

/* Weiche dunkle Übergangs-Kante oben an einzelnen Blöcken (auch wenn davor
   KEINE dunkle Section liegt) – für einen hochwertigeren, aufgeräumten Look.
   Als Overlay (::before) statt background-image, damit der Grundton der
   Section (muted/grau) unberührt bleibt. Der Inhalt liegt darüber (z-index),
   damit Überschrift/Eyebrow scharf bleiben – der Verlauf sitzt im oberen
   Freiraum. Aktuell: die drei Blöcke auf index.html (Preise, Ablauf,
   Referenzen). */
.section--seam { position: relative; padding-top: clamp(6rem, 8vw, 8.5rem); }
.section--seam::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 150px;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, #000 0%, transparent 100%);
}
.section--seam > .section__inner { position: relative; z-index: 1; }

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

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Blöcke tauchen erst beim Scrollen auf (statt alle von Anfang an zu
   zeigen), damit Besucher die Seite nach und nach lesen statt zu
   springen. Klasse wird per JS gesetzt (js/partials.js), ohne JS
   bleibt alles normal sichtbar. */
.reveal-on-scroll {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.8s cubic-bezier(.22,.61,.36,1), transform 0.8s cubic-bezier(.22,.61,.36,1);
  transition-delay: var(--reveal-delay, 0s);
}
.reveal-on-scroll.is-revealed {
  opacity: 1;
  transform: none;
}

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  line-height: 1.7;
  /* Sicherheitsnetz gegen horizontales Scrollen der ganzen Seite (v.a.
     durch die seitlich überhängenden .testimonial-stack-Karten, siehe
     "Testimonial-Karussell"-Abschnitt). Bugfix-Historie: stand vorher auf
     html statt body -- overflow-x:hidden direkt auf dem Root-Element
     macht <html> selbst zum "nearest scrolling ancestor" und bringt dabei
     in manchen Browsern position:sticky von Kindelementen durcheinander
     (der Header verschwand beim Scrollen auf Mobil, statt oben kleben zu
     bleiben). Auf body gesetzt propagiert der Overflow stattdessen ganz
     regulär auf den Viewport, ohne dieses Sticky-Problem. */
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
img, svg, video { display: block; max-width: 100%; }
ul { padding-left: 1.2rem; }

/* Vorteils-Liste ("Warum IMMO LUCHIAN?"): Statt einer einzelnen, rechts-
   bündigen 720px-Spalte mit leerer Fläche daneben (keine Bildkomponente,
   die die Asymmetrie rechtfertigt) füllt die Liste jetzt die volle
   zentrierte Breite in zwei Spalten. `columns` statt Grid, damit sie sich
   von selbst auf eine Spalte reduziert, sobald der Platz nicht mehr für
   zwei ausreicht — kein eigener Breakpoint nötig. */
.benefit-list {
  columns: 2 340px;
  column-gap: 3rem;
  margin: 1.5rem 0;
}
.benefit-list li {
  break-inside: avoid;
  margin-bottom: 1.1rem;
}

h1, h2, h3 {
  margin: 0 0 1rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  line-height: 1.2;
  overflow-wrap: break-word;
  word-break: break-word;
  hyphens: auto;
}
/* Die vw-Rate bestimmt, bei welcher Fensterbreite die Schrift ihre
   Obergrenze erreicht (Obergrenze in px / vw-Rate = Breite in px). Vorher
   lag diese Grenze bei ~1150-1170px — auf jedem normalen Laptop/Desktop-
   Bildschirm (13" bis 17"+) war die Schrift dadurch schon bei kleinsten
   Fensterbreiten eingefroren und wuchs nie mit, egal wie groß der
   Bildschirm tatsächlich war. Jetzt liegt die Grenze bei ~1850-1950px,
   deckt also den typischen Laptop-/Desktop-Bereich durchgehend ab. */
h1 { font-weight: 400; letter-spacing: 0.12em; font-size: clamp(2rem, 3.6vw, 4.4rem); }
h2 { font-size: clamp(1.5rem, 2.6vw, 3rem); }
h3 { font-weight: 500; letter-spacing: 0.18em; font-size: 1.1rem; }

.eyebrow {
  font-weight: 500;
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  /* gray-700 statt gray-500: auf hellem Grund erreicht gray-500 nur
     ca. 4.3:1 Kontrast (knapp unter WCAG-AA 4.5:1) — gray-700 liegt
     bei ca. 8.4:1 und bleibt trotzdem als "gedämpftes" Label lesbar. */
  color: var(--gray-700);
  margin: 0 0 0.8rem;
}

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

/* --- Buttons: Plakette mit zentralem Lichtschein (Referenzbild) ---------
   Ein weicher weißer Lichtkegel in der Mitte, der zu Schwarz an den
   Rändern ausblendet — wie ein beleuchtetes Schild im Dunkeln. Text
   liegt immer im hellen Kern und bleibt darum einfach schwarz, klein
   geschrieben, ohne Versalien-Sperrung. */
.btn, .btn--ghost {
  display: inline-block;
  position: relative;
  padding: 0.9rem 1.9rem;
  font-weight: 600;
  text-transform: lowercase;
  letter-spacing: 0.01em;
  font-size: 0.95rem;
  border: none;
  border-radius: 6px;
  background: radial-gradient(ellipse 75% 100% at center, #fff 0%, #fff 28%, #1a1a1a 78%, #000 100%);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.22), 0 2px 6px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
.btn:hover, .btn:focus-visible,
.btn--ghost:hover, .btn--ghost:focus-visible {
  box-shadow: 0 18px 32px rgba(0, 0, 0, 0.28), 0 4px 10px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
}
.btn__label {
  position: relative;
  z-index: 1;
  color: #111;
}

/* --- Grenzenlose Karten: keine feste Kante, weicher Rand bei Hover /
   wenn die Karte beim Scrollen ins Bild kommt. */
.card,
.site-header__brand {
  border-color: transparent;
  transition: box-shadow 0.4s ease, border-color 0.4s ease, background-color 0.3s ease, color 0.3s ease;
}
.card:hover, .card:focus-within, .card.is-inview,
.site-header__brand:hover, .site-header__brand:focus-visible {
  box-shadow: 0 0 0 1px rgba(0,0,0,0.12), 0 14px 32px rgba(0,0,0,0.14);
}
.section--dark .card:hover, .section--dark .card.is-inview,
.hero .card:hover, .hero .card.is-inview {
  box-shadow: 0 0 0 1px rgba(255,255,255,0.25), 0 14px 32px rgba(255,255,255,0.08);
}
.section--dark .card,
.hero .card {
  background: transparent;
  color: inherit;
}
/* Über dem Video keinen Rahmen/Rand zeigen — das Video soll frei
   durchscheinen, nur der Text bekommt einen leichten Schatten fürs
   Lesen. */
.hero .card,
.hero .card:hover,
.hero .card.is-inview {
  box-shadow: none;
  padding: 0.4rem 0;
}
.hero .card h3,
.hero .card p {
  text-shadow: 0 2px 10px rgba(0,0,0,0.7);
}

.btn-row { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 1.6rem; }

section { padding: 5rem var(--pad); }
/* overflow-x:hidden hier (statt nur global auf body) faengt die seitlich
   ueberhaengenden .testimonial-stack-Karten (Bewertungen, .about-carousel,
   .photo-carousel -- siehe deren data-pos 1/2/3, die per translateX bis zu
   78% ueber die eigene Kartenbreite hinausragen) schon auf Section-Ebene
   ab, statt das gesamte <body> in die Breite zu treiben. Ohne das wurde
   document.documentElement.scrollWidth auf Mobil deutlich breiter als der
   sichtbare Viewport (in einem Test z.B. 520px bei 375px Viewport) --
   das brachte sowohl den schwebenden WhatsApp-Button (position:fixed,
   right:1.5rem) aus der Spur als auch die Sticky-Positionierung des
   Headers beim Scrollen durcheinander. Visuell aendert sich nichts: der
   Peek-Effekt wurde vorher ohnehin am Viewport-Rand abgeschnitten, jetzt
   passiert das nur eine Ebene frueher. */
.section__inner { max-width: var(--maxw); margin: 0 auto; overflow-x: hidden; }
.section--muted { background: var(--gray-100); }
.section--dark {
  background:
    linear-gradient(135deg, #000 0%, #000 30%, #242424 46%, #000 62%, #000 100%);
  color: var(--white);
}
.section--dark h1, .section--dark h2, .section--dark h3 { color: var(--white); }
.section--dark .eyebrow { color: var(--gray-300); }

/* Karussell aus mehreren Textblöcken — nutzt dieselbe 3D-Stapel-Mechanik
   wie die Bewertungen (.testimonial-stack, siehe js/testimonial-stack.js):
   .about-carousel ist nur eine Zusatzklasse obendrauf, .about-carousel__slide
   sitzt zusätzlich auf .testimonial-stack__card, damit die vorhandene
   Positionierung/das Wischen/die Pfeiltasten automatisch mitgelten. */
.testimonial-stack.about-carousel { max-width: 820px; }
.testimonial-stack__card.about-carousel__slide {
  /* Glänzendes Schwarz mit drei diagonalen Lichtstreifen statt einem
     einzelnen — je einer nahe der oberen linken und unteren rechten
     Ecke zusätzlich zum mittleren Streifen (wie beim Hero-Verlauf).
     Compound-Selektor (statt nur .about-carousel__slide), damit das die
     spätere, sonst gleich spezifische .testimonial-stack__card-Regel
     zuverlässig überschreibt statt von der Reihenfolge abzuhängen. */
  background:
    linear-gradient(135deg, transparent 4%, rgba(255,255,255,0.07) 10%, transparent 16%),
    linear-gradient(135deg, transparent 78%, rgba(255,255,255,0.07) 84%, transparent 90%),
    linear-gradient(135deg, #000 0%, #000 30%, #262626 46%, #000 62%, #000 78%, transparent 100%);
  color: var(--white-bright);
  padding: 2.2rem 2rem 2.6rem;
}
.about-carousel__slide .eyebrow { color: var(--gray-300); }

/* Reines Foto-Karussell — dieselbe Stapel-Mechanik (siehe oben), aber
   die Karte ist nur der Bilderrahmen: kein Innenabstand/Hintergrund,
   das Foto füllt die Karte komplett und wird großzügiger hoch als die
   kleinen Testimonial-Fotos angezeigt. */
.testimonial-stack.photo-carousel { max-width: 920px; }
.testimonial-stack__card.photo-carousel__slide { background: #000; padding: 0; }
.photo-carousel__slide img {
  display: block;
  width: 100%;
  height: clamp(320px, 45vw, 560px);
  object-fit: cover;
}

/* Weicher schwarzer Übergang direkt über dem Foto-Karussell — dieselbe
   Naht-Logik wie bei .ba-hero/.testimonial-hero (Weißraum verdunkelt
   sich sanft, bevor die dunklen Bild-Karten beginnen), nur lokal auf
   diese eine Section begrenzt statt an eine bestimmte Klasse gekoppelt. */
.photo-carousel-section { position: relative; }
.photo-carousel-section::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 140px;
  background: linear-gradient(to bottom, transparent 0%, #000 100%);
  pointer-events: none;
}
.photo-carousel-section .section__inner { position: relative; z-index: 1; }

/* Auffälliger Dunkel-Block für "wie lange dauert das?"-Angaben,
   damit die Kernzahl nicht in einem einfachen Fließtext-Absatz
   untergeht, sondern auf den ersten Blick ins Auge fällt. */
.duration-highlight {
  margin-top: 2.5rem;
  padding: 2.2rem clamp(1.5rem, 4vw, 2.8rem);
  border-radius: 16px;
  color: var(--white-bright);
}
.duration-highlight h3 { margin-bottom: 0.6rem; }
.duration-highlight > p { color: var(--gray-300); margin-bottom: 1.6rem; }
.duration-highlight__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.6rem 2rem;
  padding-top: 1.4rem;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
}
.duration-highlight__value {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  margin: 0 0 0.4rem;
}
.duration-highlight__label {
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--gray-300);
  margin: 0;
}
@media (max-width: 620px) {
  .duration-highlight__grid { grid-template-columns: 1fr; }
}

/* --- Hierarchie-System: Wichtiges groß, Nebensächliches klein,
   Blöcke mal mittig, mal links, mal rechts positioniert. --------------- */

/* Größenstufen für Textbedeutung */
.stat {
  display: block;
  font-size: clamp(2.2rem, 3.8vw, 4.4rem);
  line-height: 1.1;
  margin: 0.3rem 0 1rem;
}
.lede {
  font-size: 1.25rem;
  line-height: 1.6;
  max-width: 62ch;
}
.fine {
  font-size: 0.82rem;
  color: var(--gray-700);
  max-width: 60ch;
}
.section--dark .fine, .hero .fine { color: var(--gray-300); }

/* Wort-Hierarchie innerhalb einer Überschrift: der Kernsatz bleibt in
   voller H1/H2-Größe, Nebensächliches (Ort, Standardfloskeln) wird
   kleiner und leiser, damit das Auge sofort weiß, wo es zuerst
   hinschauen soll — statt alles gleich groß/laut zu schreien. */
.title-detail {
  display: block;
  font-size: 0.42em;
  font-weight: 400;
  letter-spacing: 0.08em;
  opacity: 0.65;
  margin-top: 0.5em;
}
.title-tag {
  display: block;
  font-size: 0.5em;
  font-weight: 700;
  margin-top: 0.55em;
}

/* Blockposition innerhalb der Section: mittig (Standard), links, rechts.
   Der Block darf auf breiten Bildschirmen nicht an der echten Fensterkante
   kleben (dann reißt auf der Gegenseite eine riesige Lücke auf, sobald das
   Fenster breiter als --maxw + 2×--pad ist) — er bleibt stattdessen an der
   Kante der zentrierten --maxw-Spalte, genau wie alle anderen Sections. */
.section__inner--left {
  margin-left: max(0px, calc((100vw - var(--maxw)) / 2 - var(--pad)));
  margin-right: auto;
  max-width: 720px;
}
.section__inner--right {
  margin-left: auto;
  margin-right: max(0px, calc((100vw - var(--maxw)) / 2 - var(--pad)));
  max-width: 720px;
  /* Text bleibt immer linksbündig lesbar (Leserichtung Europa/Latein) —
     nur der Block selbst sitzt rechts im Abschnitt, nicht die Schrift. */
  text-align: left;
}

@media (max-width: 720px) {
  .section__inner--left,
  .section__inner--right {
    max-width: none;
    text-align: left;
  }
}

/* --- Header / Navigation --------------------------------------------- */

/* header.html wird per JS in diesen Wrapper geladen (siehe js/partials.js).
   Ohne display:contents hat der Wrapper exakt die Höhe des Headers selbst
   und nimmt .site-header dadurch jeden Spielraum zum "Kleben" — position:
   sticky bräuchte einen Container, der höher als der Header ist. */
#header-slot { display: contents; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--black-matte);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

.site-header__inner {
  /* Etwas breiter als der übrige Content (--maxw), damit alle Nav-Punkte
     als Buttons in einer Zeile Platz haben, statt schon bei normaler
     Desktop-Breite in eine zweite Zeile umzubrechen. */
  max-width: 1440px;
  margin: 0 auto;
  padding: 1rem var(--pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem;
}

.site-header__brand {
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.7rem;
  border-radius: 2px;
}
.site-header__logo {
  height: 58px;
  width: auto;
  /* Logo ist schwarze Linienzeichnung — auf dem schwarzen Header per
     Filter in Weiß gedreht, ohne eine zweite Logo-Datei zu brauchen. */
  filter: brightness(0) invert(1);
}
.site-header__brand-text {
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--white-bright);
}
.site-header__tagline {
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--white-bright);
  margin-left: 0.9rem;
  padding-left: 0.9rem;
  border-left: 1px solid rgba(255,255,255,0.25);
}

.site-header__contact {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex-shrink: 0;
}
.site-header__call,
.site-header__whatsapp {
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.8);
  white-space: nowrap;
}
.site-header__call:hover,
.site-header__whatsapp:hover { color: var(--white-bright); }

/* --- Leistungen-Dropdown in der Navigation ------------------------------ */

.site-nav__dropdown { position: relative; display: flex; align-items: center; }
/* Kein eigener Karten-Hintergrund mehr — die Buttons schweben einzeln
   frei (jeder mit eigenem Lichtkegel/Schatten), statt in einer weißen
   Box zu stecken. */
.site-nav__dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 0.6rem;
  /* Deutlich schmaler als vorher (240px) — die Buttons bleiben zwar alle
     gleich breit (align-items:stretch, Flex-Default), aber die Box wird
     nicht mehr an "Alle Leistungen"/"Zusammenarbeit" in einer Zeile
     ausgerichtet. Längere Einträge brechen stattdessen um (siehe
     white-space:normal unten), damit das Menü insgesamt kompakter wirkt. */
  min-width: 165px;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
  z-index: 60;
}
.site-nav__dropdown-menu a {
  display: block;
  padding: 0.65rem 0.85rem;
  border-radius: 6px;
  font-size: 0.82rem;
  text-align: center;
  white-space: normal;
}
.site-nav__dropdown:hover .site-nav__dropdown-menu,
.site-nav__dropdown:focus-within .site-nav__dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* Sämtliche Nav-Punkte (Top-Level-Links, "Mehr ⋯"-Trigger und die
   Dropdown-Unterpunkte) sehen wie eigene Buttons aus — derselbe
   Weiß-zu-Schwarz-Lichtkegel wie .btn, statt schlichter Textlinks. */
.site-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
/* 1:1 dasselbe Aussehen wie die echten CTA-Buttons (.btn): exakt
   derselbe Verlauf, und wie dort passt sich die Breite dem eigenen Text
   an (inline-block), statt auf volle Zeilenbreite gestreckt zu werden —
   nur so bleibt der Lichtkegel proportional korrekt, egal wie kurz oder
   lang die Beschriftung ist. */
.site-nav a, .site-nav__dropdown-trigger {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.6rem 1.1rem;
  border-radius: 6px;
  color: #111;
  background: radial-gradient(ellipse 75% 100% at center, #fff 0%, #fff 28%, #1a1a1a 78%, #000 100%);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.22), 0 2px 6px rgba(0, 0, 0, 0.18);
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
.site-nav__dropdown-trigger {
  border: none;
  font-family: inherit;
  cursor: pointer;
}
/* Dasselbe Hoch-Wachsen wie bei den echten CTA-Buttons (.btn:hover) —
   reagiert spürbar auf Maus (Hover) und Finger (Fokus beim Antippen). */
.site-nav a:hover, .site-nav a.is-active, .site-nav a:focus-visible,
.site-nav__dropdown:hover .site-nav__dropdown-trigger,
.site-nav__dropdown:focus-within .site-nav__dropdown-trigger,
.site-nav__dropdown-menu a:hover, .site-nav__dropdown-menu a.is-active, .site-nav__dropdown-menu a:focus-visible {
  color: #111;
  box-shadow: 0 18px 32px rgba(0, 0, 0, 0.28), 0 4px 10px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
}

.site-nav__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 32px;
  height: 32px;
  background: none;
  border: none;
  cursor: pointer;
}
.site-nav__toggle span { display: block; height: 2px; background: var(--white-bright); }

/* --- Hero (mit Video-Platzhalter) --------------------------------------- */

.hero {
  position: relative;
  padding: 6rem var(--pad);
  background:
    linear-gradient(150deg, #000 0%, #000 25%, #262626 42%, #000 58%, #000 100%);
  background-repeat: no-repeat;
  color: var(--white);
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.8) saturate(1.05);
}

/* Scrim über dem Video: dunkler Verlauf für Lesbarkeit. Header ist
   jetzt selbst schwarz, daher direkter Block statt Weiß-Übergang.
   Bewusst leichter gehalten, damit das Video besser durchscheint —
   die Lesbarkeit übernimmt stattdessen der Text-Schatten auf
   .hero__content (siehe unten). */
.hero__media--video::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.32) 0%, rgba(0,0,0,0.4) 100%);
}

/* Solange kein echtes Video vorliegt: neutraler Platzhalter statt Stockfoto */
.hero__media--placeholder {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: 1.2rem;
  background: linear-gradient(150deg, #000 0%, #000 25%, #2b2b2b 42%, #000 58%, #000 100%);
}
.hero__media--placeholder span {
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--gray-300);
  border: 1px dashed var(--gray-500);
  padding: 0.4rem 0.9rem;
  background: rgba(0,0,0,0.4);
}

.hero__content {
  position: relative;
  z-index: 1;
  max-width: var(--maxw);
  margin: 0 auto;
}

.hero__sub { max-width: 60ch; font-size: 1.1rem; color: var(--gray-300); }

/* Da das Video jetzt heller/sichtbarer ist und der Scrim dafür
   leichter gehalten wurde, sichert ein kräftiger Text-Schatten die
   Lesbarkeit direkt am Text ab statt allein über die Abdunkelung
   des Hintergrunds. */
.hero__content h1,
.hero__content .eyebrow,
.hero__content .hero__sub,
.hero__content .hero__fact-title,
.hero__content .hero__fact-text {
  text-shadow: 0 2px 16px rgba(0,0,0,0.85), 0 1px 4px rgba(0,0,0,0.9);
}

/* Zwei kurze Kernfakten nebeneinander statt als Fließtext-Absätze
   untereinander — mit Trennlinie dazwischen, wie ein aufgeräumtes
   Menü/Editorial-Raster statt "Buchtext". Architektonischer Aufbau:
   kleines Label + kurzer Satz, klar voneinander abgesetzt. */
.hero__facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem 2.5rem;
  max-width: 56rem;
  margin: 1.8rem 0;
  padding-top: 1.4rem;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}
.hero__fact-title {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--white-bright);
  margin-bottom: 0.5rem;
  line-height: 1.25;
}
.hero__fact-text {
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--gray-300);
  max-width: 32ch;
}

@media (max-width: 620px) {
  .hero__facts { grid-template-columns: 1fr; gap: 1.2rem; }
}

/* --- Karten (Leistungen, Referenzen) -------------------------------------- */

.cards {
  display: grid;
  /* 200px statt vorher 260px: Cards-Raster sitzt oft in der schmalen
     720px-Textspalte (.section__inner--left/--right) — bei 260px passten
     3 Karten dort nie nebeneinander (260×3 + Abstände > 720px), die dritte
     rutschte immer eine Zeile tiefer. Bei 200px passen 3 Karten fließend
     bis knapp über Handy-Breite, ganz ohne festen Breakpoint pro Seite. */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.75rem;
  margin-top: 2.5rem;
}

/* Lange Fließtext-Abschnitte (Kosten, FAQ) in einzelne, gut lesbare
   Blöcke aufgeteilt statt als ein durchgehender Textblock. */
.info-blocks {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin: 1.75rem 0;
}
.info-blocks .card { margin: 0; }
.info-blocks .card--wide { grid-column: 1 / -1; }
.inline-stat { font-size: 1.3em; font-weight: 700; }

@media (max-width: 720px) {
  .info-blocks { grid-template-columns: 1fr; }
}

/* Karten-Raster mit "Mehr lesen"-Aufklapper: nur die AUFGEKLAPPTE Karte darf
   wachsen. Ohne dies zieht das Grid alle Karten einer Reihe auf die Hoehe der
   groessten -> neben einer aufgeklappten Karte stehen sonst grosse leere
   weisse Kaesten. align-items:start laesst jede Karte nur so hoch werden wie
   ihr eigener Inhalt. */
.cards:has(details.more),
.info-blocks:has(details.more) { align-items: start; }

/* Grenzenloser Bild-Stil: kein Rahmen, keine Kante, kein Schatten —
   das Foto verblasst weich nach außen und geht nahtlos in den
   Seitenhintergrund über (radiale Alpha-Maske, opak in der Mitte,
   transparent am Rand). Gilt nur noch für Testimonial-Fotos. Die
   Vorher/Nachher-Regler brauchen die volle, unverfälschte Bildschärfe
   zum Vergleichen — deshalb kein Ausblenden mehr auf .ba-slider__before/
   __after (weder eingebettet auf reference.html noch im .ba-hero). */
.testimonial-stack__media {
  -webkit-mask-image: radial-gradient(ellipse at center, #000 42%, transparent 100%);
  mask-image: radial-gradient(ellipse at center, #000 42%, transparent 100%);
}

/* Testweise EIN Bild (Vorher/Nachher-Regler auf der Startseite) als
   randloser, vollflächiger Bereich wie der Hero oben — kein schmales
   Bild in der Content-Spalte, sondern ein ganzer Seiten-Block mit
   Foto als Hintergrund und Überschrift oben drauf. */
.ba-hero {
  position: relative;
  overflow: hidden;
  padding: 0;
  background: #000;
  color: var(--white-bright);
}
.ba-hero .eyebrow { color: var(--gray-300); }
.ba-hero h2 { color: var(--white-bright); }

.ba-slider-showcase {
  position: relative;
}
.ba-slider-showcase .ba-slider {
  width: 100%;
  aspect-ratio: unset;
  height: min(78vh, 760px);
  /* Die Basisregel oben (.ba-slider) setzt margin:2rem 0 für die
     eingebettete Karten-Variante — im randlosen .ba-hero-Vollbild-Einsatz
     erzeugte das einen 32px hohen Schwarzstreifen oben UND unten. Bei
     mehreren .ba-hero-Blöcken direkt hintereinander (z. B. reference.html)
     summierte sich das zu einer 64px hohen Lücke an der Naht. */
  margin: 0;
}
.ba-slider-showcase .ba-slider__before,
.ba-slider-showcase .ba-slider__after {
  mask-image: none;
  -webkit-mask-image: none;
}
/* Nur noch die unteren ~30% (wo die Überschrift in .ba-hero__content
   liegt) werden abgedunkelt, darüber bis nach oben bleibt das
   Vorher/Nachher-Foto in seiner Originalhelligkeit/-farbe sichtbar. */
.ba-slider-showcase::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,0) 65%,
    rgba(0,0,0,0.55) 85%,
    rgba(0,0,0,0.88) 100%);
}

/* Testweise EIN Testimonial (Ralf Witti, Startseite) als Block aus
   zwei klar getrennten Teilen — kein Verlauf, keine Vignette, keine
   Überlagerung: oben das Foto (unangetastet, Original), darunter ein
   eigener Abschnitt mit schwarzem Hintergrund und weißer Schrift. */
.testimonial-hero {
  position: relative;
  padding: 0;
  background: #000;
}
.testimonial-hero__media {
  display: block;
  width: 100%;
  height: min(60vh, 560px);
  object-fit: cover;
}
.testimonial-hero__content {
  position: relative;
  background: #000;
  color: var(--white-bright);
}
/* Weicher Übergang an der Naht zwischen Foto und Schwarz-Block
   (beides im selben Abschnitt, kein Section-Wechsel) — dieselbe
   130px-Verlaufslogik wie zwischen zwei Sections, nur als Overlay,
   das ins Foto hineinragt statt am Section-Rand anzusetzen. */
.testimonial-hero__content::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 130px;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 0%, #000 100%);
}
.testimonial-hero__content .section__inner { padding: 3rem var(--pad); }
.testimonial-hero__content .testimonial-card__name { color: var(--white-bright); }

.ba-hero__content {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--pad);
  padding-bottom: 3rem;
}

/* Foto-Galerie: echte Projektbilder, lose auf heller Fläche statt in Boxen. */
.photo-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2rem;
  margin: 2rem 0;
}
.photo-gallery figure { margin: 0; }
.photo-gallery img {
  display: block;
  width: 100%;
  height: 280px;
  object-fit: cover;
}
/* Rahmen um freistehende Fotos (per JS eingefügt, siehe
   wrapZoomableImagesInFrame() in lightbox.js): overflow:hidden fängt den
   Hover-/Scroll-Zoom sauber im eigenen Bildbereich ab, statt dass das
   vergrößerte Foto über seinen Platz hinauswächst und mit dem
   Nachbarbild kollidiert. Die weiche Aura (.photo-vignette::before)
   sitzt eine Ebene weiter außen und bleibt davon unberührt. */
.photo-frame { display: block; overflow: hidden; position: relative; }
.photo-gallery .photo-frame { height: 280px; }
.photo-frame:has(> .body-photo) { height: clamp(240px, 40vw, 420px); }
.photo-vignette .photo-frame:has(> .body-photo) { margin: 0; }
.media-split .photo-vignette .photo-frame { height: 100%; }
.photo-gallery figcaption {
  padding-top: 0.6rem;
  font-size: 0.8rem;
  color: var(--gray-700);
  text-align: center;
}
.section--dark .photo-gallery figcaption { color: var(--gray-300); }

.body-photo {
  width: 100%;
  height: clamp(240px, 40vw, 420px);
  object-fit: cover;
  margin: 2rem 0;
}

/* Grenzenloser Bild-Stil, Variante 2: Foto bleibt 100% Original (kein
   Ausblenden/Maskieren am Bild selbst), stattdessen sitzt dahinter
   eine weiche, verschwommene Aura, die von Schwarz/Grau in den
   jeweiligen Sektions-Hintergrund ausläuft (weiß, hellgrau bei
   .section--muted, oder unsichtbar auf ohnehin dunklem Grund) — dadurch
   wirkt jedes Foto wie Teil der Seite statt wie ein aufgeklebtes Bild.
   Gilt für Foto-Galerie, Bild+Text-Kombination und Einzelfotos im
   Fließtext. Testimonial-Fotos und die Vorher/Nachher-Regler behalten
   bewusst die ursprüngliche Radial-Masken-Technik (siehe oben). */
.photo-vignette {
  position: relative;
}
/* Großzügiger Streuradius + Weichzeichner statt einer harten
   Verlaufs-Box: so entsteht wirklich keine wahrnehmbare Kante/Linie
   zwischen Aura und Seiten-Weiß, egal wie genau man hinschaut. Oben
   bewusst knapper (kein Überlappen mit der Überschrift), unten/seitlich
   großzügiger. */
.photo-vignette::before {
  content: "";
  position: absolute;
  inset: -4% -22% -26% -22%;
  z-index: 0;
  background: radial-gradient(ellipse at center,
    rgba(15, 15, 15, 0.55) 0%,
    rgba(60, 60, 60, 0.3) 38%,
    rgba(140, 140, 140, 0.1) 62%,
    transparent 82%);
  filter: blur(38px);
}
.photo-vignette img {
  position: relative;
  z-index: 1;
  -webkit-mask-image: none;
  mask-image: none;
}
.photo-vignette .body-photo { margin: 0; }

/* Bild und Text nebeneinander, abwechselnd links/rechts — statt
   Bild und Schrift immer gestapelt untereinander. */
.media-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.5rem;
  align-items: center;
  margin: 2rem 0;
}
.media-split__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Der Foto-Vignette-Wrapper (statt des <img> direkt) ist jetzt das
   Grid-Item und übernimmt Reihenfolge & Mindesthöhe. */
.media-split .photo-vignette { order: 1; height: 100%; min-height: 260px; }
.media-split__text { order: 2; }
.media-split--reverse .photo-vignette { order: 2; }
.media-split--reverse .media-split__text { order: 1; }

@media (max-width: 780px) {
  .media-split { grid-template-columns: 1fr; }
  .media-split .photo-vignette,
  .media-split--reverse .photo-vignette { order: 1; }
  .media-split__text,
  .media-split--reverse .media-split__text { order: 2; }
}

/* --- Vorher/Nachher-Regler ------------------------------------------------
   Mit Maus ziehen oder mit dem Finger wischen (natives <input type="range">
   im Hintergrund, unsichtbar aber voll bedienbar — inkl. Tastatur). Der
   sichtbare Griff mit Pfeilen macht deutlich, dass man ziehen kann. */
.ba-slider {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  margin: 2rem 0;
  box-shadow: 0 14px 32px rgba(0,0,0,0.18);
  --reveal: 50%;
  touch-action: pan-y;
}
.ba-slider__after,
.ba-slider__before {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
}
.ba-slider__before {
  clip-path: inset(0 calc(100% - var(--reveal)) 0 0);
}
/* Einziges Hochformat-Foto unter allen Vorher/Nachher-Paaren (1200x1600
   statt 4:3 Querformat) — object-fit:cover schneidet dadurch im sehr
   breiten .ba-hero-Rahmen deutlich mehr oben/unten weg als bei den
   anderen Paaren. Mit der Standard-Bildmitte (50%) fällt der Duschkopf
   fast komplett weg; bei 35% bleibt er vollständig sichtbar. */
.ba-slider__after[src*="Espelkamp"] {
  object-position: center 35%;
}
.ba-slider__divider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--reveal);
  width: 3px;
  background: var(--white-bright);
  transform: translateX(-50%);
  box-shadow: 0 0 8px rgba(0,0,0,0.4);
  pointer-events: none;
}
.ba-slider__handle {
  position: absolute;
  top: 50%;
  left: var(--reveal);
  transform: translate(-50%, -50%);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--white-bright);
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  color: var(--ink);
  /* Nur der Griff selbst darf gezogen werden (nicht mehr das ganze Foto,
     siehe .ba-slider__range darunter) — braucht dafür einen eigenen,
     etwas größeren unsichtbaren Hit-Bereich fürs Touch-Ziehen. */
  cursor: ew-resize;
  touch-action: none;
  z-index: 4;
}
.ba-slider__handle::before { content: "↔"; }
.ba-slider__handle::after {
  content: "";
  position: absolute;
  inset: -14px;
}
.ba-slider__range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  /* Zieht man früher irgendwo auf dem Foto, sprang der native Range-Wert
     sofort dorthin und verschob den Regler — das sollte laut Nutzerwunsch
     nur noch möglich sein, wenn man tatsächlich den sichtbaren Griff
     (.ba-slider__handle) anfasst. pointer-events:none nimmt der ganzen
     Trackfläche die Maus-/Touch-Bedienung; übrig bleibt nur die
     Tastatursteuerung (Tab + Pfeiltasten), die pointer-events nicht
     braucht. Das eigentliche Ziehen übernimmt js/before-after-slider.js
     direkt am Griff per Pointer-Events. */
  pointer-events: none;
  z-index: 3;
}
.ba-slider__label {
  position: absolute;
  top: 0.9rem;
  z-index: 2;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--white-bright);
  background: rgba(0,0,0,0.55);
  padding: 0.4rem 0.8rem;
  pointer-events: none;
}
.ba-slider__label--before { left: 0.9rem; }
.ba-slider__label--after { right: 0.9rem; }

.card {
  background: var(--white);
  border: 1px solid transparent;
  padding: 1.8rem;
}
.card h3 { margin-bottom: 0.7rem; }

/* --- Find-us-Block: klare Größenhierarchie (wichtiges groß, Labels
   klein) — Adresse/Öffnungszeiten/Ansprechpartner nebeneinander. */
.find-us {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
  margin-top: 2.5rem;
}
/* Symmetrische Trennlinie zwischen den drei Spalten statt nur Weißraum. */
.find-us > div:not(:first-child) {
  border-left: 1px solid var(--white-mid);
  padding-left: 2.5rem;
}
.find-us__label {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gray-700);
  margin-bottom: 1rem;
}
.find-us__big {
  font-size: 1.3rem;
  line-height: 1.5;
  margin: 0 0 1rem;
}
.find-us__row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--gray-300);
  font-size: 1.05rem;
}
.find-us__row:last-of-type { border-bottom: none; }
.find-us__small { font-size: 0.9rem; color: var(--gray-700); }

/* --- Testimonial-Slider: 3D-Karten-Stapel --------------------------------- */

/* Axonometrischer Karten-Stapel (Vorbild: gestaffelte App-Screens):
   die aktive Karte liegt vorne in voller Größe, die nächsten zwei
   liegen dahinter — nach rechts/hinten versetzt, verkleinert und
   leicht gedreht, so dass nur ein schmaler Streifen (~15–25%) an der
   Seite herausschaut. Alles weitere wartet unsichtbar ganz hinten.
   Wischen (Finger/Maus, horizontal), die Pfeile/Punkte oder die
   Pfeiltasten blättern durch den Stapel — siehe js/testimonial-stack.js. */
.testimonial-stack {
  position: relative;
  margin-top: 2.5rem;
  max-width: 760px;
  padding-right: clamp(2rem, 8vw, 4.5rem);
  perspective: 1800px;
  touch-action: pan-y;
  cursor: grab;
}
.testimonial-stack:active { cursor: grabbing; }

.testimonial-stack__track {
  position: relative;
  transform-style: preserve-3d;
  transition: height 0.4s ease;
}

.testimonial-stack__card {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  /* Unten läuft das satte Schwarz in den letzten ~20% weich aus, statt
     hart an der Kante der Karte aufzuhören — dadurch geht die Karte
     nahtlos in den hellen Seitenhintergrund über, keine scharfe Kante. */
  background: linear-gradient(to bottom, #000 0%, #000 78%, transparent 100%);
  color: var(--white-bright);
  border-radius: 16px;
  overflow: hidden;
  padding: 1.8rem 1.8rem 2.8rem;
  box-shadow: 0 25px 50px rgba(0, 0, 0, 0.35);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1), opacity 0.45s ease;
}
.testimonial-stack__card .testimonial-card__name { color: var(--white-bright); }
/* Karte ist flex-column — ohne Gegenmaßnahme streckt sich ein einzelner,
   nicht in .btn-row gewrapptes Button-Link auf die volle Kartenbreite
   (flex-Default align-items:stretch). Betrifft z. B. die "Mehr lesen"-
   Buttons im .about-carousel. */
.testimonial-stack__card > .btn { align-self: flex-start; }

/* Tiefen-Staffelung je nach Position relativ zur aktiven Karte
   (Attribut wird per JS gesetzt). */
.testimonial-stack__card[data-pos="0"] {
  transform: translate3d(0, 0, 0) rotateY(0deg) scale(1);
  z-index: 5;
  opacity: 1;
  pointer-events: auto;
}
/* Durchscheinende Karten (Position 1–3) bleiben klickbar (siehe JS) —
   ein Klick mit der Maus holt sie direkt nach vorne, statt dass man
   zwingend wischen/ziehen oder die Pfeiltasten benutzen muss. */
.testimonial-stack__card[data-pos="1"] {
  transform: translate3d(28%, -6%, -110px) rotateY(-7deg) scale(0.92);
  z-index: 4;
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
}
.testimonial-stack__card[data-pos="2"] {
  transform: translate3d(55%, -10%, -220px) rotateY(-11deg) scale(0.84);
  z-index: 3;
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
}
.testimonial-stack__card[data-pos="3"] {
  transform: translate3d(78%, -14%, -330px) rotateY(-14deg) scale(0.76);
  z-index: 2;
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
}
.testimonial-stack__card[data-pos="rest"] {
  transform: translate3d(28%, -13%, -420px) rotateY(-13deg) scale(0.7);
  z-index: 1;
  opacity: 0;
  pointer-events: none;
}
/* Bereits gezeigte Karten "verabschieden" sich nach vorne-links und
   lösen sich auf, statt einfach hart zu verschwinden. */
.testimonial-stack__card[data-pos="prev"] {
  transform: translate3d(-26%, 5%, 90px) rotateY(9deg) scale(0.94);
  z-index: 1;
  opacity: 0;
  pointer-events: none;
}

/* Nur die aktive Karte (data-pos="0") zeigt ihre Überschrift in voller
   Größe. Bei den dahinter liegenden, nur teilweise sichtbaren Karten
   (Stapel-Peek) wirkt eine große Überschrift unruhig/abgeschnitten —
   dort wird sie deutlich kleiner gesetzt, damit der Stapel aufgeräumt
   bleibt und die aktive Karte klar im Fokus ist. Betrifft aktuell nur
   .about-carousel, da nur diese Karten ein <h2> im Stapel haben. */
/* Innerhalb der aktiven Karte bleibt der Kernsatz in voller H2-Größe,
   der Nebensatz danach wird nur leicht (nicht drastisch) kleiner
   gesetzt — bewusst dezenter als .title-detail/.title-tag, die für
   diesen Fall zu klein wirkten. */
.title-secondary {
  display: block;
  font-size: 0.78em;
  margin-top: 0.45em;
}
.testimonial-stack__card[data-pos="1"] h2,
.testimonial-stack__card[data-pos="2"] h2,
.testimonial-stack__card[data-pos="3"] h2 {
  font-size: 1.15rem;
}

/* Foto blendet unten weich ins schwarze Karten-Innere aus — derselbe
   Effekt wie beim großen Vollbild-Testimonial (.testimonial-hero),
   nur innerhalb der Karte statt über eine ganze Section. Oben (z.B.
   eine abgehängte Decke) bleibt bewusst unangetastet in Originalfarbe. */
.testimonial-stack__card--photo .testimonial-stack__media {
  box-shadow: inset 0 -70px 45px -35px #000;
}

.testimonial-stack__media {
  display: block;
  width: 100%;
  height: clamp(180px, 26vw, 240px);
  object-fit: cover;
  margin-bottom: 1.4rem;
}

.testimonial-card__stars { letter-spacing: 0.1em; margin-bottom: 0.6rem; }
.testimonial-card__name { font-weight: 700; margin-top: 0.8rem; }

.testimonial-stack__nav { display: flex; align-items: center; justify-content: center; gap: 1.2rem; margin-top: 1.4rem; }
.testimonial-stack__arrow {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--gray-300);
  background: transparent;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease;
}
.testimonial-stack__arrow:hover { background: var(--ink); color: var(--white-bright); }
.testimonial-stack__dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem; max-width: 200px; }
.testimonial-stack__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: var(--gray-300);
  cursor: pointer;
}
.testimonial-stack__dot.is-active { background: var(--ink); }

/* --- Mehrstufiges Kontaktformular ------------------------------------------ */

/* Überschrift über der Formular-Karte zentriert statt linksbündig, damit
   sie sich als eigener Blickfang über der Box aufbaut. */
#quizform .eyebrow,
#quizform > .section__inner > h2 {
  text-align: center;
}

/* Kräftige Schwarz-Glanz-Karte (derselbe Verlaufsstil wie .section--dark)
   statt einer schlichten weißen Box mit dünnem Rahmen — die Karte soll
   als deutlicher Blickfang aus der hellen Seite herausstechen. */
.quiz-form {
  max-width: 640px;
  margin: 2.5rem auto 0;
  padding: clamp(2rem, 5vw, 3.5rem);
  position: relative;
  min-height: 260px;
  background: linear-gradient(135deg, #000 0%, #000 30%, #242424 46%, #000 62%, #000 100%);
  border-radius: 10px;
  box-shadow: 0 40px 80px rgba(0, 0, 0, 0.35);
  color: var(--white-bright);
}

.quiz-step { display: none; }
.quiz-step.is-active { display: block; }

.quiz-step h3 { margin-bottom: 1.4rem; color: var(--white-bright); }

.quiz-options {
  display: grid;
  gap: 0.8rem;
}

.quiz-options button {
  text-align: left;
  padding: 0.9rem 1.2rem;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--white-bright);
  font-size: 1rem;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.quiz-options button:hover,
.quiz-options button:focus-visible { border-color: var(--white-bright); background: rgba(255, 255, 255, 0.18); }

.quiz-form input,
.quiz-form textarea {
  width: 100%;
  padding: 0.7rem;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 4px;
  font-size: 1rem;
  margin-bottom: 1rem;
  background: rgba(255, 255, 255, 0.06);
  color: var(--white-bright);
}
.quiz-form input::placeholder,
.quiz-form textarea::placeholder { color: rgba(255, 255, 255, 0.45); }
.quiz-form input:focus,
.quiz-form textarea:focus { border-color: var(--white-bright); outline: none; }

.quiz-form label {
  display: block;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gray-300);
  margin-bottom: 0.3rem;
}

/* Honeypot-Feld für den Spam-Schutz: nie sichtbar für Menschen, aber im
   DOM vorhanden und normal ausfüllbar, damit simple Spam-Bots es trotzdem
   erwischen (display:none wird von manchen Bots erkannt und übersprungen). */
.quiz-form__honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Hinweis-Checkbox zur Datenschutzerklärung -- bewusst NICHT die
   generische .quiz-form-label-Optik (Versalien/gesperrt, fuer kurze
   Feldnamen gedacht), da hier ein ganzer, normal zu lesender Satz
   steht. Freiwillig, keine Pflicht (kein "required") -- das Absenden
   funktioniert auch ohne Haken. */
.quiz-form .quiz-form__consent {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin: 1.1rem 0 0.4rem;
  font-size: 0.82rem;
  line-height: 1.5;
  text-transform: none;
  letter-spacing: normal;
  color: rgba(255, 255, 255, 0.75);
  cursor: pointer;
}
.quiz-form__consent input[type="checkbox"] {
  width: auto;
  margin: 0.2rem 0 0;
  flex-shrink: 0;
  accent-color: var(--white-bright);
}
.quiz-form__consent a { color: var(--white-bright); text-decoration: underline; }
.quiz-form__consent-hint {
  margin: 0 0 1.3rem;
  font-size: 0.75rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
}

.quiz-back {
  background: none;
  border: none;
  color: var(--gray-300);
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  margin-top: 1.4rem;
}
.quiz-back:hover { color: var(--white-bright); }

.quiz-form__hint { color: var(--gray-300); }

.quiz-summary { font-size: 0.95rem; margin-bottom: 1.2rem; color: var(--gray-300); }

/* --- Footer ------------------------------------------------------------------ */

.site-footer {
  background:
    linear-gradient(to bottom, var(--white-bright) 0%, transparent 180px),
    linear-gradient(var(--black-matte), var(--black-matte));
  background-repeat: no-repeat;
  color: var(--gray-300);
  padding: 2.5rem var(--pad);
  font-size: 0.85rem;
}
/* Kein weißer Einblendfleck, wenn direkt davor bereits ein dunkler
   Abschnitt sitzt (dunkel-zu-dunkel braucht keinen Übergang). */
main:has(> section:last-child.section--dark) + div .site-footer,
main:has(> .hero:last-child) + div .site-footer {
  background: linear-gradient(var(--black-matte), var(--black-matte));
}
.site-footer__inner { max-width: var(--maxw); margin: 0 auto; }
/* Drei klar getrennte Gruppen statt einer langen Link-Reihe: Social
   Media, Kontakt, Rechtliches — jede mit eigenem kleinen Label. */
.site-footer__groups {
  display: grid;
  grid-template-columns: repeat(3, auto);
  gap: 2.5rem;
  margin-bottom: 1.6rem;
}
.site-footer__group-label {
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gray-300);
  margin-bottom: 0.6rem;
}
.site-footer__links { display: flex; flex-direction: column; gap: 0.5rem; }
.site-footer__links a { color: var(--gray-300); }
.site-footer__links a:hover { color: var(--white); }
.site-footer__meta { margin-top: 0.4rem; color: var(--gray-300); }

/* Schwebender WhatsApp-Chat-Button — auf jeder Seite sichtbar (liegt im
   Footer-Partial, wird also überall mit eingeladen), bleibt beim
   Scrollen fix unten rechts. Nutzt die `.btn`-Basisklasse, damit er wie
   ein ganz normaler Seiten-Button aussieht (gleicher Lichtschein-Verlauf),
   nur zusätzlich fest positioniert und mit Icon + Text statt reinem Text. */
.whatsapp-chat-bubble {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 900;
  /* Flacher & breiter statt eckig-dick — gleiches, langgestrecktes
     Seitenverhältnis wie die normalen Buttons (z.B. "anrufen"), nur mit
     Icon davor. Weniger Höhen-Padding, mehr Breiten-Padding. */
  padding: 0.5rem 1.6rem;
  font-size: 0.85rem;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
/* Dasselbe Hoch-Wachsen wie bei den übrigen Buttons der Seite — reagiert
   spürbar auf Maus (Hover) und Finger (Fokus beim Antippen). */
.whatsapp-chat-bubble:hover,
.whatsapp-chat-bubble:focus-visible {
  box-shadow: 0 18px 32px rgba(0, 0, 0, 0.28), 0 4px 10px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
}
.whatsapp-chat-bubble .btn__label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.whatsapp-chat-bubble svg { width: 15px; height: 15px; fill: #111; flex-shrink: 0; }

/* Zweiter schwebender Button, spiegelbildlich unten links — genau wie
   der WhatsApp-Button auf jeder Seite fest sichtbar (liegt im selben
   Footer-Partial), damit eine direkte Kontaktanfrage von überall aus
   ohne Umweg über die Navigation möglich ist. */
.anfragen-chat-bubble {
  position: fixed;
  left: 1.5rem;
  bottom: 1.5rem;
  z-index: 900;
  padding: 0.5rem 1.6rem;
  font-size: 0.85rem;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
.anfragen-chat-bubble:hover,
.anfragen-chat-bubble:focus-visible {
  box-shadow: 0 18px 32px rgba(0, 0, 0, 0.28), 0 4px 10px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
}
.anfragen-chat-bubble .btn__label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.anfragen-chat-bubble svg { width: 15px; height: 15px; fill: #111; flex-shrink: 0; }

/* --- Responsive --------------------------------------------------------------- */

@media (max-width: 860px) {
  .site-footer__groups { grid-template-columns: 1fr; gap: 1.5rem; }

  .site-nav {
    position: fixed;
    /* bottom:0 statt "auto" -- die Box muss den ganzen Bildschirm bis
       unten ausfuellen, sonst zieht sich der dunkle Blur-Hintergrund nur
       so hoch wie die Buttons selbst und der Rest der Seite (inkl. der
       schwebenden Chat-Buttons) blitzt darunter unverschleiert durch.
       Bugfix-Historie: vorher "inset: 0 0 auto 0" -- bei nur 9 Links war
       die Content-Hoehe kleiner als die verfuegbare Viewport-Hoehe,
       wodurch am unteren Rand eine Luecke ohne Verdunkelung entstand. */
    inset: 72px 0 0 0;
    flex-direction: column;
    align-items: center;
    gap: 0.8rem;
    /* Kein eigener Hintergrund/Blur mehr — genau wie beim Desktop-
       Dropdown (.site-nav__dropdown-menu) schweben die Buttons einzeln
       frei über der (unveränderten, unverschleierten) Seite dahinter,
       statt in einer dunklen Blur-Fläche zu stecken. Auf Nutzerwunsch
       an den PC-Look angeglichen. */
    padding: 1.2rem var(--pad) 1.6rem;
    transform: translateY(-120%);
    transition: transform 0.3s ease;
    overflow-y: auto;
  }
  .site-nav.is-open { transform: translateY(0); }
  .site-nav__toggle { display: flex; }

  /* Rein funktionale Fläche hinter/unter dem Menü — komplett
     durchsichtig (keine eigene Abdunklung mehr), sperrt aber weiterhin
     Klicks auf die Seite dahinter (Body-Scroll wird zusätzlich per JS
     gesperrt) und dient als Tippfläche zum Schließen. */
  .site-nav-backdrop {
    position: fixed;
    inset: 0;
    top: 72px;
    background: transparent;
    z-index: 45;
    opacity: 0;
    visibility: hidden;
    transition: visibility 0.3s;
  }
  .site-nav-backdrop.is-open {
    opacity: 1;
    visibility: visible;
  }

  /* "Mehr ⋯" ist auf dem Handy überflüssig — die Unterpunkte sind hier
     ohnehin immer direkt sichtbar (kein Hover verfügbar), daher wirkt
     der Zwischenschritt nur wie ein weiterer, funktionsloser Menüpunkt.
     Alle Links erscheinen stattdessen als eine durchgehende Liste. */
  .site-nav__dropdown-trigger { display: none; }

  /* Alle 9 Buttons gleich breit statt individuell textbreit (auf
     Nutzerwunsch dem Desktop-Dropdown angeglichen, wo align-items:stretch
     alle Unterpunkte automatisch auf die Breite des längsten Eintrags
     bringt). Mindestbreite passend zum längsten Label
     "Dachgeschossausbau" (gemessen 202px) mit etwas Luft. */
  .site-nav a { min-width: 220px; text-align: center; }

  .site-header__tagline { display: none; }
  .site-header__call-number,
  .site-header__whatsapp-number { display: none; }
  /* "Anrufen" wandert in die rechte obere Ecke direkt neben den
     Hamburger-Button, statt mittig zwischen Logo und Menü-Icon zu
     schweben — dadurch bleibt es fest oben stehen, während sich das
     Button-Menü darunter öffnet. */
  .site-header__inner { justify-content: flex-start; }
  .site-header__contact { margin-left: auto; }

  /* Dropdown auf dem Handy: kein Hover verfügbar, daher immer als
     eingerückte Unterliste sichtbar statt Hover-Popup. Genau wie die
     Top-Level-Buttons bleiben auch diese textbreit statt gestreckt. */
  .site-nav__dropdown { flex-direction: column; align-items: center; width: 100%; }
  .site-nav__dropdown-menu {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    box-shadow: none;
    background: transparent;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 0;
    margin-top: 0;
  }

  .find-us { grid-template-columns: 1fr; }
  .find-us > div:not(:first-child) {
    border-left: none;
    padding-left: 0;
    border-top: 1px solid var(--white-mid);
    padding-top: 1.8rem;
  }
}

@media (max-width: 1000px) and (min-width: 861px) {
  .find-us { grid-template-columns: 1fr 1fr; }
  .find-us > div:nth-child(3) { border-left: none; padding-left: 0; border-top: 1px solid var(--white-mid); padding-top: 1.8rem; grid-column: 1 / -1; }
}

/* --- Lightbox (Foto-Vergrößerung) ---------------------------------------- */

.is-zoomable { cursor: zoom-in; }

/* Bilder pulsen kurz größer bei Hover (Maus) oder sobald sie beim
   Scrollen mittig ins Bild kommen (Finger/Touch, siehe
   initImageFocusZoom() in partials.js) — macht instinktiv spürbar, dass
   sich Fotos vergrößern lassen, auch ohne dass man vorher weiß, dass ein
   Klick die Lightbox öffnet. Bewusst ein einmaliger Puls (groß → wieder
   normal) statt eines dauerhaften Zooms: bei großflächigen Bildern (z.B.
   .ba-slider im .ba-hero) blieb ein Sustained-Zoom sonst über die ganze
   Scroll-/Hover-Dauer vergrößert hängen und zeigte nur noch einen
   Bildausschnitt statt des ganzen Fotos. In Karten mit eigenem
   Bildausschnitt (Testimonials, Foto-Karussell, Vorher/Nachher-Regler)
   ist ohnehin overflow:hidden gesetzt — dort darf der Puls kräftiger
   ausfallen, ohne dass etwas über den Rahmen hinausragt. Bei frei
   stehenden Fotos (Galerie, Bild+Text, Fließtext) bleibt er moderater,
   damit nichts in Nachbartext hineinwächst. */
@keyframes zoom-pulse-soft {
  0% { transform: scale(1); }
  40% { transform: scale(1.25); }
  100% { transform: scale(1); }
}
@keyframes zoom-pulse-strong {
  0% { transform: scale(1); }
  40% { transform: scale(1.6); }
  100% { transform: scale(1); }
}
.is-zoomable:hover,
.is-zoomable.is-in-focus {
  /* 6.63s = 4.42s x 1.5 (nochmals 50% langsamer, auf Nutzerwunsch). */
  animation: zoom-pulse-soft 6.63s ease;
  position: relative;
  z-index: 2;
}
.testimonial-stack__media.is-zoomable:hover,
.testimonial-stack__media.is-zoomable.is-in-focus,
.testimonial-hero__media.is-zoomable:hover,
.testimonial-hero__media.is-zoomable.is-in-focus,
.photo-carousel__slide img.is-zoomable:hover,
.photo-carousel__slide img.is-zoomable.is-in-focus {
  animation-name: zoom-pulse-strong;
}
/* Der Puls skaliert den GANZEN Regler (nicht nur die Fotos einzeln) —
   Trennlinie und Griff sitzen als Geschwister-Elemente im selben
   .ba-slider und müssen sich mit demselben Faktor mitskalieren. Würde
   nur .ba-slider__before/__after skaliert, verschiebt sich die
   tatsächliche Bildkante gegenüber der (unskaliert bleibenden)
   Trennlinie um genau (reveal% - 50%) × (Skalierung - 1) — bei
   reveal=25% und Skalierung 1.6 z.B. um 15 Prozentpunkte. */
.ba-slider:hover,
.ba-slider.is-in-focus {
  animation: zoom-pulse-strong 6.63s ease;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.92);
  touch-action: none;
}
.lightbox.is-open { display: flex; }
.lightbox__img {
  max-width: 92vw;
  max-height: 92vh;
  object-fit: contain;
  touch-action: none;
  cursor: grab;
  will-change: transform;
  -webkit-mask-image: none;
  mask-image: none;
}
.lightbox__close {
  position: absolute;
  top: 1.2rem;
  right: 1.2rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.12);
  color: var(--white-bright);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}

/* --- Cookie-Consent-Banner (Google Ads Tracking) ------------------------- */
/* Consent Mode v2: der Google-Ads-Tag im <head> laedt immer, sendet
   aber vorab ein "denied"-Default-Signal (siehe <head> jeder Seite) --
   erst nach "Akzeptieren" wird per "consent update" auf granted
   umgeschaltet, js/cookie-consent.js. Optik an Referenz-Beispielen
   orientiert (professionelle Cookie-Karten): derselbe Glanz-Schwarz-
   Verlauf wie .quiz-form als Hintergrund, gestapelte Buttons.
   "Ablehnen" und "Akzeptieren" sind bewusst GLEICHWERTIG gestaltet
   (identischer Verlauf, gleiche Groesse) -- ein optisch abgewertetes
   "Ablehnen" gilt rechtlich als unzulaessiges Dark Pattern (Einwilligung
   muss so leicht zu verweigern wie zu erteilen sein). */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 950;
  padding: 1.8rem var(--pad) 1.7rem;
  background: linear-gradient(135deg, #000 0%, #000 30%, #242424 46%, #000 62%, #000 100%);
  box-shadow: 0 -20px 60px rgba(0, 0, 0, 0.4);
  color: var(--white-bright);
  transform: translateY(100%);
  transition: transform 0.4s ease;
}
.cookie-banner.is-visible { transform: translateY(0); }
.cookie-banner__inner { max-width: 640px; margin: 0 auto; }
.cookie-banner__title {
  margin: 0 0 0.7rem;
  color: var(--white-bright);
}
.cookie-banner__text {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.8);
}
.cookie-banner__text a { text-decoration: underline; color: var(--white-bright); }
.cookie-banner__actions {
  display: flex;
  flex-direction: row;
  gap: 0.7rem;
  margin-top: 1.3rem;
}
/* Beide Buttons je zur Haelfte -- linke Haelfte "ablehnen", rechte
   "akzeptieren". Grosse Tap-Flaeche (v. a. Handy: Daumen liegt rechts). */
.cookie-banner__actions .btn,
.cookie-banner__actions .btn--ghost {
  flex: 1 1 0;
  width: auto;
  text-align: center;
  font-size: 0.9rem;
  padding: 1.05rem 1rem;
}
/* "Ablehnen" dunkel/dezent (nur feine Kontur), "Akzeptieren" behaelt den
   normalen kraeftigen Weiss-zu-Schwarz-Verlauf -- auf Nutzerwunsch
   zurueckgestellt. Beide bleiben gleich gross und gut sichtbar/lesbar,
   nur die Farbe unterscheidet sich bewusst wieder. */
.cookie-banner__decline {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow: none;
  color: var(--white-bright);
}
.cookie-banner__decline:hover,
.cookie-banner__decline:focus-visible {
  background: rgba(255, 255, 255, 0.08);
  box-shadow: none;
  transform: none;
  color: var(--white-bright);
}
/* .btn__label (innerer Text-Span, siehe wrapButtonLabels() in
   partials.js) hat sitesweit fest color:#111 -- ueberschreiben, sonst
   ist "ablehnen" auf dem dunklen Hintergrund fast unsichtbar. */
.cookie-banner__decline .btn__label { color: var(--white-bright); }
.lightbox__close:hover { background: rgba(255, 255, 255, 0.22); }

/* Galerie-Navigation: gross durch alle Karussell-/Galerie-Fotos blaettern
   (Wischen, Pfeil-Buttons, Pfeiltasten), ohne die Lightbox zu schliessen. */
.lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.12);
  color: var(--white-bright);
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  -webkit-tap-highlight-color: transparent;
}
.lightbox__nav:hover { background: rgba(255, 255, 255, 0.22); }
.lightbox__nav--prev { left: 1rem; }
.lightbox__nav--next { right: 1rem; }
.lightbox__counter {
  position: absolute;
  bottom: 1.2rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.35rem 0.9rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.5);
  color: var(--white-bright);
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  z-index: 2;
}
@media (max-width: 620px) {
  .lightbox__nav { width: 44px; height: 44px; font-size: 1.6rem; }
  .lightbox__nav--prev { left: 0.4rem; }
  .lightbox__nav--next { right: 0.4rem; }
}

/* Aufklappbare Bewertung INNERHALB einer Testimonial-Karte (Matthias
   Wortmann auf dachgeschossausbau.html): standardmaessig nur ein kurzer
   Anriss, per Klick der volle Text. Reines <details>/CSS; die Track-Hoehe
   des Karussells wird beim toggle per JS nachgezogen (testimonial-stack.js).
   Sitzt in .testimonial-stack__body -> Schrift ist schon weiss. */
.review-more > summary { list-style: none; cursor: pointer; outline: none; }
.review-more > summary::-webkit-details-marker { display: none; }
.review-more__teaser { display: block; }
.review-more__full { display: none; }
.review-more[open] .review-more__teaser { display: none; }
.review-more[open] .review-more__full { display: block; }
.review-more__toggle {
  display: inline-block;
  margin-top: .8rem;
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  border-bottom: 1px solid rgba(255,255,255,.5);
  padding-bottom: 2px;
  transition: border-color .2s ease;
}
.review-more > summary:hover .review-more__toggle { border-color: var(--white-bright); }
.review-more__toggle::after { content: "Weiterlesen ▾"; }
.review-more[open] .review-more__toggle::after { content: "Weniger anzeigen ▴"; }

/* --- Preisstufen (Standard / Komfort / Premium) ---------------------------
   Drei Karten nebeneinander, aufsteigend. Die mittlere (Komfort) ist die
   hervorgehobene Glanz-Schwarz-Karte mit "Beliebteste Wahl"-Kennzeichnung,
   damit sie ohne neue Akzentfarbe klar heraussticht — passend zum
   monochromen Design. Idee der Aufteilung vom Wettbewerber, Optik bewusst
   in Schwarz/Weiß gehalten. */
.price-tiers {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem;
  margin: 2.5rem 0 2rem;
  align-items: stretch;
}
.price-tier {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--white-mid);
  border-radius: 18px;
  padding: 2.2rem clamp(1.4rem, 2.4vw, 2rem) 2rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06);
}
/* Hervorgehobene mittlere Karte: Glanz-Schwarz, weiße Schrift, leicht
   angehoben und größer, damit sie wie beim Wettbewerber "vorne" steht. */
.price-tier--featured {
  color: var(--white-bright);
  border-color: transparent;
  background:
    linear-gradient(135deg, #000 0%, #000 30%, #232323 46%, #000 62%, #000 100%);
  box-shadow: 0 22px 50px rgba(0, 0, 0, 0.35);
  transform: scale(1.045);
  z-index: 2;
}
.price-tier__badge {
  position: absolute;
  top: -15px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  background: var(--white-bright);
  color: var(--black-matte);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.5rem 1.1rem;
  border-radius: 999px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.28);
}
.price-tier__name {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin: 0 0 1.1rem;
  color: var(--gray-700);
}
.price-tier--featured .price-tier__name { color: var(--gray-300); }
.price-tier__price {
  font-size: clamp(1.7rem, 3vw, 2.5rem);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: 0.01em;
  margin: 0;
}
.price-tier__unit {
  font-size: 0.9rem;
  color: var(--gray-700);
  margin: 0.5rem 0 0;
}
.price-tier--featured .price-tier__unit { color: var(--gray-300); }
.price-tier__features {
  list-style: none;
  margin: 1.6rem 0 2rem;
  padding: 1.5rem 0 0;
  border-top: 1px solid var(--white-mid);
  display: grid;
  gap: 0.85rem;
}
.price-tier--featured .price-tier__features { border-top-color: rgba(255, 255, 255, 0.2); }
.price-tier__features li {
  position: relative;
  padding-left: 1.7rem;
  font-size: 0.98rem;
  line-height: 1.45;
}
.price-tier__features li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 700;
}
/* Button unten bündig ausrichten, Karten gleich hoch wirken lassen. */
.price-tier .btn {
  margin-top: auto;
  width: 100%;
  align-self: stretch;
  text-transform: none;
  text-align: center;
}
.price-tier .btn__label { text-transform: none; }

/* Startseiten-Preis-Karussell: alle Varianten (Komplettsanierung +
   Dachgeschoss) in EINEM 3D-Stapel — nutzt dieselbe Mechanik wie die
   Bewertungen/.about-carousel (js/testimonial-stack.js), inkl. automatisch
   erzeugter Pfeile/Punkte. Karten sehen aus wie die Preis-Karten der
   Unterseiten: weiß; die Komfort-Karten glänzend schwarz mit Fähnchen. */
.testimonial-stack.price-carousel { max-width: 560px; }
.testimonial-stack__card.price-carousel__slide {
  background: var(--white);
  color: var(--ink);
  border: 1px solid var(--white-mid);
  padding: 2.3rem 1.9rem 2.5rem;
}
.testimonial-stack__card.price-carousel__slide--featured {
  background:
    linear-gradient(135deg, transparent 4%, rgba(255,255,255,0.07) 10%, transparent 16%),
    linear-gradient(135deg, transparent 78%, rgba(255,255,255,0.07) 84%, transparent 90%),
    linear-gradient(135deg, #000 0%, #000 30%, #262626 46%, #000 62%, #000 100%);
  color: var(--white-bright);
  border-color: transparent;
}
/* kleiner Dienst-Titel oben auf jeder Karte (Komplettsanierung / Dachgeschoss) */
.price-carousel__service {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gray-500);
  margin: 0 0 1rem;
}
.price-carousel__slide--featured .price-carousel__service { color: var(--gray-300); }
/* Fähnchen sitzt im Stapel INNEN (Karte hat overflow:hidden, ein
   überstehendes Fähnchen würde abgeschnitten). */
.price-carousel__slide .price-tier__badge {
  position: static;
  transform: none;
  display: inline-block;
  margin: 0 0 1rem;
}
/* Weiße Standard-/Premium-Karten nutzen die dunklen Default-Farben der
   .price-tier__*-Klassen. Auf der glänzend schwarzen Komfort-Karte auf
   helle Töne umstellen. */
.price-carousel__slide--featured .price-tier__name,
.price-carousel__slide--featured .price-tier__unit { color: var(--gray-300); }
.price-carousel__slide--featured .price-tier__features { border-top-color: rgba(255,255,255,0.2); }
.price-carousel__slide > .btn {
  align-self: stretch;
  width: 100%;
  margin-top: auto;
  text-transform: none;
  text-align: center;
  justify-content: center;
}
.price-carousel__slide .btn__label { text-transform: none; }

/* --- Globaler "Mehr lesen"-Aufklapper (sitesweit) --------------------- */
/* Wiederverwendbar ueberall, wo viel Text komprimiert werden soll (Vorteile,
   Dienstleistungen, FAQ, lange Textbloecke). Titel bleibt sichtbar, die
   Erklaerung liegt hinter einem Button, der aussieht wie ein normaler .btn
   (gleicher Weiss-zu-Schwarz-Lichtkegel) -> sitesweit einheitlich klar,
   dass man hier tippen kann. Markup:
     <details class="more">
       <summary><span class="more__toggle"></span></summary>
       <div class="more__body"> ...Text... </div>
     </details>  */
details.more > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  -webkit-tap-highlight-color: transparent;
}
details.more > summary::-webkit-details-marker { display: none; }
.more__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.7rem 1.5rem;
  border-radius: 6px;
  background: radial-gradient(ellipse 75% 100% at center, #fff 0%, #fff 28%, #1a1a1a 78%, #000 100%);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.22), 0 2px 6px rgba(0, 0, 0, 0.18);
  color: #111;
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
details.more > summary:hover .more__toggle {
  box-shadow: 0 18px 32px rgba(0, 0, 0, 0.28), 0 4px 10px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
}
.more__toggle::before { content: "Mehr lesen"; }
details.more[open] .more__toggle::before { content: "Weniger anzeigen"; }
.more__toggle::after {
  content: "\25BE"; /* ▾ */
  display: inline-block;
  transition: transform 0.25s ease;
}
details.more[open] .more__toggle::after { transform: rotate(180deg); }
.more__body { margin-top: 1rem; }

@media (max-width: 860px) {
  /* Unterseiten: Preis-Karten werden auf dem Handy zum Wisch-Karussell
     (statt gestapelt) — Reihenfolge Komfort → Premium → Standard. */
  .price-tiers {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 1rem;
    margin-left: calc(-1 * var(--pad));
    margin-right: calc(-1 * var(--pad));
    padding: 1.4rem var(--pad) 0.6rem;
    scroll-padding: 0 var(--pad);
  }
  .price-tiers > .price-tier {
    flex: 0 0 84%;
    scroll-snap-align: center;
    transform: none;
  }
  .price-tiers > .price-tier:nth-child(1) { order: 3; } /* Standard zuletzt */
  .price-tiers > .price-tier:nth-child(2) { order: 1; } /* Komfort zuerst */
  .price-tiers > .price-tier:nth-child(3) { order: 2; } /* Premium in der Mitte */
}

/* --- Ablauf in 4 Schritten (Prozess) --------------------------------------
   Nummerierte Schritte mit Foto (Idee vom Wettbewerber, monochrom gehalten):
   Desktop 4 Spalten mit gestrichelter Verbindungslinie hinter den Nummern,
   auf dem Handy sauber gestapelt. */
.process-steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.75rem;
  margin-top: 2.8rem;
}
.process-step {
  position: relative;
  text-align: center;
  display: flex;
  flex-direction: column;
}
.process-step__num {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: linear-gradient(135deg, #000 0%, #000 30%, #262626 46%, #000 62%, #000 100%);
  color: var(--white-bright);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  font-weight: 500;
  margin: 0 auto 1.4rem;
  position: relative;
  z-index: 1;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
}
/* Animierte "Straße" von Nummer zu Nummer: laufende schwarz/weiße Striche
   (wie Fahrbahnmarkierung von Punkt A nach B). Die opaken Nummern-Kreise
   (z-index:1) überdecken die Strich-Enden sauber. */
.process-step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 27px;
  left: 50%;
  width: calc(100% + 1.75rem);
  height: 4px;
  transform: translateY(-50%);
  border-radius: 4px;
  background-color: #d7d7d3;
  background-image: repeating-linear-gradient(
    90deg,
    #0d0d0d 0 15px,
    transparent 15px 22px,
    #ffffff 22px 37px,
    transparent 37px 44px
  );
  animation: process-road 1.1s linear infinite;
  z-index: 0;
}
@keyframes process-road {
  to { background-position-x: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .process-step:not(:last-child)::before { animation: none; }
}
/* Ablauf-Fläche leicht grau statt reinweiß (Nutzerwunsch "zu viel weiß") */
section:has(> .section__inner > .process-steps) { background: #ededeb; }
.process-step__title {
  font-size: 1rem;
  margin: 0 0 0.7rem;
}
.process-step__text {
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--gray-700);
  margin: 0 0 1.4rem;
}
.process-step__media {
  margin-top: auto;
  border-radius: 12px;
  overflow: hidden;
}
.process-step__media img {
  display: block;
  width: 100%;
  height: 210px;
  object-fit: cover;
}
@media (max-width: 860px) {
  /* Handy: Ablauf als horizontales Wisch-Karussell — die "Straße" bleibt
     horizontal und läuft von Karte zu Karte weiter, während man wischt. */
  .process-steps {
    grid-template-columns: none;
    display: flex;
    gap: 1.1rem;
    max-width: none;
    margin-left: calc(var(--pad) * -1);
    margin-right: calc(var(--pad) * -1);
    padding: 0.4rem var(--pad) 0.8rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .process-steps::-webkit-scrollbar { display: none; }
  .process-step {
    flex: 0 0 78%;
    scroll-snap-align: center;
  }
  .process-step:not(:last-child)::before { width: calc(100% + 1.1rem); }
}

/* --- Projekt-Karussell: kompaktes Vorher/Nachher + Projektdaten ------------
   Kleiner Vorher/Nachher-Regler (statt Vollbild) als 3D-Stapel wie die
   übrigen Karussells; darunter die Projektdaten (Fläche, Zeit, Art, Stadt) —
   Datenraster nach Vorbild des Wettbewerbers, monochrom. Das Karussell-
   Wischen ignoriert Gesten, die auf einem .ba-slider starten (siehe
   js/testimonial-stack.js), damit der Regler-Griff normal ziehbar bleibt. */
.testimonial-stack.project-carousel { max-width: 560px; }
.testimonial-stack__card.project-carousel__slide {
  background: #e7e7e4;
  color: var(--ink);
  border: 1px solid #d6d6d2;
  padding: 0 0 1.6rem;
}
.project-carousel__slide .ba-slider {
  margin: 0;
  box-shadow: none;
}
/* Leichte schwarze Unterkante + minimaler Rundum-Schatten auf den
   Vorher/Nachher-Bildern (wie früher bei den großen .ba-hero-Reglern).
   pointer-events:none, damit der Regler klick-/wischbar bleibt; z-index
   unter Griff (4), Regler (3) und Trennlinie. */
.project-carousel__slide .ba-slider::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* Weicher dunkler Übergang zur Unterkante — wie beim großen .ba-hero-Block. */
  background: linear-gradient(to bottom, transparent 50%, rgba(0, 0, 0, 0.32) 76%, rgba(0, 0, 0, 0.6) 100%);
  box-shadow: inset 0 0 34px rgba(0, 0, 0, 0.28);
}
/* Einzelnes Projekt (z.B. Bad-Sanierung Espelkamp): lone Karte auf dem PC
   nicht schmal links im 3er-Raster hängen lassen, sondern mittig zeigen. */
@media (min-width: 861px) {
  .project-carousel:has(.project-carousel__slide:only-child) .testimonial-stack__card[data-pos="0"] {
    position: relative;
    left: auto;
    transform: none;
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
  }
  .project-carousel:has(.project-carousel__slide:only-child) { max-width: 520px; margin-left: auto; margin-right: auto; }
}
/* Fixer Rahmen um den Regler (per JS gewrappt, siehe wrapProjectSlidersInFrame
   in lightbox.js): schneidet den Fokus-Zoom ab, damit das Bild nach innen
   zoomt statt über die Projektdaten darunter zu wachsen. */
.ba-zoom-frame {
  position: relative;
  overflow: hidden;
  border-radius: 16px 16px 0 0;
}
/* "Vorher"/"Nachher"-Beschriftung auf dem Bild ist überflüssig — man sieht
   am Regler sofort, was Vorher und Nachher ist. Nur im Projekt-Karussell weg
   (die großen Einzel-Regler auf den Leistungsseiten behalten sie). */
.project-carousel__slide .ba-slider__label { display: none; }
.project-carousel__body { padding: 1.4rem 1.7rem 0; }
/* Redundante "Vorher & Nachher"-Überschrift über dem Projekttitel entfernt. */
.project-carousel__body .eyebrow { display: none; }
.project-carousel__title { font-size: 1.15rem; margin: 0.35rem 0 1rem; }
.project-carousel__data { list-style: none; margin: 0; padding: 0; }
.project-carousel__data li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--white-mid);
  font-size: 0.98rem;
}
.project-carousel__data li:last-child { border-bottom: none; }
.project-carousel__data .label { color: var(--gray-700); }
.project-carousel__data .value { font-weight: 600; text-align: right; }

/* Foto-Karussell-Beschriftung, Variante 2:
   1) Projekt-Titel als Overlay UNTEN auf dem Bild (per JS auf der vordersten
      Karte, siehe js/testimonial-stack.js -> .pc-caption).
   2) Fakten-Streifen (Flaeche/Zeit/Kunde) direkt UNTER dem Karussell. */
.pc-caption {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  border-radius: inherit;
  overflow: hidden;
}
/* Angaben links oben, senkrecht -- KEIN abgedunkelter Hintergrund, das Bild
   bleibt zu 100% sichtbar; Lesbarkeit nur ueber kraeftigen Textschatten
   (wie im Hero auf der Startseite). */
.pc-caption__facts {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  padding: 1.5rem 1.6rem;
  max-width: 70%;
}
.pc-caption__l {
  display: block;
  color: #fff;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 0.1rem;
  opacity: 0.92;
  text-shadow: 0 1px 3px rgba(0,0,0,0.85), 0 2px 10px rgba(0,0,0,0.75);
}
.pc-caption__v {
  display: block;
  color: #fff;
  font-weight: 700;
  font-size: clamp(1.02rem, 2vw, 1.2rem);
  text-shadow: 0 1px 3px rgba(0,0,0,0.9), 0 2px 12px rgba(0,0,0,0.85);
}
/* Titel unten -- bleibt mit weichem Verlauf. */
.pc-caption__title {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 2.4rem 1.5rem 1.3rem;
  background: linear-gradient(to top, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.4) 55%, transparent 100%);
  color: #fff;
  font-size: clamp(1.05rem, 2.4vw, 1.4rem);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  line-height: 1.25;
  text-shadow: 0 2px 12px rgba(0,0,0,0.6);
}

/* Auf dem PC zeigen Preis- UND Projekt-Karussell DREI volle Karten
   nebeneinander (statt einer großen + kleinen Guck-Karten mit viel
   Weißraum rechts). Geblättert wird mit Pfeilen/Punkten – dann rückt das
   Dreier-Fenster eins weiter. Technik bleibt der 3D-Stapel, nur die
   Positionen 0/1/2 werden flach und gleich groß nebeneinandergelegt, alles
   dahinter ist ausgeblendet. Auf dem Handy bleibt das Wischen wie es ist. */
@media (min-width: 861px) {
  .testimonial-stack.price-carousel,
  .testimonial-stack.project-carousel {
    max-width: 1120px;
    padding-right: 0;
    perspective: none;
  }
  .price-carousel .testimonial-stack__card,
  .project-carousel .testimonial-stack__card {
    width: 32%;
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.14);
  }
  .price-carousel .testimonial-stack__card[data-pos="0"],
  .project-carousel .testimonial-stack__card[data-pos="0"] {
    transform: translate3d(0, 0, 0);
    opacity: 1;
    pointer-events: auto;
  }
  .price-carousel .testimonial-stack__card[data-pos="1"],
  .project-carousel .testimonial-stack__card[data-pos="1"] {
    transform: translate3d(106%, 0, 0);
    opacity: 1;
    pointer-events: auto;
    cursor: default;
  }
  .price-carousel .testimonial-stack__card[data-pos="2"],
  .project-carousel .testimonial-stack__card[data-pos="2"] {
    transform: translate3d(212%, 0, 0);
    opacity: 1;
    pointer-events: auto;
    cursor: default;
  }
  .price-carousel .testimonial-stack__card[data-pos="3"],
  .price-carousel .testimonial-stack__card[data-pos="rest"],
  .price-carousel .testimonial-stack__card[data-pos="prev"],
  .project-carousel .testimonial-stack__card[data-pos="3"],
  .project-carousel .testimonial-stack__card[data-pos="rest"],
  .project-carousel .testimonial-stack__card[data-pos="prev"] {
    opacity: 0;
    pointer-events: none;
  }
  /* Alle Karten im Dreier-Fenster gleich hoch, damit Unterkanten und
     Buttons bündig stehen (Karten sind je nach Inhalt unterschiedlich hoch).
     Wert knapp über der höchsten Karte; min-height wächst bei Bedarf mit,
     schneidet also nie Inhalt ab. */
  .price-carousel .testimonial-stack__card { min-height: 725px; }
  .project-carousel .testimonial-stack__card { min-height: 625px; }
}
