/* ══════════════════════════════════════════════════════════════════════════
   Younes — Grundgerüst

   Stand 11.09.2026: Schrift (Blauer Nue) und die drei Markenfarben sind
   eingesetzt. Inhalte und Seitenstruktur sind weiter Platzhalter.

   Farbwerte stehen NICHT hier, sondern in tokens.css — dort auch die
   gerechneten Kontraste. Eine Regel gilt durchgehend:
   **Hellblau #308ecb trägt keinen Fließtext** (3,59:1 gegen Weiß). Es ist die
   Farbe für Flächen, Kanten und Symbole; wo Hellblau Text trägt oder Text ist,
   steht --hellblau-text (#2877aa, 4,87:1).

   Aufbau der Datei:
     1. Grundlagen und Rücksetzer
     2. Hilfsklassen (Inhaltsbreite, nur für Screenreader, Einblenden)
     3. Kopfzeile und Navigation
     4. Abschnitte, Karten, Knöpfe
     5. Platzhalter-Kennzeichnung
     6. Fußzeile
     7. Ohne JavaScript
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Grundlagen ───────────────────────────────────────────────────────── */

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

html {
  /* Anker springen nicht unter die feste Kopfzeile. */
  /* Die Leiste schwebt seit dem 14.09.2026 mit Abstand — Ankersprünge
     müssen diese Luft mitrechnen, sonst landet die Überschrift darunter. */
  scroll-padding-top: calc(var(--kopf-hoehe) + var(--kopf-luft) * 2 + var(--a-4));
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--grund);
  color: var(--ink);
  font-family: var(--schrift-text);
  font-size: var(--t-m);
  line-height: var(--zeile);
  /* Kein overflow-x:hidden — das bricht position:sticky in manchen Browsern.
     Breite Elemente bekommen stattdessen selbst ein overflow-x:auto. */
}

h1, h2, h3, h4 {
  font-family: var(--schrift-titel);
  /* Headline = Blauer Nue Bold (Kundenvorgabe). Echtes Gewicht 700, kein vom
     Browser künstlich gefettetes 400 — der Schnitt liegt als eigene Datei vor. */
  font-weight: var(--gewicht-titel);
  line-height: var(--zeile-eng);
  margin: 0 0 var(--a-4);
  text-wrap: balance;          /* keine Schusterjungen in Überschriften */
  /* Deutsche Komposita sprengen schmale Spalten: „Auffindbarkeit" lief in einer
     234px-Karte gemessen um 24px über den Rand. hyphens wirkt nur, weil im
     <html> lang="de" steht; break-word fängt den Rest ab. */
  overflow-wrap: break-word;
  hyphens: auto;
}
h1 { font-size: var(--t-3xl); }
h2 { font-size: var(--t-2xl); }
h3 { font-size: var(--t-xl); }
h4 { font-size: var(--t-l); }

p, ul, ol { margin: 0 0 var(--a-4); }
p { max-width: var(--breite-text); text-wrap: pretty; }

a { color: var(--akzent); text-underline-offset: 0.18em; }
a:hover { color: var(--akzent-tief); }

img, svg, video { max-width: 100%; height: auto; display: block; }

/* Ein sichtbarer Fokus ist Pflicht, nicht Geschmack (WCAG 2.4.7). */
:focus-visible {
  outline: 3px solid var(--akzent);
  outline-offset: 2px;
  border-radius: var(--rundung-s);
}

/* ── 2. Hilfsklassen ─────────────────────────────────────────────────────── */

.inhalt {
  width: min(100% - 2 * var(--a-5), var(--breite));
  margin-inline: auto;
}

/* Für Screenreader da, für Augen nicht. NICHT display:none — das nimmt den
   Text auch aus dem Zugänglichkeitsbaum. */
.nur-sr {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Sprungmarke: erst sichtbar, wenn sie den Fokus hat. */
.sprung {
  position: absolute;
  left: var(--a-4); top: var(--a-4);
  z-index: 100;
  transform: translateY(-200%);
  background: var(--ink);
  color: var(--grund);
  padding: var(--a-3) var(--a-4);
  border-radius: var(--rundung-s);
  text-decoration: none;
}
.sprung:focus { transform: translateY(0); color: var(--grund); }

/* ── Einblenden beim Scrollen ─────────────────────────────────────────────
   Drei Bewegungen zugleich, damit es nach Auftauchen aussieht und nicht nach
   Aufblenden: aus der Tiefe heran (translateY + eine Spur kleiner) und dabei
   scharf werden (blur). Der Weichzeichner ist das, was den Unterschied zum
   üblichen Fade ausmacht — er darf aber klein bleiben, sonst flimmert Text.

   --verzug setzt main.js je Element: Was gemeinsam in den Blick kommt,
   erscheint gestaffelt. Ohne Skript gibt es weder .js-reveal noch --verzug,
   dann steht alles sofort da (Ausweichwert 0ms).

   will-change nur im Wartezustand: Dauerhaft gesetzt hielte es für JEDES
   Element der Seite eine eigene Ebene vor — das kostet auf schwachen
   Geräten mehr, als die Animation wert ist. Mit .sichtbar fällt es weg. */
.js-reveal .reveal {
  opacity: 0;
  transform: translateY(26px) scale(.985);
  filter: blur(6px);
  transition: opacity .68s var(--kurve) var(--verzug, 0ms),
              transform .68s var(--kurve) var(--verzug, 0ms),
              filter .68s var(--kurve) var(--verzug, 0ms);
}
.js-reveal .reveal:not(.sichtbar) { will-change: opacity, transform, filter; }
.js-reveal .reveal.sichtbar {
  opacity: 1;
  transform: none;
  filter: none;
  will-change: auto;
}

/* ── 3. Kopfzeile ────────────────────────────────────────────────────────── */

.kopf {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--grund) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: background-color var(--dauer) var(--kurve), border-color var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve), color var(--dauer) var(--kurve);
}
/* Die durchgehende Unterkante des Gerüsts entfällt: Die Leiste schwebt
   seit dem 14.09.2026 und hat ihre eigene Kante rundherum (Abschnitt 9). */
.kopf.gescrollt { border-bottom-color: transparent; }

/* ── Glas-Kopfzeile über dem Titelbild ───────────────────────────────────
   Nur auf Seiten MIT Hero (Klasse am <body>). Impressum und Datenschutz haben
   keinen dunklen Grund — dort wäre helle Schrift unsichtbar.

   Der Glas-Zustand ist bewusst nicht durchsichtig, sondern getöntes Blau mit
   Unschärfe: eine rein durchsichtige Leiste stünde je nach Scrollposition auf
   hellem Fensterlicht, und die Schrift wäre dort nicht mehr zu lesen.
   Gemessen auf dem gerenderten Bild, nicht geschätzt — die Werte stehen im
   README. Beim Scrollen wird daraus Weiß mit dunkler Schrift. */
.hat-hero .kopf {
  background: rgba(10, 68, 114, 0.38);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom-color: rgba(255, 255, 255, 0.18);
}
/* Über dem Titelbild ist die Leiste dunkelblau — dort das weiße Logo. */
.hat-hero .kopf .marke__bild--weiss { opacity: 1; }
.hat-hero .kopf .marke__bild--blau  { opacity: 0; }
.hat-hero .kopf .nav__liste a    { color: #ffffff; }
.hat-hero .kopf .nav__liste a:hover,
.hat-hero .kopf .nav__liste a[aria-current="page"] { color: #ffffff; border-bottom-color: #ffffff; }
.hat-hero .kopf .nav__schalter   { color: #ffffff; border-color: rgba(255, 255, 255, 0.55); }
.hat-hero .kopf :focus-visible   { outline-color: #ffffff; }

/* Gescrollt: weiß, wieder dunkle Schrift. Die Regeln spiegeln die Glas-Regeln
   eins zu eins — sonst bliebe eine davon hängen (Spezifität ist gleich, die
   spätere Regel gewinnt). */
.hat-hero .kopf.gescrollt {
  background: rgba(255, 255, 255, 0.92);
  border-bottom-color: var(--linie);
}
/* Gescrollt wird die Leiste weiß — dann zurück auf das blaue Logo. */
.hat-hero .kopf.gescrollt .marke__bild--weiss { opacity: 0; }
.hat-hero .kopf.gescrollt .marke__bild--blau  { opacity: 1; }
.hat-hero .kopf.gescrollt .nav__liste a { color: var(--ink-ruhig); }
.hat-hero .kopf.gescrollt .nav__liste a:hover,
.hat-hero .kopf.gescrollt .nav__liste a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--akzent); }
.hat-hero .kopf.gescrollt .nav__schalter { color: var(--ink); border-color: var(--ink-leise); }
.hat-hero .kopf.gescrollt :focus-visible { outline-color: var(--akzent); }

/* Browser ohne backdrop-filter (ältere Firefox-Stände) bekommen kein Glas,
   sondern eine deckendere Fläche — sonst stünde die Schrift auf dem blanken Bild. */
@supports not (backdrop-filter: blur(1px)) {
  .hat-hero .kopf { background: rgba(10, 68, 114, 0.82); }
  .hat-hero .kopf.gescrollt { background: #ffffff; }
}

.kopf__zeile {
  display: flex; align-items: center; gap: var(--a-5);
  min-height: var(--kopf-hoehe);
}

/* ── Marke: die Bildmarke, in zwei Fassungen übereinander ─────────────────
   Beide Bilder liegen in derselben Rasterzelle, getauscht wird über die
   Deckkraft. Kein `display: none` — daraus ließe sich nicht überblenden,
   und die zweite Datei würde erst beim Umschalten geladen, also sichtbar
   zu spät. So sind beim ersten Anstrich beide da.
   Welche Fassung zu sehen ist, entscheidet die Farbe der Leiste weiter
   unten (Abschnitt „Kopfzeile über dem Titelbild"). */
.marke {
  display: grid;
  margin-right: auto;
  line-height: 0;                    /* kein Zeilenabstand unter dem Bild */
  text-decoration: none;
  border-radius: var(--rundung-s);
}
.marke__bild {
  grid-area: 1 / 1;                  /* beide in dieselbe Zelle */
  height: clamp(1.75rem, 1.5rem + 1.1vw, 2.375rem);
  width: auto;
  transition: opacity var(--dauer) var(--kurve);
}
/* Grundfall (alle Seiten ohne Titelbild): helle Leiste, also blaues Logo. */
.marke__bild--weiss { opacity: 0; }
.marke__bild--blau  { opacity: 1; }

.nav__liste {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: center; gap: var(--a-5);
}
.nav__liste a {
  color: var(--ink-ruhig);
  text-decoration: none;
  font-size: var(--t-s);
  font-weight: var(--gewicht-ui);
  padding: var(--a-2) 0;
  border-bottom: 2px solid transparent;
}
.nav__liste a:hover,
.nav__liste a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--akzent); }

.nav__schalter {
  display: none;
  background: none; border: 1px solid var(--ink-leise);
  border-radius: var(--rundung-s);
  padding: var(--a-2) var(--a-3);
  font: inherit; font-size: var(--t-s);
  color: var(--ink); cursor: pointer;
}

@media (max-width: 800px) {
  /* ════════════════════════════════════════════════════════════════════════
     Mobilmenü (neu gebaut 15.09.2026)
     ────────────────────────────────────────────────────────────────────────
     Drei Striche statt „Menü", ein Klappfeld, das zur Leiste gehört, und
     Farben, die dem Zustand der Leiste folgen: über dem Titelbild blau mit
     weißer Schrift, gescrollt und auf Unterseiten weiß mit dunkler Schrift.

     Der alte Block hatte ein festes WEISSES Klappfeld. Über dem Titelbild
     setzt eine Regel weiter oben die Menülinks auf Weiß — das ergab weiße
     Schrift auf weißem Grund, das Menü war nach dem Öffnen nicht zu sehen.
     ════════════════════════════════════════════════════════════════════════ */

  /* Das Klappfeld richtet sich an der schwebenden Leiste aus, nicht an der
     ganzen Kopfzeile — so hat es dieselbe Breite und sitzt direkt darunter. */
  .kopf__zeile { position: relative; }

  /* ── Der Schalter: drei Striche ──────────────────────────────────────── */
  .nav__schalter {
    display: grid;
    place-items: center;
    width: 2.75rem; height: 2.75rem;          /* 44px Fingerbreite */
    margin-left: auto;
    padding: 0;
    border: 0;
    border-radius: var(--rundung-s);
    background: transparent;
    -webkit-tap-highlight-color: transparent;
  }
  .nav__schalter:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

  /* Die Striche sind unterschiedlich lang (100 / 72 / 46 Prozent) — ruhiger
     als drei gleiche Balken. Beim Überfahren gleichen sie sich an: ein
     kleiner Hinweis, dass hier etwas passiert. */
  .burger {
    position: relative;
    display: block;
    width: 1.375rem; height: 0.875rem;       /* 22 × 14 px */
  }
  .burger span {
    position: absolute; right: 0;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    /* SCHLIESSEN: erst zurückdrehen, dann auseinanderrücken. */
    transition:
      transform 0.22s cubic-bezier(.4, 0, .2, 1) 0s,
      top 0.2s cubic-bezier(.4, 0, .2, 1) 0.18s,
      width 0.3s var(--kurve),
      opacity 0.2s var(--kurve) 0.1s;
  }
  .burger span:nth-child(1) { top: 0;    width: 100%; }
  .burger span:nth-child(2) { top: 6px;  width: 72%; }
  .burger span:nth-child(3) { top: 12px; width: 46%; }
  .nav__schalter:hover .burger span { width: 100%; }

  /* ÖFFNEN: erst zur Mitte zusammenrücken, dann zum X drehen — mit einem
     leichten Überschwingen am Ende. Der mittlere Strich zieht nach rechts
     heraus. Zwei Stufen statt eines direkten Übergangs: So sieht man die
     Striche sich kreuzen, statt dass sie ineinander verschwimmen. */
  .nav__schalter[aria-expanded="true"] .burger span {
    transition:
      top 0.2s cubic-bezier(.4, 0, .2, 1) 0s,
      transform 0.34s cubic-bezier(.34, 1.56, .64, 1) 0.18s,
      width 0.2s var(--kurve),
      opacity 0.15s var(--kurve);
  }
  .nav__schalter[aria-expanded="true"] .burger span:nth-child(1) { top: 6px; width: 100%; transform: rotate(45deg); }
  .nav__schalter[aria-expanded="true"] .burger span:nth-child(2) { opacity: 0; transform: translateX(0.75rem); }
  .nav__schalter[aria-expanded="true"] .burger span:nth-child(3) { top: 6px; width: 100%; transform: rotate(-45deg); }

  /* ── Das Klappfeld ───────────────────────────────────────────────────── */
  /* visibility statt display:none: nur so lässt sich das Aufklappen
     überblenden. visibility:hidden nimmt die Einträge trotzdem aus der
     Tab-Reihenfolge und aus dem Barrierebaum — zugeklappt ist nichts
     erreichbar, was man nicht sieht. */
  .nav {
    position: absolute;
    left: 0; right: 0;
    top: calc(100% + 0.5rem);
    border-radius: var(--kopf-rundung);
    border: 1px solid var(--linie);
    /* DECKEND, nicht Glas: Mit 97 Prozent Deckkraft schien der Seitentext
       sichtbar durch die Menülinks hindurch — zwei Textebenen übereinander
       sind schwerer zu lesen als jede für sich. */
    background: var(--grund);
    box-shadow: var(--schatten-2);
    overflow: hidden;
    visibility: hidden;
    opacity: 0;
    transform: translateY(-0.6rem) scale(0.98);
    transform-origin: top center;
    transition:
      opacity 0.22s var(--kurve),
      transform 0.28s var(--kurve),
      visibility 0s linear 0.28s;
  }
  .kopf.offen .nav {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition:
      opacity 0.26s var(--kurve),
      transform 0.34s cubic-bezier(.34, 1.3, .64, 1),
      visibility 0s;
  }

  .nav__liste {
    flex-direction: column; align-items: stretch;
    gap: 0; padding: var(--a-2) var(--a-5);
  }
  /* Die Einträge laufen beim Öffnen nacheinander ein. */
  .nav__liste li {
    opacity: 0;
    transform: translateY(-0.35rem);
    transition: opacity 0.2s var(--kurve), transform 0.25s var(--kurve);
  }
  .kopf.offen .nav__liste li { opacity: 1; transform: none; }
  .kopf.offen .nav__liste li:nth-child(1) { transition-delay: 0.06s; }
  .kopf.offen .nav__liste li:nth-child(2) { transition-delay: 0.10s; }
  .kopf.offen .nav__liste li:nth-child(3) { transition-delay: 0.14s; }
  .kopf.offen .nav__liste li:nth-child(4) { transition-delay: 0.18s; }
  .kopf.offen .nav__liste li:nth-child(5) { transition-delay: 0.22s; }

  /* display:block ist hier nicht kosmetisch: an einem inline-<a> erzeugt
     padding keinen senkrechten Platz, und die Trennlinie läuft quer durch die
     nächste Zeile statt unter den Eintrag. */
  .nav__liste a,
  .hat-hero .kopf.gescrollt .nav__liste a,
  .hat-hero .kopf.gescrollt .nav__liste a[aria-current="page"],
  .nav__liste a[aria-current="page"] {
    display: block;
    padding: var(--a-3) 0;
    font-size: var(--t-m);
    border-bottom: 1px solid var(--linie);
  }
  .nav__liste li:last-child a { border-bottom-width: 0; }
  /* Die aktuelle Seite: fett statt unterstrichen — die Unterstreichung ist im
     Klappfeld schon die Trennlinie. */
  .nav__liste a[aria-current="page"] { font-weight: 700; }

  /* ── Zustand BLAU: über dem Titelbild, nicht gescrollt ───────────────── */
  .hat-hero .kopf:not(.gescrollt) .nav {
    background: var(--dunkelblau);
    border-color: rgba(255, 255, 255, 0.22);
  }
  .hat-hero .kopf:not(.gescrollt) .nav__liste a,
  .hat-hero .kopf:not(.gescrollt) .nav__liste a[aria-current="page"] {
    color: #ffffff;
    border-bottom-color: rgba(255, 255, 255, 0.16);
  }
  /* Offen wird auch die Leiste selbst deckend blau: Leiste und Klappfeld
     sollen eine Fläche sein und nicht Glas über einem Kasten. */
  .hat-hero .kopf.offen:not(.gescrollt) .kopf__zeile { background: var(--dunkelblau); }

  /* ── Zustand WEISS: gescrollt oder Unterseite ────────────────────────── */
  /* Die gescrollte Leiste steht sonst auf 92 Prozent Weiß (Regel mit
     .hat-hero .kopf.gescrollt, Spezifität 0-4-0) — über dem blauen Band
     wirkte sie offen bläulich-grau neben dem reinweißen Klappfeld. */
  .kopf.offen .kopf__zeile,
  .hat-hero .kopf.offen.gescrollt .kopf__zeile { background: var(--grund); }
  .hat-hero .kopf.offen:not(.gescrollt) .kopf__zeile { background: var(--dunkelblau); }

  /* ── Ohne JavaScript ─────────────────────────────────────────────────── */
  /* Es gibt keinen Schalter — das Menü steht offen in der Leiste. Die
     Kopfzeile ist ein Flex-Container: ohne Umbruch säße die offene Liste als
     schmale Spalte NEBEN dem Logo. flex-basis:100% schickt sie auf eine
     eigene Zeile über die volle Breite. */
  .kein-js .kopf__zeile { flex-wrap: wrap; }
  .kein-js .nav {
    position: static; flex-basis: 100%;
    visibility: visible; opacity: 1; transform: none;
    background: none; border: 0; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .kein-js .nav__liste { padding-inline: 0; padding-bottom: var(--a-2); }
  .kein-js .nav__liste li { opacity: 1; transform: none; }
  .kein-js .nav__schalter { display: none; }
}

@media (max-width: 800px) and (prefers-reduced-motion: reduce) {
  .burger span, .nav, .nav__liste li,
  .kopf.offen .nav, .kopf.offen .nav__liste li,
  .nav__schalter[aria-expanded="true"] .burger span { transition: none !important; }
}

/* ── 4. Abschnitte, Karten, Knöpfe ───────────────────────────────────────── */

.band { padding-block: var(--band); }
.band--grau   { background: var(--grund-grau); }

/* Dunkles Band. Schrift ist Lightgrau statt reinem Weiß — das hält die Palette
   geschlossen und trägt mit 9,33:1 mehr als genug. Alles, was im hellen Band
   dunkelblau ist, wird hier hellblau: auf Dunkelblau erreicht #308ecb zwar nur
   2,81:1 und scheidet als Textfarbe aus, deshalb übernimmt Lightgrau den Text
   und Hellblau nur die Kanten. */
.band--dunkel {
  background: var(--grund-tief);
  color: var(--auf-dunkel);
}
.band--dunkel h1, .band--dunkel h2,
.band--dunkel h3, .band--dunkel h4 { color: var(--auf-dunkel); }
.band--dunkel .band__kopf p,
.band--dunkel p { color: var(--auf-dunkel-leise); }
/* Verweise im dunklen Band werden unterstrichen — die Farbe allein unterscheidet
   sie hier zu wenig vom Fließtext. Knöpfe sind davon ausgenommen: sie sind schon
   an ihrer Fläche als Bedienelement zu erkennen, und eine unterstrichene
   Knopfbeschriftung sieht nach Fehler aus. */
.band--dunkel a:not(.knopf) { color: var(--auf-dunkel); text-decoration: underline; }
.band--dunkel .karte {
  background: transparent;
  border-color: color-mix(in srgb, var(--hellblau) 55%, transparent);
}
.band--dunkel .karte h3 { color: var(--auf-dunkel); }
.band--dunkel :focus-visible { outline-color: var(--hellblau); }

.band__kopf { max-width: var(--breite-text); margin-bottom: var(--a-6); }
.band__kopf p { color: var(--ink-ruhig); font-size: var(--t-l); margin-bottom: 0; }

/* Akzentbalken unter der Abschnittsüberschrift — hier trägt Hellblau nichts
   als sich selbst, also ist die gelieferte Farbe unverändert richtig. */
.band__kopf h2::after {
  content: "";
  display: block;
  width: 3.5rem; height: 4px;
  margin-top: var(--a-3);
  border-radius: 2px;
  background: var(--hellblau);
}
.band--dunkel .band__kopf h2::after { background: var(--hellblau); }

/* ── Titel-Section mit Bild ───────────────────────────────────────────────
   Aufbau in drei Ebenen: Bild (<img>, wegen srcset und fester Größe), darüber
   der blaue Verlauf, darüber der Inhalt. Die Kopfzeile liegt mit z-index 50
   über allem und wird von .hat-hero (nur auf der Startseite) zu Glas. */

.hero {
  position: relative;
  z-index: 0;
  isolation: isolate;
  /* Unter die klebende Kopfzeile ziehen, damit das Bild bis ganz nach oben
     läuft; das padding gibt dem Inhalt den Platz wieder zurück. */
  margin-top: calc(-1 * var(--kopf-hoehe));
  padding-block: calc(var(--kopf-hoehe) + var(--band) * 0.9) var(--band);
  overflow: hidden;
  color: var(--auf-dunkel);
}

.hero__bild { position: absolute; inset: 0; z-index: -2; display: block; }
.hero__bild img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 62%; }

/* Der blaue Schleier. Zwei Verläufe statt einem: senkrecht für die Lesbarkeit
   oben (Kopfzeile) und unten, waagerecht für die Textspalte links. So bleibt
   die Bildmitte mit Eimer und Mopp sichtbar, statt flächig zugedeckt zu werden. */
.hero::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(100deg,
      rgba(10, 68, 114, 0.86) 0%,
      rgba(10, 68, 114, 0.66) 32%,
      rgba(10, 68, 114, 0.24) 60%,
      rgba(10, 68, 114, 0.12) 100%),
    /* Der zusätzliche neutrale Schleier von oben ist wieder entfernt: Er war
       nur nötig, solange die Navigationsleiste keine eigene Fläche hatte.
       Jetzt trägt das Glas der Leiste ihren Kontrast, und das Titelbild
       bleibt oben unverfälscht. */
    linear-gradient(180deg,
      /* Oben bewusst schwach und WEICH auslaufend. Vorher stand hier 0,68
         mit einem Knick bei 9 Prozent — das ergab einen sichtbaren blauen
         Balken quer über den oberen Bildrand, der abrupt endete und wie ein
         zweiter Kasten hinter der Leiste wirkte. Die Abdunklung wird hier
         nicht mehr gebraucht: Die Navigationsleiste bringt ihre eigene
         Glasfläche mit und trägt ihren Kontrast selbst. */
      rgba(10, 68, 114, 0.24) 0%,
      rgba(10, 68, 114, 0.18) 12%,
      rgba(10, 68, 114, 0.10) 22%,
      rgba(10, 68, 114, 0.04) 34%,
      rgba(10, 68, 114, 0.04) 72%,
      rgba(10, 68, 114, 0.34) 100%);
}

.hero__inhalt {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 30rem);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
/* Unter 940px steht der Text mittig über der GANZEN Breite — der waagerechte
   Verlauf, der für eine linke Textspalte gebaut ist, greift dort nicht mehr.
   Gemessen fiel der kleine Lead dadurch auf 3,89:1. Der Grund dafür steckt im
   Zuschnitt: object-fit:cover schneidet im schmalen Hochformat genau das
   Fensterlicht an — zurückgerechnet liegt das Foto dort bei rgb(239,239,235),
   also praktisch Weiß. Ein mittelstarker Schleier reicht dagegen nicht; erst
   ab etwa 0,76 trägt heller Text. Deshalb ist der Schleier hier deutlich
   kräftiger als am Desktop — auf dem Telefon zählt der Text, nicht das Motiv. */
@media (max-width: 940px) {
  .hero::before {
    background:
      linear-gradient(180deg,
        rgba(10, 68, 114, 0.90) 0%,
        rgba(10, 68, 114, 0.80) 14%,
        rgba(10, 68, 114, 0.78) 60%,
        rgba(10, 68, 114, 0.86) 100%);
  }
  .hero__inhalt { grid-template-columns: minmax(0, 1fr); }
  .hero__text { max-width: 46rem; margin-inline: auto; text-align: center; }
  .hero__text .hero__lead { margin-inline: auto; }
}

.hero h1 { color: #ffffff; margin-bottom: var(--a-5); }
.hero__lead {
  font-size: var(--t-l);
  color: var(--auf-dunkel);
  max-width: 34rem;
}
/* NICHT --auf-dunkel-leise (#bcd0e0): das stimmt auf dem flachen dunkelblauen
   Band (6,36:1), auf dem Foto aber nicht — unter den Buchstaben gemessen nur
   4,16:1. Und nicht knapp über die Schwelle wählen: der ungünstigste Grund
   wandert mit dem Verlauf (gemessen zwischen #336184 und #496a82), #d5e3ee
   fiel dadurch auf 4,38:1 zurück. #edf2f7 hält an der schlechtesten Stelle
   5,08:1 und bleibt als zweite Ebene erkennbar. */
.hero__lead--klein { font-size: var(--t-m); color: #edf2f7; }

/* Offene Stelle im Fließtext sichtbar machen — Hausregel: was fehlt, sieht man
   im Browser, nicht nur im Quelltext. */
mark.offen {
  background: #ffd84d;
  color: var(--text);
  padding: 0 0.25em;
  border-radius: var(--rundung-s);
}

.raster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--a-5);
}

.karte {
  background: var(--grund);
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  padding: var(--a-5);
}
/* Karten sind schmal (bei 1200px Inhaltsbreite rund 234px innen). Eine Stufe
   kleiner als die freie h3-Größe, sonst füllt schon ein einzelnes Wort die Zeile. */
.karte h3 { font-size: var(--t-l); margin-bottom: var(--a-2); }
.karte p:last-child { margin-bottom: 0; }

.knopf {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--a-2);
  padding: var(--a-3) var(--a-5);
  border: 1px solid transparent;
  border-radius: 999px;
  font: inherit; font-size: var(--t-s); font-weight: var(--gewicht-knopf);
  text-decoration: none; cursor: pointer;
  background: var(--akzent); color: var(--auf-akzent);
  transition: background-color var(--dauer) var(--kurve);
}
.knopf:hover { background: var(--akzent-tief); color: var(--auf-akzent); }

/* ── Schimmer, nur beim Überfahren ────────────────────────────────────────
   Auftraggeber, 14.09.2026: Der Knopf unter den Leistungskacheln soll beim
   Überfahren nach außen leuchten — im Ruhezustand nichts. Deshalb ein
   box-shadow, der erst auf :hover entsteht, statt eines gedämpften
   Dauerleuchtens, das beim Hover kräftiger wird.

   Eigene Klasse statt einer Regel auf .knopf: die Seite hat sieben weitere
   Knöpfe (Hero, Funnel, Ortskarten, dunkles Band), und ein Leuchten überall
   wäre weder gewünscht noch auf dunklem Grund sinnvoll.

   Zwei Schattenebenen: ein enger Ring trägt die Kontur, ein weiter, weicher
   das Leuchten. Eine einzelne Ebene wirkt entweder als harte Kante oder als
   Nebel. Der Ton ist das Marken-Hellblau #308ecb — Dunkelblau sähe auf dem
   weißen Band nach Schlagschatten aus, nicht nach Licht.

   :focus-visible bekommt denselben Schimmer: wer mit der Tastatur bedient,
   soll dieselbe Rückmeldung sehen wie mit der Maus. Der Fokusring aus der
   Grundregel bleibt zusätzlich bestehen — der Schimmer ersetzt ihn nicht.

   Bei prefers-reduced-motion greift die Sammelregel weiter unten und setzt
   die Übergangsdauer auf ~0; der Schimmer erscheint dann ohne Überblendung.
   Er ist selbst keine Bewegung und bleibt deshalb erhalten. */
.knopf--schimmer {
  transition: background-color var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve);
}
.knopf--schimmer:hover,
.knopf--schimmer:focus-visible {
  box-shadow:
    0 0 0 5px rgba(48, 142, 203, 0.20),
    0 8px 30px rgba(48, 142, 203, 0.48);
}
/* Zweitrangig: Rand in --ink-leise (5,10:1 auf Weiß, 4,72:1 auf Lightgrau),
   nicht in --linie — ein Bedienelement braucht 3:1 gegen den Grund
   (WCAG 1.4.11). Hellblau scheidet hier aus: 3,59:1 reicht zwar für die
   Kante, aber die Beschriftung daneben wäre zu schwach. */
.knopf--leise {
  background: transparent; color: var(--ink);
  border-color: var(--ink-leise);
}
.knopf--leise:hover { background: var(--grund-grau); color: var(--ink); }

/* Knopf in Hellblau. Er nimmt --hellblau-text (#2877aa), NICHT das gelieferte
   #308ecb: darauf erreicht weder Weiß (3,59:1) noch die Textfarbe (3,75:1) die
   nötigen 4,5:1, und eine Knopfbeschriftung ist mit 15px fett keine „große
   Schrift". Mit #2877aa sind es 4,87:1 bei identischem Farbton.
   Der Hover geht auf Dunkelblau (10,08:1) und nicht auf das volle #308ecb —
   ein Hover-Zustand darf nicht schlechter lesbar sein als der Ruhezustand. */
.knopf--hell {
  background: var(--hellblau-text);
  color: var(--auf-akzent);
}
.knopf--hell:hover { background: var(--dunkelblau); color: var(--auf-akzent); }

/* Knopf innerhalb eines dunklen Bandes: Lightgrau-Fläche, dunkelblaue Schrift
   (9,33:1). Ein dunkelblauer Knopf auf dunkelblauem Grund wäre unsichtbar. */
.band--dunkel .knopf {
  background: var(--lightgrau); color: var(--dunkelblau);
}
.band--dunkel .knopf:hover { background: #ffffff; color: var(--dunkelblau-tief); }
.band--dunkel .knopf--leise {
  background: transparent; color: var(--auf-dunkel);
  border-color: var(--hellblau);
}
.band--dunkel .knopf--leise:hover {
  background: color-mix(in srgb, var(--hellblau) 22%, transparent);
  color: var(--auf-dunkel);
}

.knopfreihe { display: flex; flex-wrap: wrap; gap: var(--a-3); margin-top: var(--a-5); }

/* ── Logostreifen unter dem Titelbild ──────────────────────────────────────
   Schmales dunkelblaues Band, Marken in Weiß, endlos laufend, an beiden
   Rändern ausgeblendet.

   ── Warum die Maske auf dem FENSTER liegt und nicht auf dem Abschnitt ──
   Eine Maske blendet alles aus, was das Element malt — also auch den blauen
   Grund. Läge sie auf .logoband, schiene an den Rändern die Seitenfarbe
   durch und aus dem Band würde ein Streifen mit ausgefransten Enden.

   ── Warum -50 % und zwei Gruppen ──
   Die Spur enthält dieselbe Gruppe zweimal. Wandert sie um genau die Hälfte
   ihrer eigenen Breite, steht Gruppe zwei exakt dort, wo Gruppe eins begann —
   der Rücksprung ist unsichtbar. Mit einer Gruppe und -100 % liefe am Ende
   eine Lücke durchs Bild.

   ── Dauer statt Geschwindigkeit ──
   `animation-duration` ist fest, nicht aus der Breite gerechnet. Bei sechs
   Marken ergibt das ein ruhiges Tempo; kommen deutlich mehr dazu, wird es
   schneller und die Zahl gehört angepasst. Eine Rechnung in CSS gibt es dafür
   nicht, ohne die Breite per JavaScript zu messen — und dafür ist das hier
   zu unwichtig.
   ────────────────────────────────────────────────────────────────────────── */
.logoband {
  position: relative;
  background: var(--grund-tief);
  padding-block: var(--a-4);
  overflow: hidden;
}

/* Fenster und Anhalten-Knopf bilden eine Zeile. Der Knopf zentriert sich damit
   über die Logos und nicht über den ganzen Abschnitt — mit dem
   Platzhalterhinweis darunter stand er am Telefon sonst mitten im Text. */
.logoband__zeile { position: relative; }

.logoband__fenster {
  /* Ausblenden nach beiden Seiten. Zwei Schreibweisen, weil Safari die
     Eigenschaft bis heute nur mit Präfix kennt. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
  overflow: hidden;
}

.logoband__spur {
  display: flex;
  width: max-content;
  animation: logolauf 42s linear infinite;
}
@keyframes logolauf {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Kein Anhalten beim Überfahren und kein Knopf (Auftraggeber, 15.09.2026).
   Das Band läuft durch.

   Was damit entfällt: WCAG 2.2.2 verlangt für Bewegung, die von selbst
   startet und länger als fünf Sekunden läuft, eine Möglichkeit zum Anhalten.
   Die gibt es jetzt nur noch über die Systemeinstellung „Bewegung reduzieren"
   (Regel am Dateiende) — das deckt Nutzer ab, die sie gesetzt haben, aber
   nicht das Kriterium. Bewusste Entscheidung des Auftraggebers.
   Zum Zurückholen: Knopf in teile.logostreifen(), Regeln hier, Schalter in
   main.js — alles im Backup vom 15.09.2026. */

.logoband__gruppe {
  display: flex;
  align-items: center;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  margin: 0;
  padding: 0 clamp(1.25rem, 2.5vw, 2.25rem);
  list-style: none;
}

.logoband__marke {
  display: flex;
  align-items: center;
  gap: var(--a-3);
  flex: none;
  color: var(--auf-dunkel);
}
/* Echte Marken seit 17.09.2026: Bilddateien statt gezeichneter Platzhalter.
   Feste Hoehe, Breite nach Verhaeltnis — nur so stehen Logos mit
   unterschiedlichem Zuschnitt optisch gleich gross nebeneinander.
   Die Farben bleiben, wie sie sind: Fremde Wortmarken umzufaerben verstoesst
   gegen die Gestaltungsvorgaben der Anbieter. */
.logoband__bild {
  height: clamp(1.5rem, 1.2rem + 1vw, 2.125rem);
  width: auto;
  flex: none;
  display: block;
}

/* Marken, die fuer HELLE Gruende gezeichnet sind, bekommen eine eigene
   Flaeche. Das HWK-Zeichen ist dunkelblau (#093270) und erreicht auf dem
   dunkelblauen Band gemessen 1,85:1 — es verschwindet dort schlicht.
   Umfaerben ist keine Loesung: Fremde Wortmarken duerfen nicht veraendert
   werden. Welche Marke welchen Grund braucht, steht in fakten.LOGOS. */
.logoband__marke--hell {
  background: #ffffff;
  border-radius: var(--rundung-s);
  padding: 0.45rem 0.8rem;
}


.logoband__hinweis {
  margin: var(--a-3) auto 0;
  padding-inline: var(--a-5);
  max-width: var(--breite);
  text-align: center;
  font-size: var(--t-xs);
  color: var(--auf-dunkel-leise);
}

/* Bewegung aus: Das Band steht still und zeigt einfach die erste Gruppe.
   Nicht nur die Animation anhalten, sondern gar nicht erst starten — ein
   pausierter Zustand bleibt sonst an einer beliebigen Stelle stehen. */
@media (prefers-reduced-motion: reduce) {
  .logoband__spur { animation: none; }
}

/* ── Anfrage-Funnel ─────────────────────────────────────────────────────────
   Weiße Karte über dem Titelbild. Ohne JavaScript stehen alle drei Schritte
   untereinander und das Formular ist vollständig ausfüllbar; erst main.js
   setzt .js-funnel und blendet die Schritte einzeln ein. Deshalb steht die
   Schritt-Logik unter .js-funnel und NICHT als Grundzustand — sonst sähe man
   ohne Skript nur den ersten Schritt und käme nie weiter. */

.funnel {
  background: rgba(255, 255, 255, 0.96);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: calc(var(--rundung) * 1.6);
  box-shadow: 0 18px 50px rgba(10, 68, 114, 0.28);
  padding: clamp(1.25rem, 2.5vw, 2rem);
  color: var(--ink);
}
.funnel__form { display: block; }

.funnel__kopf { margin-bottom: var(--a-5); }
.funnel__zaehler {
  font-size: var(--t-xs); font-weight: var(--gewicht-ui);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-leise); margin: 0 0 var(--a-1);
}
.funnel__titel { font-size: var(--t-xl); margin: 0 0 var(--a-3); color: var(--ink); }
.funnel__balken {
  height: 6px; border-radius: 3px;
  background: var(--lightgrau);
  overflow: hidden;
}
.funnel__balken-fuellung {
  display: block; height: 100%; width: 33.33%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--dunkelblau), var(--hellblau));
  transition: width .32s var(--kurve);
}

.funnel__schritt { border: 0; margin: 0; padding: 0; }
.funnel__schritt + .funnel__schritt { margin-top: var(--a-6); }
.funnel__frage {
  font-family: var(--schrift-titel); font-weight: var(--gewicht-titel);
  font-size: var(--t-l); color: var(--ink);
  padding: 0; margin-bottom: var(--a-3);
}
.funnel__hinweis { font-size: var(--t-s); color: var(--ink-leise); margin: -0.35rem 0 var(--a-3); }

/* ── Auswahlkacheln ──
   Das echte Bedienelement ist das <input>; es liegt unsichtbar unter der
   Kachel, statt display:none zu sein — so bleibt es fokussierbar und wird von
   Screenreadern angesagt. Der Fokusring wandert über :focus-visible auf die
   sichtbare Kachel. */
.funnel__wahl { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(9.5rem, 100%), 1fr)); gap: var(--a-2); }
.funnel__wahl--eng { grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr)); }

.wahl { position: relative; display: block; }
.wahl input {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
  appearance: none; -webkit-appearance: none;
}
.wahl__kachel {
  display: flex; flex-direction: column; gap: 0.15rem;
  height: 100%;
  padding: var(--a-3) var(--a-4);
  border: 1.5px solid var(--linie);
  border-radius: var(--rundung);
  background: #ffffff;
  transition: border-color var(--dauer) var(--kurve), background-color var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve);
}
.wahl__titel { font-weight: var(--gewicht-ui); color: var(--ink); font-size: var(--t-s); }
.wahl__text  { font-size: var(--t-xs); color: var(--ink-leise); line-height: 1.35; }

.wahl input:hover + .wahl__kachel { border-color: var(--hellblau); }
.wahl input:checked + .wahl__kachel {
  border-color: var(--dunkelblau);
  background: rgba(48, 142, 203, 0.10);
  box-shadow: inset 0 0 0 1px var(--dunkelblau);
}
.wahl input:focus-visible + .wahl__kachel {
  outline: 3px solid var(--akzent); outline-offset: 2px;
}

/* ── Kontaktfelder ── */
.funnel__feld { margin-bottom: var(--a-4); }
.funnel__feld > label { display: block; font-size: var(--t-s); font-weight: var(--gewicht-ui); margin-bottom: var(--a-1); }
.funnel__optional { font-weight: 400; color: var(--ink-leise); }
.funnel__feld input[type="text"],
.funnel__feld input[type="email"],
.funnel__feld input[type="tel"],
.funnel__feld textarea {
  font: inherit; font-size: var(--t-s);
  width: 100%;
  padding: 0.6rem 0.75rem;
  color: var(--ink);
  background: #ffffff;
  border: 1.5px solid var(--linie);
  border-radius: var(--rundung-s);
}
.funnel__feld textarea { resize: vertical; min-height: 4.5rem; }
.funnel__feld input:focus-visible,
.funnel__feld textarea:focus-visible { border-color: var(--dunkelblau); }
.funnel__feld--check { display: grid; grid-template-columns: auto 1fr; gap: var(--a-2); align-items: start; }
.funnel__feld--check input { width: 1.125rem; height: 1.125rem; accent-color: var(--dunkelblau); margin: 0.15rem 0 0; }
.funnel__feld--check label { font-size: var(--t-s); font-weight: 400; margin: 0; }
.funnel__feld--check .funnel__fehler { grid-column: 1 / -1; }

.funnel__fehler { color: #b3261e; font-size: var(--t-xs); margin: var(--a-1) 0 0; }
.funnel__fehler:empty { display: none; }
[aria-invalid="true"] { border-color: #b3261e !important; }

/* ── Bedienleiste ── */
.funnel__leiste { display: flex; gap: var(--a-3); margin-top: var(--a-5); }
.funnel__leiste .knopf { flex: 1; }
/* .knopf setzt display:inline-flex und schlägt damit die Browserregel
   [hidden]{display:none} — die Klasse ist spezifischer als das Attribut.
   Ohne diese Zeile stehen „Weiter" und „Absenden" gleichzeitig da. */
.funnel__leiste .knopf[hidden] { display: none; }
.knopf[disabled] { opacity: .45; cursor: default; pointer-events: none; }
/* Ohne JavaScript gibt es keine Schritte — dann führt nur der Absendeknopf. */
.funnel__zurueck, .funnel__weiter { display: none; }
.js-funnel .funnel__zurueck, .js-funnel .funnel__weiter { display: inline-flex; }

/* ── Schrittlogik: nur mit JavaScript ── */
.js-funnel .funnel__schritt { display: none; }
.js-funnel .funnel__schritt.ist-aktiv { display: block; }
.js-funnel .funnel__schritt + .funnel__schritt { margin-top: 0; }

/* ── Abschluss ── */
.funnel__ende h2 { font-size: var(--t-xl); margin-bottom: var(--a-3); }
.funnel__ende p { font-size: var(--t-s); }
.funnel__zusammenfassung {
  margin: var(--a-4) 0; padding: var(--a-4);
  background: var(--lightgrau); border-radius: var(--rundung);
  font-size: var(--t-s);
}
.funnel__zusammenfassung dt { font-weight: var(--gewicht-ui); color: var(--ink-leise); font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.06em; }
.funnel__zusammenfassung dd { margin: 0 0 var(--a-3); color: var(--ink); overflow-wrap: break-word; }
.funnel__zusammenfassung dd:last-of-type { margin-bottom: 0; }

/* ── Farbproben ─────────────────────────────────────────────────────────────
   Die Flächenfarben stehen bewusst als style-Attribut im HTML und nicht hier:
   eine Farbprobe SOLL ihren Wert zeigen, und zwei Stellen für denselben Wert
   laufen erfahrungsgemäß auseinander. */
.proben {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: var(--a-4);
}
.probe { display: flex; flex-direction: column; }

/* Auf der Farbfläche steht NUR der Name — und der ist fett und 21px, zählt also
   als große Schrift (3:1 genügt). Hex-Wert und Erläuterung sitzen darunter auf
   dem Bandhintergrund. Sonst stünde 13px-Text auf Hellblau, und das wären
   3,75:1 — genau der Fall, den die Probe daneben als unzulässig beschreibt. */
.probe__feld {
  border: 1px solid; border-radius: var(--rundung) var(--rundung) 0 0;
  padding: var(--a-4);
  min-height: 5.5rem;
  display: flex; align-items: flex-end;
  font-family: var(--schrift-titel);
  font-weight: var(--gewicht-titel);
  font-size: var(--t-l);
}
.probe__text {
  border: 1px solid var(--linie); border-top: none;
  border-radius: 0 0 var(--rundung) var(--rundung);
  padding: var(--a-3) var(--a-4) var(--a-4);
  display: flex; flex-direction: column; gap: var(--a-1);
  flex: 1;
}
.band--dunkel .probe__text { border-color: color-mix(in srgb, var(--hellblau) 55%, transparent); }
.probe__text code { font-size: var(--t-s); }
.probe__text span { font-size: var(--t-xs); line-height: 1.45; }

/* ── 5. Platzhalter sichtbar machen ──────────────────────────────────────────
   Hausregel: Was noch offen ist, muss man im Browser sehen — nicht nur im
   Quelltext. Diese Klasse verschwindet, sobald echte Inhalte da sind. */

.platzhalter {
  border: 1px dashed var(--rand);
  border-radius: var(--rundung);
  background:
    repeating-linear-gradient(135deg,
      transparent 0 10px,
      color-mix(in srgb, var(--rand) 12%, transparent) 10px 20px);
  padding: var(--a-5);
  color: var(--ink-ruhig);
}
.platzhalter > :last-child { margin-bottom: 0; }

.marke-platzhalter {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  background: #ffd84d;              /* Warnton, 9,71:1 gegen --ink (nachgerechnet
                                       14.09.2026; im Gerüst stand geschätzt 14,2) */
  padding: 0.15em 0.5em;
  border-radius: var(--rundung-s);
  margin-bottom: var(--a-3);
}

/* Bildkasten mit richtigem Seitenverhältnis: hält den Platz frei, damit beim
   Einsetzen des echten Bildes nichts springt (CLS). */
.bildplatz {
  aspect-ratio: 16 / 9;
  display: grid; place-items: center;
  border: 1px dashed var(--rand);
  border-radius: var(--rundung);
  color: var(--ink-leise);
  font-size: var(--t-s);
  background: var(--grund-grau);
}

/* ── 6. Fußzeile ─────────────────────────────────────────────────────────── */

.fuss {
  border-top: 1px solid var(--linie);
  background: var(--grund-grau);
  padding-block: var(--a-7) var(--a-6);
  font-size: var(--t-s);
  color: var(--ink-ruhig);
}
.fuss__raster {
  display: grid;
  /* Vier Spalten ab genug Platz, sonst so viele wie hineinpassen.
     minmax(min(…,100%), 1fr) statt fester Breiten: sonst entsteht bei
     400px Fensterbreite eine Spalte, die breiter als der Bildschirm ist. */
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  gap: var(--a-6);
  margin-bottom: var(--a-6);
}
.fuss h2 { font-size: var(--t-s); text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink); margin-bottom: var(--a-3); }
.fuss ul { list-style: none; margin: 0; padding: 0; }
.fuss li { margin-bottom: var(--a-2); }
.fuss a { color: var(--ink-ruhig); text-decoration: none; }
.fuss a:hover { color: var(--ink); text-decoration: underline; }
.fuss__unten {
  border-top: 1px solid var(--linie);
  padding-top: var(--a-4);
  display: flex; flex-wrap: wrap; gap: var(--a-4) var(--a-5);
  align-items: center; justify-content: space-between;
  font-size: var(--t-xs); color: var(--ink-leise);
}

/* ── 7. Ohne JavaScript ──────────────────────────────────────────────────── */

/* Nur für den Fall, dass eine Seite das Kopf-Skript nicht trägt. Die Klasse
   .kein-js steht im <html> und wird im <head> sofort entfernt — siehe den
   Kommentar dort; erst in main.js entfernt kostet sie messbar Layoutsprung. */

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

@media print {
  .kopf, .nav, .sprung, .knopfreihe { display: none !important; }
  body { background: #fff; color: #000; }
  /* Auf Papier nützt ein zugeklapptes Akkordeon niemandem: Die Antworten
     sind der Inhalt des Abschnitts. Das Pluszeichen entfällt dabei — es
     verspricht eine Bedienung, die es auf Papier nicht gibt. */
  .frage__zeichen { display: none; }
  .frage::details-content { block-size: auto; content-visibility: visible; }
}

/* ══════════════════════════════════════════════════════════════════════════
   8. Mehrseiten-Ausbau (14.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Alles ab hier kam mit dem Ausbau vom Gerüst zur Website mit Leistungs- und
   Standortseiten dazu. Erzeugt werden die Seiten von _generator/; wer eine
   Klasse hier entfernt, muss dort nachsehen, ob sie noch verwendet wird —
   pruefen.py meldet Klassen im Markup, für die es keine Regel gibt.

   Die Regel der Palette gilt weiter und ohne Ausnahme: Hellblau #308ecb
   trägt KEINEN Text. Es ist Kanten-, Flächen- und Symbolfarbe. Wo Hellblau
   Text sein muss, steht --hellblau-text (#2877aa, 4,87:1).
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Titelzeile ──────────────────────────────────────────────────────────
   Hier stand bis zum 15.09.2026 .marke__zusatz — die Regeln der alten
   Textwortmarke „INSAF Gebäudeservice". Seit die Kopfzeile die Bildmarke
   trägt, gibt es dieses Element nicht mehr; die Regeln sind deshalb mit
   entfernt worden, statt als totes CSS stehenzubleiben. */

.hero__ort {
  font-size: var(--t-s);
  font-weight: var(--gewicht-ui);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #edf2f7;
  margin-bottom: var(--a-3);
}

/* Der Akzentbalken saß bisher nur unter h2. Auf den Unterseiten trägt die
   erste Überschrift ein h1 — ohne diese Zeile fehlte dort der Balken. */
.band__kopf h1::after {
  content: "";
  display: block;
  width: 3.5rem; height: 4px;
  margin-top: var(--a-3);
  border-radius: 2px;
  background: var(--hellblau);
}

/* Erstes Band einer Unterseite: oben etwas weniger Luft. Die Begründung war
   früher der Brotkrumenpfad darüber; seit dessen Wegfall am 15.09.2026 ist
   es schlicht der Abstand, der unter der schwebenden Leiste gut aussieht. */
.band--erste { padding-block: var(--a-7) var(--band); }

/* Die Regeln für den Brotkrumenpfad (.krumen, .krumen__liste) sind am
   15.09.2026 entfallen: Der sichtbare Pfad ist auf Wunsch des Auftraggebers
   weg („altbacken"), und mit ihm das BreadcrumbList im JSON-LD. Beides
   gehört zusammen — siehe teile.brotkrumen_html(). */

/* Die alten Leistungskarten (Rahmen + Text, ohne Bild) sind am 14.09.2026
   durch .kachel ersetzt worden — Abschnitt 10 am Dateiende. Die Regeln für
   .leistungsraster, .leistungskarte und .leistungskarte__mehr standen hier
   und wurden entfernt, nachdem pruefen.py sie als tot gemeldet hatte. */

/* ── Einsatzgebiet: Ortskacheln ──────────────────────────────────────────── */
.ortraster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: var(--a-4);
}
/* Seit dem 15.09.2026 ohne den hellblauen Balken am linken Rand
   (Auftraggeber) und ohne Metazeile und Kilometerangabe — beides steht
   weiter auf der Übersichtsseite und im Fragenteil der Startseite. */
.ortkarte {
  position: relative;
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  padding: var(--a-5);
  background: var(--grund);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.ortkarte:hover { border-color: var(--hellblau); }
.ortkarte h2, .ortkarte h3 { font-size: var(--t-l); margin-bottom: var(--a-1); }
.ortkarte__zusatz { font-size: var(--t-s); color: var(--ink-ruhig); margin-bottom: var(--a-4); }

/* Kleiner Knopf: die übliche Knopfform, nur knapper. Er ist der einzige
   Verweis der Karte; über ::after deckt er die ganze Karte als
   Klickfläche ab, damit man nicht genau den Knopf treffen muss. */
.knopf--klein {
  padding: 0.5rem 1rem;
  font-size: var(--t-xs);
}
.ortkarte__knopf { position: static; }
.ortkarte__knopf::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
/* Der Knopf liegt über der Silhouette; ein Grund verhindert, dass die
   Linien der Stadt durch ihn hindurchscheinen. */
.ortkarte .knopf { z-index: 1; }

/* ── Ablauf in Schritten ──────────────────────────────────────────────────
   Die drei Schritte laden nacheinander: Schiene füllt sich, Zahl springt in
   ihren Ring, der Ring zeichnet sich einmal herum, dann kommt der Text.
   Danach der nächste Schritt, um --takt versetzt.

   Aufgehängt ist alles an .schritte.sichtbar — der Beobachter in main.js
   setzt diese Klasse EINMAL auf die Liste. Läge reveal auf den einzelnen
   <li>, käme die Reihenfolge vom Scrollzufall statt von der Choreografie.

   Sämtliche Startwerte stehen unter .js-reveal. Ohne Skript (und bei
   „Bewegung reduzieren", denn dann vergibt main.js die Klasse gar nicht)
   ist der Abschnitt von Anfang an vollständig da — nichts bleibt unsichtbar
   hängen, wenn die Animation nie anläuft. */
.schritte {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: var(--a-5);
  --takt: .42s;                    /* Abstand von Schritt zu Schritt */
}
/* Die Liste bringt ihre eigene Choreografie mit (unten). Sie darf deshalb
   nicht zusätzlich heranwandern und scharf werden — zwei Bewegungen
   übereinander lesen sich als Unruhe. Das Einblenden bleibt, der Rest nicht. */
.js-reveal .schritte.reveal { transform: none; filter: none; }

.schritt { position: relative; padding-top: var(--a-6); }
/* --n ist die Nummer des Schritts und steuert jede Verzögerung darunter. */
.schritt:nth-child(1) { --n: 0; }
.schritt:nth-child(2) { --n: 1; }
.schritt:nth-child(3) { --n: 2; }

.schritt::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0;
  height: 3px; border-radius: 2px;
  background: var(--hellblau);
  transform-origin: left center;
}
.js-reveal .schritt::before { transform: scaleX(0); }
.js-reveal .schritte.sichtbar .schritt::before {
  animation: schiene .5s var(--kurve) forwards;
  animation-delay: calc(var(--n) * var(--takt));
}
@keyframes schiene { to { transform: scaleX(1); } }

/* Der Ring um die Zahl. --winkel muss registriert sein, sonst ist es für den
   Browser eine Zeichenkette und nichts bewegt sich. Wo @property fehlt,
   greift der Ausweichwert 360deg: Der Ring steht dann sofort geschlossen da,
   statt zu fehlen. */
@property --winkel {
  syntax: "<angle>";
  inherits: false;
  initial-value: 360deg;
}
.schritt__zahl {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.75rem; height: 2.75rem;
  margin-bottom: var(--a-3);
  border-radius: 50%;
  background: var(--grund-grau);
  font-family: var(--schrift-titel);
  font-weight: var(--gewicht-titel);
  font-size: var(--t-l);
  color: var(--hellblau-text);
  line-height: 1;
}
.schritt__zahl::before {
  content: "";
  position: absolute; inset: -4px;
  border-radius: 50%;
  background: conic-gradient(var(--hellblau) var(--winkel, 360deg),
                             rgba(48, 142, 203, .18) 0);
  /* Maske schneidet die Mitte heraus — übrig bleibt ein 3px-Ring. */
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 3px), #000 calc(100% - 3px));
          mask: radial-gradient(farthest-side, #0000 calc(100% - 3px), #000 calc(100% - 3px));
}
.js-reveal .schritt__zahl { opacity: 0; transform: scale(.72); }
.js-reveal .schritte.sichtbar .schritt__zahl {
  animation: zahl-auf .42s var(--kurve) forwards;
  animation-delay: calc(var(--n) * var(--takt) + .08s);
}
.js-reveal .schritte.sichtbar .schritt__zahl::before {
  animation: ring .7s var(--kurve) both;
  animation-delay: calc(var(--n) * var(--takt) + .14s);
}
@keyframes zahl-auf { to { opacity: 1; transform: none; } }
@keyframes ring { from { --winkel: 0deg; } to { --winkel: 360deg; } }

.js-reveal .schritt h3,
.js-reveal .schritt p { opacity: 0; transform: translateY(10px); }
.js-reveal .schritte.sichtbar .schritt h3,
.js-reveal .schritte.sichtbar .schritt p {
  animation: schritt-auf .45s var(--kurve) forwards;
  animation-delay: calc(var(--n) * var(--takt) + .26s);
}
@keyframes schritt-auf { to { opacity: 1; transform: none; } }

.schritt h3 { font-size: var(--t-l); margin-bottom: var(--a-2); }
.schritt p { font-size: var(--t-s); color: var(--ink-ruhig); margin-bottom: 0; }

/* ── Fragenteil als Akkordeon ────────────────────────────────────────────
   Überschrift = echte Frage, Antwort im ersten Absatz, 40–60 Wörter. Das ist
   die Form, die Antwortmaschinen zitieren können; pruefen.py misst sie.

   Gebaut aus <details>/<summary>: Auf- und Zuklappen macht der Browser, kein
   Skript. Die Antwort steht auch zugeklappt im Markup — sonst wäre das
   FAQ-JSON-LD eine Behauptung ohne Deckung.

   Eine Spalte statt zweier: Bei einem Akkordeon springt sonst die Nachbar-
   spalte mit, sobald eine Antwort aufgeht. */
.fragen {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--a-3);
  max-width: 58rem;
  margin-inline: auto;
}

/* Die Karte muss sich vom Band abheben, und der Fragenteil steht mal auf
   grauem, mal auf weißem Grund (Leistungsseiten: <section class="band">).
   Deshalb grau als Grundfall und weiß nur auf dem grauen Band — nicht
   umgekehrt, sonst verschwindet die Karte auf den Leistungsseiten. */
.frage {
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  background: var(--grund-grau);
  transition: border-color .25s var(--kurve), box-shadow .25s var(--kurve),
              background .25s var(--kurve);
}
.band--grau .frage { background: #ffffff; }
.frage[open] {
  border-color: var(--hellblau);
  box-shadow: 0 8px 26px rgba(10, 68, 114, .09);
}

.frage__kopf {
  display: flex;
  align-items: center;
  gap: var(--a-4);
  padding: var(--a-4) var(--a-5);
  cursor: pointer;
  list-style: none;                 /* Firefox: das Dreieck weg */
  border-radius: var(--rundung);
}
.frage__kopf::-webkit-details-marker { display: none; }   /* Safari, Chrome */
.frage__kopf:focus-visible { outline: 3px solid var(--hellblau); outline-offset: -3px; }

.frage h3 {
  flex: 1 1 auto;
  font-size: var(--t-l);
  margin: 0;
  transition: color .2s var(--kurve);
}
.frage__kopf:hover h3 { color: var(--hellblau-text); }

/* Das Zeichen rechts ist ein Plus aus zwei Strichen; beim Öffnen dreht der
   senkrechte Strich weg und es bleibt ein Minus. Kein Bild, keine Datei. */
.frage__zeichen {
  position: relative;
  flex: 0 0 auto;
  width: 2rem; height: 2rem;
  border-radius: 50%;
  background: #ffffff;                 /* immer der Gegenton zur Karte */
  transition: background .25s var(--kurve), transform .3s var(--kurve);
}
.band--grau .frage__zeichen { background: var(--grund-grau); }
.frage__zeichen::before,
.frage__zeichen::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 0.875rem; height: 2px;
  margin: -1px 0 0 -0.4375rem;
  border-radius: 1px;
  background: var(--hellblau-text);
  transition: transform .3s var(--kurve), background .25s var(--kurve);
}
.frage__zeichen::after { transform: rotate(90deg); }
.frage[open] .frage__zeichen { background: var(--hellblau); transform: rotate(180deg); }
.frage[open] .frage__zeichen::before,
.frage[open] .frage__zeichen::after { background: #ffffff; }
.frage[open] .frage__zeichen::after { transform: rotate(0deg); }

.frage__antwort { padding: 0 var(--a-5) var(--a-5); }
.frage__antwort p {
  margin-bottom: 0;
  color: var(--ink-ruhig);
  max-width: var(--breite-text);
}

/* Das Einblenden des Textes läuft überall. Die HÖHE lässt sich erst seit
   „interpolate-size" animieren — wo das fehlt, klappt der Kasten hart auf und
   der Text blendet trotzdem ein. Deshalb zwei getrennte Blöcke. */
.frage[open] .frage__antwort { animation: frage-auf .34s var(--kurve) both; }
@keyframes frage-auf {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
@supports (interpolate-size: allow-keywords) {
  .fragen { interpolate-size: allow-keywords; }
  .frage::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size .34s var(--kurve),
                content-visibility .34s var(--kurve) allow-discrete;
  }
  .frage[open]::details-content { block-size: auto; }
}

/* ── Antwortkasten auf Leistungsseiten ───────────────────────────────────── */
.antwortkasten {
  border: 1px solid var(--linie);
  border-top: 4px solid var(--hellblau);
  border-radius: var(--rundung);
  padding: var(--a-6);
  background: var(--grund-grau);
  max-width: calc(var(--breite-text) + 6rem);
}
.antwortkasten h2 { font-size: var(--t-xl); margin-bottom: var(--a-3); }
.antwortkasten p { margin-bottom: 0; font-size: var(--t-l); color: var(--ink); }

/* ── Leistungsumfang ─────────────────────────────────────────────────────── */
.umfang {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: var(--a-5);
}
.umfang__punkt h3 {
  font-size: var(--t-m);
  margin-bottom: var(--a-1);
  color: var(--ink);
}
.umfang__punkt p { font-size: var(--t-s); color: var(--ink-ruhig); margin-bottom: 0; }
.hinweis__wen { margin-top: var(--a-6); color: var(--ink-ruhig); font-size: var(--t-s); }

/* ── Lange Leistungs- und Ortslisten (Übersichtsseiten) ──────────────────── */
/* Die Ortsliste bleibt bei breiten Karten, die Leistungsliste geht auf DREI
   pro Zeile (Auftraggeber, 16.09.2026) — seit es fuenfzehn Leistungen sind,
   waere eine zweispaltige Liste acht Zeilen lang. */
.ortliste {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr));
  gap: var(--a-6);
}
.leistungsliste {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--a-5);
}
@media (min-width: 680px)  { .leistungsliste { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .leistungsliste { grid-template-columns: repeat(3, 1fr); } }
.leistungslang, .ortlang {
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  padding: var(--a-6);
  display: flex; flex-direction: column; align-items: flex-start;
}
.leistungslang h2, .ortlang h2 { font-size: var(--t-xl); margin-bottom: var(--a-1); }
.leistungslang h2 a, .ortlang h2 a { text-decoration: none; color: var(--ink); }
.leistungslang h2 a:hover, .ortlang h2 a:hover { color: var(--akzent); }
.leistungslang__kurz, .ortlang__meta {
  font-size: var(--t-xs);
  color: var(--ink-leise);
  margin-bottom: var(--a-4);
}
.leistungslang p, .ortlang p { font-size: var(--t-s); color: var(--ink-ruhig); }
.leistungslang__wen { font-size: var(--t-xs) !important; }
.leistungslang .knopf, .ortlang .knopf { margin-top: auto; }

/* ── Stadtprofil ─────────────────────────────────────────────────────────── */
.profil {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--a-6);
}
.profil__punkt h2 {
  font-size: var(--t-l);
  margin-bottom: var(--a-3);
  padding-bottom: var(--a-2);
  border-bottom: 2px solid var(--hellblau);
}
.profil__punkt p { margin-bottom: 0; color: var(--ink-ruhig); }

.stadtteile {
  max-width: none;
  font-size: var(--t-m);
  color: var(--ink-ruhig);
  line-height: 2;
}

/* ── Weiterführende Verweise am Seitenfuß ────────────────────────────────── */
.weiter {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: var(--a-6);
}
.weiter__spalte h2 {
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: var(--a-3);
}
.weiter__spalte ul { list-style: none; margin: 0; padding: 0; }
.weiter__spalte li { margin-bottom: var(--a-2); }
.weiter__spalte a { color: var(--ink-ruhig); text-decoration: none; }
.weiter__spalte a:hover { color: var(--akzent); text-decoration: underline; }

/* Die Regeln für den Kontaktabschnitt (.kontakt, .kontakt__raster,
   .kontakt__feld, .kontakt__hinweis) sind am 15.09.2026 entfallen: Kontakt
   hat eine eigene Seite, siehe Abschnitt 12. */

/* ── Anschrift (NAP) ─────────────────────────────────────────────────────
   Name, Anschrift, Telefon müssen auf allen Seiten und in allen Verzeichnissen
   ZEICHENGLEICH sein — daran hängt die lokale Auffindbarkeit. Sie entstehen
   deshalb an genau einer Stelle im Generator; pruefen.py vergleicht sie. */
.nap {
  font-style: normal;          /* <address> ist sonst kursiv */
  line-height: var(--zeile);
  margin-bottom: var(--a-3);
}
.nap__name { font-weight: var(--gewicht-ui); }
.nap__tel, .nap__mail { text-decoration: none; }
.nap__tel:hover, .nap__mail:hover { text-decoration: underline; }
.band--dunkel .nap { color: var(--auf-dunkel-leise); }
.band--dunkel .nap__tel, .band--dunkel .nap__mail { color: var(--auf-dunkel); }

/* ── Offene Angaben sichtbar machen ──────────────────────────────────────
   Der Grundsatz des Hauses: Offenes gehört in den Browser, nicht nur in den
   Quelltext. Wenn .marke-platzhalter und .offen-text nirgends mehr vorkommen,
   ist die Seite fertig — das ist die einfachste Fertigmeldung, die es gibt. */
/* Neutraler Strich fuer eine offene Angabe, wenn die gelben Marken
   ausgeschaltet sind (fakten.PLATZHALTER_ZEIGEN = False). Er haelt die Zeile
   im Datenblatt, ohne sie zu betonen — eine weggelassene Zeile saehe
   vollstaendig aus, obwohl die Angabe fehlt. */
.offen-strich { color: var(--ink-leise); }

.offen-text {
  color: var(--ink-leise);
  font-style: italic;
}
.band--dunkel .offen-text { color: var(--auf-dunkel-leise); }

.hinweis {
  border-radius: var(--rundung);
  padding: var(--a-5);
  margin-bottom: var(--a-6);
  max-width: calc(var(--breite-text) + 6rem);
}
.hinweis--offen {
  background: #fff8e1;
  border: 1px solid #a67c00;
  /* Warnfarbe absichtlich außerhalb der Markenpalette: Dieser Kasten soll
     stören. Er verschwindet mit der letzten offenen Angabe von selbst.

     Gerechnete Kontraste (nicht geschätzt):
       Text  #20313b auf #fff8e1  12,64:1  ✓ (4,5:1 nötig)
       Rand  #a67c00 auf #fff8e1   3,59:1  ✓ (3:1 nötig, WCAG 1.4.11)
       Rand  #a67c00 auf #ffffff   3,82:1  ✓ — die Kante grenzt außen an Weiß

     Der Rand war zuerst #e8c86a und lag damit bei 1,53:1 gegen den eigenen
     Grund: eine Kante, die man nicht sieht. #b8860b hätte mit 3,06:1
     bestanden, liegt aber zu knapp an der Schwelle — Rundungen im
     Farbmanagement kippen solche Werte. */
}
.hinweis--offen p { margin-bottom: 0; color: var(--ink); font-size: var(--t-s); }
.hinweis--offen .marke-platzhalter { margin-bottom: var(--a-2); }

/* ── Datenblatt (Über INSAF, Impressum, Datenschutz) ─────────────────────── */
.datenblatt {
  margin: 0 0 var(--a-6);
  max-width: calc(var(--breite-text) + 4rem);
  border-top: 1px solid var(--linie);
}
.datenzeile {
  display: grid;
  grid-template-columns: minmax(8rem, 14rem) 1fr;
  gap: var(--a-4);
  padding: var(--a-3) 0;
  border-bottom: 1px solid var(--linie);
}
.datenblatt dt {
  font-weight: var(--gewicht-ui);
  color: var(--ink-ruhig);
  font-size: var(--t-s);
}
.datenblatt dd { margin: 0; overflow-wrap: break-word; }
@media (max-width: 560px) {
  /* Zwei Spalten kippen unter 560px: „Umsatzsteuer-Identifikationsnummer"
     bekommt sonst 8rem und bricht in fünf Zeilen um. */
  .datenzeile { grid-template-columns: 1fr; gap: var(--a-1); }
}

/* ── Rechtstexte ─────────────────────────────────────────────────────────
   Eigene Abstände: Global steht margin-bottom an h2, in Kacheln und Rastern
   ist das richtig, im langen Fließtext einer Rechtsseite zu wenig Luft
   zwischen Absatz und nächster Überschrift. */
.rechtstext { max-width: calc(var(--breite-text) + 8rem); }
.rechtstext h2 { margin-top: var(--a-7); font-size: var(--t-xl); }
.rechtstext h2:first-of-type { margin-top: var(--a-6); }
.rechtstext p { margin-bottom: var(--a-4); }
.rechtstext .klein {
  font-size: var(--t-s);
  color: var(--ink-leise);
  border-left: 2px solid var(--linie);
  padding-left: var(--a-4);
}

/* ── Zweispaltiger Textblock ─────────────────────────────────────────────── */
.raster-zwei {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--a-6);
}
.raster-zwei h3 { font-size: var(--t-l); margin-bottom: var(--a-2); }
.raster-zwei p { margin-bottom: 0; color: var(--ink-ruhig); }

/* ── Fußzeile: vier Spalten statt drei ───────────────────────────────────── */
.fuss__spalte ul { list-style: none; margin: 0; padding: 0; }
.fuss__kontakt { font-size: var(--t-s); margin-bottom: 0; }
.fuss__stand {
  color: var(--hellblau-text);
  font-weight: var(--gewicht-ui);
}



/* Kopf einer Leistung in der Übersicht: hält Titel und Kurzzeile zusammen,
   damit der Abstand zum Fließtext darunter unabhängig davon bleibt, ob der
   Titel ein- oder zweizeilig umbricht. */
.leistungslang__kopf { margin-bottom: var(--a-4); }

/* ══════════════════════════════════════════════════════════════════════════
   9. Schwebende Navigationsleiste + Titelbild über den ganzen Bildschirm
      (Auftraggeber, 14.09.2026)
   ──────────────────────────────────────────────────────────────────────────
   Die Kopfzeile lief vorher als durchgehender Balken über die volle Breite.
   Jetzt ist sie eine abgesetzte Leiste mit Abstand zu allen Rändern und
   runden Ecken — sie liegt sichtbar AUF dem Bild, statt es abzuschneiden.

   Die Regeln stehen bewusst am Dateiende und überschreiben Abschnitt 3.
   Das ist billiger und nachvollziehbarer, als den alten Block zu zerlegen:
   Abschnitt 3 beschreibt weiter, wie die Leiste sich beim Scrollen verhält,
   und hier steht nur, was anders ist.
   ══════════════════════════════════════════════════════════════════════════ */

.kopf {
  /* Der Abstand nach oben macht aus dem Balken eine schwebende Leiste.
     `top` muss denselben Wert haben, sonst springt sie beim Scrollen an
     den Rand. */
  top: var(--kopf-luft);
  /* Luft oben UND unten. Der untere Teil ist kein Gestaltungsmittel, sondern
     Platzhalter: `position: sticky` mit `top: 24px` schiebt die Leiste schon
     im Ruhezustand um 24px nach unten, während sie im Textfluss weiter an
     ihrer alten Stelle Platz belegt. Ohne diese 24px unten lag der
     Brotkrumenpfad der Unterseiten halb unter der Leiste (gemessen: Leiste
     bis y=119, Pfad ab y=96). */
  padding-block: var(--kopf-luft);
  background: none;            /* der Glanz sitzt jetzt auf .kopf__zeile */
  backdrop-filter: none;
  border-bottom: 0;
  box-shadow: none;
}
:root {
  --kopf-luft: clamp(0.75rem, 0.4rem + 1.2vw, 1.5rem);
  --kopf-rundung: 14px;
}

.kopf__zeile {
  /* Die Leiste selbst: gerundet, abgesetzt, mit eigenem Innenabstand.
     .inhalt liefert weiterhin die Maximalbreite und die Seitenränder. */
  padding-inline: clamp(1rem, 0.6rem + 1.6vw, 2rem);
  border-radius: var(--kopf-rundung);
  border: 1px solid transparent;
  background: color-mix(in srgb, var(--grund) 90%, transparent);
  backdrop-filter: blur(12px);
  box-shadow: var(--schatten-1);
  transition: background-color var(--dauer) var(--kurve),
              border-color var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve);
}

/* ── Über dem Titelbild: blaues Glas ──────────────────────────────────────
   Das Dunkelblau der Marke mit Deckkraft, nicht neutrales Schwarz — so
   bleibt die Leiste Teil der Palette und nicht ein grauer Fremdkörper.
   Der Kontrast des Textes darauf ist unten gemessen. */
/* Über dem Titelbild: blaues Glas mit heller Kante.
   Das Dunkelblau der Marke mit Deckkraft, nicht neutrales Schwarz — so
   bleibt die Leiste Teil der Palette und nicht ein grauer Fremdkörper.

   Diese Fläche war am 14.09.2026 kurz entfernt („der blaue Hintergrund muss
   weg"), was ein Missverständnis war: Gemeint war der angedockte Zustand
   beim Scrollen, nicht die schwebende Leiste über dem Bild. Sie ist mit
   demselben Entwurf wiederhergestellt. Ohne sie fiel der Kontrast des
   weißen Textes auf 2,63:1 und musste über einen dunklen Schleier im
   Titelbild aufgefangen werden — der ist damit ebenfalls wieder raus. */
.hat-hero .kopf {
  /* Die Kopfzeile selbst ist über dem Titelbild vollständig unsichtbar —
     das Glas sitzt auf .kopf__zeile darunter.

     Hier müssen ALLE VIER Eigenschaften der alten Regel aus Abschnitt 3
     zurückgenommen werden, nicht nur der Hintergrund. Solange nur
     `background: none` dastand, blieben `backdrop-filter` und die helle
     Unterkante aktiv: Das ergab einen weichgezeichneten, kräftiger
     gesättigten Streifen über die volle Fensterbreite von y=24 bis y=143 —
     sichtbar als blaues Rechteck hinter der Leiste, und der Grund dafür,
     dass das Titelbild oben unscharf wirkte.
     Ein `background: none` allein räumt einen Glas-Effekt nicht ab. */
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom-color: transparent;
}
.hat-hero .kopf .kopf__zeile {
  background: color-mix(in srgb, var(--dunkelblau) 62%, transparent);
  backdrop-filter: blur(12px);
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow: 0 10px 30px rgba(5, 30, 55, 0.28);
}
/* Gescrollt wird die Leiste weiß — heller Text auf hellem Seiteninhalt
   wäre sonst unlesbar, sobald das Bild durchgelaufen ist. */
.hat-hero .kopf.gescrollt .kopf__zeile {
  background: color-mix(in srgb, var(--grund) 92%, transparent);
  border-color: var(--linie);
  box-shadow: var(--schatten-2);
}

/* ── Titelbild über den ganzen Bildschirm ─────────────────────────────────
   `min-height`, nicht `height`: Der Anfrage-Assistent ist auf kleinen
   Fenstern höher als der Bildschirm — mit fester Höhe würde er
   abgeschnitten statt den Abschnitt wachsen zu lassen.

   `100dvh` statt `100vh`: Auf dem Telefon rechnet `vh` mit eingeklappter
   Browserleiste. Die Seite wäre beim Laden rund 60–100px zu hoch, und der
   untere Rand des Bildes läge unter der Adressleiste. `dvh` folgt der
   tatsächlich sichtbaren Höhe. Die vh-Zeile davor bleibt als Rückfall für
   ältere Browser stehen. */
.hero {
  /* Die Höhe muss die Verschiebung nach oben AUSGLEICHEN: Der Abschnitt
     beginnt durch das negative margin-top rund 96px über dem Bildschirmrand.
     Mit glatten 100dvh endete er dieselben 96px zu früh — unten blieb ein
     weißer Streifen des nächsten Abschnitts stehen. */
  min-height: calc(100vh + var(--kopf-hoehe) + var(--kopf-luft) * 2);
  min-height: calc(100dvh + var(--kopf-hoehe) + var(--kopf-luft) * 2);
  /* Zentriert den Inhalt senkrecht im nun bildschirmhohen Abschnitt.

     Zwei Umwege, die nicht funktioniert haben:
     1. `display:flex` PLUS `.hero > .inhalt { width: 100% }` — das `width`
        schlug die eigene Regel von .inhalt (`width: min(100% - 3rem,
        1200px)`), der Titeltext lief bis an den Fensterrand. Gemessen:
        1425px breit statt 1200, linker Rand 0 statt 113px.
     2. `display:grid` mit `align-content:center` — dabei verschwand das
        Titelbild. In einem Grid-Container ist der Bezugsrahmen für absolut
        positionierte Kinder der Grid-Bereich, nicht die Polsterbox des
        Containers. `.hero__bild { inset: 0 }` füllte deshalb nur noch den
        zentrierten Inhaltsblock statt des ganzen Abschnitts.

     Richtig ist Flex OHNE eigene Breitenangabe: .inhalt behält sein
     `width: min(…)` und zentriert sich über `margin-inline: auto`. */
  display: flex;
  align-items: center;
  /* Der Abschnitt wird unter die Leiste gezogen, damit das Bild wirklich am
     oberen Bildschirmrand beginnt. Der Wert muss die GANZE Leiste abdecken:
     ihre Zeilenhöhe UND die Luft darüber. Mit nur --kopf-hoehe blieb ein
     24px hoher weißer Streifen über dem Bild stehen (gemessen: Hero begann
     bei y=24 statt 0). */
  margin-top: calc(-1 * (var(--kopf-hoehe) + var(--kopf-luft) * 2));
  /* Der obere Innenabstand gibt dem Inhalt den Platz wieder zurück. */
  padding-block: calc(var(--kopf-hoehe) + var(--kopf-luft) * 2 + var(--a-6)) var(--band);
}

/* Keine Ausnahme für schmale Bildschirme: `min-height` ist eine MINDEST-
   höhe, der Abschnitt wächst also von selbst, sobald der gestapelte
   Anfrage-Assistent mehr Platz braucht. Eine Regel `min-height: 0` stand
   hier kurz — sie hätte nur bewirkt, dass das Titelbild am Telefon NICHT
   bildschirmfüllend ist, ohne irgendein Problem zu lösen. */

/* ── Navigation und Marke bleiben in Blauer Nue ───────────────────────────
   Inter ist seit dem 14.09.2026 die FLIESSTEXT-Schrift. Bedienelemente
   gehören nicht dazu: Die Marke ist ein Schriftzug, die Navigation eine
   kurze Auszeichnung. Beides in der Markenschrift zu halten, ist der
   Unterschied zwischen „zwei Schriften mit Aufgaben" und „zwei Schriften". */
.marke,
.nav__liste a,
.nav__schalter,
.knopf { font-family: var(--schrift-titel); }

/* ── Taglines über den Überschriften: Inter Bold ───────────────────────────
   Auftraggeber, 14.09.2026. Gemeint ist die kleine Versalienzeile, die über
   einer Überschrift steht und sie einordnet — im Titelbild die Ortszeile,
   im Anfrage-Assistenten der Schrittzähler. Beide haben dieselbe Aufgabe
   und bekommen deshalb dieselbe Behandlung.

   Warum Inter Bold und nicht Blauer Nue: In Versalien mit weitem
   Buchstabenabstand zählt Gleichmäßigkeit mehr als Charakter. Inters
   Großbuchstaben stehen ruhiger nebeneinander, und der fette Schnitt hält
   die Zeile in dieser kleinen Größe sichtbar, ohne sie zu einer zweiten
   Überschrift zu machen.

   `font-weight: 700` greift, weil Inter hier als Variable Font mit dem
   Bereich 300–700 eingebunden ist (siehe tokens.css). */
.hero__ort,
.funnel__zaehler {
  font-family: 'Inter', var(--schrift-text);
  font-weight: 700;
}

/* ── Gescrollt: dieselbe Leiste, nur hell ─────────────────────────────────
   Auftraggeber, 14.09.2026. Die Leiste bleibt in JEDEM Zustand dieselbe
   Form: schwebend, mit Abstand zu den Rändern, runde Ecken, eigene Fläche.
   Beim Scrollen wechselt nur die Farbe — von blauem Glas zu weißem Glas.

   Eine Zwischenfassung ließ sie beim Scrollen randlos an den oberen Rand
   andocken (volle Breite, ohne Rundung). Das ergab optisch zwei
   verschiedene Navigationen auf derselben Seite und ist zurückgenommen:
   `top` und `padding-block` aus .kopf bleiben unangetastet, damit die Form
   erhalten bleibt. */
.kopf.gescrollt,
.hat-hero .kopf.gescrollt {
  /* Beide Selektoren nötig: `.hat-hero .kopf.gescrollt` in Abschnitt 3 setzt
     seit dem Gerüst `background: rgba(255,255,255,0.92)` und ist mit 0-3-0
     spezifischer als `.kopf.gescrollt` allein (0-2-0). Ohne die zweite Zeile
     blieb dieser weiße Grund aktiv und legte sich als Balken über die volle
     Fensterbreite hinter die Leiste — derselbe Fehler wie zuvor mit dem
     blauen Kasten, nur in Weiß. */
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
  border-bottom-color: transparent;
}
.kopf.gescrollt .kopf__zeile,
.hat-hero .kopf.gescrollt .kopf__zeile {
  background: color-mix(in srgb, var(--grund) 92%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-color: var(--linie);
  border-radius: var(--kopf-rundung);
  box-shadow: var(--schatten-2);
}

/* ── Die beiden Knöpfe unter dem Titeltext ────────────────────────────────
   Sie stehen auf dem Foto, brauchen also eigene Flächen statt bloßer
   Textfarbe. Der erste ist hell gefüllt (Bewertungen = der Beleg, den ein
   Besucher zuerst sucht), der zweite hat nur eine Kontur, damit die beiden
   nicht gegeneinander arbeiten. */
.hero__knoepfe {
  display: flex;
  flex-wrap: wrap;
  gap: var(--a-3);
  margin-top: var(--a-6);
}
.knopf--hero {
  gap: 0.6rem;
  padding: 0.85rem 1.4rem;
  border-radius: 100px;
  background: #ffffff;
  color: var(--dunkelblau);
  border: 1px solid #ffffff;
  /* Weiß auf Dunkelblau: 10,08:1 — der Text liegt auf der eigenen Fläche
     des Knopfes, nicht auf dem Foto, deshalb ist der Wert stabil. */
}
.knopf--hero:hover { background: var(--lightgrau); color: var(--dunkelblau-tief); border-color: var(--lightgrau); }
.knopf__icon { width: 1.15em; height: 1.15em; flex-shrink: 0; }

/* Zweiter Knopf: nur Kontur. Der Rand ist reines Weiß (nicht abgedunkelt) —
   auf einem Foto trägt eine halbtransparente Kante zu wenig. */
.knopf--ruf {
  background: transparent;
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.75);
}
.knopf--ruf:hover { background: rgba(255, 255, 255, 0.14); color: #ffffff; border-color: #ffffff; }

/* ── Solange Nummer und Profil fehlen ─────────────────────────────────────
   Der Knopf sieht aus wie einer, führt aber nirgendwohin und sagt das auch.
   `cursor: default` und `pointer-events: none` verhindern den Klick;
   `aria-disabled` sagt es der Vorlesesoftware. */
.knopf.ist-offen {
  cursor: default;
  pointer-events: none;
  opacity: 1;                 /* NICHT über Deckkraft abschwächen: das
                                 zerstört den Kontrast der Beschriftung. */
  border-style: dashed;
}
.knopf__offen {
  margin-left: 0.15rem;
  padding: 0.1rem 0.5rem;
  border-radius: 100px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: #ffd84d;
  color: var(--ink);          /* 9,71:1 — derselbe Warnton wie überall sonst */
}

@media (max-width: 560px) {
  /* Am Telefon stehen die beiden untereinander und waren dabei
     unterschiedlich breit — der eine trägt mehr Text als der andere. Gleich
     breit sieht nicht nur ruhiger aus, es vergrößert auch die Trefferfläche
     des kürzeren auf die volle Zeile. */
  .hero__knoepfe { flex-direction: column; align-items: stretch; }
  .knopf--hero { justify-content: center; }
}

/* ══════════════════════════════════════════════════════════════════════════
   10. Leistungskacheln mit Bild (14.09.2026, nach Entwurf des Auftraggebers)
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Zentrierter Abschnittskopf mit Pille ─────────────────────────────────── */
.kopf-mitte {
  /* Keine Breitenbegrenzung am ganzen Block: Sie galt sonst auch für die
     Überschrift, und „Einblick in unsere Leistungen" brach dadurch in zwei
     Zeilen um, obwohl der Abschnitt breit genug ist. Begrenzt wird nur der
     Fließtext darunter — dort ist die Lesebreite sinnvoll. */
  margin: 0 auto var(--a-8);
  text-align: center;
}
.kopf-mitte h2 { margin-bottom: var(--a-4); }
/* Der Akzentbalken aus .band__kopf gehört hier nicht hin: Die Pille darüber
   setzt die Auszeichnung bereits, ein zweiter Strich wäre doppelt gemoppelt. */
.kopf-mitte h2::after { content: none; }
.kopf-mitte p {
  color: var(--ink-ruhig);
  font-size: var(--t-l);
  margin: 0 auto;
  max-width: 56ch;
}

/* Umrisspille statt gefüllter Fläche (15.09.2026, Kundenwunsch): Der Ton, der
   vorher die Fläche war, ist jetzt Rand UND Schrift.

   Weiter --hellblau-text (#2877aa) und NICHT --hellblau (#308ecb): Als Fläche
   war die Wahl eine Frage des weißen Textes darauf, jetzt ist sie eine Frage
   der Schrift selbst — und #308ecb schafft als Text auf Weiß nur 3,04:1.
   #2877aa hält gemessen 4,87:1 auf Weiß und 4,51:1 auf dem grauen Band; auf
   dunklen Bändern steht keine Pille.

   Der Rand kommt vom Innenabstand ab, nicht dazu: Sonst wäre die Pille nach
   dem Umbau 4px höher als vorher und stünde anders zur Überschrift. */
.pille {
  display: inline-block;
  margin-bottom: var(--a-4);
  padding: calc(0.5rem - 2px) calc(1.4rem - 2px);
  border: 2px solid var(--hellblau-text);
  border-radius: 100px;
  background: none;
  color: var(--hellblau-text);
  font-family: 'Inter', var(--schrift-text);
  font-weight: 700;
  font-size: var(--t-s);
  letter-spacing: 0.01em;
}

.knopfreihe--mitte { justify-content: center; margin-top: var(--a-8); }
/* Steht die Knopfreihe NICHT am Ende ihres Abschnitts, braucht sie auch nach
   unten Luft — seit der Knopf „Alle Leistungen im Überblick" über dem
   Kachelraster sitzt, klebte er sonst daran (gemessen 0px).
   :not(:last-child) statt „+ .kachelraster": Zwischen beiden kann der
   Platzhalterhinweis stehen, sobald fakten.PLATZHALTER_ZEIGEN wieder True ist —
   ein Geschwister-Selektor würde dann ins Leere greifen. */
.knopfreihe--mitte:not(:last-child) { margin-bottom: var(--a-8); }
.hinweis--mitte { margin-inline: auto; text-align: left; }

/* ── Das Raster ───────────────────────────────────────────────────────────
   Drei Spalten ab 1040px, darunter zwei, am Telefon eine. Feste Stufen statt
   auto-fit: Bei sechs Kacheln soll die letzte Reihe nie mit einer einzelnen
   Kachel enden, und das lässt sich mit auto-fit nicht steuern. */
.kachelraster {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--a-5);
}
@media (min-width: 700px)  { .kachelraster { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .kachelraster { grid-template-columns: repeat(3, 1fr); } }

/* ── Eine Kachel ──────────────────────────────────────────────────────────
   Das Bild füllt die Kachel, Text und Pfeil liegen darauf. `isolation`
   schafft einen eigenen Stapelkontext, damit die z-index-Werte innerhalb der
   Kachel nichts außerhalb beeinflussen. */
.kachel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 20px;
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: flex-end;
  background: var(--dunkelblau);   /* sichtbar, solange das Bild lädt */
  transition: transform var(--dauer) var(--kurve), box-shadow var(--dauer) var(--kurve);
}
.kachel:hover { transform: translateY(-4px); box-shadow: var(--schatten-2); }

.kachel__bild { position: absolute; inset: 0; z-index: -2; display: block; }
.kachel__bild img { width: 100%; height: 100%; object-fit: cover; }

/* Der Verlauf ist kein Dekor, sondern trägt den Kontrast der weißen Schrift:
   Ohne ihn läge sie auf einem hellen Bildbereich. Er beginnt erst bei 38 %,
   damit das Motiv oben frei bleibt. Werte unten gemessen. */
.kachel::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg,
    rgba(8, 32, 56, 0.00) 0%,
    rgba(8, 32, 56, 0.18) 38%,
    rgba(8, 32, 56, 0.72) 66%,
    rgba(8, 32, 56, 0.92) 100%);
}

.kachel__text {
  /* position: static ist hier ABSICHT und nicht vergessen.
     Der Verweis in der Ueberschrift spannt sich ueber ein ::after mit
     inset: 0 auf. Dessen Bezugsrahmen ist der naechste positionierte
     Vorfahr — stand hier `position: relative`, war das dieser Textblock, und
     klickbar war nur das untere Drittel der Kachel. Mit static faellt der
     Bezug auf .kachel zurueck, und die ganze Kachel wird zur Flaeche. */
  position: static;
  padding: var(--a-5);
  padding-right: calc(var(--a-5) + 3.4rem);   /* Platz für den Pfeil */
}
.kachel__text h3 {
  font-size: var(--t-l);
  color: #ffffff;
  margin-bottom: var(--a-1);
}
.kachel__text h3 a { color: inherit; text-decoration: none; }
/* Die ganze Kachel ist anklickbar, benannt bleibt aber der Titel — so hört
   eine Vorlesesoftware einen echten Verweis und keine leere Fläche. */
/* Die Verweisflaeche deckt die GANZE Kachel ab — Bild, Verlauf und Text.
   Ein einziger Verweis bleibt dabei im Tabulatorlauf, der Name kommt aus der
   Ueberschrift. */
.kachel__text h3 a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.kachel__text p {
  margin: 0;
  font-size: var(--t-s);
  color: #e8eef4;
  max-width: none;
}

.kachel__pfeil {
  position: absolute;
  right: var(--a-5);
  bottom: var(--a-5);
  width: 2.75rem; height: 2.75rem;
  z-index: 2;
  pointer-events: none;   /* der Verweis liegt darunter und soll klickbar bleiben */
  /* Im Ruhezustand KEIN Schein (Auftraggeber, 15.09.2026). Vorher lag hier ein
     dauerhaftes `drop-shadow`, das beim Überfahren nur kräftiger wurde — der
     Pfeil leuchtete also immer. `filter: none` ist ausdrücklich gesetzt und
     nicht bloß weggelassen, damit der Übergang unten etwas hat, wovon aus er
     überblenden kann. */
  filter: none;
  transition: transform var(--dauer) var(--kurve), filter var(--dauer) var(--kurve);
}

/* Schein erst beim Überfahren der KACHEL, nicht des Pfeils: der Pfeil hat
   `pointer-events: none`, ein eigenes :hover käme dort nie zustande.
   :focus-within ergänzt die Tastatur — der Verweis liegt im Titel der Kachel.

   `drop-shadow` statt `box-shadow`: Der Filter folgt dem Alphakanal der
   Grafik, legt sich also um den Kreis selbst. `box-shadow` würde das
   rechteckige Bildfeld umranden und an den Ecken sichtbar werden.
   Zwei gestaffelte Schatten: ein enger, kräftiger an der Kante und ein
   weiter, weicher darum herum — einer allein wirkt hart oder flau. */
.kachel:hover .kachel__pfeil,
.kachel:focus-within .kachel__pfeil {
  transform: translate(3px, -3px);
  filter:
    drop-shadow(0 0 7px rgba(48, 142, 203, 0.85))
    drop-shadow(0 0 26px rgba(48, 142, 203, 0.60));
}

@media (prefers-reduced-motion: reduce) {
  .kachel, .kachel__pfeil { transition: none; }
  .kachel:hover { transform: none; }
  .kachel:hover .kachel__pfeil,
  .kachel:focus-within .kachel__pfeil { transform: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   11. Haltungsband: Logo, Anspruch, Freisteller, Skyline
       (Entwurf des Auftraggebers, 14.09.2026)
   ══════════════════════════════════════════════════════════════════════════ */
.haltung {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--grund-tief);
  color: var(--auf-dunkel);
  padding-block: var(--a-9) 0;   /* unten 0: der Freisteller steht auf der Kante */
}

/* ── Skyline im Hintergrund ───────────────────────────────────────────────
   Sie sitzt unten, über die volle Breite, und ist stark zurückgenommen.
   `aria-hidden` plus leeres alt: eine Stadtsilhouette trägt keine
   Information, die jemand vorgelesen bekommen müsste.

   `mix-blend-mode: soft-light` statt bloßer Deckkraft: Die Zeichnung legt
   sich damit in das Blau hinein, statt als grauer Schleier darüber zu
   liegen. Wo das Band dunkler ist, verschwindet sie fast — genau das
   Verhalten, das eine Hintergrundgrafik haben soll. */
.haltung__skyline {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: -1;
  display: block;
  pointer-events: none;
  /* Die Zeichnung liegt in #308ecb vor — dem Marken-Hellblau, nicht in
     Weiß. Mit `mix-blend-mode: soft-light` war sie auf dem dunkelblauen
     Band praktisch unsichtbar: soft-light nimmt hellen Tönen genau die
     Helligkeit, die sie hier bräuchten. `screen` hellt stattdessen auf und
     lässt die Linien aus dem Grund heraustreten, ohne sie hart
     aufzusetzen. */
  opacity: 0.45;
  mix-blend-mode: screen;
}
.haltung__skyline img {
  width: 100%;
  height: auto;
  display: block;
}

/* ── Zweispaltig: Text links, Person rechts ───────────────────────────────
   `align-items: end` stellt den Freisteller auf die Unterkante des Bandes —
   im Entwurf steht die Person auf der Kante, nicht in der Luft. */
.haltung__raster {
  position: relative;
  display: grid;
  /* Seit dem 15.09.2026 steht rechts ein Gruppenbild im QUERFORMAT
     (1110×810, Verhältnis 1,37) statt des hochformatigen Freistellers einer
     einzelnen Person. Ein Querformat braucht mehr Breite, sonst wird es
     winzig — die Spalte ist deshalb von 23rem auf 34rem gewachsen. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 34rem);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: end;
}
.haltung__text { padding-bottom: var(--a-9); }

.haltung__logo {
  width: clamp(11rem, 9rem + 6vw, 15.5rem);
  height: auto;
  margin-bottom: var(--a-7);
}

/* Größe bewusst NICHT überschrieben: Jede Abschnittsüberschrift trägt
   --t-2xl, auch diese. Vorher stand hier --t-3xl — das ist die Größe der
   h1 und ließ den Abschnitt aus der Reihe fallen (gemessen 64px gegen 44px
   in allen übrigen Bändern). Die Auszeichnung leistet hier das Logo. */
.haltung h2 {
  color: #ffffff;
  margin-bottom: var(--a-5);
}
/* Der Akzentbalken der übrigen Abschnitte entfällt hier: Das Logo darüber
   übernimmt die Auszeichnung. */
.haltung h2::after { content: none; }

.haltung p {
  color: var(--auf-dunkel-leise);
  max-width: 46ch;
}
.haltung p:last-of-type { margin-bottom: 0; }

/* ── Freisteller ──────────────────────────────────────────────────────────
   Ohne `display:block` am picture entsteht unter dem Bild die
   Zeilenabstandslücke eines Inline-Elements — die Person stünde dann
   sichtbar neben der Kante statt darauf. */
.haltung__bild {
  position: relative;
  /* Das Bild sitzt am unteren Ende seiner Spalte, mit einem schmalen Rest
     Luft zur Bandkante (Auftraggeber, 15.09.2026: „fast bis zum Boden").

     Vorher stand hier `align-self: center` mit großem Abstand nach unten —
     die Gruppe schwebte dadurch auf halber Höhe, während links der Text
     bis nach unten lief. */
  align-self: end;
  padding-bottom: var(--a-5);
}
.haltung__bild picture { display: block; }
.haltung__bild img {
  width: 100%;
  height: auto;
  display: block;
  /* Der Freisteller hat keinen eigenen Schatten; ein weicher Schlagschatten
     nach unten trennt ihn vom Band, ohne ihn auszuschneiden. */
  filter: drop-shadow(0 18px 40px rgba(3, 18, 34, 0.45));
}

.haltung__hinweis {
  margin: var(--a-6) 0 0;
  font-size: var(--t-xs);
  color: var(--auf-dunkel-leise);
  max-width: 46ch;
}
.haltung__hinweis .marke-platzhalter { margin: 0 var(--a-2) 0 0; }

@media (max-width: 940px) {
  /* Untereinander: erst der Text, dann die Person. Sie bleibt am unteren
     Rand stehen, wird aber nicht mehr so hoch — sonst nimmt sie am Telefon
     den halben Bildschirm. */
  .haltung__raster { grid-template-columns: 1fr; }
  .haltung__text { padding-bottom: var(--a-6); }
  .haltung__bild { max-width: 26rem; margin-inline: auto; padding-bottom: var(--a-7); }
  .haltung__hinweis { margin-top: var(--a-5); }
}

/* ══════════════════════════════════════════════════════════════════════════
   12. Kontaktseite (15.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Kontakt ist seit dem 15.09.2026 eine eigene Seite. Der Abschnitt am Fuß
   jeder Seite ist dafür entfallen — er hätte dasselbe Angebot zweimal
   gemacht und der Navigationsverweis wäre am Formular vorbeigegangen.
   ══════════════════════════════════════════════════════════════════════════ */
.kontaktseite {
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}
@media (max-width: 860px) {
  /* Unter 860px untereinander: Zwei Spalten lassen dem Formular sonst
     weniger Platz, als seine Felder brauchen. */
  .kontaktseite { grid-template-columns: 1fr; }
}
.kontaktseite__daten h2 { font-size: var(--t-xl); margin-bottom: var(--a-5); }
.kontaktseite__daten .datenblatt { margin-bottom: var(--a-4); }

/* ── Formular ─────────────────────────────────────────────────────────────
   Gleiche Bauart wie die Felder im Anfrage-Assistenten, damit beide
   Formulare der Seite sich nicht widersprechen. */
.kform__feld { margin-bottom: var(--a-4); }
.kform__feld > label {
  display: block;
  font-size: var(--t-s);
  font-weight: var(--gewicht-ui);
  margin-bottom: var(--a-1);
}
.kform__optional { font-weight: 400; color: var(--ink-leise); }
.kform__feld input[type="text"],
.kform__feld input[type="email"],
.kform__feld input[type="tel"],
.kform__feld textarea {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--rand);
  border-radius: var(--rundung-s);
  background: var(--grund);
  color: var(--ink);
  font: inherit;
  transition: border-color var(--dauer) var(--kurve);
}
.kform__feld textarea { resize: vertical; min-height: 7rem; }
.kform__feld input:focus-visible,
.kform__feld textarea:focus-visible { border-color: var(--dunkelblau); }
.kform__feld--check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--a-2);
  align-items: start;
  margin-top: var(--a-5);
}
.kform__feld--check input {
  width: 1.125rem; height: 1.125rem;
  accent-color: var(--dunkelblau);
  margin: 0.15rem 0 0;
}
.kform__feld--check label { font-size: var(--t-s); font-weight: 400; margin: 0; }
.kform__fehler {
  margin: var(--a-1) 0 0;
  font-size: var(--t-xs);
  color: #a4232a;   /* 5,9:1 auf Weiß — Rot allein darf keine Information tragen,
                       deshalb steht immer auch ein Text daneben (WCAG 1.4.1). */
  min-height: 1em;
}
.kform button[type="submit"] { margin-top: var(--a-5); }
.kform__ende h3 { font-size: var(--t-xl); margin-bottom: var(--a-3); }
.kform__ende[hidden] { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   13. Fußzeile auf Dunkelblau (15.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Auftraggeber: Der Fuß übernimmt die Farbe des entfallenen
   Kontaktabschnitts. Damit endet die Seite auf derselben Fläche wie vorher,
   nur ohne das doppelte Kontaktangebot.

   Alle Textfarben müssen mit — auf Dunkelblau trägt --ink (1,33:1)
   überhaupt nichts. Werte unten sind die gerechneten aus tokens.css.
   ══════════════════════════════════════════════════════════════════════════ */
.fuss {
  background: var(--grund-tief);
  border-top: 0;
  color: var(--auf-dunkel-leise);      /* #bcd0e0 auf #0a4472 = 6,36:1 */
}
.fuss h2 { color: var(--auf-dunkel); } /* #f6f6f6 = 9,33:1 */
.fuss a { color: var(--auf-dunkel-leise); }
.fuss a:hover { color: #ffffff; text-decoration: underline; }
.fuss .nap { color: var(--auf-dunkel-leise); }
.fuss .nap__tel, .fuss .nap__mail { color: var(--auf-dunkel); }
.fuss__unten {
  border-top-color: rgba(255, 255, 255, 0.14);
  color: var(--auf-dunkel-leise);
}
.fuss .marke-platzhalter { color: var(--ink); }   /* gelber Chip bleibt hell */
.fuss .offen-text { color: var(--auf-dunkel-leise); }
.fuss :focus-visible { outline-color: var(--hellblau); }

/* Die Formularspalte braucht keine eigene Gestaltung — sie ist der Platz,
   den das Formular bekommt. Die Regel steht trotzdem hier, damit die
   Klasse nicht ohne Deckung im Markup steht (pruefen.py meldet das). */
.kontaktseite__form { min-width: 0; }

/* In der schmalen linken Spalte der Kontaktseite bricht die zweispaltige
   Datenzeile zu hart um: „Ringstraße 44" stand dort in drei Zeilen. Dort
   also Bezeichnung über Wert, nicht daneben. */
.kontaktseite__daten .datenzeile {
  grid-template-columns: 1fr;
  gap: var(--a-1);
}
.kontaktseite__daten .datenblatt dt {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ══════════════════════════════════════════════════════════════════════════
   14. Stadtsilhouetten in den Ortskarten (15.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Je Stadt eine Silhouette in #0a4472, geliefert vom Auftraggeber. Sie sitzt
   am unteren Kartenrand über die volle Breite und läuft nach oben weich aus.

   Zwei Dinge halten den Text lesbar:
   1. Geringe Deckkraft. Die Silhouette ist Dunkelblau auf Weiß; bei 0,09
      ergibt sie einen hellen Blauschleier (etwa #e9eef3), auf dem die
      Textfarbe weiterhin deutlich über 4,5:1 liegt — unten gemessen.
   2. Eine Maske, die sie nach oben ausblendet. Ohne sie endet die Grafik
      an ihrer Oberkante in einer harten Linie quer durch den Text.
   ══════════════════════════════════════════════════════════════════════════ */
.hat-silhouette {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.silhouette {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: -1;
  width: 100%;
  height: auto;
  opacity: 0.09;
  pointer-events: none;
  /* Weicher Auslauf nach oben: unten volle Deckung, oben durchsichtig. */
  -webkit-mask-image: linear-gradient(to top, #000 55%, transparent 100%);
          mask-image: linear-gradient(to top, #000 55%, transparent 100%);
  transition: opacity var(--dauer) var(--kurve);
}
/* Beim Überfahren tritt die Stadt etwas hervor — ein Hinweis, dass die
   Karte zu dieser Stadt führt, ohne dass sie laut wird. */
.hat-silhouette:hover .silhouette { opacity: 0.15; }

/* Die langen Karten der Übersichtsseite sind höher und haben unten einen
   Knopf; die Silhouette darf dort kräftiger sein, weil mehr Weißraum über
   ihr liegt. Der Knopf bekommt einen hellen Grund, damit seine Kontur nicht
   in den Linien der Stadt verschwimmt. */
.ortlang.hat-silhouette { padding-bottom: calc(var(--a-6) + 2rem); }
.ortlang .knopf { position: relative; background: var(--grund); }

@media (prefers-reduced-motion: reduce) {
  .silhouette { transition: none; }
}

/* ── Gruppenbild im Haltungsband: rund 30 Prozent größer ─────────────────
   Auftraggeber, 15.09.2026. Die Bildspalte wächst von 34 auf 44rem; die
   Textspalte links behält dabei ihre Lesebreite von 46ch, denn der
   Fließtext ist ohnehin darauf begrenzt. */
/* ACHTUNG Kaskade — beide Regeln brauchen eine UNTERGRENZE.
   Sie stehen am Dateiende, also NACH der Mobilregel in Abschnitt 11
   (`@media (max-width: 940px) { grid-template-columns: 1fr }`). Ohne
   min-width überschrieben sie diese auf dem Telefon: Das Raster blieb
   zweispaltig, `minmax(0, 1fr)` neben einer 36rem-Spalte ließ der Textspalte
   fast nichts, und die Überschrift stand ein Buchstabe pro Zeile (gemessen
   15.09.2026). Merksatz: Eine Regel, die hinten angehängt wird, braucht
   dieselben Grenzen wie die, die sie ergänzt. */
@media (min-width: 1181px) {
  .haltung__raster { grid-template-columns: minmax(0, 1fr) minmax(0, 44rem); }
}
@media (min-width: 941px) and (max-width: 1180px) {
  /* Zwischen 940 und 1180px wäre eine 44rem-Spalte breiter als die Hälfte
     des Inhalts und drückte den Text auf unter 30 Zeichen je Zeile. */
  .haltung__raster { grid-template-columns: minmax(0, 1fr) minmax(0, 36rem); }
}
@media (max-width: 940px) {
  /* Einspaltig: Text über die volle Breite, das Bild darunter. Hier noch
     einmal ausdrücklich, damit die Reihenfolge in der Datei keine Rolle
     mehr spielt. */
  .haltung__raster { grid-template-columns: 1fr; gap: var(--a-6); }
  .haltung__text { padding-bottom: 0; }
  .haltung p { max-width: none; }
  .haltung__bild { max-width: none; width: 100%; margin: 0; padding-bottom: var(--a-6); }
  .haltung h2 { font-size: var(--t-2xl); }
}

/* Die Leiste blendet ihre Farben über. Wer weniger Bewegung wünscht,
   bekommt den Wechsel sofort — und Prüfaufnahmen im Headless-Browser
   bleiben sonst in einem Zwischenzustand hängen. */
@media (prefers-reduced-motion: reduce) {
  .kopf, .kopf__zeile, .marke__bild { transition: none !important; }
}

/* Die kompakten Ortskarten der Startseite waren so niedrig, dass die
   Silhouette fast ihre ganze Höhe einnahm — Frankfurts Hochhäuser standen
   hinter dem Titel. Mit mehr Raum unten steht die Stadt UNTER dem Text. */
.ortkarte.hat-silhouette { padding-bottom: calc(var(--a-5) + 3.2rem); }

/* ══════════════════════════════════════════════════════════════════════════
   15. WhatsApp-Knopf, fixiert unten rechts (15.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Offizielles Glyph auf WhatsApp-Grün #25D366. Form und Farbe des Logos
   bleiben unverändert — so verlangen es die Markenrichtlinien.

   Zum Kontrast: Weiß auf #25D366 liegt bei rund 2:1, Grün auf Weiß
   ebenso. Markenzeichen sind von WCAG 1.4.3 ausgenommen; damit der Knopf
   sich trotzdem vom hellen Seitengrund abhebt (1.4.11 verlangt 3:1 für
   Bedienelemente), trägt er einen dunklen Schatten. Der ändert das Logo
   nicht, zieht aber eine sichtbare Kante um den Kreis.
   ══════════════════════════════════════════════════════════════════════════ */
.wa-knopf {
  position: fixed;
  right: clamp(1rem, 0.6rem + 1.2vw, 1.75rem);
  /* safe-area: Auf dem iPhone läge der Knopf sonst auf dem Home-Balken. */
  bottom: max(clamp(1rem, 0.6rem + 1.2vw, 1.75rem), env(safe-area-inset-bottom));
  z-index: 60;                      /* über der Navigationsleiste (50) */
  width: 3.75rem; height: 3.75rem;  /* 60px — deutlich über 44px Fingerbreite */
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #25D366;
  color: #ffffff;
  box-shadow:
    0 0 0 1px rgba(7, 60, 34, 0.18),
    0 6px 18px rgba(7, 40, 25, 0.28);
  transition: transform var(--dauer) var(--kurve), box-shadow var(--dauer) var(--kurve);
}
.wa-knopf__logo { width: 58%; height: 58%; display: block; }
a.wa-knopf:hover {
  transform: translateY(-2px) scale(1.04);
  box-shadow:
    0 0 0 1px rgba(7, 60, 34, 0.22),
    0 10px 26px rgba(7, 40, 25, 0.34);
}
/* Fokus: ein Ring in Dunkelblau mit Abstand — auf dem grünen Kreis selbst
   wäre ein grüner oder weißer Ring nicht zu sehen. */
a.wa-knopf:focus-visible {
  outline: 3px solid var(--dunkelblau);
  outline-offset: 3px;
}

/* Ohne Nummer: sieht aus wie der Knopf, reagiert aber nicht. */
.wa-knopf.ist-offen { cursor: default; }
.wa-knopf__offen {
  position: absolute;
  right: 0; bottom: calc(100% + 0.4rem);
  white-space: nowrap;
  padding: 0.15rem 0.5rem;
  border-radius: 100px;
  font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  background: #ffd84d; color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .wa-knopf { transition: none; }
  a.wa-knopf:hover { transform: none; }
}
@media print { .wa-knopf { display: none; } }

/* Der fixierte WhatsApp-Knopf läge ganz unten gescrollt über den letzten
   Einträgen der Fußzeile — und damit auch über deren Fokusmarkierung, wenn
   jemand per Tastatur dorthin springt (WCAG 2.4.11: Fokus darf nicht
   verdeckt werden). Unten so viel Platz, wie der Knopf samt Abstand braucht. */
body:has(.wa-knopf) .fuss { padding-bottom: calc(var(--a-6) + 5rem); }
@supports not selector(:has(*)) {
  .fuss { padding-bottom: calc(var(--a-6) + 5rem); }
}

/* ══════════════════════════════════════════════════════════════════════════
   Pageloader (nur Startseite)
   ────────────────────────────────────────────────────────────────────────
   Dunkelblauer Vorhang, in der Mitte baut sich das Logo aus seinen Teilen
   auf. Reihenfolge: hellblauer Diagonalstreifen, obere Ecke, untere Ecke,
   dann INSAF Buchstabe für Buchstabe, zuletzt „Gebäudeservice".

   Die Wischer sind Rechtecke in einem <clipPath>. Sie starten außerhalb des
   Sichtfelds und fahren auf Null — dadurch wächst das jeweilige Teil herein,
   statt einfach aufzutauchen. Gerechnet wird in Nutzereinheiten des viewBox
   (496 × 137), NICHT in Prozent: Prozentwerte sind in SVG-Transformationen
   nicht erlaubt.

   .kein-js .lader: Ohne Skript wird der Vorhang gar nicht erst gezeigt —
   es nähme ihn ja auch niemand wieder weg. Bei „Bewegung reduzieren"
   entfernt main.js ihn sofort.
   ══════════════════════════════════════════════════════════════════════════ */
.lader {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--dunkelblau);
  animation: lader-weg .55s var(--kurve) 2.38s forwards;
}
.kein-js .lader { display: none; }

.lader__logo {
  width: min(62vw, 23rem);
  height: auto;
  /* Sanftes Setzen am Ende: Das fertige Logo atmet einmal auf seine Größe,
     damit der Aufbau einen Schlusspunkt hat statt einfach aufzuhören. */
  animation: lader-setzen .5s var(--kurve) 1.88s both;
}

/* ── Die drei Teile der Bildmarke ─────────────────────────────────────────
   Der Schein liegt auf der ganzen Gruppe, nicht auf den einzelnen Teilen:
   Drei überlappende Schatten addierten sich an den Nahtstellen zu hellen
   Kanten. Er kommt erst, wenn die Marke steht. */
.lader__marke {
  filter: drop-shadow(0 0 0 rgba(48, 142, 203, 0));
  animation: lader-schein .8s var(--kurve) 1.18s forwards;
}
@keyframes lader-schein {
  to { filter: drop-shadow(0 0 22px rgba(48, 142, 203, .55)); }
}

/* Jedes Teil deckt SEINE EIGENE Fläche auf: Die Prozentwerte in inset()
   beziehen sich bei SVG-Elementen auf die Fläche des Elements selbst
   (fill-box), nicht auf das ganze Logo.

   ── Was hier vorher falsch war (behoben 15.09.2026) ──────────────────────
   Die erste Fassung schob drei Rechtecke über den gesamten viewBox: 496
   Einheiten breit, 520 Einheiten Weg. Die Bildmarke belegt davon aber nur
   rund 95 Einheiten. Die Wischkante fuhr also fast nur über leere Fläche,
   und jedes Teil sprang innerhalb weniger Prozent seiner Laufzeit von
   unsichtbar auf vollständig. Gemessen über Bildfolgen: alle drei Teile
   gingen zwischen zwei Aufnahmen von 0 auf 100 Prozent. Aufgefallen ist es
   an der unteren Ecke, weil die zuletzt kommt und deshalb am deutlichsten
   „einfach da" war.

   inset(100% 0 0 0) heißt: oben um die volle Höhe eingerückt — sichtbar ist
   nichts, und der sichtbare Streifen wächst von unten nach oben. Die drei
   Startwerte unten geben so je eine Richtung vor; das gemeinsame keyframe
   fährt sie alle auf inset(0).

   Die Bildmarke hat VIER Teile, nicht drei: Diagonalstreifen, obere Ecke und
   unten je eine links und eine rechts. Die linke untere ist in der Logodatei
   ein polygon, alle anderen sind path — deshalb fiel sie beim Erzeugen
   zunaechst durch das Raster, siehe teile._logo_formen(). */
.lader__teil--mitte        { clip-path: inset(100% 0 0 0); animation: lader-aufdecken .52s var(--kurve) .12s forwards; }
.lader__teil--oben         { clip-path: inset(0 100% 0 0); animation: lader-aufdecken .40s var(--kurve) .54s forwards; }
.lader__teil--unten-links  { clip-path: inset(0 0 100% 0); animation: lader-aufdecken .38s var(--kurve) .74s forwards; }
.lader__teil--unten-rechts { clip-path: inset(0 0 0 100%); animation: lader-aufdecken .38s var(--kurve) .92s forwards; }

@keyframes lader-aufdecken { to { clip-path: inset(0 0 0 0); } }

/* ── INSAF, Buchstabe für Buchstabe ───────────────────────────────────────
   Die Verzögerungen stehen einzeln statt über eine Rechnung mit --n: Es sind
   genau fünf Buchstaben, und fünf Zeilen sind hier ehrlicher lesbar als eine
   Formel. Die Gruppe selbst hält nur den gemeinsamen Ursprung fest, damit
   das translateY der Buchstaben sich nicht am eigenen Kasten ausrichtet. */
.lader__wort { transform-box: fill-box; transform-origin: center; }

.lader__buchstabe {
  opacity: 0;
  transform: translateY(9px);
  animation: lader-buchstabe .40s var(--kurve) forwards;
}
.lader__buchstabe:nth-child(1) { animation-delay: 1.34s; }
.lader__buchstabe:nth-child(2) { animation-delay: 1.42s; }
.lader__buchstabe:nth-child(3) { animation-delay: 1.50s; }
.lader__buchstabe:nth-child(4) { animation-delay: 1.58s; }
.lader__buchstabe:nth-child(5) { animation-delay: 1.66s; }
@keyframes lader-buchstabe { to { opacity: 1; transform: translateY(0); } }

/* ── Die Zusatzzeile kommt als Ganzes ───────────────────────────────────── */
.lader__zusatz {
  opacity: 0;
  animation: lader-zusatz .45s var(--kurve) 1.84s forwards;
}
@keyframes lader-zusatz { to { opacity: 1; } }

@keyframes lader-setzen {
  from { transform: scale(.965); }
  to   { transform: scale(1); }
}

/* Der Vorhang hebt sich: verblassen UND leicht nach oben ziehen, damit es
   nach Weggehen aussieht und nicht nach Ausblenden. */
@keyframes lader-weg {
  to { opacity: 0; transform: translateY(-2.5%); visibility: hidden; }
}

/* Während der Vorhang liegt, wird nicht gescrollt — sonst steht man beim
   Aufdecken mitten auf der Seite. scrollbar-gutter hält die Breite stabil,
   damit das Wegnehmen keinen Sprung erzeugt. */
.laedt { overflow: hidden; scrollbar-gutter: stable; }

@media (prefers-reduced-motion: reduce) {
  .lader { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Titelbild der Unterseiten (16.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Kürzere Schwester der Startseiten-Hero. Gleiche Technik: negatives
   margin-top zieht den Abschnitt unter die klebende Kopfzeile, das padding
   gibt dem Inhalt den Platz zurueck.

   Der Verlauf ist KRAEFTIGER als auf der Startseite. Grund: Das Motiv der
   Leistungsseite ist sehr hell (weisse Handschuhe, Fensterlicht), und der
   Text steht darauf links unten.

   Wie kraeftig, ist gemessen, nicht geschaetzt — Glyphenpixel gegen den Grund
   an derselben Stelle (zwei Aufnahmen, die zweite mit color:transparent).
   Mit dem ersten Entwurf (0.94/0.86/0.58) lag der Lead im unguenstigsten
   Prozent des Grundes bei 3,82:1 und die Augenzeile bei 3,94:1 — beide unter
   den geforderten 4,5:1. Mit den Werten unten sind es 6,12:1 und 6,75:1, die
   h1 liegt bei 7,75:1 (Schwelle 3:1, weil gross). Wer hier aufhellt, misst
   bitte nach: Das Motiv ist an der rechten Textkante am hellsten.
   ══════════════════════════════════════════════════════════════════════════ */
.titel {
  position: relative;
  z-index: 0;
  isolation: isolate;
  /* Der Wert muss die GANZE Leiste abdecken: ihre Zeilenhoehe UND die Luft
     darueber und darunter. Hier stand zuerst nur --kopf-hoehe — wie einst
     bei .hero. Ergebnis war derselbe Fehler: ein weisser Streifen ueber dem
     Bild, gemessen 44px (Titelbild begann bei y=44 statt 0). */
  margin-top: calc(-1 * (var(--kopf-hoehe) + var(--kopf-luft) * 2));
  /* Der obere Innenabstand gibt dem Inhalt den Platz wieder zurueck. */
  padding-block: calc(var(--kopf-hoehe) + var(--kopf-luft) * 2 + var(--a-9)) var(--a-9);
  min-height: clamp(20rem, 30vw, 27rem);
  display: grid;
  align-items: end;
  overflow: hidden;
  color: var(--auf-dunkel);
}
.titel__bild { position: absolute; inset: 0; z-index: -2; display: block; }
.titel__bild img { width: 100%; height: 100%; object-fit: cover; display: block; }

.titel::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(100deg,
      rgba(8, 46, 78, 0.96) 0%,
      rgba(8, 46, 78, 0.93) 38%,
      rgba(9, 57, 96, 0.82) 62%,
      rgba(10, 68, 114, 0.38) 100%),
    linear-gradient(180deg,
      rgba(10, 68, 114, 0.30) 0%,
      rgba(10, 68, 114, 0.10) 34%,
      rgba(10, 68, 114, 0.28) 100%);
}

/* Die Textbreite gehoert an die KINDER, nicht an den Traeger.
   .titel__inhalt traegt auch die Klasse .inhalt (Breite 1200px, margin-inline:
   auto). Ein max-width hier verkleinert genau diesen Kasten — und weil das
   auto-Margin bleibt, rueckt er in die Mitte. Gemessen: h1 begann bei x=265
   statt bei x=33 wie auf der Startseite, also sichtbar eingerueckt gegenueber
   der Navigation. */
.titel__inhalt > * { max-width: 46rem; }

/* Der Abschnitt unter dem Titelbild bekommt oben denselben Abstand wie unten.
   .band--erste ist sonst oben knapper (--a-7), weil es dort direkt unter der
   Kopfleiste sitzt — unter einem Titelbild wirkte das einseitig gedrueckt
   (gemessen 48px oben gegen 96px unten). */
.titel + .band--erste { padding-top: var(--band); }
.titel__ort {
  font-size: var(--t-s);
  font-weight: var(--gewicht-ui);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #edf2f7;
  margin-bottom: var(--a-3);
}
.titel h1 { color: #ffffff; margin-bottom: var(--a-4); }
.titel__lead {
  color: #edf2f7;
  font-size: var(--t-l);
  max-width: 44rem;
  margin-bottom: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   Weitere Einsatzorte — kleine Kacheln
   ────────────────────────────────────────────────────────────────────────
   Bewusst schlichter als .ortkarte: Zu diesen Orten gibt es keine
   Silhouette und keine eigene Seite, also auch keinen Verweis. Eine Kachel,
   die aussieht wie ein Link, aber keiner ist, waere schlechter als eine,
   die von vornherein wie ein Eintrag aussieht.
   ══════════════════════════════════════════════════════════════════════════ */
.ortchips {
  list-style: none;
  margin: 0 0 var(--a-6);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(13rem, 100%), 1fr));
  gap: var(--a-3);
}
.ortchip {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--a-4) var(--a-4);
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  background: #ffffff;
}
.ortchip__name { font-weight: 600; color: var(--ink); }
.ortchip__meta { font-size: var(--t-s); color: var(--ink-ruhig); }

.ortchips__nachsatz {
  margin: 0 auto;
  max-width: var(--breite-text);
  text-align: center;
  color: var(--ink-ruhig);
}

/* ══════════════════════════════════════════════════════════════════════════
   Hellblaues Band, Bento-Raster, Zielgruppen-Kapseln (16.09.2026)
   ────────────────────────────────────────────────────────────────────────
   #308ecb traegt Weiss nur mit 3,66:1 — das reicht fuer GROSSEN Text
   (Schwelle 3:1), nicht fuer Fliesstext (4,5:1). Auf diesem Band steht
   deshalb nur die Ueberschrift in Weiss; alles Kleinteilige bringt seine
   eigene helle Flaeche mit (Pille, Kapseln). Das ist dieselbe Hausregel wie
   sonst auf der Seite: Hellblau traegt keinen Fliesstext.
   ══════════════════════════════════════════════════════════════════════════ */
.band--hellblau { background: var(--hellblau); }
.band--hellblau h2 { color: #ffffff; }
.band--hellblau .kopf-mitte p { color: #eaf4fb; }
/* Umrisspille auch auf Blau: weisser Rand, weisse Schrift, keine Flaeche
   (Auftraggeber, 16.09.2026).

   Weisse Schrift auf #308ecb misst 3,59:1. Das reicht NICHT fuer die sonst
   15px grosse Pillenschrift (Schwelle 4,5:1) — wohl aber, sobald sie als
   grosser Text zaehlt: ab 18,66px bei fettem Schnitt liegt die Schwelle bei
   3:1. Deshalb steht die Pille auf diesen beiden Baendern auf 1.1875rem
   (19px) statt 0.9375rem. Der Unterschied faellt kaum auf, die Schrift bleibt
   lesbar. Wer hier auf 15px zurueckgeht, nimmt einen Kontrastfehler in Kauf. */
.band--hellblau .pille {
  background: none;
  border-color: #ffffff;
  color: #ffffff;
  font-size: 1.1875rem;
  padding: calc(0.45rem - 2px) calc(1.5rem - 2px);
}

/* ── Bento ─────────────────────────────────────────────────────────────────
   Vier Spalten, feste Zeilenhoehe. Die Formen greifen erst ab 900px — auf
   dem Telefon ist ein Bento-Raster eine Spalte, sonst wird jedes Feld zum
   Briefmarkenbild. */
.bento {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--a-4);
}
.bento__feld {
  margin: 0;
  overflow: hidden;
  border-radius: 20px;
  background: var(--dunkelblau);     /* sichtbar, solange das Bild laedt */
  aspect-ratio: 4 / 3;
}
.bento__feld img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .5s var(--kurve);
}
.bento__feld:hover img { transform: scale(1.04); }

@media (min-width: 900px) {
  .bento {
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 13rem;
  }
  .bento__feld { aspect-ratio: auto; }
  .bento__feld--gross { grid-column: span 2; grid-row: span 2; }
  .bento__feld--hoch  { grid-column: span 1; grid-row: span 2; }
  .bento__feld--breit { grid-column: span 2; grid-row: span 1; }
  .bento__feld--klein { grid-column: span 1; grid-row: span 1; }
}

/* ── Zielgruppen ─────────────────────────────────────────────────────────── */
.kapseln {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--a-3);
}
.kapsel {
  background: #ffffff;
  color: var(--ink);
  border-radius: 100px;
  padding: var(--a-3) var(--a-5);
  font-weight: 600;
  font-size: var(--t-s);
  line-height: 1.3;
  /* Mittig, nicht linksbuendig: Auf schmalen Geraeten bricht „Hausverwaltungen
     und Eigentuemergemeinschaften" auf zwei Zeilen um, und die kuerzere stand
     dann links an der Rundung statt in der Mitte. Auf dem Desktop aendert die
     Regel nichts — dort passt jede Kapsel in eine Zeile. */
  text-align: center;
  box-shadow: 0 2px 10px rgba(6, 34, 58, .10);
}

/* ══════════════════════════════════════════════════════════════════════════
   Landeseite /ihr-gebaeudeservice.html (16.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Baut auf den vorhandenen Bausteinen auf (.titel, .band, .schritte,
   .kapseln, .bento). Eigenes CSS gibt es nur fuer das, was es sonst
   nirgends gibt: die Vertrauenszeile, das Nutzenraster, die
   Leistungs-Chips und den Abschlussblock.
   ══════════════════════════════════════════════════════════════════════════ */

/* Der Kopf traegt hier keine Navigation — der Knopf rueckt an den rechten
   Rand, weil .marke schon margin-right:auto hat. */
.kopf--schlank .kopf__zeile { gap: var(--a-4); }
.kopf__ruf { flex: 0 0 auto; }

/* Das Titelbild der Landeseite ist hoeher als das der Unterseiten: Es traegt
   Ueberschrift, Lead, zwei Knoepfe und die Vertrauenszeile. */
.titel--lp { min-height: clamp(30rem, 74vh, 44rem); }
.titel--lp .titel__inhalt > * { max-width: 52rem; }
/* Auf 390px trennte die Ueberschrift zu „Gebaeudeser-vice": text-wrap:balance
   und hyphens:auto zusammen zerlegen das lange Kompositum, obwohl es als
   Ganzes in die Zeile passte. hyphens:manual verbietet die Trennung, und die
   etwas flachere Kurve sorgt dafuer, dass „Ihr Gebaeudeservice" schmal auch
   wirklich hineingeht (gemessen: 312px in einer 342px-Spalte). */
.titel--lp h1 {
  font-size: clamp(2rem, 1.3rem + 3.2vw, 4rem);
  hyphens: manual;
}
.titel--lp .knopfreihe { margin-top: var(--a-6); }

.vertrauen {
  list-style: none;
  margin: var(--a-6) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--a-3) var(--a-5);
}
.vertrauen__punkt {
  position: relative;
  padding-left: 1.6rem;
  color: #edf2f7;
  font-size: var(--t-s);
  font-weight: var(--gewicht-ui);
}
/* Haken aus zwei Strichen statt eines Bildes — eine Datei weniger, und er
   erbt die Schriftfarbe. */
.vertrauen__punkt::before,
.vertrauen__punkt::after {
  content: "";
  position: absolute;
  background: var(--hellblau);
  border-radius: 1px;
}
.vertrauen__punkt::before { left: 2px;   top: 0.66em; width: 0.42rem; height: 2px; transform: rotate(45deg); }
.vertrauen__punkt::after  { left: 0.3rem; top: 0.58em; width: 0.72rem; height: 2px; transform: rotate(-52deg); }

/* ── Nutzenraster ──────────────────────────────────────────────────────── */
.nutzen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: var(--a-5);
}
.nutzen__punkt {
  padding: var(--a-5);
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  background: #ffffff;
}
.nutzen__punkt h3 { font-size: var(--t-l); margin-bottom: var(--a-2); }
.nutzen__punkt p { color: var(--ink-ruhig); margin-bottom: 0; font-size: var(--t-s); }

/* ── Leistungs-Chips ───────────────────────────────────────────────────────
   Verweise, keine Kapseln: Sie fuehren auf die jeweilige Leistungsseite und
   muessen deshalb auch wie etwas Anklickbares aussehen. */
.leistungschips {
  list-style: none;
  margin: 0 0 var(--a-6);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--a-3);
}
.leistungschip {
  display: inline-block;
  background: #ffffff;
  color: var(--ink);
  text-decoration: none;
  border: 1px solid var(--linie);
  border-radius: 100px;
  padding: var(--a-3) var(--a-5);
  font-weight: 600;
  font-size: var(--t-s);
  transition: border-color var(--dauer) var(--kurve), color var(--dauer) var(--kurve),
              transform var(--dauer) var(--kurve);
}
.leistungschip:hover,
.leistungschip:focus-visible {
  border-color: var(--hellblau);
  color: var(--hellblau-text);
  transform: translateY(-2px);
}

/* ── Funnel auf dunklem Band ───────────────────────────────────────────────
   Der Assistent bringt seine eigene helle Flaeche mit; hier bekommt er nur
   eine Hoechstbreite und die Mitte. */
.lp-funnel { max-width: 46rem; margin-inline: auto; }

/* ── Abschluss ─────────────────────────────────────────────────────────── */
.lp-abschluss { text-align: center; }
.lp-abschluss h2 { color: #ffffff; }
.lp-abschluss__text {
  color: #ffffff;
  font-size: var(--t-xl);      /* ab 24px zaehlt Weiss auf #308ecb als grosser
                                  Text — Schwelle 3:1 statt 4,5:1 */
  max-width: 34rem;
  margin: 0 auto var(--a-5);
}
.lp-abschluss__nap {
  margin: var(--a-6) 0 0;
  color: #ffffff;
  font-size: var(--t-l);       /* bewusst nicht kleiner, siehe oben */
}

/* ══════════════════════════════════════════════════════════════════════════
   Korrekturen fuer die Landeseite (16.09.2026, nachgemessen)
   ══════════════════════════════════════════════════════════════════════════ */

/* 1. Der zentrierte Kopf auf farbigen Baendern.
      .kopf-mitte p setzt --ink-ruhig und ist spezifischer als .band--dunkel p
      — auf Dunkelblau ergab das 2,1:1, praktisch unlesbar. */
.band--dunkel .kopf-mitte p { color: var(--auf-dunkel-leise); }
/* Auf Hellblau traegt Weiss nur 3,59:1. Damit ein Absatz dort zulaessig ist,
   muss er als grosser Text zaehlen — deshalb --t-xl und nicht kleiner. */
.band--hellblau .kopf-mitte p { color: #ffffff; font-size: var(--t-xl); }

/* 2. Der Anfrage-Assistent auf dunklem Band.
      Er bringt eine eigene HELLE Karte mit. Die Regeln von .band--dunkel
      faerben aber alles darin hell ein — gemessen: Titel #f6f6f6 auf weisser
      Flaeche, Zaehler #bcd0e0 auf weisser Flaeche, beides unsichtbar, und der
      Weiter-Knopf hatte dunkle Schrift auf hellgrauer Flaeche.
      Hier bekommt die Karte ihre eigenen Farben zurueck. Die Werte sind die,
      die der Assistent auf der Startseite ohnehin hat. */
.band--dunkel .funnel,
.band--dunkel .funnel h2,
.band--dunkel .funnel h3,
.band--dunkel .funnel legend,
.band--dunkel .funnel dt,
.band--dunkel .funnel dd { color: var(--ink); }
.band--dunkel .funnel p { color: var(--ink-ruhig); }
.band--dunkel .funnel .funnel__zaehler { color: var(--ink-leise); }
.band--dunkel .funnel .knopf { background: var(--akzent); color: #ffffff; }
.band--dunkel .funnel .knopf:hover { background: var(--akzent-tief); color: #ffffff; }
.band--dunkel .funnel .knopf--leise {
  background: transparent;
  color: var(--ink);
  border-color: var(--rand);
}
.band--dunkel .funnel a:not(.knopf) { color: var(--akzent); }

/* 3. Der Verlauf ueber dem Titelbild der Landeseite.
      Die Werte von .titel sind fuer das sehr helle Leistungsmotiv gebaut; auf
      dem dunkleren Hero-Foto liess das vom Bild praktisch nichts uebrig.
      Hier ist er schwaecher — was der Kontrast hergibt, ist unten gemessen. */
.titel--lp::before {
  background:
    linear-gradient(100deg,
      rgba(8, 46, 78, 0.94) 0%,
      rgba(8, 46, 78, 0.89) 44%,
      rgba(9, 57, 96, 0.70) 70%,
      rgba(10, 68, 114, 0.18) 100%),
    linear-gradient(180deg,
      rgba(10, 68, 114, 0.34) 0%,
      rgba(10, 68, 114, 0.08) 38%,
      rgba(10, 68, 114, 0.30) 100%);
}

/* Schlanke Fusszeile der Landeseite: zwei Spalten statt vier.
   Weniger Inhalt braucht auch weniger Hoehe — sonst steht unter der
   Landeseite ein Block, der leerer wirkt als der Rest der Seite. */
.fuss--schlank { padding-block: var(--a-8) var(--a-6); }
.fuss__schlank {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: var(--a-6);
}

/* ══════════════════════════════════════════════════════════════════════════
   Ueber uns: Text links, Bild rechts (16.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Zwei Spalten ab 900px, darunter gestapelt — Text zuerst, weil er die
   Aussage traegt und das Bild nur begleitet.
   ══════════════════════════════════════════════════════════════════════════ */
.ueberuns {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--a-6);
  align-items: center;
}
@media (min-width: 900px) {
  .ueberuns { grid-template-columns: 1fr 1fr; gap: clamp(2rem, 4vw, 4rem); }
}
/* Die h1 steht hier in einer halbbreiten Spalte. Mit der vollen --t-3xl
   (64px) passte „INSAF Gebaeudeservice" nicht in die Zeile und wurde zu
   „Gebaeu-deservice" getrennt — derselbe Fall wie im Hero der Landeseite.
   hyphens:manual verbietet die Trennung, die flachere Kurve sorgt dafuer,
   dass das laengste Wort hineingeht (gemessen: 499px in 590px Spalte). */
.ueberuns__text h1 {
  font-size: clamp(1.875rem, 1.4rem + 2.2vw, 3rem);
  hyphens: manual;
}
.ueberuns__text p { color: var(--ink-ruhig); max-width: var(--breite-text); }
.ueberuns__text p:last-child { margin-bottom: 0; }

/* Der Freisteller hat einen durchsichtigen Hintergrund. Abgerundete Ecken
   brauchen aber eine Flaeche, sonst rundet man nichts — deshalb liegt die
   Toenung auf der <figure>, nicht auf dem Bild. */
.ueberuns__bild {
  margin: 0;
  border-radius: 24px;
  overflow: hidden;
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--hellblau) 28%, #ffffff) 0%,
    color-mix(in srgb, var(--dunkelblau) 16%, #ffffff) 100%);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  aspect-ratio: 4 / 3;
}
.ueberuns__bild picture,
.ueberuns__bild img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom center;
}

/* ══════════════════════════════════════════════════════════════════════════
   Einwilligungsbanner — unten links (17.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Erscheint nur, wenn es etwas zu entscheiden gibt (siehe
   fakten.EINWILLIGUNG_DIENSTE). Bewusst als schmale Karte am unteren linken
   Rand statt als Balken ueber die ganze Breite: Man soll die Seite lesen
   koennen, waehrend man entscheidet.

   Der WhatsApp-Knopf sitzt unten RECHTS — die beiden kommen sich nicht ins
   Gehege.
   ══════════════════════════════════════════════════════════════════════════ */
.cc {
  position: fixed;
  left: var(--a-5);
  bottom: var(--a-5);
  z-index: 120;
  width: min(24rem, calc(100vw - 2 * var(--a-5)));
  padding: var(--a-5);
  background: #ffffff;
  border: 1px solid var(--linie);
  border-radius: var(--rundung);
  box-shadow: 0 14px 40px rgba(6, 34, 58, .20);
  animation: cc-auf .32s var(--kurve) both;
}
@keyframes cc-auf {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.cc__titel { font-size: var(--t-l); margin-bottom: var(--a-2); }
.cc__text {
  font-size: var(--t-s);
  color: var(--ink-ruhig);
  margin-bottom: var(--a-4);
}

.cc__dienste { display: grid; gap: var(--a-3); margin-bottom: var(--a-4); }
.cc__dienst { display: flex; gap: var(--a-3); align-items: flex-start; cursor: pointer; }
.cc__dienst input { margin-top: 0.2em; flex: 0 0 auto; }
.cc__dienst-text { font-size: var(--t-s); color: var(--ink-ruhig); line-height: 1.4; }
.cc__dienst-text strong { display: block; color: var(--ink); }

.cc__knoepfe { display: flex; flex-wrap: wrap; gap: var(--a-2); align-items: center; }
/* „Auswahl speichern" ist absichtlich KEIN Knopf im Markenton: Die drei
   Moeglichkeiten muessen gleichwertig aussehen. Ein bunter „Alle zulassen"
   neben zwei grauen Links waere eine Lenkung, und genau die ist unzulaessig. */
.cc__auswahl {
  background: none;
  border: 0;
  padding: var(--a-2);
  font: inherit;
  font-size: var(--t-s);
  color: var(--ink-ruhig);
  text-decoration: underline;
  cursor: pointer;
}
.cc__auswahl:hover { color: var(--ink); }

/* Der Widerruf muss erreichbar bleiben (Art. 7 Abs. 3 DSGVO). */
.cc-wieder {
  position: fixed;
  left: var(--a-5);
  bottom: var(--a-5);
  z-index: 119;
  padding: var(--a-2) var(--a-4);
  background: #ffffff;
  color: var(--ink-ruhig);
  border: 1px solid var(--linie);
  border-radius: 100px;
  font: inherit;
  font-size: var(--t-xs);
  cursor: pointer;
  box-shadow: var(--schatten-1);
}
.cc-wieder:hover { color: var(--ink); border-color: var(--rand); }

@media (max-width: 600px) {
  .cc { left: var(--a-3); right: var(--a-3); bottom: var(--a-3); width: auto; }
  .cc-wieder { left: var(--a-3); bottom: var(--a-3); }
}

/* ══════════════════════════════════════════════════════════════════════════
   16. Fußzeile unten: Widerruf und Agenturnachweis (17.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Auftraggeber: unten rechts der Hinweis auf die Agentur, dazu ein
   Widerrufsknopf.

   Die unterste Zeile war ein schlichtes flex mit space-between und einem
   einzigen Kind. Jetzt sind es zwei Gruppen: links Copyright und
   Widerrufsknopf, rechts der Nachweis. Ohne die innere Gruppe rutschte der
   Knopf zwischen beide Enden und stand mitten im Nichts.

   Gerechnete Kontraste auf --grund-tief (#0a4472):
     Knopftext  #f6f6f6   9,33:1  ✓
     Knopfrand  rgba(255,255,255,.45) über #0a4472 ≈ #7ca1bf → 3,4:1 ✓ (3:1)
     Nachweis   #bcd0e0   6,36:1  ✓
   ══════════════════════════════════════════════════════════════════════════ */
.fuss__unten-links {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--a-3) var(--a-5);
}
.fuss__agentur {
  margin: 0;
  font-size: var(--t-xs);
  color: var(--auf-dunkel-leise);
  text-align: right;
}
.fuss__agentur a { text-decoration: underline; text-underline-offset: 2px; }
.fuss__agentur a:hover { color: #ffffff; }

/* .fuss a ist 0-1-1 und schlug die einfache Klasse 0-1-0: Der Knopf bekam
   die leise Textfarbe der Fußverweise statt seiner eigenen. Gemessen am
   17.09.2026 — rgb(188,208,224) statt #f6f6f6. Deshalb hier mit .fuss davor,
   nicht mit !important. */
.fuss .fuss__widerruf {
  display: inline-flex; align-items: center; gap: 0.5em;
  padding: 0.45em 1em;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 100px;
  color: var(--auf-dunkel);
  /* Der Fuß setzt text-decoration: none auf alle Verweise; hier wäre sie
     ohnehin falsch — der Knopf ist als Fläche erkennbar, nicht als Wort. */
  line-height: 1.2;
  transition: background var(--zeit-2) var(--kurve),
              border-color var(--zeit-2) var(--kurve);
}
.fuss .fuss__widerruf:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.75);
  color: #ffffff;
  text-decoration: none;          /* sonst greift .fuss a:hover */
}
.fuss__widerruf-icon { width: 1.05em; height: 1.05em; flex: none; }

/* Die schlanke Fußzeile der Landeseite trägt dieselbe Zeile. Sie ist
   schmaler, deshalb dort untereinander statt nebeneinander. */
@media (max-width: 700px) {
  .fuss__unten { flex-direction: column; align-items: flex-start; }
  .fuss__agentur { text-align: left; }
}

/* ══════════════════════════════════════════════════════════════════════════
   17. Widerrufsseite (17.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Gleicher Aufbau wie die Kontaktseite: links die Angaben, rechts das
   Formular. Neu sind der Warnkasten und der erzeugte Text.

   Der Warnkasten ist NICHT der gelbe Platzhalterkasten. Der sagt „hier
   fehlt noch etwas", dieser sagt „was Sie hier tun, kommt nicht an" — bei
   einer laufenden Frist ein Unterschied ums Ganze. Deshalb eine eigene,
   kräftigere Farbe.

   Gerechnete Kontraste (nicht geschätzt):
     Text  #20313b auf #fdecea  11,74:1  ✓
     Rand  #b3261e auf #fdecea   5,72:1  ✓
     Rand  #b3261e auf #ffffff   6,54:1  ✓ — die Kante grenzt außen an Weiß
   ══════════════════════════════════════════════════════════════════════════ */
.hinweis--warnung {
  background: #fdecea;
  border: 1px solid #b3261e;
}
.hinweis--warnung p { margin-bottom: 0; color: var(--ink); font-size: var(--t-s); }
.hinweis--warnung .marke-platzhalter {
  margin-bottom: var(--a-2);
  background: #b3261e;
  color: #ffffff;                 /* 6,54:1 */
}

/* Zwei Datumsfelder nebeneinander, solange Platz ist. Unter 30rem stehen
   sie untereinander — ein date-Feld unter 8rem ist in Safari unbedienbar. */
.kform__zwei {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
  gap: 0 var(--a-4);
}
/* Gemessen am 17.09.2026, 1280×900: Das rechte Datumsfeld reichte bis x=1240,
   der fixierte WhatsApp-Knopf beginnt bei x=1195 — und in genau dieser Ecke
   sitzt bei einem date-Feld das Kalendersymbol. Wer es anklickte, traf
   WhatsApp. Ein Datumsfeld braucht keine 390 px; mit 13rem endet es bei
   x≈1058 und die Kollision ist geometrisch ausgeschlossen, nicht bloß
   unwahrscheinlich gemacht. */
.kform__zwei input[type="date"] { max-width: 13rem; }
.kform__feld input[type="date"] {
  width: 100%;
  padding: 0.7em 0.9em;
  border: 1px solid var(--rand);
  border-radius: var(--rundung-klein);
  background: #ffffff;
  font: inherit;
  color: var(--ink);
  /* Ohne appearance greift Safari zum eigenen Innenleben und das Feld wird
     schmaler als seine Box — dasselbe Muster wie beim Fragebogen im Portal. */
  appearance: none;
  min-height: 2.9rem;
}
.kform__feld input[type="date"]:focus-visible { border-color: var(--dunkelblau); }

.kform__rechtshinweis {
  font-size: var(--t-xs);
  color: var(--ink-ruhig);
  margin: var(--a-4) 0 0;
}
.kform__rechtshinweis a { color: var(--dunkelblau); }

/* Der erzeugte Widerruf. Monospace und Zeilenumbrüche wie eingegeben: Was
   hier steht, soll genau so auf dem Papier landen. */
.widerruf__text {
  margin: var(--a-4) 0 0;
  padding: var(--a-4);
  background: var(--grund-grau);
  border: 1px solid var(--linie);
  border-radius: var(--rundung-klein);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--t-xs);
  line-height: 1.6;
  color: var(--ink);              /* #20313b auf #f4f6f7 = 12,39:1 */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.widerruf__aktionen {
  display: flex; flex-wrap: wrap; gap: var(--a-3);
  margin-top: var(--a-4);
}
.wform__ende { max-width: none; }

/* Gedruckt wird nur die Erklärung. Wer den Text zu Papier bringt, will ihn
   im Umschlag haben — nicht die Navigation, nicht den Fuß, nicht den
   WhatsApp-Knopf. */
@media print {
  .wform__ende .widerruf__aktionen,
  body:has(.wform) .kopf,
  body:has(.wform) .fuss,
  body:has(.wform) .wa-knopf,
  body:has(.wform) .band__kopf,
  body:has(.wform) .kontaktseite__daten,
  body:has(.wform) .hinweis--warnung { display: none; }
  .widerruf__text { border: 0; background: transparent; padding: 0; font-size: 11pt; }
}

/* Solange jemand in einem Formular arbeitet, hat der fixierte WhatsApp-Knopf
   dort nichts zu suchen: Er überlagert Felder und fängt Klicks ab, die dem
   Formular galten. Bei einem fristgebundenen Widerruf wiegt das schwer.

   :focus-within statt JavaScript — der Knopf kommt zurück, sobald der Fokus
   das Formular verlässt. `visibility` zusätzlich zu `opacity`, sonst bliebe
   er für Klicks und für Vorlesesoftware weiter da. */
body:has(.kform:focus-within) .wa-knopf {
  opacity: 0;
  visibility: hidden;
}

/* ══════════════════════════════════════════════════════════════════════════
   18. Versand: Honigtopf und Formularmeldung (17.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Der Honigtopf ist NICHT display:none und nicht hidden — beides lesen
   Bots als „ignorieren". Er wird aus dem Sichtfeld geschoben und aus der
   Tabulatorfolge genommen (tabindex="-1" im Markup), aria-hidden hält ihn
   von Vorlesesoftware fern.

   `position: absolute` statt `left: -9999px` am Element selbst: So bleibt
   das Feld für einen Bot, der CSS auswertet, unauffällig, verschiebt aber
   nichts im Layout und erzeugt keine waagerechte Bildlaufleiste.
   ══════════════════════════════════════════════════════════════════════════ */
.honigtopf {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Meldung für das ganze Formular (Dienst nicht erreichbar, zu viele
   Anfragen). Sie steht ÜBER dem Absendeknopf, nicht darunter: Wer auf
   „Senden" gedrückt hat, schaut dorthin zurück, nicht weiter nach unten. */
.kform__fehler--form,
.funnel__fehler--form {
  margin-top: var(--a-4);
  font-size: var(--t-s);
}
.kform__fehler--form:empty,
.funnel__fehler--form:empty { margin: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   19. Zusage statt Warnung (17.09.2026)
   ────────────────────────────────────────────────────────────────────────
   Der Hinweis über dem Widerrufsformular sagt seit dem Anschluss des
   Versands etwas Positives: dass der Widerruf ankommt und bestätigt wird.
   In der gelben Platzhalterfarbe gelesen wirkte das wie ein Mangel — Gelb
   heißt auf dieser Seite „hier fehlt noch etwas".

   Deshalb ein eigener Kasten in der Markenfarbe. Gerechnete Kontraste:
     Text  #20313b auf #e8f2fa   11,84:1  ✓
     Rand  #0a4472 auf #e8f2fa    8,89:1  ✓
     Rand  #0a4472 auf #ffffff   10,08:1  ✓ — die Kante grenzt außen an Weiß
     Marke #ffffff auf #0a4472   10,08:1  ✓
   ══════════════════════════════════════════════════════════════════════════ */
.hinweis--zusage {
  background: #e8f2fa;
  border: 1px solid var(--dunkelblau);
}
.hinweis--zusage p { margin-bottom: 0; color: var(--ink); font-size: var(--t-s); }
.marke-zusage {
  display: inline-block;
  margin-bottom: var(--a-2);
  padding: 0.2em 0.7em;
  border-radius: 100px;
  background: var(--dunkelblau);
  color: #ffffff;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
