/* ═══════════════════════════════════════════════════
   RECOLORO — styles.css
   CI Farben: Blau #0F46D4 · BG #F3F4F5 · Warm-Weiss #F7F5F0
              Anthrazit #1E2428 · Liniengrau #DDE1E4 · Mittelgrau #8B9298
   ═══════════════════════════════════════════════════ */

/* Source Sans 3, selbst gehostet (N1b T-1). Variable Fonts, Gewichtsbereich
   300–600 abgedeckt. Lizenz: SIL Open Font License, siehe assets/fonts/LICENSE.md */
@font-face {
  font-family: 'Source Sans 3';
  src: url('assets/fonts/source-sans-3-variable.woff2') format('woff2-variations'),
       url('assets/fonts/source-sans-3-variable.woff2') format('woff2');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Source Sans 3';
  src: url('assets/fonts/source-sans-3-variable-italic.woff2') format('woff2-variations'),
       url('assets/fonts/source-sans-3-variable-italic.woff2') format('woff2');
  font-weight: 200 900;
  font-style: italic;
  font-display: swap;
}

:root {
  --blue:       #0F46D4;
  --blue-dark:  #0a38a8;
  --bg:         #F3F4F5;
  --warm-white: #F7F5F0;
  --anthracite: #1E2428;
  --border:     #DDE1E4;
  --mid-grey:   #8B9298;
  --text-muted: #5B6268; /* Sekundärtext auf hellem Grund, WCAG AA (N1 Q-3) */

  --font: 'Source Sans 3', 'Source Sans Pro', Arial, sans-serif;

  --nav-h:         72px;
  --nav-h-scrolled: 60px;
  --nav-pad:       48px;
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);

  /* Einheitliches Raster für die ganze Seite (T29v2 §1, N1c-2 T-1): eine
     Inhaltsbreite 1280px, 12 Spalten, 32px Spaltenabstand (Mobile 16px).
     Ersetzt die bisherigen Sonderbreiten 1480/1120/980/760/680px. */
  --content-max: 1280px;
  --grid-gap:    32px;
  --section-pad-y: clamp(64px, 7vw, 104px);
}

@media (max-width: 760px) {
  :root { --grid-gap: 16px; }
}

/* Gemeinsame Inhaltsbreite, zentriert; Seitenrand kommt vom umgebenden
   Element (padding: var(--nav-pad)), daher hier bewusst kein eigenes
   Padding (T29v2 §1). */
.container {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
}

/* 12-Spalten-Grid-Hilfe für geteilte Köpfe (Vorteile, FAQ) u. ä. */
.grid-12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--grid-gap);
}

/* ── Reset ─────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

body {
  font-family: var(--font);
  font-weight: 400;
  color: var(--anthracite);
  background: var(--bg);
  overflow-x: hidden;
  /* Befund «NEUANST RICH» (Chrome/Windows): ungleichmässige Zeichenabstände bei
     Laufweite auf Variable Fonts. Gegenmassnahmen: geometricPrecision hier,
     Laufweite (letter-spacing) im gesamten Stylesheet nur noch auf kurze
     Rubriken-Versalien (.section-eyebrow u. ä.), nicht auf Fliesstext,
     Tabellenköpfe oder Menüs (N1c T-1). */
  text-rendering: geometricPrecision;
}

/* ── Intro ──────────────────────────────────────── */
/* Warmweisser Vollbildschirm, R-Symbol und Wortmarke in Blau, zentriert;
   steht 2,2 s, dann 0,8 s Überblendung (in script.js gesteuert). Ausser dem
   Einblenden (N1d-1 W-2) keine weitere Animation (T29 §2).
   N1c-19 I-1: Variante «Gross» (D-166). Bezug 1440 x 900: R-Zeichen 200 px,
   Schriftzug 540 px; begrenzt durch Breite UND Höhe des Fensters (min(vw, vh)),
   Obergrenzen 240 / 640 px. Sollwerte: 1280x720 ca. 158/432 px, 1440x900 ca.
   198/540 px, 1920x1080 ca. 238/640 px.
   N1c-18 F-5: Der Bildschirm wird nur gezeichnet, wenn das Inline-Skript im
   <head> der Seite (index.html) die Klasse intro-on an <html> gesetzt hat
   (Entscheidung vor dem ersten Zeichnen); ohne die Klasse bleibt er
   display: none und blitzt auch bei verzögert geladenem script.js nicht auf. */
.intro-screen {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 300;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, min(2.8vw, 4.5vh), 44px);
  background: var(--warm-white);
  opacity: 1;
  transition: opacity 0.8s ease;
}

.intro-on .intro-screen { display: flex; }

.intro-screen.is-fading { opacity: 0; }

.intro-screen.is-done { display: none; }

.intro-mark {
  width: clamp(120px, min(13.9vw, 22vh), 240px);
  color: var(--blue);
}

/* recoloro-wordmark.svg ist bereits in Recoloro-Blau angelegt (style="color:
   #0F46D4" im SVG selbst) — kein Filter nötig, anders als .hero-wordmark/
   .footer-logo-word, die für Weiss auf dunklem Grund invertiert werden. */
.intro-word {
  display: block;
  width: clamp(320px, min(37.5vw, 60vh), 640px);
  height: auto;
}

/* N1d-1 W-2: Einblenden statt Hereingleiten (revidiert D-166). R-Zeichen und
   Schriftzug erscheinen an ihrem Platz, ohne Bewegung: Deckkraft 0 -> 1 in
   0,6 s ease-out, beide gleichzeitig; danach stehen sie bis zum Ausblenden
   (2,2 s nach Start, Gesamtdauer unverändert). Kein transform. Die Animation
   hängt an .intro-on .intro-screen: sie startet erst, wenn der Bildschirm
   tatsächlich gezeichnet wird; ohne Intro (display: none) läuft nichts und
   nichts blitzt auf. backwards hält beide vor dem Start unsichtbar. */
@keyframes intro-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.intro-on .intro-screen .intro-mark,
.intro-on .intro-screen .intro-word {
  animation: intro-fade-in 0.6s ease-out backwards;
}

@media (prefers-reduced-motion: reduce) {
  .intro-screen { transition: none; }
  /* Kein Einblenden: Elemente sofort an Endposition sichtbar. */
  .intro-on .intro-screen .intro-mark,
  .intro-on .intro-screen .intro-word { animation: none; }
}

/* Kein Intro auf dem Handy (T29v4 §2/§11, N1c-4 U-2): Absicherung rein per
   Media Query, damit das Overlay unter 1024px auch dann nie aufblitzt,
   wenn script.js noch nicht ausgeführt ist. script.js selbst überspringt
   auf dieser Breite ohnehin die ganze Intro-Logik (shouldShowIntro). Grenze
   deckungsgleich mit compactMediaQuery ('(min-width: 1024px)') in script.js. */
@media (max-width: 1023.98px) {
  .intro-screen,
  .intro-on .intro-screen { display: none; }
}

/* ── Navigation ─────────────────────────────────── */
/* Im Empfang verborgen: visibility:hidden statt nur opacity, damit die
   Links vorher weder sichtbar noch fokussierbar/per Tab erreichbar sind
   (T29 §2/§9). Erscheint erst per JS (Klasse is-visible) beim ersten
   Scrollen oder Pfeil-Klick und bleibt danach fixiert; heller Hintergrund
   von Anfang an, da sie nie über dem Bild eingeblendet wird. */
#nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--bg);
  box-shadow: 0 1px 0 var(--border);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.35s ease, visibility 0s linear 0.35s;
}

#nav.is-visible {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.35s ease;
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-h-scrolled);
  padding: 0 var(--nav-pad);
}

/* Logo: R-Ausschnitt + Wortmarke, waagrecht, Blau */
.nav-logo-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  text-decoration: none;
}

.nav-logo-mark {
  display: block;
  width: 26px;
  height: 26px;
  color: var(--blue);
}

.nav-logo-mark svg {
  display: block;
  width: 100%;
  height: 100%;
}

.nav-logo-word {
  display: block;
  /* N1d-1 W-1: ViewBox ist 95.5 statt 92.56 hoch; die Höhe wächst mit, damit die Schrift gleich gross bleibt. */
  height: calc(24px * 95.5 / 92.56);
  width: auto;
}

/* Menu (desktop): Anthrazit, Stärke 500 (T29 §9) */
.nav-menu {
  display: flex;
  align-items: center;
  list-style: none;
  gap: 4px;
}

.nav-menu a {
  display: inline-block;
  padding: 8px 12px;
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--anthracite);
  transition: opacity 0.2s ease;
  white-space: nowrap;
}

.nav-menu a:hover {
  opacity: 0.65;
}

/* Scroll-Spy-Markierung: keine Transition auf der Markierung selbst (T29 §9). */
.nav-menu a.is-current {
  color: var(--blue);
  transition: none;
}

/* Primärer Anfrageweg — ganz rechts, gefüllter blauer Knopf */
.nav-link--cta {
  margin-left: 20px !important;
  padding: 10px 22px !important;
  background: var(--blue);
  border-radius: 999px;
  color: #fff !important;
  font-weight: 600 !important;
}

.nav-link--cta:hover {
  background: var(--blue-dark);
  opacity: 1 !important;
}

/* Hamburger (hidden on desktop) */
.nav-hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  margin-right: -8px;
}

.nav-hamburger span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--anthracite);
  border-radius: 1px;
  transition: transform 0.3s var(--ease-smooth), opacity 0.3s ease;
}

.nav-hamburger.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-hamburger.is-open span:nth-child(2) { opacity: 0; transform: scaleX(0); }
.nav-hamburger.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ── Hero ───────────────────────────────────────── */
/* Bleibt in beiden Zuständen (voll/verkleinert) genau 100vh/100svh hoch,
   damit sich das Seitenlayout darunter nie verschiebt (T29v2 §3, N1c-2
   T-6). Hintergrund wechselt weich auf Warmweiss, sobald die verkleinerte
   Ansicht aktiv ist (Klasse is-compact, ab 1024px). */
#hero {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100svh;
  min-height: 500px;
  overflow: hidden;
  background: transparent;
  transition: background .5s ease;
}

#hero.is-compact {
  background: var(--warm-white);
}

/* Zurückhaltende Lesefläche für den zentrierten Hero-Claim: dunkler Verlauf
   auf das Lesbarkeitsminimum reduziert (höchstens ca. 36 % Schwarz in der
   Claim-Zone in der Mitte, nach aussen transparent; vorher bis 62 %, T29 §2).
   Nur in der Claim-Zone (unteres Drittel) und erst nach dem Laden des
   ersten Bilds eingeblendet — vorher wäre auf hellem Grund vor dem
   Bildladen ein grauer Fleck sichtbar gewesen (T29v2 §2, N1c-2 T-5:
   #hero.is-image-ready schaltet das frei, siehe script.js
   preloadFirstHeroImage()). */
#hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 62% 46% at 50% 75%,
    rgba(0, 0, 0, 0.36) 0%,
    rgba(0, 0, 0, 0.16) 60%,
    transparent 88%
  );
  z-index: 4;
  pointer-events: none;
  opacity: 0;
  transition: opacity .4s ease;
}

#hero.is-image-ready::after {
  opacity: 1;
}

/* Verkleinerte Ansicht: kein dunkler Verlauf auf dem hellen Hintergrund
   (T29v2 §3, N1c-2 T-6). */
#hero.is-compact::after {
  opacity: 0;
}

/* N1c-18 F-2: Empfang ohne Hero-Paar (Konfiguration fehlt oder kein aktives Paar):
   Claim und Text auf neutraler Fläche, ohne Schieber, Bilder und dunklen Verlauf.
   Klasse is-empty setzt script.js (prepareHero). Rahmenfarbe wie heroDefaults. */
#hero.is-empty {
  background: var(--bg);
}

#hero.is-empty .slider-wrap,
#hero.is-empty .hero-caption-bar,
#hero.is-empty::after {
  display: none;
}

#hero.is-empty .hero-claim {
  color: var(--anthracite);
  text-shadow: none;
}

#hero.is-empty .hero-wordmark {
  filter: none;
}

/* R-Symbol allein, oben links, auf jedem Bildpaar lesbar (T29 §2). Feiner
   weisser Schein, damit es auch auf blauen Bildern (z. B. Industrietor)
   nicht untergeht. Blendet aus, sobald das Menü erscheint — das Menü-Logo
   sitzt an derselben Stelle (T29 §2, N1c-2 T-5). */
.hero-mark {
  position: absolute;
  top: clamp(20px, 3vw, 32px);
  left: clamp(20px, 3vw, var(--nav-pad));
  z-index: 10;
  width: clamp(32px, 3.2vw, 44px);
  color: var(--blue);
  filter:
    drop-shadow(0 0 3px rgba(255, 255, 255, .6))
    drop-shadow(0 0 12px rgba(255, 255, 255, .35));
  opacity: 1;
  transition: opacity .3s ease;
  pointer-events: none;
}

#nav.is-visible ~ #hero .hero-mark {
  opacity: 0;
}

.hero-mark svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Pfeil nach unten, ca. 56 px mit Kreis, wippt sanft (T29 §2). Die
   allgemeine prefers-reduced-motion-Regel weiter unten setzt die
   Animation in dem Fall auf einen einzigen, praktisch unsichtbaren Schritt.
   Nachbesserung: dezent dunkle Füllung wie die Vorher/Nachher-Etiketten
   statt eines fast unsichtbaren hellen Kreisrands, damit der Pfeil auch auf
   hellem Bildgrund (z. B. Terrazzoboden) klar erkennbar bleibt (Befund 10b). */
.hero-scroll {
  position: absolute;
  left: 50%;
  bottom: clamp(20px, 3vw, 32px);
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(20, 24, 28, .55);
  border: 1.5px solid rgba(255, 255, 255, .85);
  color: #fff;
  transform: translateX(-50%);
  animation: hero-scroll-bob 2.2s ease-in-out infinite;
  opacity: 1;
  transition: background .2s ease, opacity .4s ease;
}

.hero-scroll svg { width: 22px; height: 22px; }

.hero-scroll:hover,
.hero-scroll:focus-visible {
  background: rgba(20, 24, 28, .72);
  outline: none;
}

.hero-scroll:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
}

@keyframes hero-scroll-bob {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(8px); }
}

/* Slider wrapper. Explizite top/left/width/height statt inset:0, damit sich
   der Rahmen in der verkleinerten Ansicht (T-6) per Transition auf die von
   script.js berechneten Masse (--frame-*) zusammenfahren lässt. */
.slider-wrap {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  cursor: col-resize;
  user-select: none;
  -webkit-user-select: none;
  touch-action: pan-y;
  opacity: 1;
  transition:
    opacity 280ms var(--ease-smooth),
    /* Verkleinerungs-Übergang (N1c-5 U-2): .9s → .5s, deckungsgleich mit
       SCROLL_LOCK_TRANSITION_MS in script.js. */
    top .5s cubic-bezier(.6, 0, .2, 1),
    left .5s cubic-bezier(.6, 0, .2, 1),
    width .5s cubic-bezier(.6, 0, .2, 1),
    height .5s cubic-bezier(.6, 0, .2, 1),
    border-radius .5s ease;
}

/* Verkleinerte Ansicht (nur ab 1024px, Klasse is-compact): Rahmen im
   Seitenverhältnis 16:9 (Desktop-Bildmass), zentriert zwischen Menü und
   unterer Leiste; Masse als CSS-Variablen von script.js berechnet
   (updateCompactFrame, bei Resize neu). Da Rahmen und Bild dasselbe
   Seitenverhältnis haben, zeigt background-size:cover das Bild vollständig
   (T29v2 §3, N1c-2 T-6). */
#hero.is-compact .slider-wrap {
  top: var(--frame-top, 0);
  left: var(--frame-left, 0);
  width: var(--frame-width, 100%);
  height: var(--frame-height, 100%);
  border-radius: 8px;
}

/* Bildtitel als Bildunterschrift (D-153): nur in der verkleinerten Ansicht
   ab 1024px. Absolut unter dem Rahmen, im oberen Leerraum der unteren Leiste
   (kein Einfluss auf das Layout); feste Einzeilenhöhe, lange Titel mit
   Auslassung, rein dekorativ (aria-hidden). Blendet beim Paarwechsel mit
   den Bildern aus und ein. */
.hero-caption-bar,
.hero-caption,
.hero-tagline {
  display: none;
  margin: 0;
}

@media (min-width: 1024px) {
  /* Leiste: Bildtitel links (kürzt sich mit Auslassung), feste Zeile rechts. */
  .hero-caption-bar {
    display: flex;
    align-items: baseline;
    gap: 24px;
    position: absolute;
    z-index: 9;
    top: calc(var(--frame-top, 0px) + var(--frame-height, 100%) + 5px);
    left: var(--frame-left, 0);
    width: var(--frame-width, 100%);
    box-sizing: border-box;
    padding: 0 2px;
    pointer-events: none;
  }

  .hero-tagline {
    display: block;
    flex: none;
    margin-left: auto;
    color: var(--anthracite);
    font-size: 1rem;
    line-height: 1.4;
    white-space: nowrap;
    opacity: 0;
    transition: opacity .3s ease;
  }

  #hero.is-compact .hero-tagline {
    opacity: 1;
    transition-delay: .45s;
  }

  .hero-caption {
    display: block;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    color: var(--anthracite); /* N1c-16 F-3 (D-153): Textfarbe des body statt gedämpft */
    font-size: 1rem; /* N1c-16 F-3: vorher .85rem */
    line-height: 1.4;
    white-space: nowrap;
    text-overflow: ellipsis;
    pointer-events: none;
    opacity: 0;
    transition: opacity .3s ease;
  }

  #hero.is-compact .hero-caption {
    opacity: 1;
    transition-delay: .45s;
  }

  #hero.is-compact .hero-caption.is-changing {
    opacity: 0;
    transition-delay: 0s;
  }
}

/* Beim Bildwechsel bleibt die 50/50-Ansicht sichtbar; das Zurücksetzen
   auf Vorher passiert erst in dieser kurzen unsichtbaren Phase. */
.slider-wrap.is-pair-transition {
  opacity: 0;
  pointer-events: none;
}

.slider-wrap.is-before-only .slider-side--after,
.slider-wrap.is-before-only .slider-divider {
  opacity: 0;
}

/* Before / After containers */
.slider-side {
  position: absolute;
  inset: 0;
}

.slider-side--before { z-index: 1; }
.slider-side--after  { z-index: 2; }

/* The actual image divs (placeholder via bg-color; real images via bg-image) */
.slide-img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: var(--bg);
}

.slide-img--before { background-color: var(--bg); }
.slide-img--after  { background-color: var(--bg); }

/* Labels: deutlich lesbar, auf dezentem dunklem Etikett (T29 §2). */
/* Nachbesserung (Befund 10a): grösser (ca. 15-16px statt 13.6px) und
   Etikett-Hintergrund auf mind. rgba(20,24,28,.72) angehoben, damit der
   Kontrast auch über hellem Bildgrund rechnerisch ≥ 4,5:1 erreicht
   (vorher rgba(20,24,28,.5) ≈ 3,2:1). */
.slide-label {
  position: absolute;
  z-index: 5;
  bottom: 84px;
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(20, 24, 28, .75);
  font-family: var(--font);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.95);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.8s ease;
}

.slide-label--before { left: 32px; }
.slide-label--after  { right: 32px; }

#hero.is-ready .slide-label { opacity: 1; }

/* Slider divider line */
.slider-divider {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 6;
  width: 2px;
  background: rgba(255, 255, 255, 0.85);
  transform: translateX(-50%);
  /* left is set dynamically by JS */
  left: 90%;
}

/* Draggable handle */
.slider-handle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: white;
  border: none;
  cursor: col-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--anthracite);
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.22);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.slider-handle:hover,
.slider-handle:focus-visible {
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
  outline: none;
}

.slider-handle:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
}

.handle-arrow {
  width: 10px;
  height: 18px;
  flex-shrink: 0;
}

/* Hero overlay: Claim vertikal bei 75 % der Empfangshöhe (Zentrum 25 % von
   unten), horizontal zentriert (T29v2 §2, N1c-2 T-3). */
.hero-overlay {
  position: absolute;
  top: 75%;
  right: 0;
  left: 0;
  z-index: 10;
  width: calc(100% - (var(--nav-pad) * 2));
  margin: 0 auto;
  transform: translateY(-50%);
  text-align: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity .4s ease;
}

/* Claim und Pfeil in der verkleinerten Ansicht ausgeblendet (T29v2 §3,
   N1c-2 T-6). */
#hero.is-compact .hero-overlay,
#hero.is-compact .hero-scroll {
  opacity: 0;
  pointer-events: none;
}

.hero-claim {
  color: white;
  font-size: inherit;
  font-weight: inherit;
  margin: 0;
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
}

/*
 * Wiederverwendbares Marken-Lockup: unverändertes RECOLORO-SVG plus Text.
 * Referenz für die optische Kalibrierung ist ein Grossbuchstabe im Folgetext:
 * Seine tatsächlich sichtbare Ober- und Unterkante muss mit dem Wortzeichen
 * innerhalb von maximal einem Bildpixel übereinstimmen. CSS-Zeilenboxen sind
 * ausdrücklich kein Abnahmekriterium.
 */
.brand-lockup {
  --brand-lockup-brand-width: clamp(174px, 27vw, 332px);
  --brand-lockup-gap: clamp(10px, 1vw, 16px);
  --brand-lockup-message-size: clamp(2.044rem, 5.075vw, 3.9rem);
  --brand-lockup-message-shift-y: -0.074em;
  white-space: nowrap;
}

.brand-lockup__brand,
.brand-lockup__message {
  display: inline-block;
  vertical-align: middle;
}

.brand-lockup__brand {
  width: var(--brand-lockup-brand-width);
  margin-right: var(--brand-lockup-gap);
  line-height: 0;
}

.brand-lockup__wordmark {
  display: block;
  width: 100%;
  height: auto;
}

.brand-lockup__message {
  font-family: var(--font);
  font-size: var(--brand-lockup-message-size);
  font-weight: 300;
  letter-spacing: -0.04em;
  line-height: .98;
  transform: translateY(var(--brand-lockup-message-shift-y));
}

/* «RECOLORO» steht fest; nur die Wortmarke selbst braucht keine eigene
   Animation (T29 §2). */
.hero-wordmark {
  filter: brightness(0) invert(1);
}

/* Textteil «bringt die Farbe zurück.»: wortweise Einblendung aus einer
   Maske von unten, bei jedem Schieber-Durchlauf neu (T29v2 §2, N1c-2 T-3).
   Jedes Wort sitzt in einem eigenen overflow:hidden-Fenster; nur das innere
   span verschiebt sich (transform), die Aussenbox behält ihre Breite —
   «RECOLORO» verschiebt sich dadurch nie, der Platz bleibt reserviert.
   Ausblenden (keine .is-revealed-Klasse) ist die Grundregel: schnell,
   synchron, ohne Verzögerung (~0,25 s, Abtauchen vor dem nächsten Bildpaar).
   Einblenden (.is-revealed) überschreibt das je Wort versetzt (~90 ms) mit
   einer längeren, weicheren Kurve (~0,6 s). */
.claim-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: .12em;
  margin-bottom: -.12em;
}

.claim-word > span {
  display: inline-block;
  transform: translateY(115%);
  transition: transform .25s ease-in;
}

.hero-claim.is-revealed .claim-word > span {
  transform: translateY(0);
  transition: transform .6s cubic-bezier(.2, .75, .2, 1);
}

.hero-claim.is-revealed .claim-word:nth-child(2) > span { transition-delay: .09s; }
.hero-claim.is-revealed .claim-word:nth-child(3) > span { transition-delay: .18s; }
.hero-claim.is-revealed .claim-word:nth-child(4) > span { transition-delay: .27s; }

/* Handy (<1024px, N1c-5 U-4a): der Claim ist das LCP-Element; die
   wortweise Einblendung (siehe oben) sorgte für einen "Element Render
   Delay", weil der Text erst nach dem Schieber-Tween sichtbar wurde. Beim
   allerersten Bildpaar steht der Textteil deshalb bereits im ersten Paint
   vollständig da (kein FOUC-Umweg über opacity 0, reiner CSS-Ausgangs-
   zustand — gilt auch, bevor script.js überhaupt läuft). Sobald der Claim
   zum ersten Mal regulär eingeblendet wurde, setzt showClaimText() in
   script.js dauerhaft die Klasse claim-was-revealed auf #heroClaim; ab
   diesem Zeitpunkt (spätestens beim Übergang zum zweiten Bildpaar) gilt
   wieder die normale Ein-/Ausblendelogik von oben. Deckungsgleich mit
   compactMediaQuery ('(min-width: 1024px)') in script.js; ab 1024px
   (Desktop) unverändert. */
@media (max-width: 1023.98px) {
  .hero-claim:not(.claim-was-revealed) .claim-word > span {
    transform: translateY(0);
    transition: none;
  }
}

/* Auftrag 98: Zeile 2 und 3 unter dem Claim. Grösse relativ zur Claim-
   Schrift (Zeile 2 etwa 42 %, Zeile 3 etwa 32 %), am Handy mindestens
   16 px bzw. 14 px. Einblendung nach dem letzten Claim-Wort (Wort 4 endet
   bei .27 s + .6 s), Ausblenden synchron mit dem Claim (.25 s). */
.hero-sub {
  margin: clamp(10px, 1.2vw, 18px) 0 0;
  color: white;
  font-size: max(16px, calc(clamp(2.044rem, 5.075vw, 3.9rem) * .42));
  font-weight: 400;
  line-height: 1.3;
  text-wrap: balance;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .55), 0 2px 20px rgba(0, 0, 0, .4);
  opacity: 0;
  transition: opacity .25s ease-in;
}

.hero-sub--small {
  margin-top: 6px;
  font-size: max(14px, calc(clamp(2.044rem, 5.075vw, 3.9rem) * .32));
}

.hero-claim.is-revealed ~ .hero-sub {
  opacity: 1;
  transition: opacity .7s ease .9s;
}

.hero-claim.is-revealed ~ .hero-sub--small {
  transition-delay: 1.2s;
}

/* Handy: wie der Claim beim ersten Bildpaar sofort sichtbar. */
@media (max-width: 1023.98px) {
  .hero-claim:not(.claim-was-revealed) ~ .hero-sub {
    opacity: 1;
    transition: none;
  }
}

#hero.is-empty .hero-sub {
  color: var(--anthracite);
  text-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .hero-claim.is-revealed ~ .hero-sub,
  .hero-claim.is-revealed ~ .hero-sub--small { transition-delay: 0s; }
}

/* ── Mobile ─────────────────────────────────────── */
@media (max-width: 900px) {
  :root {
    --nav-pad: 24px;
  }

  .nav-hamburger {
    display: flex;
  }

  .nav-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--bg);
    border-top: 1px solid var(--border);
    padding: 8px 0 12px;
    display: none;
  }

  .nav-menu.is-open {
    display: flex;
  }

  .nav-menu a {
    display: block;
    padding: 13px 24px !important;
    color: var(--anthracite) !important;
    font-size: 1rem;
    border: none !important;
    margin: 0 !important;
  }

  .nav-menu a:hover {
    background: rgba(0, 0, 0, 0.04);
    opacity: 1;
  }

  .nav-link--cta {
    display: inline-block !important;
    width: fit-content;
    margin: 10px 24px 4px !important;
  }

  .slide-label--before { left: 16px; }
  .slide-label--after  { right: 16px; }
  .slide-label { bottom: 72px; }

  .slider-handle {
    width: 46px;
    height: 46px;
  }

  .hero-scroll {
    width: 48px;
    height: 48px;
  }
}

/* ── Inhaltsabschnitte / Conversion ────────────── */
.content-section,
.offer-section {
  padding: var(--section-pad-y) var(--nav-pad);
  scroll-margin-top: var(--nav-h-scrolled);
}

/* Formular bleibt kompakter, damit es bei 1440 × 900 unter der Navigation
   ohne Scrollen sichtbar ist (N1c T-11, bewusste Abweichung vom allgemeinen
   Abschnittsabstand, siehe eigene Regel weiter unten). */

.content-section {
  background: var(--anthracite);
  color: #fff;
}

.content-section--light,
.faq-section {
  background: var(--warm-white);
  color: var(--anthracite);
}

/* Kopf → Inhalt 56 px, Mobil 40 px (T29v2 §1, N1c-2 T-1). Keine eigene
   Breitenbegrenzung mehr (früher 760px, Sonderbreite) — die Breite ergibt
   sich aus dem umgebenden .container bzw. den einzelnen Abschnitten. */
.section-heading {
  max-width: none;
  margin: 0 0 56px;
  text-align: left;
}

@media (max-width: 900px) {
  .section-heading { margin-bottom: 40px; }
}

/* Abschnittsüberschriften: linksbündig, auf Desktop einzeilig, alle
   gleich gross (ca. 40–44 px), Stärke 400, Anthrazit (T29 §1). Überschrift
   → Einleitung 20 px (T29v2 §1). */
.section-heading h2,
.offer-copy h2,
.applications-intro h2 {
  max-width: none;
  margin-bottom: 20px;
  color: var(--anthracite);
  font-size: clamp(2.4rem, 2.9vw, 2.75rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

/* Einleitungstext: 18 px, Stärke 400, Anthrazit, max. ca. 70 Zeichen/Zeile
   (T29v2 §1). :last-of-type (statt :last-child), da in .offer-copy nach
   dem Vorspann noch die Schritte-Liste «Was nach dem Absenden passiert»
   (.offer-steps) folgt (T29v3 §8). :not(.section-eyebrow) ergänzt
   (Nachbesserung): in Vergleich/FAQ ist die Rubrik-Zeile der einzige <p>
   in .section-heading und damit zugleich :last-of-type — ohne den
   Ausschluss wurde ihre Rubrik-Farbe von hier überschrieben (Anthrazit
   statt Blau). Sonderbreite 680px (N1c-2 T-1) durch 70ch ersetzt. */
.section-heading > p:last-of-type:not(.section-eyebrow),
.offer-copy > p:last-of-type:not(.section-eyebrow) {
  max-width: 70ch;
  color: var(--anthracite);
  font-size: 1.125rem;
  font-weight: 400;
  line-height: 1.6;
}

/* Geteilter Kopf (Vorteile, T29v2 §5, N1c-2 T-9): Rubrik+Überschrift auf
   den Spalten 1-6, Einleitung auf den Spalten 7-12. align-items:baseline
   statt stretch/start, damit die Oberkante der Rubrik und die erste
   Textzeile der Einleitung (unterschiedliche Schriftgrössen) optisch auf
   gleicher Höhe stehen. */
.section-heading--split {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--grid-gap);
  align-items: baseline;
}

.section-heading--split .section-heading__head {
  grid-column: 1 / 7;
}

.section-heading--split > p {
  grid-column: 7 / 13;
  margin-top: 0;
}

@media (max-width: 900px) {
  .section-heading--split {
    display: block;
  }

  .section-heading--split > p {
    margin-top: 20px;
  }
}

/* Vorteile-Kacheln: weiss, kompakt, gleich hoch, auf Desktop vier
   nebeneinander (T29 §5). Oberkante: blaue Linie mit kurzer Lücke links,
   darin die Nummer 01–04 in Blau, danach läuft die Linie weiter — statisch,
   keine Animation.
   Nachbesserung (Befund 7c): kein max-width/margin:auto mehr — die
   Kachelreihe war dadurch bei 1440px zentriert (Linke Kante x≈80) statt
   linksbündig auf der Inhaltskante der Überschrift (x≈48) zu beginnen. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}

/* Keine Mindesthöhe mehr über den Inhalt hinaus (T29v2 §5, N1c-2 T-9) —
   gleiche Höhe ergibt sich allein aus dem Grid-Standard (align-items:
   stretch, hier nicht überschrieben). */
.card-grid article {
  display: flex;
  flex-direction: column;
  padding: 0 clamp(20px, 2.2vw, 28px) clamp(24px, 3vw, 32px);
  background: #fff;
}

/* Nachbesserung (Befund 7b): .card-top erhielt nach der negativen
   Aussenrand-Verschiebung (Flucht zur Kachel-Aussenkante) zusätzlich
   dasselbe Innen-Padding wie der Artikel selbst — beide hoben sich exakt
   auf, wodurch die Linie faktisch wieder auf der eingerückten
   Inhaltskante landete statt auf der echten Kachel-Aussenkante. Das
   erneute Padding entfällt jetzt; ::before/::after laufen dadurch von der
   linken bis zur rechten Aussenkante der Kachel, mit der Nummer in der
   kurzen Lücke links (Text darunter bleibt über das Artikel-Padding
   eingerückt). */
.card-top {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 clamp(-28px, -2.2vw, -20px) 20px;
}

.card-top::before {
  content: '';
  width: 16px;
  height: 2px;
  flex-shrink: 0;
  background: var(--blue);
}

.card-top::after {
  content: '';
  flex: 1;
  height: 2px;
  background: var(--blue);
}

.card-number {
  color: var(--blue);
  font-size: .85rem;
  font-weight: 600;
  white-space: nowrap;
}

.card-grid h3 {
  margin-bottom: 10px;
  font-size: 1.3rem;
  font-weight: 400;
  color: var(--anthracite);
}

/* N1c-8 U-1: Kacheltitel bleiben einzeilig, wenn der Container unter ca. 1200 px
   liegt (Laptop 1280 px mit Scrollleiste). Text unverändert (Entscheid 05.10.2026). */
@media (min-width: 901px) and (max-width: 1320px) {
  .card-grid h3 { font-size: 1.15rem; }
}

/* Nachbesserung (Befund 7a): gedämpftes Grau → Anthrazit, 16px → 17px. */
.card-grid p {
  color: var(--anthracite);
  font-size: 1.0625rem;
  line-height: 1.6;
}

/* ── Vergleich ──────────────────────────────────── */
/* Heller Abschnittshintergrund statt dunkel (N1b T-5b, CI-Clipboard v0.1
   Abschnitt 5: Recoloro-CI ist grundsätzlich hell). Abfolge damit:
   Anwendungen --bg → Vorteile Warm-Weiss → Vergleich --bg → Ablauf
   Warm-Weiss. */
.vergleich-section {
  background: var(--bg);
  color: var(--anthracite);
}

/* Volle Inhaltsbreite (T29v2 §1/§6, N1c-2 T-1/T-10): Sonderbreite 1120px
   entfällt, die Tabelle nimmt die Breite des .container ein, in dem sie
   steht. */
.vergleich-table-wrap {
  margin: 0 0 clamp(40px, 6vw, 64px);
  overflow-x: auto;
}

.vergleich-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
}

.vergleich-table th,
.vergleich-table td {
  text-align: left;
  vertical-align: top;
  font-weight: 400;
}

/* Kein Versal-Text mit Laufweite auf den Tabellenköpfen mehr: Ursache des
   Befunds «NEUANST RICH» (Chrome/Windows zeigt bei Laufweite + Versalien auf
   dem Variable Font ungleichmässige, teils klaffende Zeichenabstände, hier an
   „NEUANSTRICH" besonders auffällig). Laufweite bleibt Rubriken vorbehalten
   (T29 §1, N1c T-1). */
.vergleich-table thead th {
  padding: 16px 20px;
  font-size: 1rem;
  font-weight: 600;
}

.vergleich-table thead th:first-child { background: none; }

.vergleich-table tbody th[scope="row"] {
  padding: 18px 20px 18px 0;
  color: var(--anthracite);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.4;
}

/* Tabellentext 16 px (T29 §6). */
.vergleich-table td {
  padding: 18px 20px;
  font-size: 1rem;
  line-height: 1.55;
}

.vergleich-table .col-ersatz,
.vergleich-table .col-neuanstrich {
  background: var(--bg);
  color: var(--text-muted);
}

/* RECOLORO-Spalte: Text Stärke 600 Anthrazit (T29 §6). */
.vergleich-table td.col-recoloro {
  font-weight: 600;
}

/* Dünne Trennlinien über die volle Breite, ausser unter der weissen
   RECOLORO-Karte (die Linie darf die Karte nicht zerschneiden) und in
   der letzten Zeile. */
.vergleich-table tbody tr:not(:last-child) th[scope="row"],
.vergleich-table tbody tr:not(:last-child) td.col-ersatz,
.vergleich-table tbody tr:not(:last-child) td.col-neuanstrich {
  border-bottom: 1px solid var(--border);
}

.vergleich-table .col-recoloro {
  background: #fff;
  color: var(--anthracite);
  box-shadow: -8px 0 20px -12px rgba(0, 0, 0, .4), 8px 0 20px -12px rgba(0, 0, 0, .4);
}

.vergleich-table thead .col-recoloro {
  color: var(--blue);
  font-weight: 700;
  box-shadow: -8px 0 20px -12px rgba(0, 0, 0, .4), 8px 0 20px -12px rgba(0, 0, 0, .4), 0 -8px 16px -12px rgba(0, 0, 0, .4);
  border-radius: 10px 10px 0 0;
}

.vergleich-table tbody tr:last-child .col-recoloro {
  box-shadow: -8px 0 20px -12px rgba(0, 0, 0, .4), 8px 0 20px -12px rgba(0, 0, 0, .4), 0 8px 16px -12px rgba(0, 0, 0, .4);
  border-radius: 0 0 10px 10px;
}

/* Unter der Tabelle, rechtsbündig: Hinweiszeile + Knopf «Offerte anfragen»
   (T29 §6). Sonderbreite 1120px entfällt (N1c-2 T-1); die Box nimmt die
   volle Breite des umgebenden .container ein, der Knopf bleibt über
   justify-content:flex-end rechtsbündig an der Inhaltskante. */
.vergleich-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 20px 28px;
  margin: 0;
  text-align: right;
}

.vergleich-cta p {
  color: var(--anthracite);
  font-size: 1rem;
  line-height: 1.5;
}

@media (max-width: 767px) {
  .vergleich-table,
  .vergleich-table thead,
  .vergleich-table tbody,
  .vergleich-table tr,
  .vergleich-table th,
  .vergleich-table td {
    display: block;
    width: auto;
  }

  .vergleich-table thead { display: none; }

  .vergleich-table tbody tr {
    margin-bottom: 32px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border);
  }

  .vergleich-table tbody tr:last-child { border-bottom: none; }

  .vergleich-table tbody th[scope="row"] {
    padding: 0 0 12px;
    color: var(--anthracite);
    font-size: 1.05rem;
    border-bottom: 0 !important;
  }

  .vergleich-table td {
    padding: 3px 0;
    border-bottom: 0 !important;
    box-shadow: none !important;
  }

  .vergleich-table td.col-ersatz,
  .vergleich-table td.col-neuanstrich {
    background: none;
    color: var(--text-muted);
    font-size: .85rem;
  }

  .vergleich-table td.col-ersatz::before,
  .vergleich-table td.col-neuanstrich::before {
    content: attr(data-label) ": ";
    color: var(--anthracite);
    font-weight: 600;
  }

  .vergleich-table td.col-recoloro {
    margin-top: 10px;
    padding: 16px 18px;
    border-radius: 8px;
    font-size: 1.08rem;
    font-weight: 600;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .18) !important;
  }

  /* Mobile: RECOLORO gross, mit sichtbarer Bezeichnung in Blau (T29 §6). */
  .vergleich-table td.col-recoloro::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 6px;
    color: var(--blue);
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
  }

  /* Fliesstext mobil linksbündig (T29 §11). */
  .vergleich-cta {
    justify-content: flex-start;
    text-align: left;
  }
}

/* Kompakter als der übrige vertikale Rhythmus, damit das Formular bei
   1440 × 900 unter der fixierten Navigation ohne Scrollen sichtbar ist
   (T29 §8, N1c T-11). */
/* Nachbesserung (Kanten-Fluchtprüfung, N1c-2 T-1/T-11): max-width+margin
   direkt auf .offer-section (das zugleich die genab var(--nav-pad)
   gepolsterte Vollbreiten-Box ist) addierte sich mit dem nav-pad-Padding zu
   80+48=128px Einzug statt 80px wie bei allen anderen Abschnitten. Jetzt
   wie überall über einen inneren .container/.offer-grid-Wrapper gelöst;
   .offer-section bleibt reine Vollbreiten-Box mit dem üblichen
   nav-pad-Rand. */
.offer-section {
  padding-top: clamp(40px, 5vw, 64px);
  padding-bottom: clamp(40px, 5vw, 64px);
  background: var(--bg);
}

/* Nachbesserung (Kanten-Fluchtprüfung, N1c-2 T-1/T-11): eigenes Zwei-
   Spalten-Verhältnis statt des gemeinsamen 12-Spalten-Rasters — die
   Formularkarte begann dadurch rechts der Spalte-6-Kante (an der z. B.
   die FAQ-Fragenliste beginnt). Jetzt dasselbe 12-Spalten-Raster wie
   .faq-layout/.section-heading--split (T29v2 §1/§8): linke Spalte 1–6,
   rechte Spalte (Formular) 6–12 — Kante fluchtet mit der FAQ-Liste. */
.offer-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--grid-gap);
  align-items: start;
}

.offer-copy {
  grid-column: 1 / 6;
  position: sticky;
  top: calc(var(--nav-h-scrolled) + 40px);
}

/* «Was nach dem Absenden passiert»: nummerierte Liste (T29v3 §8). */
.offer-steps {
  margin-top: clamp(24px, 3vw, 36px);
}

.offer-steps__title {
  margin-bottom: 14px;
  color: var(--anthracite);
  font-size: 1.05rem;
  font-weight: 500;
}

.offer-steps ol {
  display: grid;
  gap: 12px;
  list-style: none;
  counter-reset: offer-step;
}

.offer-steps li {
  position: relative;
  padding-left: 30px;
  color: var(--text-muted);
  font-size: .96rem;
  line-height: 1.5;
}

.offer-steps li::before {
  counter-increment: offer-step;
  content: counter(offer-step) ".";
  position: absolute;
  left: 0;
  color: var(--blue);
  font-weight: 600;
}

.offer-steps li strong {
  color: var(--anthracite);
  font-weight: 600;
}

.lead-form {
  grid-column: 6 / 13;
  display: grid;
  gap: 18px;
  padding: clamp(24px, 3vw, 40px);
  background: #fff;
  box-shadow: 0 24px 70px rgba(30, 36, 40, .08);
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

/* Verhindert, dass ein Feld ohne Hinweistext (z. B. PLZ) auf die Höhe
   seines Reihen-Partners mit Hinweistext (z. B. Telefonnummer) gestreckt
   wird; beide Eingabefelder behalten so dieselbe Oberkante (N1b T-9). */
.field-grid > label {
  align-self: start;
}

.lead-form label,
.lead-form legend {
  display: grid;
  gap: 6px;
  font-size: .92rem;
  font-weight: 500;
}

.lead-form fieldset {
  border: 0;
}

/* Nachbesserung (N1c-2 T-11): input[type=number] (Anzahl Bauteile) fehlte
   in der Selektor-Liste und erschien im Browser-Standard statt wie die
   übrigen Textfelder. */
.lead-form input[type="text"],
.lead-form input[type="email"],
.lead-form input[type="tel"],
.lead-form input[type="number"],
.lead-form textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--bg);
  color: var(--anthracite);
  font: inherit;
}

.lead-form input[type="text"],
.lead-form input[type="email"],
.lead-form input[type="tel"],
.lead-form input[type="number"] {
  min-height: 48px;
  padding: 12px 14px;
}

/* Notizen: rows="3" (T29 §8). */
.lead-form textarea {
  min-height: 82px;
  padding: 12px 14px;
  resize: vertical;
}

/* Datei-Upload: gestalteter Knopf, natives Input bleibt zugänglich
   (nicht display:none) und liegt unsichtbar über dem Knopf (N1b T-9). */
.file-field {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 4px;
}

.file-field__control {
  position: relative;
  display: inline-flex;
}

/* Nur umrandet, nicht gefüllt (T29 §8). Normale Schreibung, keine Laufweite
   (T29 §1 — Laufweite nur auf Rubriken), Stärke 600 wie die übrigen Knöpfe
   (Nachbesserung). */
.file-field__button {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 9px 22px;
  border: 1.5px solid var(--blue);
  border-radius: 999px;
  background: transparent;
  color: var(--blue);
  font-family: var(--font);
  font-size: .85rem;
  font-weight: 600;
  white-space: nowrap;
  transition: background .2s ease, color .2s ease;
}

.file-field__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}

.file-field__input:hover ~ .file-field__button {
  background: var(--blue);
  color: #fff;
}

.file-field__input:focus-visible ~ .file-field__button {
  outline: 3px solid rgba(15, 70, 212, .35);
  outline-offset: 2px;
}

.file-field__filenames {
  color: var(--text-muted);
  font-size: .88rem;
  line-height: 1.4;
}

.lead-form input:focus-visible,
.lead-form textarea:focus-visible,
.component-options label:has(input:focus-visible) {
  outline: 3px solid rgba(15, 70, 212, .24);
  outline-offset: 2px;
  border-color: var(--blue);
}

/* Stärke 400 statt 300 (T29v2 §1) — Hinweise unter Telefon, Masse, Anzahl
   und Upload waren zu dünn (Nachbesserung N1c-2 T-11). */
.lead-form small {
  color: var(--text-muted);
  font-size: .82rem;
  font-weight: 400;
  line-height: 1.4;
}

.lead-form .privacy-check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-weight: 300;
  line-height: 1.45;
  cursor: pointer;
}

/* Pflichtfeld-Zeile (N1c-5 U-3): linke Kante auf die Startkante des
   Einwilligungstexts ("Ich habe die Datenschutzinformationen ...").
   .privacy-box liegt in Spalte 2 eines zweispaltigen .field-grid (gap
   16px) — ihre linke Kante liegt bei (100% + 16px) / 2 der .field-grid
   -Breite, die identisch mit der Breite von .form-required-note ist
   (beide sind volle Zeilen im einspaltigen .lead-form-Grid). Darin folgen
   Rahmen der Box (1px), Box-Padding (16px), Kästchenbreite (18px) und
   Zeilenabstand der Box (10px) bis zur Textkante = 45px. Ab 640px wird
   .field-grid einspaltig (siehe Media Query unten), dort verschwindet der
   Spalten-Versatz. Geprüft per getBoundingClientRect auf 1440/1280/390:
   Abweichung 0px. Schriftgrösse wie Einwilligungstext (.92rem, von
   ".lead-form label"), da die Zeile auf allen drei Breiten einzeilig
   bleibt; Farbe weiterhin gedämpft über ".lead-form small"
   (var(--text-muted)). Abstand zum Absendeknopf ergibt sich unverändert
   aus dem Grid-Row-Gap des Formulars (18px, wie zwischen allen anderen
   Feldgruppen). */
.lead-form small.form-required-note {
  padding-left: calc((100% + 16px) / 2 + 45px);
  font-size: .92rem;
}

@media (max-width: 640px) {
  /* .field-grid wird hier einspaltig (siehe unten), .privacy-box beginnt
     dann an der Kante von .form-required-note selbst + Rahmen/Padding/
     Kästchen/Lücke, ohne Spalten-Versatz. */
  .lead-form small.form-required-note {
    padding-left: 45px;
  }
}

/* Einwilligung als umrandete Box, neben den Fotos (T29 §8, N1c-2 T-11). */
.privacy-box {
  display: flex;
  align-items: center;
  height: 100%;
  padding: 14px 16px;
  border: 1px solid var(--border);
  background: var(--bg);
}

/* Wahlkarten Richtpreis / verbindliche Offerte (T29 §8, N1c-2 T-11):
   Radiobuttons name="request_type", aktive Karte über :has(input:checked)
   rein in CSS erkannt (kein JS nötig für die Optik). Tastaturbedienbar
   (native Radiogruppe), sichtbarer Fokus über :has(input:focus-visible). */
.request-type-choice {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  border: 0;
}

.request-type-card {
  position: relative;
  display: block;
  align-content: start;
  padding: 16px 18px 16px 42px;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}

.request-type-card input {
  position: absolute;
  top: 18px;
  left: 16px;
  margin: 0;
  accent-color: var(--blue);
}

.request-type-card__title {
  display: block;
  margin-bottom: 4px;
  font-weight: 600;
  color: var(--anthracite);
}

.request-type-card__desc {
  display: block;
  color: var(--text-muted);
  font-size: .88rem;
  line-height: 1.45;
}

.request-type-card:has(input:checked) {
  border-color: var(--blue);
  background: rgba(15, 70, 212, .05);
}

.request-type-card:has(input:focus-visible) {
  outline: 3px solid rgba(15, 70, 212, .24);
  outline-offset: 2px;
}

/* Pflicht-Sternchen, je nach Wahl (Richtpreis/Offerte) über script.js
   ein-/ausgeblendet (T29 §8, N1c-2 T-11). */
.field-star {
  color: var(--blue);
}

.field-star[hidden] {
  display: none;
}

/* Bauteile als kompakte Chips in zwei Reihen; Checkbox bleibt das
   Formularelement, nur visuell als Chip (T29 §8). */
.component-options {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
}

.component-options label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 42px;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--anthracite);
  font-weight: 400;
  line-height: 1.3;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

/* Checked-Zustand sichtbar: Chip füllt sich blau (T29 §8). */
.component-options label:has(input:checked) {
  border-color: var(--blue);
  background: var(--blue);
  color: #fff;
}

.component-options input {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  accent-color: var(--blue);
}

.privacy-check input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  accent-color: var(--blue);
}

.privacy-check a,
.simple-panel a {
  color: var(--blue);
}

.honeypot {
  position: absolute !important;
  left: -10000px !important;
  width: 1px !important;
  height: 1px !important;
  opacity: 0 !important;
}

/* Normale Schreibung, keine Laufweite (T29 §1 — Laufweite nur auf Rubriken),
   Stärke 600 (Nachbesserung; Text im HTML war bereits «Offerte anfragen»). */
.primary-button {
  justify-self: start;
  min-height: 50px;
  padding: 14px 34px;
  border: 0;
  border-radius: 999px;
  background: var(--blue);
  color: #fff;
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
}

.primary-button:hover { background: var(--blue-dark); }
.primary-button:disabled { cursor: wait; opacity: .65; }

/* Absendeknopf linksbündig, allein auf seiner Zeile (T29 §8, N1c-2 T-11). */
.form-submit-row {
  display: flex;
  align-items: center;
}

.form-submit-row .primary-button {
  flex: 0 0 auto;
}

.form-note {
  min-height: 1.5em;
  color: #176b38;
  font-weight: 500;
  line-height: 1.5;
}

.form-note.is-error { color: #a12626; }

/* Fehlerliste über dem Absendeknopf (N1c-7 U-10): sammelt alle offenen
   Pflicht- und Formatfehler als Links, die zum jeweiligen Feld springen und
   es fokussieren. Gedämpftes Rot (#a12626, bereits bei .form-note.is-error
   verwendet) nur für Fehlertext und -rahmen, keine Ausrufezeichen. */
.form-errors {
  padding: 14px 18px;
  border: 1px solid #a12626;
  border-radius: 8px;
  background: rgba(161, 38, 38, .05);
}

.form-errors[hidden] { display: none; }

.form-errors__intro {
  margin: 0 0 8px;
  color: #a12626;
  font-weight: 600;
}

.form-errors__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 4px;
}

.form-errors__link {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  color: #a12626;
  font: inherit;
  text-decoration: underline;
  text-align: left;
  cursor: pointer;
}

.form-errors__link:hover,
.form-errors__link:focus-visible {
  color: #7a1c1c;
}

/* Einzelmeldung direkt unter dem betroffenen Feld: bestehende Wortlaute
   (z. B. «Bitte wählen Sie mindestens ein Bauteil aus.»), neu dauerhaft
   sichtbar statt nur als native Validierungsblase. */
.field-error {
  color: #a12626;
  font-size: .85rem;
  line-height: 1.4;
}

.field-error:empty { display: none; }

.lead-form input[aria-invalid="true"],
.lead-form textarea[aria-invalid="true"] {
  border-color: #a12626;
}

.lead-form fieldset[aria-invalid="true"] {
  outline: 2px solid #a12626;
  outline-offset: 6px;
}

.lead-form input[type="checkbox"][aria-invalid="true"] {
  outline: 2px solid #a12626;
  outline-offset: 2px;
}

.file-field__input[aria-invalid="true"] ~ .file-field__button {
  border-color: #a12626;
  color: #a12626;
}

/* Zweispaltig: Kopf Spalten 1-5, Fragen Spalten 6-12; Kopf bleibt beim
   Scrollen unter dem Menü stehen (T29v2 §7, N1c-2 T-10). */
.faq-layout {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--grid-gap);
  align-items: start;
}

.faq-head {
  grid-column: 1 / 6;
  position: sticky;
  top: calc(var(--nav-h-scrolled) + 24px);
}

/* Überschrift darf hier zweizeilig sein (bewusste Ausnahme, T29v2 §1). */
.faq-head h2 {
  max-width: none;
  margin-bottom: 20px;
  color: var(--anthracite);
  font-size: clamp(2.4rem, 2.9vw, 2.75rem);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.faq-list {
  grid-column: 6 / 13;
  margin: 0;
  border-top: 1px solid var(--border);
}

@media (max-width: 900px) {
  .faq-layout {
    display: block;
  }

  .faq-head {
    position: static;
    margin-bottom: 40px;
  }
}

.faq-list details { border-bottom: 1px solid var(--border); }

.faq-list summary {
  position: relative;
  padding: 26px 52px 26px 0;
  font-size: 1.2rem;
  font-weight: 400;
  cursor: pointer;
  list-style: none;
}

/* Frage semantisch als Überschrift (h3, T29v3 §12/N1c-3 U-6) statt reinem
   Text in <summary>; Optik bleibt durch vollständiges Zurücksetzen der
   Überschrift-Formatierung unverändert. */
.faq-list summary h3 {
  margin: 0;
  font: inherit;
  font-weight: inherit;
  color: inherit;
  display: inline;
}

.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after { content: '+'; position: absolute; right: 8px; color: var(--blue); }
.faq-list details[open] summary::after { content: '−'; }
.faq-list details p { max-width: 790px; padding: 0 52px 28px 0; color: var(--text-muted); line-height: 1.7; }

/* Recoloro-Blau, weisse Schrift, volles Logo (R-Symbol + Wortmarke) in
   Weiss (logo-secondary.svg), darunter der Claim (T29 §10). */
/* Fussband-Hintergrund bleibt vollflächig; der Inhalt schliesst an
   derselben Inhaltskante wie die übrigen Abschnitte ab (T29v2 §1, N1c-2
   T-1: gemeinsames Raster über .footer-inner/.container). */
.site-footer {
  padding: 52px var(--nav-pad);
  background: var(--blue);
  color: #fff;
}

.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
}

/* Nachbesserung (Befund 11): waagrechte Anordnung wie im Nav-Logo
   (.nav-logo-mark/.nav-logo-word), in Weiss, ähnliche Höhe wie dort. */
.footer-logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.footer-logo-mark {
  display: block;
  width: 28px;
  height: 28px;
  color: #fff;
}

.footer-logo-mark svg {
  display: block;
  width: 100%;
  height: 100%;
}

.footer-logo-word {
  display: block;
  /* N1d-1 W-1: wie .nav-logo-word (ViewBox 95.5 statt 92.56). */
  height: calc(26px * 95.5 / 92.56);
  width: auto;
  filter: brightness(0) invert(1);
}
.site-footer p { margin-top: 12px; color: rgba(255, 255, 255, .82); }
/* Auftrag 98: Absenderzeile und Hinweis für Fachbetriebe, zurückhaltend. */
.site-footer .footer-note { max-width: 46ch; margin-top: 8px; font-size: .875rem; line-height: 1.45; overflow-wrap: anywhere; }
.site-footer nav { display: flex; align-items: center; gap: 28px; }
.site-footer a { color: #fff; text-decoration: none; }
.site-footer a:hover { opacity: .8; }

/* Schwebende Offerte-Leiste, nur mobil (≤ 760 px); Sichtbarkeit wird von
   script.js über die Klasse is-visible gesteuert (T29 §11). display:none
   ausserhalb der Media Query und ohne is-visible, damit sie auf Desktop
   nie existiert und mobil vor dem ersten Zustand nicht aufblitzt. */
.mobile-cta { display: none; }

@media (max-width: 760px) {
  .mobile-cta {
    display: none;
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 90;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    padding: 14px 24px;
    border-radius: 999px;
    background: var(--blue);
    color: #fff;
    text-decoration: none;
    font-family: var(--font);
    font-size: .9rem;
    font-weight: 600;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
  }

  .mobile-cta.is-visible {
    display: flex;
  }
}

/* ── Pflichtseiten ─────────────────────────────── */
.simple-page { background: var(--warm-white); }
.simple-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 72px;
  padding: 0 var(--nav-pad);
  border-bottom: 1px solid var(--border);
}
.simple-header img { width: 170px; }
.simple-header a { color: var(--anthracite); text-decoration: none; }
.simple-main { min-height: calc(100vh - 180px); padding: clamp(72px, 10vw, 130px) var(--nav-pad); }
.simple-main .section-heading { text-align: left; margin-right: 0; margin-left: 0; }
.simple-main .section-heading h1 { font-size: clamp(2.4rem, 5vw, 4.8rem); font-weight: 300; }
.simple-panel { max-width: 860px; padding: clamp(28px, 5vw, 64px); background: #fff; }
.simple-panel h2 { margin-bottom: 24px; font-size: 1.7rem; font-weight: 400; }
.simple-panel h3 { margin: 32px 0 8px; font-size: 1.1rem; font-weight: 500; }
.simple-panel p, .simple-panel li { color: #50575c; line-height: 1.7; }
.simple-panel ul { padding-left: 20px; }
.simple-footer { padding: 28px var(--nav-pad); border-top: 1px solid var(--border); color: var(--text-muted); }

@media (max-width: 900px) {
  .card-grid { grid-template-columns: 1fr 1fr; }
  .offer-grid { grid-template-columns: 1fr; }
  .offer-copy,
  .lead-form { grid-column: auto; }
  .offer-copy { position: static; }
  .form-submit-row {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
  }
  .form-submit-row .primary-button {
    align-self: flex-start;
  }
}

@media (max-width: 640px) {
  .content-section,
  .offer-section { padding: 64px 24px; }
  .card-grid,
  .field-grid,
  .request-type-choice { grid-template-columns: 1fr; }
  .request-type-choice { grid-auto-rows: 1fr; }
  .card-grid article { min-height: auto; }
  .lead-form { margin: 0 -8px; padding: 28px 20px; }
  .site-footer { padding: 42px 24px; }
  .footer-inner { flex-direction: column; align-items: flex-start; }
  .site-footer nav { flex-direction: column; align-items: flex-start; gap: 14px; }
  .simple-header { padding: 0 24px; }
  .simple-main { padding: 64px 24px; }
}

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

/* ── Anwendungsgrafik / Hotspots ───────────────── */
.applications-section {
  min-height: calc(100svh - var(--nav-h-scrolled));
  padding: clamp(18px, 2vw, 30px) var(--nav-pad) 24px;
  background: var(--bg);
  scroll-margin-top: var(--nav-h-scrolled);
}

.applications-intro {
  margin: 0 0 clamp(26px, 4vh, 44px);
  text-align: left;
}

/* Rubrik über der Überschrift: Blau, 16 px, Stärke 600, Versalien mit
   Laufweite 0.08em (T29v2 §1, N1c-2 T-1: grösser, weniger gesperrt als
   zuvor) — einzige Stelle im Fliesstext-Umfeld, die bewusst Laufweite
   trägt. */
.section-eyebrow {
  margin-bottom: 12px;
  color: var(--blue);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Grafik und Liste oben bündig und gleich hoch, enden gemeinsam: Grid-
   Standard (align-items:stretch) statt bisher "end" — die Liste passt sich
   dadurch der Grafikhöhe an, kein Leerraum mehr über der Grafik (T29v2 §4,
   N1c-2 T-8). Liste ca. 400–420px (statt 470px), Grafik nimmt den Rest und
   wird dadurch grösser.
   Nachbesserung (N1c-2 T-8): min-height (vormals min(66vh,700px)) entfernt
   — bei 1440/1920 ist der Container gleich breit (auf 1280px gedeckelt),
   die Grafik dadurch gleich hoch, aber min(66vh,700px) wuchs mit der
   Bildschirmhöhe (594px bei 900, 700px bei 1080) über die Grafikhöhe
   hinaus; das gestreckte Feld folgte dieser überschüssigen Zeilenhöhe
   statt der Grafik (46 px bzw. 153 px Differenz). Die Grafikhöhe (aus dem
   Seitenverhältnis von .hotspot-stage) ist jetzt allein massgebend. */
.applications-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(400px, 420px);
  gap: clamp(24px, 2.5vw, 38px);
  margin: 0;
  align-items: stretch;
}

.hotspot-figure {
  min-width: 0;
  margin: 0;
}

.hotspot-stage {
  position: relative;
  aspect-ratio: 1537 / 1023;
  width: 100%;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 18px 50px rgba(30, 36, 40, .08);
}

.hotspot-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.hotspot-layer {
  position: absolute;
  inset: 0;
}

/* Weisser Kreis, 2-px-Rand in Recoloro-Blau; Umkehreffekt beim Überfahren
   bleibt (T29 §4). */
.hotspot-button {
  position: absolute;
  z-index: 1;
  width: clamp(23px, 1.8vw, 30px);
  height: clamp(23px, 1.8vw, 30px);
  transform: translate(-50%, -50%);
  border: 2px solid var(--blue);
  border-radius: 50%;
  background: rgba(255, 255, 255, .96);
  color: var(--blue);
  cursor: default;
  box-shadow: 0 2px 8px rgba(30, 36, 40, .28);
  transition: transform .18s ease, background .18s ease, color .18s ease, box-shadow .18s ease;
}

/* R-Symbol im Punkt ca. 15 % kleiner als zuvor (62 % → 53 %, T29 §4). */
.hotspot-mark {
  display: block;
  width: 53%;
  height: 53%;
  margin: auto;
  fill: currentColor;
}

.hotspot-button:hover,
.hotspot-button:focus-visible,
.hotspot-button.is-active {
  z-index: 2;
  background: var(--blue);
  color: #fff;
  transform: translate(-50%, -50%) scale(1.2);
  box-shadow: 0 0 0 5px rgba(15, 70, 212, .16), 0 4px 14px rgba(0, 0, 0, .25);
  outline: none;
}

/* Bauteilbezeichnung als kleine Beschriftung über dem Punkt, beim Überfahren
   und bei Tastaturfokus (T29 §4). is-active wird auch gesetzt, wenn der
   gekoppelte Listeneintrag überfahren/fokussiert wird. */
.hotspot-tooltip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 9px);
  z-index: 3;
  padding: 4px 10px;
  border-radius: 4px;
  background: rgba(20, 24, 28, .88);
  color: #fff;
  font-family: var(--font);
  font-size: .72rem;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%);
  transition: opacity .15s ease;
}

.hotspot-button:hover .hotspot-tooltip,
.hotspot-button:focus-visible .hotspot-tooltip,
.hotspot-button.is-active .hotspot-tooltip {
  opacity: 1;
}

/* Feld mit blauer Oberkante; als Flex-Spalte, damit sich die Liste
   darunter (flex:1) auf die verfügbare Höhe verteilt — Panel und Grafik
   enden dadurch gemeinsam (T29v2 §4, N1c-2 T-8).
   Nachbesserung (N1c-2 T-8): height:0 + min-height:100% statt nur
   align-self:stretch — sonst bestimmt das Panels eigener Inhalt (Feld-
   Mindesthöhen) die Grid-Zeilenhöhe mit, und die Grafik wird auf diese
   (zu grosse) Höhe hochgezogen, ohne dass das Bild mitwächst (aspect-
   ratio) → Feld endet tiefer als die Grafik. height:0 macht den
   Inhaltsbeitrag des Panels zur Zeilenhöhen-Berechnung neutral, die
   Zeilenhöhe richtet sich dadurch allein nach der Grafik; min-height:100%
   zieht das Panel danach auf die volle Zeilenhöhe. */
.application-index {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 0;
  min-height: 100%;
  align-self: stretch;
  padding: clamp(18px, 2vw, 26px);
  border-top: 3px solid var(--blue);
  background: var(--warm-white);
  box-shadow: 0 18px 50px rgba(30, 36, 40, .07);
}

/* grid-auto-rows:1fr verteilt die Feldhöhen automatisch auf die
   Grafikhöhe (ca. 35px bei 1440px Breite, T29v2 §4). */
.application-list {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  gap: 5px;
}

/* Schrift 14–15px, Stärke 400, Anthrazit (T29v2 §1/§4). Kleinerer
   vertikaler Innenabstand (Nachbesserung T-8), damit auch zweizeilige
   Bezeichnungen (z. B. «Industrie- / Tiefgaragentor») in die auf die
   Grafikhöhe verteilte Feldhöhe passen. */
.application-item {
  display: flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, .58);
  color: var(--anthracite);
  font-family: var(--font);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.15;
  text-align: left;
  cursor: default;
  transition: border-color .18s ease, background .18s ease, color .18s ease, transform .18s ease;
}

/* N1c-24 B-2: Hand nur bei Bauteilen, deren Gruppe Beispiele hat. */
.hotspot-button.has-examples,
.application-item.has-examples {
  cursor: pointer;
}

.application-item:hover,
.application-item:focus-visible,
.application-item.is-active {
  border-color: var(--blue);
  background: var(--blue);
  color: #fff;
  outline: none;
  transform: translateY(-1px);
}

/* Unter ca. 1120px: bisheriges Umbruchverhalten unverändert (T29v2 §4,
   Auftragsvorgabe Nachbesserung T-8) — die neue Bündig-Kopplung an die
   Grafikhöhe (height:0/min-height:100%, engerer Zeilenabstand) gilt nur
   im breiteren zweispaltigen Layout; hier wieder der ursprüngliche
   inhaltsbestimmte Feldaufbau (wie vor der Nachbesserung), damit sich am
   bekannten schmaleren Umbruch nichts ändert. */
@media (max-width: 1120px) {
  .applications-layout {
    grid-template-columns: minmax(0, 1fr) minmax(360px, 400px);
    gap: 24px;
    min-height: min(66vh, 650px);
  }
  .application-index { height: auto; min-height: 0; }
  .application-list { grid-auto-rows: auto; gap: 7px; }
  .application-item { padding: 6px 10px; font-size: 0.9375rem; line-height: 1.25; }
}

@media (max-width: 900px) {
  .applications-section { padding: 32px 24px 64px; }
  .applications-layout { grid-template-columns: 1fr; min-height: 0; align-items: start; }
  .hotspot-figure { width: min(100%, 900px); margin: 0 auto; }
  .application-index { margin-top: 24px; }
  .application-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .applications-intro { margin-bottom: 22px; }
  .applications-intro h2 { font-size: clamp(1.85rem, 9vw, 2.65rem); }
  .application-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hotspot-button { width: 21px; height: 21px; }
  .application-index { padding: 20px; }
  .application-item { min-height: 44px; font-size: .9375rem; }
}

/* Alle Abschnittsüberschriften auf Desktop einzeilig, ausser FAQ und Anfrage
   (T29 §1, T29v3 §8: die Anfrage-Überschrift darf zweizeilig sein). Bislang
   stand .offer-copy h2 hier fälschlich mit im nowrap – bei kurzem Text ohne
   sichtbare Wirkung, mit der neuen, längeren Überschrift (N1c-3 U-1) aber ein
   Widerspruch zur eigenen Ausnahmeregel. */
@media (min-width: 901px) {
  .section-heading h2,
  .applications-intro h2 {
    white-space: nowrap;
  }
}

@media (max-width: 480px) {
  .hero-claim {
    white-space: normal;
    line-height: 1.2;
  }

  /* Nachbesserung (Befund 10c): Wortmarke erzwungen auf eigener Zeile,
     mit Abstand zum Text darunter — vorher berührten sich Wortmarke und
     «bringt die Farbe zurück.» durch die sehr enge line-height fast. */
  .brand-lockup__brand {
    display: block;
    margin: 0 auto 14px;
  }

  .brand-lockup {
    --brand-lockup-brand-width: clamp(166px, 52vw, 242px);
    --brand-lockup-message-size: clamp(1.952rem, 9.773vw, 2.843rem);
  }
}

/* ── Gruppen-Navigation ─────────────────────────── */
.group-section {
  background: var(--warm-white);
  scroll-margin-top: var(--nav-h-scrolled);
}

/* Ab 1024px hängt script.js diesen Abschnitt (Einleitungszeile + Gruppen)
   als untere Leiste in #hero ein (placeHeroBar) — Empfang und Leiste
   zusammen füllen dann genau einen Bildschirm (T29v2 §3, N1c-2 T-6).
   Unter 1024px bleibt er ein normaler Abschnitt direkt unter dem Empfang
   (Grundregel oben). */
#hero .group-section {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 8;
  background: transparent;
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s ease;
}

#hero.is-compact .group-section {
  opacity: 1;
  pointer-events: auto;
  transition-delay: .45s;
}

/* Einleitungszeile: zentriert, 18–19px, Anthrazit; ab 1280px Breite
   einzeilig, darunter ausgeglichen umbrechend (T29v2 §3, N1c-2 T-7). */
.intro-line {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(24px, 3.5vw, 36px) var(--nav-pad) 0;
  color: var(--anthracite);
  font-size: 1.1875rem;
  font-weight: 400;
  line-height: 1.55;
  text-align: center;
  text-wrap: balance;
}

@media (min-width: 1280px) {
  .intro-line { white-space: nowrap; }
}

/* Gruppen-Schaltflächen: echte <button>, Pillenform ~40px hoch, Stärke 600
   (T29v2 §3). Aktiv: Blau gefüllt, weiss. Inaktiv: weiss, feiner grauer
   Rand, Anthrazit. Ersetzen die bisherigen unterstrichenen Reiter. */
.group-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: clamp(16px, 2.4vw, 24px) var(--nav-pad) clamp(28px, 4vw, 40px);
}

.group-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 8px 22px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: #fff;
  font-family: var(--font);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--anthracite);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.group-btn:hover {
  border-color: var(--blue);
}

/* N1c-23 W-3: display:inline-flex überstimmt sonst das hidden-Attribut
   (Kacheln ohne Bildpaar werden per script.js ausgeblendet). */
.group-btn[hidden] {
  display: none;
}

.group-btn.is-active {
  background: var(--blue);
  border-color: var(--blue);
  color: #fff;
}

/* N1c-24 B-3: «Zurück zur Grafik» rechts in der Kachelleiste, nach einem
   Sprung aus der Anwendungsgrafik. Absolut positioniert: verschiebt keine
   Kachel und ändert die Leistenhöhe nicht. Oben bündig mit der Kachelreihe
   (gleiche Polsterung wie .group-nav). */
.group-nav { position: relative; }

.back-to-graphic {
  position: absolute;
  right: var(--nav-pad);
  top: clamp(16px, 2.4vw, 24px);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 4px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font-family: var(--font);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--anthracite);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s ease;
}

.back-to-graphic svg { width: 16px; height: 16px; flex-shrink: 0; }

.back-to-graphic:hover,
.back-to-graphic:focus-visible {
  color: var(--blue);
}

.back-to-graphic:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
}

.back-to-graphic[hidden] {
  display: none;
}

@media (max-width: 1023.98px) {
  .back-to-graphic { display: none; }
}

@media (max-width: 900px) {
  .group-btn {
    padding: 7px 18px;
    font-size: 0.85rem;
  }
}

/* ── N1c-24 B-4: Beispiele unter der Anwendungsgrafik (nur unter 1024 px) ──
   Aussehen von Etiketten, Trennlinie und Griff wie im Hero unter 1024 px. */
.examples[hidden] { display: none; }

.examples {
  margin-top: 32px;
  scroll-margin-top: calc(var(--nav-h-scrolled) + 12px);
}

.examples-title {
  margin: 0 0 12px;
  font-family: var(--font);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--anthracite);
  text-align: center;
}

.examples-frame {
  position: relative;
  overflow: hidden;
  width: var(--examples-w, 100%);
  max-width: 100%;
  aspect-ratio: 585 / 1050;
  margin: 0 auto;
  background-color: #F3F4F5;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.examples-img {
  position: absolute;
  inset: 0;
  background-color: #F3F4F5;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.examples-img--before { z-index: 1; }
.examples-img--after  { z-index: 2; }

.examples-label {
  position: absolute;
  z-index: 5;
  bottom: 72px;
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(20, 24, 28, .75);
  font-family: var(--font);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.95);
  pointer-events: none;
}

.examples-label--before { left: 16px; }
.examples-label--after  { right: 16px; }

.examples-divider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  z-index: 6;
  width: 2px;
  background: rgba(255, 255, 255, 0.85);
  transform: translateX(-50%);
}

.examples-handle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 46px;
  height: 46px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: white;
  cursor: col-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--anthracite);
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.22);
  touch-action: none;
}

.examples-handle:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
}

.examples-arrow {
  width: 10px;
  height: 18px;
  flex-shrink: 0;
}

.examples-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 12px;
}

.examples-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: #fff;
  color: var(--anthracite);
  cursor: pointer;
  transition: border-color 0.2s ease;
}

.examples-nav svg { width: 10px; height: 18px; }

.examples-nav:hover { border-color: var(--blue); }

.examples-nav:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
}

.examples-nav:disabled {
  opacity: 0.4;
  cursor: default;
}

.examples-counter {
  min-width: 4.5em;
  font-family: var(--font);
  font-size: 0.95rem;
  font-weight: 600;
  text-align: center;
  color: var(--anthracite);
}

@media (min-width: 1024px) {
  .examples { display: none !important; }
}

/* ═══ N1c-27 Bauteilseite ═══════════════════════════════════════════
   Gilt für die vom Generator (bauteilseiten.py) erzeugten Seiten
   <slug>/index.html (body.bauteilseite) und für die Links in Anwendungs-
   grafik und A–Z-Liste der Hauptseite (C-1). Bestehende Regeln oben
   bleiben unverändert. Schritt 4b: Feinschliff der Gestaltung. */

/* C-1: Bauteile mit Seite sind Links, sehen aber aus wie die Knöpfe. */
a.hotspot-button,
a.application-item {
  text-decoration: none;
  cursor: pointer;
}

a.hotspot-button {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Bauteilseite: aktuelles Bauteil wie hervorgehoben, nicht verlinkte Bauteile ohne Hand. */
.hotspot-button.is-current {
  z-index: 2;
  background: var(--blue);
  color: #fff;
  transform: translate(-50%, -50%) scale(1.2);
  box-shadow: 0 0 0 5px rgba(15, 70, 212, .16), 0 4px 14px rgba(0, 0, 0, .25);
}

.hotspot-button.is-current .hotspot-tooltip { opacity: 1; }

.application-item.is-current {
  border-color: var(--blue);
  background: var(--blue);
  color: #fff;
}

.hotspot-button.is-static,
.application-item.is-static { cursor: default; }

/* Seitenrahmen: Menü von Anfang an sichtbar, Platz unter der festen Navigation. */
body.bauteilseite {
  /* Eine Breite für Karussell und Textspalte (--bt-karussell-breite). Herkunft: Das verkleinerte Karussell der
     Hauptseite (script.js updateCompactFrame) ist min(1280px, Fensterbreite − 2·Seitenrand, (Fensterhöhe − Menü 60
     − Leiste 169 − 2·16) · 16/9); gemessen 1136 px bei 1440 × 900 und 901 px bei 1366 × 768. Dieselbe Regel gilt hier,
     nur dass anstelle der Leiste der Kopf (Überschrift, Frage, Knopf), Bildtitel und die zwei Zeilen Anriss unter
     das Bild passen müssen (--bt-abzug, damit der Anriss im ersten Bildschirm sichtbar bleibt). Ergebnis (veröffentlichte
     Seite mit eigenen Fotos) 1074 px bei 1440 × 900 und 839 px bei 1366 × 768; Entwurf mit Band und Hinweiszeile 974 px
     bzw. 740 px. Daniel legt den Wert nach
     Sichtprüfung fest: nur diese Variable ändern. Unter 1024 px (Tablet/Handy) gilt die volle Seitenbreite. */
  --bt-abzug: 296px;
  --bt-karussell-breite: min(1280px, max(560px, calc((100vh - var(--bt-abzug)) * 16 / 9)));
  padding-top: var(--nav-h-scrolled);
}

body.bauteilseite.bt-entwurf { --bt-abzug: 328px; }
body.bauteilseite.bt-verwandt { --bt-abzug: 320px; }
body.bauteilseite.bt-entwurf.bt-verwandt { --bt-abzug: 352px; }

/* Niedrige Fenster: Die Kopfzeile wird schmal und stapelt sich (ca. 68 px höher). */
@media (min-width: 1024px) and (max-height: 840px) {
  body.bauteilseite { --bt-abzug: 364px; }
  body.bauteilseite.bt-entwurf { --bt-abzug: 396px; }
  body.bauteilseite.bt-verwandt { --bt-abzug: 388px; }
  body.bauteilseite.bt-entwurf.bt-verwandt { --bt-abzug: 420px; }
}

@supports (height: 100svh) {
  body.bauteilseite {
    --bt-karussell-breite: min(1280px, max(560px, calc((100svh - var(--bt-abzug)) * 16 / 9)));
  }
}

@media (max-width: 1023.98px) {
  body.bauteilseite { --bt-karussell-breite: 100vw; }
}

body.bauteilseite #nav {
  visibility: visible;
  opacity: 1;
  transition: none;
}

.bt-entwurfband {
  box-sizing: border-box;
  height: 32px;
  padding: 0 var(--nav-pad);
  border-bottom: 2px solid #c98a00;
  background: #ffd45c;
  color: var(--anthracite);
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 30px;
  text-align: center;
}

.bt-text-inhalt,
.bt-fragen-inhalt,
.bt-sprung-inhalt {
  width: min(var(--bt-karussell-breite), calc(100% - (var(--nav-pad) * 2)));
  margin-inline: auto;
}

/* Kopfzeile: gleiche Breite wie das Karussell (linke Kante H1 = linke Bildkante, rechte Kante Anfrageblock = rechte Bildkante).
   Ist es zu eng (Breite < 880 px), steht der Anfrageblock unter der Überschrift (Container-Regel unten). */
.bt-kopf {
  container: btkopf / inline-size;
  width: min(var(--bt-karussell-breite), calc(100% - (var(--nav-pad) * 2)));
  margin-inline: auto;
  padding-top: 16px;
  padding-bottom: 12px;
}

.bt-kopf-inhalt {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 40px;
}

.bt-h1 {
  flex: 1 1 280px;
  color: var(--anthracite);
  font-size: clamp(1.75rem, 2.4vw, 2.25rem);
  text-wrap: balance;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.bt-anfrage {
  flex: 0 1 400px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.bt-anfrage-frage {
  color: var(--anthracite);
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.3;
}

.bt-anfrage-knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

@container btkopf (max-width: 879.98px) {
  .bt-h1,
  .bt-anfrage { flex: 1 1 100%; }
}

@container btkopf (max-width: 879.98px) and (min-width: 600px) {
  .bt-anfrage { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px 20px; }
  .bt-anfrage-hinweis { flex-basis: 100%; }
}

.bt-anfrage-hinweis {
  color: var(--text-muted);
  font-size: .8125rem;
}

/* Karussell: ein Rahmen je Folie, Seitenverhältnis wie die Hero-Bilder (Computer 1440:810, Handy 585:1050). */
.bt-karussell {
  width: min(var(--bt-karussell-breite), calc(100% - (var(--nav-pad) * 2)));
  margin: 0 auto;
}

.bt-hinweis {
  margin-bottom: 4px;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 20px;
}

.bt-folie { display: none; margin: 0; }
.bt-folie.is-active,
.bt-karussell:not(.is-js) .bt-folie:first-child { display: block; }

.bt-rahmen {
  position: relative;
  overflow: hidden;
  aspect-ratio: 1440 / 810;
  border-radius: 8px;
  background: var(--bg);
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.bt-bild { position: absolute; inset: 0; }
.bt-bild--vor { z-index: 1; }
.bt-bild--nach { z-index: 2; }

.bt-bild picture,
.bt-bild img {
  display: block;
  width: 100%;
  height: 100%;
}

.bt-bild img { object-fit: cover; }

.bt-etikett {
  position: absolute;
  z-index: 5;
  bottom: 16px;
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(20, 24, 28, .75);
  color: rgba(255, 255, 255, .95);
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  pointer-events: none;
}

.bt-etikett--vor { left: 16px; }
.bt-etikett--nach { right: 16px; }

.bt-teiler {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 6;
  width: 2px;
  background: rgba(255, 255, 255, .85);
  transform: translateX(-50%);
}

.bt-griff {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 46px;
  height: 46px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: #fff;
  color: var(--anthracite);
  box-shadow: 0 2px 16px rgba(0, 0, 0, .22);
  cursor: col-resize;
  touch-action: none;
}

.bt-griff:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
}

/* Bildtitel wie .hero-caption der Hauptseite: 1rem, Anthrazit, einzeilig mit Auslassung, 5 px unter dem Bild. */
.bt-titel {
  min-height: 1.4em;
  margin-top: 5px;
  padding: 0 2px;
  overflow: hidden;
  color: var(--anthracite);
  font-size: 1rem;
  line-height: 1.4;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.bt-steuerung { margin-top: 12px; }

/* Computer: Pfeile und Zähler stehen in der Zeile des Bildtitels (rechts), damit der Anriss direkt unter dem Bild bleibt. */
@media (min-width: 1024px) {
  .bt-karussell { position: relative; }
  .bt-folie { position: relative; padding-bottom: 40px; }
  .bt-steuerung { position: absolute; right: 0; bottom: 0; margin-top: 0; gap: 12px; }
  .bt-steuerung .examples-nav { width: 40px; height: 40px; }
  .bt-titel { position: absolute; left: 0; right: 0; bottom: 0; box-sizing: border-box; height: 40px; min-height: 0; margin-top: 0; padding-right: 190px; line-height: 40px; }
}

/* Zeiger: Überblendung zum nächsten Paar (wie .slider-wrap.is-pair-transition der Hauptseite). */
.bt-folien { transition: opacity .28s ease; }
.bt-folien.is-wechsel { opacity: 0; }
.bt-steuerung[hidden] { display: none; }

/* Handy: Bild über die ganze Breite im Hochformat; Bildtitel bleibt für Bildschirmleser, wird aber nicht gezeigt (wie auf der Hauptseite). */
@media (max-width: 700px) {
  .bt-karussell { width: 100%; }
  .bt-hinweis { padding-inline: var(--nav-pad); }
  .bt-rahmen { aspect-ratio: 585 / 1050; border-radius: 0; }
}

@media (max-width: 1023.98px) {
  .bt-titel {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
  }
}

/* Text unter dem Bild */
.bt-text-inhalt { padding-top: 8px; }

.bt-anriss {
  color: var(--anthracite);
  font-size: 1.125rem;
  line-height: 1.45;
}

.bt-lead {
  margin-top: 20px;
  max-width: 70ch;
  color: var(--anthracite);
  font-size: 1.125rem;
  line-height: 1.6;
}

.bt-kernpunkte {
  display: grid;
  gap: 12px;
  margin-top: 24px;
  list-style: none;
}

.bt-kernpunkte li {
  padding-left: 16px;
  border-left: 3px solid var(--blue);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.4;
}

.bt-fragen-inhalt { padding-top: clamp(28px, 3.5vw, 48px); }

.bt-zusatz { margin-top: clamp(28px, 3.5vw, 48px); }

.bt-zwischentitel {
  margin: 28px 0 8px;
  color: var(--anthracite);
  font-size: 1.5rem;
  font-weight: 400;
  line-height: 1.2;
}

.bt-zwischentitel:first-child { margin-top: 0; }

.bt-zusatz p {
  max-width: 70ch;
  color: var(--text-muted);
  line-height: 1.7;
}

.bt-main > .offer-section { margin-top: clamp(40px, 5vw, 72px); }

.bt-sprung-inhalt {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: clamp(28px, 3.5vw, 48px) 0;
}

.bt-sprungknopf {
  display: inline-flex;
  align-items: center;
  min-height: 50px;
  padding: 12px 24px;
  border: 2px solid var(--blue);
  border-radius: 999px;
  color: var(--blue);
  font-size: .95rem;
  font-weight: 600;
  line-height: 1.25;
  text-decoration: none;
  transition: background .18s ease, color .18s ease;
}

.bt-sprungknopf:hover,
.bt-sprungknopf:focus-visible {
  background: var(--blue);
  color: #fff;
  outline: none;
}
