/* =====================================================================
   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
   Neutrale Grundlage plus EIN Akzent. Frueher lagen hier drei Orangetoene
   und ein Bernstein nebeneinander; diese warme Haeufung hat den Auftritt
   billig gemacht.
   Der Markenton traegt jetzt die Bedienelemente — aber als FLAECHE mit
   dunkler Schrift (4.90:1), nicht mit weisser (nur 3.55:1, unzulaessig).
   Genau dieser Kontrastmangel hatte frueher den zweiten, braeunlichen Ton
   noetig gemacht. Als SCHRIFT auf hellem Grund bleibt Orange verboten.
   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:       #1A1A1A;   /* Überschriften, dunkle Flächen, Schaltflächen */
  --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;
  /* Der Markenton trägt jetzt die Bedienelemente — als FLÄCHE mit dunkler
     Schrift (4.90:1), nicht als Schrift auf hellem Grund (dort nur 3.55:1). */
  --akzent:      #E2600F;
  --akzent-hell: #EE6B10;   /* Überfahren — 5.59: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. */
.tel-link { font-weight: 700; color: var(--tinte); text-decoration: underline; text-underline-offset: 3px; }
.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: #1A1A1A; }
.btn--primaer:hover { background: var(--akzent-hell); }
.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: var(--tinte); 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 wird NICHT übernommen: der Bernsteinton ist aus dem Farbsystem
   gestrichen, weil er den grössten Anteil am billigen Eindruck hatte, und
   er erreicht auf keinem Grund einen zulässigen Kontrast (2.03:1 auf
   Weiss). Stattdessen die geltende Regel des Blattes — der Markenton
   trägt die Fläche, die Schrift ist dunkel: #1A1A1A auf #E2600F = 4.90:1.

   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 h2-Grad zwingt damit zu **mindestens 208 px** — auf Ansage soll der
   Kreis kleiner sein, deshalb läuft er jetzt auch am Schreibtisch auf dem
   Textgrad und misst 160 px (rechnerisches Minimum 109 px). Am Telefon
   120 px. Wer ihn wieder deutlich grösser will, muss den Grad mitgrössern,
   sonst schwimmt die Schrift in der Fläche.

   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(--akzent); color: #1A1A1A;
  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, an der rechten Kante des
   Satzspiegels — also im selben Raster wie Logo, Überschrift und
   Angabenzeile, nicht frei über dem Bild.
   Erst ab 1000 px, NICHT ab 900: bei 900 steht die 700er Tafel schon fast
   über die ganze Breite, der 236er Kreis läge auf ihr. Bis dahin läuft er
   im Fluss unter der Tafel mit. */
@media (min-width: 1000px) {
  .siegel {
    position: absolute; right: 0; top: 50%;
    transform: translateY(-50%) rotate(-13deg);
    width: 116px; height: 116px; margin: 0;
  }
}

/* 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: #1A1A1A; 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='%23E2600F' 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: #1A1A1A; padding-block: var(--s5); }
.ruf h2 { color: #1A1A1A; }
.ruf__inhalt { display: grid; gap: var(--s4); align-items: center; }
@media (min-width: 900px) { .ruf__inhalt { grid-template-columns: minmax(0, 1.3fr) auto; } }
.ruf p { color: #2A1A0C; max-width: 52ch; }
.ruf__aktion { display: flex; flex-direction: column; gap: var(--s2); }
.ruf .btn--primaer { background: #1A1A1A; 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: #1A1A1A;
}
.ruf__nummer:hover { text-decoration: underline; text-underline-offset: 4px; }
.ruf__label { color: #2A1A0C; }

/* 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; }

.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); }

/* 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); }

/* ---------- Vergleich ----------
   Hier gilt das Gegenteil der Regel von oben: beide Blöcke haben Rahmen
   bzw. Fläche. Ein abgeschnittener Rahmen neben einem langen liest sich
   als Fehler, während eine gemeinsame Unterkante wie zwei Spalten eines
   Formulars wirkt. Deshalb stretch — gemessene Differenz vorher: 242 px. */
.vergleich { display: grid; gap: var(--s4); align-items: stretch; }
@media (min-width: 860px) { .vergleich { grid-template-columns: 1.3fr 1fr; } }
.vergleich__block { padding: var(--s4); border: 1px solid var(--linie); background: var(--weiss); }
.vergleich__block--gedaempft { background: var(--flaeche); }
.vergleich__block h3 { margin-bottom: var(--s3); }
.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. */
.referenzen { display: grid; gap: var(--s1); }
@media (min-width: 760px) {
  .referenzen { grid-template-columns: 1.55fr 1fr; grid-template-rows: 1fr 1fr; }
  .referenz:first-child { grid-row: span 2; }
  .referenz:first-child img { aspect-ratio: 4 / 5; }
  .referenz:not(:first-child) 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(--tinte); 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; }

.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: var(--tinte); 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: var(--tinte); 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 ---------- */
.rechtstext { padding-top: calc(var(--header-h-klein) + var(--abschnitt)); }
.rechtstext h1 { margin-bottom: var(--s4); }
.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, .cookie, .hero__cta, .formular, .burger, .schweber { display: none !important; }
  body { color: #000; }
  .reveal { opacity: 1; transform: none; }
}

