/* =====================================================================
   Steinteppich-Bauer — ITB Instandsetzungsteam Bauer, Österreich
   Onepager, handgeschriebenes CSS, kein Build-Step.

   GESTALTUNGSPRINZIP — „Prüfprotokoll"
   Die Seite liest sich wie ein technischer Befund, nicht wie ein Prospekt:
   Linien statt Kärtchen, rechte Winkel statt Rundungen, Zahlen als Grafik.
   Eigenständigkeit entsteht aus Ordnung, nicht aus Abwechslung.

   DIE VIER REGELN. Sie sind der ganze Grund, warum die Seite ruhig wirkt —
   jede Ausnahme kostet mehr, als sie bringt:

   1. EINE SCHRIFT, EINE BREITE.  Archivo variabel, Breitenachse fest auf
      100 % (im Font instanziiert, also technisch nicht umgehbar).
   2. ZWEI GEWICHTE.  400 für alles Laufende, 700 für Überschriften und
      Hervorhebungen. Kein 300, kein 500, kein 600, kein 800.
   3. DREI GRADE: h1, h2, Text (16 px).  Kein einziger Schriftgrad steht
      ausserhalb dieser Skala — auch nicht „nur kurz".
   4. EINE ABSTANDSSKALA (--s1 … --s7, Vielfache von 8 px).  Kein margin,
      kein padding mit freier Zahl, keine Inline-Abstände im Markup.

   Ausnahmen von Regel 4 — es sind genau zwei, beide sind OPTISCHE Korrekturen
   unterhalb der Wahrnehmungsschwelle und keine Layout-Abstände. Wer eine
   dritte hinzufügt, hat die Regel verloren:
     .zustimmung input  margin-top .2rem   — Kästchen auf die erste Textzeile
     .kopf p            padding-bottom .35rem — Grundlinie an die Überschrift

   FARBE
   Palette des DRUCKFLYERS des Kunden (08.2026). Die Seite lief
   zwischenzeitlich auf Orange, dann kurz auf den Farben der alten Website;
   der Flyer ist die verbindlichere Quelle, weil er ein gestaltetes Stueck
   ist. Werte aus der PDF ausgelesen und am Rendering gegengeprueft.
     --akzent      #4A842F  Flaechen mit WEISSER Schrift und zugleich
                            Schrift/Sinnbilder auf Weiss, beides 4.53:1
     --gruen-tief  #002E21  Grund von Kopfband und Fusszeile, weiss 14.86:1
     --gelb        #FEED0F  nur das Siegel, dunkle Schrift 13.49:1
   Der Flyerton selbst (#4E8C32) ist ein Mittelton und traegt WEDER weisse
   (4.10) NOCH dunkle Schrift (3.99). Deshalb 3 % abgedunkelt — sichtbar
   ist der Unterschied nicht, rechnerisch entscheidet er alles.
   Anthrazit traegt nur noch Ueberschriften und die Fusszeile: als
   Schaltflaechenfarbe wirkte es zusammen mit einem dunklen Abschnitt und
   dem dunklen Auftakt zu streng fuer Terrassen von Hausbesitzern.
   ===================================================================== */

/* ---------- Schrift: lokal, kein CDN (DSGVO) ---------- */
@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-var.woff2") format("woff2-variations");
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
}

/* ---------- Token ---------- */
:root {
  /* Farbe — neutral, plus ein Akzent */
  --tinte:       #221F20;   /* Schriftschwarz des Flyers (16.34:1 auf Weiss) */
  --tinte-weich: #3D3D3D;   /* Hervorhebungen im Fliesstext */
  --grau:        #5E5E5E;   /* Fliesstext (6.48:1 auf Weiss) */
  --linie:       #E2E2E1;
  --linie-stark: #C9C9C7;
  --flaeche:     #F4F4F2;   /* abgesetzte Abschnitte */
  --weiss:       #FFFFFF;
  /* Palette aus dem DRUCKFLYER des Kunden (08.2026) — die verbindlichste
     Quelle, die es gibt: ein gestaltetes Stück, nicht die alte Website.
     Werte aus der PDF-Datei ausgelesen (Füllfarben der Vektorobjekte) und
     am Rendering gegengeprüft; beide Wege stimmen überein.

     ACHTUNG, hier steckt der eine Haken: das Flyergrün #4E8C32 ist ein
     MITTELTON. Weisse Schrift darauf schafft 4.10, dunkle 3.99 — BEIDE
     unter 4.5. Im Druck fällt das nicht auf, dort ist die Schrift gross;
     eine 16-px-Schaltfläche zählt aber nicht als grosse Schrift.
     Deshalb ist der Ton um 3 % Helligkeit abgedunkelt: #4A842F trägt
     weisse Schrift mit 4.53 und ist vom Original nicht zu unterscheiden.
     Der Flyer setzt dort ebenfalls WEISS — die Anmutung stimmt also. */
  --akzent:        #4A842F;   /* Flächen mit WEISSER Schrift (4.53:1) und
                                 zugleich Schrift/Sinnbilder auf Weiss (4.53:1) */
  --akzent-dunkel: #3E6F27;   /* Überfahren — ABdunkeln, weil die Schrift
                                 jetzt weiss ist (vorher genau umgekehrt) */
  --gruen-tief:    #002E21;   /* Grund von Kopfband und Fusszeile im Flyer.
                                 Weisse Schrift 14.86:1. */
  --gelb:          #FEED0F;   /* Signalfläche, nur das Siegel. 13.49:1 zu --tinte */

  /* Zustände */
  --fehler: #B3261E;
  --erfolg: #2E6B36;

  /* Schriftgrade — DREI. h1, h2, Text. Mehr gibt es nicht.
     Es waren zwischenzeitlich sechs, dann vier; beides war zu viel und die
     Grade waren zu gross. Jetzt: 16 px Fliesstext am Schreibtisch, darüber
     genau zwei Überschriftengrade.
     Alles Nebensächliche — Bildunterschrift, Navigation, Formularmarke,
     Rechtszeile, Angabenzeile — läuft ebenfalls auf 16 px und unterscheidet
     sich über FARBE und GEWICHT, nicht über die Grösse.
     Die Positionsziffern benutzen den h2-Grad. */
  --t-text: 1rem;                                       /* 16 — alles Laufende */
  --t-h2:   clamp(1.625rem, 1.15rem + 1.9vw, 2rem);     /* 26 → 32 */
  --t-h1:   clamp(2.125rem, 1.4rem + 3vw, 3rem);        /* 34 → 48 */

  /* Zeilenabstand — drei */
  --z-eng:   1.06;   /* h1, h2 */
  --z-mittel:1.35;   /* h3, Einleitung */
  --z-weit:  1.65;   /* Fliesstext */

  /* Abstandsskala — Vielfache von 8 */
  --s1: 0.5rem;    /*   8 */
  --s2: 1rem;      /*  16 */
  --s3: 1.5rem;    /*  24 */
  --s4: 2.5rem;    /*  40 */
  --s5: 4rem;      /*  64 */
  --s6: 6rem;      /*  96 */
  --s7: 9rem;      /* 144 */

  /* Raster */
  --container: 1200px;
  --pad: clamp(1.25rem, 5vw, 2.5rem);
  /* Die Leiste richtet sich nach der Wortmarke: sie ist gestapelt (Dach
     über Schriftzug) und braucht Höhe, um lesbar zu bleiben. */
  --header-h:       104px;
  --header-h-klein:  88px;
  /* EIN Abschnittsabstand für die ganze Seite. Unterschiedlich grosse
     Abstände zwischen den Abschnitten waren der zweite Grund für den
     unruhigen Eindruck. */
  --abschnitt: clamp(3rem, 5.5vw, 4.5rem);

  --ease: cubic-bezier(.22, 1, .36, 1);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html {
  -webkit-text-size-adjust: 100%; scroll-behavior: smooth;
  /* Beim Überscrollen wird der Bereich ausserhalb der Seite sichtbar.
     ACHTUNG: sobald <html> eine eigene Hintergrundfarbe hat, wandert der
     Hintergrund von <body> nicht mehr auf die Leinwand, sondern wird zu
     einer gewöhnlichen Ebene — alles mit negativem z-index verschwindet
     dahinter. Deshalb arbeitet die Seite ohne negative z-index. */
  background: var(--tinte);
  color-scheme: light;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
body {
  font-family: "Archivo", ui-sans-serif, system-ui, "Segoe UI", Arial, sans-serif;
  font-size: var(--t-text);
  font-weight: 400;
  line-height: var(--z-weit);
  color: var(--grau);
  background: var(--weiss);
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;   /* Zahlen laufen überall auf gleicher Breite */
  overflow-x: hidden;
}
img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; }
[hidden] { display: none !important; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--akzent); outline-offset: 3px; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--tinte); color: #fff; padding: var(--s2) var(--s3);
}
.skip-link:focus { left: 0; }

/* ---------- Typografie ----------
   Regel 2 und 3 in Code: zwei Gewichte, drei Grade. Der Unterschied
   zwischen Überschrift und Text entsteht über Grad, Gewicht und Farbe —
   nicht über eine zweite Schrift, nicht über Versalien, nicht über
   Sperrung. Genau diese Häufung von Mitteln hat vorher billig gewirkt. */
h1, h2, h3, h4 { color: var(--tinte); font-weight: 700; text-wrap: balance; }
h1 { font-size: var(--t-h1); line-height: var(--z-eng); letter-spacing: -0.022em; }
h2 { font-size: var(--t-h2); line-height: var(--z-eng); letter-spacing: -0.022em; }
h3 { font-size: var(--t-text); line-height: var(--z-mittel); }
h4 { font-size: var(--t-text); line-height: var(--z-mittel); }
p  { max-width: 68ch; }
strong, b { font-weight: 700; color: var(--tinte-weich); }

.lead  { color: var(--tinte-weich); }
.klein { font-size: var(--t-text); }

/* Telefonnummer im Fliesstext: unterstrichen statt farbig. Orange erreicht
   in Textgrösse nur 3.55:1 und wäre hier unzulässig.
   `nowrap`, weil die Leerstellen in „+43 316 46 822 47" echte Umbruchstellen
   sind: der Satz brach mitten in der Nummer und liess „47" allein auf der
   nächsten Zeile stehen. Jetzt wandert sie als Ganzes nach unten. Sie misst
   185 px und passt damit auch in die schmalste Spalte (280 px bei 320 px
   Bildschirmbreite) — kein Überlauf. */
.tel-link { font-weight: 700; color: var(--tinte); text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
.tel-link:hover { color: var(--akzent); text-decoration-color: var(--akzent); }

/* Aufeinanderfolgende Absätze bekommen ihren Abstand hier — nicht als
   Inline-Angabe im Markup. Das war die dritte Quelle für uneinheitliche
   Abstände: fünfzehn verschiedene margin-top-Werte direkt im HTML. */
p + p,
p + .btn, p + ul, p + ol, p + address, h3 + p, h2 + p { margin-top: var(--s2); }
div + .karten, p + .karten { margin-top: var(--s4); }
.lead + p, p + .lead { margin-top: var(--s3); }

/* ---------- Layout ---------- */
.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--pad); }
.abschnitt { padding-block: var(--abschnitt); }
[id] { scroll-margin-top: calc(var(--header-h-klein) + var(--s3)); }

/* Gliederung: Flächenwechsel und Haarlinie. Keine Label-Zeilen über den
   Überschriften — ausdrückliche Vorgabe des Auftraggebers.
   Zwei Flächen, mehr nicht: Weiss und ein heller Ton. Der frühere dritte,
   anthrazitfarbene Abschnitt ist entfallen. */
.abschnitt--flaeche { background: var(--flaeche); }
.abschnitt--linie   { border-top: 1px solid var(--linie); }

/* Abschnittskopf.
   Bis 2026-08-08 stand die Einleitung als eigener Textblock RECHTS neben
   der Überschrift. Vom Kunden auf allen Abschnitten beanstandet: zwei
   Textsäulen nebeneinander zwingen den Blick zum Springen, und der rechte
   Block hing ohne Bezug in der Fläche. Jetzt läuft die Einleitung direkt
   unter der Überschrift in EINER Spalte — Lesefluss von oben nach unten,
   wie in jedem Fließtext. Die Zeilenlänge bleibt begrenzt, damit daraus
   kein Textteppich wird. */
.kopf { margin-bottom: var(--s4); max-width: 62ch; }
.kopf > * + * { margin-top: var(--s2); }
.kopf p { max-width: 58ch; }

/* ---------- Schaltflächen ----------
   Orange als Fläche mit DUNKLER Schrift: 4.90:1, damit für Fliesstext
   zulässig. Das ist der Punkt, an dem das alte Farbproblem kippt — weiss
   auf demselben Orange erreichte nur 3.55:1, und genau deshalb brauchte
   die frühere Fassung einen zweiten, bräunlichen Ton, der den Auftritt
   billig gemacht hat. Mit dunkler Schrift trägt der Markenton selbst.
   Anthrazit-Schaltflächen wirkten dagegen streng bis düster — bei
   Terrassen für Hausbesitzer der falsche Ton. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: var(--s1) var(--s4);
  font-size: var(--t-text); font-weight: 700; line-height: 1.2;
  border: 1px solid transparent; border-radius: 0; cursor: pointer;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
/* Aufhellen statt Abdunkeln beim Überfahren: nach unten würde der Kontrast
   zur dunklen Schrift unter 4.5 fallen, nach oben steigt er auf 5.59. */
/* Die Schriftfarbe der Hauptschaltfläche steht FEST und folgt nicht den
   Token: in dunklen Abschnitten ist --tinte hell, dadurch stand vorher
   helle Schrift auf Orange (3.17:1 statt 4.90:1). Die Fläche ist in
   beiden Fällen dieselbe, also muss es die Schrift auch sein. */
.btn--primaer { background: var(--akzent); color: #fff; }
.btn--primaer:hover { background: var(--akzent-dunkel); }
.btn--linie { border-color: var(--linie-stark); color: var(--tinte); background: transparent; }
.btn--linie:hover { border-color: var(--tinte); }
/* (Der Umriss-Knopf im Auftakt brauchte eine eigene helle Kante, solange er
   auf dem Foto stand. Seit der Text auf der weissen Tafel sitzt, gilt
   wieder die normale Regel — die Sonderregel ist entfallen.) */
.btn--block { width: 100%; }

/* ---------- Kopfzeile ----------
   ZWEI ZUSTÄNDE, auf Ansage des Auftraggebers („хедер должен быть не белым
   а там должен быть банер"): am Seitenanfang liegt die Leiste durchsichtig
   auf der Bildfolge, beim Scrollen wird sie weiss.
   Das Foto reicht ohnehin bis zur Oberkante — die Leiste ist fest
   positioniert und nimmt keinen Platz im Fluss ein; die weisse Fläche hat
   es bisher nur verdeckt.
   Der durchsichtige Zustand hängt an `.js`: ohne JavaScript wird
   `.is-scrolled` nie gesetzt, die Leiste bliebe beim Scrollen durchsichtig
   und weisse Schrift stünde auf weissem Grund. Ohne JS also immer weiss. */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 100; height: var(--header-h);
  display: flex; align-items: center;
  /* DECKEND, nicht .97: bei 3 % Durchlass schien alles darunter durch —
     das Laufband, das orange Farbband, Überschriften. Gemessen an jedem
     Abschnitt sichtbar, am deutlichsten über dem Farbband. */
  background: var(--weiss); box-shadow: 0 1px 0 var(--linie);
  transition: height .25s var(--ease);
}
.site-header.is-scrolled { height: var(--header-h-klein); }

/* --- Durchsichtig über der Bildfolge --------------------------------- */
/* Der Verlauf gehört zur LEISTE, nicht zum Foto: er endet mit ihr und
   lässt den Rest des Bildes unangetastet. Ohne ihn steht die Navigation
   auf hellem Granit und ist stellenweise nicht lesbar — pixelweise
   gemessen an allen vier Bildern, nicht nach Gefühl. */
.js .site-header:not(.is-scrolled) {
  background: linear-gradient(to bottom, rgba(12,12,11,.76) 0%, rgba(12,12,11,.72) 70%, rgba(12,12,11,0) 100%);
  box-shadow: none;
}
.js .site-header:not(.is-scrolled) .nav__link { color: #fff; }
.js .site-header:not(.is-scrolled) .burger span,
.js .site-header:not(.is-scrolled) .burger span::before,
.js .site-header:not(.is-scrolled) .burger span::after { background: #fff; }

/* Zwei Logo-Fassungen übereinander, nicht nebeneinander: sonst wäre die
   Leiste doppelt so breit. Die helle trägt kein alt-Attribut, sonst läse
   ein Screenreader den Firmennamen zweimal. */
.header__logo--hell { display: none; }
.js .site-header:not(.is-scrolled) .header__logo--hell { display: block; }
.js .site-header:not(.is-scrolled) .header__logo--dunkel { display: none; }

/* position: relative als Anker für das Siegel an der Unterkante. */
.header__inner { position: relative; display: flex; align-items: center; gap: var(--s3); width: 100%; }

/* Die Marke bleibt in ihrer originalen, gestapelten Anordnung — geändert
   wurde ausschliesslich die Farbe. Deshalb die hohe Leiste. */
.header__logo { display: flex; align-items: center; min-height: 44px; margin-right: auto; flex: none; }
.header__logo img { height: 72px; width: auto; transition: height .25s var(--ease); }
.is-scrolled .header__logo img { height: 62px; }

.nav { display: flex; align-items: center; gap: var(--s4); }
/* min-height statt padding: 44 px Antippfläche, ohne dass ein Wert
   ausserhalb der Abstandsskala ins CSS kommt. */
.nav__link {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-text); color: var(--tinte-weich); position: relative;
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--akzent); transform: scaleX(0); transform-origin: left;
  transition: transform .2s var(--ease);
}
.nav__link:hover::after, .nav__link.is-active::after { transform: scaleX(1); }

.header__tel {
  display: inline-flex; align-items: center; gap: var(--s1);
  min-height: 44px; padding-inline: var(--s3);
  font-size: var(--t-text); font-weight: 700;
  color: #fff; background: var(--akzent);
}
.header__tel svg { width: 17px; height: 17px; }

.burger {
  display: none; width: 44px; height: 44px; background: none; border: 0; cursor: pointer;
  align-items: center; justify-content: center;
}
.burger span { display: block; width: 24px; height: 2px; background: var(--tinte); position: relative; }
.burger span::before, .burger span::after {
  content: ""; position: absolute; left: 0; width: 24px; height: 2px; background: inherit;
  transition: transform .25s var(--ease);
}
.burger span::before { top: -7px; }
.burger span::after  { top: 7px; }
.burger.is-open span { background: transparent; }
.burger.is-open span::before { transform: translateY(7px) rotate(45deg); background: var(--tinte); }
.burger.is-open span::after  { transform: translateY(-7px) rotate(-45deg); background: var(--tinte); }

/* visibility zusätzlich zu transform: bei einem kurzen Menü (die
   Rechtsseiten haben nur zwei Einträge) reicht -100% der Eigenhöhe nicht,
   um es aus dem Bild zu schieben. */
.mobile-menu {
  position: fixed; inset: var(--header-h) 0 auto 0; z-index: 99;
  background: #fff; border-bottom: 1px solid var(--linie);
  transform: translateY(-100%); visibility: hidden; pointer-events: none;
  transition: transform .3s var(--ease), visibility .3s;
  max-height: calc(100dvh - var(--header-h)); overflow-y: auto;
}
.mobile-menu.is-open { transform: translateY(0); visibility: visible; pointer-events: auto; }
.mobile-menu a {
  display: flex; align-items: center; min-height: 56px;
  padding-inline: var(--pad); color: var(--tinte);
  border-bottom: 1px solid var(--linie);
}
.mobile-menu a:last-child { border-bottom: 0; }

/* ---------- Auftakt ----------
   Der Auftakt lief bis 2026-08-07 als Foto mit weisser Schrift darauf.
   Das erzwingt eine kräftige Abdunklung — sonst ist die Schrift nicht
   lesbar — und macht den Seitenanfang zwangsläufig dunkel. Nachregeln am
   Verlauf hilft nicht: entweder die Schrift verschwindet oder das Bild.
   Deshalb ist die Anordnung getauscht statt nachjustiert. Die Schrift
   steht auf Weiss (17.4:1, kein Verlauf nötig), das Foto steht ungetrübt
   darunter über die volle Breite — es zeigt das Material jetzt so, wie es
   aussieht, statt durch einen dunklen Schleier. */
/* Hintergrundfolge im Auftakt.
   Der Kunde wollte „Video oder grosse Bilder" — Videodateien gibt es im
   Projekt nicht, und eine dafuer erzeugte Datei waere mehrere Megabyte
   schwer. Stattdessen laufen vier vorhandene Projektfotos ueberblendet
   mit langsamem Zoom: dieselbe Wirkung, keine neuen Dateien, und beim
   ersten Laden ist nur EIN Bild noetig (die uebrigen sind lazy).
   Bewegt werden nur transform und opacity — kein Neuberechnen des
   Layouts. Bei prefers-reduced-motion steht die Folge still. */
.hero { position: relative; isolation: isolate; padding-top: calc(var(--header-h) + var(--s4)); overflow: hidden; }
.hero__folge { position: absolute; inset: 0; z-index: 0; }
.hero__folge img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 55%; opacity: 0;
}
/* KEINE Abdunklung mehr — auf Ansage des Auftraggebers („затемнение с фото
   херо секции убрать"). Das Foto steht unbearbeitet.
   Damit trägt der Grund die Schrift nicht mehr: der Text bekommt seinen
   Halt jetzt aus sich selbst (siehe .hero h1 / .hero__lead / .hero__fakten).
   Wer hier wieder einen Verlauf einbaut, macht die Ansage rückgängig. */
@media (prefers-reduced-motion: no-preference) {
  .hero__folge img { animation: hero-wechsel 32s linear infinite; }
  .hero__folge img:nth-child(1) { animation-delay:  0s; }
  .hero__folge img:nth-child(2) { animation-delay:  8s; }
  .hero__folge img:nth-child(3) { animation-delay: 16s; }
  .hero__folge img:nth-child(4) { animation-delay: 24s; }
}
/* Ohne Bewegungswunsch bleibt das erste Bild stehen. */
@media (prefers-reduced-motion: reduce) {
  .hero__folge img:first-child { opacity: 1; }
}
@keyframes hero-wechsel {
  0%   { opacity: 0; transform: scale(1.04); }
  4%   { opacity: 1; }
  25%  { opacity: 1; transform: scale(1.13); }
  30%  { opacity: 0; transform: scale(1.14); }
  100% { opacity: 0; transform: scale(1.04); }
}
.hero > .container, .hero > .hero__fakten, .hero > .buehne { position: relative; z-index: 1; }
.hero__inhalt { padding-bottom: var(--s4); }

/* ---------- Tafel im Auftakt ----------
   Weil das Foto nicht mehr abgedunkelt wird, kann der Grund die Schrift
   nicht mehr tragen. Gemessen ohne Abdunklung, hellster Bildpunkt unter
   jedem Textkasten über alle vier Fotos: weisse Schrift käme auf
   1.01 bis 1.61 statt der nötigen 4.5 — die Fotos enthalten hellen
   Granit und Himmel. Deshalb steht der Text auf einer eigenen weissen
   Fläche und ist wieder dunkel. Das Foto selbst bleibt unangetastet und
   ist rechts und oben in voller Sättigung zu sehen.
   Rechte Winkel wie überall, kein Schatten — die Tafel ist eine Fläche,
   kein schwebendes Kärtchen. */
.hero__tafel { background: var(--weiss); padding: var(--s3); max-width: 60ch; }
.hero__lead { color: var(--grau); line-height: var(--z-mittel); }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3); max-width: none; }

/* Am Schreibtisch derselbe Bauplan wie bei jedem Abschnittskopf:
   Überschrift links, Text rechts, an der Unterkante bündig.
   Vorher stand die Überschrift allein in einer 20ch schmalen Spalte und
   liess rechts 589 px leer stehen (gemessen), die Einleitung sogar 738 px —
   während Angabenzeile und Bildfolge darunter die volle Breite nutzten.
   Genau dieser Sprung hat den Auftakt löchrig wirken lassen. */
/* Alles in EINER Spalte links — Überschrift, Einleitung, Schaltflächen
   untereinander. Vorher stand die Einleitung als zweiter Textblock rechts;
   derselbe Einwand wie bei den Abschnittsköpfen: zwei Textsäulen zwingen
   den Blick zum Springen. Die Spalte endet bei gut der halben Breite,
   damit rechts das Foto sichtbar bleibt. */
@media (min-width: 900px) {
  .hero { min-height: min(86vh, 760px); display: flex; flex-direction: column; justify-content: flex-end; }
  /* PFLICHT: Als Flex-Kind zieht sich der Satzspiegel sonst auf die Breite
     seines Inhalts zusammen — gemessen 644 statt 1200 px, dadurch begann die
     Überschrift bei 438 px, während Logo und Angabenzeile bei 160 px stehen.
     Der Auftakt stand also nicht mehr im selben Raster wie der Rest. */
  .hero > * { width: 100%; }
  .hero__inhalt { display: block; padding-bottom: var(--s5); }
  /* Innenabstand --s3 (24) wie am Telefon — der Weg war 64 → 40 → 24,
     jeder Schritt auf Ansage. Kleiner geht nicht: die Skala kennt darunter
     nur 16, und damit klebte die Überschrift an der Kante.
     Breite 620: die beiden Schaltflächen messen zusammen 563 px
     (344 + 203 + 16), plus 2 × 24 Innenabstand sind das 611 — darunter
     bricht die zweite Schaltfläche um. Gemessen, nicht geschätzt. */
  .hero__tafel { max-width: 620px; }
  .hero h1 { max-width: 15ch; }
  .hero__neben { margin-top: var(--s3); }
  .hero__lead { max-width: 44ch; }
}
@media (max-width: 899px) {
  .hero__lead { margin-top: var(--s3); }
}

/* ---------- Siegel im Banner ----------
   Auf Kundenwunsch, Vorlage war ein rundes gelbes Störerzeichen auf einem
   Foto. Der Ort ist geklärt: **auf das Foto**, nicht in die weisse Leiste
   („это в банер можно а не в хедер"). Schrift in VERSALIEN und SCHRÄG,
   wie in der Vorlage.

   GELB `var(--gelb)` — **pixelweise vom Bestandsauftritt des Kunden
   abgenommen** (dach-und-fassaden.com, Siegel im Auftakt; dort ist es eine
   Bilddatei, keine CSS-Farbe, deshalb aus dem gerenderten Kreis gemessen:
   23 969 Pixel dieses Wertes). Der Zwischenstand `#F7B02E` aus dem
   Logoverlauf war zu bräunlich und wurde beanstandet.
   Das ist eine bewusste Ausnahme vom Farbsystem, in dem Gelb gestrichen
   war — als **Schrift** bleibt es weiter verboten. Hier trägt es eine
   Fläche mit dunkler Schrift: --tinte auf var(--gelb) = **13.49:1**.
   Es kommt genau einmal auf der Seite vor; sobald es sich wiederholt,
   kippt der Auftritt in die Richtung zurück, die als billig beanstandet
   wurde.

   Der Kreis ist die EINZIGE Rundung der Seite. Das ist Absicht: er liest
   sich dadurch als aufgeklebtes Zeichen und nicht als Bauteil des
   Rasters, in dem sonst durchgehend rechte Winkel gelten. Bleibt es bei
   diesem einen Vorkommen, ist es eine Auszeichnung; wiederholt sich die
   Form, wird sie zur Dekoration.

   GRÖSSE folgt der Schrift, nicht umgekehrt: VERSALIEN sind breit —
   „FESTPREIS" misst bei 32 px fett 185 px, bei 16 px fett 93 px. Der
   Kreis muss so gross sein, dass die längere Zeile auf ihrer Höhe noch
   in die Sehne passt, sonst stösst die Schrift an den Rand.
   Der Weg war 152 → 236 → 160 → 116 → 216, und die Lehre daraus steht
   hier: die Beanstandung „много пустого пространства вокруг текста" galt
   dem VERHÄLTNIS, nicht der absoluten Grösse. Beides hängt zusammen —
   Grad und Durchmesser müssen gemeinsam wandern, sonst schwimmt die
   Schrift oder stösst an den Rand.
   Vorlage des Auftraggebers (sein Bestandsauftritt): Schrift füllt den
   Kreis zu 0.79. Am Schreibtisch deshalb h2-Grad und **216 px**
   (rechnerisches Minimum 208, Verhältnis 0.86). Am Telefon bleibt es beim
   Textgrad und **116 px** (Minimum 109, Verhältnis 0.81) — ein 216er
   Kreis nähme dort die halbe Bildschirmbreite ein.

   SCHRÄG wie in der Vorlage: -13°. Der Kreis ist drehsymmetrisch, sichtbar
   gedreht wird also nur die Schrift. ACHTUNG: am Schreibtisch muss die
   Drehung MIT der Zentrierung in EINER transform-Angabe stehen — zwei
   getrennte Regeln überschreiben einander, und die Zentrierung fiele weg. */
.siegel {
  display: grid; place-content: center; justify-items: center;
  width: 116px; height: 116px; border-radius: 50%;
  background: var(--gelb); color: var(--tinte);
  font-size: var(--t-text); font-weight: 700; line-height: 1.15;
  text-transform: uppercase; letter-spacing: .01em; text-align: center;
  margin-left: auto; margin-top: var(--s3); max-width: none;
  transform: rotate(-13deg);
}
.siegel span { display: block; }
/* Die Rufnummer darf nie umbrechen — zweizeilig sieht die Schaltfläche
   kaputt aus. (Aus dem Versuch, das Siegel in die Leiste zu setzen; die
   Absicherung bleibt sinnvoll.) */
.header__tel { white-space: nowrap; }

/* Am Schreibtisch rechts auf dem Foto, aber NICHT mehr an der äussersten
   Kante des Satzspiegels: dort klebte der Kreis am Rand und lag auf dem
   Gitterrost des ersten Fotos. Auf Ansage („кружочек справа нужно
   передвинуть") sitzt er jetzt **mittig im freien Streifen** zwischen der
   Texttafel und der rechten Kante.
   Die Rechnung: freier Streifen = Satzspiegel − 620 px Tafel; der Kreis
   steht in dessen Mitte, also 58 px (halber Durchmesser) davor.
   Bei 1200 px Satzspiegel sind das 232 px Abstand von rechts, bei
   schmalerem Fenster entsprechend weniger — der Kreis wandert mit und
   stösst nie an die Tafel.
   Erst ab 1000 px, NICHT ab 900: bei 900 steht die Tafel schon fast über
   die ganze Breite. Bis dahin läuft der Kreis im Fluss unter ihr mit. */
@media (min-width: 1000px) {
  .siegel {
    position: absolute; right: calc((100% - 620px) / 2 - 108px); top: 50%;
    transform: translateY(-50%) rotate(-13deg);
    width: 216px; height: 216px; margin: 0;
    font-size: var(--t-h2); line-height: 1.1;
  }
}

/* Angabenzeile: eine Zeile, linksbündig, durch Haarlinien getrennt — keine
   gleich breiten Drittel mit Sinnbild, das war das erkennbarste Muster. */
/* Ebenfalls auf eigener Fläche: seit das Foto nicht mehr abgedunkelt wird,
   stünde die Zeile sonst dunkel auf hellem Granit. */
.hero__fakten { border-block: 1px solid var(--linie); background: var(--weiss); }
.hero__fakten ul {
  display: flex; flex-wrap: wrap; align-items: baseline;
  list-style: none; padding: 0; margin: 0;
}
.hero__fakten li { padding-block: var(--s2); font-size: var(--t-text); }
.hero__fakten li + li::before {
  content: ""; display: inline-block; width: 1px; height: .9em;
  background: var(--linie-stark); margin-inline: var(--s3);
  transform: translateY(.08em);
}

/* ---------- Bühne (Bildfolge) ----------
   DERZEIT NICHT IM MARKUP. Sie stand im Auftakt unter der Hintergrundfolge —
   zweimal Fotos direkt hintereinander. Der Auftraggeber wollte eins von
   beidem, die Wahl fiel auf den Hintergrund. Die Regeln bleiben stehen,
   weil die Folge in einem anderen Abschnitt wiederverwendet werden kann;
   das Ziehen mit der Maus und die Bedienung sind fertig und geprüft.
   ---------- (ursprünglich: Bildfolge im Auftakt) ----------
   Bewusst NICHT über die volle Breite: die Folge sitzt im Satzspiegel wie
   jeder andere Inhalt, und der nächste Ausschnitt schaut rechts hervor.
   Das zeigt ohne Punkte und ohne Beschriftung, dass es weitergeht.
   Gescrollt wird nativ (scroll-snap) — dadurch funktionieren Wischen am
   Telefon, Trackpad und Tastatur ohne eigenen Code. */
.buehne__spur {
  display: flex; gap: var(--s2);
  /* overflow-x: auto macht den Kasten in BEIDEN Richtungen scrollbar —
     overflow-y steht dann implizit ebenfalls auf auto. Genau daher kam
     das senkrechte Ruckeln in der Bildfolge. */
  overflow-x: auto; overflow-y: hidden;
  /* NUR waagrecht abfangen. „contain" auf beiden Achsen hat verhindert,
     dass das Mausrad ueber der Bildfolge die SEITE scrollt — man blieb
     mit dem Zeiger darin haengen. */
  overscroll-behavior-x: contain; overscroll-behavior-y: auto;
  align-items: start;           /* sonst dehnt sich die Folie und wird zu hoch */
  scroll-snap-type: x mandatory;
  list-style: none; padding: 0; margin: 0;
  scrollbar-width: none;
  cursor: grab;                 /* am Schreibtisch ziehbar */
  touch-action: pan-x pinch-zoom;
}
.buehne__spur.wird-gezogen { cursor: grabbing; scroll-snap-type: none; }
/* Waehrend des Ziehens darf das Bild nicht als Bild aufgenommen werden. */
.buehne__spur.wird-gezogen img { pointer-events: none; user-select: none; }
.buehne__spur::-webkit-scrollbar { display: none; }
.buehne__spur > li { flex: 0 0 86%; scroll-snap-align: start; }
@media (min-width: 900px) { .buehne__spur > li { flex: 0 0 68%; } }
/* Der Parallax vergroessert das Bild um 14 %. Ohne eigenen Rahmen ragte es
   dadurch 35 px ueber die Spur hinaus und erzeugte genau die senkrechte
   Scrollbarkeit, die als Ruckeln aufgefallen ist. Der Ausschnitt haelt die
   Vergroesserung jetzt fest. */
.buehne__spur > li { overflow: hidden; }
.buehne__spur img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; }

/* Bedienleiste: Zähler links, Schaltflächen rechts, dazwischen die
   Haarlinie, die auch sonst die Abschnitte gliedert. */
/* Bedienelemente liegen AUF dem Bild statt darunter. Darunter kostete die
   Leiste eine eigene Zeile plus Haarlinie — Platz, der unter der Bildfolge
   nur leer stand. Der Hinweis „Zum Blättern ziehen oder wischen" ist
   entfallen: eine Bildfolge mit sichtbar hervorschauendem nächsten
   Ausschnitt erklärt sich selbst. */
.buehne__rahmen { position: relative; }

.buehne__knopf {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 56px; height: 56px; padding: 0; display: grid; place-items: center;
  background: rgba(255,255,255,.94); color: var(--tinte); border: 0; cursor: pointer;
  transition: background-color .2s var(--ease), opacity .2s var(--ease);
}
.buehne__knopf:hover:not([disabled]) { background: #fff; }
.buehne__knopf[disabled] { opacity: 0; pointer-events: none; }   /* am Rand einfach weg */
.buehne__knopf svg { width: 22px; height: 22px; }
.buehne__knopf--zurueck { left: 0; }
.buehne__knopf--vor { right: 0; }

/* Zähler in der Bildecke, damit er keine eigene Zeile braucht. */
.buehne__zaehler {
  display: block; position: absolute; left: 0; bottom: 0; z-index: 2; margin: 0;
  padding: var(--s1) var(--s2);
  background: rgba(18,18,17,.82); color: #fff; font-weight: 700;
}
.buehne__zaehler span { color: rgba(255,255,255,.7); font-weight: 400; }

@media (max-width: 640px) {
  .buehne__knopf { width: 48px; height: 48px; }
}

/* Ohne JavaScript bleibt die Folge waagrecht scrollbar; die Schaltflächen
   wären dann wirkungslos und werden deshalb nur unter .js gezeigt. Der
   Zähler bleibt sichtbar, er stimmt auch ohne Skript. */
.buehne__knopf { display: none; }
.js .buehne__knopf { display: grid; }

/* =====================================================================
   HANDSCHRIFT — was diese Seite von einer beliebigen unterscheidet
   Ein Gedanke, konsequent durchgezogen: das Material selbst ist die
   Grafik. Steinteppich besteht aus Körnung, also liegt über der ganzen
   Seite ein feines Korn, das Material trennt die Abschnitte, und der
   einzige dunkle Block zeigt eine fertige Fläche in voller Breite.
   Nichts davon ist Dekoration ohne Bezug — das ist der Unterschied
   zwischen Handschrift und Effekt.
   ===================================================================== */

/* ---------- Korn über der ganzen Seite ----------
   Erzeugt aus SVG-Rauschen, keine Bilddatei, rund 300 Byte. Sehr schwach
   dosiert: auf einem Foto ist es unsichtbar, auf weissen Flächen nimmt es
   die digitale Härte. Fest verankert und ohne Zeigerereignisse, damit es
   beim Scrollen nicht neu gezeichnet wird und nichts blockiert. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 300; pointer-events: none;
  opacity: .045; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='k'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23k)'/%3E%3C/svg%3E");
}
@media print { body::after { display: none; } }

/* ---------- Laufband: das Einsatzgebiet als Materialkante ----------
   Ersetzt den entfernten Materialstreifen. Statt eines verzerrten
   Bildausschnitts laufen hier die Orte des Einzugsgebiets durch — eine
   Angabe, die sonst nur klein in der Fusszeile stünde. */
.laufband {
  overflow: hidden; border-block: 1px solid var(--linie);
  background: var(--flaeche); padding-block: var(--s2);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.laufband__spur {
  display: flex; width: max-content; gap: var(--s5);
  animation: laufen 42s linear infinite;
}
.laufband span { display: inline-flex; align-items: center; gap: var(--s5); white-space: nowrap; color: var(--grau); }
/* Der Punkt zwischen den Orten ist der einzige farbige Akzent hier. */
.laufband span::after { content: ""; width: 5px; height: 5px; background: var(--akzent); flex: none; }
@keyframes laufen { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .laufband__spur { animation: none; } }

/* ---------- Der eine dunkle Block ----------
   Genau EINE Kontraststelle auf der ganzen Seite. Ohne sie liest sich
   alles gleich hell durch; mit zweien wäre die Seite wieder düster. */
.abschnitt--kontrast { background: var(--tinte); color: #C2C2C2; }
.abschnitt--kontrast h2, .abschnitt--kontrast h3 { color: #fff; }
.abschnitt--kontrast .kopf p { color: #C2C2C2; }
.abschnitt--kontrast .referenz { background: #262626; }
.abschnitt--kontrast .referenz figcaption { color: #fff; }

/* =====================================================================
   DUNKLE ABSCHNITTE — der Mix
   Nicht die ganze Seite ist dunkel, sondern drei Stellen: der Auftakt,
   der technische Abschnitt und die ausgefuehrten Arbeiten. Dazwischen
   bleibt es hell. Grund: auf Anthrazit leuchtet das graue Marmorgranulat,
   auf Weiss verblasst es — aber durchgehend dunkel wird eine Seite mit
   so viel Fliesstext anstrengend.

   Umgesetzt ueber lokal umdefinierte Token statt ueber Dutzende
   Einzelregeln: alles darin (Karten, Linien, Formulare, Schaltflaechen)
   rechnet automatisch mit den dunklen Werten weiter.
   ===================================================================== */
.abschnitt--dunkel, .hero--dunkel {
  --tinte:       #F2F2F0;
  --tinte-weich: #D6D6D2;
  --grau:        #A8A7A2;   /* 7.9:1 auf #141413 */
  --linie:       #2E2E2C;
  --linie-stark: #4A4A46;
  --flaeche:     #1F1F1E;
  --weiss:       #141413;
  background: #141413; color: var(--grau);
}
.abschnitt--dunkel .karte, .hero--dunkel .karte { background: var(--flaeche); border-color: var(--linie); }
.abschnitt--dunkel .karte:hover { border-color: var(--akzent); }
.abschnitt--dunkel strong, .hero--dunkel strong { color: #fff; }

/* ---------- Dachform als Hintergrundmotiv ----------
   Der Umriss stammt aus der Wortmarke: eine Reihe Dachschraegen. Sehr
   schwach dosiert (rund 4 % Deckung) und nur auf den dunklen Flaechen —
   dort traegt es, ohne den Text zu stoeren. Auf hellem Grund wuerde
   dasselbe Muster als Tapete lesen.
   Rein dekorativ, deshalb ohne eigenes Element und ohne Alternativtext. */
.abschnitt--dunkel, .hero--dunkel { position: relative; isolation: isolate; }
.abschnitt--dunkel::before, .hero--dunkel::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='120' viewBox='0 0 240 120'%3E%3Cg fill='none' stroke='%234A842F' stroke-width='1.4' stroke-linejoin='round' stroke-opacity='.16'%3E%3Cpath d='M-10 78 L34 40 L78 78'/%3E%3Cpath d='M62 96 L96 68 L130 96'/%3E%3Cpath d='M118 66 L162 28 L206 66'/%3E%3Cpath d='M190 100 L222 74 L254 100'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 240px 120px;
}
/* Der Inhalt liegt ueber dem Muster — niemals mit negativem z-index
   arbeiten, sonst verschwindet er hinter dem Seitenhintergrund. */
/* Der Inhalt liegt über dem Muster — aber NICHT der Hintergrund selbst.
   `.hero--dunkel > *` hat der Bildfolge ihre absolute Lage genommen, sie
   fiel auf Höhe 0 zusammen und war unsichtbar. Deshalb ausdrücklich alles
   AUSSER .hero__folge. */
.abschnitt--dunkel > .container,
.hero--dunkel > *:not(.hero__folge) { position: relative; z-index: 1; }

/* ---------- Aufruf in der Seitenmitte ----------
   Die einzige farbige Flaeche der Seite. Der Markenton traegt hier dunkle
   Schrift (4.90:1) — dieselbe Kombination wie auf den Schaltflaechen, nur
   ueber die volle Breite. Genau EINMAL eingesetzt: mehrere farbige Baender
   nutzen sich ab und lesen sich als Werbung statt als Angebot. */
.ruf { background: var(--akzent); color: #fff; padding-block: var(--s5); }
.ruf h2 { color: #fff; }
.ruf__inhalt { display: grid; gap: var(--s4); align-items: center; }
@media (min-width: 900px) { .ruf__inhalt { grid-template-columns: minmax(0, 1.3fr) auto; } }
/* Auf dem Markenton trägt NUR reines Weiss die 4.5 (4.53). Jede Abtönung
   für „zweitrangig" fiele darunter — deshalb hier keine Abstufung über die
   Farbe. Vorher stand hier #2A1A0C, ein Braunton aus der Orangezeit. */
.ruf p { color: #fff; max-width: 52ch; }
.ruf__aktion { display: flex; flex-direction: column; gap: var(--s2); }
.ruf .btn--primaer { background: var(--gruen-tief); color: #fff; }
.ruf .btn--primaer:hover { background: #000; }
.ruf__nummer {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-h2); font-weight: 700; line-height: var(--z-eng);
  letter-spacing: -0.022em; color: #fff;
}
.ruf__nummer:hover { text-decoration: underline; text-underline-offset: 4px; }
.ruf__label { color: #fff; }

/* Zweiter Aufruf, weiter unten. BEWUSST anders gebaut als das Farbband:
   ruhige Flaeche, die Telefonnummer als groesstes Element, Schaltflaeche
   nur als zweite Wahl. Zwei gleiche Baender haetten sich abgenutzt und
   sich als Werbung gelesen statt als Angebot. */
.ruf2 { background: var(--flaeche); border-block: 1px solid var(--linie); padding-block: var(--s5); }
.ruf2__inhalt { display: grid; gap: var(--s4); align-items: center; }
@media (min-width: 900px) { .ruf2__inhalt { grid-template-columns: minmax(0, 1fr) auto; } }
.ruf2 h2 { margin-bottom: var(--s2); }
.ruf2__nummer {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-h2); font-weight: 700; line-height: var(--z-eng);
  letter-spacing: -0.022em; color: var(--tinte);
  border-bottom: 3px solid var(--akzent);
}
.ruf2__nummer:hover { border-bottom-color: var(--tinte); }
.ruf2__aktion { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); }

/* ---------- Karten ----------
   Bis 2026-08-07 liefen sieben Abschnitte als Listen auf Haarlinien. Das
   war konsequent, aber vom Auftraggeber als „unbequem und unübersichtlich"
   beanstandet: ohne Rahmen und ohne Sinnbild fehlt dem Auge der Halt, und
   sieben gleich aussehende Abschnitte hintereinander verschwimmen.
   Deshalb jetzt Karten mit Sinnbild. Damit daraus kein Baukasten-Raster
   wird, gelten drei Regeln:
     · Sinnbilder sind INHALTLICH — Stufen für Stiegen, Riss für Risse,
       Gefällepfeil für Gefälle. Keine dekorativen Häkchen und Sterne.
     · Ein Umriss, eine Strichstärke, ein Raster (24er-Feld). Sinnbilder
       aus verschiedenen Quellen sind das sicherste Erkennungszeichen
       zusammengeklickter Seiten.
     · Kein Schlagschatten, keine Rundung, keine Verläufe — die Karte ist
       ein Feld mit Haarlinie, kein schwebendes Kärtchen. */
/* EINE Rasterbreite für alle Karten: drei Spalten. Vorher liefen drei
   verschiedene Raster nebeneinander (2, 3 und 4 Spalten) — dadurch war
   jede Karte anders breit als die im nächsten Abschnitt, und das las sich
   als Unordnung. Knappe Karten (einzeilig) haben ihr eigenes, gröberes
   Raster, weil drei Spalten dort nur Leerraum erzeugen würden. */
.karten { display: grid; gap: var(--s2); }
@media (min-width: 640px) and (max-width: 899px) { .karten { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .karten { grid-template-columns: repeat(3, 1fr); } }

/* Angebrochene Reihe schliessen. Sieben Karten auf drei Spalten liessen
   unten zwei Felder leer, fünf Karten eines — beides sah aus wie ein
   Fehler. Die letzte Karte füllt jetzt den Rest der Reihe.
   3n+1 = eine Karte übrig, 3n+2 = zwei Karten übrig; geht es glatt auf,
   greift keine der beiden Regeln. */
@media (min-width: 900px) {
  .karten > .karte:last-child:nth-child(3n + 1) { grid-column: span 3; }
  .karten > .karte:last-child:nth-child(3n + 2) { grid-column: span 2; }
}
@media (min-width: 640px) and (max-width: 899px) {
  .karten > .karte:last-child:nth-child(2n + 1) { grid-column: span 2; }
}

/* Vier Karten gehen in drei Spalten nicht auf: die letzte würde sich über
   die ganze Breite ziehen und wäre dreimal so breit wie ihre Nachbarn —
   das liest sich als Fehler. Zwei Spalten teilen den Satzspiegel sauber,
   alle vier Karten bleiben gleich gross. */
@media (min-width: 640px) {
  .karten--paare { grid-template-columns: repeat(2, 1fr) !important; }
  .karten--paare > .karte:last-child { grid-column: auto !important; }
}

/* Knappe Karten: eine Zeile Text, deshalb zwei Spalten statt drei. */
@media (min-width: 640px) { .karten--knapp { grid-template-columns: repeat(2, 1fr) !important; } }
@media (min-width: 640px) {
  .karten--knapp > .karte:last-child:nth-child(2n + 1) { grid-column: span 2 !important; }
  .karten--knapp > .karte:last-child:nth-child(3n + 2) { grid-column: auto; }
}

.karte {
  background: var(--weiss);
  border: 1px solid var(--linie);
  display: flex; flex-direction: column;
}
/* Innenabstand sitzt auf dem Textteil, damit ein Bild bündig an den
   Kartenrand laufen kann. */
.karte__text { padding: var(--s3); }
.karte:not(:has(.karte__bild)) > .karte__text { padding: var(--s3); }

/* Bild in der Karte: fester Ausschnitt, damit alle Karten einer Reihe
   dieselbe Bildhöhe haben — ungleiche Bildhöhen sind der schnellste Weg
   zu einem unruhigen Raster. */
.karte__bild { display: block; overflow: hidden; background: var(--flaeche); }
.karte__bild img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover;
  transition: transform .5s var(--ease);
}
.karte:hover .karte__bild img { transform: scale(1.04); }
/* Auf hellen Abschnittsflächen bleibt die Karte weiss — der Wechsel
   Fläche/Karte ersetzt dort den Rahmen als Trennung. */
.abschnitt--flaeche .karte { border-color: transparent; }

/* Auf dunklem Grund ist der tiefe Ton unbrauchbar (2.65:1). Dort übernimmt
   der Flächenton die Rolle der Schrift- und Linienfarbe (4.88:1). */
/* Auf dunklem Grund bleibt der Markenton lesbar (4.53 gegen #002E21 → 3.28,
   reicht für Kanten und Sinnbilder, nicht für Fliesstext — dort steht Weiss). */

.karte__zeichen { color: var(--akzent); margin-bottom: var(--s2); }
/* Mit Bild braucht die Karte kein zweites Erkennungszeichen. */
.karte__bild ~ .karte__text .karte__zeichen { display: none; }
.karte__zeichen svg { width: 32px; height: 32px; }
.karte h3 { margin-bottom: var(--s1); }
.karte p { max-width: 46ch; }

/* Nummerierte Karte: bei Arbeitsschritten und Prüffragen sagt die Ziffer
   mehr als jedes Sinnbild — sie zeigt die Reihenfolge. */
.karte__nummer {
  font-size: var(--t-h2); font-weight: 700; line-height: var(--z-eng);
  color: var(--akzent); margin-bottom: var(--s1);
}

/* Kompakte Karte: eine Zeile Text, kein Titel — für Aufzählungen wie die
   Punkte am Aussenaufbau. */
.karte--knapp { flex-direction: row; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); }
.karte--knapp .karte__zeichen { margin-bottom: 0; flex: none; }
.karte--knapp .karte__zeichen svg { width: 26px; height: 26px; }

/* ---------- Vorher / Nachher ---------- */
.va { position: relative; overflow: hidden; background: var(--tinte); touch-action: pan-y; }
.va__bild { display: block; width: 100%; }
.va__bild img { width: 100%; display: block; }
.va__nachher { position: absolute; inset: 0; clip-path: inset(0 0 0 var(--pos, 50%)); }
.va__nachher img { width: 100%; height: 100%; object-fit: cover; }
.va__griff {
  position: absolute; top: 0; bottom: 0; left: var(--pos, 50%); width: 2px;
  background: #fff; pointer-events: none;
}
.va__griff::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 48px; height: 48px;
  transform: translate(-50%, -50%);
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231A1A1A' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6 4 12l5 6M15 6l5 6-5 6'/%3E%3C/svg%3E") center/22px no-repeat;
}
.va__regler {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize;
  -webkit-appearance: none; appearance: none; background: transparent;
}
/* Ohne Versalien und ohne Sperrung: das waren zwei weitere Schriftbilder
   für zwei Wörter. */
.va__marke {
  position: absolute; top: var(--s2); padding: var(--s1) var(--s2);
  font-size: var(--t-text); font-weight: 700; color: #fff; background: rgba(14,14,14,.8);
  pointer-events: none;
}
.va__marke--links  { left: var(--s2); }
.va__marke--rechts { right: var(--s2); }
.va__hinweis { margin-top: var(--s2); font-size: var(--t-text); }

/* ---------- Zweispalter ---------- */
.duo { display: grid; gap: var(--s5); align-items: start; }
@media (min-width: 900px) {
  .duo { grid-template-columns: 1fr 1fr; }
  .duo--schmal-links { grid-template-columns: 5fr 6fr; }
  /* Bildspalte auf die Höhe der Textspalte ziehen — sonst endet das Bild
     weit vor dem Text und darunter bleibt eine grosse leere Fläche. */
  .duo--bild-fuellt { align-items: stretch; }
  .duo--bild-fuellt .duo__bild { display: flex; flex-direction: column; }
  .duo--bild-fuellt .duo__bild img { flex: 1 1 auto; min-height: 300px; object-fit: cover; }
}
.duo__bild img { width: 100%; }
.bildunterschrift { margin-top: var(--s2); font-size: var(--t-text); max-width: 46ch; }

/* Wo eine Spalte deutlich kürzer ist als die andere, blieb bisher unten ein
   Loch von 230 bis 380 px stehen (gemessen, nicht geschätzt). Die kürzere
   Spalte läuft deshalb mit: die Erläuterung bleibt im Blick, solange die
   lange Liste daneben gelesen wird. Das Loch verschwindet, ohne dass am
   Text etwas gestreckt oder gefüllt werden muss. */
@media (min-width: 900px) {
  .haftet { position: sticky; top: calc(var(--header-h-klein) + var(--s4)); }
}

/* Zwei hervorgehobene Kästen auf der Seite: der technische Hinweis beim
   Aussenaufbau und die beiden Zusagen bei den Kosten. Beide tragen die
   Akzentkante — bei zwei Vorkommen liest sich das als Auszeichnung, nicht
   als wiederholtes Abzeichen.
   ACHTUNG: `.zusage` fehlte hier zeitweise und hatte dadurch weder Rahmen
   noch Innenabstand — der Text klebte am Bildschirmrand. Beide Klassen
   müssen zusammen stehen bleiben. */
.warnung, .zusage {
  margin-top: var(--s4); padding: var(--s4);
  border: 1px solid var(--linie); border-top: 2px solid var(--akzent);
  background: var(--weiss); max-width: 80ch;
}
/* Am Telefon ist der Innenabstand kleiner — 40 px ringsum fressen dort
   ein Drittel der Zeilenbreite. */
@media (max-width: 640px) {
  .warnung, .zusage { padding: var(--s3); }
}
.warnung strong, .zusage strong { display: block; margin-bottom: var(--s1); line-height: var(--z-mittel); color: var(--tinte); }

/* ---------- Einstieg: Kopf links, Fliesstext rechts ----------
   Auf Ansage des Auftraggebers, der auf das leere Feld rechts neben der
   Überschrift gezeigt hat. Gemessen standen dort 580 px ungenutzt, während
   der Fliesstext darunter in einer halbbreiten Spalte weiterlief.

   ACHTUNG, das widerspricht einer früheren Vorgabe: „Abschnittskopf
   einspaltig" (Einleitung unter der Überschrift, nicht daneben). Der
   Unterschied ist, WAS rechts steht — damals die Einleitung selbst, jetzt
   der nachfolgende Fliesstext. Der Kopf bleibt links zusammen.
   Nicht ungefragt zurückbauen.

   Nur dort, wo unter dem Kopf überhaupt Fliesstext folgt — seit dem
   Wegfall der „Prüfung" ist das allein „Farbe und Gestaltung". Alle
   übrigen Abschnitte gehen vom Kopf direkt in Karten, Bilder oder Listen
   über — da gibt es nichts zu verschieben. */
@media (min-width: 900px) {
  .einstieg {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--s5); align-items: start;
  }
  /* Die Begrenzung auf 58 ch stammt aus der einspaltigen Fassung und
     wirkt in der halben Spalte doppelt — dort begrenzt schon die Spalte. */
  .einstieg .kopf .lead { max-width: none; }
}

/* Zwischenüberschrift über einem Kartenblock. */
.abschnitt > .container > h3 { margin-bottom: var(--s2); }
h3 + .karten { margin-top: var(--s2); }
.zusage + div { margin-top: var(--s4); }
.zusage p + .btn, div > p + .btn { margin-top: var(--s3); }

/* Der Abschnitt „Steinteppich oder Fliesen" ist am 10.08.2026 auf Wunsch
   des Auftraggebers entfallen; die Regeln .vergleich* stehen hier nicht
   mehr, weil sie sonst tote Selektoren wären. Falls der Block je
   zurückkehrt: beide Spalten brauchten align-items: stretch, sonst stand
   ein 242 px kürzerer Rahmen neben dem längeren und las sich als Fehler. */
.haken { list-style: none; padding: 0; margin: 0; }
.haken li { position: relative; padding: var(--s2) 0 var(--s2) var(--s3); border-top: 1px solid var(--linie); }
.haken li:first-child { border-top: 0; }
.haken li::before {
  content: ""; position: absolute; left: 0; top: 1.75rem; width: 8px; height: 1px;
  background: var(--akzent);
}

/* ---------- Referenzen ----------
   Bewusst ungleiche Grössen: drei gleich grosse Kacheln nebeneinander
   sind das Erkennungsmerkmal beliebiger Baukastenseiten.

   Das Muster läuft in Dreierbändern: ein hohes Bild links, zwei flache
   rechts. Seit der zweiten Bildlieferung (11.08.2026) sind es sechs
   Referenzen, also zwei Bänder. Deshalb `3n+1` statt `first-child` und
   `grid-auto-rows` statt fester Zeilen — jedes weitere Dreierpaket ordnet
   sich von selbst ein, ohne dass hier etwas nachgezogen werden muss.
   Bei einer Zahl, die nicht durch drei teilbar ist, bleibt rechts eine
   Lücke; dann lieber eine Referenz weglassen als das Band anbrechen. */
.referenzen { display: grid; gap: var(--s1); }
@media (min-width: 760px) {
  .referenzen { grid-template-columns: 1.55fr 1fr; grid-auto-rows: 1fr; }
  .referenz:nth-child(3n + 1) { grid-column: 1; grid-row: span 2; }
  .referenz:nth-child(3n + 1) img { aspect-ratio: 4 / 5; }
  .referenz:not(:nth-child(3n + 1)) { grid-column: 2; }
  .referenz:not(:nth-child(3n + 1)) img { aspect-ratio: 16 / 10; }
}
.referenz { position: relative; overflow: hidden; cursor: zoom-in; background: var(--flaeche); }
.referenz img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform .6s var(--ease); }
.referenz:hover img, .referenz:focus-visible img { transform: scale(1.04); }
.referenz figcaption {
  position: absolute; inset: auto 0 0 0; padding: var(--s5) var(--s3) var(--s3);
  background: linear-gradient(to top, rgba(12,12,12,.9) 10%, transparent);
  color: #fff; font-size: var(--t-text);
}

/* ---------- FAQ ---------- */
.faq details { border-top: 1px solid var(--linie); }
.faq details:last-of-type { border-bottom: 1px solid var(--linie); }
.faq summary {
  list-style: none; cursor: pointer; padding: var(--s3) var(--s5) var(--s3) 0; position: relative;
  font-size: var(--t-text); font-weight: 700; color: var(--tinte); line-height: var(--z-mittel);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: var(--s1); top: 1.9rem; width: 11px; height: 11px;
  border-right: 1.5px solid var(--tinte); border-bottom: 1.5px solid var(--tinte);
  transform: rotate(45deg); transition: transform .2s var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); top: 2.1rem; }
.faq details > p { padding: 0 var(--s5) var(--s3) 0; margin-top: calc(var(--s1) * -1); }

/* ---------- Kontakt ---------- */
.kontakt { display: grid; gap: var(--s5); }
@media (min-width: 900px) { .kontakt { grid-template-columns: 1fr 1.15fr; } }
.kontakt__daten address { font-style: normal; line-height: var(--z-weit); }
.kontakt__daten > address + .kontakt__zeile { margin-top: var(--s3); }
/* Ohne Sinnbilder: eine Telefonnummer sieht aus wie eine Telefonnummer und
   eine E-Mail-Adresse wie eine E-Mail-Adresse. Hörer, Umschlag und Stecknadel
   nebeneinander sind dasselbe Muster wie in der Angabenzeile am Auftakt —
   Sinnbild plus Beschriftung, dreimal untereinander. */
.kontakt__zeile { display: flex; align-items: center; border-top: 1px solid var(--linie); font-weight: 700; color: var(--tinte); }
/* Padding sitzt auf dem Link, damit die Antippfläche die ganze Zeile umfasst. */
.kontakt__zeile > a, .kontakt__zeile > span { display: flex; align-items: center; min-height: 48px; overflow-wrap: anywhere; }
.kontakt__zeile a:hover { color: var(--akzent); }

.karte-consent { margin-top: var(--s3); padding: var(--s3); background: var(--flaeche); border: 1px solid var(--linie); }
.karte-consent p { font-size: var(--t-text); margin-bottom: var(--s2); }
.karte-einbettung { margin-top: var(--s3); }
.karte-einbettung iframe { display: block; width: 100%; height: 320px; border: 0; }

.formular { padding: var(--s4); border: 1px solid var(--linie); background: var(--weiss); }
.feld { margin-bottom: var(--s3); }
.feld label { display: block; font-size: var(--t-text); font-weight: 700; color: var(--tinte); margin-bottom: var(--s1); }
.feld .optional { font-weight: 400; color: var(--grau); }
.eingabe {
  width: 100%; min-height: 48px; padding: var(--s1) var(--s2); background: #fff;
  border: 1px solid var(--linie-stark); border-radius: 0;
  transition: border-color .15s;
}
.eingabe:focus { outline: none; border-color: var(--tinte); box-shadow: inset 0 0 0 1px var(--tinte); }
textarea.eingabe { min-height: 130px; resize: vertical; padding-block: var(--s2); }
.feld-fehler { display: none; margin-top: var(--s1); font-size: var(--t-text); color: var(--fehler); }
.feld.has-error .eingabe, .zustimmung.has-error input { border-color: var(--fehler); }
.feld.has-error .feld-fehler { display: block; }
.zustimmung { display: flex; gap: var(--s2); align-items: flex-start; margin-bottom: var(--s3); font-size: var(--t-text); }
/* 24 px ist das Mindestmass für Bedienelemente (WCAG 2.5.8). */
.zustimmung input { margin-top: .2rem; width: 24px; height: 24px; flex: none; accent-color: var(--tinte); cursor: pointer; }
.zustimmung label { cursor: pointer; }
.zustimmung a, .karte-consent a { text-decoration: underline; text-underline-offset: 2px; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-hinweis { margin-top: var(--s2); padding: var(--s2); font-size: var(--t-text); }
.form-hinweis--fehler { background: #FDECEA; color: var(--fehler); }
.btn.is-loading { opacity: .7; pointer-events: none; }

/* „Was passiert jetzt" direkt unter dem Absende-Knopf. Der Planlauf nennt
   das als zweite Konversionsluecke neben der Preisungewissheit: kostet
   nichts, hebt die Absenderate. */
.form-danach { margin-top: var(--s2); font-size: var(--t-text); color: var(--grau); }

.formular-erfolg { display: none; padding: var(--s4); border: 1px solid var(--linie); background: var(--weiss); }
.formular-erfolg.is-visible { display: block; }
/* Nach erfolgreicher Umleitung steht die Bestaetigung an der Stelle
   des Formulars — nicht darunter. */
.formular.is-erledigt { display: none; }
.formular-erfolg h3 { color: var(--erfolg); margin-bottom: var(--s1); }

/* ---------- Fusszeile ----------
   Kein Sitemap-Raster aus Logo, Leistungsliste und Kontaktliste: auf einer
   einzigen Seite verweisen solche Spalten nur auf Sprungmarken weiter oben.
   Stattdessen ein Briefkopf — die Telefonnummer ist bei dieser Zielgruppe
   der häufigste Weg zum Auftrag und damit das grösste Element. */
.site-footer {
  background: var(--gruen-tief); color: #A5A5A5;
  padding-block: var(--s5) var(--s3); font-size: var(--t-text);
  border-top: 1px solid var(--akzent);
}
.site-footer img { height: 52px; width: auto; }
.site-footer a:hover { color: #fff; }

.briefkopf { display: grid; gap: var(--s5); align-items: start; }
@media (min-width: 860px) { .briefkopf { grid-template-columns: 1fr auto; } }

.briefkopf__ruf { display: block; }
/* Ohne Versalien und Sperrung — siehe Regel 2. */
.briefkopf__ruf span { display: block; font-size: var(--t-text); color: #A5A5A5; margin-bottom: var(--s1); }
.briefkopf__nummer {
  display: block; font-size: var(--t-h2); font-weight: 700;
  line-height: var(--z-eng); letter-spacing: -0.022em; color: #fff;
  transition: color .2s var(--ease);
}
.briefkopf__ruf:hover .briefkopf__nummer { color: var(--akzent); }
.briefkopf__mail { display: inline-flex; align-items: center; min-height: 44px; margin-top: var(--s1); color: #C2C2C2; overflow-wrap: anywhere; }
.briefkopf__mail:hover { color: #fff; }

.briefkopf__adresse { font-style: normal; line-height: var(--z-weit); margin-top: var(--s3); }
.briefkopf__adresse strong { display: block; color: #fff; margin-bottom: var(--s1); }
.briefkopf__gebiet { margin-top: var(--s2); max-width: 32ch; }

.footer__unten {
  display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3); justify-content: space-between;
  margin-top: var(--s5); padding-top: var(--s3);
  border-top: 1px solid rgba(255,255,255,.16); font-size: var(--t-text);
}
.footer__rechtlich { display: flex; gap: var(--s3); }
.footer__rechtlich a, .footer__unten a { display: inline-flex; align-items: center; min-height: 40px; }

/* ---------- Lightbox ---------- */
.lightbox { padding: 0; border: 0; background: transparent; max-width: 100vw; max-height: 100dvh; width: 100%; height: 100%; }
.lightbox::backdrop { background: rgba(12,12,12,.94); }
.lightbox__inner { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; padding: var(--s5) var(--s2); }
.lightbox img { max-height: 82dvh; width: auto; }
.lightbox__cap { color: #C2C2C2; font-size: var(--t-text); margin-top: var(--s2); text-align: center; }
.lightbox button {
  position: absolute; background: rgba(255,255,255,.12); border: 0; color: #fff; cursor: pointer;
  width: 48px; height: 48px; display: grid; place-items: center;
}
.lightbox button:hover { background: rgba(255,255,255,.24); }
.lightbox__schliessen { top: var(--s2); right: var(--s2); font-size: var(--t-text); line-height: 1; }
.lightbox__nav--prev { left: var(--s2); top: 50%; transform: translateY(-50%); }
.lightbox__nav--next { right: var(--s2); top: 50%; transform: translateY(-50%); }

/* ---------- Hinweisleiste ----------
   Wird derzeit nicht ausgeliefert: die Seite lädt keine Analyse-, Tracking-
   oder Marketingdienste, die Schrift liegt lokal und die Karte erst nach
   ausdrücklichem Klick. Die Gestaltung steht bereit, falls doch ein Dienst
   dazukommt — dann ist sie bereits Teil des Systems. */
.cookie {
  position: fixed; right: var(--s3); bottom: var(--s3); left: auto; z-index: 150; max-width: 420px;
  background: #fff; border: 1px solid var(--linie-stark); padding: var(--s3);
  box-shadow: 0 24px 60px rgba(20,20,20,.18);
  transform: translateY(150%); transition: transform .35s var(--ease);
}
.cookie.is-visible { transform: translateY(0); }
.cookie p { font-size: var(--t-text); margin-bottom: var(--s2); }
.cookie a { text-decoration: underline; text-underline-offset: 2px; }
/* Beide Schaltflächen gleichwertig — kein Dark Pattern. */
.cookie__aktionen { display: flex; gap: var(--s1); flex-wrap: wrap; }
.cookie__aktionen .btn { flex: 1 1 0; min-width: 140px; padding-inline: var(--s3); }

/* ---------- Schwebende Schaltflächen ---------- */
.schweber {
  position: fixed; right: var(--s2); bottom: var(--s2); z-index: 90;
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--s1);
  pointer-events: none;
}
.schweber > * { pointer-events: auto; }

/* ---------- Cookie-Hinweis ----------
   Gebaut wie im Vorbild `matern_website`, aber in diesem Blattsystem:
   rechte Winkel, kein Schlagschatten, eine Akzentfarbe, ein Schriftgrad.
   Die Trennung zum Inhalt trägt die Haarlinie, wie bei den Karten.

   Er sitzt links unten, weil rechts unten die Anruf-Schaltfläche steht.
   Sobald der Kasten die volle Breite einnimmt (schmale Geräte), würden sich
   beide überlagern — dann hebt `body.hat-hinweis` die Schaltflächen darüber.
   Fällt automatisch weg, wenn der Kasten geschlossen ist. */
.hinweis {
  position: fixed; z-index: 95;
  left: var(--pad); bottom: var(--pad); right: var(--pad); max-width: 420px;
  background: var(--weiss); border: 1px solid var(--linie-stark);
  padding: var(--s3);
  opacity: 0; transform: translateY(12px); visibility: hidden;
  transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
}
.hinweis.ist-da { opacity: 1; transform: none; visibility: visible; }
.hinweis__titel { font-weight: 700; margin-bottom: var(--s1); }
.hinweis p { color: var(--grau); line-height: var(--z-mittel); }
.hinweis__aktion { display: flex; flex-wrap: wrap; gap: var(--s1); margin-top: var(--s2); }
.hinweis__aktion .btn { flex: 1 1 auto; justify-content: center; text-align: center; }
.hinweis__link {
  display: inline-block; margin-top: var(--s2);
  color: var(--grau); text-decoration: underline; text-underline-offset: 3px;
}
.hinweis__link:hover { color: var(--tinte); }
@media (max-width: 620px) {
  /* Hier nimmt der Kasten die volle Breite ein und läge unter den
     Schaltflächen. Sie oben zu parken sähe nach Fehler aus, also warten sie:
     der Hinweis will ohnehin zuerst beantwortet werden, danach sind sie
     sofort wieder da. Sie erscheinen frühestens nach 600 px Scrollweg —
     bis dahin ist die Entscheidung meist gefallen. */
  body.hat-hinweis .schweber { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hinweis { transition: none; }
}

.nach-oben {
  display: grid; place-items: center; width: 48px; height: 48px; padding: 0;
  background: #fff; color: var(--tinte); border: 1px solid var(--linie-stark); cursor: pointer;
  opacity: 0; transform: translateY(120%); transition: opacity .25s, transform .25s var(--ease), border-color .15s;
}
.nach-oben:hover { border-color: var(--tinte); }
.nach-oben.is-visible { opacity: 1; transform: translateY(0); }
.nach-oben svg { width: 20px; height: 20px; }

/* Anruf-Schaltfläche nur mobil — am Schreibtisch steht die Nummer in der Kopfzeile. */
.fab {
  display: none; align-items: center; gap: var(--s1); min-height: 48px; padding-inline: var(--s3);
  background: var(--akzent); color: #fff; font-weight: 700; font-size: var(--t-text);
  opacity: 0; transform: translateY(120%); transition: opacity .25s, transform .25s var(--ease);
}
.fab.is-visible { opacity: 1; transform: translateY(0); }
.fab svg { width: 18px; height: 18px; }

/* Kompakte Kontakt-Schaltfläche in der mobilen Kopfzeile. */
.header__kontakt {
  display: none; align-items: center; gap: var(--s1); flex: none;
  min-height: 44px; padding-inline: var(--s2);
  font-size: var(--t-text); font-weight: 700; color: #fff; background: var(--akzent);
}
.header__kontakt svg { width: 16px; height: 16px; }

/* ---------- Bewegung ----------
   Regeln: nur transform und opacity (alles andere loest Neuberechnung des
   Layouts aus), kein scroll-Ereignis in JavaScript, und bei
   prefers-reduced-motion bleibt alles stehen. Der Parallax laeuft ueber
   animation-timeline — reine CSS-Loesung; Browser ohne Unterstuetzung
   zeigen das Bild einfach ruhig, es faellt nichts aus. */
@media (prefers-reduced-motion: no-preference) {

  /* Karten laufen versetzt ein statt alle gleichzeitig. Die Verzoegerung
     kommt aus der Position in der Reihe, nicht aus JavaScript. */
  .js .karten > .karte { transition-delay: calc(var(--reihe, 0) * 60ms); }
  .karten > .karte:nth-child(1) { --reihe: 0; }
  .karten > .karte:nth-child(2) { --reihe: 1; }
  .karten > .karte:nth-child(3) { --reihe: 2; }
  .karten > .karte:nth-child(4) { --reihe: 1; }
  .karten > .karte:nth-child(5) { --reihe: 2; }
  .karten > .karte:nth-child(6) { --reihe: 3; }
  .karten > .karte:nth-child(7) { --reihe: 2; }

  @supports (animation-timeline: view()) {
    /* Das Foto steht etwas groesser im Rahmen und wandert beim Scrollen
       langsamer als die Seite. Dadurch wirkt die Flaeche wie hinter einem
       Ausschnitt statt aufgeklebt. */
    .buehne__spur img, .abschnitt--kontrast .referenz img {
      animation: wandern linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes wandern {
      from { transform: scale(1.14) translateY(-2.5%); }
      to   { transform: scale(1.14) translateY(2.5%); }
    }
    /* Beim Ueberfahren gewinnt die Vergroesserung — sonst wuerde die
       Parallax-Animation den Zoom ueberschreiben. */
    .referenz:hover img, .referenz:focus-visible img { animation-play-state: paused; transform: scale(1.2); }
  }
}

/* Karte beim Ueberfahren: die Haarlinie wird zur Kante, das Sinnbild
   ruecht ein Stueck. Kein Schweben, kein Schatten — die Karte bleibt ein
   Feld im Raster. */
.karte { transition: border-color .25s var(--ease), background-color .25s var(--ease); }
.karte__zeichen { transition: transform .25s var(--ease); }
.karte:hover { border-color: var(--linie-stark); }
.karte:hover .karte__zeichen { transform: translateX(3px); }
.abschnitt--flaeche .karte:hover { border-color: var(--linie-stark); }


/* ---------- Einblenden beim Scrollen ----------
   Versteckt wird NUR, wenn JavaScript läuft (die Klasse .js setzt ein
   Inline-Skript im <head>). Ohne diese Absicherung bliebe die halbe Seite
   unsichtbar, sobald das Skript fehlschlägt oder blockiert wird. */
.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.js .reveal.is-in { opacity: 1; transform: none; }

/* ---------- Rechtstexte ----------
   Unten derselbe Abstand wie oben. Vorher gab es gar keinen: „Zurück zur
   Startseite" klebte auf der Fusszeile, weil nur das Aussenabstandsmass des
   letzten Absatzes (16 px) dazwischenlag — beanstandet am 11.08.2026. */
.rechtstext { padding-top: calc(var(--header-h-klein) + var(--abschnitt)); padding-bottom: var(--abschnitt); }
/* Der Rücksprung steht für sich, nicht als weiterer Absatz im Fliesstext. */
.rechtstext > .container > p:last-child { margin-top: var(--s4); }
/* „Datenschutzerklärung" ist ein einziges Wort aus 20 Zeichen und misst im
   h1-Grad 345 px — auf 320 px breiten Geräten ragte es 45 px aus dem Bild
   und machte die Seite waagrecht scrollbar. `hyphens: auto` greift, weil
   das Dokument `lang="de-AT"` trägt, und trennt korrekt mit Bindestrich.
   `break-word` ist nur die Rückfalllinie für Browser ohne Trennmuster. */
.rechtstext h1 { margin-bottom: var(--s4); hyphens: auto; overflow-wrap: break-word; }
.rechtstext h2 { font-size: var(--t-text); margin: var(--s4) 0 var(--s2); letter-spacing: 0; }
.rechtstext p, .rechtstext ul { margin-bottom: var(--s2); max-width: 72ch; }
.rechtstext ul { padding-left: var(--s3); }
.rechtstext a { text-decoration: underline; text-underline-offset: 2px; }

/* ---------- Mobil ---------- */
@media (max-width: 1080px) {
  .nav { gap: var(--s3); }
  .hero__fakten li { padding-inline: var(--s3); }
}
@media (max-width: 900px) {
  .nav, .header__tel { display: none; }
  .burger { display: flex; }
  .header__kontakt { display: inline-flex; }
  .header__logo img, .is-scrolled .header__logo img { height: 56px; }
  /* Umbrochen stünde der Trenner am Zeilenanfang. Am Telefon deshalb
     untereinander, getrennt durch die Haarlinie zwischen den Zeilen. */
  .hero__fakten ul { display: block; }
  .hero__fakten li { border-top: 1px solid var(--linie); }
  .hero__fakten li:first-child { border-top: 0; }
  .hero__fakten li + li::before { content: none; }
  .hero__bild img { aspect-ratio: 4 / 3; }
  .fab { display: inline-flex; }
    .hero__inhalt { padding-bottom: var(--s4); }
  .hero__inhalt > * { max-width: none; }
}
@media (max-width: 560px) {
  .referenz img { aspect-ratio: 4 / 3; }
  .schweber { right: var(--s1); bottom: var(--s1); }
}
/* Nur ganz schmale Geräte: dort reicht der Platz für die Beschriftung nicht. */
@media (max-width: 360px) {
  .header__logo img, .is-scrolled .header__logo img { height: 46px; }
  .header__kontakt span { display: none; }
  .header__kontakt { padding-inline: var(--s1); }
}

/* ---------- Druck ---------- */
@media print {
  .site-header, .fab, .hinweis, .hero__cta, .formular, .burger, .schweber { display: none !important; }
  body { color: #000; }
  .reveal { opacity: 1; transform: none; }
}

