/* ============================================================================
   Levante Service GmbH — projekteigene Gestaltungsschicht
   Richtung „Die freie linke Seite" (siehe .factory/entwuerfe.md)

   Ein Gedanke traegt die Seite: Text steht in der hellen Zone eines Fotos.
   Ein Motiv zieht sich durch: die Giebellinie — eine haarfeine Limettenlinie,
   die einmal zu einem Dach ausschlaegt.

   Farben ausschliesslich ueber Tokens. Petrol = --accent (aus site.json),
   Limette = --accent-2. Keine Hex-Werte in den Bloecken.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. Tokens — Corporate Design der Marke
   ------------------------------------------------------------------------ */
:root {
  /* Styleguide-Werte. --accent (#005a82) und --accent-2 (#cdcd00) setzt
     head.php inline aus site.json; hier die uebrigen Toene des CD. */
  --petrol-tief:  #00405d;   /* dunkles Band, Abbinder */
  --hellblau:     #579ed6;   /* Zwischenton, nie Text */
  --planblau:     #e2ebf9;   /* ruhiger Sektionswechsel */
  --creme:        #f5f5d8;
  --hellgelb:     #e5e598;
  --lesegrau:     #2b3338;   /* 12,9:1 auf Weiss */
  --lesegrau-mut: #55606a;   /*  6,4:1 auf Weiss */

  /* Semantik umhaengen: Weiss traegt, Petrol fuehrt, Grau liest. */
  --bg:        #ffffff;
  --surface:   #ffffff;
  --surface-2: var(--planblau);
  --surface-3: var(--creme);
  --fg:        var(--lesegrau);
  --fg-muted:  var(--lesegrau-mut);
  --fg-subtle: var(--lesegrau-mut);
  --border:        color-mix(in srgb, var(--accent) 15%, #fff);
  --border-strong: color-mix(in srgb, var(--accent) 32%, #fff);

  /* Typografie: Mukta in drei Schnitten. Der Kontrast entsteht ueber Groesse
     und Gewicht, nicht ueber eine zweite Familie. */
  --display-weight: 400;              /* Mukta Regular traegt die Ueberschriften */
  --display-tracking: -0.012em;       /* Mukta ist eng genug; -0.035em waere Matsch */
  --leading-tight: 1.08;
  --leading-normal: 1.68;

  /* Weiche, aber nicht runde Formen — kein Broadsheet-Radius-0, keine Pillen. */
  --radius-sm: 3px;
  --radius-md: 4px;
  --radius-lg: 6px;
  --radius-xl: 8px;
  --btn-radius: 4px;

  --card-shadow: none;
  --card-shadow-hover: none;
  --elevation-hero: none;

  /* Grosszuegiger Rhythmus — die Seite darf atmen. */
  --section-pad: clamp(4.5rem, 9vw, 9rem);
  --section-pad-tight: clamp(3rem, 5vw, 4.5rem);
  --container: 78rem;
  /* Die Lesespur ist an der SCHRIFT bemessen, nicht am Raster: 44rem ergaben in
     Mukta Light rund 104 Zeichen je Zeile — beim Zeilenwechsel verliert das Auge
     dann die naechste Zeile. 34rem landen bei knapp 80. */
  --container-narrow: 34rem;

  /* Die senkrechte Fluchtlinie: der Textsatz haengt seitenweit an EINER Achse. */
  --achse: clamp(1.1rem, 4vw, 2rem);
}

/* Fokus sichtbar und markengerecht. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Deutsche Komposita nie mitten im Wort brechen. */
h1, h2, h3, .display, .claim {
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
  text-wrap: balance;
}

body { font-weight: 300; }            /* Mukta Light traegt den Fliesstext */
p, li { font-weight: 300; }
strong, b { font-weight: 600; }

.lead {
  font-size: var(--step-1);
  font-weight: 300;
  line-height: 1.6;
  color: var(--lesegrau);
  max-width: 34ch;
}

/* Das Sektionslabel — eine haengende Zeile, KEIN gesperrtes Versal-Chip.
   Das gesperrte Versal-Label zitierte zwar die Wortmarke „SERVICE", stand aber
   auf jeder Seite mehrfach als kleines Etikett ueber einer Ueberschrift — genau
   die Form, die jede Baukastenseite benutzt, und in Versalien ohne Wortsilhouette
   auch schlechter lesbar. Die Sperrung bleibt der Wortmarke und der Taktzeile
   vorbehalten; hier traegt die Limettenlinie die Auszeichnung, der Text liest
   sich normal. */
.eyebrow {
  font-weight: 600;
  font-size: var(--step-0);
  letter-spacing: 0.005em;
  line-height: 1.3;
  color: var(--accent);
  text-transform: none;
}
.eyebrow::before {
  background: var(--accent-2);
  height: 2px;
  width: 1.4rem;
  align-self: center;
  flex: none;
}

/* ---------------------------------------------------------------------------
   2. Die Giebellinie — die Signatur der Seite
   Eine Haarlinie, die einmal zu einem Dach ausschlaegt. Reduktion des
   Logo-Signets auf einen einzigen Strich. Zeichnet sich beim Scrollen selbst
   (effects.css, data-sda="draw"); Ruhezustand ist die FERTIGE Linie.
   ------------------------------------------------------------------------ */
.giebel {
  display: block;
  width: var(--giebel-breite, 8.5rem);
  height: auto;
  color: var(--accent-2);
  overflow: visible;
}
.giebel--breit { --giebel-breite: 14rem; }
.giebel--hell  { color: var(--accent-2); }

/* Auf Petrolgrund bleibt die Limette die Limette — dort traegt sie 4,43:1
   und wird ohnehin nur als Linie eingesetzt. */
.abbinder .giebel { color: var(--accent-2); }

/* ---------------------------------------------------------------------------
   3. Kopfbereich — liegt transparent ueber dem Foto, wird beim Scrollen fest
   Ausgangszustand (und Zustand ohne Unterstuetzung) ist der SICHERE: weiss.
   ------------------------------------------------------------------------ */
.site-header {
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  backdrop-filter: none;
}
.site-header .header-inner { padding-block: 0.85rem; gap: var(--space-md); }

.brand__logo { height: 2.9rem; max-width: 15rem; }
/* Auf dem Foto braucht die Wortmarke Kontrast, ohne Kasten: ein weicher weisser
   Lichthof um die Striche. drop-shadow folgt der Kontur des SVG, nicht dem
   Rechteck des Bildes. Auf weissem Grund (Desktop-Lichtzone, gescrollter Kopf)
   ist Weiss auf Weiss unsichtbar — deshalb kein Zustandswechsel, der flackern
   koennte. */
body.hat-buehne .brand__logo {
  filter: drop-shadow(0 0 1px rgb(255 255 255 / 0.95))
          drop-shadow(0 0 5px rgb(255 255 255 / 0.9))
          drop-shadow(0 0 14px rgb(255 255 255 / 0.75));
}

/* Der Kopf faehrt als Ganzes von oben herein — und erst, wenn das Logo da ist.
   base.css blendet Logo, Navigation und Knopf einzeln ab dem ersten
   Bildaufbau ein; das Logo ist aber ein nachgeladenes SVG und kam als letztes
   Teil einzeln nachgesprungen (Kunde, 2026-09-25). Jetzt: solange das Logo
   nicht geladen ist (is-loaded, gesetzt per onload in render.php), steht der
   ganze Kopf oberhalb des Bildschirms; sobald es da ist, faehrt er in einer
   Bewegung herein. Die Einzel-Einblendungen aus base.css sind bis dahin
   angehalten (animation-play-state) und laufen dann als Nachklang; das Logo
   selbst bekommt keine mehr, es faehrt mit. Auch der Buehnentext wartet auf
   diesen Moment, damit die Seite sich in EINER Bewegung oeffnet statt in zwei.

   Schlaegt das Laden fehl, entfernt onerror das Bild und kein :has() greift
   mehr — der Kopf steht sofort. Ohne :has()-Unterstuetzung (alte Browser),
   ohne JavaScript und bei reduced-motion steht alles sofort da. */
@media (prefers-reduced-motion: no-preference) {
  html.js body[data-header-reveal] .site-header:has(.brand__logo:not(.is-loaded)) {
    opacity: 0;
    transform: translateY(-100%);
  }
  html.js body[data-header-reveal] .site-header:has(.brand__logo.is-loaded) {
    animation: kopf-herein 0.85s var(--ease-out, cubic-bezier(.2,.85,.25,1)) both;
  }
  /* `to` endet auf `none`, nicht auf translateY(0): ein bleibender transform
     wuerde den fixen Kopf zum Bezugsrahmen des fixen Mobilmenues machen. */
  @keyframes kopf-herein {
    from { opacity: 0; transform: translateY(-100%); }
    to   { opacity: 1; transform: none; }
  }
  html.js body[data-header-reveal] .brand__logo { animation: none; }
  /* Ausdruecklich das Logo IM KOPF: im Fuss steht ein zweites, das per
     loading="lazy" erst beim Scrollen laedt — darauf darf nichts warten. */
  html.js body[data-header-reveal]:has(.site-header .brand__logo:not(.is-loaded)) .nav__link,
  html.js body[data-header-reveal]:has(.site-header .brand__logo:not(.is-loaded)) .header-actions,
  html.js body[data-header-reveal]:has(.site-header .brand__logo:not(.is-loaded)) .buehne__inhalt > * {
    animation-play-state: paused;
  }
}
.site-footer .brand__logo { height: 4.2rem; max-width: 19rem; }

/* Der Markenname steht im Markenlink ZWEIMAL: einmal als alt-Text des Logos,
   einmal als zusaetzlicher visually-hidden-Schriftzug (render.php::brand_lockup).
   Ein Screenreader liest ihn dadurch doppelt, und weil `.brand` relativ
   positioniert ist, liegt der unsichtbare Schriftzug geometrisch genau unter dem
   Logo — die Pruefung meldet ihn folgerichtig als zu 40 % verdeckten Text.
   Er bleibt fuer den einen Fall stehen, fuer den er gedacht war: laedt das Logo
   nicht, entfernt onerror das <img>, `:has()` greift nicht mehr, und der
   Schriftzug traegt den Namen wieder allein. */
.brand:has(.brand__logo) > .visually-hidden { display: none; }

.nav__link {
  font-weight: 600;
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.nav__link::after { background: var(--accent-2); height: 2px; }
.nav__link:hover, .nav__link[aria-current="page"] { color: var(--accent); }
.nav__link[aria-current="page"]::after { width: 100%; }

.btn { font-weight: 600; letter-spacing: 0.04em; }
.btn--primary { --_bg: var(--accent); --_fg: var(--accent-ink); }
.btn:hover { transform: translateY(-1px); box-shadow: none; }
.btn--ghost {
  --_bg: transparent;
  --_fg: var(--accent);
  --_bd: var(--border-strong);
}
.btn--ghost:hover { --_bg: transparent; --_bd: var(--accent); }

/* Auf Seiten mit Fotobuehne liegt der Kopfbereich TRANSPARENT auf dem Foto,
   nicht als weisse Leiste davor. Dafuer muss er aus dem Fluss: `sticky` wuerde
   oben ein 79 px hohes weisses Band reservieren und das Bild erst darunter
   beginnen lassen — genau die harte Kante, die die Buehne kaputtmacht.
   Grund unter den Fuessen gibt der obere Schleier der Buehne (Abschnitt 4).
   Sobald gescrollt wird, bekommt der Kopf seine Flaeche zurueck; `data-scrolled`
   setzt motion.js. Ohne JavaScript (html ohne .js) bleibt er von Anfang an
   gedeckt — der sichere Zustand. */
body.hat-buehne .site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  background: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: background var(--dur-base, 0.25s) var(--ease, ease),
              border-color var(--dur-base, 0.25s) var(--ease, ease);
}
html:not(.js) body.hat-buehne .site-header,
body.hat-buehne .site-header[data-scrolled] {
  background: color-mix(in srgb, #fff 88%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-bottom-color: var(--border);
}
/* Beim Losscrollen deckt der Kopf SOFORT (motion.js setzt data-scrolled ab
   dem ersten Pixel); nur zurueck nach oben blendet er weich aus. Mit der
   Blende auch auf dem Hinweg schien bei schnellem Wischen das Foto fuer die
   Viertelsekunde durch den halb durchsichtigen Kopf — dunkel, dann weiss. */
body.hat-buehne .site-header[data-scrolled] { transition: none; }

/* Bei geoeffnetem Menue bekommt der Kopf seine Flaeche sofort zurueck — sonst
   haengt die weisse Menueflaeche unter einem durchsichtigen Streifen, durch den
   das Foto scheint. */
body.hat-buehne .site-header:has(.nav.is-open) {
  background: var(--bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* `motion.stickyMark` (site.json) schaltet nur den Zustandswechsel oben ein.
   Das Schrumpfen von Logo und Leiste, das effects.css daran haengt, gehoert
   nicht dazu: die Wortmarke steht hier ohnehin klein, und eine Leiste, die beim
   ersten Scrollen die Hoehe wechselt, springt. Der Kopf wechselt die FARBE,
   nicht die Groesse. */
.site-header[data-scrolled] { box-shadow: none; }
.site-header[data-scrolled] .header-inner { min-height: 0; }
.site-header[data-scrolled] .brand__logo { height: 2.9rem; }
@media (max-width: 820px) {
  .site-header[data-scrolled] .brand__logo { height: 2.5rem; }
}

/* ---------------------------------------------------------------------------
   4. Die Fotobuehne — der eine Gedanke der Seite

   Ab 900 px EINE Komposition: das Foto liegt randlos ueber der vollen Flaeche,
   der Kopfbereich transparent darauf, der Text in der hellen Zone des Motivs.

   Darunter eine eigene Komposition mit demselben Kopf: er liegt weiter
   transparent auf dem Foto (Wunsch des Kunden, 2026-09-25), das Foto beginnt
   als randloses Band an der Oberkante der Seite und ist um die Kopfhoehe
   laenger, damit Schluessel und Gesicht nicht unter Logo und Menueknopf
   liegen; darunter der Text auf Weiss. Der Grund fuer das Band ist das Motiv
   selbst: die vier Buehnenfotos sind 2,24:1-Panoramen mit dem Menschen am
   rechten Rand. Unter `object-fit: cover` blieb davon auf 390 px nur der
   Schluessel in der Bildmitte — die Frau war weggeschnitten —, und ein bis zur
   Mitte reichender Textschleier liess vom Rest ein ausgewaschenes Drittel
   uebrig. Jetzt liefert render.php unter 700 px den hochformatigen Zuschnitt
   (`mobil` in site.json, 900x1200 mit Schluessel UND Gesicht), das Band zeigt
   ihn fast ganz; oben liegt nur ein kurzer Schleier unter dem Kopf, unten
   loest sich der Rand in den Text auf. Kein Kasten, kein Balken.

   Ein erster Anlauf mit Band war 2026 an genau dem Panorama gescheitert (ein
   Achtel Bildschirmhoehe Streifen); die Hoehe des Bands haengt deshalb an der
   Breite (92vw = der 3:4-Zuschnitt bis kurz unter den Anhaenger), nicht am
   Seitenverhaeltnis des Panoramas.
   ------------------------------------------------------------------------ */
.buehne {
  /* Mindesthoehe des Fotobands mobil: der sichtbare Teil (92vw = der
     3:4-Zuschnitt bis kurz unter den Anhaenger) plus die Kopfhoehe, die der
     fixe Kopf oben ueberdeckt — dieselben 73 px, an denen in Abschnitt 20 das
     Menue haengt. */
  --kopf-h: 4.5625rem;
  --band: calc(clamp(17rem, 92vw, 26rem) + var(--kopf-h));
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* Zwei Zeilen: oben das Band, unten der Text. Die Buehne fuellt mobil immer
     den ganzen Bildschirm (Kundenwunsch, 2026-09-25); was ueber Band-Minimum
     und Text hinaus an Hoehe da ist, bekommt das Band — auf einem hohen
     Handy ist so mehr vom Zuschnitt zu sehen, nie mehr Leere. svh statt vh:
     die kleine Viewport-Hoehe, damit die Buehne unter der eingeblendeten
     Browserleiste nicht ueber den Rand ragt und beim Scrollen nicht springt. */
  grid-template-rows: minmax(var(--band), 1fr) auto;
  min-height: 100svh;
  isolation: isolate;
}

.buehne__bild {
  grid-area: 1 / 1;
  position: relative;
  z-index: -2;
  overflow: hidden;
  background: var(--planblau);
  /* Das Foto endet 1 px ueber dem Schleier. Die Bandhoehe ist krumm (92vw,
     svh), ihre Unterkante faellt mitten in ein Geraetepixel. Chrome malt das
     Foto dort anteilig hinein, den Schleier aber auf ganze Pixel gerundet —
     die letzte Pixelzeile blieb ungedeckt und stand als feiner grauer Strich
     zwischen Band und Claim (gemessen bei 1,25x und 2,625x, Kunde 2026-10-01).
     So liegt die angeschnittene Zeile unter dem deckenden Weiss. */
  margin-bottom: 1px;
}
.buehne__bild img {
  /* Absolut, damit die Bildhoehe die Rasterzeile nicht aufblaeht: die Zeile
     bestimmt die Hoehe, das Foto fuellt sie per cover. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--bild-pos, 62% center);
  display: block;
}
@media (max-width: 700px) {
  /* Hier kommt der Hochformat-Zuschnitt (render.php, <source media>). Sein
     Motiv sitzt oben — Hand, Schluessel, Gesicht —, der untere Rand (Pullover,
     Tischkante) darf unter dem Schleier verschwinden. */
  .buehne__bild img { object-position: var(--bild-pos-mobil, 50% 0); }
}

.buehne__schleier {
  grid-area: 1 / 1;
  position: relative;
  z-index: -1;
  /* KEIN pointer-events: none. Der Schleier liegt hinter dem Inhalt (z-index -1)
     und faengt daher nichts ab, was der Besucher anklicken will — aber
     elementsFromPoint() UEBERSPRINGT alles mit pointer-events: none, und genau
     darueber sucht die Kontrastmessung des Detektors den Untergrund. Mit der
     Eigenschaft war der Schleier fuer sie unsichtbar und sie las die nackten
     Bildpixel (1,2:1 fuer den Titel, den man in Wahrheit auf fast Weiss liest). */
  /* Mobil zwei kurze Schleier an den Raendern des Bands, die Mitte — Schluessel,
     Anhaenger, Gesicht — bleibt nackt. Oben gibt er dem transparenten Kopf
     Grund unter den Fuessen: kraeftig nur in den 73 px des Kopfes, darunter
     rasch ausgelaufen, damit der Schluesselbart nicht mitgewaschen wird.
     Unten beginnt der Text erst dort, wo der Verlauf schon ueber 0,9 deckt
     (siehe margin-top von .buehne__inhalt). Beide Verlaeufe in rem, nicht in
     Prozent: das Band waechst mit der Bildschirmhoehe, der Auslauf soll es
     nicht. */
  /* Dazu ein heller Fleck in der linken oberen Ecke, wo die Wortmarke steht:
     mobil liegt sie auf Hand und Schluesselkopf und verschwamm dort (Kunde,
     2026-09-25). Die Ellipse deckt Logo und Schluesselkopf, laeuft nach rechts
     vor dem Gesicht und nach unten vor dem Anhaenger aus. */
  background:
    radial-gradient(ellipse 22rem 9rem at 0 0, rgb(255 255 255 / 0.92) 0,
                    rgb(255 255 255 / 0.6) 45%, rgb(255 255 255 / 0) 100%),
    linear-gradient(to bottom, rgb(255 255 255 / 0.78) 0, rgb(255 255 255 / 0.55) var(--kopf-h),
                    rgb(255 255 255 / 0) calc(var(--kopf-h) + 3rem)),
    linear-gradient(to top, #fff 0, #fff 2rem, rgb(255 255 255 / 0.92) 4rem,
                    rgb(255 255 255 / 0.55) 6.75rem, rgb(255 255 255 / 0) 9.5rem);
}

.buehne__inhalt {
  grid-area: 2 / 1;
  /* Der Text beginnt 3,25 rem ueber der Bandunterkante — im weissen Teil des
     Verlaufs. Der negative Rand zieht die zweite Rasterzeile in die erste. */
  margin-top: -3.25rem;
  padding-block: 0 clamp(2.25rem, 5vw, 3.5rem);
  display: grid;
  gap: clamp(0.9rem, 2vw, 1.4rem);
  justify-items: start;
}
/* Unter 560 px passen die beiden Knoepfe nicht nebeneinander. Zwei verschieden
   breite Knoepfe untereinander sehen aus wie eine Liste; in voller Breite
   stehen sie als Paar. */
@media (max-width: 559px) {
  .buehne .btn-group {
    display: grid;
    grid-template-columns: 1fr;
    justify-self: stretch;
  }
}

.buehne h1 {
  /* Der vw-Anteil ist die Sicherung: er haelt auch das laengste deutsche
     Kompositum („Ansprechpartnerin.", 18 Zeichen) innerhalb des Satzspiegels.
     Ohne ihn drueckt ein einziges unbrechbares Wort das ganze Raster ueber den
     Geraeterand — Komposita duerfen hier nicht getrennt werden (Abschnitt 1). */
  font-size: clamp(2.1rem, 10.4vw, 4.25rem);
  font-weight: 400;
  line-height: var(--leading-tight);
  color: var(--accent);
  margin: 0;
  max-width: 15ch;
}
.buehne .lead { max-width: 38ch; }
.buehne .btn-group { margin-top: 0.4rem; }
/* Auf dem hellen Foto braucht der sekundaere Knopf eine sichtbare Kante — die
   zarte Standardlinie verschwindet dort.

   Und einen eigenen Grund: seine Beschriftung ist 16 px und damit KEIN grosser
   Text, sie braucht 4,5:1. Der Knopf steht aber weiter rechts als die Zeilen
   darueber, dort wo der Schleier schon ausgelaufen ist — nachgemessen standen
   bei 1000 px Fensterbreite 3,3:1 auf dem nackten Motiv. Statt den Schleier fuer
   diesen einen Knopf ueber das halbe Bild zu ziehen, traegt er seine Deckung
   selbst; sichtbar wird das kaum, weil er ohnehin in der hellen Zone steht. */
.buehne .btn--ghost {
  --_bd: color-mix(in srgb, var(--accent) 55%, transparent);
  background: rgb(255 255 255 / 0.78);
}
.buehne .btn--ghost:hover { --_bd: var(--accent); background: rgb(255 255 255 / 0.92); }

/* Der Kopf bleibt in jeder Breite der fixe, transparente aus Abschnitt 3. Ein
   Zwischenstand vom 2026-09-25 hatte ihn unter 900 px als weisse Leiste in den
   Fluss gestellt — der Kunde wollte ihn ueber dem Foto behalten. Seinen Grund
   unter den Fuessen bekommt er vom oberen Schleier des Bands (oben). */

/* Ab 900 px steht der Text mittig in der freigehaltenen linken Zone; Foto und
   Schleier fuellen wieder die ganze Buehne, der Schleier dreht sich mit und
   kommt von links statt von unten. */
@media (min-width: 900px) {
  /* Eine Zelle statt zwei Zeilen: Foto und Schleier liegen absolut ueber der
     ganzen Buehne, der Text darauf. */
  .buehne {
    grid-template-rows: auto;
    align-items: center;
    min-height: clamp(32rem, 82svh, 46rem);
  }
  .buehne__bild,
  .buehne__schleier { grid-area: 1 / 1; position: absolute; inset: 0; }
  /* Hier liegt unten kein weisser Schleier, das Foto reicht bis an den Rand. */
  .buehne__bild { margin-bottom: 0; }
  .buehne__inhalt { grid-area: 1 / 1; margin-top: 0; }
  .buehne__schleier {
    background:
      linear-gradient(to bottom, rgb(255 255 255 / 0.82) 0, rgb(255 255 255 / 0) 9rem),
      linear-gradient(to right, rgb(255 255 255 / 0.86) 0, rgb(255 255 255 / 0.6) 26%, rgb(255 255 255 / 0) 56%);
  }
  .buehne__inhalt {
    align-self: center;
    padding-block: clamp(5.5rem, 11vh, 8rem) clamp(3rem, 7vh, 5rem);
  }
  /* Nur der Textsatz bekommt die Lesebreite — die Knopfreihe nicht, sonst
     bricht sie mitten in der Zeile um und die beiden Knoepfe stehen
     untereinander wie eine Liste. Die Ausnahme steht als eigene Regel und
     nicht als :not() im Selektor: :not() hebt die Spezifitaet, und dann
     verliert `.buehne h1` seine eigene, engere Breite. */
  .buehne__inhalt > * { max-width: 46ch; }
  .buehne__inhalt > .btn-group { max-width: none; }
  .buehne h1 { max-width: 13ch; }
  /* Der Bildinhalt wird nach rechts gerueckt, damit er nicht unter die
     Schrift wandert. */
  .buehne__bild img { object-position: var(--bild-pos-gross, 74% center); }
}
@media (min-width: 1500px) {
  .buehne__bild img { object-position: var(--bild-pos-gross, 68% center); }
}

/* Die Startseiten-Buehne steht ab 900 px hoeher als die Koepfe der Unterseiten:
   sie ist der Auftritt der Seite und zeigt das Motiv fast ganz, waehrend
   Kontakt, Leistungen und Ueber uns weiter mit dem knapperen Kopf beginnen.
   Auf jedem quer stehenden Bildschirm fuellt sie das Fenster ganz (Kunde
   2026-10-07: der Streifen des naechsten Abschnitts unten soll weg — 92svh
   mit Deckel 58rem liess ihn auf jedem Full-HD-Fenster stehen). Nur ein
   hochkant gestellter Monitor behaelt den Deckel: dort schnitte cover vom
   2,24:1-Panorama bloss einen schmalen Streifen heraus, und die Buehne
   wuerde zur leeren Flaeche. */
@media (min-width: 900px) {
  body.seite-start .buehne { min-height: clamp(38rem, 92svh, 58rem); }
}
@media (min-width: 900px) and (min-aspect-ratio: 5/4) {
  body.seite-start .buehne { min-height: 100svh; }
}

/* Auf dem Handy zeigt die Startseite ihren QUADRATISCHEN Zuschnitt in voller
   Breite (Kunde 2026-10-05: so viel Foto wie moeglich). Unter cover zoomte er mit
   dem Band: das Band ist hoeher als breit und wuchs auf hohen Handys weiter
   (1fr), also blieb die volle Hoehe, aber die Breite schrumpfte — auf 430 px
   nur 77 %, die Hand mit dem Schluessel lag halb am Rand. Fuer die 3:4-
   Zuschnitte der Unterseiten ist das Wachsen richtig, fuer das Quadrat nicht.
   Jetzt ist das Foto so breit wie das Band und quadratisch, das Band genau
   3,25 rem hoeher: dort beginnt der Text, im fast deckenden Weiss des
   Schleiers. Die Unterkante des Fotos laeuft zusaetzlich selbst aus — der
   Schleier deckt dort erst 95 %, und der Rest stand als gerade Linie quer
   ueber dem Band (4 bis 6 Tonwerte, gemessen auf 430 px).
   Was ein hohes Handy an Hoehe uebrig hat, bekommt weiter das Band (1fr),
   aber UEBER dem Foto: das Foto rutscht um diesen Versatz nach unten und
   sitzt immer direkt auf dem Text. Ein erster Stand hatte den Rest um den
   Text verteilt — dann klebte das Foto oben unter Logo und Menue, darunter
   stand eine weisse Luecke (Kunde: „haengt so weit oben"). Der Versatz holt
   Kopf und Schluessel unter dem Kopf hervor; die Oberkante blendet ueber
   hoechstens 3 rem ein, sonst stuende sie als Kante im Weiss. Gedeckelt bei
   Kopfhoehe plus 2 rem: ein noch hoeheres Fenster soll oben keine leere
   Flaeche aufziehen. 700 px wie die <source> in render.php, die den
   Zuschnitt liefert.

   Auf den meisten Handys ist das Fenster aber NIEDRIGER als Quadrat plus
   Text (auf 393 px rund 836 px). Mit dem ganzen Quadrat als Mindesthoehe
   hing die Knopfreihe unter dem Bildschirmrand — unter iOS 26 genau hinter
   der schwebenden Safari-Leiste (Kunde 2026-10-07). Jetzt ist das Band der
   Puffer: Text und beide Knoepfe passen in 100svh, das Foto bekommt, was
   uebrig bleibt. Ist das weniger als das Quadrat, schneidet das Band das
   Foto unten ab — dort liegt nur Pullover, der ohnehin im Schleier
   verschwindet. Erst bei 55 % der Breite plus Kopfhoehe gibt das Band nicht
   mehr nach: so weit reicht im Zuschnitt alles Wichtige, Hand, Anhaenger und
   Gesicht; darunter scrollt die Buehne eben.

   Und der Kopf ist hier WEISS, nicht transparent auf dem Foto (Kunde
   2026-10-07: die Wortmarke lag auf Hand und Schluessel, das Foto war „nur
   ein Schlitz"). Das Foto beginnt mit harter Kante an seiner Unterkante, der
   obere Schleier und der Lichtfleck fuer die Wortmarke entfallen. Die
   Unterseiten behalten den transparenten Kopf auf ihrem Kopfband. Damit
   trotzdem moeglichst viel Foto ins Fenster passt, sitzt der Text enger
   (Lead in Grundgroesse, kleinere Abstaende) und beginnt 5 rem statt
   3,25 rem ueber der Bandunterkante; der Schleier ist dafuer nach oben
   verlaengert, die Giebellinie steht auf 0,92 Weiss.

   Die Buehne ist 100lvh hoch, nicht 100svh, und traegt die Differenz als
   weissen Rand UNTER den Knoepfen: unter iOS 26 reicht die Seite hinter die
   schwebende Safari-Leiste, und dort schien der Planblau-Grund des naechsten
   Abschnitts durch das Glas. Die Knoepfe selbst bleiben in den 100svh, also
   ueber der Leiste. Auf Android (Leiste oben) ist der Rand schlicht Luft
   unter der Knopfreihe. */
@media (max-width: 899px) {
  body.seite-start .site-header {
    background: var(--bg);
    border-bottom-color: var(--border);
  }
  body.seite-start .buehne {
    min-height: 100lvh;
    padding-bottom: calc(100lvh - 100svh);
  }
  body.seite-start .buehne__bild { background: var(--surface); }
  body.seite-start .buehne__bild img { top: var(--kopf-h); }
  body.seite-start .buehne__schleier {
    background: linear-gradient(to top, #fff 0, #fff 3rem, rgb(255 255 255 / 0.92) 5rem,
                                rgb(255 255 255 / 0.55) 7.75rem, rgb(255 255 255 / 0) 10.5rem);
  }
}
@media (max-width: 700px) {
  body.seite-start .buehne {
    --ueberlappung: 5rem;
    --band: calc(55vw + var(--kopf-h));
  }
  body.seite-start .buehne__inhalt {
    margin-top: calc(-1 * var(--ueberlappung));
    gap: 0.75rem;
    padding-bottom: 1.75rem;
  }
  body.seite-start .buehne .lead { font-size: var(--step-0); line-height: 1.55; max-width: none; }
  body.seite-start .buehne .btn-group { margin-top: 0; gap: 0.6rem 0.9rem; }
  body.seite-start .buehne__bild { container-type: size; }
  body.seite-start .buehne__bild img {
    /* Unter dem weissen Kopf beginnt das Foto buendig (Versatz = Kopfhoehe);
       nur wenn ein hohes Fenster mehr Platz hat als Quadrat plus Text,
       rutscht es weiter herunter und blendet dann oben weich ein. */
    --versatz: clamp(var(--kopf-h), 100cqh - 100cqw - var(--ueberlappung), var(--kopf-h) + 2rem);
    --bild-maske: linear-gradient(to bottom, rgb(0 0 0 / 0) 0,
                                  #000 min(3rem, var(--versatz) - var(--kopf-h)),
                                  #000 calc(100% - 4rem), rgb(0 0 0 / 0));
    top: var(--versatz);
    bottom: auto;
    height: auto;
    aspect-ratio: 1;
    -webkit-mask-image: var(--bild-maske);
    mask-image: var(--bild-maske);
  }
}

/* Der Markenspruch als Ueberschrift der Buehne. Die Schreibschrift braucht
   dafuer drei Dinge, die der Grotesk-Titel nicht braucht:

   MEHR GROESSE — ihre Strichstaerke ist rund halb so kraeftig wie die der
   Mukta, bei gleicher Punktgroesse wirkt sie zart und liest sich schlechter;
   der untere Wert bleibt trotzdem bei 2 rem, weil sie darunter auf dem Foto
   ausfranst. MEHR ZEILENABSTAND — Ober- und Unterlaengen greifen ineinander
   ("Fokus," ueber "Immobilie"), 1.28 aus dem Band reicht auf zwei langen
   Zeilen nicht. Der untere Wert ist auf 320 px nachgemessen: bei 2 rem stand
   die laengere Zeile mit 3 px Rest im Satzspiegel, bei 1.9 rem sind es 17 —
   fiele die Schreibschrift einmal auf eine Ersatzschrift zurueck, bricht die
   Zeile dann um, statt zu klemmen. UND KEINE BALANCE — text-wrap: balance verteilt die Woerter
   neu und macht damit genau die zwei Zeilen kaputt, die in site.json
   ausdruecklich gesetzt sind. Aufgehoben wird sie mit `normal`, nicht mit
   `nowrap`: passt eine der beiden Zeilen auf einem schmalen Geraet doch
   nicht, soll sie umbrechen duerfen statt aus dem Satzspiegel zu laufen.

   Die Regel steht auf `.buehne h1.claim` und nicht auf `.claim`: `.buehne h1`
   ist spezifischer als die Klasse allein und wuerde Groesse und Schrift sonst
   zurueckholen. */
.buehne h1.claim {
  font-family: var(--stack-meow-script);
  font-size: clamp(1.9rem, 9vw, 3.5rem);
  line-height: 1.38;
  letter-spacing: 0.01em;
  text-wrap: normal;
  max-width: none;
}
/* Der Giebel steht an der Stelle des Kickers und haelt zur Schreibschrift
   etwas mehr Abstand als das Grid-gap gibt — die Oberlaenge des "D" reicht
   sonst fast an die Dachschraege. */
.buehne .giebel { margin-bottom: clamp(0.2rem, 1vw, 0.6rem); }

@media (min-width: 900px) {
  /* Ab hier begrenzt `.buehne__inhalt > *` alles auf 46ch — fuer die
     Schreibschrift zu eng, sie braucht ihre zwei ganzen Zeilen. */
  /* Die untere Grenze liegt dicht an dem Wert, den die mobile Kurve bei 899 px
     erreicht (56 px). Ohne sie sprang der Claim an der Umbruchstelle von 62 px
     auf 42 px — beim Ziehen des Fensters ein sichtbarer Ruck, und das Fuellwort
     der Zeile wechselte mitten in der Bewegung die Groesse. */
  .buehne h1.claim { font-size: clamp(3.4rem, 4vw, 3.7rem); max-width: none; }

  /* Der Schleier der Startseite reicht weiter nach rechts als der der
     Unterseiten. Grund ist gemessen, nicht geraten: die zwei Claim-Zeilen sind
     laenger als jede Grotesk-Ueberschrift, die hier je stand, und liefen mit
     ihren Enden in den unscharfen Gruenton des Motivs — an der Stelle standen
     2,5:1 und 2,9:1, wo 3:1 gefordert sind (grosser Text, WCAG 2.2 AA). Der
     Verlauf deckt deshalb bis 30 % voll und laeuft erst bei 64 % aus statt bei
     56 %. Das Motiv bleibt rechts unangetastet, wo die Frau steht. */
  body.seite-start .buehne__schleier {
    background:
      linear-gradient(to bottom, rgb(255 255 255 / 0.82) 0, rgb(255 255 255 / 0) 9rem),
      linear-gradient(to right, rgb(255 255 255 / 0.94) 0, rgb(255 255 255 / 0.82) 34%,
                      rgb(255 255 255 / 0) 68%);
  }
}

/* Eroeffnung „Das Fenster" (assets/eroeffnung.css/js, Markup in head.php direkt
   hinter <main>): zweites Netz unter eroeffnung.css. Laedt das Stylesheet
   nicht, waere die Flaeche sonst ein Leerblock mit SVG vor der Buehne.
   Sichtbar macht sie allein html.lv-eroeffnung in eroeffnung.css. */
.eroeffnung { display: none; }

/* Ruhige Eroeffnung der Buehne selbst: das Bild setzt sich langsam, der Text
   laeuft gestaffelt von unten ein. Laeuft die Eroeffnungsflaeche, warten Kopf
   und Text unter ihr (animation-play-state in eroeffnung.css). Ohne JS und bei
   reduced-motion steht sofort alles fertig da. */
@media (prefers-reduced-motion: no-preference) {
  .buehne__bild img { animation: buehne-setzen 14s var(--ease-out, ease-out) both; }
  @keyframes buehne-setzen { from { transform: scale(1.055); } to { transform: scale(1); } }
  /* Die Startseite richtet ihr Foto oben aus (posGross in index.php, mobil
     ohnehin); der Zoom haengt dann ebenfalls an der Oberkante, sonst schnitte
     er in den ersten Sekunden genau dort wieder rund 3 % ab — Kopf und
     Schluesselring. */
  body.seite-start .buehne__bild img { transform-origin: 50% 0; }

  body[data-header-reveal] .buehne__inhalt > * {
    animation: buehne-auf 0.75s var(--ease-out, cubic-bezier(.2,.85,.25,1)) both;
  }
  body[data-header-reveal] .buehne__inhalt > :nth-child(1) { animation-delay: 0.10s; }
  body[data-header-reveal] .buehne__inhalt > :nth-child(2) { animation-delay: 0.20s; }
  body[data-header-reveal] .buehne__inhalt > :nth-child(3) { animation-delay: 0.30s; }
  body[data-header-reveal] .buehne__inhalt > :nth-child(4) { animation-delay: 0.40s; }
  body[data-header-reveal] .buehne__inhalt > :nth-child(5) { animation-delay: 0.48s; }
  @keyframes buehne-auf { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
}

/* ---------------------------------------------------------------------------
   4b. Das Bildband — dieselbe Sprache wie die Buehne, eine Etage tiefer.
   Randloses Foto, Schleier statt Kasten, Text an derselben Fluchtlinie. Flacher
   als die Buehne: es eroeffnet eine Sektion, es traegt keine Seite.
   ------------------------------------------------------------------------ */
.bildband {
  position: relative;
  display: grid;
  isolation: isolate;
  align-items: end;
  min-height: clamp(19rem, 52svh, 27rem);
}
.bildband__bild {
  grid-area: 1 / 1;
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  background: var(--planblau);
}
.bildband__bild img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--bild-pos, 60% center);
  display: block;
}
.bildband::before {
  content: "";
  grid-area: 1 / 1;
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to top, #fff 0, rgb(255 255 255 / 0.92) 20%, rgb(255 255 255 / 0.66) 46%, rgb(255 255 255 / 0) 74%);
}
.bildband__inhalt {
  grid-area: 1 / 1;
  align-self: end;
  padding-block: clamp(3.5rem, 9vh, 6rem) clamp(1.75rem, 4vw, 2.5rem);
  display: grid;
  gap: 0.6rem;
  justify-items: start;
}
.bildband__inhalt .giebel { margin-bottom: 0.35rem; }
.bildband h2 {
  font-size: clamp(1.9rem, 8vw, 3.25rem);
  font-weight: 400;
  line-height: var(--leading-tight);
  color: var(--accent);
  margin: 0;
  max-width: 16ch;
}
.bildband .lead { max-width: 40ch; }
@media (min-width: 900px) {
  .bildband { align-items: center; }
  .bildband::before {
    background: linear-gradient(to right, rgb(255 255 255 / 0.88) 0, rgb(255 255 255 / 0.62) 28%, rgb(255 255 255 / 0) 58%);
  }
  .bildband__inhalt { align-self: center; padding-block: clamp(3rem, 7vh, 4.5rem); }
  .bildband__bild img { object-position: var(--bild-pos-gross, 70% center); }
}

/* Pflichtausschnitt (bildband--fokus, Werte aus bildband.php): ein Rechteck im
   Foto, das bei jeder Breite und Zoomstufe ganz zu sehen ist. cover allein kann
   das nicht — das Band ist hoechstens 27rem hoch, aber beliebig breit, und
   herausgezoomt zeigte es nur noch einen Streifen von Stirn bis Kinn.
   Groesse: mindestens so hoch wie das Band, sonst so gross wie cover verlangt,
   aber nie groesser, als dass der Ausschnitt noch hineinpasst. Ist das Band
   breiter als das so begrenzte Foto, bleibt das Foto rechts stehen und laeuft
   links ins Weiss aus — dort zeigt es ohnehin nur das ueberstrahlte Fenster.
   Lage: der Ausschnitt sitzt am Anker, wird aber nie angeschnitten, und das
   Foto deckt das Band (aussen geklammert, das gewinnt bei Platzmangel).
   Buehne: Foto und Schleier nehmen hoechstens 160rem ein (2.560 px bei 100 %,
   ein QHD-Monitor laeuft also noch bis zum Rand). Erst breiter — Ultrawide,
   stark herausgezoomt — bleiben sie mittig beim Text, statt an den rechten
   Fensterrand zu wandern, und das Foto laeuft rechts weich ins Weiss aus.
   Die Grenze lag zuerst bei 1.920 px — da hing es dem Kunden zu oft in der
   Mitte (2026-10-05). */
@supports (height: 1cqh) {
  .bildband--fokus {
    --anker-x: 0.5;
    --anker-y: 0.4;
    container-type: inline-size;
    --buehne-rand: max(0px, (100cqw - 160rem) / 2);
  }
  .bildband--fokus .bildband__bild,
  .bildband--fokus::before {
    left: var(--buehne-rand);
    right: var(--buehne-rand);
  }
  /* Der rechte Auslauf waechst mit dem weissen Rand bis 18rem und folgt einer
     S-Kurve statt einer Geraden: linear blieb an seinem Ende eine sichtbare
     Kante stehen. 18rem enden vor der Schulter der Frau (rund 20rem Abstand). */
  .bildband--fokus .bildband__bild {
    --auslauf: min(18rem, var(--buehne-rand));
    --auslauf-maske: linear-gradient(to left,
      rgb(0 0 0 / 0) 0,
      rgb(0 0 0 / 0.028) calc(var(--auslauf) * 0.1),
      rgb(0 0 0 / 0.104) calc(var(--auslauf) * 0.2),
      rgb(0 0 0 / 0.216) calc(var(--auslauf) * 0.3),
      rgb(0 0 0 / 0.352) calc(var(--auslauf) * 0.4),
      rgb(0 0 0 / 0.5) calc(var(--auslauf) * 0.5),
      rgb(0 0 0 / 0.648) calc(var(--auslauf) * 0.6),
      rgb(0 0 0 / 0.784) calc(var(--auslauf) * 0.7),
      rgb(0 0 0 / 0.896) calc(var(--auslauf) * 0.8),
      rgb(0 0 0 / 0.972) calc(var(--auslauf) * 0.9),
      #000 var(--auslauf));
    container-type: size;
    background: var(--surface);
    -webkit-mask-image: var(--auslauf-maske);
    mask-image: var(--auslauf-maske);
  }
  .bildband--fokus .bildband__bild img {
    --fokus-mx: calc((var(--fokus-l) + var(--fokus-r)) / 2);
    --fokus-my: calc((var(--fokus-o) + var(--fokus-u)) / 2);
    --bild-h: max(100cqh, min(
      100cqw / var(--bild-seiten),
      100cqh / (var(--fokus-u) - var(--fokus-o)),
      100cqw / (var(--bild-seiten) * (var(--fokus-r) - var(--fokus-l)))
    ));
    --bild-b: calc(var(--bild-h) * var(--bild-seiten));
    position: absolute;
    width: var(--bild-b);
    max-width: none;
    height: var(--bild-h);
    left: clamp(100cqw - var(--bild-b), clamp(
      -1 * var(--fokus-l) * var(--bild-b),
      var(--anker-x) * 100cqw - var(--fokus-mx) * var(--bild-b),
      100cqw - var(--fokus-r) * var(--bild-b)
    ), 0px);
    top: clamp(100cqh - var(--bild-h), clamp(
      -1 * var(--fokus-o) * var(--bild-h),
      var(--anker-y) * 100cqh - var(--fokus-my) * var(--bild-h),
      100cqh - var(--fokus-u) * var(--bild-h)
    ), 0px);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 12%);
    mask-image: linear-gradient(to right, transparent, #000 12%);
  }
  /* Ab 900 px steht der Text links: der Ausschnitt rueckt nach rechts. */
  @media (min-width: 900px) {
    .bildband--fokus { --anker-x: 0.68; --anker-y: 0.5; }
  }
}
/* Direkt nach dem Band braucht die folgende Sektion keinen vollen Vorlauf —
   der Kopf steht schon auf dem Foto. */
.bildband + .section { padding-top: clamp(2.25rem, 5vw, 3.5rem); }

/* Die Taktzeile — die Logo-Unterzeile als roter Faden.
   Die Trennstriche sind das einzige Limetten-Element im Kopfbereich. */
.takt {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7em;
  margin: 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
}
.takt span[aria-hidden] {
  color: var(--accent-2);
  font-weight: 400;
  transform: translateY(-0.04em);
}

/* ---------------------------------------------------------------------------
   5. Fluchtlinie und Satzspiegel
   ------------------------------------------------------------------------ */
.section__head { max-width: 46rem; gap: var(--space-xs); margin-bottom: var(--space-xl); }
.section__head h2 { font-size: var(--step-4); color: var(--accent); font-weight: 400; }
.section h3 { font-weight: 600; }

/* Auch die schmale Sektion haengt an der linken Achse. Zentriert stuende sie
   quer zu einer Seite, deren Satz durchgehend links anschlaegt — und mit der
   engeren Lesebreite faellt das sofort auf. Verschmaelert wird deshalb der
   INHALT, nicht der Behaelter: der bleibt auf der normalen Containerbreite und
   damit auf derselben Fluchtlinie wie Kopfbereich und Fussbereich. */
.section--narrow > .container { max-width: var(--container); }
.section--narrow > .container > * { max-width: var(--container-narrow); }

/* Schmale Lesespur, LINKS an der Achse — nicht zentriert. Breite nach der
   Schrift bemessen: 42rem ergaben in Mukta Light ueber 100 Zeichen je Zeile. */
.spur { max-width: 34rem; }
.spur .lead { max-width: 30rem; }
.spur p + p { margin-top: 1em; }

/* Ein Textblock, der sich bewusst schmal haelt und rechts Luft laesst. */
.section--planblau { background: var(--planblau); }
.section--creme    { background: var(--creme); }

/* ---------------------------------------------------------------------------
   6. Der Claim — der einzige Auftritt der Schreibschrift je Seite
   ------------------------------------------------------------------------ */
.claim-band { padding-block: clamp(3.5rem, 8vw, 6.5rem); }
.claim-band .giebel { margin-bottom: clamp(1rem, 2.5vw, 1.75rem); }
.claim {
  font-family: var(--stack-meow-script);
  font-weight: 400;
  font-size: clamp(2rem, 5.4vw, 3.75rem);   /* nie unter 32 px */
  line-height: 1.28;
  letter-spacing: 0.01em;
  color: var(--accent);
  margin: 0;
  max-width: 20ch;
}
.claim-band__quelle {
  margin-top: clamp(1rem, 2.5vw, 1.5rem);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
}

/* ---------------------------------------------------------------------------
   7. Die drei Saeulen — EIN Mandat in drei Stationen
   Keine Kachelreihe: eine durchlaufende Limettenlinie mit drei Knoten,
   darunter die Stationen in ungleichen Breiten. Die Linie zeichnet sich
   beim Scrollen — sie tut, was sie beschreibt: sie begleitet.
   ------------------------------------------------------------------------ */
.mandat { position: relative; }
.mandat__linie {
  display: block;
  width: 100%;
  height: 10px;
  color: var(--accent-2);
  margin-bottom: 2.25rem;
  overflow: visible;
}

.saeulen {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(2.25rem, 4vw, 3.5rem);
}
@media (min-width: 860px) {
  .saeulen { grid-template-columns: 1fr 0.94fr 1.14fr; gap: clamp(2rem, 4vw, 4rem); }
}

.saeule { position: relative; padding-top: 1.5rem; }
/* Der Knoten sitzt auf der Linie — immer genau ueber seiner Spalte. */
.saeule::before {
  content: "";
  position: absolute;
  top: -2.9rem;
  left: 0;
  width: 9px;
  height: 9px;
  background: var(--accent-2);
  transform: rotate(45deg);
}
@media (max-width: 859px) {
  .saeule::before { display: none; }
  .saeule { border-top: 2px solid var(--accent-2); padding-top: 1.25rem; }
  .mandat__linie { display: none; }
}

/* Die Station bekommt eine grosse Ziffer statt eines gesperrten Versal-Labels.
   Die Reihenfolge ist echt — Beraten kommt vor Vermitteln kommt vor Begleiten —,
   deshalb darf sie gezaehlt werden. Der Zaehler liegt im CSS, weil er nichts
   aussagt, was nicht schon im Text steht: er gibt der Wiederholung nur eine
   Gestalt. Ein Zaehlername fuer beide Seiten, zurueckgesetzt am jeweiligen
   Behaelter (Startseite: die Saeulenreihe; Leistungsseite: die Seite selbst,
   dort ist jeder Abschnitt eine eigene <section>). */
.saeulen { counter-reset: station; }
.saeule { counter-increment: station; }
body { counter-reset: station; }
.leistungsblock__kopf { counter-increment: station; }

.saeule__takt {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.005em;
  text-transform: none;
  color: var(--lesegrau-mut);
  margin-bottom: 0.5rem;
}
.saeule__takt::before {
  content: counter(station, decimal-leading-zero);
  font-size: var(--step-4);
  font-weight: 300;
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: color-mix(in srgb, var(--accent) 38%, #fff);
  font-variant-numeric: lining-nums tabular-nums;
}
.saeule h3 {
  font-size: var(--step-2);
  font-weight: 400;
  color: var(--accent);
  margin: 0 0 0.6rem;
}
.saeule > p { margin: 0 0 1.25rem; color: var(--lesegrau); }
.saeule ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.7rem;
  border-top: 1px solid var(--border);
  padding-top: 1.15rem;
}
.saeule ul li {
  position: relative;
  padding-left: 1.35rem;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--lesegrau-mut);
}
.saeule ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.7rem;
  height: 2px;
  background: var(--accent-2);
}

/* ---------------------------------------------------------------------------
   8. Wechselnde Bild/Text-Reihen und Regionen
   ------------------------------------------------------------------------ */
.regionen {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
  counter-reset: none;
}
.region {
  display: grid;
  gap: 0.5rem clamp(1.5rem, 5vw, 5rem);
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
  border-top: 1px solid var(--border);
}
.region:last-child { border-bottom: 1px solid var(--border); }
@media (min-width: 760px) {
  .region { grid-template-columns: minmax(9rem, 15rem) 1fr; align-items: baseline; }
}
.region h3 {
  margin: 0;
  font-size: var(--step-2);
  font-weight: 400;
  color: var(--accent);
}
.region p { margin: 0; max-width: 54ch; color: var(--lesegrau); }

/* ---------------------------------------------------------------------------
   9. Der Abbinder — genau EIN tiefpetrolfarbenes Band je Seite
   ------------------------------------------------------------------------ */
.abbinder {
  background: var(--petrol-tief);
  color: #fff;
  padding-block: clamp(3.5rem, 8vw, 6.5rem);
}
.abbinder h2 {
  color: #fff;
  font-weight: 400;
  font-size: var(--step-4);
  margin: 0 0 var(--space-sm);
  max-width: 18ch;
}
/* Weiss mit einem Hauch Limette statt abgedunkeltem Weiss. Die alte Mischung
   (82 % Weiss in Petrol) ergab #d1dde2 — ein blaeulich entsaettigtes Grau, das
   auf dem Petrolband wie ausgeblichener Fliesstext wirkte, obwohl der Kontrast
   rechnerisch stimmte. Der warme Elfenbeinton liest sich als gesetzte Farbe. */
.abbinder p { color: color-mix(in srgb, #fff 92%, var(--accent-2)); max-width: 46ch; }
.abbinder .giebel { margin-bottom: 1.5rem; }
.abbinder .btn--primary { --_bg: #fff; --_fg: var(--petrol-tief); }
.abbinder .btn--primary:hover { --_bg: color-mix(in srgb, #fff 88%, var(--accent-2)); }
.abbinder .btn--ghost {
  --_fg: #fff;
  --_bd: color-mix(in srgb, #fff 45%, transparent);
}
.abbinder .btn--ghost:hover { --_bd: #fff; --_bg: transparent; }
.abbinder__kontakt {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid color-mix(in srgb, #fff 22%, transparent);
  display: grid;
  gap: 0.4rem 3rem;
  font-size: var(--step-0);
}
@media (min-width: 700px) { .abbinder__kontakt { grid-auto-flow: column; justify-content: start; } }
.abbinder__kontakt a { color: #fff; text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--accent-2); }
.abbinder__kontakt a:hover { text-decoration-thickness: 2px; }

/* ---------------------------------------------------------------------------
   10. Immobilien — Uebersicht, Filter, Karten, Leerzustand, Detailseite
   ------------------------------------------------------------------------ */

/* Filter: eine ruhige Zeile, kein Formular-Klotz. */
.filter {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(0.9rem, 2vw, 1.75rem);
  padding-block: 1.4rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.filter__feld { display: grid; gap: 0.3rem; min-width: 9.5rem; flex: 1 1 9.5rem; }
.filter__feld > span {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
}
.filter select {
  appearance: none;
  width: 100%;
  min-height: 2.9rem;
  padding: 0.45rem 2rem 0.45rem 0;
  font: inherit;
  font-weight: 400;
  color: var(--accent);
  background: transparent;
  border: 0;
  border-bottom: 2px solid var(--border-strong);
  border-radius: 0;
  background-image: linear-gradient(45deg, transparent 50%, var(--accent) 50%),
                    linear-gradient(135deg, var(--accent) 50%, transparent 50%);
  background-position: right 0.75rem center, right 0.4rem center;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
  cursor: pointer;
}
.filter select:hover { border-bottom-color: var(--accent); }
.filter__aktion { display: flex; gap: 0.75rem; align-items: center; flex: 0 0 auto; }
.filter__zuruecksetzen {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--lesegrau-mut);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.filter__zuruecksetzen:hover { color: var(--accent); }

.treffer {
  margin: 1.25rem 0 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
}

/* Objektkarten — grosszuegig, ohne Rahmen und ohne Schatten. */
.objekte {
  list-style: none;
  margin: var(--space-xl) 0 0;
  padding: 0;
  display: grid;
  gap: clamp(2rem, 4vw, 3.25rem) clamp(1.5rem, 3vw, 2.5rem);
}
@media (min-width: 700px)  { .objekte { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1120px) { .objekte { grid-template-columns: repeat(3, 1fr); } }

.objekt-karte { position: relative; display: grid; gap: 0.9rem; }
.objekt-karte__bild {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--planblau);
  border-radius: var(--radius-sm);
}
.objekt-karte__bild img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--dur-slow) var(--ease-out);
}
.objekt-karte:hover .objekt-karte__bild img { transform: scale(1.03); }
.objekt-karte__leer {
  display: grid;
  place-items: center;
  height: 100%;
  color: color-mix(in srgb, var(--accent) 45%, #fff);
}
.objekt-karte__leer svg { width: 3.5rem; height: auto; }

.objekt-karte__status {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  padding: 0.3rem 0.7rem;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--lesegrau);
  background: var(--accent-2);   /* dunkle Schrift auf Limette: 10,2:1 */
  border-radius: 2px;
}
.objekt-karte__meta {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
  margin: 0;
}
.objekt-karte h3 { margin: 0; font-size: var(--step-2); font-weight: 400; color: var(--accent); }
.objekt-karte h3 a { color: inherit; }
/* Ganze Karte klickbar, Linktext bleibt der Titel (Screenreader-freundlich). */
.objekt-karte h3 a::after { content: ""; position: absolute; inset: 0; }
.objekt-karte__preis {
  margin: 0;
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--lesegrau);
}
.objekt-karte__preis span { font-weight: 300; font-size: var(--step--1); color: var(--lesegrau-mut); }

/* Der Leerzustand ist kein Fehler, sondern eine Aufforderung — und eine echte
   Komposition: die Aussage links, der Suchauftrag als Merkzettel rechts. Ohne
   die zweite Spalte laege bei einem leeren Bestand die halbe Seite brach. */
.leerstand {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  padding-block: clamp(1rem, 2vw, 2rem);
  align-items: start;
}
/* Zwei Spalten nur, wenn der Merkzettel wirklich dasteht. Als Anriss auf der
   Startseite faellt er weg — dann stuende die zweite Spalte leer. */
@media (min-width: 940px) { .leerstand:has(.suchauftrag) { grid-template-columns: 1fr 22rem; } }
.leerstand__text { display: grid; gap: clamp(1.25rem, 2.5vw, 1.75rem); }
.leerstand h2 { font-size: var(--step-3); font-weight: 400; color: var(--accent); margin: 0; max-width: 20ch; }
.leerstand p { margin: 0; max-width: 52ch; }
.leerstand .treffer { margin: 0 0 -0.75rem; }

.suchauftrag {
  padding: clamp(1.5rem, 3vw, 2rem);
  background: var(--planblau);
  border-radius: var(--radius-sm);
}
.suchauftrag h3 {
  margin: 1rem 0 1.25rem;
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--accent);
}
.suchauftrag dl { margin: 0; display: grid; gap: 0.25rem; }
.suchauftrag dt {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
  margin-top: 1rem;
}
.suchauftrag dt:first-of-type { margin-top: 0; }
.suchauftrag dd {
  margin: 0;
  font-size: var(--step-0);
  line-height: 1.5;
  color: var(--lesegrau);
}
.suchauftrag > p {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  font-size: var(--step--1);
  color: var(--lesegrau-mut);
}
/* Die Objektarten sind Beschriftung, nicht Bedienung — sie fuehren nirgendwo
   hin. Trotzdem standen sie als kleine, eng gesetzte Pillen da und sahen aus
   wie Filterknoepfe, die nicht reagieren. Jetzt haben sie die Hoehe eines
   echten Tippziels und genug Luft dazwischen, damit die Reihe als gesetzte
   Aufzaehlung liest und nicht als klemmende Schalterleiste. */
.arten {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.arten li {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.4rem 1.15rem;
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.005em;
  color: var(--accent);
  border: 1px solid var(--border);
  border-radius: 2px;
}

/* Detailseite: Daten als echte Tabelle, nicht als Kachelraster. */
.objekt-galerie { display: grid; gap: 0.75rem; }
@media (min-width: 760px) {
  .objekt-galerie { grid-template-columns: repeat(4, 1fr); }
  .objekt-galerie > :first-child { grid-column: 1 / -1; }
}
.objekt-galerie figure { margin: 0; }
.objekt-galerie img {
  width: 100%;
  height: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
  border-radius: var(--radius-sm);
  background: var(--planblau);
}
.objekt-galerie > :first-child img { aspect-ratio: 16 / 9; }

.objekt-raster { display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: start; }
@media (min-width: 980px) { .objekt-raster { grid-template-columns: 1fr 22rem; } }

.datenblatt { width: 100%; border-collapse: collapse; margin: 0; }
/* Nur eine SICHTBARE Tabellenueberschrift bekommt die Versal-Auszeichnung. Auf
   „Über uns" ist die Caption `visually-hidden` — dort beschriftet sie die
   Tabelle nur fuer Screenreader, und Versalien auf einem ganzen Satz sind dann
   Auszeichnung ohne Betrachter (das Slop-Gate meldet sie als `all-caps-body`). */
.datenblatt caption:not(.visually-hidden) {
  text-align: left;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
  padding-bottom: 0.75rem;
}
.datenblatt th, .datenblatt td {
  text-align: left;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--step-0);
  vertical-align: baseline;
}
.datenblatt th { font-weight: 400; color: var(--lesegrau-mut); width: 46%; }
.datenblatt td { font-weight: 600; color: var(--lesegrau); }

.objekt-preis {
  font-size: var(--step-3);
  font-weight: 400;
  color: var(--accent);
  margin: 0 0 0.35rem;
}
.objekt-preis span { font-size: var(--step-0); font-weight: 300; color: var(--lesegrau-mut); }

.energie {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding: clamp(1.1rem, 2.5vw, 1.6rem) clamp(1.1rem, 2.5vw, 1.6rem);
  background: var(--planblau);
  border-left: 3px solid var(--accent-2);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.energie h2 {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.5rem;
}
.energie p { margin: 0; font-size: var(--step-0); color: var(--lesegrau); }

.objekt-text { max-width: 60ch; }
.objekt-text p { margin: 0 0 1em; }

.zurueck {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
}
.zurueck:hover { color: var(--accent); }
.zurueck svg { width: 1rem; height: 1rem; transform: rotate(180deg); }

/* ---------------------------------------------------------------------------
   11. Formular
   ------------------------------------------------------------------------ */
.form { display: grid; gap: var(--space-md); }
.field { display: grid; gap: 0.4rem; }
.field label {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
}
.field input, .field textarea, .field select {
  width: 100%;
  font: inherit;
  font-weight: 300;
  color: var(--lesegrau);
  background: transparent;
  border: 0;
  border-bottom: 2px solid var(--border-strong);
  border-radius: 0;
  padding: 0.65rem 0;
  min-height: 2.9rem;
}
.field textarea { min-height: 8rem; resize: vertical; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-bottom-color: var(--accent);
}
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.field--check { grid-template-columns: auto 1fr; align-items: start; gap: 0.75rem; }
.field--check input { width: 1.25rem; height: 1.25rem; min-height: 0; accent-color: var(--accent); margin-top: 0.15rem; }
.field--check label { text-transform: none; letter-spacing: 0; font-weight: 300; font-size: var(--step-0); color: var(--lesegrau); }
.field--check a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.field__fehler { font-size: var(--step--1); color: var(--danger); font-weight: 600; }
.field--fehler input, .field--fehler textarea { border-bottom-color: var(--danger); }
.pflicht-hinweis { font-size: var(--step--1); color: var(--lesegrau-mut); margin: 0; }
.honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.kontakt-raster { display: grid; gap: clamp(2.5rem, 6vw, 5rem); align-items: start; }
@media (min-width: 940px) { .kontakt-raster { grid-template-columns: 1fr 20rem; } }
.kontaktdaten { display: grid; gap: var(--space-md); }
.kontaktdaten h2 {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
  margin: 0 0 0.5rem;
}
.kontaktdaten p { margin: 0; line-height: 1.7; }
.kontaktdaten a { color: var(--accent); text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--accent-2); }
.kontaktdaten__block { padding-top: var(--space-md); border-top: 1px solid var(--border); }
.kontaktdaten__block:first-child { padding-top: 0; border-top: 0; }

/* ---------------------------------------------------------------------------
   12. Rechtstexte
   ------------------------------------------------------------------------ */
/* Rechtstexte sind lange Fliesstexte — hier zaehlt die Zeilenlaenge am meisten.
   44rem waren in Mukta Light rund 104 Zeichen; 34rem sind knapp 80. */
.prose { max-width: 34rem; }
.prose h2 {
  font-size: var(--step-2);
  font-weight: 400;
  color: var(--accent);
  margin-top: 2.5em;
  margin-bottom: 0.5em;
}
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: var(--step-1); font-weight: 600; color: var(--lesegrau); margin-top: 1.8em; margin-bottom: 0.4em; }
.prose p, .prose li { line-height: 1.72; }
.prose p { margin-bottom: 1.1em; }
.prose ul, .prose ol { margin-bottom: 1.1em; padding-left: 1.2rem; }
.prose li { margin-bottom: 0.4em; }
.prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.prose .subtle { font-size: var(--step--1); color: var(--lesegrau-mut); }

/* Schlanker Seitenkopf fuer die Rechtsseiten — kein Foto, aber dieselbe Achse. */
.section--pagehead, .pagehead {
  padding-block: clamp(3rem, 7vw, 5.5rem) clamp(1.5rem, 3vw, 2.5rem);
  border-bottom: 1px solid var(--border);
}
.pagehead h1, .section--pagehead h1 {
  font-size: var(--step-5);
  font-weight: 400;
  color: var(--accent);
  margin: 0;
}

/* ---------------------------------------------------------------------------
   13. Fussbereich
   ------------------------------------------------------------------------ */
.site-footer { background: var(--bg); border-top: 1px solid var(--border); margin-top: 0; }
.footer-grid { padding-block: clamp(3rem, 6vw, 4.5rem) var(--space-lg); }
/* Vier Spalten: Marke, Seiten, Rechtliches, Kontakt. */
@media (min-width: 900px) {
  .footer-grid { grid-template-columns: 1.5fr 0.9fr 1fr 1.1fr; }
}
@media (min-width: 761px) and (max-width: 899px) {
  .footer-grid { grid-template-columns: repeat(2, 1fr); }
}
.footer-col h2 { color: var(--lesegrau-mut); letter-spacing: 0.16em; font-weight: 600; }
/* Die Linkliste braucht Zeilenabstand, damit sie als gegliederter Abschluss
   liest und der Daumen sicher trifft — vorher standen bis zu neun Links in
   einer einzigen eng gesetzten Kolonne. */
.footer-col a { color: var(--lesegrau-mut); padding-block: 0.42rem; }
.footer-col a:hover { color: var(--accent); }
.footer-bottom { border-top: 1px solid var(--border); }

/* Der Claim in der Schreibschrift der Wortmarke — die Signatur unter dem Logo.
   Bewusst klein: gross gehoert er auf die Startseite, hier schliesst er ab. */
.footer-claim {
  font-family: var(--stack-meow-script);
  font-weight: 400;
  font-size: var(--step-2);
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: var(--accent);
  margin: var(--space-sm) 0 0;
  /* Der Umbruch steht im Claim selbst (site.json). 18ch schnitten ihn quer
     dazu — "Der Mensch im Fokus, die / Immobilie im Griff!" —, deshalb nur so
     viel Breite begrenzen, dass die laengere der beiden gesetzten Zeilen
     hineinpasst. */
  max-width: 24ch;
}

/* ---------------------------------------------------------------------------
   14. Ruhe bewahren
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .buehne__bild img,
  .buehne__inhalt > *,
  .objekt-karte__bild img { animation: none !important; transition: none !important; transform: none !important; }
}

/* ---------------------------------------------------------------------------
   15. Leistungsseite — dieselben drei Abschnitte, anderer Rhythmus:
   gestapelte Baender statt Spalten, Kopf links, Inhalt rechts.
   ------------------------------------------------------------------------ */
.leistungsblock__raster { display: grid; gap: clamp(1.5rem, 4vw, 4rem); align-items: start; }
@media (min-width: 880px) {
  .leistungsblock__raster { grid-template-columns: minmax(12rem, 18rem) 1fr; }
}
.leistungsblock__kopf .giebel { margin-bottom: 1.1rem; }
.leistungsblock__kopf h2 {
  font-size: var(--step-5);
  font-weight: 400;
  line-height: 1.02;
  color: var(--accent);
  margin: 0;
}
.leistungsblock__inhalt .lead { max-width: 42ch; margin: 0 0 var(--space-lg); }

/* Die Verwaltung (partials/custom/verwaltung.php) steht ausserhalb der
   gezaehlten Reihenfolge Beraten, Vermitteln, Begleiten: sie ist laufende
   Arbeit, kein Abschnitt eines Auftrags. Ohne das haette Beraten die 02. */
.leistungsblock--schwerpunkt .leistungsblock__kopf { counter-increment: none; }
.leistungsblock--schwerpunkt .eyebrow { display: flex; margin-bottom: 0.5rem; }
/* Der Giebel darueber ist schon die Linie — kein zweiter Strich davor. */
.leistungsblock--schwerpunkt .eyebrow::before { content: none; }

.umfang { list-style: none; margin: 0; padding: 0; display: grid; }
.umfang li {
  position: relative;
  padding: 1rem 0 1rem 2rem;
  border-top: 1px solid var(--border);
  font-size: var(--step-1);
  font-weight: 300;
  line-height: 1.45;
  color: var(--lesegrau);
  max-width: 46ch;
}
.umfang li:last-child { border-bottom: 1px solid var(--border); }
.umfang li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.55em;
  width: 1.1rem;
  height: 2px;
  background: var(--accent-2);
}

/* ---------------------------------------------------------------------------
   16. Katalog- und Detailkopf (Seiten ohne Fotobuehne)
   ------------------------------------------------------------------------ */
.katalogkopf { padding-top: clamp(2.75rem, 6vw, 4.5rem); }
.katalogkopf .giebel { margin-bottom: clamp(1rem, 2.5vw, 1.5rem); }
.katalogkopf h1 {
  font-size: var(--step-5);
  font-weight: 400;
  line-height: var(--leading-tight);
  color: var(--accent);
  margin: 0 0 var(--space-md);
  max-width: 18ch;
}
.katalogkopf .lead { max-width: 48ch; }
.katalogkopf .lead a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--accent-2); }
.katalogkopf .zurueck + .objekt-karte__meta { margin-top: var(--space-lg); }

/* ---------------------------------------------------------------------------
   16b. Fehlerseite — derselbe Seitenkopf wie ueberall, und die Auswege als
   abgesetzte Zeilen statt als nackte Aufzaehlung.
   ------------------------------------------------------------------------ */
.section__head h1 {
  font-size: var(--step-5);
  font-weight: 400;
  line-height: var(--leading-tight);
  color: var(--accent);
  margin: 0;
}
.wege {
  list-style: none;
  margin: var(--space-lg) 0 0;
  padding: 0;
  display: grid;
  max-width: 26rem;
}
.wege li { border-top: 1px solid var(--border); }
.wege li:last-child { border-bottom: 1px solid var(--border); }
.wege a {
  display: block;
  padding: 0.95rem 0;
  font-size: var(--step-1);
  color: var(--accent);
  text-decoration: none;
}
.wege a:hover { text-decoration: underline; text-underline-offset: 5px; text-decoration-color: var(--accent-2); }

/* ---------------------------------------------------------------------------
   17. Rueckmeldungen des Formulars
   ------------------------------------------------------------------------ */
.hinweis {
  padding: 0.9rem 0 0.9rem 1.1rem;
  margin: 0 0 var(--space-lg);
  font-size: var(--step-0);
  background: var(--planblau);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.hinweis--ok { border-left: 3px solid var(--accent-2); color: var(--lesegrau); }
.hinweis--fehler { border-left: 3px solid var(--danger); color: var(--lesegrau); }

/* ---------------------------------------------------------------------------
   18. Formular auf dem dunklen Band (Objektanfrage)
   ------------------------------------------------------------------------ */
.abbinder .field label,
.abbinder .pflicht-hinweis { color: color-mix(in srgb, #fff 86%, var(--accent-2)); }
.abbinder .field input,
.abbinder .field textarea {
  color: #fff;
  border-bottom-color: color-mix(in srgb, #fff 42%, transparent);
}
.abbinder .field input:focus,
.abbinder .field textarea:focus { border-bottom-color: var(--accent-2); }
.abbinder .field input:focus-visible,
.abbinder .field textarea:focus-visible { outline-color: var(--accent-2); }
.abbinder .field--check label { color: color-mix(in srgb, #fff 88%, var(--petrol-tief)); }
.abbinder .field--check input { accent-color: var(--accent-2); }
.abbinder .field--check a { color: #fff; text-decoration-color: var(--accent-2); }
.abbinder .btn--lg { --_bg: #fff; --_fg: var(--petrol-tief); }
.abbinder ::placeholder { color: color-mix(in srgb, #fff 55%, var(--petrol-tief)); }

/* Rechtstexte an derselben Fluchtlinie wie der Rest der Seite. */
.prose { margin-inline: 0; }

/* ---------------------------------------------------------------------------
   Einwilligungsbanner — KEINE Umgestaltung, eine Reparatur.
   base.css setzt beide Knoepfe auf `white-space: nowrap`; zusammen mit dem
   grosszuegigen Innenabstand waechst die Aktionszeile auf einem 390-px-Geraet
   auf 411 px, und „Alle akzeptieren" laeuft ueber den Bildschirmrand hinaus.
   Auf schmalen Geraeten teilen sich die beiden Knoepfe die Zeile deshalb zu
   gleichen Teilen. Die Vorgabe aus consent.php bleibt damit gewahrt: gleiche
   Groesse, gleiche Reihe, gleiche Sichtbarkeit fuer Ablehnen und Annehmen.
   ------------------------------------------------------------------------ */
/* Auf breiten Schirmen zog derselbe Absatz sich auf rund 126 Zeichen je Zeile
   auseinander — der laengste Fliesstext der ganzen Seite, und er steht auf
   jeder. Eine Lesebreite, mehr aendert sich nicht. */
.consent-banner__text { max-width: 30rem; }

@media (max-width: 480px) {
  .consent-banner { padding-inline: var(--achse); }
  .consent-banner__aktionen {
    width: 100%;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
  }
  .consent-banner__aktionen .btn {
    white-space: normal;
    text-align: center;
    justify-content: center;
    padding-inline: 0.6rem;
  }
}

/* ---------------------------------------------------------------------------
   19. Selbstzeichnende Linien — Ruhezustand ist die FERTIGE Linie

   effects.css koppelt [data-sda="draw"] an die Scroll-Timeline: der Pfad startet
   auf stroke-dashoffset 1 (unsichtbar) und wird erst gezeichnet, wenn er ins Bild
   scrollt. Fuer die Giebellinie ist das der falsche Handel — sie ist die Signatur
   dieser Seite und muss IMMER dastehen: ohne JavaScript, bei unterdrueckter
   Animation, bei prefers-reduced-motion und in jedem Screenshot, auch weit
   unterhalb des ersten Bildschirms.

   Deshalb zeichnet sie sich ZEITGESTEUERT beim Laden, einmal, und der
   Ruhezustand ist der gezeichnete Pfad. Die Animation kommt rein additiv dazu.
   ------------------------------------------------------------------------ */
.giebel .draw,
.mandat__linie .draw { stroke-dasharray: 1; stroke-dashoffset: 0; }

@media (prefers-reduced-motion: no-preference) {
  .giebel .draw       { animation: linie-zeichnen 1.1s var(--ease-out, ease-out) 0.25s both; }
  .mandat__linie .draw { animation: linie-zeichnen 1.6s var(--ease-out, ease-out) 0.35s both; }
  @keyframes linie-zeichnen {
    from { stroke-dashoffset: 1; }
    to   { stroke-dashoffset: 0; }
  }
}

/* ---------------------------------------------------------------------------
   20. Mobile Navigation — im ausgeklappten Menue gehoert Lesegroesse hin
   Das kleine gesperrte Versal-Label ist die DESKTOP-Auszeichnung. Im mobilen
   Menue waere es zu klein und die Tippziele zu eng beieinander.
   ------------------------------------------------------------------------ */
@media (max-width: 820px) {
  /* Buendig an der Unterkante des Kopfbereichs (dort 73 px hoch). Ein zu
     grosser Wert liess auf den Buehnen-Seiten einen durchsichtigen Streifen
     zwischen Kopf und Menueflaeche stehen, durch den das Foto schien. */
  .nav { inset-block-start: 4.5625rem; }
  /* Der Kopf behaelt mobil seine 73 px auch nach dem Scrollen. Abschnitt 3
     setzt fuer den gescrollten Zustand `min-height: 0` (Desktop-Schrumpfen);
     hier wurde er dadurch 72 px hoch, und zwischen seiner Unterkante und dem
     aufgeklappten Menue blieb eine 1-px-Fuge, durch die der Seiteninhalt
     schien. */
  .site-header[data-scrolled] .header-inner { min-height: 4.5rem; }
  .nav__link {
    font-size: var(--step-1);
    letter-spacing: 0.02em;
    text-transform: none;
    padding: 1rem 0;
    min-height: 3rem;
    display: flex;
    align-items: center;
  }
  .brand__logo { height: 2.5rem; max-width: 12rem; }
}

/* ---------------------------------------------------------------------------
   21. Formular auf dem dunklen Band ohne weisse Karte
   base.css gibt .form eine helle Flaeche mit Rahmen. Auf dem Petrolband ist das
   eine Karte zu viel — und die hellen Beschriftungen aus Abschnitt 18 waeren
   darauf unlesbar. Das Formular steht hier direkt auf dem Grund.
   ------------------------------------------------------------------------ */
.abbinder .form {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 0;
}

/* Preis-Zusaetze: Nebenkosten und die Provisionsangabe. Letztere gehoert bei
   einem Makler in jede Anzeige — sie steht deshalb direkt beim Preis. */
.objekt-preis__zusatz {
  margin: 0.15rem 0 0;
  font-size: var(--step--1);
  color: var(--lesegrau-mut);
}

.objekt-text h2 {
  font-size: var(--step-2);
  font-weight: 400;
  color: var(--accent);
  margin: var(--space-lg) 0 var(--space-sm);
}
.ausstattung {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem 1.5rem;
  max-width: 46rem;
}
@media (min-width: 560px) { .ausstattung { grid-template-columns: repeat(2, 1fr); } }
.ausstattung li {
  position: relative;
  padding-left: 1.35rem;
  font-size: var(--step-0);
  color: var(--lesegrau);
}
.ausstattung li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.7rem;
  height: 2px;
  background: var(--accent-2);
}

/* Ohne Fotos wuerde zwischen Titel und Text eine Luecke klaffen. */
.objekt .katalogkopf + .section { padding-top: var(--space-lg); }

/* Objektanfrage: Formular und der direkte Weg nebeneinander — sonst laege die
   halbe Bandbreite brach, und wer lieber anruft, faende die Nummer nicht. */
.anfrage-raster { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); align-items: start; margin-top: var(--space-lg); }
@media (min-width: 900px) { .anfrage-raster { grid-template-columns: minmax(0, 34rem) 1fr; } }
.anfrage-direkt { max-width: 30ch; display: grid; gap: var(--space-md); }
.anfrage-direkt p { margin: 0; color: color-mix(in srgb, #fff 92%, var(--accent-2)); }
.anfrage-direkt__objekt {
  padding-bottom: var(--space-md);
  border-bottom: 1px solid color-mix(in srgb, #fff 22%, transparent);
  font-size: var(--step--1);
}
.anfrage-direkt__objekt strong { color: #fff; font-weight: 600; font-size: var(--step-0); }
.anfrage-direkt__wege a {
  color: #fff;
  font-size: var(--step-1);
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-color: var(--accent-2);
  line-height: 2;
}

/* ---------------------------------------------------------------------------
   22. Die Person — Peggy Schmidt im Bild (partials/custom/_marke.php: person())
   Die Texte sprechen als „wir" (Kundenwunsch 2026-09-25, nach einem Tag Ich-Form);
   das Portraet zeigt, wer hinter dem „wir" die Ansprechpartnerin ist.
   Weiche Ecken wie ueberall, kein Kreis (keine Pillen, siehe Tokens).
   ------------------------------------------------------------------------ */
.person { margin: 0; }
.person__bild img { width: 100%; border-radius: var(--radius-md); }
.person__name { display: grid; gap: 0.1rem; line-height: 1.35; }
.person__name strong { font-size: var(--step-0); font-weight: 600; color: var(--lesegrau); }
.person__name span { font-size: var(--step--1); color: var(--lesegrau-mut); }

/* Qualifikationen der Geschaeftsfuehrerin (legal.ownerQualifikationen) unter
   Name und Rolle, abgesetzt durch eine Haarlinie. Volle Lesefarbe statt
   gedaempft: Makler und Eigentuemer sollen sie lesen, nicht ueberlesen.
   Nicht in der kompakten Fassung (Kontakt, Objektanfrage). */
.person__titel {
  margin: 0.6rem 0 0;
  padding: 0.6rem 0 0;
  border-top: 1px solid var(--border);
  display: grid;
  gap: 0.25rem;
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--lesegrau);
}

/* Kompakt: quadratischer Ausschnitt neben Name und Rolle. Das Gesicht sitzt
   im 4:5-Zuschnitt im oberen Drittel — der Ausschnitt haengt deshalb oben. */
.person--kompakt,
.person--abbinder {
  display: grid;
  grid-template-columns: 5rem 1fr;
  gap: 1rem;
  align-items: center;
}
.person--kompakt .person__bild img,
.person--abbinder .person__bild img {
  aspect-ratio: 1;
  object-fit: cover;
  object-position: 50% 0;
}

/* Gross: Hochformat, Name darunter an einer kurzen Limettenlinie. */
.person--gross { max-width: 20rem; }
.person--gross .person__bild img { aspect-ratio: 4 / 5; }
.person--gross .person__name,
.person--abbinder .person__name { position: relative; }
.person--gross .person__name {
  margin-top: 1rem;
  padding-top: 0.9rem;
}
.person--gross .person__name::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 1.4rem;
  height: 2px;
  background: var(--accent-2);
}

/* Über uns: Text an der linken Fluchtlinie, das Portraet rechts daneben.
   Im DOM steht das Portraet zuerst — mobil sieht man zuerst, wer die
   Ansprechpartnerin ist. */
.vorstellung { display: grid; gap: clamp(2.5rem, 6vw, 4rem); align-items: start; }
@media (min-width: 900px) {
  .vorstellung {
    grid-template-columns: minmax(0, 34rem) minmax(16rem, 22rem);
    column-gap: clamp(3rem, 8vw, 8rem);
  }
  .vorstellung .person { grid-column: 2; grid-row: 1; max-width: none; }
  .vorstellung .spur   { grid-column: 1; grid-row: 1; }
}

/* Auf dem Petrolband (Abbinder, Objektanfrage): helle Schrift. */
.abbinder .person__name strong { color: var(--accent-ink); }
.abbinder .person__name span { color: color-mix(in srgb, var(--accent-ink) 80%, var(--petrol-tief)); }
.abbinder .person__titel {
  color: var(--accent-ink);
  border-top-color: color-mix(in srgb, var(--accent-ink) 25%, transparent);
}

/* Abbinder der Startseite: mobil eine Zeile unter dem Text wie eine
   Unterschrift, ab 900 px das Hochformat in der rechten Spalte. */
.abbinder__raster { display: grid; gap: clamp(2rem, 5vw, 3rem); }
@media (min-width: 900px) {
  .abbinder__raster {
    grid-template-columns: minmax(0, 1fr) 17rem;
    column-gap: clamp(3rem, 8vw, 8rem);
    align-items: end;
  }
  .person--abbinder { display: block; }
  .person--abbinder .person__bild img { aspect-ratio: 4 / 5; }
  .person--abbinder .person__name { margin-top: 1rem; }
}

/* ==========================================================================
   Objekte-Modul 1.3.0: Videos, Unterlagen, Energiezeile in der Karte,
   Widerrufs-Hinweis unter dem Anfrageformular.
   ========================================================================== */

/* Videos unter der Galerie: dieselbe Spur, ein Video volle Breite, mehrere zu zweit. */
.objekt-videos { display: grid; gap: 0.75rem; }
@media (min-width: 760px) {
  .objekt-videos { grid-template-columns: repeat(2, 1fr); }
  .objekt-videos > :only-child { grid-column: 1 / -1; }
}
.objekt-video { margin: 0; }
.objekt-video video {
  width: 100%;
  aspect-ratio: 16 / 9;
  display: block;
  background: var(--planblau);
  border-radius: var(--radius-sm);
  object-fit: contain;
}

/* Unterlagen: im Datenblatt-Stil der Eckdaten, als Liste mit Groesse. */
.objekt-unterlagen { margin-top: var(--space-md); }
.objekt-unterlagen h2 {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lesegrau-mut);
  margin: 0 0 0.25rem;
}
.objekt-unterlagen ul { list-style: none; margin: 0; padding: 0; }
.objekt-unterlagen li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--step-0);
}
.objekt-unterlagen a { color: var(--accent); font-weight: 600; text-decoration: none; overflow-wrap: anywhere; }
.objekt-unterlagen a:hover { text-decoration: underline; }
.objekt-unterlagen span { color: var(--lesegrau-mut); white-space: nowrap; }

/* Energiezeile in der Karte: Pflichtangabe nach GEG, klein und ruhig, aber da. */
.objekt-karte__energie {
  margin: 0.4rem 0 0;
  font-size: var(--step--1);
  color: var(--lesegrau-mut);
  line-height: 1.45;
}

/* Widerrufs-Hinweis auf dem dunklen Band: lesbar, nicht laut. */
.objekt-anfrage__hinweis {
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.5;
  color: color-mix(in srgb, #fff 85%, var(--accent-2));
}
.objekt-anfrage__hinweis a { color: #fff; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--accent-2); }
