/*! don-sergio Transport & Umzüge - gebuendelt von scripts/build.mjs. Quelle: src/styles/ */
/* ===== styles/00-fonts.css ===== */
/* =========================================================================
   Schrift: Inter, aus dem eigenen Webspace
   Bis zum 20.09.2026 kam die Schrift von fonts.googleapis.com. Dabei ging
   die IP-Adresse jeder Besucherin an Google in die USA - ohne Einwilligung
   und ohne Not. Genau dafuer gab es in Deutschland eine Abmahnwelle und
   ein Schadenersatzurteil (LG Muenchen I, 3 O 17493/20). Seitdem liegen
   die Dateien unter assets/fonts/ und die Seite stellt keine einzige
   Anfrage mehr an einen fremden Server.

   Es sind variable Schnitte: eine Datei deckt 400 bis 800 ab, statt fuenf
   einzelnen Gewichten. Zusammen sind das rund 430 kB, geladen werden aber
   nur die Bereiche, die der Text tatsaechlich braucht - dafuer sorgt
   unicode-range. Deutscher Text kommt mit latin aus (73 kB).

   font-display: swap - der Text steht sofort in der Systemschrift da und
   wird ersetzt, sobald Inter geladen ist. Lieber ein kurzer Wechsel als
   eine Sekunde leere Flaeche.

   Die unicode-range-Werte sind unveraendert aus der Google-Fonts-Antwort
   uebernommen. Nicht von Hand kuerzen: fehlt ein Bereich, faellt der Text
   dort stumm auf die Systemschrift zurueck.

   Lizenz: SIL Open Font License 1.1, siehe assets/fonts/LICENSE.txt. Die
   Datei wird mit ausgeliefert - das verlangt die Lizenz beim Selbsthosten.
   ========================================================================= */

/* ---- aufrecht, 400-800 --------------------------------------------- */

/* latin-ext: osteuropaeische Zeichen, erweiterte Diakritika, Waehrungen */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin: deckt Deutsch samt Umlauten und Eszett ab - der Normalfall */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---- kursiv, 700-800 ------------------------------------------------
   Nur die fetten Schnitte, wie schon bei der externen Einbindung: die
   Seite setzt kursiv ausschliesslich in Auszeichnungen.                 */

@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 700 800;
  font-display: swap;
  src: url('../fonts/inter-latin-ext-italic.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 700 800;
  font-display: swap;
  src: url('../fonts/inter-latin-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ===== styles/01-tokens.css ===== */
/* =========================================================================
   Design Tokens
   Alle Werte sind aus der Referenz-Vorlage (reference/web-inspo.jpeg)
   ausgemessen. Die Vorlage ist 1024 px breit; das Design wird auf einem
   1280-px-Viewport 1:1 abgebildet (Faktor 1.25). Ab 1200 px greifen die
   Referenzwerte, darunter skaliert die Skala in definierten Stufen.
   ========================================================================= */

:root {
  color-scheme: light;

  /* ---- Markenfarben: eine Blau-Skala, kein zweiter Akzent ------------- */
  --navy-900: #0f2452;
  --navy-800: #14336f;   /* Primaerbutton, Nav-Unterstrich                */
  --navy-700: #1a3e85;   /* Hover Primaerbutton                           */
  --blue-700: #1e4290;   /* gefuellte Icon-Marken (Checks, Card-Badges)   */
  --blue-600: #2a55a8;   /* Eyebrows, Textlinks, Icon-Ringe               */
  --blue-500: #3568c4;   /* Hover Textlinks                               */
  --blue-050: #eef2fa;   /* zarte Flaechen (Focus-Ring-Halo, Hover-Tint)  */
  --focus-halo: rgba(42, 85, 168, .16); /* Schein um fokussierte Eingaben    */

  /* ---- Neutrale ------------------------------------------------------- */
  --ink:        #111318; /* Headlines                                     */
  --ink-soft:   #1d2026; /* Nav aktiv, Footer-Ueberschriften              */
  --text:       #4c5057; /* Fliesstext                                    */
  --text-soft:  #6a6e76; /* sekundaerer Text                              */
  --line:       #edeef1; /* Sektionstrenner                               */
  --line-strong:#e2e3e7; /* betonte Trenner                               */
  --line-card:  #eaecef; /* Karten- und Inputrahmen                       */

  /* ---- Flaechen -------------------------------------------------------- */
  --surface:      #ffffff;
  --surface-soft: #fafbfc;
  --surface-band: #f6f7f9; /* Angebots-Band                                */
  --surface-tile: #f0f1f4;        /* Flaeche der drei Varianten-Karten      */
  --surface-tile-strong: #e5ebf5; /* Button darin: 12 % Markenblau auf Weiss*/

  /* ---- Radien: Buttons/Inputs = 4px, Karten/Medien = 6px, Pills = voll -- */
  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 22px;          /* weiche Rundung der schwebenden Kopfleiste     */
  --r-full: 999px;

  /* ---- Schatten: in Markenton getoent, nie reines Schwarz -------------- */
  --shadow-badge:      0 4px 14px rgba(16, 32, 64, .10), 0 1px 3px rgba(16, 32, 64, .07);
  --shadow-card:       0 1px 2px rgba(16, 32, 64, .04);
  --shadow-card-hover: 0 14px 32px -12px rgba(16, 32, 64, .20), 0 2px 6px rgba(16, 32, 64, .05);
  --shadow-btn:        0 1px 2px rgba(15, 36, 82, .18);
  --shadow-btn-hover:  0 8px 18px -8px rgba(15, 36, 82, .45);

  /* ---- Typografie ------------------------------------------------------ */
  /* Alle Schriftgroessen haengen an diesem Faktor. Das Barrierefreiheits-
     Widget hebt ihn an ("Groessere Schrift"), sonst bleibt er bei 1. */
  --fs-scale: 1;

  --font-sans: "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, system-ui, sans-serif;

  --fs-h1:          calc(56px * var(--fs-scale));  --lh-h1: 1.12;
  --fs-h2:          calc(27px * var(--fs-scale));  --lh-h2: 1.28;
  --fs-h2-sm:       calc(25px * var(--fs-scale));
  --fs-h3:          calc(20px * var(--fs-scale));
  --fs-card-title:  calc(17px * var(--fs-scale));
  --fs-eyebrow:     calc(14px * var(--fs-scale));
  --fs-eyebrow-sm:  calc(12px * var(--fs-scale));
  --fs-lead:        calc(18px * var(--fs-scale));
  --fs-body:        calc(17px * var(--fs-scale));
  --fs-body-sm:     calc(15px * var(--fs-scale));
  --fs-nav:         calc(15px * var(--fs-scale));
  --fs-btn:         calc(16px * var(--fs-scale));
  --fs-btn-sm:      calc(15px * var(--fs-scale));
  --fs-micro:       calc(13px * var(--fs-scale));

  --ls-display: -.012em;
  --ls-caps:     .045em;
  --ls-eyebrow:  .18em;

  /* ---- Raster & Rhythmus ---------------------------------------------- */
  --container: 1180px;
  --gutter: 24px;
  --header-h: 68px;      /* Bauhoehe der Leiste selbst                    */
  /* Die Leiste schwebt: sie steht seitlich etwas ueber den Inhaltsrahmen
     hinaus (--header-shell-x) und haelt oben wie unten Luft
     (--header-shell-y). Die Inhalte darin behalten exakt ihre bisherige
     Position, weil der Ueberstand als Innenabstand zurueckgegeben wird. */
  --header-shell-x: 14px;
  --header-shell-y: 10px;
  /* Die Leiste laeuft nicht bis an den Inhaltsrahmen, sondern bleibt beid-
     seitig um diesen Betrag darunter - sie wirkt dadurch weniger wie ein
     Balken quer durchs Bild. Greift nur, solange das Fenster breit genug
     ist (ab rund 1140px); darunter begrenzen ohnehin die Seitenraender. */
  --header-inset: 44px;
  --header-total: calc(var(--header-h) + var(--header-shell-y) * 2);
  /* Auf der Startseite liegt die Leiste im Hero-Bild und sitzt dort
     tiefer als auf den Unterseiten. */
  --header-drop: 28px;
  --header-total-start: calc(var(--header-h) + var(--header-drop) + var(--header-shell-y));

  --gap-cards: 32px;
  --sec-pt: 34px;   /* Sektions-Innenabstand oben (Referenz: kompakt)      */
  --sec-pb: 27px;   /* Sektions-Innenabstand unten                         */

  /* ---- Motion --------------------------------------------------------- */
  --ease: cubic-bezier(.16, 1, .3, 1);
  --dur-fast: 200ms;
  --dur: 330ms;
  --dur-slow: 820ms;

  /* ---- Layer ---------------------------------------------------------- */
  --z-sticky: 100;
  --z-nav-panel: 110;
  --z-a11y: 120;
}

/* ---- Stufenweise Verkleinerung unterhalb der Referenzbreite ------------ */
@media (max-width: 1199px) {
  :root {
    --fs-h1: calc(48px * var(--fs-scale));  --fs-h2: calc(26px * var(--fs-scale));  --fs-h2-sm: calc(24px * var(--fs-scale));
    --fs-lead: calc(17px * var(--fs-scale)); --header-h: 64px; --gap-cards: 24px;
    --r-lg: 20px;
  }
}

@media (max-width: 1023px) {
  :root {
    --fs-h1: calc(43px * var(--fs-scale));  --fs-h2: calc(25px * var(--fs-scale));  --fs-h2-sm: calc(23px * var(--fs-scale)); --fs-h3: calc(19px * var(--fs-scale));
    --fs-lead: calc(17px * var(--fs-scale)); --fs-body: calc(16px * var(--fs-scale));
    --header-h: 60px; --gutter: 24px;
    --header-shell-x: 12px; --header-shell-y: 8px; --r-lg: 18px; --header-drop: 22px;
    --sec-pt: 48px; --sec-pb: 44px;
  }
}

@media (max-width: 639px) {
  :root {
    --fs-h1: calc(35px * var(--fs-scale));  --lh-h1: 1.14;
    --fs-h2: calc(23px * var(--fs-scale));  --fs-h2-sm: calc(21px * var(--fs-scale)); --fs-h3: calc(18px * var(--fs-scale));
    --fs-eyebrow: calc(12px * var(--fs-scale)); --ls-eyebrow: .15em;
    --fs-lead: calc(16px * var(--fs-scale)); --fs-body: calc(16px * var(--fs-scale)); --fs-btn: calc(15px * var(--fs-scale));
    --header-h: 56px; --gutter: 20px;
    --header-shell-x: 10px; --header-shell-y: 8px; --r-lg: 16px;
    --sec-pt: 44px; --sec-pb: 40px;
  }
}

/* ===== styles/02-reset.css ===== */
/* ===== Reset: minimal, modern, ohne Nebenwirkungen ====================== */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-total) + 20px);
}

body {
  min-height: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

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

button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

ul[class], ol[class] { list-style: none; padding: 0; }

a { color: inherit; text-decoration: none; }

:where(h1, h2, h3, h4, p, figure) { overflow-wrap: break-word; }

/* Sichtbarer, markenkonformer Fokus-Ring - nie entfernen */
:focus-visible {
  outline: 2px solid var(--blue-600);
  outline-offset: 3px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ===== styles/03-base.css ===== */
/* ===== Basistypografie ================================================== */
body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--text);
  background: var(--surface);
  font-synthesis-weight: none;
}

h1, h2, h3, h4 {
  color: var(--ink);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: var(--ls-display);
}

strong, b { font-weight: 600; color: var(--ink); }

::selection { background: var(--blue-600); color: #fff; }

/* --- Eyebrow: kleine blaue Vorzeile ueber Ueberschriften ---------------- */
.eyebrow {
  display: block;
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--blue-600);
}
.eyebrow--sm { font-size: var(--fs-eyebrow-sm); letter-spacing: .16em; }

/* --- Ueberschriften ----------------------------------------------------- */
.h-display {
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
  letter-spacing: -.018em;
  text-transform: uppercase;
}
.h-section {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  text-transform: uppercase;
  letter-spacing: -.004em;
}
.h-section--sm { font-size: var(--fs-h2-sm); }
.h-band {
  font-size: var(--fs-h3);
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: -.002em;
}

/* --- Fliesstext ---------------------------------------------------------- */
.lead { font-size: var(--fs-lead); line-height: 1.6; color: var(--text); }
.text-sm { font-size: var(--fs-body-sm); line-height: 1.7; }
/* Lauflaengen fuer einzelne Absaetze. Als Klasse statt als style-Attribut,
   damit die Content-Security-Policy ohne 'unsafe-inline' auskommt. */
.measure-56 { max-width: 56ch; }
.measure-58 { max-width: 58ch; }

/* --- Textlink mit Pfeil (Referenz: "Mehr erfahren  ->") ------------------ */
.link-arrow {
  display: inline-flex;
  align-items: center;
  /* 24px ist die Mindestgroesse eines Tippziels nach WCAG 2.5.8.
     Aus der Zeilenhoehe allein ergaeben sich nur knapp 22px. */
  min-height: 24px;
  gap: 12px;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  line-height: 1.45;
  color: var(--blue-600);
  transition: color var(--dur-fast) var(--ease);
}
.link-arrow .icon { transition: transform var(--dur) var(--ease); }
.link-arrow:hover { color: var(--blue-500); }
.link-arrow:hover .icon { transform: translateX(5px); }

/* Bei Beruehrungsbedienung auf Fingergroesse. Mit Maus bleibt die Zeile
   kompakt, dort zeigt der Zeiger genau. */
@media (max-width: 639px), (pointer: coarse) {
  .link-arrow { min-height: 44px; }
}

/* --- Skip-Link ----------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 999;
  padding: 12px 20px;
  background: var(--navy-800);
  color: #fff;
  border-radius: var(--r-sm);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: 16px; }

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

/* ===== styles/04-layout.css ===== */
/* ===== Layout-Primitive ================================================= */

/* Zentrierter Inhaltsrahmen.
   Referenz: Inhalt 938/1024 breit -> auf 1280 px exakt 1180 px mit 50 px Rand. */
.container {
  width: min(100% - (var(--gutter) * 2), var(--container));
  margin-inline: auto;
}

.section {
  padding-block: var(--sec-pt) var(--sec-pb);
}
.section--rule { border-top: 1px solid var(--line); }

/* Kopfzeile einer Sektion: Ueberschrift links, Begleittext rechts.
   Referenz-Layout des Leistungsbereichs. */
.section-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 470px;
  gap: 40px;
  align-items: start;
}
.section-head__text { padding-top: 35px; max-width: 44ch; }

@media (max-width: 1023px) {
  .section-head { grid-template-columns: 1fr; gap: 16px; }
  .section-head__text { max-width: 60ch; padding-top: 0; }
}

/* ===== styles/components/button.css ===== */
/* ===== Buttons =========================================================
   Groessen sind aus der Referenz abgeleitet:
   Header-CTA 191x46, Hero-Buttons 209x52, Band-Button 184x48 (bei 1280px).
   ======================================================================= */
.btn {
  --btn-h: 52px;
  --btn-px: 22px;
  --btn-gap: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  min-height: var(--btn-h);
  padding-inline: var(--btn-px);
  border-radius: var(--r-sm);
  font-size: var(--fs-btn);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.002em;
  white-space: nowrap;          /* CTA-Label bricht nie um */
  transition:
    background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur-fast) var(--ease);
}
.btn .icon { flex: none; transition: transform var(--dur) var(--ease); }
.btn:hover .icon { transform: translateX(4px); }
.btn:active { transform: translateY(0) scale(.985); }

/* --- Varianten ---------------------------------------------------------- */
.btn--primary {
  background: var(--navy-800);
  color: #fff;                      /* 12.1:1 auf #14336f - WCAG AAA       */
  box-shadow: var(--shadow-btn);
}
.btn--primary:hover {
  background: var(--navy-700);
  box-shadow: var(--shadow-btn-hover);
  transform: translateY(-1px);
}

.btn--ghost {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line-strong);
}
.btn--ghost:hover {
  background: var(--surface-soft);
  border-color: #cfd3da;
  transform: translateY(-1px);
  box-shadow: 0 8px 18px -10px rgba(16, 32, 64, .3);
}

/* --- Groessen ------------------------------------------------------------ */
.btn--sm { --btn-h: 46px; --btn-px: 13px; --btn-gap: 10px; font-size: var(--fs-btn-sm); }
.btn--md { --btn-h: 48px; --btn-px: 24px; --btn-gap: 14px; font-size: var(--fs-btn-sm); }

.btn--block { width: 100%; }

/* --- Buttongruppe -------------------------------------------------------- */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

@media (max-width: 639px) {
  .btn { --btn-h: 48px; --btn-px: 20px; --btn-gap: 12px; }
  .btn-row { gap: 12px; }
  .btn-row .btn { flex: 1 1 100%; }
}

/* Sehr schmale Geraete: die laengeren CTA-Label duerfen umbrechen, statt
   ueber den Rand hinauszulaufen. Die Tippflaeche bleibt dabei erhalten. */
@media (max-width: 400px) {
  .btn {
    white-space: normal;
    text-align: center;
    line-height: 1.25;
    padding-block: 12px;
  }
}

/* Ladezustand (Formular-Absenden) */
.btn[aria-busy="true"] { pointer-events: none; opacity: .72; }
.btn[aria-busy="true"] .icon { animation: btn-pulse 900ms ease-in-out infinite; }
@keyframes btn-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .btn[aria-busy="true"] .icon { animation: none; }
}

/* ===== styles/components/logo.css ===== */
/* ===== Wortmarke ========================================================
   Zwei Bildmarken: quer in der Kopfzeile (36px hoch), hoch in der
   Fusszeile (128px hoch).
   ======================================================================= */
.logo {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ink);
  line-height: 1;
}
/* --- Bildmarke (Kopfzeile) ----------------------------------------------
   Variante 2 der endgueltigen Marke: nur der Schriftzug, ohne Signet.
   Datei: src/assets/img/logo-wortmarke.png, aus dem Original in
   reference/logo/variante-2-wortmarke.png freigestellt und auf Webmass
   gebracht (480x120 im Attribut, damit nichts springt).
   Die Hoehe steuert die Groesse, die Breite folgt dem Seitenverhaeltnis.
   ----------------------------------------------------------------------- */
.logo--image { gap: 0; }
.logo__img {
  /* 40px statt der frueheren 36px: die neue Marke traegt den Zusatz
     "TRANSPORT" als zweite Zeile, der Schriftzug selbst nimmt also nur rund
     zwei Drittel der Bildhoehe ein. Bei 40px liest er sich so gross wie
     vorher. Die Datei ist 120px hoch, also dreifach - scharf auch auf
     feinen Displays. */
  height: 40px;
  width: auto;
  /* Sollte die Leiste je eng werden, schrumpft die Marke massstabsgetreu
     statt sich zu verziehen. */
  object-fit: contain;
  object-position: left center;
  transition: transform var(--dur) var(--ease);
}
.logo:hover .logo__img { transform: translateX(2px); }

/* --- Bildmarke (Fusszeile) ----------------------------------------------
   Variante 1 der endgueltigen Marke, das vollstaendige Hochformat: Signet
   ueber Schriftzug und Zusatz. Datei: src/assets/img/logo-vollmarke.png,
   freigestellt aus reference/logo/variante-1-vollmarke.png.
   128px ist so gewaehlt, dass der Schriftzug "Don Sergio" darin dieselbe
   Bauhoehe bekommt wie die Wortmarke in der Kopfzeile.
   Zwei Klassen im Selektor, damit die Hoehe der Kopfzeilen-Marke aus den
   Medienabfragen unten nicht dazwischenfunkt.
   ----------------------------------------------------------------------- */
.logo--footer .logo__img { height: 128px; }

@media (max-width: 1023px) {
  .logo { gap: 6px; }
  .logo__img { height: 34px; }
  .logo--footer .logo__img { height: 112px; }
}
@media (max-width: 400px) {
  .logo__img { height: 30px; }
  .logo--footer .logo__img { height: 100px; }
}

/* ===== styles/components/icon.css ===== */
/* ===== Icons ============================================================ */
.svg-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  color: inherit;
  vertical-align: middle;
}
.icon--16 { width: 16px; height: 16px; }
.icon--18 { width: 18px; height: 18px; }
.icon--20 { width: 20px; height: 20px; }
.icon--24 { width: 24px; height: 24px; }

/* Weisse Badge-Scheibe, die auf der Bildkante der Karten sitzt */
.icon-badge {
  display: grid;
  place-items: center;
  width: 71px;
  height: 71px;
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--blue-700);
  box-shadow: var(--shadow-badge);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.icon-badge .icon { width: 35px; height: 35px; }

@media (max-width: 639px) {
  .icon-badge { width: 62px; height: 62px; }
  .icon-badge .icon { width: 30px; height: 30px; }
}

/* ===== styles/components/header.css ===== */
/* ===== Kopfzeile ========================================================
   Schlanke, schwebende Leiste: 68 px hoch, milchig transparent ueber dem
   Inhalt, rundum weich gerundet. Logo links, Navigation mittig, CTA rechts.

   Traeger der Gestaltung ist .site-header__inner, nicht das <header>: das
   aeussere Element bleibt durchsichtig und gibt nur oben und unten Luft
   (--header-shell-y), damit die gerundete Leiste frei ueber dem Inhalt
   steht. Die Leiste selbst ist um --header-shell-x breiter als der
   Inhaltsrahmen und gibt denselben Betrag als Innenabstand zurueck - Logo,
   Navigation und CTA sitzen dadurch exakt dort wie zuvor.
   ======================================================================= */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  padding-block: var(--header-shell-y);
  /* Die durchsichtigen Streifen ueber und unter der Leiste sollen keine
     Klicks abfangen - nur die Leiste selbst und das Panel reagieren. */
  pointer-events: none;
}
.site-header__inner,
.mobile-nav { pointer-events: auto; }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: var(--header-h);
  /* Inhaltsbreite = Inhaltsrahmen; der Ueberstand steckt in Rahmen+Polster. */
  width: min(
    100% - (var(--gutter) - var(--header-shell-x)) * 2,
    calc(var(--container) + var(--header-shell-x) * 2 - var(--header-inset) * 2)
  );
  padding-inline: calc(var(--header-shell-x) - 1px);
  background: rgba(255, 255, 255, .74);
  border: 1px solid rgba(16, 32, 64, .07);
  border-radius: var(--r-lg);
  box-shadow: 0 8px 24px -20px rgba(16, 32, 64, .5);
  transition: background-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
/* Die Wortmarke setzt links ohne Anlauf ein: die Serife des "D" stuende sonst
   hart am Innenrand der Leiste. Ein kleiner Vorlauf gibt ihr Luft. */
.site-header__inner .logo--image { margin-left: 8px; }

/* Milchglas nur dort, wo der Browser es kann - sonst deckendes Weiss. */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .site-header__inner {
    -webkit-backdrop-filter: saturate(180%) blur(16px);
    backdrop-filter: saturate(180%) blur(16px);
  }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header__inner { background: var(--surface); }
}

/* Nach dem ersten Scrollen wird die Leiste dichter und setzt sich ab. */
.site-header[data-scrolled] .site-header__inner {
  background: rgba(255, 255, 255, .88);
  border-color: rgba(16, 32, 64, .1);
  box-shadow: 0 14px 34px -24px rgba(16, 32, 64, .6);
}

/* --- Desktop-Navigation -------------------------------------------------- */
.nav__list {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0;
}
/* Pille statt Unterstrich: kompakter, ruhiger, klarer Trefferbereich. */
.nav__link {
  display: block;
  padding: 8px 14px;
  border-radius: var(--r-full);
  font-size: var(--fs-nav);
  font-weight: 500;
  color: var(--text);
  transition: color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.nav__link:hover {
  color: var(--ink);
  background: var(--blue-050);
}
.nav__link[aria-current="page"] {
  color: var(--navy-800);
  background: var(--blue-050);
  font-weight: 600;
}

/* --- Aktionen rechts: Direktwahl + CTA -----------------------------------
   Beide stehen in einer eigenen Gruppe, damit die Leiste weiterhin aus drei
   Teilen besteht (Logo | Navigation | Aktionen) und die Navigation mittig
   bleibt. Ohne die Gruppe wuerde space-between vier Bloecke verteilen und
   die Navigation nach links rutschen.
   ------------------------------------------------------------------------- */
.site-header__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* CTA und Umschalter folgen der schlanken Bauhoehe. */
.site-header__cta { --btn-h: 40px; --btn-px: 16px; --btn-gap: 8px; }

/* --- Direktwahl ----------------------------------------------------------
   Sichtbar nur dort, wo ein Fingertipp die Telefon-App oeffnet: unterhalb
   von 1024px, also genau in dem Bereich, in dem auch das mobile Panel
   uebernimmt. Am Rechner blendet die Regel ganz unten sie wieder aus - dort
   fuehren Kopfzeilen-CTA, Fusszeile und Kontaktseite zur Nummer.

   Gestaltung wie ein vollwertiger Aktionsknopf, nicht wie ein Beiwerk:
   gefuellter Kreis in der Markenfarbe, weisses Symbol, weicher Schlagschatten.
   Damit steht er gleichberechtigt neben dem Primaerbutton, statt daneben
   auszubleichen.
   ------------------------------------------------------------------------- */
.site-header__phone {
  position: relative;
  /* Grundzustand unsichtbar - die Regel am Umschaltpunkt blendet sie ein,
     genau wie beim Menue-Umschalter daneben. */
  display: none;
  /* Die Ausrichtung gilt, sobald sie eingeblendet ist. */
  align-items: center;
  justify-content: center;
  flex: none;
  /* Volle Fingergroesse - das ist auf dem Handy der kuerzeste Weg zum Auftrag. */
  width: 44px;
  height: 44px;
  border-radius: var(--r-full);
  color: #fff;
  background: linear-gradient(145deg, var(--blue-600) 0%, var(--navy-800) 62%, var(--navy-900) 100%);
  box-shadow: 0 2px 6px -1px rgba(15, 36, 82, .34), inset 0 1px 0 rgba(255, 255, 255, .16);
  transition: transform var(--dur-fast) var(--ease),
              box-shadow var(--dur) var(--ease),
              filter var(--dur-fast) var(--ease);
}

/* Der Ring geht beim Hover nach aussen auf - dieselbe Geste, mit der ein
   Telefon laeutet, nur still. Er liegt hinter dem Kreis und faengt keine
   Klicks ab. */
.site-header__phone::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: inherit;
  border: 2px solid var(--blue-600);
  opacity: 0;
  transform: scale(.78);
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.site-header__phone:hover,
.site-header__phone:focus-visible {
  transform: translateY(-2px);
  filter: saturate(1.08);
  box-shadow: 0 10px 20px -8px rgba(15, 36, 82, .55), inset 0 1px 0 rgba(255, 255, 255, .22);
}
.site-header__phone:hover::before,
.site-header__phone:focus-visible::before {
  opacity: .34;
  transform: scale(1);
}

/* Gedrueckt: der Knopf setzt sich zurueck auf die Leiste, der Ring zieht sich
   mit. Das ist die einzige Rueckmeldung, die auf dem Handy wirklich ankommt -
   dort gibt es kein Hovern. */
.site-header__phone:active {
  transform: translateY(0) scale(.94);
  box-shadow: 0 1px 3px -1px rgba(15, 36, 82, .4), inset 0 1px 0 rgba(255, 255, 255, .12);
}
.site-header__phone:active::before { opacity: .5; transform: scale(.92); }

/* Das Symbol selbst laeutet kurz an - fuenf abklingende Ausschlaege, danach
   steht es wieder ruhig. */
@media (prefers-reduced-motion: no-preference) {
  .site-header__phone:hover .icon,
  .site-header__phone:focus-visible .icon {
    animation: phone-ring 820ms var(--ease);
  }
  @keyframes phone-ring {
    0%, 100% { transform: rotate(0); }
    12% { transform: rotate(-15deg); }
    26% { transform: rotate(13deg); }
    40% { transform: rotate(-9deg); }
    54% { transform: rotate(7deg); }
    68% { transform: rotate(-4deg); }
    82% { transform: rotate(2deg); }
  }
}

/* --- Umschalter (mobil) --------------------------------------------------- */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  /* 44px: die einzige Navigationsschaltflaeche auf dem Handy. */
  width: 44px;
  height: 44px;
  margin-right: -8px;
  border-radius: var(--r-sm);
  color: var(--ink);
  transition: background-color var(--dur-fast) var(--ease);
}
.nav-toggle:hover { background: var(--blue-050); }
.nav-toggle__box { display: grid; place-items: center; }
.nav-toggle__box > * { grid-area: 1 / 1; transition: opacity var(--dur-fast) var(--ease), transform var(--dur) var(--ease); }
.nav-toggle__close { opacity: 0; transform: rotate(-45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__open  { opacity: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__close { opacity: 1; transform: rotate(0); }

/* --- Mobiles Panel --------------------------------------------------------- */
/* Das Panel greift die Form der Leiste auf: gleiche Breite, gleiche
   Rundung, knapp darunter haengend. */
.mobile-nav {
  position: absolute;
  inset-inline: calc(var(--gutter) - var(--header-shell-x));
  top: 100%;
  z-index: var(--z-nav-panel);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 40px -28px rgba(16, 32, 64, .45);
  overflow: hidden;
}
.mobile-nav[hidden] { display: none; }
/* Kein Inhaltsrahmen noetig - das Panel steht bereits eingerueckt. Der
   Innenabstand entspricht dem der Leiste, die Links fluchten mit dem Logo. */
.mobile-nav__inner {
  width: auto;
  margin-inline: 0;
  /* minus Rahmen - so fluchten die Links exakt mit dem Logo darueber. */
  padding-inline: calc(var(--header-shell-x) - 1px);
  padding-block: 8px 28px;
}

.mobile-nav__list { border-top: 1px solid var(--line); }
.mobile-nav__link {
  display: block;
  padding: 15px 2px;
  border-bottom: 1px solid var(--line);
  font-size: calc(17px * var(--fs-scale));
  font-weight: 500;
  color: var(--text);
  transition: color var(--dur-fast) var(--ease), padding-left var(--dur) var(--ease);
}
.mobile-nav__link:hover { color: var(--ink); padding-left: 8px; }
.mobile-nav__link[aria-current="page"] {
  color: var(--navy-800);
  font-weight: 700;
  box-shadow: inset 3px 0 0 var(--navy-800);
  padding-left: 12px;
}

.mobile-nav__cta { margin-top: 22px; }

.mobile-nav__contact {
  margin-top: 20px;
  display: grid;
  gap: 4px;
  font-size: var(--fs-body-sm);
}
.mobile-nav__contact a {
  display: inline-flex;
  align-items: center;
  /* Telefon und E-Mail im ausgeklappten Menue: das Panel gibt es nur auf
     Beruehrungsgeraeten, also durchgaengig auf Fingergroesse. */
  min-height: 44px;
  gap: 12px;
  color: var(--text);
}
.mobile-nav__contact a:hover { color: var(--navy-800); }

/* Einblenden des Panels (nur wenn Bewegung erwuenscht ist) */
@media (prefers-reduced-motion: no-preference) {
  .mobile-nav:not([hidden]) { animation: panel-in 380ms var(--ease); }
  @keyframes panel-in {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: translateY(0); }
  }
}

/* --- Enge Breiten: sechs Menuepunkte brauchen schmalere Pillen -----------
   Zwischen 1024 und 1199 px stehen Logo, sechs Punkte und CTA nebeneinander,
   ohne dass die Leiste breiter wird. Deshalb dort etwas kompakter: kleinere
   Bildmarke, schmalere Pillen, engere Fugen. Unterhalb 1024 uebernimmt
   ohnehin das Panel.
   ------------------------------------------------------------------------- */
@media (min-width: 1024px) and (max-width: 1199px) {
  .site-header__inner { gap: 14px; }
  .nav__link { padding-inline: 8px; }
  .site-header__cta { --btn-px: 12px; }
  .site-header__actions { gap: 8px; }
  .logo__img { height: 30px; }
}

/* --- Startseite: die Leiste liegt im Hero-Bild ----------------------------
   Der Auftakt beginnt ganz oben, die Leiste schwebt darin statt darueber.
   Umgesetzt ueber einen negativen Aussenabstand: die Leiste bleibt sticky
   und behaelt ihre Hoehe, nimmt dem Inhalt darunter aber keinen Platz mehr
   weg. Den Abstand zur Ueberschrift haelt der Hero selbst (hero.css).
   Erst ab 900px - darunter steht das Hero-Bild unter dem Text, dort gibt es
   kein Bild, in dem die Leiste liegen koennte.
   ------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .page-start .site-header {
    padding-top: var(--header-drop);
    margin-bottom: calc(var(--header-total-start) * -1);
  }
}

/* --- Umschaltpunkt --------------------------------------------------------- */
@media (max-width: 1023px) {
  .nav,
  .site-header__cta { display: none; }
  .nav-toggle { display: inline-flex; }
  /* Ab hier zeigt das Geraet mit hoher Wahrscheinlichkeit einen Telefonhoerer:
     die Direktwahl erscheint und ersetzt den ausgeblendeten Kopfzeilen-CTA. */
  .site-header__phone { display: inline-flex; }
  .site-header__inner { gap: 12px; }
  /* Ohne Navigation und CTA blieben nur drei Bloecke uebrig - die Direktwahl
     stuende dann mittig in der Leiste. Sie rueckt deshalb an den rechten Rand,
     direkt neben den Umschalter. */
  .site-header__actions { margin-left: auto; }
  /* Auf schmalen Fenstern ist die Leiste ohnehin knapp - halber Vorlauf. */
  .site-header__inner .logo--image { margin-left: 4px; }
}

/* Body-Scroll sperren, solange das Panel offen ist */
body.is-nav-open { overflow: hidden; }

/* ===== styles/components/card.css ===== */
/* ===== Leistungskarte ===================================================
   Referenz: 369x392, Bild 369x219, weisse Icon-Scheibe mittig auf der
   Bildkante, zentrierter Text, Textlink mit Pfeil.
   ======================================================================= */
.card {
  position: relative;   /* Bezug fuer .card__link::after (ganze Karte klickbar) */
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/* Das Anheben der Karte steht weiter unten im Bewegungsblock (-6px),
   damit die drei Ebenen der Kartenbewegung an einer Stelle stehen. */
.card:hover,
.card:focus-within {
  border-color: #dde1e8;
  box-shadow: var(--shadow-card-hover);
}

.card__media {
  position: relative;   /* Bezug fuer den Lichtstreif .card__media::after */
  overflow: hidden;
  border-radius: calc(var(--r-md) - 1px) calc(var(--r-md) - 1px) 0 0;
  background: var(--surface-soft);
}
.card__media img {
  width: 100%;
  aspect-ratio: 369 / 219;
  object-fit: cover;
  transition: transform 900ms var(--ease);
}

/* ── KI-Motive: der Vermerk muss stehen bleiben ──────────────────────────
   Die mit generativer KI erzeugten Motive tragen unten rechts im Bild den
   eingeblendeten Hinweis "AI-generiert". Das Impressum beruft sich darauf
   ("Erkennbar sind sie am eingeblendeten Hinweis"), also darf ihn kein
   Beschnitt wegnehmen.

   Zwei Vorkehrungen greifen ineinander:

   1. Die Dateien sind bereits auf das Seitenverhaeltnis ihres Kastens
      zugeschnitten, und zwar UNTEN verankert. object-fit: cover hat damit
      im Normalfall nichts mehr wegzunehmen.
   2. Diese Regel ist das Netz darunter. Bleibt durch Rundung bei einer
      krummen Fensterbreite doch ein Pixel uebrig, nimmt cover ihn oben weg
      statt unten - der Vermerk bleibt stehen.

   Die Regel haengt am Attribut data-ai und damit nur an den KI-Motiven.
   Die echten Fotos behalten ihre mittige Ausrichtung. */
img[data-ai] { object-position: bottom; }
.card:hover .card__media img { transform: scale(1.045); }

/* Steht statt eines Fotos ein Platzhalter in der Karte, uebernimmt er dessen
   Seitenverhaeltnis. Rahmen und Rundung liegen bereits an .card__media - die
   Flaeche bringt hier also keine zweiten mit. */
.card__media .ph {
  --ph-ratio: 369 / 219;
  border: 0;
  border-radius: 0;
}
/* Oben links sitzt schon die Nummer der Karte (Block 5 in
   sections/startseite-2.css) - die Marke der Platzhalterflaeche weicht
   deshalb nach rechts aus. */
.card__media .ph__tag { left: auto; right: 12px; }

.card__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  padding: 0 22px 18px;
  text-align: center;
}

.card__badge { margin-top: -39px; }
.card:hover .card__badge {
  box-shadow: 0 8px 22px rgba(16, 32, 64, .16), 0 1px 3px rgba(16, 32, 64, .08);
}

.card__title {
  margin-top: 0;
  font-size: var(--fs-card-title);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: .055em;
  text-transform: uppercase;
  color: var(--ink);
}

.card__text {
  margin-top: 10px;
  max-width: 30ch;
  font-size: calc(16px * var(--fs-scale));
  line-height: 1.5;
  color: var(--text);
}

.card__link { margin-top: auto; padding-top: 20px; }

/* Die ganze Karte ist klickbar, das Ziel bleibt der sichtbare Link.
   Bezugspunkt ist .card (position: relative in der Basisregel oben). */
.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

@media (max-width: 639px) {
  .card__badge { margin-top: -34px; }
  .card__body { padding: 0 20px 26px; }
  .card__text { max-width: 36ch; }
}

/* =======================================================================
   Bewegung der Leistungskarten
   -----------------------------------------------------------------------
   Drei Ebenen, alle rein ueber transform/opacity (Compositor, kein Layout):
     1. Ruhezustand  - die Icon-Scheibe schwebt sehr langsam, je Karte
                       phasenverschoben, damit die Reihe lebt statt tickt.
     2. Hover        - Karte hebt sich, Bild zoomt, ein weicher Lichtstreif
                       laeuft einmal ueber das Foto.
     3. Motiv        - jedes Icon bewegt sich passend zu seiner Leistung:
                       Haus hebt an, Paket wippt, Motorrad faehrt an.
   Alles bleibt klein (<= 6px, <= 3 Grad). prefers-reduced-motion schaltet
   saemtliche Animationen global ab (siehe styles/05-motion.css).
   ======================================================================= */

/* --- 1. Ruhezustand: langsames Schweben der Icon-Scheibe ---------------- */
@media (prefers-reduced-motion: no-preference) {
  .card__badge {
    animation: badge-float 5.4s var(--float-delay, 0s) ease-in-out infinite;
    will-change: translate;
  }
  /* Phasenversatz, damit die drei Scheiben nicht im Gleichschritt laufen */
  .services__grid > :nth-child(2) .card__badge { --float-delay: -1.8s; }
  .services__grid > :nth-child(3) .card__badge { --float-delay: -3.6s; }

  /* Beim Hover uebernimmt die Hover-Bewegung, das Schweben pausiert. */
  .card:hover .card__badge,
  .card:focus-within .card__badge { animation-play-state: paused; }
}

/* --- 2. Hover: Karte, Bild, Lichtstreif ---------------------------------- */
.card:hover,
.card:focus-within { transform: translateY(-6px); }

/* Lichtstreif: laeuft beim Hover einmal quer ueber das Foto. */
.card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgba(255, 255, 255, 0) 26%,
    rgba(255, 255, 255, .28) 42%,
    rgba(255, 255, 255, .62) 50%,
    rgba(255, 255, 255, .28) 58%,
    rgba(255, 255, 255, 0) 74%
  );
  transform: translateX(-115%);
  opacity: 0;
  pointer-events: none;
}
.card:hover .card__media::after,
.card:focus-within .card__media::after {
  opacity: 1;
  transform: translateX(115%);
  transition: transform 1450ms cubic-bezier(.4, 0, .3, 1), opacity 280ms linear;
}

/* --- 3. Motivbewegung der Icons ------------------------------------------ */
.card__badge .icon {
  transition: transform 540ms var(--ease);
  transform-origin: 50% 60%;
}

/* Umzüge: das Haus hebt sich kurz an. */
.card--move:hover .card__badge .icon,
.card--move:focus-within .card__badge .icon { transform: translateY(-3px) scale(1.05); }

/* Warentransport: das Paket wippt leicht zur Seite. */
.card--freight:hover .card__badge .icon,
.card--freight:focus-within .card__badge .icon { transform: rotate(-7deg) translateY(-2px); }

/* Motorradtransport: kleine Anfahrbewegung mit leichtem Aufbaeumen. */
.card--moto:hover .card__badge .icon,
.card--moto:focus-within .card__badge .icon { transform: translateX(4px) rotate(-4deg); }

.card:hover .card__badge,
.card:focus-within .card__badge { transform: translateY(-5px); }

/* ===== styles/components/feature.css ===== */
/* ===== Info-Kachel (Unterseiten) ======================================== */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

.feature {
  display: flex;
  gap: 20px;
  padding: 26px 24px;
  background: var(--surface);
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.feature:hover {
  border-color: #dde1e8;
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-3px);
}
.feature__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--blue-050);
  color: var(--blue-700);
}
.feature__icon .icon { width: 23px; height: 23px; }
.feature__title {
  font-size: calc(15px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--ink);
}
.feature__text { margin-top: 8px; font-size: var(--fs-body-sm); color: var(--text); }

/* Zweispaltiger Textblock mit Bild */
.split {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 56px;
  align-items: center;
}
.split__media img {
  width: 100%;
  border-radius: var(--r-md);
  border: 1px solid var(--line-card);
}
.split--reverse .split__media { order: -1; }

@media (max-width: 899px) {
  .split { grid-template-columns: 1fr; gap: 28px; }
  .split--reverse .split__media { order: 0; }
}

/* ===== styles/components/placeholder.css ===== */
/* ===== Foto-Platzhalter ==================================================
   Bewusst leere Bildflaechen: eine ruhige Flaeche, eine Haarlinie und ein
   kleines Bildsymbol. Kein Dekor, keine Illustration - die Flaeche soll
   erkennbar auf ein spaeteres Foto warten und sich nicht als Grafik
   ausgeben. Seitenverhaeltnis kommt ueber --ph-ratio.
   ======================================================================= */
.ph {
  position: relative;
  display: grid;
  place-items: center;
  gap: 10px;
  aspect-ratio: var(--ph-ratio, 4 / 3);
  padding: 20px;
  overflow: hidden;
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  background: var(--surface-soft);
  color: var(--text-soft);
  text-align: center;
}

/* Sehr zarte diagonale Schraffur - macht die Flaeche als Platzhalter
   lesbar, ohne wie ein Muster oder eine Grafik zu wirken. */
.ph::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    -45deg,
    rgba(16, 32, 64, .028) 0 1px,
    transparent 1px 11px
  );
  pointer-events: none;
}

.ph__inner {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 10px;
}

.ph__icon {
  width: 34px;
  height: 34px;
  color: var(--line-strong);
}

.ph__label {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: .12em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--text-soft);
}
.ph__hint {
  font-size: calc(12px * var(--fs-scale));
  line-height: 1.5;
  /* Kein zusaetzliches opacity: --text-soft liegt bei 5,1:1 und damit ueber
     WCAG AA; abgedunkelt fiele der Hinweis darunter. */
  color: var(--text-soft);
}

/* --- Varianten ----------------------------------------------------------- */
.ph--wide  { --ph-ratio: 16 / 9; }
.ph--tall  { --ph-ratio: 3 / 4; }
.ph--square{ --ph-ratio: 1 / 1; }
.ph--pano  { --ph-ratio: 21 / 9; }

/* Auf ruhigen Baendern kehrt sich die Flaeche um, damit der Platzhalter
   nicht mit dem Sektionshintergrund verschmilzt. */
.ph--on-soft { background: var(--surface); }

/* Kleine Ecken-Marke: macht klar, dass hier ein Bild eingesetzt wird. */
.ph__tag {
  position: absolute;
  top: 12px;
  left: 12px;
  padding: 4px 9px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--line-card);
  font-size: calc(10.5px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-soft);
}

/* Galerie aus mehreren Platzhaltern (Team, Fuhrpark) */
.ph-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 20px;
}

@media (max-width: 639px) {
  .ph__icon { width: 28px; height: 28px; }
  .ph-grid { gap: 14px; }
}

/* ===== styles/components/testimonial.css ===== */
/* ===== Kundenbewertungen ================================================
   Kartenoptik der Leistungskarten, aber ruhiger: viel Weissraum, ein
   grosses typografisches Anfuehrungszeichen, Sterne in der Markenfarbe und
   eine Initialen-Scheibe. Ab 720px ein Raster, darunter eine horizontale
   Spur mit Scroll-Snap - kein JavaScript noetig.
   ======================================================================= */
/* Sechs Spalten als Hilfsraster: jede Karte nimmt zwei davon. Die letzten
   beiden Karten der fuenfteiligen Reihe ruecken damit exakt in die Mitte,
   statt links angeschlagen zu haengen. */
.testimonials__track {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--gap-cards);
  margin-top: 34px;
}
.testimonial { grid-column: span 2; }
.testimonial:nth-child(4):nth-last-child(2) { grid-column: 2 / span 2; }
.testimonial:nth-child(5):nth-last-child(1) { grid-column: 4 / span 2; }

.testimonial {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 30px 28px 26px;
  background: var(--surface);
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  transition:
    border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}
.testimonial:hover {
  border-color: #dde1e8;
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-4px);
}

/* Grosses Anfuehrungszeichen als ruhige Marke oben rechts. Bewusst U+201C
   und nicht das tiefstehende U+201E: dessen Punzen sitzen auf Grundlinien-
   hoehe und liefen dem Zitattext ins Bild. Die Groesse haengt bewusst
   nicht an --fs-scale: als reines Zierzeichen wuerde es bei 115 % aus der
   Karte laufen, ohne dass jemand es liest. */
.testimonial::before {
  content: "\201C";
  position: absolute;
  top: 12px;
  right: 24px;
  font-size: 96px;
  font-weight: 800;
  line-height: 1;
  color: #e2eafa;
  pointer-events: none;
  transition: color var(--dur) var(--ease), transform var(--dur-slow) var(--ease);
}
.testimonial:hover::before {
  color: #d3dff6;
  transform: translateY(-3px);
}

.testimonial__stars {
  position: relative;
  display: flex;
  gap: 3px;
  color: var(--blue-600);
}
.testimonial__stars .icon { width: 17px; height: 17px; }

.testimonial__text {
  position: relative;
  margin-top: 16px;
  font-size: calc(16px * var(--fs-scale));
  line-height: 1.65;
  color: var(--text);
}

.testimonial__foot {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

.testimonial__avatar {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--blue-050);
  color: var(--navy-800);
  font-size: calc(14px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: .04em;
  transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.testimonial:hover .testimonial__avatar {
  background: var(--navy-800);
  color: #fff;
  transform: scale(1.06);
}

.testimonial__name {
  font-size: calc(15px * var(--fs-scale));
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink);
}
.testimonial__meta {
  margin-top: 3px;
  font-size: var(--fs-micro);
  line-height: 1.4;
  color: var(--text-soft);
}

/* --- Leerer Zustand: noch keine Bewertungen ------------------------------
   Steht statt der Karten, solange keine echte Bewertung vorliegt. Bewusst
   ein Kasten in derselben Optik und nicht einfach nichts: die Sektion
   behaelt ihren Platz im Seitenrhythmus, und beim Einsetzen der ersten
   Bewertung veraendert sich nur der Inhalt, nicht das Layout.

   Ueber die volle Rasterbreite - ein Kasten, der nur zwei von sechs
   Spalten fuellt, saehe nach einem Fehler aus. Ohne Anfuehrungszeichen und
   ohne Hover: hier ist nichts zu lesen und nichts anzuklicken.          */
.testimonial.testimonial--empty {
  grid-column: 1 / -1;
  align-items: center;
  justify-content: center;
  min-height: 148px;
  padding: 34px 28px;
  border-style: dashed;
  border-color: var(--line-strong);
  background: var(--surface-soft);
  box-shadow: none;
  text-align: center;
}
.testimonial.testimonial--empty::before { content: none; }
.testimonial.testimonial--empty:hover {
  border-color: var(--line-strong);
  box-shadow: none;
  transform: none;
}

.testimonial__empty-text {
  font-size: calc(16px * var(--fs-scale));
  font-weight: 700;
  line-height: 1.5;
  color: var(--ink-soft);
}
.testimonial__empty-hint {
  max-width: 46ch;
  margin-top: 8px;
  font-size: var(--fs-micro);
  line-height: 1.6;
  color: var(--text-soft);
}

/* Mobil ist die Spur ein Flex-Band; dort zaehlt grid-column nicht, der
   Kasten muss stattdessen die Breite selbst halten. */
@media (max-width: 719px) {
  .testimonial.testimonial--empty {
    /* Volle Breite statt Snap-Karte: es gibt nur diesen einen Kasten,
       und ein schmales Kaertchen ohne Nachbarn saehe nach Fehler aus.

       Der eigene Seitenabstand ist noetig, weil das padding-inline der
       Spur nicht ankommt: 02-reset.css setzt ul[class] { padding: 0 },
       und das ist spezifischer als .testimonials__track. Fuer das
       Karussell aus echten Karten ist der randlose Anschnitt stimmig,
       fuer einen einzelnen Kasten nicht - er soll mit der Ueberschrift
       fluchten. Deshalb hier margin statt einer Aenderung am Reset. */
    flex: 0 0 calc(100% - var(--gutter) * 2);
    margin-inline: var(--gutter);
    padding: 28px 22px;
  }
}

/* --- Vier und mehr Karten: zwei Reihen ---------------------------------- */
@media (max-width: 1023px) {
  .testimonials__track { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .testimonial:nth-child(4):nth-last-child(2),
  .testimonial:nth-child(5):nth-last-child(1) { grid-column: span 2; }
}

/* Der Wischhinweis erscheint nur dort, wo gewischt werden kann. */
.testimonials__hint { display: none; }

/* Auf breiten Schirmen ist das Band ein normales Raster und braucht keinen
   Fokus; dort nimmt tabindex="0" sonst einen leeren Tabstopp weg. */
@media (min-width: 720px) {
  .testimonials__track { outline: none; }
}
@media (max-width: 719px) {
  .testimonials__track:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 4px; }
}

/* --- Mobil: horizontale Spur mit Snap ----------------------------------- */
@media (max-width: 719px) {
  .testimonials__track {
    display: flex;
    gap: 16px;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-block: 4px 18px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
  }
  .testimonial {
    flex: 0 0 min(84vw, 340px);
    scroll-snap-align: start;
    padding: 26px 22px 22px;
  }
  .testimonial::before { font-size: 76px; right: 20px; top: 10px; }
  .testimonials__hint {
    display: block;
    margin-top: 2px;
    font-size: var(--fs-micro);
    color: var(--text-soft);
  }
}

/* ===== styles/components/checklist.css ===== */
/* ===== Häkchenliste ===================================================== */
.checklist {
  display: grid;
  gap: 7px;
  margin: 0;
}
.checklist li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: var(--text);
}
.checklist__mark {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--blue-700);
  color: #fff;
}
.checklist__mark .icon { width: 11px; height: 11px; }

/* Grössere Variante für Unterseiten */
.checklist--lg { gap: 14px; }
.checklist--lg li { font-size: var(--fs-body); align-items: flex-start; }
.checklist--lg .checklist__mark { width: 22px; height: 22px; margin-top: 3px; }
.checklist--lg .checklist__mark .icon { width: 13px; height: 13px; }

/* ===== styles/components/accordion.css ===== */
/* ===== Akkordeon (FAQ) ==================================================
   Details/Summary als Basis: funktioniert auch ohne JavaScript.
   ======================================================================= */
.accordion { border-top: 1px solid var(--line); }

.accordion__item { border-bottom: 1px solid var(--line); }

.accordion__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  padding: 22px 2px;
  font-size: calc(17px * var(--fs-scale));
  font-weight: 600;
  line-height: 1.45;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-fast) var(--ease);
}
.accordion__summary::-webkit-details-marker { display: none; }
.accordion__summary:hover { color: var(--navy-800); }

.accordion__icon {
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--blue-600);
  transition: transform var(--dur) var(--ease);
}
.accordion__item[open] .accordion__icon { transform: rotate(180deg); }

.accordion__panel {
  padding: 0 44px 24px 2px;
  font-size: var(--fs-body-sm);
  line-height: 1.75;
  color: var(--text);
}
.accordion__panel p + p { margin-top: 12px; }

@media (prefers-reduced-motion: no-preference) {
  .accordion__item[open] .accordion__panel { animation: acc-in 350ms var(--ease); }
  @keyframes acc-in { from { opacity: 0; transform: translateY(-6px); } }
}

@media (max-width: 639px) {
  .accordion__summary { font-size: calc(16px * var(--fs-scale)); padding: 18px 2px; gap: 16px; }
  .accordion__panel { padding-right: 8px; }
}

/* ===== styles/components/form.css ===== */
/* ===== Formular =========================================================
   Label immer ueber dem Feld, Hilfetext darunter, Fehlertext unter dem Feld.
   Kontraste: Label 18.6:1, Platzhalter 5.1:1, Rahmen sichtbar auf Weiss.
   ======================================================================= */
.form { display: grid; gap: 20px; }

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

.field { display: grid; gap: 7px; }

.field__label {
  font-size: calc(14px * var(--fs-scale));
  font-weight: 600;
  color: var(--ink);
}
.field__label .req { color: var(--blue-600); margin-left: 2px; }

.field__hint { font-size: calc(13px * var(--fs-scale)); color: var(--text-soft); }

.field__control {
  width: 100%;
  min-height: 50px;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid #d7dae0;
  border-radius: var(--r-sm);
  font-size: calc(16px * var(--fs-scale));
  line-height: 1.5;
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.field__control::placeholder { color: #6a6e76; }  /* 5.1:1 auf Weiss - WCAG AA */
.field__control:hover { border-color: #c2c7d0; }
.field__control:focus {
  outline: none;
  border-color: var(--blue-600);
  /* Ueber ein Token, damit "Erhoehter Kontrast" auch hier greift. */
  box-shadow: 0 0 0 3px var(--focus-halo);
}
textarea.field__control { min-height: 140px; resize: vertical; }
select.field__control {
  appearance: none;
  /* Der Pfeil ist eine Grafik und kann currentColor nicht erben. Deshalb
     zwei Fassungen: hier die normale, die kraeftigere steht bei den
     Kontrast-Regeln in components/a11y-widget.css. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234c5057' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6.5 9.75 5.5 5.5 5.5-5.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 18px;
  padding-right: 42px;
}

/* Honigtopf der Spamabwehr (components/anfrage-form.html). Bewusst NICHT
   display: none: Einige Skripte ueberspringen Felder, die so ausgeblendet
   sind - genau die will man aber fangen. Aus dem Weg geraeumt wird es
   stattdessen ueber die Position, und aus dem Vorlesebaum nimmt es das
   aria-hidden im Markup. */
.form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
/* Auch das Feld selbst bekommt die Hoehe 0. Zwei Gruende: Es kann so unter
   keinen Umstaenden irgendwo aufblitzen, und es taucht nicht mehr als
   winziges Tippziel in scripts/responsive.mjs auf - der Pruefer ueberspringt
   Elemente ohne Hoehe. Fuer ein Skript, das stur jedes Feld nach Namen
   ausfuellt, aendert sich nichts; genau die will der Honigtopf fangen. */
.form__trap input {
  width: 1px;
  height: 0;
  padding: 0;
  border: 0;
  min-height: 0;
}

.field__error {
  display: none;
  font-size: calc(13px * var(--fs-scale));
  font-weight: 500;
  color: #b3261e;      /* 5.3:1 auf Weiss */
}
.field[data-invalid] .field__control { border-color: #b3261e; }
.field[data-invalid] .field__control:focus { box-shadow: 0 0 0 3px rgba(179, 38, 30, .15); }
.field[data-invalid] .field__error { display: block; }

/* Checkbox (Einwilligung) */
.field--check { grid-template-columns: auto 1fr; align-items: start; gap: 12px; }
.field--check input {
  /* 24px statt 19px: Pflichtfeld und zugleich das kleinste Ziel des
     Formulars. Das zugehoerige <label for> bleibt zusaetzlich klickbar. */
  width: 24px; height: 24px;
  margin-top: 1px;
  accent-color: var(--navy-800);
  flex: none;
}
.field--check label { font-size: calc(14px * var(--fs-scale)); line-height: 1.6; color: var(--text); }
.field--check a { color: var(--blue-600); text-decoration: underline; text-underline-offset: 2px; }

/* Status nach dem Absenden */
.form__status {
  display: none;
  align-items: flex-start;
  gap: 14px;
  padding: 18px 20px;
  border-radius: var(--r-sm);
  font-size: var(--fs-body-sm);
}
.form__status[data-state="success"] {
  display: flex;
  background: var(--blue-050);
  border: 1px solid #cfdcf3;
  color: var(--navy-900);
}
.form__status[data-state="error"] {
  display: flex;
  background: #fdf2f1;
  border: 1px solid #f2d2cf;
  color: #8c1d18;
}
.form__status .icon { flex: none; margin-top: 2px; }

@media (max-width: 639px) {
  .form__row { grid-template-columns: 1fr; }
}

/* ===== styles/components/quote-dialog.css ===== */
/* ===== Anfragefenster ===================================================
   Das Formular von kontakt.html, ueber die laufende Seite gelegt. Markup in
   components/anfrage-dialog.html, Verhalten in scripts/quote-dialog.js.

   Der Dialog selbst fuellt den ganzen Bildschirm und ist durchsichtig; das
   sichtbare Fenster ist .quote-dialog__panel darin. Das hat zwei Gruende:
   ein Klick neben das Panel trifft dadurch den Dialog und kann zum
   Schliessen ausgewertet werden, und das Panel laesst sich frei zentrieren,
   ohne gegen die Vorgabewerte von <dialog> anzukaempfen.
   ======================================================================= */
.quote-dialog {
  /* Vorgabefassung von <dialog> vollstaendig zuruecknehmen. */
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;

  display: grid;
  place-items: center;
  /* Auf dem Handy sitzt das Fenster unten - dort ist der Daumen. */
  align-items: end;
}
.quote-dialog:not([open]) { display: none; }

/* --- Der unscharfe Grund ------------------------------------------------
   backdrop-filter macht die Seite dahinter unscharf, die Farbe nimmt ihr
   zusaetzlich die Aufmerksamkeit. Wo backdrop-filter fehlt, bleibt die
   Farbe allein - dann ist der Hintergrund nicht verschwommen, aber immer
   noch deutlich zurueckgenommen.
   ------------------------------------------------------------------------- */
.quote-dialog::backdrop {
  background: rgba(10, 20, 44, .34);
  opacity: 0;
  transition: opacity 220ms var(--ease, ease);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .quote-dialog::backdrop {
    background: rgba(10, 20, 44, .26);
    -webkit-backdrop-filter: blur(9px) saturate(115%);
            backdrop-filter: blur(9px) saturate(115%);
  }
}
.quote-dialog.is-open::backdrop { opacity: 1; }

/* --- Das Fenster --------------------------------------------------------- */
.quote-dialog__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(100% - 32px, 760px);
  /* Nie hoeher als der Bildschirm: der Inhalt scrollt im Fenster, nicht die
     Seite dahinter. svh statt vh, damit die Leisten mobiler Browser den
     Absendeknopf nicht abschneiden. */
  max-height: min(92svh, 92vh);
  margin-block: 16px;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow:
    0 40px 80px -30px rgba(10, 20, 44, .55),
    0 4px 16px -8px rgba(10, 20, 44, .25);
  overflow: hidden;

  opacity: 0;
  transform: translateY(18px) scale(.985);
  transition:
    opacity 220ms var(--ease, ease),
    transform 220ms var(--ease, ease);
}
.quote-dialog.is-open .quote-dialog__panel {
  opacity: 1;
  transform: none;
}
.quote-dialog__panel:focus { outline: none; }

/* --- Kopf des Fensters ---------------------------------------------------
   Bleibt beim Scrollen stehen: bei einem langen Formular soll das
   Schliesskreuz immer erreichbar sein, ohne erst nach oben zu scrollen. */
.quote-dialog__head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 26px 28px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.quote-dialog__title { margin-top: 6px; }

.quote-dialog__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  /* 44px: auch mit dem Finger sicher zu treffen. */
  width: 44px;
  height: 44px;
  margin: -6px -6px 0 0;
  border-radius: var(--r-full);
  color: var(--text);
  transition:
    background-color var(--dur-fast, 150ms) var(--ease, ease),
    color var(--dur-fast, 150ms) var(--ease, ease),
    transform var(--dur-fast, 150ms) var(--ease, ease);
}
.quote-dialog__close:hover {
  background: var(--blue-050);
  color: var(--navy-800);
  transform: rotate(90deg);
}
.quote-dialog__close:active { transform: rotate(90deg) scale(.92); }

/* --- Inhalt --------------------------------------------------------------- */
.quote-dialog__body {
  padding: 4px 28px 28px;
  overflow-y: auto;
  overscroll-behavior: contain;   /* Scrollt am Ende nicht die Seite dahinter */
  -webkit-overflow-scrolling: touch;
}
/* Der Abstand kommt hier vom Polster des Fensters. */
.quote-dialog__body .form { margin-top: 0; }

/* Die Seite dahinter haelt still, solange das Fenster offen ist. */
body.is-dialog-open { overflow: hidden; }

/* --- Schmale Fenster ------------------------------------------------------
   Das Panel sitzt unten und laeuft bis an den unteren Rand - wie ein Blatt,
   das von unten hereingezogen wird. Das ist auf dem Handy der gewohnte Weg
   und legt den Absendeknopf in Daumennaehe.
   ------------------------------------------------------------------------- */
@media (max-width: 639px) {
  .quote-dialog__panel {
    width: 100%;
    max-height: min(94svh, 94vh);
    margin-block: 0;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    transform: translateY(26px);
  }
  .quote-dialog__head { padding: 20px 20px 16px; }
  .quote-dialog__body { padding: 4px 20px 24px; }
}

/* --- Ohne Bewegung --------------------------------------------------------
   Das Fenster erscheint dann ohne Uebergang. Wichtig ist nur, dass es
   sichtbar ist - der Anfangszustand darf nicht stehen bleiben.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .quote-dialog::backdrop,
  .quote-dialog__panel {
    transition-duration: 1ms;
  }
  .quote-dialog__panel { transform: none; }
  .quote-dialog__close:hover,
  .quote-dialog__close:active { transform: none; }
}

/* ===== styles/components/footer.css ===== */
/* ===== Fusszeile ========================================================
   Referenz: 216 px hoch, vier Spalten (1.4 / 1 / 1 / 1.6),
   darunter eine schmale Zeile mit Copyright und Rechtslinks.
   ======================================================================= */
.site-footer {
  background: var(--surface);
  border-top: 1px solid var(--line);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.6fr;
  gap: 32px;
  padding-block: 18px 22px;
}

.site-footer__about { max-width: 250px; }
.site-footer__about > .logo { display: flex; width: max-content; }
.site-footer__blurb {
  margin-top: 7px;
  font-size: calc(14px * var(--fs-scale));
  line-height: 1.35;
  color: var(--text);
}

.site-footer__heading {
  font-size: calc(12px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink);
}

.site-footer__col { padding-top: 6px; }
.site-footer__links { margin-top: 14px; display: grid; gap: 0; }
.site-footer__links a {
  display: inline-block;
  /* Aus 14px Schrift und Zeilenhoehe 1.3 ergeben sich 18px. Das Polster
     hebt das Tippziel auf 28px - auf dem Handy sind das gestapelte Links
     direkt untereinander, keine Verweise im Fliesstext. */
  padding-block: 5px;
  font-size: calc(14px * var(--fs-scale));
  line-height: 1.3;
  color: var(--text);
  transition: color var(--dur-fast) var(--ease), translate var(--dur) var(--ease);
}
.site-footer__links a:hover { color: var(--navy-800); translate: 3px 0; }

/* Kontaktliste */
.site-footer__contact { margin-top: 14px; display: grid; gap: 12px; }
.site-footer__contact li { display: flex; align-items: center; gap: 16px; }
/* Mehrzeilige Angaben (Anschrift, Einsatzgebiet): Symbol auf Hoehe der
   ersten Zeile ausrichten statt mittig zum ganzen Block. */
.site-footer__contact li.site-footer__contact-block { align-items: flex-start; }
.site-footer__contact-block .icon { margin-top: 3px; }
.site-footer__contact .icon { width: 18px; height: 18px; color: var(--ink); flex: none; }
.site-footer__contact a,
.site-footer__contact span {
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  color: var(--text);
}
/* Einschraenkender Zusatz unter einer Angabe (Gewichtsgrenze im EU-Verkehr).
   Leiser gesetzt als die Hauptzeile, aber bewusst nicht so klein, dass er
   als Kleingedrucktes durchgeht - er schraenkt ein Werbeversprechen ein. */
.site-footer__contact .site-footer__qualifier {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--text-soft);
}

/* Telefon und E-Mail sind auf dem Handy die wichtigsten Ziele der Seite. */
.site-footer__contact a { display: inline-block; padding-block: 4px; }
.site-footer__contact a { transition: color var(--dur-fast) var(--ease); }
.site-footer__contact a:hover { color: var(--navy-800); }

/* Social */
.social { display: flex; gap: 12px; margin-top: 2px; }
.social a {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-full);
  color: var(--ink);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease),
              background-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.social .icon { width: 15px; height: 15px; }
.social a:hover {
  background: var(--navy-800);
  border-color: var(--navy-800);
  color: #fff;
  transform: translateY(-2px);
}

/* Untere Zeile */
.site-footer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding-block: 9px 10px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-micro);
  line-height: 1.35;
  color: var(--text-soft);
}
/* flex-wrap seit dem 22.09.2026: Die Leiste traegt jetzt vier Eintraege -
   die drei Pflichtlinks und den Weg in die andere Sprache. Auf breiten
   Bildschirmen stehen sie wie zuvor in einer Zeile; auf schmalen bricht
   die Zeile um, statt die ganze Seite waagrecht scrollen zu lassen.
   row-gap ist kleiner als column-gap: zwei Zeilen sollen als eine Leiste
   lesbar bleiben und nicht als zwei Bloecke. */
.site-footer__legal {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 14px;
}
.site-footer__legal a {
  display: inline-block;
  padding-block: 5px;
  transition: color var(--dur-fast) var(--ease);
}
.site-footer__legal a:hover { color: var(--navy-800); }
.site-footer__legal span { color: var(--line-strong); }

/* --- Entwicklernachweis ------------------------------------------------
   Steht unter der Rechtsleiste. Leiser gesetzt als die Pflichtlinks: er
   soll lesbar sein, aber Impressum und Datenschutz nicht ueberstrahlen. */
.site-footer__credit {
  padding-bottom: 12px;
  font-size: var(--fs-micro);
  line-height: 1.4;
  color: var(--text-soft);
}
.site-footer__credit a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--dur-fast) var(--ease);
}
.site-footer__credit a:hover { color: var(--navy-800); }

@media (max-width: 1023px) {
  .site-footer__grid { grid-template-columns: 1fr 1fr; gap: 36px 32px; padding-block: 40px 32px; }
  .site-footer__about { grid-column: 1 / -1; max-width: 46ch; }
}
/* Beruehrungsbedienung: Breite ODER grober Zeiger. Die zweite Bedingung
   holt Tablets im Hochformat mit, die bei 768px sonst durchs Raster fielen. */
@media (max-width: 639px), (pointer: coarse) {
  /* Icon-Schaltflaechen ohne Text: am Finger gemessen, nicht an der Maus.
     Mit Maus bleiben die 30px der Vorlage. */
  .social { gap: 8px; }
  .social a { width: 44px; height: 44px; }
  .social .icon { width: 18px; height: 18px; }

  /* Untereinander stehende Links: 44px Zeilenhoehe. Die Fusszeile wird
     dadurch laenger, ist aber mit dem Daumen sicher zu treffen. */
  .site-footer__links a,
  .site-footer__contact a,
  .site-footer__legal a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding-block: 0;
  }
  .site-footer__contact { gap: 4px; }
  /* Die 4px sind auf die 44px hohen Linkzeilen gemuenzt. Die mehrzeiligen
     Textbloecke haben keine Mindesthoehe und liefen sonst ineinander. */
  .site-footer__contact li.site-footer__contact-block { margin-top: 12px; }

  /* Das Barrierefreiheits-Widget schwebt unten rechts (48px + 16px Rand).
     Am Seitenende laesst sich nicht weiterscrollen, deshalb bekommt die
     letzte Zeile hier festen Freiraum darunter. */
  .site-footer__bar { padding-bottom: 0; }
  .site-footer__credit { padding-bottom: 74px; }
  /* Auch dieser Link wird mit dem Daumen getroffen. */
  .site-footer__credit a { display: inline-flex; align-items: center; min-height: 44px; }
}

@media (max-width: 559px) {
  .site-footer__grid { grid-template-columns: 1fr; gap: 30px; }
  .site-footer__bar { justify-content: flex-start; gap: 10px; }
}

/* ===== styles/components/a11y-widget.css ===== */
/* ===== Barrierefreiheits-Widget =========================================
   Helles Panel in der Markensprache: weisse Flaeche, Haarlinien, Navy als
   aktiver Zustand. Nutzt durchgehend die Tokens der Seite, damit sich das
   Widget wie ein Teil der Seite anfuehlt und nicht wie ein Fremdkoerper.

   Ausnahme: die Schriftgroessen hier sind feste px-Werte. "Groessere
   Schrift" darf das Bedienpanel nicht sprengen, mit dem es abgeschaltet
   wird.
   ======================================================================= */
.a11y {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: var(--z-a11y);
  font-family: var(--font-sans);
}

/* --- Schaltflaeche -------------------------------------------------------- */
.a11y__fab {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-left: auto;
  border-radius: var(--r-full);
  background: var(--navy-800);
  color: #fff;
  box-shadow: 0 10px 26px -8px rgba(15, 36, 82, .5), 0 2px 6px rgba(16, 32, 64, .14);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.a11y__fab .icon { width: 28px; height: 28px; }
.a11y__fab:hover {
  background: var(--navy-700);
  transform: translateY(-2px);
  box-shadow: 0 16px 32px -10px rgba(15, 36, 82, .55), 0 2px 6px rgba(16, 32, 64, .14);
}
.a11y__fab[aria-expanded="true"] { background: var(--navy-700); }

/* --- Panel ---------------------------------------------------------------- */
.a11y__panel {
  position: absolute;
  right: 0;
  bottom: calc(52px + 14px);
  width: 340px;
  max-height: calc(100vh - 120px);
  max-height: calc(100svh - 120px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 26px 56px -22px rgba(16, 32, 64, .34), 0 4px 14px rgba(16, 32, 64, .07);
}
.a11y__panel[hidden] { display: none; }

.a11y__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 12px 13px 18px;
  border-bottom: 1px solid var(--line);
}
.a11y__title {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink);
}
.a11y__close {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: var(--r-full);
  color: var(--text-soft);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.a11y__close:hover { background: var(--blue-050); color: var(--ink); }

.a11y__body {
  padding: 18px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.a11y__section + .a11y__section { margin-top: 22px; }

/* Abschnittsmarke im Eyebrow-Stil der Seite */
.a11y__label {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 12px;
  /* 11px war fuer ein Barrierefreiheits-Panel zu klein. */
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--blue-600);
}

/* --- Sprache -------------------------------------------------------------- */
.a11y-lang {
  padding: 18px 16px 16px;
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  background: var(--surface-soft);
}

.a11y-globe {
  position: relative;
  display: grid;
  place-content: center;
  justify-items: center;
  width: 132px;
  height: 132px;
  margin: 0 auto 18px;
  overflow: hidden;
  border-radius: var(--r-full);
  background: linear-gradient(150deg, #4a7fd8 0%, #2a55a8 46%, #14336f 100%);
  box-shadow: 0 12px 26px -10px rgba(20, 51, 111, .55);
}
.a11y-globe__mesh {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: rgba(255, 255, 255, .3);
  stroke-width: 1;
}
.a11y-globe__code {
  position: relative;
  font-size: 34px;
  font-weight: 800;
  letter-spacing: .02em;
  line-height: 1;
  color: #fff;
}
.a11y-globe__name {
  position: relative;
  margin-top: 6px;
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, .9);
}

/* Segmentierter Umschalter: aktives Segment im Navy des Primaerbuttons */
.a11y-seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--line-card);
  border-radius: var(--r-full);
  background: var(--surface);
}
.a11y-seg__btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 9px 6px 10px;
  border-radius: var(--r-full);
  color: var(--text-soft);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.a11y-seg__btn:hover { background: var(--blue-050); color: var(--ink); }
.a11y-seg__btn[aria-checked="true"] {
  background: var(--navy-800);
  color: #fff;
}
.a11y-seg__btn[aria-checked="true"]:hover { background: var(--navy-700); color: #fff; }
/* Die Sprachwahl ist seit dem 22.09.2026 ein Link auf die andere Fassung
   derselben Seite und kein Radiofeld mehr. aria-current ist dafuer die
   richtige Auszeichnung; die Gestaltung bleibt unveraendert. */
.a11y-seg__btn[aria-current="page"] {
  background: var(--navy-800);
  color: #fff;
}
.a11y-seg__btn[aria-current="page"]:hover { background: var(--navy-700); color: #fff; }
.a11y-seg__code { font-size: 14px; font-weight: 700; letter-spacing: .04em; }
.a11y-seg__name { font-size: 12px; font-weight: 500; }

/* --- Schalterzeilen ------------------------------------------------------- */
.a11y-opts { border-top: 1px solid var(--line); }

.a11y-opt {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: start;
  gap: 12px;
  padding: 15px 2px 16px;
  border-bottom: 1px solid var(--line);
}
.a11y-opt__icon { color: var(--blue-600); padding-top: 1px; }
.a11y-opt__text { display: block; }
.a11y-opt__title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink);
}
.a11y-opt__desc {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text);
}

.a11y-switch {
  position: relative;
  width: 46px;
  height: 26px;
  flex: none;
  margin-top: 2px;
  border-radius: var(--r-full);
  background: #d7dae1;
  transition: background-color var(--dur) var(--ease);
}
.a11y-switch:hover { background: #c7cbd4; }
.a11y-switch__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: var(--r-full);
  background: #fff;
  box-shadow: 0 1px 3px rgba(16, 32, 64, .28);
  transition: translate var(--dur) var(--ease);
}
.a11y-switch[aria-checked="true"] { background: var(--navy-800); }
.a11y-switch[aria-checked="true"]:hover { background: var(--navy-700); }
.a11y-switch[aria-checked="true"] .a11y-switch__knob { translate: 20px 0; }

/* Zuruecksetzen im Stil des Ghost-Buttons */
.a11y__reset {
  margin-top: 18px;
  width: 100%;
  padding: 11px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.a11y__reset:hover {
  background: var(--surface-soft);
  border-color: #cfd3da;
  color: var(--ink);
}

/* --- Einblenden ----------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .a11y__panel:not([hidden]) { animation: a11y-in 300ms var(--ease); }
  @keyframes a11y-in {
    from { opacity: 0; transform: translateY(10px) scale(.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
  }
}

/* --- Kleine Schirme ------------------------------------------------------- */
@media (max-width: 479px) {
  .a11y { right: 16px; bottom: 16px; }
  .a11y__fab { width: 48px; height: 48px; }
  .a11y__fab .icon { width: 25px; height: 25px; }
  .a11y__panel {
    position: fixed;
    right: 16px;
    left: 16px;
    bottom: 76px;
    width: auto;
    max-height: calc(100svh - 108px);
  }
  .a11y-globe { width: 110px; height: 110px; }
  .a11y-globe__code { font-size: 29px; }
}

@media print { .a11y { display: none !important; } }

/* =======================================================================
   Wirkung der Schalter auf die gesamte Seite
   ======================================================================= */

/* Groessere Schrift: alle Schriftgroessen haengen an --fs-scale. */
:root[data-a11y-font="lg"] { --fs-scale: 1.15; }

/* Erhoehter Kontrast: dunklerer Fliesstext, kraeftigere Linien,
   unterstrichene Textlinks. Flaechen bleiben weiss. */
:root[data-a11y-contrast="high"] {
  --ink:         #000205;
  --ink-soft:    #0a0c11;
  --text:        #26292f;
  --text-soft:   #35383f;
  --line:        #c4c7ce;
  --line-strong: #a9adb6;
  --line-card:   #a9adb6;
  --surface-soft: #ffffff;
  --surface-band: #f0f2f5;
  --blue-600:    #1b3f88;
  --blue-500:    #1b3f88;
}
/* Zwei Stellen koennen keine Token erben: der Schein um fokussierte
   Eingabefelder und der Pfeil im Auswahlfeld (eine Grafik mit fester Farbe).
   Beide bekommen hier ihre kontrastreiche Fassung. */
:root[data-a11y-contrast="high"] {
  --focus-halo: rgba(27, 63, 136, .32);
}
:root[data-a11y-contrast="high"] select.field__control {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2326292f' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6.5 9.75 5.5 5.5 5.5-5.5'/%3E%3C/svg%3E");
}

:root[data-a11y-contrast="high"] .prose a,
:root[data-a11y-contrast="high"] .link-arrow,
:root[data-a11y-contrast="high"] .site-footer__links a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ===== Sprachabhaengige Bilder ==========================================
   Manche Motive tragen Text im Bild. Fuer die gibt es zwei Fassungen, und
   die Sprache der SEITE entscheidet, welche steht:

     <img data-lang-img="de" ...>   Deutsch
     <img data-lang-img="en" ...>   English

   Seit dem 22.09.2026 haengt die Regel an <html lang> und nicht mehr an
   einem data-Attribut aus dem Widget. Grund: Die Sprache ist jetzt die
   Seite selbst (en/ gegenueber der Wurzel) und keine Einstellung mehr.
   Damit greift die Regel auch ohne JavaScript und ohne localStorage.

   Beide Zweige haengen an :root, damit sie ueber den Bausteinen liegen:
   styles/components/ kommt im Buendel VOR styles/sections/, und dort setzt
   etwa .individual__photo ein display. Ohne den :root-Vorsatz waere die
   spaetere Regel gleich stark und gewaenne.

   Geschrieben ist es als eine Regel mit :not() statt als zwei mit einem
   Zuruecksetzen auf display:block. So behalten die Bilder die Darstellungs-
   art ihres Bausteins - ein Rasterbild bliebe ein Rasterbild.
   ======================================================================= */
:root[lang="en"] [data-lang-img="de"],
:root:not([lang="en"]) [data-lang-img="en"] {
  display: none;
}

/* ===== styles/sections/hero-two.css ===== */
/* ===== Auftakt der zweiten Startseite ===================================
   Ein Foto über die volle Breite, darauf zwei Ebenen: links die Aussage im
   hellen Himmel, rechts der Angebotsrechner. Die Kopfzeile liegt wie auf
   der ersten Startseite im Bild (bodyClass "page-start"), deshalb haelt der
   Auftakt oben deren Bauhoehe frei.

   Der Angebotsrechner arbeitet seit dem 20.09.2026: Er nimmt die beiden
   Adressen entgegen und oeffnet damit das Anfragefenster. Das Verhalten
   steht in scripts/quote-dialog.js, das Markup im Kopf von
   src/pages/index.html. Hier geht es nur um sein Aussehen.
   ======================================================================= */
.hero2 {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

/* --- Das Foto liegt hinter allem und fuellt die ganze Breite ------------- */
.hero2__media {
  position: absolute;
  inset: 0;
  z-index: -1;
}
.hero2__media img {
  width: 100%;
  height: 100%;
  /* 16:9 - auf den ueblichen Fensterformaten bleibt fast das ganze Motiv
     stehen, es wird also kaum hineingezoomt. */
  object-fit: cover;
  object-position: 50% center;
}
/* Weisser Schleier nur hinter der Aussage: er sichert den Kontrast von
   Ueberschrift und Unterzeile und laeuft knapp darunter aus.

   23.09.2026 (Kundenwunsch): Der seitliche Verlauf von links ist entfallen,
   und der Verlauf von oben reicht nicht mehr bis zur Bildmitte, sondern
   endet gleich unter der Unterzeile. Unter der Aussage liegt das Foto
   unverschleiert.

   Der Schleier haengt deshalb am Auftakt und nicht mehr am Foto: das Foto
   ist auf der Startseite oben und unten ueber den Abschnitt hinaus gezogen
   (startseite-2.css), seine Oberkante liegt also nicht dort, wo der Text
   gemessen wird. --hero-veil ist die Hoehe, bei der er ganz ausgelaufen
   ist - gemessen ab Oberkante Auftakt, rund 40 px unter der Unterzeile.
   Der Textanteil waechst mit --fs-scale mit, sonst liefe die Unterzeile
   bei "Groessere Schrift" (Barrierefreiheits-Widget) unter dem Schleier
   hinaus. */
.hero2 { --hero-veil: calc(var(--header-total-start) + 240px * var(--fs-scale)); }
.hero2::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: var(--hero-veil);
  /* Gleiche Ebene wie das Foto, aber spaeter im Dokument - liegt also
     darueber und unter dem Text. */
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, .78) 0%,
    rgba(255, 255, 255, .42) 60%,
    rgba(255, 255, 255, 0) 100%);
}

/* --- Inhalt: Aussage links, Rechner rechts ------------------------------- */
.hero2__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 424px);
  gap: 48px;
  align-items: center;
  /* Der Auftakt fuellt genau einen Bildschirm - die Leiste liegt im Bild
     und nimmt keinen eigenen Platz weg. */
  min-height: 100vh;
  min-height: 100svh;
  /* Oben die Bauhoehe der schwebenden Leiste plus Luft. Rechts nur ein
     schmaler Rand, damit der Rechner weit aussen steht; links bleibt der
     Inhaltsrahmen der uebrigen Seite erhalten. */
  width: 100%;
  max-width: none;
  margin-inline: 0;
  padding-block: calc(var(--header-total-start) + 20px) 56px;
  padding-inline: max(var(--gutter), calc((100% - var(--container)) / 2)) 40px;
}

.hero2__claim {
  /* Breit genug, damit die Ueberschrift in zwei Zeilen steht und komplett
     im hellen Himmel ueber dem Fahrzeug bleibt. */
  align-self: start;
  max-width: 620px;
  /* Die Aussage steht mittig (Kundenwunsch): auf breiten Fenstern ueber die
     ganze Seitenbreite zentriert, darunter innerhalb der linken Spalte. */
  text-align: center;
  /* 23.09.2026: minimal hoeher gesetzt (Kundenwunsch). Nur die Aussage
     rueckt nach oben, der Rechner bleibt stehen. */
  margin-top: -16px;
}
.hero2__title {
  /* Kleiner als auf der ersten Startseite: die Aussage ist laenger und
     soll in zwei Zeilen stehen. */
  font-size: calc(44px * var(--fs-scale));
}
.hero2__lead {
  margin-top: 14px;
  max-width: 46ch;
  margin-inline: auto;
  /* Einen Punkt groesser als der uebrige Vorspann (--fs-lead: 18px). */
  font-size: calc(19px * var(--fs-scale));
}

.hero2__aside {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
/* --- Angebotsrechner ----------------------------------------------------- */
.quote-box {
  /* Aufbau aus der Kundenvorlage, Farben aus der Markenskala der Seite:
     der Handlungsaufruf traegt dasselbe Navy wie alle Hauptbuttons, die
     Hervorhebung dasselbe Blau wie die Vorzeilen. */
  --quote-accent: var(--blue-600);
  --quote-cta: var(--navy-800);
  --quote-cta-hover: var(--navy-700);
  --quote-shell: #e9edf3;

  width: 100%;
  max-width: 424px;
  background: var(--quote-shell);
  border-radius: 16px;
  overflow: hidden;
  /* Die Karte schwebt ueber dem Foto und braucht dafuer mehr Tiefe. */
  box-shadow:
    0 30px 60px -34px rgba(15, 36, 82, .7),
    0 4px 14px -8px rgba(16, 32, 64, .25);
}

/* Die weisse Flaeche liegt eine Spur in der Schale - rundum bleibt ein
   schmaler Rand sichtbar. */
.quote-box__body {
  margin: 7px;
  padding: 26px 24px 28px;
  background: var(--surface);
  border-radius: 12px;
}

.quote-box__title {
  text-align: center;
  font-size: calc(22px * var(--fs-scale));
  font-style: italic;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -.01em;
  color: var(--ink);
}
.quote-box__title span { color: var(--quote-accent); }

.quote-box__field { display: block; margin-top: 22px; }
.quote-box__label {
  display: block;
  margin-bottom: 8px;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--text);
}
.quote-box__field input {
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  background: #f0f2f6;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: var(--fs-body);
  color: var(--ink);
}
.quote-box__field input::placeholder { color: var(--text-soft); }

.quote-box__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  min-height: 58px;
  margin-top: 26px;
  padding-inline: 20px;
  background: var(--quote-cta);
  border-radius: var(--r-full);
  color: #fff;
  font-size: var(--fs-btn);
  font-weight: 700;
  line-height: 1.2;
  box-shadow: var(--shadow-btn);
  transition: background-color var(--dur-fast) var(--ease), box-shadow var(--dur) var(--ease);
}
.quote-box__cta:hover { background: var(--quote-cta-hover); box-shadow: var(--shadow-btn-hover); }
/* Der Button ist deaktiviert, soll aber wie in der Vorlage aussehen -
   deshalb keine ausgegraute Darstellung, nur der Zeiger verraet es. */
.quote-box__cta[disabled] { opacity: 1; cursor: default; }
.quote-box__cta[disabled]:hover { background: var(--quote-cta); box-shadow: var(--shadow-btn); }
.quote-box__cta .icon { flex: none; }

/* --- Aussage mittig auf der Seite ---------------------------------------
   Ab dieser Breite bleibt neben dem Rechner genug Luft, damit die Aussage
   ueber die volle Seitenbreite zentriert stehen kann, ohne ihn zu
   beruehren. Sie liegt dafuer absolut im Auftakt und nicht mehr in der
   linken Rasterspalte - der Rechner behaelt seinen Platz rechts.
   Auf schmaleren Fenstern bleibt die Aussage in der linken Spalte, dort
   aber ebenfalls zentriert gesetzt.

   22.09.2026: Schwelle von 1560px auf 1360px gesenkt (Kundenwunsch) - die
   seitenbreite Zentrierung greift damit schon auf uebliche Laptopbreiten.

   WARUM NICHT TIEFER: Die Ueberschrift selbst passt problemlos, sie sitzt
   ueber dem Rechner. Die Grenze setzt die UNTERZEILE. Sie steht mittig und
   waechst nach rechts in den Rechner hinein:

     1280px  10px Ueberdeckung
     1300px  beruehren sich genau
     1320px  10px Luft
     1360px  30px Luft   <- gewaehlt

   Wer tiefer will, muss die Unterzeile schmaler setzen (max-width unten)
   oder den Rechner nach unten schieben. */
@media (min-width: 1360px) {
  .hero2__claim {
    position: absolute;
    inset-inline: 0;
    top: calc(var(--header-total-start) + 64px);
    z-index: 1;
    margin-top: 0;
    max-width: none;
    padding-inline: var(--gutter);
  }
  .hero2__title {
    max-width: 780px;
    margin-inline: auto;
  }
  /* Die linke Rasterspalte ist jetzt leer - der Rechner muss deshalb
     ausdruecklich in der zweiten Spalte gehalten werden. */
  .hero2__aside { grid-column: 2; }

  /* Der Satz laeuft durch, bricht aber nach "Entruempelung" um: so bleibt
     die Zeile schmal genug, dass sie mittig unter der Ueberschrift nicht
     mehr an die Kuppelspitze im Foto stoesst. */
  .hero2__lead { max-width: 30ch; }

  /* Die Aussage steht hier tiefer (siehe top oben), der Schleier reicht
     entsprechend weiter hinab. */
  .hero2 { --hero-veil: calc(var(--header-total-start) + 300px * var(--fs-scale)); }
}

/* --- Zwischenbreiten ----------------------------------------------------- */
@media (max-width: 1199px) {
  .hero2__inner { gap: 36px; }
  .hero2__title { font-size: calc(38px * var(--fs-scale)); }
}

/* Flache Fenster: der Rechner braucht seinen Platz, also unten weniger
   Polster - der Auftakt bleibt trotzdem genau einen Bildschirm hoch. */
@media (min-width: 900px) and (max-height: 760px) {
  .hero2__inner { padding-block: calc(var(--header-total-start) + 12px) 28px; }
}

@media (max-width: 1023px) {
  .hero2__inner { grid-template-columns: minmax(0, 1fr) minmax(320px, 380px); }
  .hero2__media img { object-position: 46% center; }
}

/* --- Aussage UND Rechner im Foto ----------------------------------------
   Untereinander, aber beide IM Bild: erst die Aussage im hellen Himmel,
   darunter der Rechner - genau wie auf dem Desktop, nur gestapelt statt
   nebeneinander. Der Rechner steht nie auf der weissen Flaeche darunter.

   Dazu wird der Auftakt selbst zum Raster. Der Rahmen .hero2__inner gibt
   seine Kiste dafuer auf (display: contents), damit Foto, Aussage und
   Rechner gemeinsam darin liegen. Aussage und Rechner belegen die beiden
   Zeilen, das Foto laeuft ueber beide hinweg.

   Die Hoehe kommt damit aus dem Inhalt: das Foto ist immer genau so hoch
   wie Aussage plus Rechner. Es kann nie zu kurz werden und nichts kann
   darunter rutschen - auch nicht im Querformat oder bei vergroesserter
   Schrift.
   ------------------------------------------------------------------------- */
@media (max-width: 899px) {
  .hero2 {
    display: grid;
    grid-template-columns: 1fr;
    row-gap: 22px;
    /* Kein eigenes Polster mehr: der Abstand nach unten steckt jetzt im
       Rechner, damit ihn das Foto noch mittraegt. */
    padding-block: 0;
  }

  .hero2__inner { display: contents; }

  /* Das Foto liegt absolut in seiner Rasterzelle und spannt beide Zeilen:
     so fuellt es den ganzen Auftakt aus, ohne ihn mit seiner eigenen Hoehe
     aufzuspannen. */
  .hero2__media {
    position: relative;
    grid-column: 1;
    grid-row: 1 / 3;
  }
  .hero2__media img {
    position: absolute;
    /* Unten steht das Motiv 14 % ueber den Auftakt hinaus; .hero2 hat
       overflow: hidden und schneidet es dort ab.

       Warum ueberhaupt: Senkrecht wird auf dem Handy nichts beschnitten -
       das Bild fuellt die Hoehe des Auftakts genau aus. Der KI-Vermerk sitzt
       auf 84 % der Bildhoehe und landete damit immer auf 84 % der
       Auftaktshoehe, also rund 100 px ueber der weissen Flaeche. Dieser
       Abstand liess sich durch eine niedrigere Hoehe nicht verkleinern - er
       waechst ja mit. Erst der Ueberstand nach unten verschiebt den Vermerk
       ans Ende: 84 % von 114 % sind 96 % der sichtbaren Hoehe.

       Der Schleier (.hero2::after) haengt am Auftakt, nicht am Bild, und
       wandert deshalb nicht mit. */
    inset: 0;
    /* Hochformatiger Ausschnitt: etwas weiter nach rechts als auf dem
       Desktop, damit neben dem Transporter noch Stadt zu sehen bleibt. */
    /* Hochformatiger Ausschnitt: etwas weiter nach rechts als auf dem
       Desktop, damit neben dem Transporter noch Stadt zu sehen bleibt. */
    object-position: 42% center;
  }

  /* Der Auftakt beginnt hier unter der Kopfleiste, der Schleier braucht
     deren Hoehe also nicht mehr mitzurechnen. Er endet knapp unter der
     Unterzeile; darunter bleibt das Motiv unangetastet, damit Transporter
     und Stadt rund um den Rechner sichtbar bleiben. */
  .hero2 { --hero-veil: calc(250px * var(--fs-scale)); }
  .hero2::after {
    background:
      linear-gradient(180deg,
        rgba(255, 255, 255, .82) 0%,
        rgba(255, 255, 255, .62) 30%,
        rgba(255, 255, 255, .26) 70%,
        rgba(255, 255, 255, 0) 100%);
  }

  /* Die Aussage steht oben im Foto, wo der Himmel hell ist - wie auf dem
     Desktop. Die Mindesthoehe gibt dem Motiv Luft zwischen Text und
     Rechner; braucht der Text mehr, waechst das Foto mit. */
  .hero2__claim {
    grid-column: 1;
    grid-row: 1;
    /* Nur wenig hoeher als der Text selbst - der Rechner soll weit oben im
       Bild sitzen. Die Hoehe des Fotos kommt stattdessen aus dem Polster
       unter dem Rechner. Auf flachen Fenstern greift der svh-Anteil und
       der Auftakt bleibt trotzdem auf einem Bildschirm. */
    min-height: min(30svh, 240px);
    max-width: none;
    margin-top: 0;
    padding-block: 16px 0;
  }

  .hero2__aside {
    grid-column: 1;
    grid-row: 2;
    /* Rechts in die freie Flaeche des Fotos - dieselbe Ecke wie auf dem
       Desktop. Links bleibt dadurch der Transporter sichtbar, statt dass
       der Rechner das ganze Motiv zudeckt. */
    align-items: flex-end;
    /* Das Polster liegt im Rechner, nicht im Auftakt - so reicht das Foto
       bis zur Unterkante des Abschnitts. Es traegt hier zugleich die Hoehe
       des Motivs: unter dem Rechner bleibt dadurch der Vorplatz sichtbar,
       statt dass die Karte am unteren Bildrand klebt. */
    padding-bottom: clamp(44px, 15svh, 120px);
  }

  /* Ersetzt den Innenrahmen, den .hero2__inner eben abgegeben hat. */
  .hero2__claim,
  .hero2__aside {
    width: min(100% - (var(--gutter) * 2), var(--container));
    margin-inline: auto;
  }

  /* Die Breite waechst mit dem Fenster mit, bleibt aber immer deutlich
     schmaler als das Foto: 60% der Fensterbreite, nach unten begrenzt auf
     eine noch bedienbare Formularbreite, nach oben auf das Desktopmass.
     Nur wenn das Fenster so schmal ist, dass selbst 280px nicht mehr
     hineinpassen, nimmt der Rechner die volle Breite. */
  .quote-box {
    width: clamp(214px, 43vw, 400px);
    max-width: 100%;
    margin-inline: 0;
  }
}

/* --- Handy ---------------------------------------------------------------
   Der Rechner wird hier nicht nur schmaler, sondern auch flacher: engeres
   Polster, kleinere Schrift, niedrigere Felder. Sonst waere die Karte zwar
   schmal, aber so hoch, dass sie das Foto doch wieder zudeckt. Die
   Tippflaechen bleiben dabei ueber 44px.
   ------------------------------------------------------------------------- */
@media (max-width: 639px) {
  .hero2__title { font-size: calc(30px * var(--fs-scale)); }

  .quote-box { border-radius: 12px; }
  .quote-box__body { margin: 4px; padding: 12px 11px 14px; border-radius: 9px; }
  .quote-box__title { font-size: calc(15px * var(--fs-scale)); line-height: 1.2; }
  .quote-box__field { margin-top: 9px; }
  .quote-box__label { margin-bottom: 4px; font-size: calc(12px * var(--fs-scale)); }
  /* Die Schriftgroesse der Felder bleibt bei 16px. Alles darunter laesst
     iOS Safari beim Antippen in die Seite hineinzoomen - der Auftakt
     springt dann aus dem Bild. Geschmaelert wird nur das Polster, und die
     Tippflaechen bleiben mit 44px auf dem geforderten Mindestmass. */
  .quote-box__field input {
    min-height: 44px;
    padding-inline: 11px;
  }
  /* Der Platzhalter darf kleiner sein als das Eingabefeld: iOS zoomt an der
     Schriftgroesse des Feldes, nicht an der des Platzhalters. So passt die
     Beispieladresse auch in die schmale Karte, ohne abgeschnitten zu werden. */
  .quote-box__field input::placeholder { font-size: calc(12px * var(--fs-scale)); }
  .quote-box__cta {
    min-height: 44px;
    margin-top: 11px;
    padding-inline: 9px;
    gap: 6px;
    font-size: calc(14px * var(--fs-scale));
  }
  .quote-box__cta .icon { width: 15px; height: 15px; }
}

/* --- Schleier: Hoehe je nach Umbruch der Aussage -------------------------
   Der Schleier soll knapp unter der Unterzeile enden (--hero-veil, siehe
   oben). Wie tief die Unterzeile steht, haengt davon ab, wie oft
   Ueberschrift und Unterzeile umbrechen - gemessen am 23.09.2026:

     640-899px   Unterzeile endet bei ca. 164px  -> 210px
     340-639px   ca. 177-211px                   -> 250px (Grundwert)
     unter 340px bricht zweimal mehr um, bis 276px -> 320px             */
@media (min-width: 640px) and (max-width: 899px) {
  .hero2 { --hero-veil: calc(210px * var(--fs-scale)); }
}
@media (max-width: 339px) {
  .hero2 { --hero-veil: calc(320px * var(--fs-scale)); }
}

/* Mit "Groessere Schrift" bricht die Ueberschrift unter 374px in vier
   Zeilen um, die Unterzeile endet dann bei bis zu 349px (gemessen
   23.09.2026 bei 320-373px). Der skalierte Grundwert reichte nicht. */
@media (max-width: 373px) {
  :root[data-a11y-font="lg"] .hero2 { --hero-veil: 390px; }
}

/* ===== styles/sections/support.css ===== */
/* ===== So viel Unterstützung, wie Sie möchten ===========================
   Drei gleichwertige Varianten. Bewusst keine Preisstufe, keine
   hervorgehobene Karte und kein Bestseller-Band: die Karten unterscheiden
   sich nur darin, wie viel Arbeit abgegeben wird, nicht in der Wertigkeit.
   Deshalb tragen alle drei dieselbe graue Flaeche, denselben Aufbau und
   denselben Button.

   Beim Scrollen fliegen sie nacheinander von oben an ihren Platz, von links
   nach rechts: ausgeloest allein davon, dass der Bereich ins Bild kommt
   (scripts/reveal.js), danach laeuft die Bewegung selbstaendig ab - nicht an
   die Scrollposition gekoppelt und nur einmal je Seitenaufruf.
   ======================================================================= */
.support {
  padding-block: 74px 78px;
  border-top: 1px solid var(--line);
}

.support__head { max-width: 62ch; }
.support__title { margin-top: 13px; }
.support__lead  { margin-top: 16px; }

/* Die Vorzeile dieses Abschnitts steht groesser als die uebrigen: sie traegt
   die zentrale Aussage der Seite und soll schon vor der Ueberschrift greifen.
   Bei mehr Schriftgroesse wird die Sperrung zurueckgenommen, sonst zerfaellt
   die Zeile. */
.support__eyebrow {
  font-size: calc(18px * var(--fs-scale));
  letter-spacing: .12em;
}

.support__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-cards);
  margin-top: 44px;
}

/* Die Karte ist eine ruhige graue Flaeche ohne Rahmen. Reihenfolge:
   Kennzeichnung, Ueberschrift, Text, Bild, Button - der Button sitzt bei
   allen dreien buendig auf einer Linie. */
.support-card {
  display: flex;
  flex-direction: column;
  padding: 34px 32px 32px;
  background: var(--surface-tile);
  border-radius: var(--r-lg);
  /* Etwas laenger als der Standard: der Weg von oben ist weiter als das
     uebliche Einblenden. */
  --reveal-dur: 1000ms;
  transition:
    background-color var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}
.support-card:hover {
  background: #eaecf1;
  transform: translateY(-3px);
}

/* Kennzeichnung: Nummer und Name der Variante, gesperrt in Versalien und im
   Markenblau der uebrigen Vorzeilen (6,3:1 auf der grauen Flaeche). */
.support-card__eyebrow {
  display: flex;
  gap: 12px;
  font-size: calc(12.5px * var(--fs-scale));
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--blue-600);
}

.support-card__title {
  margin-top: 18px;
  font-size: calc(22px * var(--fs-scale));
  font-weight: 600;
  line-height: 1.28;
  letter-spacing: -.01em;
  color: var(--ink);
}

.support-card__text {
  margin-top: 14px;
  font-size: var(--fs-body-sm);
  line-height: 1.65;
  color: var(--text);
}

/* Das Bild steht unter dem Text und traegt dieselbe Rundung wie die Karte,
   nur eine Stufe kleiner. Festes Seitenverhaeltnis: kein Springen beim
   Laden, unabhaengig davon, wie hoch die Datei ist. */
.support-card__media {
  margin-top: 24px;
  margin-bottom: 28px;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 12px;
}

/* Button: gefuellte Flaeche statt Rahmen, Label in gesperrten Versalien.
   margin-top:auto schiebt ihn nach unten, damit die drei Handlungsaufrufe
   trotz unterschiedlich langer Texte auf einer Linie sitzen. */
.support-card__action {
  --btn-h: 56px;
  --btn-px: 16px;
  margin-top: auto;
  background: var(--surface-tile-strong);
  color: var(--ink);
  border-radius: 10px;
  font-size: calc(13px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* Beim Hover kippt der Button ins Navy des Hauptbuttons - dieselbe
   Reaktion wie beim Anfrage-Button in der Kopfzeile. */
.support-card__action:hover {
  background: var(--navy-800);
  color: #fff;
  box-shadow: var(--shadow-btn-hover);
  transform: translateY(-1px);
}

/* ---- Gemeinsamer Vertrauensbereich unter den drei Varianten ------------ */
.support__note {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 32px 56px;
  margin-top: var(--gap-cards);
  padding: 30px 32px;
  background: var(--surface-soft);
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
}

.support__note-title {
  font-size: var(--fs-h3);
  line-height: 1.3;
  color: var(--ink);
}
.support__note-text {
  margin-top: 10px;
  font-size: var(--fs-body-sm);
  line-height: 1.65;
  color: var(--text);
}

.support__note-claim {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: calc(15.5px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--ink);
}
.support__note-claim .icon {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--blue-700);
}

/* Tablet: zwei Karten nebeneinander, die dritte mittig darunter statt
   linksbuendig. Das Raster laeuft dafuer auf vier gleich breiten Spalten,
   jede Karte belegt zwei davon - so bleiben die Kartenbreiten exakt die des
   Zweispalters, und die letzte Karte beginnt in Spalte 2 und steht damit
   mittig. Bewusst in der bestehenden max-width-Kaskade statt in einem
   eigenen min-width-Bereich: auf Geraeten mit gebrochenem Pixelverhaeltnis
   (z.B. dpr 1.25) liegt die Viewportbreite zwischen den ganzen Pixeln, eine
   zusaetzliche 640px-Grenze liesse dort den Dreispalter durchschlagen.
   Den Einspalter setzt der 639px-Block weiter unten zurueck. */
@media (max-width: 1023px) {
  .support { padding-block: 58px 60px; }
  .support__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 36px; }
  .support-card { grid-column: span 2; }
  .support-card:last-child { grid-column: 2 / span 2; }
  .support__note { padding: 26px 26px; gap: 24px 40px; }
}

@media (max-width: 767px) {
  .support__note { grid-template-columns: 1fr; }
}

@media (max-width: 639px) {
  .support { padding-block: 46px 48px; }
  /* Kuerzerer Weg auf schmalen Geraeten: die Karten stehen untereinander,
     ein langer Anflug liefe ueber die Karte darueber. */
  .support-card { --reveal-shift: -32px; }
  .support__eyebrow { font-size: calc(15px * var(--fs-scale)); letter-spacing: .1em; }
  /* Handyansicht unveraendert: eine Karte pro Zeile - das Vierer-Raster
     und die Spaltenzuweisung des Tabletblocks werden dafuer zurueckgesetzt. */
  .support__grid { grid-template-columns: 1fr; }
  .support-card,
  .support-card:last-child { grid-column: auto; }
  .support-card { padding: 26px 22px 24px; }
  .support-card__title { font-size: calc(20px * var(--fs-scale)); margin-top: 14px; }
  .support-card__media { margin-top: 20px; margin-bottom: 22px; }
  .support-card__action { --btn-h: 52px; }
  .support__note { padding: 24px 20px; }
}

/* ===== styles/sections/services.css ===== */
/* ===== Leistungen ======================================================= */
.services { padding-block: var(--sec-pt) var(--sec-pb); }

.services__title { margin-top: 14px; }

.services__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-cards);
  margin-top: 18px;
}

@media (max-width: 1023px) {
  .services__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 32px; }
}
@media (max-width: 719px) {
  .services__grid { grid-template-columns: 1fr; gap: 22px; }
}

/* ===== styles/sections/steps.css ===== */
/* ===== So einfach funktioniert es =======================================
   Kopf, Ablaufreihe, Handlungsaufruf. Die Reihe selbst ist dieselbe wie auf
   der Unterseite Leistungen ("So läuft es ab"); ihre Gestaltung steht in
   sections/flow.css. Hier steht nur, wie sie im Abschnitt sitzt.
   ======================================================================= */
.steps {
  padding-block: 74px 78px;
  background: var(--surface-soft);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.steps__head { max-width: 56ch; }
.steps__title { margin-top: 13px; }
.steps__lead  { margin-top: 16px; }

/* Mehr Luft als auf der Unterseite: dort steht nur eine Ueberschrift ueber
   der Reihe, hier Vorzeile, Ueberschrift und Fliesstext. */
.steps .flow__list { margin-top: 52px; }

.steps__cta { margin-top: 46px; }

@media (max-width: 1023px) {
  .steps { padding-block: 58px 60px; }
  .steps .flow__list { margin-top: 42px; }
}

@media (max-width: 599px) {
  .steps { padding-block: 46px 48px; }
  .steps .flow__list { margin-top: 34px; }
  .steps__cta { margin-top: 36px; }
}

/* ===== styles/sections/overview.css ===== */
/* ===== Leistungen auf einen Blick =======================================
   Eine Liste statt einer weiteren Kartenreihe: die drei Kernbereiche
   stehen schon oben als Karten, hier geht es um Vollstaendigkeit. Jede
   Zeile ist ein eigener Weg in die Anfrage.
   ======================================================================= */
.overview {
  padding-block: 74px 78px;
  background: var(--surface-soft);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* Der Abschnitt traegt bewusst nur eine kleine Vorzeile als Ueberschrift:
   die drei Kernleistungen stehen als grosse Karten direkt darueber, hier
   geht es nur noch um die Ergaenzungen. */
.overview__eyebrow { margin-bottom: 0; }

.overview__list {
  margin-top: 28px;
  border-top: 1px solid var(--line-strong);
}

.overview__row {
  position: relative;
  display: grid;
  grid-template-columns: 58px minmax(0, 300px) minmax(0, 1fr) auto;
  align-items: center;
  gap: 26px;
  padding: 24px 20px 24px 12px;
  border-bottom: 1px solid var(--line);
  background: transparent;
  transition: background-color var(--dur) var(--ease), padding-left var(--dur) var(--ease);
}
.overview__row:hover {
  background: var(--surface);
  padding-left: 20px;
}

/* Blaue Kante links, faehrt beim Hover ein. */
.overview__row::before {
  content: "";
  position: absolute;
  left: 0;
  top: -1px;
  bottom: -1px;
  width: 2px;
  background: var(--blue-600);
  transform: scaleY(0);
  transform-origin: 50% 50%;
  transition: transform var(--dur) var(--ease);
}
.overview__row:hover::before { transform: scaleY(1); }

.overview__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--r-full);
  background: var(--surface);
  border: 1px solid var(--line-card);
  color: var(--blue-700);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.overview__icon .icon { width: 23px; height: 23px; }
.overview__row:hover .overview__icon {
  background: var(--navy-800);
  border-color: var(--navy-800);
  color: #fff;
  transform: translateY(-2px);
}

.overview__title {
  font-size: calc(16px * var(--fs-scale));
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease);
}
.overview__row:hover .overview__title { color: var(--navy-800); }

.overview__text {
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--text);
}

.overview__link { white-space: nowrap; }
/* Die ganze Zeile ist klickbar, das Ziel bleibt der sichtbare Link. */
.overview__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.overview__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 32px;
  margin-top: 34px;
}
.overview__foot-text { max-width: 52ch; }
.overview__foot-title {
  font-size: calc(16px * var(--fs-scale));
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--ink);
}
.overview__foot p { margin-top: 8px; font-size: var(--fs-body-sm); color: var(--text-soft); }

@media (max-width: 1023px) {
  .overview { padding-block: 58px 60px; }
  .overview__row {
    grid-template-columns: 46px minmax(0, 1fr) auto;
    align-items: start;
    gap: 12px 20px;
    padding: 22px 14px 22px 12px;
  }
  .overview__icon { grid-row: span 2; }
  .overview__text { grid-column: 2; }
  .overview__link { grid-column: 2 / -1; margin-top: 4px; }
}
@media (max-width: 639px) {
  .overview { padding-block: 46px 48px; }
  .overview__list { margin-top: 30px; }
  .overview__row:hover { padding-left: 12px; }
}

/* ===== styles/sections/testimonials.css ===== */
/* ===== Bewertungs-Sektion ===============================================
   Rahmen um die Bewertungskarten (src/styles/components/testimonial.css):
   Sektionsabstand, Kopfzeile und Gesamtbewertung.
   ======================================================================= */
.testimonials { padding-block: 74px 78px; }

.testimonials__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 32px;
  align-items: end;
}
.testimonials__title { margin-top: 13px; }
.testimonials__lead  { margin-top: 16px; max-width: 52ch; }

/* Herkunftszeile unter dem Vorspann. Sie steht nur auf der englischen
   Fassung: Die Rezensionen sind auf Deutsch abgegeben und hier uebersetzt -
   das gehoert dazugesagt. Leiser gesetzt als der Vorspann, damit sie die
   Stimmen nicht ueberstrahlt. */
.testimonials__note {
  margin-top: 8px;
  max-width: 52ch;
  font-size: var(--fs-micro);
  line-height: 1.5;
  color: var(--text-soft);
}

/* Gesamtbewertung rechts neben der Ueberschrift */
.rating-sum {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 22px;
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
.rating-sum__stars { display: flex; gap: 3px; color: var(--blue-600); }
.rating-sum__stars .icon { width: 18px; height: 18px; }
.rating-sum__value {
  font-size: calc(26px * var(--fs-scale));
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.rating-sum__text {
  margin-top: 6px;
  font-size: var(--fs-micro);
  line-height: 1.4;
  color: var(--text-soft);
}

@media (max-width: 1023px) {
  .testimonials { padding-block: 58px 60px; }
  .testimonials__head { grid-template-columns: 1fr; align-items: start; gap: 24px; }
  .rating-sum { justify-self: start; }
}
@media (max-width: 639px) {
  .testimonials { padding-block: 46px 48px; }
}

/* ===== styles/sections/statement.css ===== */
/* ===== Vertrauens-Band ==================================================
   Das einzige dunkle Feld der Seite. Es setzt in der Mitte des Scrollwegs
   einen ruhigen Bruch und traegt die Kernaussage samt Handlungsaufruf.
   Farben kommen aus der Navy-Skala, kein zusaetzlicher Farbton.
   ======================================================================= */
.statement {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 78px 82px;
  background: linear-gradient(160deg, var(--navy-900) 0%, var(--navy-800) 52%, #16386f 100%);
  color: #fff;
}

/* Sehr weicher Lichtschein oben rechts - gibt der Flaeche Tiefe, ohne
   ein zweites Gestaltungsmittel einzufuehren. */
.statement::before {
  content: "";
  position: absolute;
  top: -34%;
  right: -12%;
  width: 60%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, 0) 66%);
  z-index: -1;
  pointer-events: none;
}

/* .statement__inner traegt nur .container: der Inhalt bleibt damit am
   Seitenraster. Begrenzt wird allein die Lauflaenge der Textzeilen. */
.statement .eyebrow { color: #9fbaf0; }

.statement__title {
  margin-top: 16px;
  font-size: calc(40px * var(--fs-scale));
  line-height: 1.14;
  letter-spacing: -.022em;
  text-transform: uppercase;
  color: #fff;
}
/* Zweite Zeile leicht zurueckgenommen: gibt der Aussage einen Rhythmus. */
.statement__title span { color: rgba(255, 255, 255, .58); }

.statement__lead {
  margin-top: 20px;
  max-width: 56ch;
  font-size: var(--fs-lead);
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
}

/* Fugen als Kanten an den Kacheln, nicht als eingefaerbte Flaeche dahinter
   - sonst leuchtet das Raster beim Einblenden kurz als helle Platte auf. */
.statement__points {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: 48px;
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: var(--r-md);
  overflow: hidden;
}
.statement__point {
  padding: 26px 24px 24px;
  background: rgba(255, 255, 255, .03);
  border-right: 1px solid rgba(255, 255, 255, .16);
  transition: background-color var(--dur) var(--ease);
}
.statement__point:last-child { border-right: 0; }
.statement__point:hover { background: rgba(255, 255, 255, .09); }

.statement__point .icon {
  width: 24px;
  height: 24px;
  color: #9fbaf0;
  transition: transform var(--dur) var(--ease), color var(--dur) var(--ease);
}
.statement__point:hover .icon { transform: translateY(-2px); color: #fff; }

.statement__point-title {
  margin-top: 16px;
  font-size: calc(14.5px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  line-height: 1.3;
  color: #fff;
}
.statement__point-text {
  margin-top: 9px;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: rgba(255, 255, 255, .72);
}

.statement__actions { margin-top: 44px; }

/* Buttons auf dunklem Grund: gefuellt weiss, sekundaer als Umriss. */
.btn--invert {
  background: #fff;
  color: var(--navy-900);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .22);
}
.btn--invert:hover {
  background: #f2f5fb;
  transform: translateY(-1px);
  box-shadow: 0 10px 22px -10px rgba(0, 0, 0, .55);
}
.btn--outline-invert {
  background: transparent;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .42);
}
.btn--outline-invert:hover {
  background: rgba(255, 255, 255, .10);
  border-color: rgba(255, 255, 255, .7);
  transform: translateY(-1px);
}
.statement :focus-visible { outline-color: #fff; }

@media (max-width: 1023px) {
  .statement { padding-block: 60px 64px; }
  .statement__title { font-size: calc(33px * var(--fs-scale)); }
  .statement__points { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 38px; }
  .statement__point { border-right: 1px solid rgba(255, 255, 255, .16); }
  .statement__point:nth-child(2n) { border-right: 0; }
  .statement__point:nth-child(-n + 2) { border-bottom: 1px solid rgba(255, 255, 255, .16); }
  .statement__actions { margin-top: 36px; }
}
@media (max-width: 599px) {
  .statement { padding-block: 48px 52px; }
  .statement__title { font-size: calc(27px * var(--fs-scale)); }
  .statement__points { grid-template-columns: 1fr; }
  .statement__point {
    padding: 22px 20px;
    border-right: 0;
    border-bottom: 1px solid rgba(255, 255, 255, .16);
  }
  .statement__point:last-child { border-bottom: 0; }
}

/* ===== styles/sections/individual.css ===== */
/* ===== Individuelle Transporte ==========================================
   Vorletzter Abschnitt der Startseite, direkt vor dem Abschluss
   (sections/closing.css): faengt alles auf, was nicht in die drei
   Kernbereiche passt, und fuehrt in die Anfrage.
   ======================================================================= */
.individual { padding-block: 74px 78px; border-top: 1px solid var(--line); }

.individual__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .92fr);
  gap: 60px;
  align-items: center;
}

.individual__title { margin-top: 13px; }
.individual__text  { margin-top: 16px; max-width: 48ch; }

/* Beispielhafte Anfragen als ruhige Pillen - zeigt Bandbreite, ohne eine
   weitere Liste aufzumachen. */
.individual__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 26px;
}
.individual__tag {
  padding: 8px 15px;
  border: 1px solid var(--line-card);
  border-radius: var(--r-full);
  background: var(--surface);
  font-size: calc(13.5px * var(--fs-scale));
  line-height: 1.35;
  color: var(--text);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.individual__tag:hover {
  border-color: var(--blue-600);
  background: var(--blue-050);
  color: var(--navy-800);
  transform: translateY(-2px);
}

.individual__actions { margin-top: 34px; }
.individual__note {
  margin-top: 16px;
  font-size: var(--fs-micro);
  line-height: 1.6;
  color: var(--text-soft);
}

/* Das Foto steht im selben Rahmen wie zuvor der Platzhalter: gleiches
   Seitenverhaeltnis, gleiche Eckenrundung. object-fit haelt den Ausschnitt
   stabil, wenn die Spalte schmaler wird. */
.individual__photo {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-md);
}

@media (max-width: 1023px) {
  .individual { padding-block: 58px 60px; }
  .individual__inner { grid-template-columns: 1fr; gap: 40px; }
  .individual__text { max-width: 60ch; }
  .individual__photo { aspect-ratio: 16 / 9; }
}
@media (max-width: 639px) {
  .individual { padding-block: 46px 48px; }
}

/* ===== styles/sections/flow.css ===== */
/* ===== Ablaufreihe („So läuft es ab") ===================================
   Umsetzung des Diagramms aus reference/So_laeuft_es_ab_Diagramm.html:
   vier Spalten,
   je eine Ziffernscheibe mit auslaufender Haarlinie, darunter Versaltitel
   und Fliesstext. Die Vorlage lag als eigenstaendige Zeichenflaeche mit
   Archivo/Source Sans 3 und leicht abweichenden Blautoenen vor; hier haengt
   alles an den Tokens aus 01-tokens.css, damit die Reihe im Auftritt der
   Seite steht und nicht daneben.

   Zuordnung Vorlage -> Token:
     #1B3B6F  Ziffernscheibe   -> var(--navy-800)
     #111827  Titel            -> var(--ink)
     #55607A  Fliesstext       -> var(--text)
     #D6DCE7  Haarlinie        -> var(--line-strong)
   ======================================================================= */
.flow__list {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 48px;
  margin-top: 34px;
}

.flow__step {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Kopfzeile des Schritts: Scheibe links, Linie laeuft nach rechts aus. */
.flow__marker {
  display: flex;
  align-items: center;
  gap: 12px;
}

.flow__num {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--navy-800);
  color: #fff;
  font-size: calc(15px * var(--fs-scale));
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.flow__rule {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--line-strong), var(--line-strong) 60%, transparent);
}
/* Der letzte Schritt fuehrt nirgends mehr hin. */
.flow__step:last-child .flow__rule { display: none; }

.flow__title {
  font-size: calc(16px * var(--fs-scale));
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink);
}

.flow__text {
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--text);
  text-wrap: pretty;
}

/* Dezente Rueckmeldung, wie bei den uebrigen Kacheln der Seite. */
.flow__step:hover .flow__num {
  transform: translateY(-2px);
  box-shadow: 0 8px 18px -10px rgba(15, 36, 82, .65);
}

@media (max-width: 1023px) {
  .flow__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px 36px; }
  /* Am Zeilenende laeuft die Linie ins Leere - dort entfaellt sie. */
  .flow__step:nth-child(2n) .flow__rule { display: none; }
}

@media (max-width: 559px) {
  .flow__list { grid-template-columns: 1fr; gap: 32px; margin-top: 28px; }
  .flow__step { gap: 16px; }
  .flow__step:nth-child(2n) .flow__rule { display: block; }
  .flow__step:last-child .flow__rule { display: none; }
}

/* ===== styles/sections/quote-band.css ===== */
/* ===== Angebots-Band ====================================================
   Referenz: 91 px hoch, hellgraues randloses Band, Icon + Text links,
   Button rechts.
   ======================================================================= */
.quote-band {
  background: linear-gradient(90deg, #fafbfc 0%, #f4f6f9 48%, #fafbfc 100%);
  border-bottom: 1px solid var(--line);
}

.quote-band__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  min-height: 93px;
  padding-block: 8px;
}

.quote-band__intro {
  display: flex;
  align-items: center;
  gap: 29px;
}
.quote-band__icon {
  width: 72px;
  height: 72px;
  flex: none;
  color: var(--blue-700);
}
.quote-band__title { margin-top: 6px; }

@media (max-width: 899px) {
  .quote-band__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 22px;
    padding-block: 30px;
  }
  .quote-band__intro { gap: 22px; }
}
@media (max-width: 639px) {
  .quote-band__icon { width: 40px; height: 40px; }
  .quote-band__intro { gap: 16px; }
  .quote-band .btn { width: 100%; }
}

/* ===== styles/sections/closing.css ===== */
/* ===== Abschluss der Startseite =========================================
   Ersetzt auf der Startseite das gemeinsame Angebots-Band. Ruhiges helles
   Band, mittig gesetzt, ein einziger Handlungsaufruf - der letzte Blick
   soll nicht wieder wie Werbung wirken, sondern wie eine Einladung.
   ======================================================================= */
.closing {
  padding-block: 68px 72px;
  background: linear-gradient(180deg, var(--surface-soft) 0%, var(--surface-band) 100%);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.closing__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.closing__title { margin-top: 13px; max-width: 20ch; }
.closing__text  { margin-top: 16px; max-width: 58ch; }

.closing__actions { margin-top: 32px; justify-content: center; }

/* Das Haekchen laeuft im Textfluss mit, damit die Zeile auch dann sauber
   zentriert bleibt, wenn sie auf zwei Zeilen umbricht. */
.closing__note {
  margin-top: 24px;
  max-width: 60ch;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--text-soft);
}

@media (max-width: 1023px) {
  .closing { padding-block: 56px 58px; }
}
@media (max-width: 639px) {
  .closing { padding-block: 44px 46px; }
  .closing__inner { align-items: stretch; text-align: left; }
  .closing__title { max-width: none; }
}

/* ===== styles/sections/page-head.css ===== */
/* ===== Seitenkopf der Unterseiten ======================================= */
.page-head {
  padding-block: 54px 46px;
  background: linear-gradient(180deg, #fafbfc 0%, #ffffff 100%);
  border-bottom: 1px solid var(--line);
}
.page-head__title { margin-top: 12px; }
.page-head__text { margin-top: 16px; max-width: 58ch; }

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 18px;
  font-size: var(--fs-micro);
  color: var(--text-soft);
}
.breadcrumb a {
  display: inline-block;
  padding-block: 3px;
  transition: color var(--dur-fast) var(--ease);
}
.breadcrumb a:hover { color: var(--navy-800); }

/* Wie ueberall auf der Seite: mit dem Finger 44px, mit der Maus kompakt. */
@media (max-width: 639px), (pointer: coarse) {
  .breadcrumb a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-block: 0;
  }
  .breadcrumb { margin-bottom: 10px; }
}
.breadcrumb [aria-current] { color: var(--ink); font-weight: 500; }

@media (max-width: 639px) {
  .page-head { padding-block: 32px 30px; }
}

/* ===== styles/sections/prose.css ===== */
/* ===== Fliesstext-Seiten (Impressum, Datenschutz) ======================= */
.prose { max-width: 74ch; }
.prose > * + * { margin-top: 18px; }
.prose h2 {
  margin-top: 40px;
  font-size: calc(20px * var(--fs-scale));
  text-transform: uppercase;
  letter-spacing: -.002em;
}
.prose h3 { margin-top: 28px; font-size: calc(16px * var(--fs-scale)); font-weight: 700; }
.prose p, .prose li { font-size: var(--fs-body-sm); line-height: 1.8; color: var(--text); }
.prose ul { padding-left: 20px; list-style: disc; display: grid; gap: 8px; }
.prose a { color: var(--blue-600); text-decoration: underline; text-underline-offset: 2px; }
.prose a:hover { color: var(--blue-500); }
.prose dl { display: grid; grid-template-columns: max-content 1fr; gap: 8px 24px; font-size: var(--fs-body-sm); }
.prose dt { font-weight: 600; color: var(--ink); }

@media (max-width: 559px) {
  .prose dl { grid-template-columns: 1fr; gap: 2px 0; }
  .prose dd + dt { margin-top: 12px; }
}

/* Redaktioneller Hinweis (Platzhaltertexte auf den Rechtsseiten) */
.notice {
  padding: 16px 18px;
  background: var(--blue-050);
  border-left: 3px solid var(--blue-600);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--navy-900);
}
.notice strong { color: inherit; }

/* ===== styles/sections/subpages.css ===== */
/* ===== Layouts der Unterseiten ========================================== */

/* FAQ: Akkordeon links, Hilfekarte rechts */
.faq-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 56px;
  align-items: start;
}
.faq-aside,
.contact-aside {
  padding: 28px 26px;
  background: var(--surface-soft);
  border: 1px solid var(--line-card);
  border-radius: var(--r-md);
}
.faq-aside .site-footer__contact { margin-top: 18px; }

/* Kontakt: Formular links, Infokarte rechts */
.contact-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 56px;
  align-items: start;
}
.contact-aside { position: sticky; top: calc(var(--header-total) + 24px); }

.hours {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 8px 20px;
  font-size: var(--fs-body-sm);
}
.hours dt { color: var(--ink); font-weight: 600; }
.hours dd { color: var(--text); }

@media (max-width: 1023px) {
  .faq-layout,
  .contact-layout { grid-template-columns: 1fr; gap: 36px; }
  .contact-aside { position: static; }
}
@media (max-width: 559px) {
  .hours { grid-template-columns: 1fr; gap: 2px 0; }
  .hours dd + dt { margin-top: 12px; }
}

/* ===== styles/sections/kontakt.css ===== */
/* ===== Anfrageformular in der Kantensprache =============================
   Gilt ausschliesslich fuer src/pages/kontakt.html: jede Regel haengt an
   .page-kontakt (Front-Matter "bodyClass"). Das ist hier kein Schmuck,
   sondern noetig - die Bausteine .form, .field und .form__status stehen in
   components/form.css, und die Infokarte teilt sich ihre Regel mit der
   FAQ-Seite (.faq-aside/.contact-aside in sections/subpages.css). Ohne die
   Klasse faerbte jede Zeile hier auf andere Seiten ab.

   Uebernommen ist die Kantensprache der zweiten Startseite
   (sections/startseite-2.css, Gedanke 1): rechte Winkel statt gerundeter
   Ecken, Haarlinien als Gliederung, Eckwinkel im Markenblau als
   Auszeichnung und die Ziffernkaestchen von deren Varianten-Karten. Sie
   zeigen, wo etwas anfaengt und aufhoert - beim Formular also, aus wie
   wenigen Schritten es besteht.

   Was bewusst NICHT mitkommt: die scrollgebundene Bewegung. Die haengt an
   scroll-fx.js und ausschliesslich an .page-start-2. Hier steht alles
   still, bis jemand ein Feld anfasst.
   ======================================================================= */

.page-kontakt {
  /* Dieselben zwei Kantenwerte wie auf der zweiten Startseite: --edge ist
     die Haarlinie, --edge-ink die betonte Kante im Markenblau. */
  --edge: var(--line-strong);
  --edge-ink: var(--blue-600);
}

/* --- Der Block ----------------------------------------------------------
   Das Formular stand bisher frei auf der weissen Flaeche. Jetzt ist es
   gefasst: eigene Flaeche, Haarlinie ringsum, rechte Winkel. */
.page-kontakt .form {
  position: relative;
  gap: 26px;
  padding: 34px 32px;
  background: var(--surface);
  border: 1px solid var(--line-card);
  border-radius: 0;
}

/* Eckwinkel oben links und unten rechts - dieselbe Auszeichnung wie an den
   Varianten-Karten der zweiten Startseite, nur eine Nummer groesser, weil
   die Flaeche groesser ist.

   Sie fahren beim Einblenden aus. Gebunden sind sie an die Klasse, die
   reveal.js am umgebenden Block setzt (das <div data-reveal>, in dem
   Ueberschrift und Formular stehen) - ein eigenes Skript braucht es dafuer
   nicht. Ohne JavaScript stehen sie von Anfang an. */
.page-kontakt .form::before,
.page-kontakt .form::after {
  content: "";
  position: absolute;
  width: 26px;
  height: 26px;
  border: 0 solid var(--edge-ink);
  pointer-events: none;
  opacity: 0;
  transform: scale(.4);
  transition: opacity 620ms var(--ease), transform 620ms var(--ease);
}
.page-kontakt .form::before {
  top: 14px;
  left: 14px;
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-kontakt .form::after {
  right: 14px;
  bottom: 14px;
  border-right-width: 1px;
  border-bottom-width: 1px;
}
.page-kontakt .is-revealed .form::before,
.page-kontakt .is-revealed .form::after,
html:not(.js) .page-kontakt .form::before,
html:not(.js) .page-kontakt .form::after {
  opacity: .55;
  transform: none;
  transition-delay: 380ms;
}
/* Waehrend ausgefuellt wird, treten sie deutlicher hervor - die Fassung
   reagiert auf Benutzung, so wie die Kanten der zweiten Startseite auf das
   Ueberfahren reagieren. */
.page-kontakt .form:focus-within::before,
.page-kontakt .form:focus-within::after { opacity: 1; }

/* --- Drei Schritte statt einer langen Liste -----------------------------
   Die Felder liegen jetzt in drei <fieldset>-Gruppen. Getrennt werden sie
   von Haarlinien, angeschrieben mit den Ziffernkaestchen der zweiten
   Startseite. Das ist zugleich die richtige Auszeichnung: zusammen-
   gehoerende Felder in einer Gruppe mit gemeinsamer Beschriftung. */
.page-kontakt .form-group {
  /* min-width: 0 - sonst zieht die Vorgabebreite eines <fieldset> das
     Raster darin auf. */
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.page-kontakt .form-group + .form-group {
  padding-top: 26px;
  border-top: 1px solid var(--edge);
}

.page-kontakt .form-group__title {
  display: flex;
  align-items: center;
  gap: 10px;
  /* float: none haelt die Legende in modernen Browsern in der Zeile; das
     padding der Vorgabefassung wuerde sie sonst einruecken. */
  float: none;
  width: 100%;
  padding: 0;
  margin-bottom: 18px;
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink);
}

/* Das Ziffernkaestchen, Bauart wie .support-card__num. */
.page-kontakt .form-group__num {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  padding: 2px 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  color: var(--edge-ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: .06em;
  opacity: .85;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
/* Die Gruppe, in der gerade geschrieben wird, faerbt ihr Kaestchen aus -
   dasselbe Bild wie eine ueberfahrene Varianten-Karte, hier aber an den
   Fokus gebunden: es zeigt, an welchem Schritt man steht. */
.page-kontakt .form-group:focus-within .form-group__num {
  background: var(--edge-ink);
  border-color: var(--edge-ink);
  color: #fff;
  opacity: 1;
}

.page-kontakt .form-group__fields {
  display: grid;
  gap: 20px;
}

/* --- Die Felder ---------------------------------------------------------
   Rechte Winkel, eine Spur zurueckgenommene Flaeche, und im Fokus eine
   betonte Kante an der linken Seite: die schmale blaue Marke, die auf der
   zweiten Startseite an Karten und Bewertungen sitzt. Sie liegt innen
   (inset) und braucht deshalb kein eigenes Pseudoelement.

   Der Fokusschein bleibt in derselben Regel stehen - er kommt aus
   --focus-halo und traegt damit weiterhin die Einstellung "Erhoehter
   Kontrast" aus dem Bedienhilfen-Fenster. */
/* background-COLOR, nicht background: die Kurzform wuerde auch
   background-image, -repeat, -position und -size zuruecksetzen. Genau daran
   haengt aber der Pfeil im Auswahlfeld (components/form.css). Mit der
   Kurzform verschwand er hier ganz - und sobald "Erhoehter Kontrast" ihn
   ueber eine staerkere Regel zurueckholte, kam er ohne no-repeat wieder und
   kachelte quer durch das Feld. */
.page-kontakt .field__control {
  border-radius: 0;
  border-color: var(--edge);
  background-color: var(--surface-soft);
}
.page-kontakt .field__control:hover { border-color: #c8ccd4; }
.page-kontakt .field__control:focus {
  background-color: var(--surface);
  border-color: var(--edge-ink);
  box-shadow:
    inset 2px 0 0 var(--edge-ink),
    0 0 0 3px var(--focus-halo);
}

/* Der Fehlerfall traegt dieselbe Marke in Rot - gleiche Bauart, andere
   Farbe, damit die Aussage nicht allein an der Farbe haengt.

   Die Rahmenfarbe steht hier noch einmal ausdruecklich, obwohl
   components/form.css sie schon setzt: die Fokusregel darueber ist gleich
   stark und steht spaeter im Buendel. Ohne diese Zeile schlueg sie im
   fokussierten Fehlerfeld durch - der Rahmen waere blau, waehrend die
   Meldung darunter einen Fehler nennt. */
.page-kontakt .field[data-invalid] .field__control {
  border-color: #b3261e;
  box-shadow: inset 2px 0 0 #b3261e;
}
.page-kontakt .field[data-invalid] .field__control:focus {
  border-color: #b3261e;
  box-shadow:
    inset 2px 0 0 #b3261e,
    0 0 0 3px rgba(179, 38, 30, .15);
}

/* --- Statusmeldung und Abschluss ---------------------------------------- */
.page-kontakt .form__status {
  border-radius: 0;
  border-left-width: 2px;
}
.page-kontakt .form__status[data-state="success"] { border-left-color: var(--edge-ink); }
.page-kontakt .form__status[data-state="error"] { border-left-color: #b3261e; }

/* Absenden und Pflichtfeld-Hinweis stehen in einer Zeile ueber einer
   Haarlinie - der Fuss des Formulars, sichtbar abgesetzt. */
.page-kontakt .form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px 24px;
  padding-top: 24px;
  border-top: 1px solid var(--edge);
}
.page-kontakt .form__actions .field__hint { margin: 0; }

/* Auf schmalen Fenstern nimmt die Fassung sich zurueck: weniger Polster,
   und die Eckwinkel ruecken mit. Der Knopf steht dort ueber die volle
   Breite, der Hinweis darunter. */
@media (max-width: 559px) {
  .page-kontakt .form { padding: 26px 20px; }
  .page-kontakt .form::before { top: 10px; left: 10px; }
  .page-kontakt .form::after { right: 10px; bottom: 10px; }
  .page-kontakt .form__actions { justify-content: stretch; }
  .page-kontakt .form__actions .btn { width: 100%; justify-content: center; }
}

/* ===== Seitenkopf =======================================================
   Der Kopf stand bisher in der Grundfassung aller Unterseiten: linksbuendig
   auf fast weisser Flaeche. Auf der Kontaktseite ist er aber das Erste, was
   man sieht, und das Einzige vor dem Formular. Er bekommt deshalb eine
   eigene Fassung - gebaut aus Bausteinen, die es auf der Seite schon gibt,
   nicht aus neuen:

     * die mittige Anlage des Abschlussbandes der Startseite (.closing)
     * das Signet des Angebots-Bandes (#i-clipboard-check) in der Fassung
       der Leistungskarten (.icon-badge)
     * ein weiches Licht im Markenblau, wie es der Auftakt der Startseite
       ueber dem Foto liegen hat

   Zwei Dinge sind bewusst so gebaut:

   1. KEINE Trennlinie nach unten. Der Verlauf endet auf reinem Weiss -
      genau der Farbe des Abschnitts darunter. Der Uebergang ist damit eine
      Verlaufskante und keine Naht; Kopf und Formular lesen sich als ein
      Stueck.
   2. NUR DURCHGEHENDE BEWEGUNG. Statt mehrerer kurzer Auftritte, die
      nacheinander einsetzen, gibt es einen einzigen Auftritt fuer den
      ganzen Kopf und zwei sehr langsame Atembewegungen mit "alternate" -
      die laufen hin und zurueck, haben also keinen sichtbaren Anfang und
      kein Zurueckspringen.
   ======================================================================= */
.page-kontakt .page-head {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Oben knapp, unten grosszuegig: der Kopf soll nicht als eigener Block
     vor dem Formular stehen, sondern in es hineinlaufen. */
  /* Unten knapp gehalten: .section--page bringt darunter schon 56px mit,
     zusammen waere das sonst ein Loch zwischen Kopf und Formular. */
  padding-block: 38px 30px;
  /* Die Periode des Lichtbandes: Kachelbreite, Vorlauf links, Ueberbreite
     und Wanderweg haengen alle an diesem einen Wert. Wer das Band enger
     oder weiter haben will, aendert nur ihn (und die Dauer, damit die
     Geschwindigkeit bleibt). */
  --band-periode: 760px;
  background: linear-gradient(180deg,
    var(--surface-soft) 0%,
    var(--surface-band) 32%,
    #fbfcfd 68%,
    var(--surface) 100%);
  border-bottom: 0;
  text-align: center;
}

/* Das Licht ist kein Fleck mehr, sondern ein Band: eine Reihe weicher
   Kuppen, die sich alle 760px wiederholt und langsam nach links wandert.

   Der Trick fuer den nahtlosen Rundlauf steckt in den Massen. Die Flaeche
   ist links und rechts je eine volle Periode breiter als der Abschnitt, und
   die Bewegung verschiebt sie um genau eine Periode. Danach sieht das Bild
   exakt aus wie am Anfang - der Sprung zurueck ist unsichtbar, und weil die
   Bewegung "linear" laeuft, gibt es auch kein Abbremsen vor dem Rundlauf.

   Jede Kuppe faellt zu allen Seiten auf durchsichtig ab. Deshalb stossen die
   Kacheln ohne Kante aneinander, und das Band braucht keine Maske, die beim
   Wandern mitlaufen wuerde. */
.page-kontakt .page-head::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--band-periode) * -1);
  width: calc(100% + var(--band-periode) * 2);
  z-index: -1;
  background-image: radial-gradient(70% 60% at 50% 44%, rgba(30, 66, 144, .17), transparent 74%);
  background-size: var(--band-periode) 100%;
  background-repeat: repeat-x;
}

/* --- Der Inhalt, mittig ------------------------------------------------- */
.page-kontakt .page-head .breadcrumb {
  justify-content: center;
  margin-bottom: 22px;
}

.page-kontakt .page-head__badge { position: relative; margin-inline: auto; }
/* Ein einzelner Ring um das Signet, der langsam auf- und wieder zugeht.
   Dieselbe Geste wie beim Telefonknopf in der Kopfleiste, nur ohne Anlass. */
.page-kontakt .page-head__badge::after {
  content: "";
  position: absolute;
  inset: -11px;
  border: 1px solid rgba(42, 85, 168, .32);
  border-radius: var(--r-full);
  opacity: .45;
  pointer-events: none;
}

.page-kontakt .page-head .eyebrow { margin-top: 20px; }
.page-kontakt .page-head__title {
  margin-top: 10px;
  /* Keine Breitengrenze: die Zeile darf den ganzen Inhaltsrahmen nutzen und
     steht auf dem Desktop dadurch in einer Zeile. Erst wenn der Rahmen zu
     schmal wird, bricht sie von selbst - dann sorgt balance fuer eine
     gleichmaessige Teilung. */
  max-width: none;
  text-wrap: balance;
  /* Eine Spur groesser als die uebrigen Abschnittsueberschriften: sie ist
     hier die Ueberschrift der Seite, nicht die eines Abschnitts. */
  font-size: calc(var(--fs-h2) * 1.14);
}
.page-kontakt .page-head__text {
  margin-top: 16px;
  margin-inline: auto;
  /* Weiter als die ueblichen 58ch: der Vorspann soll unter der langen
     Ueberschrift in zwei Zeilen stehen, nicht in drei. balance teilt sie
     gleichmaessig, statt eine kurze Restzeile zu hinterlassen. */
  max-width: 88ch;
  text-wrap: balance;
}

/* --- Bewegung ------------------------------------------------------------
   Alles hier ist durchgehend. Ohne diese Abfrage steht der Kopf sofort
   fertig da - nichts ist unsichtbar, nichts wartet auf eine Animation.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  /* Ein Auftritt fuer den ganzen Kopf, nicht vier nacheinander. */
  .page-kontakt .page-head > .container {
    animation: kontakt-kopf-auftritt 760ms var(--ease) backwards;
  }
  @keyframes kontakt-kopf-auftritt {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }

  /* 34 Sekunden fuer eine Periode - rund 22 Pixel in der Sekunde. Langsam
     genug, dass man der Bewegung nicht folgt, schnell genug, dass die
     Flaeche nicht steht. "linear" ist hier Pflicht: jede Beschleunigung
     wuerde den Rundlauf sichtbar machen. */
  .page-kontakt .page-head::before {
    animation: kontakt-band 34s linear infinite;
    will-change: transform;
  }
  @keyframes kontakt-band {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(calc(var(--band-periode) * -1), 0, 0); }
  }

  .page-kontakt .page-head__badge::after {
    animation: kontakt-ring 5.6s ease-in-out infinite alternate;
  }
  @keyframes kontakt-ring {
    from { transform: scale(.93); opacity: .26; }
    to   { transform: scale(1.07); opacity: .6; }
  }
}

/* --- Schmale Fenster ----------------------------------------------------- */
@media (max-width: 639px) {
  .page-kontakt .page-head {
    padding-block: 24px 22px;
    /* Bei 760px waere auf dem Handy immer nur eine halbe Kuppe im Bild.
       Engere Kacheln geben dem Band auch dort einen Rhythmus; die Dauer
       sinkt im selben Verhaeltnis, damit das Tempo gleich bleibt. */
    --band-periode: 440px;
  }
  .page-kontakt .page-head::before { animation-duration: 20s; }
  .page-kontakt .page-head .breadcrumb { margin-bottom: 12px; }
  .page-kontakt .page-head__badge::after { inset: -9px; }
  .page-kontakt .page-head .eyebrow { margin-top: 16px; }
  .page-kontakt .page-head__title { max-width: none; }
  .page-kontakt .page-head__text { margin-top: 14px; }
}

/* ===== styles/sections/leistungen.css ===== */
/* ===== Leistungen - eigene Gestaltungsebene =============================
   Gilt ausschliesslich fuer src/pages/leistungen.html: jede Regel haengt an
   .page-leistungen (Front-Matter "bodyClass"). Das ist hier keine Ordnungs-
   frage, sondern Bedingung: das Angebots-Band ist ein gemeinsamer Baustein
   (components/quote-band.html) und steht genauso auf faq.html. Ohne die
   Seitenklasse faerbte jede Zeile dieser Datei auch dort ab - freigegeben
   ist aber nur die Leistungen-Seite.

   Die Datei laedt nach sections/quote-band.css und ueberschreibt sie
   deshalb ohne !important. Das Markup bleibt unberuehrt: alles, was
   zusaetzlich erscheint, ist Hintergrundebene oder Pseudoelement auf einer
   bereits vorhandenen Klasse.

   WAS SICH AENDERT UND WARUM
   Das Band war eine hellgraue Leiste von 93 px Hoehe - auf der Startseite
   ein Zwischenruf, am Fuss einer Unterseite aber der letzte Abschnitt vor
   der Fusszeile und damit der Ort, an dem die Seite ihre Frage stellt. Es
   bekommt darum die Fassung, die sections/startseite-2.css (Block 13) fuer
   genau diese Rolle gefunden hat: eine fast schwarze Navy-Platte mit sehr
   flachem Haarlinienraster. Gleiche Aufgabe, gleiche Sprache - und weil die
   Fusszeile darunter weiss ist, steht der Abschluss fuer sich.

   Dazu die Kantensprache derselben Seite (Gedanke 1 "KANTEN"): rechte
   Winkel statt Rundungen, eine betonte Oberkante mit den Teilstrichen der
   gezahnten Kante (Block 6), Eckwinkel aus zwei Borderkanten um den ganzen
   Inhalt (Block 4), der ziehende Strich unter der Vorzeile - und ein Knopf,
   der auf dunklem Grund nicht mitgedunkelt, sondern umgedreht wird: weisse
   Platte, rechte Winkel, blaue Standkante.

   Was bewusst NICHT mitkommt: jede scrollgebundene Bewegung. Die haengt an
   scripts/scroll-fx.js und an .page-start-2. Das Band traegt auch kein
   data-reveal, also darf nichts an "is-revealed" haengen - es steht
   vollstaendig da, sobald es im Bild ist. Bewegung gibt es nur als
   Uebergang beim Ueberfahren; prefers-reduced-motion nimmt sie global
   ueber styles/05-motion.css zurueck.
   ======================================================================= */

/* --- Farb- und Kantenwerte an einer Stelle -------------------------------
   Bewusst am Band und nicht am body: es sind Werte einer dunklen Flaeche,
   und dunkel wird auf dieser Seite genau ein Abschnitt.

   Die drei Navy-Werte stammen unveraendert vom Abschluss der zweiten
   Startseite. Als Token gibt es sie nicht - 01-tokens.css fuehrt nur die
   helle Skala, und --navy-900 (#0f2452) waere als ganze Flaeche zu blass.
   Sie hier neu zu erfinden hiesse, zwei dunkle Flaechen im Auftritt zu
   haben, die sich um wenige Prozent unterscheiden.

   --qb-ink ist das helle Markenblau derselben Fassung. Es traegt alles,
   was auf dem Band Blau sein soll: --blue-600 kaeme auf dieser Flaeche auf
   2.3:1 und waere weder als Text noch als Kante zu erkennen. */
.page-leistungen .quote-band {
  --qb-plate: #0d1f47;      /* Grundton der Platte                          */
  --qb-plate-deep: #0a1836; /* Fuss der Platte, zur Fusszeile hin           */
  --qb-glow: #16386f;       /* Aufhellung oben links, wo der Blick eintritt */
  --qb-ink: #9fbaf0;        /* Vorzeile und betonte Kanten - 5.9:1          */
  --qb-icon: #cfe0ff;       /* Klemmbrett                                   */
  --qb-hair: rgba(255, 255, 255, .16); /* Teilstriche der Oberkante         */
  --qb-bracket: 22px;       /* wie weit die Eckwinkel ausserhalb liegen     */
  --qb-bracket-arm: 26px;   /* Schenkellaenge, wie in sections/kontakt.css  */

  position: relative;
  /* isolation, damit das Raster mit z-index -1 ueber der Flaeche, aber
     unter dem Inhalt liegt, ohne aus dem Band auszubrechen. */
  isolation: isolate;
  /* Nichts in diesem Band ragt hinaus; die Zeile ist die Zusicherung, dass
     auch bei 320 px keine Zierkante waagrecht schiebt. */
  overflow: hidden;
  /* Aus der Leiste wird ein Abschnitt. Unten etwas knapper als oben: die
     Fusszeile bringt eigenes Polster mit. */
  padding-block: 64px 58px;
  /* Die Haarlinie der hellen Fassung entfaellt - die Fusszeile setzt ihre
     eigene Oberkante, zwei Linien uebereinander waeren eine zu viel. */
  border-bottom: 0;
  color: #fff;
  /* Drei Ebenen, von oben nach unten gelesen:
     1. die betonte Oberkante im hellen Markenblau (8.3:1 gegen die Platte).
        Sie steht als Hintergrundebene und nicht als Pseudoelement, damit
        ::before fuer die Teilstriche frei bleibt, die an ihr haengen;
     2. eine Aufhellung oben links, wo das Klemmbrett steht und das Lesen
        anfaengt - der einzige weiche Uebergang im Band, alles andere sind
        Kanten;
     3. die Platte selbst, zur Fusszeile hin eine Spur tiefer. */
  background:
    linear-gradient(var(--qb-ink), var(--qb-ink)) 0 0 / 100% 2px no-repeat,
    radial-gradient(120% 150% at 16% 0%, var(--qb-glow) 0%, rgba(22, 56, 111, 0) 62%),
    linear-gradient(180deg, var(--qb-plate) 0%, var(--qb-plate-deep) 100%);
}

/* --- Oberkante: Teilstriche wie an einem Massstab ------------------------
   Dieselbe Auszeichnung wie der Uebergang zum Ueberblick auf der zweiten
   Startseite (Block 6), hier unter die blaue Kante gehaengt. Sie macht den
   Wechsel von der weissen Flaeche auf die Platte zu einem eigenen
   Ereignis, statt ihn nur geschehen zu lassen.

   Sie sitzen im Polster oberhalb des Inhalts, koennen also nichts
   verdecken; pointer-events ab, weil sie ueber dem Fluss liegen. */
.page-leistungen .quote-band::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 0;
  right: 0;
  height: 10px;
  pointer-events: none;
  background: repeating-linear-gradient(90deg, var(--qb-hair) 0 1px, transparent 1px 36px);
}

/* --- Haarlinienraster ----------------------------------------------------
   Liegt sehr flach unter allem und gibt der Flaeche Massstab, ohne als
   Muster aufzufallen (1.1:1 gegen die Platte - man sieht es, man liest es
   nicht). Nach unten blendet es aus, damit die weisse Fusszeile nicht an
   einer angeschnittenen Rasterzeile anstoesst.

   64 px statt der 88 px des Vorbilds: das Band ist deutlich flacher als
   ein ganzer Abschnitt, bei 88 px laege im sichtbaren Bereich kaum eine
   waagrechte Linie. */
.page-leistungen .quote-band::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .05) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(0deg,  rgba(255, 255, 255, .05) 0 1px, transparent 1px 64px);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .3) 74%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .3) 74%, transparent 100%);
}

/* --- Der Inhalt und seine Fassung ---------------------------------------
   Das Polster liegt jetzt am Abschnitt, nicht mehr am Inhaltsrahmen; die
   Mindesthoehe der Leiste faellt weg, die Hoehe ergibt sich aus Inhalt und
   Polster. Zeilenfall und Umbruch bleiben unveraendert - Ausrichtung und
   Umbruchpunkte kommen weiter aus sections/quote-band.css. */
.page-leistungen .quote-band__inner {
  position: relative;
  min-height: 0;
  padding-block: 0;
  gap: 40px;
}

/* Eckwinkel oben links und unten rechts. Zwei Borderkanten je Pseudo-
   element ergeben ein diagonales Paar - das genuegt, damit die Flaeche als
   gefasst gelesen wird, und kostet die Haelfte eines vollen Rahmens. Sie
   liegen ausserhalb des Inhalts, im Polster des Bandes, und fassen damit
   die ganze Gruppe aus Klemmbrett, Text und Knopf.

   Kein Ausfahren beim Einblenden wie in sections/kontakt.css: das Band
   traegt kein data-reveal, es gibt also keine Klasse, an der ein Endwert
   haengen koennte. Sie stehen von Anfang an. */
.page-leistungen .quote-band__inner::before,
.page-leistungen .quote-band__inner::after {
  content: "";
  position: absolute;
  width: var(--qb-bracket-arm);
  height: var(--qb-bracket-arm);
  border: 0 solid var(--qb-ink);
  pointer-events: none;
  opacity: .55;
  transition: opacity var(--dur) var(--ease);
}
.page-leistungen .quote-band__inner::before {
  top: calc(var(--qb-bracket) * -1);
  left: calc(var(--qb-bracket) * -1);
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-leistungen .quote-band__inner::after {
  right: calc(var(--qb-bracket) * -1);
  bottom: calc(var(--qb-bracket) * -1);
  border-right-width: 1px;
  border-bottom-width: 1px;
}
/* Die Fassung reagiert, sobald jemand das Band anfasst - dasselbe Bild wie
   das Formular auf kontakt.html, das im Fokus deutlicher gefasst wird.
   :focus-within deckt die Tastatur mit ab. */
.page-leistungen .quote-band:hover .quote-band__inner::before,
.page-leistungen .quote-band:hover .quote-band__inner::after,
.page-leistungen .quote-band:focus-within .quote-band__inner::before,
.page-leistungen .quote-band:focus-within .quote-band__inner::after { opacity: 1; }

/* --- Klemmbrett: gefasst statt frei stehend ------------------------------
   Das Symbol bekommt einen eigenen Kasten mit rechten Winkeln. Bewusst
   Rahmen und Polster direkt am <svg> und kein Pseudoelement: ein inline-SVG
   ist ein ersetztes Element, ::before/::after werden darauf nicht
   zuverlaessig dargestellt, Rahmen, Flaeche und Polster dagegen schon.

   Die Zeichenflaeche wird durch das Polster kleiner (box-sizing: border-box
   aus dem Reset), der Kasten aussen bleibt in der Groessenordnung der
   bisherigen 72 px. Gefasst wirkt das Symbol dadurch groesser, nicht
   kleiner. */
.page-leistungen .quote-band__icon {
  width: 76px;
  height: 76px;
  padding: 15px;
  border: 1px solid rgba(159, 186, 240, .34);
  background: rgba(159, 186, 240, .07);
  color: var(--qb-icon);
}

/* --- Vorzeile: hell, mit dem ziehenden Strich ----------------------------
   Ohne diese Regel behielte die Vorzeile ihr --blue-600 vom hellen Grund
   und stuende mit 2.3:1 auf der Platte. Der kurze Strich darunter ist das
   wiederkehrende Zeichen der zweiten Startseite; dort waechst er beim
   Einblenden, hier steht er - es gibt keine Einblendung, an die er sich
   haengen koennte. */
.page-leistungen .quote-band .eyebrow {
  position: relative;
  padding-bottom: 14px;
  color: var(--qb-ink);
}
.page-leistungen .quote-band .eyebrow::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 5px;
  width: 48px;
  height: 1px;
  background: currentColor;
  opacity: .5;
  pointer-events: none;
}

.page-leistungen .quote-band__title { color: #fff; }

/* --- Der Knopf: umgedreht statt mitgedunkelt ----------------------------
   Der Primaerknopf ist Navy auf Weiss. Auf der Platte kaeme er auf 1.3:1
   und verschwaende. Er wird darum umgedreht: weisse Flaeche, Beschriftung
   im dunkelsten Markenton, rechte Winkel statt der 4 px Rundung. Damit ist
   er der hellste Punkt des ganzen Abschnitts - genau das soll er sein.

   Groesser als die gemeinsame Fassung (--btn-h 48 -> 56, mehr Polster,
   normale statt kleiner Schriftgroesse): am Fuss einer Unterseite ist er
   das Ziel der Seite und kein Beiwerk.

   Der Schatten faellt weg - auf dunklem Grund ist ein dunkler Schatten
   nicht zu sehen. Seine Aufgabe uebernimmt beim Ueberfahren ein weicher
   Schein im hellen Markenblau, dasselbe Mittel wie die beleuchtete Strecke
   auf der zweiten Startseite. */
.page-leistungen .quote-band .btn--primary {
  --btn-h: 56px;
  --btn-px: 34px;
  --btn-gap: 16px;
  position: relative;
  flex: none;
  font-size: var(--fs-btn);
  border-radius: 0;
  background: #fff;
  color: var(--navy-900);
  box-shadow: none;
}
.page-leistungen .quote-band .btn--primary:hover {
  background: var(--blue-050);
  box-shadow: 0 0 30px -6px rgba(159, 186, 240, .45);
}

/* Standkante im Markenblau: die einzige Stelle, an der --blue-600 auf
   dieser Seite noch als Kante taugt, weil sie auf Weiss sitzt (7.1:1).
   Sie steht dauerhaft. Beim Ueberfahren faehrt die Gegenkante oben ein und
   die Klammer schliesst sich - dieselbe Bewegung wie an den Zeilen des
   Ueberblicks auf der zweiten Startseite (Block 6). */
.page-leistungen .quote-band .btn--primary::before,
.page-leistungen .quote-band .btn--primary::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--blue-600);
  pointer-events: none;
}
.page-leistungen .quote-band .btn--primary::after { bottom: 0; }
.page-leistungen .quote-band .btn--primary::before {
  top: 0;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 420ms var(--ease);
}
.page-leistungen .quote-band .btn--primary:hover::before,
.page-leistungen .quote-band .btn--primary:focus-visible::before { transform: none; }

/* Der Fokusring bleibt, wechselt aber die Farbe: --blue-600 kaeme auf der
   Platte auf 2.3:1, Weiss auf 16.1:1. Der Ring liegt mit outline-offset
   3 px vom Knopf ab, zwischen weissem Knopf und weissem Ring steht also
   immer ein dunkler Streifen - er ist auch dort eindeutig zu sehen. */
.page-leistungen .quote-band :focus-visible { outline-color: #fff; }

/* --- Erhoehter Kontrast --------------------------------------------------
   Die Schalter des Bedienhilfen-Fensters arbeiten ueber Token; die
   Flaechenwerte des Bandes sind fest und wuerden nicht mitgehen. Die
   Vorzeile geht darum auf Weiss (11.5:1 statt 5.9:1), und alles Zierliche
   wird kraeftiger, damit die Fassung bei dieser Einstellung nicht
   verschwimmt. */
:root[data-a11y-contrast="high"] .page-leistungen .quote-band {
  --qb-ink: #dbe6fb;
  --qb-hair: rgba(255, 255, 255, .3);
}
:root[data-a11y-contrast="high"] .page-leistungen .quote-band .eyebrow { color: #fff; }
:root[data-a11y-contrast="high"] .page-leistungen .quote-band__inner::before,
:root[data-a11y-contrast="high"] .page-leistungen .quote-band__inner::after { opacity: .9; }
:root[data-a11y-contrast="high"] .page-leistungen .quote-band__icon {
  border-color: rgba(219, 230, 251, .6);
}

/* --- Schmale Fenster ----------------------------------------------------
   Ab 899 px stellt sich das Band von selbst um (sections/quote-band.css):
   Knopf unter den Text. Hier wird nur nachgezogen, was daran haengt -
   Polster, Symbolgroesse und die Eckwinkel, die naeher an den Inhalt
   ruecken muessen, damit sie im Seitenrand Platz haben.

   Bei 320 px betraegt der Seitenrand 20 px (--gutter); die Eckwinkel
   liegen dann 10 px ausserhalb des Inhalts und damit sicher im Bild. Die
   Zeile overflow: hidden am Band faengt jeden Rest ab. */
@media (max-width: 899px) {
  .page-leistungen .quote-band { padding-block: 52px 48px; }
  /* Der Abstand muss hier noch einmal stehen: die Regel oben ist staerker
     als die gestapelte Fassung in sections/quote-band.css und wuerde deren
     22 px sonst ueberschreiben. Gestapelt genuegen 28 px zwischen Text und
     Knopf - 40 px waeren dort ein Loch. */
  .page-leistungen .quote-band__inner {
    --qb-bracket: 18px;
    --qb-bracket-arm: 22px;
    gap: 28px;
  }
}

@media (max-width: 639px) {
  .page-leistungen .quote-band { padding-block: 44px 40px; }
  .page-leistungen .quote-band__inner { --qb-bracket: 10px; --qb-bracket-arm: 18px; }
  /* Der Kasten misst hier 56 px, die Zeichenflaeche darin 32 px. Die
     gemeinsame Fassung setzt an dieser Stelle 40 px an - das ist der
     Wert ohne Rahmen und Polster, den es dort nicht gibt. */
  .page-leistungen .quote-band__icon { width: 56px; height: 56px; padding: 11px; }
  /* Der Knopf steht hier ueber die volle Breite (gemeinsame Fassung) und
     braucht die grosse Bauhoehe nicht mehr. Die Zeile ist noetig, weil die
     Ruecknahme in components/button.css schwaecher ist als die Regel
     oben. */
  .page-leistungen .quote-band .btn--primary {
    --btn-h: 52px;
    --btn-px: 24px;
    font-size: var(--fs-btn-sm);
  }
}

/* ===== styles/sections/leistungen-ausbau.css ===== */
/* ===== Leistungen: Ausbau vom 18.09.2026 ================================
   Eigene Datei, damit der Ausbau in einem Stueck wieder verschwinden kann:
   die Zeile aus CSS_ORDER in scripts/build.mjs nehmen und die Seite aus
   reference/rueckbau/leistungen-2026-09-18/ zurueckholen - fertig. Die
   bestehende sections/leistungen.css bleibt davon unberuehrt; sie gestaltet
   das Angebots-Band am Seitenfuss und hat mit dem hier nichts zu tun.

   Alles haengt an .page-leistungen. Die Bausteine .split, .checklist und
   .flow stehen auch auf anderen Seiten - ohne die Seitenklasse faerbte jede
   Zeile dort ab.

   DIE SPRACHE
   Uebernommen ist die Kantensprache, die sections/leistungen.css am Band
   dieser Seite schon spricht: rechte Winkel, Haarlinien, Eckwinkel aus zwei
   Borderkanten, Ziffern in kleinen Kaesten. Es kommt also keine zweite
   Formensprache dazu, die vorhandene reicht nur weiter nach oben.

   DIE BEWEGUNG
   Drei Quellen, alle schon im Haus:
     1. data-reveal (scripts/reveal.js) - Einblenden beim Scrollen, greift
        auf jeder Seite und respektiert prefers-reduced-motion von selbst.
     2. Uebergaenge beim Ueberfahren - kosten nichts, wenn niemand hinfaehrt.
     3. Zwei Zahlen aus scripts/leistungen.js (--jump-x, --jump-w fuer die
        Marke im Sprungmenue, --flow-p fuer die Fortschrittslinie). Was
        daraus wird, steht ausschliesslich hier.
   Scrollgebundene Effekte aus scripts/scroll-fx.js gibt es bewusst nicht:
   das Modul ist an .page-start-2 gebunden und soll es bleiben.
   ======================================================================= */

/* ============ 1. Seitenkopf mit Sprungmenue ============================ */

.page-leistungen .page-head {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 44px 40px;
  background: linear-gradient(180deg, var(--surface-soft) 0%, #f7f9fc 46%, var(--surface) 100%);
  border-bottom: 0;
}

/* Ein sehr flaches Haarlinienraster, dasselbe Mittel wie am Band dieser
   Seite - nur hell statt dunkel. Es blendet nach unten aus, damit der
   erste Abschnitt nicht an einer angeschnittenen Rasterzeile anstoesst. */
.page-leistungen .page-head::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, rgba(30, 66, 144, .055) 0 1px, transparent 1px 72px),
    repeating-linear-gradient(0deg,  rgba(30, 66, 144, .055) 0 1px, transparent 1px 72px);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .4) 62%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .4) 62%, transparent 100%);
}

.page-leistungen .page-head__title { margin-top: 10px; }
.page-leistungen .page-head__text { margin-top: 16px; }

/* --- Das Sprungmenue -----------------------------------------------------
   Drei Ziele in einer Reihe, darunter eine durchgehende Haarlinie, auf der
   eine kraeftige Marke sitzt. Die Marke wandert zum aktiven Ziel, statt bei
   jedem Ziel eine eigene Unterstreichung ein- und auszublenden: eine
   Bewegung liest sich als Ortswechsel, vier Ueberblendungen als Flackern. */
/* Die Leiste steht im Fluss und scrollt mit. Sie war eine Zeit lang klebend
   unter der Kopfzeile - das ist auf Wunsch zurueckgenommen.

   Mit dem Kleben ist auch die wandernde Marke entfallen: Sie zeigte, in
   welchem Abschnitt man gerade steht, und das laesst sich nur beantworten,
   solange die Leiste im Bild ist. Uebrig bleiben drei Ankerlinks, die tun,
   was sie sollen - hinspringen. Zurueckholen liesse sich beides ueber
   reference/rueckbau/leistungen-2026-09-18/. */
.page-leistungen .jump-bar {
  border-bottom: 1px solid var(--line);
}

.page-leistungen .jump {
  --jump-x: 0px;    /* Startkante der Marke, von scripts/leistungen.js */
  --jump-w: 0px;    /* Breite der Marke, ebenso                        */

  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 30px;
  padding-block: 4px;
}

.page-leistungen .jump__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* 44px Tippflaeche, ohne dass die Reihe hoch wird. */
  min-height: 44px;
  padding-block: 10px;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--text);
  transition: color var(--dur-fast) var(--ease);
}
.page-leistungen .jump__link:hover { color: var(--ink); }

/* Das Ziffernkaestchen aus der Kantensprache dieser Seite. */
.page-leistungen .jump__num {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  padding: 2px 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  color: var(--blue-600);
  font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
  opacity: .55;
  transition: opacity var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.page-leistungen .jump__link:hover .jump__num {
  opacity: 1;
  background: var(--blue-600);
  color: #fff;
}

/* ============ 2. Die drei Leistungsabschnitte ========================== */

.page-leistungen .service-block {
  position: relative;
  /* Der Anker liegt sonst unter der schwebenden Kopfleiste: beim Sprung aus
     dem Menue stuende die Ueberschrift dahinter. */
  scroll-margin-top: calc(var(--header-total, 96px) + 24px);
}

/* Die grosse Ziffer ueber der Ueberschrift. Sie zaehlt nur mit - deshalb
   aria-hidden im Markup und hier eine Groesse, die als Marke gelesen wird
   und nicht als Text. */
.page-leistungen .service-block__num {
  display: block;
  margin-bottom: 6px;
  font-size: calc(13px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--blue-600);
}
/* Der kurze Strich dahinter zieht beim Einblenden auf - das wiederkehrende
   Zeichen dieser Seite. Er haengt an der Klasse, die reveal.js setzt. */
.page-leistungen .service-block__num::after {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 54px;
  height: 1px;
  margin-left: 12px;
  background: currentColor;
  opacity: .45;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 640ms var(--ease) 180ms;
}
.page-leistungen [data-reveal].is-revealed .service-block__num::after,
html:not(.js) .page-leistungen .service-block__num::after { transform: none; }

/* --- Die Bildfassung ----------------------------------------------------
   Rechte Winkel statt der Rundung aus components/feature.css, dazu ein
   Eckwinkelpaar wie am Band dieser Seite. Das Bild selbst sitzt in einem
   Rahmen mit overflow: hidden, damit es beim Ueberfahren hineinzoomen kann,
   ohne die Fassung zu sprengen. */
.page-leistungen .service-block__frame {
  position: relative;
  --frame-bracket: 14px;
  --frame-arm: 30px;
}
.page-leistungen .service-block__frame img {
  display: block;
  border-radius: 0;
  border: 1px solid var(--line-card);
  /* Beim Einblenden faehrt das Bild aus einer leichten Vergroesserung in
     seinen Stand - eine Bewegung, kein Aufblitzen. */
  transform: scale(1.04);
  transition: transform 900ms var(--ease);
}
.page-leistungen .service-block__frame.is-revealed img,
html:not(.js) .page-leistungen .service-block__frame img { transform: none; }
.page-leistungen .service-block__frame:hover img { transform: scale(1.035); }

/* Eckwinkel oben links und unten rechts, diagonal - dieselbe Bauart und
   dieselben Masse wie am Angebots-Band. Sie fahren beim Einblenden aus. */
.page-leistungen .service-block__frame::before,
.page-leistungen .service-block__frame::after {
  content: "";
  position: absolute;
  width: var(--frame-arm);
  height: var(--frame-arm);
  border: 0 solid var(--blue-600);
  pointer-events: none;
  opacity: 0;
  transform: scale(.5);
  transition: opacity 620ms var(--ease) 260ms, transform 620ms var(--ease) 260ms;
}
.page-leistungen .service-block__frame::before {
  top: calc(var(--frame-bracket) * -1);
  left: calc(var(--frame-bracket) * -1);
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-leistungen .service-block__frame::after {
  right: calc(var(--frame-bracket) * -1);
  bottom: calc(var(--frame-bracket) * -1);
  border-right-width: 1px;
  border-bottom-width: 1px;
}
.page-leistungen .service-block__frame.is-revealed::before,
.page-leistungen .service-block__frame.is-revealed::after,
html:not(.js) .page-leistungen .service-block__frame::before,
html:not(.js) .page-leistungen .service-block__frame::after {
  opacity: .5;
  transform: none;
}
.page-leistungen .service-block__frame:hover::before,
.page-leistungen .service-block__frame:hover::after { opacity: 1; }

/* --- Die Checkliste ------------------------------------------------------
   Die Punkte kommen einer nach dem anderen, statt alle zugleich. Die
   Verzoegerung haengt an der Position in der Liste - deshalb sechs feste
   Stufen statt einer Variablen, die das Markup mitliefern muesste. */
.page-leistungen .checklist--lg li {
  opacity: 0;
  transform: translateX(-10px);
  transition: opacity 520ms var(--ease), transform 520ms var(--ease);
}
.page-leistungen [data-reveal].is-revealed .checklist--lg li,
html:not(.js) .page-leistungen .checklist--lg li {
  opacity: 1;
  transform: none;
}
.page-leistungen .checklist--lg li:nth-child(1) { transition-delay: 160ms; }
.page-leistungen .checklist--lg li:nth-child(2) { transition-delay: 250ms; }
.page-leistungen .checklist--lg li:nth-child(3) { transition-delay: 340ms; }
.page-leistungen .checklist--lg li:nth-child(4) { transition-delay: 430ms; }
.page-leistungen .checklist--lg li:nth-child(5) { transition-delay: 520ms; }
.page-leistungen .checklist--lg li:nth-child(6) { transition-delay: 610ms; }

/* ============ 3. Band "Wie weit wir fahren" ============================= */

.page-leistungen .reach {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 92px 96px;
  color: #fff;
  /* Grundfarbe unter dem Foto: faellt das Bild aus, steht der Text trotzdem
     auf dunklem Grund und bleibt lesbar. */
  background: #0d1f47;
  border-top: 2px solid var(--blue-600);
}

.page-leistungen .reach__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.page-leistungen .reach__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Der Transporter steht links im Motiv. Da der Text nach rechts gerueckt
     ist, bekommt er dort jetzt die freie Flaeche. */
  object-position: 38% 42%;
}

/* Zwei Schleier ueber dem Foto: einer von links, damit der Text steht,
   einer von unten, damit der Uebergang zum naechsten Abschnitt nicht an
   einer harten Kante passiert. */
.page-leistungen .reach__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(265deg, rgba(10, 24, 54, .93) 0%, rgba(10, 24, 54, .82) 38%, rgba(10, 24, 54, .34) 72%, rgba(10, 24, 54, .2) 100%),
    linear-gradient(180deg, rgba(10, 24, 54, .35) 0%, rgba(10, 24, 54, 0) 34%, rgba(10, 24, 54, .55) 100%);
}

/* Haarlinienraster wie am Band dieser Seite - es verbindet die beiden
   dunklen Flaechen der Seite sichtbar miteinander. */
.page-leistungen .reach::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .05) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(0deg,  rgba(255, 255, 255, .05) 0 1px, transparent 1px 64px);
  -webkit-mask-image: radial-gradient(90% 120% at 88% 30%, #000 0%, transparent 78%);
          mask-image: radial-gradient(90% 120% at 88% 30%, #000 0%, transparent 78%);
}

/* Der Text steht rechts im Bild. Umgesetzt als eine einzige Rasterspalte,
   die an den rechten Rand geschoben wird - nicht als text-align: right.
   Der Unterschied ist wichtig: der Block sitzt rechts, die Zeilen darin
   bleiben linksbuendig. Rechtsbuendiger Fliesstext hat keine ruhige
   Einstiegskante und liest sich muehsam.

   Damit muss auch kein einziges Kind eine eigene Ausrichtung bekommen -
   Vorzeile, Ueberschrift, Text, Schlagworte und Knopf folgen alle der
   Spalte. */
.page-leistungen .reach__inner {
  display: grid;
  grid-template-columns: minmax(0, 54%);
  justify-content: end;
  justify-items: start;
}
.page-leistungen .reach__eyebrow {
  position: relative;
  padding-bottom: 14px;
  color: #9fbaf0;
}
.page-leistungen .reach__eyebrow::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 5px;
  width: 0;
  height: 1px;
  background: currentColor;
  opacity: .6;
  transition: width 700ms var(--ease) 140ms;
}
.page-leistungen .reach__eyebrow.is-revealed::after,
html:not(.js) .page-leistungen .reach__eyebrow::after { width: 48px; }

/* Keine eigenen Breitengrenzen mehr: die Rasterspalte ist das Mass. Mit
   einer zusaetzlichen Grenze von 17ch stuende die Ueberschrift mitten in
   ihrer eigenen Spalte und der Block saehe aus, als haette er den rechten
   Rand verfehlt. */
.page-leistungen .reach__title {
  margin-top: 12px;
  max-width: none;
  color: #fff;
  text-wrap: balance;
}
.page-leistungen .reach__text {
  margin-top: 18px;
  max-width: none;
  color: rgba(255, 255, 255, .84);
}

/* --- Die drei Schlagworte ------------------------------------------------
   Kein Versprechen, nur eine Staffelung: Stadt, Land, Union. Sie stehen als
   Kaesten mit rechten Winkeln, damit sie nicht wie Knoepfe aussehen. */
.page-leistungen .reach__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 30px;
}
.page-leistungen .reach__tag {
  padding: 9px 16px;
  border: 1px solid rgba(159, 186, 240, .38);
  background: rgba(159, 186, 240, .08);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: #dbe6fb;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.page-leistungen .reach__tags:hover .reach__tag { border-color: rgba(159, 186, 240, .22); }
.page-leistungen .reach__tag:hover {
  background: rgba(159, 186, 240, .18);
  border-color: rgba(159, 186, 240, .7);
}

/* Der Knopf wird umgedreht wie am Band dieser Seite: auf dunklem Grund ist
   die helle Flaeche der sichtbarste Punkt. */
.page-leistungen .reach__cta {
  margin-top: 34px;
  border-radius: 0;
  background: transparent;
  border-color: rgba(255, 255, 255, .5);
  color: #fff;
}
.page-leistungen .reach__cta:hover {
  background: #fff;
  border-color: #fff;
  color: var(--navy-900);
  box-shadow: 0 0 34px -8px rgba(159, 186, 240, .5);
}
.page-leistungen .reach :focus-visible { outline-color: #fff; }

/* ============ 4. Fortschrittslinie der Ablaufreihe ===================== */

.page-leistungen .flow__list[data-flowline] {
  --flow-p: 0;      /* 0..1, von scripts/leistungen.js */
  position: relative;
}
/* Die Linie liegt auf Hoehe der Ziffernscheiben und waechst mit dem
   Scrollen von links nach rechts. Sie liegt hinter den Scheiben (z-index),
   damit sie an ihnen nicht vorbeilaeuft, sondern sie zu verbinden scheint. */
.page-leistungen .flow__list[data-flowline]::before {
  content: "";
  position: absolute;
  left: 0;
  top: var(--flowline-y, 22px);
  width: 100%;
  height: 2px;
  z-index: -1;
  background: linear-gradient(90deg, var(--blue-600) 0%, var(--blue-600) 100%);
  transform: scaleX(var(--flow-p));
  transform-origin: 0 50%;
  opacity: .35;
  pointer-events: none;
}

/* ============ Erhoehter Kontrast ======================================== */

:root[data-a11y-contrast="high"] .page-leistungen .service-block__frame::before,
:root[data-a11y-contrast="high"] .page-leistungen .service-block__frame::after { opacity: .85; }
:root[data-a11y-contrast="high"] .page-leistungen .reach__eyebrow { color: #fff; }
:root[data-a11y-contrast="high"] .page-leistungen .reach__text { color: rgba(255, 255, 255, .95); }
:root[data-a11y-contrast="high"] .page-leistungen .reach__tag {
  border-color: rgba(219, 230, 251, .7);
  color: #fff;
}

/* ============ Weniger Bewegung ========================================== */
/* 05-motion.css nimmt Uebergaenge global zurueck. Hier steht nur, was sonst
   im Anfangszustand haengen bliebe - ein unsichtbares Bild oder eine Linie
   der Breite 0 waere schlimmer als gar keine Bewegung. */
@media (prefers-reduced-motion: reduce) {
  .page-leistungen .service-block__num::after,
  .page-leistungen .service-block__frame img { transform: none; }
  .page-leistungen .service-block__frame::before,
  .page-leistungen .service-block__frame::after { opacity: .5; transform: none; }
  .page-leistungen .checklist--lg li { opacity: 1; transform: none; }
  .page-leistungen .reach__eyebrow::after { width: 48px; }
  .page-leistungen .flow__list[data-flowline]::before { transform: none; }
}

/* ============ Schmale Fenster =========================================== */

@media (max-width: 1023px) {
  .page-leistungen .reach { padding-block: 72px 76px; }
  .page-leistungen .reach__inner { grid-template-columns: minmax(0, 66%); }
}

@media (max-width: 899px) {
  /* Gestapelt laeuft die Ablaufreihe senkrecht - eine waagrechte Linie
     haette dort nichts zu verbinden. */
  .page-leistungen .flow__list[data-flowline]::before { display: none; }
}

@media (max-width: 639px) {
  .page-leistungen .page-head { padding-block: 26px 28px; }
  /* Einzeilig und wischbar statt umgebrochen: zweizeilig kostete die
     klebende Leiste zusammen mit der Kopfzeile ein Sechstel des
     Bildschirms - auf einer Seite, die man zum Lesen aufruft, zu viel.

     ------------------------------------------------------------------- */
  .page-leistungen .jump {
    flex-wrap: nowrap;
    gap: 0 18px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .page-leistungen .jump::-webkit-scrollbar { display: none; }
  .page-leistungen .jump__link {
    flex: none;
    font-size: calc(13px * var(--fs-scale));
    gap: 7px;
  }
  .page-leistungen .jump__num { min-width: 22px; padding: 1px 4px; }
  .page-leistungen .service-block__frame { --frame-bracket: 9px; --frame-arm: 22px; }
  .page-leistungen .service-block__num::after { width: 34px; margin-left: 9px; }
  .page-leistungen .reach { padding-block: 56px 58px; }
  /* Volle Breite: 54 % waeren hier eine Spalte von 180 px. */
  .page-leistungen .reach__inner {
    grid-template-columns: minmax(0, 1fr);
    justify-content: stretch;
  }
  .page-leistungen .reach__tag { padding: 8px 13px; font-size: calc(13px * var(--fs-scale)); }
  .page-leistungen .reach__cta { width: 100%; justify-content: center; }
}

/* ============ 5. Umfang: das Diagramm ==================================
   Kein JavaScript. Der Zustand liegt in drei Radiofeldern, die im Markup
   VOR dem Diagramm stehen; das CSS greift mit dem Geschwisterwaehler (~)
   darauf zu. Das hat drei Vorteile gegenueber einer Skriptloesung:

     * Es funktioniert ohne JavaScript und ohne :has() - also auch dort,
       wo eines von beidem fehlt.
     * Tastatur und Vorlesesoftware bedienen echte Radiofelder von sich
       aus: Pfeiltasten, Gruppenname, gesprochener Zustand. Ein Nachbau
       aus <button> und aria-pressed muesste das alles nachahmen.
     * Der Zustand liegt an genau einer Stelle und kann nicht auseinander-
       laufen.

   Alles haengt an einer einzigen Zahl: --anteil, dem Teil der Arbeit, den
   die Kundschaft selbst uebernimmt. Balken, Messlatten und die sichtbare
   Notiz lesen sie ab.
   ======================================================================= */

.page-leistungen .umfang__title { margin-top: 10px; }
.page-leistungen .umfang__lead { margin-top: 16px; max-width: 62ch; }

.page-leistungen .scale {
  --scale-you: var(--blue-600);
  --scale-us: var(--navy-800);
  /* Eine Dauer fuer alles, damit die Teile zusammen laufen und nicht
     nacheinander eintrudeln. */
  --scale-dur: 620ms;
  margin-top: 40px;
}

/* Die Felder selbst sind unsichtbar, aber bedienbar: kein display: none,
   sonst waeren sie fuer Tastatur und Vorlesesoftware weg.

   BITTE NICHT "REPARIEREN": scripts/responsive.mjs meldet diese drei
   Felder als TAP24 (Tippziel unter 24x24). Das ist ein Messartefakt - der
   Pruefer misst den Kasten des <input>, nicht das, was man trifft.
   Getroffen wird die Beschriftung: 335x49 px auf dem Handy, und ein Klick
   darauf waehlt das Feld (nachgemessen am 18.09.2026). Die 1px-Fassung ist
   die uebliche zugaengliche Bauart; sie durch etwas Groesseres zu ersetzen
   wuerde die Meldung beseitigen und die Bedienung verschlechtern. */
.page-leistungen .scale__radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Die drei Schalter --------------------------------------------------- */
.page-leistungen .scale__choices {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.page-leistungen .scale__choice {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* 44px Tippflaeche. */
  min-height: 44px;
  padding: 10px 18px 10px 14px;
  background: var(--surface-soft);
  border: 1px solid var(--line-strong);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.page-leistungen .scale__choice:hover {
  border-color: var(--blue-600);
  color: var(--ink);
}
.page-leistungen .scale__num {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  padding: 2px 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  color: var(--blue-600);
  font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

/* Gewaehlt: umgedreht, wie der Knopf auf dunklem Grund anderswo auf der
   Seite. Die Regeln paaren das n-te Feld mit dem n-ten Schalter. */
.page-leistungen .scale__radio:nth-of-type(1):checked ~ .scale__choices .scale__choice:nth-child(1),
.page-leistungen .scale__radio:nth-of-type(2):checked ~ .scale__choices .scale__choice:nth-child(2),
.page-leistungen .scale__radio:nth-of-type(3):checked ~ .scale__choices .scale__choice:nth-child(3) {
  background: var(--navy-800);
  border-color: var(--navy-800);
  color: #fff;
}
.page-leistungen .scale__radio:nth-of-type(1):checked ~ .scale__choices .scale__choice:nth-child(1) .scale__num,
.page-leistungen .scale__radio:nth-of-type(2):checked ~ .scale__choices .scale__choice:nth-child(2) .scale__num,
.page-leistungen .scale__radio:nth-of-type(3):checked ~ .scale__choices .scale__choice:nth-child(3) .scale__num {
  background: #fff;
  color: var(--navy-800);
}

/* Der Fokusring haengt am Feld, sichtbar wird er am Schalter - sonst laege
   er an einem 1px grossen, unsichtbaren Kasten irgendwo daneben. */
.page-leistungen .scale__radio:nth-of-type(1):focus-visible ~ .scale__choices .scale__choice:nth-child(1),
.page-leistungen .scale__radio:nth-of-type(2):focus-visible ~ .scale__choices .scale__choice:nth-child(2),
.page-leistungen .scale__radio:nth-of-type(3):focus-visible ~ .scale__choices .scale__choice:nth-child(3) {
  outline: 2px solid var(--blue-600);
  outline-offset: 3px;
}

/* --- Die Tafel ----------------------------------------------------------- */
.page-leistungen .scale__board {
  /* Vorgabe = Stufe 01. Steht hier und nicht am Elternteil, damit die drei
     Regeln darunter sie ueberschreiben koennen.

     Zwei Zahlen statt einer: Der Preis war frueher schlicht 1 - Anteil.
     Das war rechnerisch bequem, aber falsch - wer die Haelfte der Arbeit
     abgibt, zahlt nicht die Haelfte. Fahrzeug, Anfahrt und Planung fallen
     immer an. Beide Reihen sind deshalb frei gesetzt und laufen nur noch
     in dieselbe Richtung, nicht mehr spiegelbildlich. */
  --anteil: .68;
  --preis: .22;
  margin-top: 22px;
  padding: 30px 32px 26px;
  background: var(--surface-soft);
  border: 1px solid var(--line-card);
}

/* --- Die Zahl, von der alles abhaengt ------------------------------------ */
.page-leistungen .scale__radio:nth-of-type(1):checked ~ .scale__board { --anteil: .68; --preis: .22; }
.page-leistungen .scale__radio:nth-of-type(2):checked ~ .scale__board { --anteil: .40; --preis: .48; }
/* Stufe 03 behaelt einen schmalen Streifen: Ganz ohne eigenes Feld saehe der
   Balken nicht wie eine Aufteilung aus, sondern wie ein Fehler. Der Streifen
   sagt zugleich das Richtige - den Schluessel uebergeben muss man. */
.page-leistungen .scale__radio:nth-of-type(3):checked ~ .scale__board { --anteil: .04; --preis: 1; }

.page-leistungen .scale__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 26px;
  margin: 0 0 14px;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--text);
}
.page-leistungen .scale__key {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.page-leistungen .scale__key::before {
  content: "";
  width: 12px;
  height: 12px;
  background: var(--scale-you);
}
.page-leistungen .scale__key--us::before { background: var(--scale-us); }

/* Der Balken. Die Fuge zwischen den Feldern ist eine echte Luecke von 3px:
   So bleibt der Uebergang auch bei erhoehtem Kontrast als Kante lesbar und
   nicht nur als Farbwechsel. */
.page-leistungen .scale__bar {
  display: flex;
  gap: 3px;
  height: 58px;
}
.page-leistungen .scale__part {
  display: block;
  /* flex-basis statt width: so teilen sich die beiden Felder den Platz
     restlos, egal wie breit die Tafel gerade ist. */
  transition: flex-basis var(--scale-dur) var(--ease);
}
.page-leistungen .scale__part--you {
  flex: 0 0 calc(var(--anteil) * 100%);
  background: var(--scale-you);
}
.page-leistungen .scale__part--us {
  flex: 1 1 auto;
  background: var(--scale-us);
}

/* --- Die beiden Messlatten ----------------------------------------------- */
.page-leistungen .scale__meters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 32px;
  margin: 26px 0 0;
}
.page-leistungen .scale__meter dt {
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.page-leistungen .scale__meter dd {
  margin: 8px 0 0;
  height: 8px;
  background: var(--line-strong);
}
.page-leistungen .scale__fill {
  display: block;
  height: 100%;
  background: var(--scale-us);
  transform-origin: 0 50%;
  transition: transform var(--scale-dur) var(--ease);
}
/* Der Aufwand waechst mit dem eigenen Anteil, der Preis laeuft dagegen.
   Das ist die ganze Aussage des Diagramms - und sie steckt in diesen zwei
   Zeilen. */
.page-leistungen .scale__meter--aufwand .scale__fill { transform: scaleX(var(--anteil)); }
.page-leistungen .scale__meter--preis .scale__fill { transform: scaleX(var(--preis)); }

/* --- Die wechselnde Notiz ------------------------------------------------
   Alle drei liegen uebereinander in derselben Rasterzelle, damit die Tafel
   beim Wechsel nicht in der Hoehe springt. Sichtbar ist immer genau eine. */
.page-leistungen .scale__notes {
  display: grid;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line-strong);
}
.page-leistungen .scale__note {
  grid-area: 1 / 1;
  margin: 0;
  font-size: var(--fs-body);
  color: var(--text);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--scale-dur) var(--ease), transform var(--scale-dur) var(--ease);
}
.page-leistungen .scale__radio:nth-of-type(1):checked ~ .scale__board .scale__note--01,
.page-leistungen .scale__radio:nth-of-type(2):checked ~ .scale__board .scale__note--02,
.page-leistungen .scale__radio:nth-of-type(3):checked ~ .scale__board .scale__note--03 {
  opacity: 1;
  transform: none;
}

.page-leistungen .scale__hint {
  margin: 16px 0 0;
  font-size: var(--fs-body-sm);
  color: var(--text-soft);
}

/* --- Erhoehter Kontrast --------------------------------------------------- */
:root[data-a11y-contrast="high"] .page-leistungen .scale__meter dd { background: #9aa0aa; }

/* --- Weniger Bewegung ----------------------------------------------------- */
/* Die sichtbare Notiz darf nicht im Anfangszustand haengen bleiben -
   unsichtbar waere schlimmer als sprunghaft. */
@media (prefers-reduced-motion: reduce) {
  .page-leistungen .scale__note { transform: none; }
}

/* --- Schmale Fenster ------------------------------------------------------ */
@media (max-width: 899px) {
  .page-leistungen .scale__board { padding: 24px 22px 22px; }
  .page-leistungen .scale__bar { height: 48px; }
}

@media (max-width: 639px) {
  .page-leistungen .scale { margin-top: 28px; }
  .page-leistungen .scale__choices { gap: 8px; }
  .page-leistungen .scale__choice {
    /* Volle Breite: nebeneinander waeren die drei Namen hier zu eng. */
    width: 100%;
    padding: 10px 14px;
    font-size: calc(14px * var(--fs-scale));
  }
  .page-leistungen .scale__board { padding: 20px 18px 18px; }
  .page-leistungen .scale__bar { height: 42px; }
  /* Untereinander: zwei Messlatten nebeneinander waeren hier je rund 130px
     breit - zu kurz, um einen Unterschied zu zeigen. */
  .page-leistungen .scale__meters { grid-template-columns: minmax(0, 1fr); gap: 14px; }
}

/* ===== styles/sections/startseite-2.css ===== */
/* =========================================================================
   Startseite 2 - eigene Gestaltungsebene
   -------------------------------------------------------------------------
   Diese Datei gilt ausschliesslich fuer src/pages/startseite-2.html. Jede
   Regel haengt an .page-start-2 (Front-Matter "bodyClass"). Die erste
   Startseite traegt nur .page-start und bleibt davon unberuehrt - das ist
   der einzige Grund, warum hier ueberhaupt eine zweite Klasse steht.

   Sie laedt als letzte Sektionsdatei und ueberschreibt damit bewusst
   Einzelheiten aus support.css, services.css, statement.css und den
   uebrigen - immer nur fuer diese eine Seite.

   Drei Gedanken tragen die Seite:

   1. KANTEN. Die erste Startseite trennt Abschnitte mit einer Haarlinie.
      Hier bekommt jeder Uebergang eine eigene Kante: geneigt, gezahnt,
      gerundet, geklammert. Dazu Eckwinkel an Bildern und Karten. Sie sind
      Auszeichnung, nicht Zierat - sie zeigen, wo etwas anfaengt und aufhoert.

   2. BEWEGUNG AM SCROLLWEG. Was sich bewegt, bewegt sich, weil gescrollt
      wird - nicht auf eigene Rechnung. Text faerbt sich wortweise ein,
      Fotos laufen langsamer als die Seite, das dunkle Band oeffnet sich.
      Die Zahlen dafuer liefert scripts/scroll-fx.js, die Wirkung steht hier.

   3. ANORDNUNG. Zwei Abschnitte sind umgestellt: bei den individuellen
      Transporten bleibt die Bildflaeche stehen waehrend der Text daran
      vorbeilaeuft, und der Abschluss ist eine eigene Fassung (Block 13) -
      er zeigt die Anfrage als Strecke von der Nachricht zur Antwort.

   Der Wortlaut der Seite ist bis auf einen Abschnitt unveraendert: nur der
   Abschluss hat neue Vorzeile, Ueberschrift und Haltebeschriftungen
   bekommen, weil er inhaltlich neu aufgebaut ist (Kunde, 31.08.2026).
   Fliesstext, Button und Schlusszeile stehen dort weiter wie auf
   index.html. Was an zusaetzlicher Beschriftung erscheint (die Ziffern
   01-03 an den Leistungskarten), ist CSS-content - Auszeichnung im selben
   Muster wie die bereits vorhandenen Ziffern der Varianten-Karten.

   prefers-reduced-motion schaltet den bewegten Teil ab: 05-motion.css
   nimmt global alle Uebergaenge zurueck, scroll-fx.js setzt zusaetzlich
   jeden Endwert sofort. Uebrig bleibt die ruhige Fassung mit allen Kanten.
   ========================================================================= */

.page-start-2 {
  /* Kantenwerte an einer Stelle. --edge ist die Haarlinie, --edge-ink die
     betonte Kante im Markenblau, --bracket die Schenkellaenge der
     Eckwinkel. */
  --edge: var(--line-strong);
  --edge-ink: var(--blue-600);
  --bracket: 15px;
  /* Weichzeichnung des Farbverlaufs im Text: ueber wie viele Woerter der
     Uebergang von blass nach dunkel laeuft. Kleiner = haertere Kante. */
  --fill-feather: 7;
}

/* =========================================================================
   1. Wortweise Einfaerbung beim Scrollen
   -------------------------------------------------------------------------
   scroll-fx.js legt jedes Wort in ein <span class="sfx-w"> mit seiner
   laufenden Nummer (--i) und setzt am Absatz die Wortzahl (--n) sowie den
   Scrollfortschritt (--p, 0..1). Den Rest rechnet das CSS.

   Jedes Wort bestimmt seinen eigenen Anteil --w: bis der Verlauf es
   erreicht hat 0, danach in --fill-feather Schritten auf 1. Weil alles an
   --p haengt, muss das Skript je Bild genau eine Eigenschaft setzen - nicht
   eine je Wort.

   Der ganze Block steht in @supports: ohne color-mix bliebe der Text sonst
   dauerhaft blass. Fehlt die Unterstuetzung, sieht der Absatz aus wie auf
   der ersten Startseite.
   ========================================================================= */
@supports (color: color-mix(in oklab, #000 50%, #fff)) {
  /* Bewusst .sfx-fill und nicht [data-fill]: die Klasse setzt das Skript
     erst, wenn es den Absatz wirklich in Woerter zerlegt hat. Damit haengt
     die blasse Grundfarbe untrennbar an den Wort-Huellen, die sie wieder
     aufheben. Alle Faelle ohne Zerlegung - weniger Bewegung gewuenscht,
     kein IntersectionObserver, Auszeichnung im Absatz - behalten dadurch
     von selbst die normale Textfarbe, statt blass stehen zu bleiben. */
  html.js .page-start-2 .sfx-fill {
    --p: 0;
    --fill-off: #b9bdc6;
    --fill-on: var(--ink);
    color: var(--fill-off);
  }
  html.js .page-start-2 .sfx-w {
    --w: clamp(0, calc((var(--p) * (var(--n) + var(--fill-feather)) - var(--i)) / var(--fill-feather)), 1);
    color: color-mix(in oklab, var(--fill-on) calc(var(--w) * 100%), var(--fill-off));
  }

  /* Auf dem dunklen Band laeuft derselbe Verlauf andersherum. */
  html.js .page-start-2 .statement .sfx-fill {
    --fill-off: rgba(255, 255, 255, .26);
    --fill-on: #fff;
  }
  html.js .page-start-2 .statement__lead.sfx-fill {
    --fill-off: rgba(255, 255, 255, .22);
    --fill-on: rgba(255, 255, 255, .86);
  }

  /* Hoher Kontrast: die blasse Stufe waere hier ein Rueckschritt. Der Text
     steht vollstaendig in seiner Endfarbe, die Bewegung entfaellt. */
  :root[data-a11y-contrast="high"] .page-start-2 .sfx-w {
    color: var(--fill-on);
  }
}

/* =========================================================================
   2. Kanten-Bausteine
   ========================================================================= */

/* --- Eckwinkel ----------------------------------------------------------
   Zwei Pseudoelemente ergeben ein diagonales Paar (oben links, unten
   rechts). Das genuegt, um eine Flaeche als "gefasst" zu lesen, und kostet
   die Haelfte eines vollen Rahmens. Sie fahren beim Einblenden aus. */
.page-start-2 .sfx-frame { position: relative; }
.page-start-2 .sfx-frame::before,
.page-start-2 .sfx-frame::after {
  content: "";
  position: absolute;
  width: var(--bracket);
  height: var(--bracket);
  border: 0 solid var(--edge-ink);
  pointer-events: none;
  opacity: .75;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.page-start-2 .sfx-frame::before {
  top: -1px;
  left: -1px;
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-start-2 .sfx-frame::after {
  right: -1px;
  bottom: -1px;
  border-right-width: 1px;
  border-bottom-width: 1px;
}

/* --- Vorzeilen bekommen einen Strich, der sich zieht --------------------
   Wiederkehrendes Zeichen ueber die ganze Seite: jede Vorzeile sitzt auf
   einer kurzen Linie, die beim Einblenden von links nach rechts waechst.
   Sie ersetzt den Abstand nicht, sie macht ihn sichtbar. */
.page-start-2 main .eyebrow {
  position: relative;
  padding-bottom: 15px;
}
.page-start-2 main .eyebrow::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 6px;
  width: 48px;
  height: 1px;
  background: currentColor;
  opacity: .45;
  transform: scaleX(0);
  transform-origin: 0 50%;
}
.page-start-2 main .eyebrow.is-revealed::after {
  transform: none;
  transition: transform 760ms var(--ease) calc(var(--reveal-delay, 0ms) + 120ms);
}
/* Vorzeilen ohne Einblendung (und die Fassung ohne JavaScript) zeigen den
   Strich einfach fertig. */
html:not(.js) .page-start-2 main .eyebrow::after,
.page-start-2 main .eyebrow:not([data-reveal])::after { transform: none; }

/* --- Lesefortschritt als Kante am oberen Rand ---------------------------
   Die einzige Bewegung, die ueber die ganze Seite laeuft. Sie liegt unter
   der Kopfleiste (--z-sticky ist 100) und nimmt keine Klicks an. */
.page-start-2::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  z-index: 90;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, var(--navy-800), var(--blue-500));
  transform: scaleX(var(--scroll-p, 0));
  transform-origin: 0 50%;
  pointer-events: none;
}

/* --- Zwei senkrechte Haarlinien am Inhaltsrahmen ------------------------
   Nur auf breiten Fenstern, wo neben dem Inhalt ohnehin Rand steht. Sie
   geben der Seite eine Spur, an der die Abschnitte haengen. Bewusst sehr
   blass: sie sollen im Blickfeld liegen, nicht darin stehen.

   Sie liegen ueber den Flaechen der Abschnitte, nicht darunter - sonst
   waeren sie von jedem randlosen Abschnitt verdeckt. Der Grauton ist so
   gewaehlt, dass er auf Weiss wie auf dem dunklen Band traegt.

   Sie beginnen erst an der weissen Platte, nicht im Foto des Auftakts:
   dort haetten sie kein Raster, an dem sie haengen, und lagen quer ueber
   dem Motiv. Deshalb haengen sie am Dokument (absolut) statt am Fenster
   (fixiert) - nur so bleibt ihr Anfang beim Scrollen an der Platte und
   wandert nicht mit dem Blick mit.

   Der Anfang ist die Oberkante der Platte. Sie steht in --lines-top, das
   scroll-fx.js einmal misst: in CSS ist sie nicht auszudruecken, weil der
   Auftakt zwar mindestens einen Bildschirm hoch ist, aber hoeher wird,
   sobald der Rechner mehr Platz braucht. Der Naeherungswert im Fallback
   gilt nur ohne JavaScript - 100svh fuer den Auftakt, seine 1 px
   Unterkante dazu, die 38 px Ueberlappung der Platte (Abschnitt 3) ab. */
@media (min-width: 1340px) {
  .page-start-2 { position: relative; }

  .page-start-2::after {
    content: "";
    position: absolute;
    inset: var(--lines-top, calc(100svh - 37px)) 0 0;
    z-index: 2;
    pointer-events: none;
    background:
      linear-gradient(rgba(128, 140, 160, .17), rgba(128, 140, 160, .17)) calc(50% - var(--container) / 2 - 40px) 0 / 1px 100% no-repeat,
      linear-gradient(rgba(128, 140, 160, .17), rgba(128, 140, 160, .17)) calc(50% + var(--container) / 2 + 40px) 0 / 1px 100% no-repeat;
  }
}

/* --- Bezugspunkt fuer alle Kanten, die an einem Abschnitt haengen -------
   Die gezahnte Kante, das Lot und die Klammer am Abschluss sind
   Pseudoelemente ihrer Sektion und brauchen sie als Bezug. Steht bewusst
   ausserhalb der Klebe-Regeln weiter unten: die gelten erst ab 900 px, die
   Kanten aber auf jeder Breite. */
.page-start-2 main > * { position: relative; }

/* =========================================================================
   3. Auftakt: das Foto zieht sich zurueck, die Platte faehrt darueber
   -------------------------------------------------------------------------
   Der Auftakt scrollt normal weg - das Foto verlaesst die Seite mit ihm und
   steht nicht hinter den folgenden Abschnitten. (Eine frueher hier
   erprobte Klebe-Fassung tat genau das und wurde verworfen: das Motiv lag
   dann hinter der ganzen Seite und schien durch jede Luecke.)

   Was bleibt, ist die Bewegung, die den Uebergang traegt:

     * Das Foto laeuft langsamer als die Seite. Dazu ist die Bildflaeche
       oben und unten ueber den Abschnitt hinaus gezogen und wandert
       innerhalb dieses Vorlaufs nach unten; .hero2 schneidet ab
       (overflow: hidden). Bewusst ueber die Hoehe und nicht ueber scale:
       eine gleichmaessige Vergroesserung machte das Foto ohne Gegenwert
       breiter als das Fenster.
     * Die Aussage im Bild zieht sich zurueck und wird blasser.
     * Der Abschnitt darunter schiebt sich als weisse Platte mit gerundeter
       Oberkante darueber.

   Alles haengt an --hero-p, also an der Scrollposition (scroll-fx.js).

   Erst ab 900 px: darunter steht das Foto ohnehin als eigene Flaeche ueber
   dem Text (siehe hero-two.css) und hat kein Bild, hinter dem es laufen
   koennte.
   ========================================================================= */
@media (min-width: 900px) {
  /* Der Auftakt bleibt in der normalen Reihenfolge stehen und liegt nur
     unter der Platte, die ihn ueberfaehrt. */
  .page-start-2 .hero2 { z-index: 0; }
  .page-start-2 .support,
  .page-start-2 .services { z-index: 1; }

  /* Vorlauf oben und unten, in dem das Motiv wandern kann.

     23.09.2026 leicht verkleinert (Kundenwunsch: minimal herauszoomen).
     Der Kasten war 136 % der Auftaktshoehe hoch; je hoeher er ist, desto
     mehr schneidet object-fit: cover seitlich weg. Mit 130 % bleiben rund
     68 % der Bildbreite stehen statt 66 % - eine kleine Stufe, keine neue
     Bildaufteilung.

     Die Wanderung muss kleiner bleiben als der Vorlauf, sonst faehrt die
     Oberkante des Motivs in den Auftakt hinein und es klafft eine Luecke.
     Sie ist deshalb von 16vh auf 13vh mitgegangen: 13vh < 15 % von 100vh. */
  .page-start-2 .hero2__media {
    inset: -15% 0;
    translate: 0 calc(var(--hero-p, 0) * 13vh);
  }

  .page-start-2 .hero2__inner {
    transform: translateY(calc(var(--hero-p, 0) * -52px));
    opacity: calc(1 - var(--hero-p, 0) * .9);
  }

  /* Die Platte, die darueber faehrt: gerundete Oberkante, deckende Flaeche
     und ein Schatten, der nur nach oben faellt. Deckend muss sie sein,
     weil sie den Auftakt um 38 px ueberlappt. */
  .page-start-2 .support {
    position: relative;
    margin-top: -38px;
    border-top: 0;
    border-radius: 38px 38px 0 0;
    background-color: var(--surface);
    box-shadow: 0 -22px 44px -26px rgba(15, 36, 82, .38);
  }
}

/* =========================================================================
   4. Unterstuetzungs-Karten: gefasst statt nur gefuellt
   ========================================================================= */

/* Die Kennzeichnung bekommt einen Rahmen um die Ziffer - dieselbe Sprache
   wie die Eckwinkel, nur klein. */
.page-start-2 .support-card__num {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  padding: 2px 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-variant-numeric: tabular-nums;
  opacity: .85;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.page-start-2 .support-card:hover .support-card__num {
  background: var(--blue-600);
  color: #fff;
  opacity: 1;
}

/* Die Karte selbst: Eckwinkel und eine Haarlinie zwischen Text und Bild.
   Die Winkel fahren beim Einblenden aus - sie sind an dieselbe Klasse
   gebunden, die reveal.js setzt, brauchen also kein eigenes Skript. */
.page-start-2 .support-card {
  position: relative;
  border: 1px solid transparent;
  transition:
    background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}
.page-start-2 .support-card::before,
.page-start-2 .support-card::after {
  content: "";
  position: absolute;
  width: 22px;
  height: 22px;
  border: 0 solid var(--edge-ink);
  pointer-events: none;
  opacity: 0;
  transform: scale(.4);
  transition: opacity 620ms var(--ease), transform 620ms var(--ease);
}
.page-start-2 .support-card::before {
  top: 14px;
  left: 14px;
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-start-2 .support-card::after {
  right: 14px;
  bottom: 14px;
  border-right-width: 1px;
  border-bottom-width: 1px;
}
.page-start-2 .support-card.is-revealed::before,
.page-start-2 .support-card.is-revealed::after,
html:not(.js) .page-start-2 .support-card::before,
html:not(.js) .page-start-2 .support-card::after {
  opacity: .55;
  transform: none;
  transition-delay: calc(var(--reveal-delay, 0ms) + 380ms);
}
.page-start-2 .support-card:hover { border-color: #dde1e8; }
.page-start-2 .support-card:hover::before,
.page-start-2 .support-card:hover::after { opacity: 1; }

/* Das Bild wird beim Einblenden von oben nach unten aufgedeckt - eine
   Kante, die ueber das Foto laeuft, statt es nur einzublenden. */
.page-start-2 .support-card__media {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.06);
  transition: clip-path 900ms var(--ease), transform 1200ms var(--ease);
  will-change: clip-path;
}
.page-start-2 .support-card.is-revealed .support-card__media,
html:not(.js) .page-start-2 .support-card__media {
  clip-path: inset(0 0 0 0);
  transform: none;
  transition-delay: calc(var(--reveal-delay, 0ms) + 260ms);
}
/* Innerhalb des aufgedeckten Ausschnitts laeuft das Motiv beim Scrollen
   langsamer als die Seite (--shift kommt aus scroll-fx.js). */
.page-start-2 .support-card.is-revealed .support-card__media {
  translate: 0 var(--shift, 0px);
}

/* Der gemeinsame Vertrauensbereich: aus zwei gleichen Spalten wird eine
   ungleiche mit einer echten Trennkante dazwischen. */
@media (min-width: 768px) {
  .page-start-2 .support__note {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: 0;
    padding: 0;
  }
  .page-start-2 .support__note-main { padding: 30px 40px 30px 32px; }
  .page-start-2 .support__note-aside {
    padding: 30px 32px 30px 40px;
    border-left: 1px solid var(--line-card);
    background: var(--surface);
  }
}

/* =========================================================================
   5. Uebergang zu den Leistungen: geneigte Kante
   -------------------------------------------------------------------------
   Der Abschnitt bekommt eine eigene, leicht getoente Flaeche und schneidet
   seine Oberkante schraeg an. Damit unterscheidet sich dieser Uebergang
   klar vom gerundeten davor und vom gezahnten danach.
   ========================================================================= */
.page-start-2 .services {
  background-color: var(--surface-band);
  margin-top: -44px;
  padding-block: 104px 84px;
  clip-path: polygon(0 44px, 100% 0, 100% 100%, 0 100%);
}

/* Die Neigung allein traegt den Uebergang nicht: zwischen Weiss und der
   getoenten Flaeche liegen keine zwei Prozent Helligkeit. Die Kante bekommt
   deshalb eine Haarlinie.

   Sie kommt aus einem Farbverlauf, weil er die Neigung von selbst trifft:
   "to top left" legt seine Farbbaender genau auf die Verbindung der beiden
   Nachbarecken - bei einem Kasten von voller Breite und 44 px Hoehe also
   auf dieselbe Schraege, die auch der Beschnitt schneidet. Kein Winkel muss
   von Hand nachgerechnet werden, auch nicht beim Wechsel der Fensterbreite.

   Das Band ist 2 px breit, weil der Beschnitt die aeussere Haelfte
   wegnimmt; sichtbar bleibt eine saubere Linie. */
.page-start-2 .services::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 44px;
  pointer-events: none;
  background: linear-gradient(
    to top left,
    transparent calc(50% - 1px),
    var(--edge) calc(50% - 1px),
    var(--edge) calc(50% + 1px),
    transparent calc(50% + 1px)
  );
}

/* Ziffernmarke an jeder Leistungskarte. Dieselbe Auszeichnung wie an den
   Varianten-Karten weiter oben, damit die Seite eine Sprache spricht.
   CSS-content: Auszeichnung, kein Inhalt - der Zaehler steht nicht im
   Markup und wird von Vorlesesoftware uebergangen. */
.page-start-2 .services__grid { counter-reset: sfx-svc; }
.page-start-2 .services__grid .card { counter-increment: sfx-svc; }
.page-start-2 .services__grid .card__media::before {
  content: counter(sfx-svc, decimal-leading-zero);
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 1;
  padding: 3px 8px;
  background: rgba(255, 255, 255, .9);
  border: 1px solid rgba(20, 40, 80, .16);
  border-radius: 3px;
  font-size: calc(11px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: .14em;
  line-height: 1.4;
  color: var(--navy-800);
  font-variant-numeric: tabular-nums;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.page-start-2 .services__grid .card:hover .card__media::before {
  background: var(--navy-800);
  color: #fff;
}

/* Kante, die beim Ueberfahren ueber die Oberkante der Karte laeuft.
   pointer-events ab: die ganze Karte ist ueber .card__link::after klickbar,
   und der Streifen liegt mit z-index 2 darueber - ohne diese Zeile schluckte
   er die obersten zwei Pixel des Klickziels. */
.page-start-2 .services__grid .card::before {
  content: "";
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  height: 2px;
  background: var(--blue-600);
  border-radius: var(--r-md) var(--r-md) 0 0;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 520ms var(--ease);
  pointer-events: none;
  z-index: 2;
}
.page-start-2 .services__grid .card:hover::before,
.page-start-2 .services__grid .card:focus-within::before { transform: none; }

/* =========================================================================
   6. Uebergang zum Ueberblick: gezahnte Kante
   -------------------------------------------------------------------------
   Eine Haarlinie mit aufgesetzten Teilstrichen, wie an einem Massstab. Sie
   ersetzt die glatte Trennlinie und macht den Wechsel von der getoenten
   auf die weisse Flaeche zu einem eigenen Ereignis.
   ========================================================================= */
.page-start-2 .overview {
  background-color: var(--surface);
  border-top: 0;
  padding-top: 84px;
}
.page-start-2 .overview::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 10px;
  pointer-events: none;
  background:
    linear-gradient(var(--edge), var(--edge)) 0 0 / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, var(--edge) 0 1px, transparent 1px 36px) 0 0 / 100% 10px no-repeat;
}

/* Die Zeilen bekommen beim Ueberfahren eine volle Klammer statt nur der
   linken Kante: oben und unten faehrt die Linie mit ein. */
.page-start-2 .overview__row::after {
  content: "";
  position: absolute;
  inset: 0 0 -1px 0;
  border-top: 1px solid var(--edge-ink);
  border-bottom: 1px solid var(--edge-ink);
  opacity: 0;
  transform: scaleX(.9);
  transform-origin: 0 50%;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.page-start-2 .overview__row:hover::after,
.page-start-2 .overview__row:focus-within::after {
  opacity: .5;
  transform: none;
}

/* =========================================================================
   7. Das dunkle Band oeffnet sich beim Scrollen
   -------------------------------------------------------------------------
   Der auffaelligste scrollgebundene Uebergang der Seite. Das Band kommt als
   schmale, gerundete Platte ins Bild und waechst auf die volle Breite, je
   weiter man scrollt. Umgesetzt mit clip-path: der Beschnitt kostet kein
   Layout, die Seite springt also nicht.

   --p kommt aus scroll-fx.js. Ohne JavaScript steht das Band offen da, also
   genau wie auf der ersten Startseite.
   ========================================================================= */
html.js .page-start-2 .statement {
  --p: 0;

  /* Das Band ist hoch; ueber seinen ganzen Weg durch das Fenster gerechnet
     waere es erst offen, wenn es fast wieder draussen ist. --open geht
     deshalb schneller als --p und steht bei gut der Haelfte des Weges auf
     1: das Band ist offen, sobald man es liest, und nicht erst danach. */
  --open: clamp(0, calc(var(--p) * 1.9), 1);

  /* Wie weit die Platte im geschlossenen Zustand eingezogen ist. Zwei
     Grenzen, beide notwendig:
       6vw            waechst mit dem Fenster mit,
       (Rest - 18px)  laesst den Einzug nie den Inhaltsrahmen erreichen -
                      sonst schnitte die Platte in die Ueberschrift.
     Auf Fenstern ohne freien Rand wird daraus 0: dort steht das Band von
     Anfang an randlos, was richtiger ist als eine beschnittene Zeile.
     100vw rechnet die Bildlaufleiste mit, der Abzug faengt das mit ab. */
  --band-inset: max(0px, min(6vw, calc((100vw - var(--container)) / 2 - 18px)));

  /* Die weisse Rueckwand. Sie muss hier stehen, weil die dunkle Platte im
     eingeklappten Zustand seitlich Platz laesst - ohne sie schiene an
     diesen Stellen der geklebte Auftakt durch. */
  background: var(--surface);
}

/* Die dunkle Platte selbst. Sie traegt jetzt den Verlauf, der sonst am
   Abschnitt haengt, und wird als einzige beschnitten. z-index -2 haelt sie
   unter dem Lichtschein (-1), beide bleiben unter dem Inhalt. */
html.js .page-start-2 .statement::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background: linear-gradient(160deg, var(--navy-900) 0%, var(--navy-800) 52%, #16386f 100%);
  /* Die Rundung haengt am Einzug, nicht an einem festen Wert: wo kein
     Rand frei ist (schmale Fenster, --band-inset also 0), waeren runde
     Ecken an einer randlosen Flaeche nur abgeschnittene Ecken. */
  clip-path: inset(
    0 calc((1 - var(--open)) * var(--band-inset))
    round calc((1 - var(--open)) * min(36px, var(--band-inset) * .42))
  );
}

/* Der Lichtschein folgt dem Scrollweg: er wandert von rechts oben in die
   Mitte, waehrend sich die Platte oeffnet. Wo er im eingeklappten Zustand
   ueber die Platte hinausragt, faellt er nicht auf - er ist weisses Licht
   auf weisser Rueckwand. */
html.js .page-start-2 .statement::before {
  transform: translate(calc(var(--p, 0) * -14%), calc(var(--p, 0) * 16%));
  opacity: calc(.35 + var(--p, 0) * .65);
}

/* Eckwinkel in Weiss - dieselbe Auszeichnung wie auf hellem Grund. */
.page-start-2 .statement__inner {
  position: relative;
  padding-block: 6px;
}
.page-start-2 .statement__inner::before,
.page-start-2 .statement__inner::after {
  content: "";
  position: absolute;
  width: 26px;
  height: 26px;
  border: 0 solid rgba(255, 255, 255, .55);
  pointer-events: none;
}
/* Nur 10 px ausserhalb des Inhaltsrahmens: der Einzug der Platte haelt
   18 px Abstand zum Rahmen, damit bleiben die Winkel auch im eingeklappten
   Zustand auf dunklem Grund. Weiter aussen waeren sie weiss auf weiss. */
.page-start-2 .statement__inner::before {
  top: 0;
  left: -10px;
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-start-2 .statement__inner::after {
  right: -10px;
  bottom: 0;
  border-right-width: 1px;
  border-bottom-width: 1px;
}

/* Die vier Kacheln erben die Kantensprache: statt einer Flaeche, die beim
   Ueberfahren aufhellt, faehrt eine helle Kante von links ein. */
.page-start-2 .statement__point { position: relative; }
.page-start-2 .statement__point::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: #9fbaf0;
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform var(--dur) var(--ease);
}
.page-start-2 .statement__point:hover::before { transform: none; }

/* =========================================================================
   8. Uebergang zum Ablauf: Lot unter dem Band
   -------------------------------------------------------------------------
   Ein auf die Spitze gestelltes Quadrat haengt aus dem dunklen Band in den
   hellen Abschnitt darunter. Es steht auf .steps, nicht auf .statement:
   das Band beschneidet sich selbst (siehe oben), ein Anhaengsel waere
   abgeschnitten.
   ========================================================================= */
.page-start-2 .steps {
  position: relative;
  border-top: 0;
  padding-top: 84px;
}
.page-start-2 .steps::before {
  content: "";
  position: absolute;
  top: -9px;
  left: 50%;
  width: 18px;
  height: 18px;
  transform: translateX(-50%) rotate(45deg);
  background: #16386f;
  pointer-events: none;
}

/* Die Verbindungslinien der Ablaufreihe ziehen sich mit dem Scrollweg.
   --p liegt an .flow__list (data-progress); jede Linie startet ein Stueck
   spaeter als die davor, damit die Reihe von links nach rechts entsteht. */
html.js .page-start-2 .steps .flow__list { --p: 0; }
html.js .page-start-2 .steps .flow__rule {
  transform: scaleX(clamp(0, calc(var(--p) * 4 - var(--rule-i, 0)), 1));
  transform-origin: 0 50%;
}
html.js .page-start-2 .steps .flow__step:nth-child(2) .flow__rule { --rule-i: .55; }
html.js .page-start-2 .steps .flow__step:nth-child(3) .flow__rule { --rule-i: 1.1; }

/* Die Ziffernscheibe faerbt sich, sobald ihre Linie sie erreicht hat. */
html.js .page-start-2 .steps .flow__num {
  transition: background-color 420ms var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* =========================================================================
   10. Platzhalterflaechen: Eckwinkel
   -------------------------------------------------------------------------
   Die Bildflaeche der Individuellen Transporte bekommt dieselbe Fassung wie
   die uebrigen Kanten der Seite: zwei Winkel an gegenueberliegenden Ecken.
   ========================================================================= */
.page-start-2 .individual__media .ph {
  /* Eckwinkel als Fassung der Platzhalterflaeche. */
  position: relative;
}
.page-start-2 .individual__media .ph::before {
  content: "";
  position: absolute;
  top: -7px;
  left: -7px;
  width: var(--bracket);
  height: var(--bracket);
  border-top: 1px solid var(--edge-ink);
  border-left: 1px solid var(--edge-ink);
  pointer-events: none;
}
.page-start-2 .individual__media .ph::after {
  content: "";
  position: absolute;
  right: -7px;
  bottom: -7px;
  width: var(--bracket);
  height: var(--bracket);
  border-right: 1px solid var(--edge-ink);
  border-bottom: 1px solid var(--edge-ink);
  pointer-events: none;
}

/* =========================================================================
   11. Individuelle Transporte: die Bildflaeche bleibt stehen
   -------------------------------------------------------------------------
   Zweite Umstellung der Anordnung. Der Text laeuft an der stehenden
   Bildflaeche vorbei. align-items muss dafuer von center auf start - eine
   mittig ausgerichtete Zelle hat keinen Weg, an dem sie kleben koennte.
   ========================================================================= */
@media (min-width: 1024px) {
  .page-start-2 .individual__inner { align-items: start; }
  .page-start-2 .individual__media {
    position: sticky;
    top: calc(var(--header-total) + 28px);
  }
}

.page-start-2 .individual { border-top: 1px solid var(--edge); }

/* Die Beispiel-Pillen kommen beim Einblenden nacheinander, von links. */
.page-start-2 .individual__tags .individual__tag {
  opacity: 0;
  transform: translateX(-10px);
}
.page-start-2 .individual__tags.is-revealed .individual__tag,
html:not(.js) .page-start-2 .individual__tags .individual__tag {
  opacity: 1;
  transform: none;
  transition: opacity 480ms var(--ease), transform 480ms var(--ease);
}
.page-start-2 .individual__tags.is-revealed .individual__tag:nth-child(1) { transition-delay: 60ms; }
.page-start-2 .individual__tags.is-revealed .individual__tag:nth-child(2) { transition-delay: 130ms; }
.page-start-2 .individual__tags.is-revealed .individual__tag:nth-child(3) { transition-delay: 200ms; }
.page-start-2 .individual__tags.is-revealed .individual__tag:nth-child(4) { transition-delay: 270ms; }
.page-start-2 .individual__tags.is-revealed .individual__tag:nth-child(5) { transition-delay: 340ms; }

/* =========================================================================
   12. Kundenstimmen: die Gesamtbewertung wird gefasst
   ========================================================================= */
.page-start-2 .testimonials { border-top: 1px solid var(--edge); }
.page-start-2 .rating-sum {
  position: relative;
  border-radius: 0;
}
.page-start-2 .rating-sum::before,
.page-start-2 .rating-sum::after {
  content: "";
  position: absolute;
  width: 12px;
  height: 12px;
  border: 0 solid var(--edge-ink);
  pointer-events: none;
}
.page-start-2 .rating-sum::before {
  top: -4px;
  left: -4px;
  border-top-width: 1px;
  border-left-width: 1px;
}
.page-start-2 .rating-sum::after {
  right: -4px;
  bottom: -4px;
  border-right-width: 1px;
  border-bottom-width: 1px;
}

/* Die Bewertungskarten heben sich beim Ueberfahren mit einer Kante oben.

   Die Kante haengt an ::after, nicht an ::before. ::before traegt in
   components/testimonial.css das grosse Anfuehrungszeichen oben rechts -
   die Kante hat es dort einmal verdraengt, womit die Karten als einzige
   der Seite ohne dieses Zeichen dastanden. Beides passt nebeneinander,
   solange jede Wirkung ihr eigenes Pseudoelement behaelt. */
.page-start-2 .testimonial {
  position: relative;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.page-start-2 .testimonial::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--blue-600);
  border-radius: var(--r-md) var(--r-md) 0 0;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 520ms var(--ease);
  pointer-events: none;
}
.page-start-2 .testimonial:hover { transform: translateY(-4px); }
.page-start-2 .testimonial:hover::after { transform: none; }

/* =========================================================================
   13. Abschluss: die Anfrage als Strecke
   -------------------------------------------------------------------------
   NUR .closing--route, also nur die zweite Startseite. index.html behaelt
   den hellen, mittig gesetzten Abschluss aus sections/closing.css - keine
   Regel hier fasst ihn an.

   Der Gedanke: Der letzte Abschnitt einer Transportseite zeigt, was eine
   Anfrage selbst ist - eine kurze Strecke von der Nachricht zur Antwort.
   Die Linie liegt quer ueber den Abschnitt, der Lastwagen darauf faehrt
   sie ab, waehrend man zum Seitenende scrollt (--p aus scroll-fx.js,
   data-progress an .route).

   Warum dunkel, obwohl das Vertrauensband weiter oben schon dunkel ist:
   die beiden sehen bewusst nicht gleich aus. Das Band ist eine glatte
   Verlaufsflaeche, der Abschluss fast schwarzes Navy mit einem
   Haarlinienraster - die Kantensprache der Seite an ihrem Ende zu Ende
   gefuehrt. Die Fusszeile darunter ist weiss, der Abschluss steht also
   fuer sich.
   ========================================================================= */
.page-start-2 .closing--route {
  --route-ink: #cfe0ff;      /* Beschriftung auf dunklem Grund            */
  --route-line: rgba(255, 255, 255, .18);
  --route-live: #9fbaf0;     /* zurueckgelegter Teil, wie die Vorzeilen   */

  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 92px 88px;
  border: 0;
  background:
    radial-gradient(120% 90% at 18% 0%, #16386f 0%, rgba(22, 56, 111, 0) 60%),
    linear-gradient(180deg, #0d1f47 0%, #0a1836 100%);
  color: #fff;
}

/* Haarlinienraster. Es liegt sehr flach unter allem und gibt der Flaeche
   Massstab, ohne als Muster aufzufallen - dasselbe Mittel wie die
   gezahnte Kante und die senkrechten Linien am Inhaltsrahmen. Nach unten
   blendet es aus, damit die Fusszeile nicht angeschnitten wirkt. */
.page-start-2 .closing--route::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .05) 0 1px, transparent 1px 88px),
    repeating-linear-gradient(0deg,  rgba(255, 255, 255, .05) 0 1px, transparent 1px 88px);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .25) 78%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .25) 78%, transparent 100%);
}

/* Das Lot am oberen Rand zeigt nach oben in die weisse Flaeche darueber -
   Gegenstueck zum gefuellten Lot unter dem Vertrauensband. Es traegt die
   Farbe des Abschlusses, haengt also sichtbar an ihm. */
.page-start-2 .closing--route::before {
  content: "";
  position: absolute;
  top: -9px;
  left: 50%;
  width: 18px;
  height: 18px;
  transform: translateX(-50%) rotate(45deg);
  background: #0d1f47;
  border: 0;
  z-index: -1;
  pointer-events: none;
}

/* Die mittige Ausrichtung der hellen Fassung wird zurueckgenommen: hier
   steht alles links am Raster, wie im uebrigen Seitenaufbau. */
.page-start-2 .closing--route .closing__inner {
  display: block;
  text-align: left;
}

/* --- Kopf: Aussage links, Erlaeuterung rechts --------------------------- */
.page-start-2 .closing--route .closing__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 20px 60px;
  align-items: end;
}
.page-start-2 .closing--route .eyebrow { color: var(--route-live); }
.page-start-2 .closing--route .closing__title {
  margin-top: 0;
  /* 21ch: gerade so breit, dass "wohin es gehen soll." in einer Zeile
     steht. Enger zerfiele die Aussage in drei Zeilen. */
  max-width: 21ch;
  color: #fff;
}
.page-start-2 .closing--route .closing__text {
  margin-top: 0;
  max-width: 52ch;
}
/* Die wortweise Einfaerbung laeuft hier hell statt dunkel. */
html.js .page-start-2 .closing--route .sfx-fill {
  --fill-off: rgba(255, 255, 255, .22);
  --fill-on: rgba(255, 255, 255, .88);
}

/* --- Die Strecke -------------------------------------------------------- */
.page-start-2 .route {
  --p: 0;
  /* Der Lastwagen soll ankommen, bevor die Seite zu Ende ist. Unter der
     Strecke liegt nur noch der Fuss des Abschnitts und die Fusszeile - auf
     hohen Fenstern reicht dieser Scrollweg gerade eben. --drive geht darum
     schneller als --p und steht bei vier Fuenfteln des Weges auf 1. Ohne
     das bliebe der Wagen je nach Fensterhoehe kurz vor dem Ziel stehen.
     Dasselbe Mittel wie --open am dunklen Band. */
  --drive: clamp(0, calc(var(--p) * 1.25), 1);
  /* Abstand der beiden Haeuser von den Enden der Spur. */
  --route-house: 26px;
  margin-top: 64px;
}
html:not(.js) .page-start-2 .route { --p: 1; }

/* Linie: der offene Teil gestrichelt, der zurueckgelegte durchgezogen.
   Zwei Ebenen uebereinander, damit der Wechsel eine Kante ist und kein
   Verlauf. */
.page-start-2 .route__track {
  position: relative;
  height: 2px;
  /* Beidseitig eingerueckt: in der gewonnenen Luft stehen die beiden
     Haeuser, sonst ragten sie aus dem Inhaltsrahmen. */
  margin-inline: calc(var(--route-house) + 16px);
  background: repeating-linear-gradient(90deg, var(--route-line) 0 7px, transparent 7px 14px);
}
/* Der zurueckgelegte Teil muss sich deutlich von der gestrichelten
   Reststrecke abheben, sonst liest man den Fortschritt nicht. Er ist
   darum durchgezogen, heller als die Linie und traegt einen weichen
   Schein - so wirkt er wie beleuchtete Fahrbahn statt wie eine zweite
   graue Linie. */
.page-start-2 .route__done {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(var(--drive) * 100%);
  background: linear-gradient(90deg, rgba(159, 186, 240, .6), #fff);
  box-shadow: 0 0 12px rgba(159, 186, 240, .55);
}

/* Halte-Punkte. Der Start ist von Anfang an gesetzt, das Ziel fuellt sich
   erst auf den letzten Prozent des Weges - der Lastwagen kommt an. */
.page-start-2 .route__dot {
  position: absolute;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -5.5px;
  border-radius: 50%;
  border: 2px solid var(--route-live);
  background: #0a1836;
}
.page-start-2 .route__dot--start { left: -5.5px; background: var(--route-live); }
.page-start-2 .route__dot--end   { right: -5.5px; }
.page-start-2 .route__dot--end::after {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  background: #fff;
  /* Reine Zahlenrechnung statt color-mix: opacity versteht jeder Browser,
     der auch den Rest der Seite darstellt. */
  opacity: clamp(0, calc((var(--drive) - .86) * 8), 1);
}

/* Start- und Zieladresse. Sie sitzen aussen neben den beiden Halte-Punkten
   auf der Linienachse; die Spur ist dafuer beidseitig eingerueckt (siehe
   .route__track). Der dunkle Grund schneidet die Linie frei, damit sie nicht
   durch das Haus laeuft - dasselbe Mittel wie beim Fahrzeug. */
.page-start-2 .route__house {
  position: absolute;
  top: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #0a1836;
  color: var(--route-live);
}
.page-start-2 .route__house .icon { width: 21px; height: 21px; }
.page-start-2 .route__house--start { left: calc(var(--route-house) * -1); }
.page-start-2 .route__house--end   { right: calc(var(--route-house) * -1); translate: 50% -50%; }
/* Das Ziel liegt noch vor uns: gedaempft, bis der Wagen ankommt. Gleiche
   Zahlenrechnung wie am Zielpunkt, damit beide zusammen hell werden. */
.page-start-2 .route__house--end .icon {
  opacity: clamp(.4, calc(.4 + (var(--drive) - .8) * 3), 1);
}

/* Der Lastwagen sitzt auf der Linie und faehrt sie ab. #i-truck zeigt nach
   rechts - die Fahrtrichtung stimmt also mit der Leserichtung ueberein.
   Der breite Ring in der Flaechenfarbe schneidet die Linie sauber frei,
   damit sie nicht durch das Fahrzeug laeuft. */
.page-start-2 .route__van {
  position: absolute;
  top: 50%;
  /* 42 px vor dem Ziel: sonst deckte die Scheibe des Fahrzeugs den
     Zielpunkt genau dann zu, wenn er sich fuellt. So haelt der Wagen davor
     und man sieht beides - Ankunft und gesetzten Punkt. */
  left: calc(var(--drive) * (100% - 42px));
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: #0a1836;
  border: 1px solid rgba(159, 186, 240, .55);
  box-shadow: 0 0 0 6px #0a1836, 0 10px 26px -10px rgba(0, 0, 0, .9);
  color: #fff;
}
.page-start-2 .route__van .icon { width: 24px; height: 24px; }

/* --- Die beiden Halte --------------------------------------------------- */
.page-start-2 .route__stops {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 32px 60px;
  margin-top: 26px;
}
.page-start-2 .route__stop--end { text-align: right; justify-self: end; }

.page-start-2 .route__label {
  font-size: calc(14.5px * var(--fs-scale));
  font-weight: 700;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  line-height: 1.3;
  color: #fff;
}
.page-start-2 .route__hint {
  margin-top: 9px;
  max-width: 34ch;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: rgba(255, 255, 255, .68);
}
.page-start-2 .route__stop--end .route__hint { margin-left: auto; }

/* --- Fuss: Handlungsaufruf am Start, Schlusszeile am Ziel ---------------
   Bewusst nicht mittig: der Button steht dort, wo die Strecke beginnt -
   hier setzt sich die Anfrage in Bewegung. */
.page-start-2 .closing--route .closing__foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 24px 60px;
  align-items: center;
  margin-top: 52px;
  padding-top: 40px;
  border-top: 1px solid rgba(255, 255, 255, .14);
}
.page-start-2 .closing--route .closing__actions { margin-top: 0; justify-content: flex-start; }
.page-start-2 .closing--route .closing__note {
  margin-top: 0;
  max-width: 42ch;
  justify-self: end;
  text-align: right;
  color: rgba(255, 255, 255, .62);
}
.page-start-2 .closing--route :focus-visible { outline-color: #fff; }

/* --- Schmale Fenster: die Strecke stellt sich auf -----------------------
   Nebeneinander waere die Linie hier zu kurz, um etwas zu zeigen. Sie
   kippt darum in die Senkrechte und laeuft am linken Rand von Halt zu
   Halt; der Lastwagen faehrt sie von oben nach unten ab. Gerechnet wird
   dasselbe --p, nur auf die andere Achse gelegt.
   ======================================================================= */
@media (max-width: 899px) {
  .page-start-2 .closing--route { padding-block: 68px 64px; }
  .page-start-2 .closing--route .closing__head { grid-template-columns: 1fr; gap: 16px; }
  .page-start-2 .closing--route .closing__title { max-width: none; }

  .page-start-2 .route {
    position: relative;
    margin-top: 44px;
    padding-left: 46px;
  }
  .page-start-2 .route__track {
    position: absolute;
    /* Die Einrueckung der breiten Fassung kippt mit: dort stand sie
       seitlich, hier oben und unten - die Haeuser sitzen jetzt an den
       Enden der senkrechten Linie. */
    margin-inline: 0;
    top: calc(var(--route-house) + 14px);
    bottom: calc(var(--route-house) + 14px);
    left: 15px;
    width: 2px;
    height: auto;
    background: repeating-linear-gradient(180deg, var(--route-line) 0 7px, transparent 7px 14px);
  }
  .page-start-2 .route__done {
    top: 0;
    left: 0;
    right: 0;
    bottom: auto;
    width: auto;
    height: calc(var(--drive) * 100%);
    background: linear-gradient(180deg, rgba(159, 186, 240, .6), #fff);
  }
  .page-start-2 .route__dot { left: 50%; margin-left: -5.5px; margin-top: 0; }
  .page-start-2 .route__dot--start { top: -5.5px; }
  .page-start-2 .route__dot--end   { top: auto; bottom: -5.5px; }

  .page-start-2 .route__house { left: 50%; right: auto; }
  .page-start-2 .route__house--start { top: calc(var(--route-house) * -1); translate: -50% -50%; }
  .page-start-2 .route__house--end {
    top: auto;
    bottom: calc(var(--route-house) * -1);
    translate: -50% 50%;
  }

  .page-start-2 .route__van {
    top: calc(var(--drive) * (100% - 42px));
    left: 50%;
    width: 38px;
    height: 38px;
  }
  .page-start-2 .route__van .icon { width: 20px; height: 20px; }

  .page-start-2 .route__stops { grid-template-columns: 1fr; gap: 28px; margin-top: 0; }
  .page-start-2 .route__stop--end { text-align: left; justify-self: stretch; }
  .page-start-2 .route__stop--end .route__hint { margin-left: 0; }
  .page-start-2 .route__hint { max-width: none; }

  .page-start-2 .closing--route .closing__foot {
    grid-template-columns: 1fr;
    margin-top: 40px;
    padding-top: 32px;
  }
  .page-start-2 .closing--route .closing__note {
    justify-self: start;
    text-align: left;
    max-width: none;
  }
}

@media (max-width: 639px) {
  .page-start-2 .closing--route { padding-block: 54px 52px; }
  .page-start-2 .closing--route .closing__actions .btn { width: 100%; }
}

/* =========================================================================
   14. Ruecknahme auf schmalen Geraeten
   -------------------------------------------------------------------------
   Unter 900 px laeuft das Foto im Auftakt nicht mit, also entfallen auch die
   Kanten, die nur ueber ihm wirken. Die geneigte Kante wird flacher, damit
   sie auf schmalen Fenstern nicht zur Rutschbahn wird.
   Der Abschluss regelt seine Abstaende selbst - siehe Block 13.
   ========================================================================= */
@media (max-width: 899px) {
  .page-start-2 .services {
    margin-top: -22px;
    padding-block: 74px 62px;
    clip-path: polygon(0 22px, 100% 0, 100% 100%, 0 100%);
  }
  .page-start-2 .services::before { height: 22px; }
  .page-start-2 .overview,
  .page-start-2 .steps { padding-top: 62px; }
}

@media (max-width: 639px) {
  .page-start-2 { --bracket: 12px; }
  .page-start-2 .support-card::before,
  .page-start-2 .support-card::after { width: 16px; height: 16px; }
  .page-start-2 .statement__inner::before,
  .page-start-2 .statement__inner::after { display: none; }
  .page-start-2 .services { padding-block: 58px 52px; }
  .page-start-2 .overview,
  .page-start-2 .steps { padding-top: 52px; }
}

/* =========================================================================
   15. Weniger Bewegung
   -------------------------------------------------------------------------
   05-motion.css nimmt bereits global alle Uebergaenge und Animationen
   zurueck. Hier bleiben die Stellen, die ohne Uebergang trotzdem in einem
   Zwischenzustand stehenblieben: verdeckte Bilder, ausgefahrene Kanten,
   der Beschnitt des dunklen Bandes.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .page-start-2 .support-card__media,
  html:not(.js) .page-start-2 .support-card__media {
    clip-path: none;
    transform: none;
    translate: none;
  }
  .page-start-2 .support-card::before,
  .page-start-2 .support-card::after,
  .page-start-2 .sfx-frame::before,
  .page-start-2 .sfx-frame::after {
    opacity: .55;
    transform: none;
  }
  .page-start-2 main .eyebrow::after,
  html.js .page-start-2 .steps .flow__rule { transform: none; }
  .page-start-2 .individual__tags .individual__tag { opacity: 1; transform: none; }
  .page-start-2 .hero2__media img { translate: none; transform: none; scale: 1; }
  .page-start-2 .hero2__inner { transform: none; opacity: 1; }
  html.js .page-start-2 .statement::after { clip-path: none; }
  .page-start-2::before { display: none; }

  /* Die Strecke im Abschluss steht fertig da: Linie durchgezogen, Ziel
     gefuellt, Lastwagen angekommen. scroll-fx.js setzt --p ohnehin auf 1,
     das hier ist die Absicherung fuer den Fall, dass gar kein Wert
     ankommt. */
  .page-start-2 .route { --p: 1; }
}

/* =========================================================================
   16. Ueber uns: die Aussage steht auf dem Foto
   -------------------------------------------------------------------------
   Es standen hier zwei Fassungen zur Auswahl; der Kunde hat sich am
   02.09.2026 fuer diese entschieden, die hellere Fassung A (.about) ist
   samt ihrem Block 9 entfallen.

   Der Block steht hinter 14 und 15 statt weiter oben: er ist als Anhang
   entstanden, der sich in einem Stueck herausloesen laesst. Weil die
   Ruecknahmen dort vor ihm liegen, bringt er seine eigenen Regeln fuer
   schmale Fenster und fuer weniger Bewegung am Ende mit.

   Vorbild ist ein Abschnitt der Website "Terminal": ein randloses Foto
   ueber die volle Breite, kraeftig abgedunkelt, darauf mittig eine grosse
   Aussage, darunter klein die Zuordnung. Der Abschnitt begruendet nichts,
   er behauptet - deshalb traegt er einen Satz und keinen Textblock.

   Warum das neben dem dunklen Vertrauensband weiter oben bestehen kann:
   das Band ist eine reine Farbflaeche mit Kacheln, hier traegt ein Foto
   und die Flaeche ist bis auf einen Satz leer. Und die weissen Boegen an
   Ober- und Unterkante sind ein Kantentyp, den die Seite noch nicht hat -
   nach geneigt, gezahnt und geklammert nun gerundet.
   ========================================================================= */
.page-start-2 .about-alt {
  /* Tiefe der beiden Boegen an Ober- und Unterkante. Sie waechst mit dem
     Fenster, bleibt aber in Grenzen: unter etwa 30 px liest sich der Bogen
     als schiefe Kante statt als Absicht, ueber etwa 66 px nimmt er der
     Bildflaeche die Ruhe. */
  --arc: clamp(30px, 4.4vw, 66px);
  /* Die Abdunklung als eine Eigenschaft, damit der hohe Kontrast weiter
     unten nur einen Wert austauschen muss. Zur Deckkraft siehe die
     Rechnung bei .about-alt__media::after. */
  --veil: rgba(11, 23, 48, .68);

  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  /* Nur die Zeile mittig setzen, die Spalte laufen lassen: der Inhalt
     traegt .container und richtet sich selbst am Seitenraster aus. Ein
     place-items: center wuerde ihm stattdessen seine Breite nehmen. */
  align-content: center;
  /* Erst die Bogentiefe, dann der eigentliche Abstand - so kann der Text
     auf keiner Fensterbreite unter einen Bogen geraten. */
  padding-block: calc(var(--arc) + clamp(46px, 6vw, 92px));
  /* Bildschirmfuellend, aber gedeckelt. Ohne Deckel entstuende auf sehr
     hohen Fenstern eine leere dunkle Flaeche, durch die man nur scrollt.
     Die erste Zeile ist der Rueckfall fuer Browser ohne svh; svh statt vh,
     damit die ein- und ausfahrende Adressleiste am Handy die Hoehe nicht
     springen laesst. */
  min-height: min(88vh, 940px);
  min-height: min(88svh, 940px);
  /* Weiss, nicht Foto: die Boegen sind Ausschnitte aus dieser Flaeche. So
     stimmt die Kante auch dann noch, wenn ueber oder unter dem Abschnitt
     einmal etwas anderes steht als heute. Oben und unten grenzt ohnehin
     schon je eine Haarlinie der Nachbarn an (Block 9 und 10), eine eigene
     Kante braucht der Abschnitt deshalb nicht. */
  background: var(--surface);
  color: #fff;
  text-align: center;
}

/* --- Das Foto -----------------------------------------------------------
   Eigene Ebene hinter allem. 18 % zuviel Hoehe, gleichmaessig oben und
   unten - das ist der Spielraum, in dem das Bild langsamer laufen darf als
   die Seite (data-parallax="30" liefert --shift, hoechstens +-15 px).

   Bewusst ueber top/height und nicht ueber einen negativen Rand wie in
   Block 9: prozentuale Raender rechnen gegen die BREITE des Elternteils.
   Bei einem randlosen Abschnitt haengt der Versatz damit an der
   Fensterbreite statt an der Bildhoehe - auf einem breiten Fenster waere
   das Bild weit ueber den Spielraum hinausgeschoben. */
.page-start-2 .about-alt__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}
.page-start-2 .about-alt__media img {
  position: absolute;
  top: -9%;
  left: 0;
  width: 100%;
  height: 118%;
  object-fit: cover;
  /* Rechts der Mitte und etwas oberhalb: dort steht das Fahrzeug, und der
     ruhige Himmel bleibt oben - genau dort, wo die Aussage anfaengt. */
  object-position: 58% 42%;
  translate: 0 var(--shift, 0px);
}

/* --- Die Abdunklung -----------------------------------------------------
   Sie haengt an der Bildebene, nicht am Bild: so bleibt sie stehen,
   waehrend das Foto darunter laeuft.

   Die Deckkraft ist gerechnet, nicht geschaetzt. Massgabe ist der
   unguenstigste Fall - eine Bildstelle in Reinweiss. rgb(11 23 48) mit
   68 % druecken Weiss auf eine relative Helligkeit von 0.119. Darauf
   stehen: weisse Schrift bei 6.2:1, die zurueckgenommenen Zeilen (82 %
   Weiss) bei 4.8:1, die Vorzeile in #dce7fd bei 5.0:1. Alle drei ueber den
   geforderten 4.5:1, und zwar unabhaengig davon, welches Foto spaeter im
   <img> steht. Wer die 68 % senkt, faellt darunter.

   Der Verlauf liegt obendrauf und kann die Flaeche nur dunkler machen, den
   Wert also nicht unterschreiten. Seine Aufgabe ist eine andere: er nimmt
   dem Bild an Ober- und Unterkante die Zeichnung, damit die weissen Boegen
   nicht auf ein unruhiges Motiv treffen. */
.page-start-2 .about-alt__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      rgba(6, 13, 30, .38) 0%,
      rgba(6, 13, 30, 0) 30%,
      rgba(6, 13, 30, 0) 70%,
      rgba(6, 13, 30, .38) 100%),
    var(--veil);
}

/* --- Die weissen Boegen -------------------------------------------------
   Das Formmerkmal dieser Fassung: die weisse Flaeche greift in der Mitte
   in das Bild hinein und laeuft zu den Seiten hin auf null aus.

   Gebaut aus zwei weissen Rechtecken, deren zugewandte Ecken beide auf
   50 % gerundet sind. Bei genau 50 % je Ecke bleibt zwischen ihnen kein
   gerades Stueck uebrig - die Kante ist dann eine durchgehende halbe
   Ellipse ueber die volle Breite. Das Rechteck ist doppelt so hoch wie der
   Bogen tief werden soll und um die Bogentiefe nach aussen geschoben;
   damit liegt der Scheitel der Ellipse genau --arc innen und ihre Enden
   sitzen auf der Aussenkante. Der Rest des Rechtecks steht ausserhalb und
   faellt dem overflow der Sektion zum Opfer.

   Warum nicht clip-path: eine Polygon-Naeherung braucht ein Dutzend Punkte
   und wird an den flachen Stellen sichtbar kantig, path() rechnet gar
   nicht in Prozent. Beides ergaebe zwischen 320 und 1920 px nicht dieselbe
   Form. border-radius skaliert von selbst mit der Breite.

   Sie liegen ueber dem Foto und unter dem Text (1 gegen 2). */
.page-start-2 .about-alt::before,
.page-start-2 .about-alt::after {
  content: "";
  position: absolute;
  left: 0;
  z-index: 1;
  width: 100%;
  height: calc(var(--arc) * 2);
  background: var(--surface);
  pointer-events: none;
}
.page-start-2 .about-alt::before {
  top: calc(var(--arc) * -1);
  border-radius: 0 0 50% 50%;
}
.page-start-2 .about-alt::after {
  bottom: calc(var(--arc) * -1);
  border-radius: 50% 50% 0 0;
}

/* --- Inhalt -------------------------------------------------------------
   Eine Spalte, mittig. Der Abschnitt hat genau einen Schwerpunkt, und das
   ist die Aussage; alles andere ordnet sich ihr unter. */
.page-start-2 .about-alt__inner {
  position: relative;
  z-index: 2;
}

/* Der Strich unter der Vorzeile haengt sonst am linken Rand des
   Inhaltsrahmens (Block 2) - bei mittigem Satz stuende er allein weit
   links neben seinem Wort. Hier waechst er aus der Mitte heraus.

   Das "main" im Selektor ist kein Versehen: die Regel in Block 2 traegt es
   auch, und ohne es waere diese hier schwaecher und bliebe wirkungslos. */
.page-start-2 .about-alt__eyebrow {
  color: #dce7fd;
}
.page-start-2 main .about-alt__eyebrow::after {
  left: 50%;
  margin-left: -24px;
  transform-origin: 50% 50%;
}

/* Bewusst nicht .h-section: das ist Versalschrift. Zwei Saetze in
   Versalien liest man als Geschrei, nicht als Zusage - und genau eine
   Zusage ist dieser Satz. Also gemischt gesetzt, dafuer gross und
   schwer.

   Die Anfuehrungszeichen stehen als Zeichen im Text und nicht als
   CSS-content: sie gehoeren zur Aussage und sollen auch dann dastehen,
   wenn die Gestaltung einmal nicht laedt.

   28ch halten den Satz auf vier bis fuenf Zeilen. Weil ch an der
   Schriftgroesse haengt und die an der Fensterbreite, bleibt die
   Zeilenzahl ueber alle Breiten ungefaehr gleich - die Aussage wird also
   kleiner, nie abgeschnitten. */
.page-start-2 .about-alt__title {
  margin: 0 auto;
  max-width: 28ch;
  font-size: calc(clamp(24px, 4.5vw, 54px) * var(--fs-scale));
  line-height: 1.16;
  letter-spacing: -.018em;
  text-wrap: balance;
  color: #fff;
}

/* Der zweite Absatz und die Zuordnung: deutlich kleiner und mit Abstand,
   damit die Aussage darueber allein steht. In der Vorlage stehen an
   dieser Stelle Name und Firma einer Person - hier spricht das
   Unternehmen selbst, also zeichnet es auch selbst. */
.page-start-2 .about-alt__note {
  margin: clamp(24px, 3.2vw, 38px) auto 0;
  max-width: 46ch;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: rgba(255, 255, 255, .88);
}
.page-start-2 .about-alt__by {
  margin-top: 16px;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: rgba(255, 255, 255, .82);
}

.page-start-2 .about-alt :focus-visible { outline-color: #fff; }

/* Die beiden senkrechten Haarlinien der Seite (Block 2) laufen auch ueber
   diesen Abschnitt. Das bleibt so: sie liegen bei Inhaltsrand plus 40 px
   und damit weit ausserhalb der 28ch der Aussage, kreuzen also keine
   Schrift. Ueber dem dunklen Vertrauensband tun sie dasselbe - der Grauton
   ist genau dafuer gewaehlt. Sie durch den dunklen Abschnitt zu ziehen
   haelt die Spur der Seite zusammen, statt sie zu unterbrechen. */

/* Hoher Kontrast: dichtere Abdunklung. Weisse Schrift steht dann bei
   8.9:1, die zurueckgenommenen Zeilen bei 6.6:1 - dasselbe Mittel, das
   a11y-widget.css schon fuer die weissen Verlaeufe ueber den Fotos im
   Auftakt und in Fassung A anwendet. */
:root[data-a11y-contrast="high"] .page-start-2 .about-alt {
  --veil: rgba(11, 23, 48, .78);
}

@media (max-width: 639px) {
  .page-start-2 .about-alt {
    /* Auf dem Handy ist ein voller Bildschirm Dunkelheit schnell zu viel,
       und die Aussage steht ohnehin frueher fertig da. Der Abschnitt darf
       hier von seinem Inhalt hoeher werden, aber nicht von sich aus. */
    min-height: min(74vh, 560px);
    min-height: min(74svh, 560px);
    padding-block: calc(var(--arc) + 40px);
  }
  .page-start-2 .about-alt__note { max-width: 38ch; }
}

@media (prefers-reduced-motion: reduce) {
  /* Eigene Ruecknahme: sonst bliebe das Foto auf dem zuletzt gesetzten
     Versatz stehen. */
  .page-start-2 .about-alt__media img { translate: none; }
}

/* ===== styles/05-motion.css ===== */
/* ===== Bewegung =========================================================
   Sparsam und begruendet: Einblenden beim Scrollen ordnet die Lesereihenfolge,
   Hover-Zustaende geben Rueckmeldung. Alles respektiert prefers-reduced-motion.
   ======================================================================= */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--reveal-dur, var(--dur-slow)) var(--ease) var(--reveal-delay, 0ms),
    transform var(--reveal-dur, var(--dur-slow)) var(--ease) var(--reveal-delay, 0ms);
}

/* Variante: von oben hereinfliegen statt von unten aufsteigen. Genutzt von
   den drei Unterstuetzungs-Karten, die nacheinander von links nach rechts an
   ihren Platz kommen. */
[data-reveal="from-top"] { transform: translateY(var(--reveal-shift, -52px)); }

/* Ohne JavaScript bleibt alles sichtbar */
html:not(.js) [data-reveal] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
  }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ===== Ruhebewegungen ===================================================
   Sehr langsame, kleine Schleifen. Sie laufen nur ueber transform und
   opacity, damit der Browser sie auf dem Compositor abarbeitet und kein
   Layout anfaellt. Der Block oben schaltet sie bei prefers-reduced-motion
   mit ab.

   Dauerhaft laeuft nur eine: das Schweben der drei Icon-Scheiben auf den
   Leistungskarten. Die uebrigen Keyframes hier laufen einmalig - beim
   Einblenden oder beim Hover.
   ======================================================================= */

/* Icon-Scheibe der Leistungskarten: 4px auf und ab.
   Bewusst ueber die eigenstaendige translate-Eigenschaft: so kann der
   Hover-Zustand gleichzeitig ein transform setzen, ohne zu kollidieren. */
@keyframes badge-float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -4px; }
}

/* Kleine Fahrbewegung fuer Fahrzeug-Icons (nur beim Hover ausgeloest). */
@keyframes van-roll {
  0%   { transform: translateX(0); }
  45%  { transform: translateX(4px); }
  100% { transform: translateX(0); }
}

/* ===== styles/06-utilities.css ===== */
/* ===== Hilfsklassen ===================================================== */
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.mt-32 { margin-top: 32px; }

.divider { height: 1px; background: var(--line); border: 0; }

/* Sektionsabstand fuer Unterseiten (grosszuegiger als die Startseite) */
.section--page { padding-block: 56px 60px; }
@media (max-width: 639px) { .section--page { padding-block: 40px 44px; } }

@media print {
  .site-header, .site-footer, .quote-band, .nav-toggle { display: none !important; }
  body { color: #000; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 11px; }
}

/* Umbruch nur ab Tablet: haelt Referenz-Zeilenfall, ohne mobil zu stoeren */
.br-md { display: none; }
@media (min-width: 720px) { .br-md { display: inline; } }
