/* =============================================================================
   site.css  ·  TAXI LAKIS  (Ebene 3 von 3: Foundation → Theme → Site)
   -----------------------------------------------------------------------------
   Projektspezifische Kompositionen. Lädt als letzte Ebene.

   ARBEITSWEISE (KIT.md, „Neues Design bauen vs. bestehendes migrieren"):
   Hier wird ein FREIGEGEBENER Entwurf übernommen (260811_taxilakis_idea.html,
   vom Kunden abgenommen). Es gilt daher „erst Fidelity, dann optional
   normalisieren": die konkreten Werte des Originals sind die Wahrheit und
   stehen bewusst als px in dieser Datei. styles.css bleibt unangetastet
   tokenbasiert; die Marken-Tokens liegen in theme.css.

   GLIEDERUNG
     1  Schriften (selbst gehostet)
     2  Grundlagen & Farbkontexte
     3  Buttons je Untergrund (Spec §1.3)
     4  Header (Spec §2, §12)
     5  Hero (Spec §4)
     6  Section-Rhythmus
     7  Fahrtkarten: Top 3 + alle Leistungen (Spec §5, §6)
     8  Über uns · Fuhrpark (Spec §7)
     9  Kontakt-CTA (Spec §8)
    10  FAQ: Teaser + Vollseite (Spec §9)
    11  Footer (Spec §10)
    12  Sticky Action Bar (Spec §3)
    13  Buchungs-Modal (booking-modal-spec)
    14  Rechtstexte / Inhaltsseiten
    15  Bewegung — was sich bewegen darf und was nicht
   ============================================================================= */


/* =============================================================================
   1  SCHRIFTEN — selbst gehostet, latin-Subset
   Kitty-Prinzip „Datenschutz by default": keine extern geladenen Schriften.
   Die TTFs aus dem Design-Kit wurden auf latin subsettet und als woff2
   gepackt (7 Dateien, zusammen ~105 KB).
   ========================================================================== */
@font-face {
  font-family: "Jost"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/jost-latin-500.woff2") format("woff2");
}
@font-face {
  font-family: "Jost"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/jost-latin-600.woff2") format("woff2");
}
@font-face {
  font-family: "Jost"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("fonts/jost-latin-700.woff2") format("woff2");
}
/* 800 nachgezogen (14.09.2026). Ohne diese Datei wäre font-weight: 800
   wirkungslos: der Browser nimmt dann einfach den nächstgelegenen Schnitt,
   also 700, und man sieht keinen Unterschied. Geprüft, bevor die Datei da
   war — 700, 800 und 900 rendern Zeichen für Zeichen gleich.
   Quelle: Jost 3.710, dieselbe Version wie die anderen Schnitte. */
@font-face {
  font-family: "Jost"; font-style: normal; font-weight: 800; font-display: swap;
  src: url("fonts/jost-latin-800.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/inter-latin-400.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/inter-latin-500.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/inter-latin-600.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("fonts/inter-latin-700.woff2") format("woff2");
}
/* Inter 800 aus der variablen Schrift instanziert, opsz 18 — genau wie die
   anderen Schnitte. Geprüft: bei 500, 600 und 700 liefert dieselbe Rechnung
   Zeichenbreite für Zeichenbreite die vorhandenen Dateien, 800 ist also
   wirklich die Fortsetzung derselben Familie und kein Fremdkörper. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 800; font-display: swap;
  src: url("fonts/inter-latin-800.woff2") format("woff2");
}
/* Hinweis zu den Pfaden: url() in einer CSS-Datei löst RELATIV ZUR CSS-DATEI
   auf, nicht relativ zum Dokument. site.css liegt im Root, also gilt
   "fonts/…" gleichermaßen für /de/ und /en/ — kein zweiter Pfadsatz nötig,
   und es läuft so auch per file://.

   LEISTUNGS-IKONEN liegen als eigenständige SVG in icons/ und werden als
   ganz normales <img> eingebunden. Bewusst KEINE CSS-Maske und kein
   currentColor: mask-image gilt im Browser als Cross-Origin-Ressource und
   wird unter file:// blockiert — Kitty verlangt aber ausdrücklich, dass die
   Site auch per Doppelklick läuft. Die Markenfarbe steckt deshalb in der
   Datei; die Icons erscheinen im Entwurf ohnehin ausschließlich gelb auf
   Navy. */
.ico-svc { display: block; width: 30px; height: 30px; }


/* =============================================================================
   2  GRUNDLAGEN & FARBKONTEXTE
   ========================================================================== */
body {
  background: var(--tl-white);
  overflow-x: hidden;
}

/* Die Sections tragen ihre Farbe randlos bis an die Viewport-Kante; zwischen
   ihnen darf keine Fuge stehen. Kitty's .frame-Gap wird deshalb bewusst nicht
   verwendet (siehe PROJECT.md). */
main > .section { margin: 0; }

h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 800; }

/* --- Farbkontexte ---------------------------------------------------------
   Eine Section (oder Karte) deklariert ihren Untergrund. Alles darin — Text,
   Buttons, Icons, Fokusringe — richtet sich danach. Das ist der Mechanismus
   hinter Spec §1.3 („Primary/Secondary sind nicht fix, sie passen sich dem
   Untergrund an"). */
.on-navy {
  background: var(--tl-navy);
  color: var(--tl-white);
}
.on-soft   { background: var(--tl-soft-2); color: var(--tl-navy); }
.on-yellow { background: var(--tl-yellow); color: var(--tl-navy); }

.on-navy :where(h1, h2, h3, h4) { color: var(--tl-white); }
.on-navy :where(p, li)          { color: rgba(255, 255, 255, 0.78); }
.on-navy a:not(.button)         { color: var(--tl-white); }

/* Fokus bleibt in jedem Kontext sichtbar: gelb auf dunkel, navy auf gelb. */
:focus-visible { outline: 3px solid var(--tl-yellow); outline-offset: 3px; border-radius: 4px; }
.on-yellow :focus-visible { outline-color: var(--tl-navy); }

/* Eyebrow — Kitty's .overline in CI-Ausprägung. */
.eyebrow {
  display: block;
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--tl-muted);
  margin: 0 0 12px;
}
.on-navy .eyebrow   { color: var(--tl-yellow); }
.on-yellow .eyebrow { color: rgba(7, 3, 49, 0.62); }

.lede {
  font-size: var(--text-lead);
  color: var(--tl-muted);
  max-width: 56ch;
  line-height: 1.6;
}
.on-navy .lede   { color: rgba(255, 255, 255, 0.76); }
.on-yellow .lede { color: rgba(7, 3, 49, 0.78); }

/* Inline-Icon-Grundform: erbt Farbe und Größe vom Text. */
.ico {
  width: 19px; height: 19px; flex: none;
  fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}


/* --- Grundgewicht des Fließtextes ----------------------------------------
   500 statt 400. Die Marke stellt viel Text auf farbige Flächen — Navy auf
   Gelb, Weiß auf Navy, Navy auf Softblau. Auf solchen Gründen wirkt ein
   regulärer Schnitt dünn und die Kanten der Buchstaben fransen optisch aus;
   eine halbe Stufe mehr Fleisch macht denselben Text ruhiger lesbar, ohne
   dass er fett wirkt.

   body trägt das Gewicht, nicht eine lange Liste von Selektoren: alles, was
   ein eigenes Gewicht setzt (Überschriften 600/700, Buttons 600, Eyebrows),
   bleibt unberührt; alles andere erbt.

   strong und b haben in Kitty keine eigene Regel und stehen damit auf dem
   Browser-Standard `bolder`. Von 500 aus rechnet der Browser 700 — der
   Unterschied zwischen normalem und hervorgehobenem Text bleibt also genau
   so deutlich wie vorher. Wo site.css eigene 600er für strong gesetzt hat,
   stehen jetzt 700, damit sie sich weiter absetzen.

   Inter 500 ist ohnehin schon geladen; es kommt keine einzige Datei dazu. */
body { font-weight: 600; }

/* =============================================================================
   3  BUTTONS JE UNTERGRUND  (Spec §1.3)
   Kitty's .button steuert sich über --btn-bg / --btn-fg / --btn-border. Wir
   überschreiben nur diese drei Variablen pro Kontext — die Komponente selbst
   bleibt unangetastet (Prinzip „Klassenverträge respektieren").
   ========================================================================== */
/* Eine gemeinsame Höhenformel für ALLES, was als Button nebeneinander steht —
   .button, .tel-link und die Felder im Buchungsformular. Zwei Knöpfe
   nebeneinander dürfen sich bei keiner Textgröße um einen Pixel unterscheiden,
   deshalb stehen Innenabstand und Zeilenhöhe hier EINMAL und werden von allen
   geteilt. (Vorher hatte .tel-link 14px und .button 15px Innenabstand: bei A
   deckte die min-height den Unterschied zu, bei A+ nicht mehr.) */
:root {
  --btn-pad-block: 15px;
  --btn-leading:   1;      /* wie in der Foundation — hält die 52 px aus dem
                              freigegebenen Entwurf; 1.35 hätte jeden Button
                              auf 55,6 px aufgeblasen und den Kopf mitgezogen */
  --btn-h:         52px;
}
.button {
  min-height: var(--btn-h);
  padding: var(--btn-pad-block) 26px;
  font-size: 1rem;
  line-height: var(--btn-leading);
  font-weight: 600;
  border-radius: var(--radius-control);
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform 120ms var(--ease);
}
.button:active { transform: translateY(1px); }
.button--sm { min-height: 44px; padding: 11px 18px; font-size: 0.94rem; }
.button--wide { width: 100%; }

/* Auf Navy: Primary = Gelb, Secondary = Weiß.
   Der dunkle Footer ist derselbe Untergrund und wird deshalb überall
   mitgeführt, wo hier .on-navy steht. */
.on-navy .button,
.site-footer--dark .button {
  --btn-bg: var(--tl-yellow); --btn-fg: var(--tl-navy); --btn-border: var(--tl-yellow);
}
.on-navy .button:hover,
.site-footer--dark .button:hover {
  --btn-bg: var(--tl-yellow-2); --btn-border: var(--tl-yellow-2);
  box-shadow: var(--shadow-card);
}
.on-navy .button--secondary,
.site-footer--dark .button--secondary {
  --btn-bg: var(--tl-white); --btn-fg: var(--tl-navy); --btn-border: var(--tl-white);
}
/* ACHTUNG, hier lauerte ein Fehler: --btn-fg MUSS hier mitstehen.
   Weiter unten setzt `.button--secondary:hover` die Schrift auf Weiß (das ist
   der Zustand für hellen Untergrund). Diese Regel hier ist zwar spezifischer,
   aber sie vererbt nichts — was sie nicht selbst setzt, holt sich der Browser
   aus der gleichrangigen, SPÄTER stehenden Regel. Ohne die Zeile wurde der
   weiße Button beim Überfahren weiß auf hellblau: unlesbar. */
.on-navy .button--secondary:hover,
.site-footer--dark .button--secondary:hover {
  --btn-bg: var(--tl-soft);
  --btn-fg: var(--tl-navy);
  --btn-border: var(--tl-soft);
}

/* Auf Gelb: Primary = Navy/Weiß, Secondary = Weiß mit Navy-Rand. */
.on-yellow .button {
  --btn-bg: var(--tl-navy); --btn-fg: var(--tl-white); --btn-border: var(--tl-navy);
}
.on-yellow .button:hover { --btn-bg: var(--tl-navy-3); --btn-border: var(--tl-navy-3); }
.on-yellow .button--secondary {
  --btn-bg: var(--tl-white); --btn-fg: var(--tl-navy); --btn-border: var(--tl-navy);
}
/* Gleiche Falle wie oben. Hier müssen ALLE DREI Variablen stehen: was eine
   Hover-Regel nicht selbst setzt, holt sich der Browser aus der letzten
   gleichrangigen Regel — und die kann nach einem Kit-Update eine andere
   sein als heute. Lieber drei Zeilen zu viel als ein Rand, der plötzlich
   nicht mehr zur Fläche passt. */
.on-yellow .button--secondary:hover {
  --btn-bg: var(--tl-soft); --btn-fg: var(--tl-navy); --btn-border: var(--tl-soft);
}

/* Auf Weiß/Softblau: Primary = Gelb, Secondary = Navy-Outline. */
.button          { --btn-bg: var(--tl-yellow); --btn-fg: var(--tl-navy); --btn-border: var(--tl-yellow); }
.button:hover    { --btn-bg: var(--tl-yellow-2); --btn-border: var(--tl-yellow-2); box-shadow: var(--shadow-card); }
.button--secondary       { --btn-bg: transparent; --btn-fg: var(--tl-navy); --btn-border: var(--tl-navy); }
.button--secondary:hover { --btn-bg: var(--tl-navy); --btn-fg: var(--tl-white); --btn-border: var(--tl-navy); }

/* Ghost — Grundform: zurückhaltend, aber auf HELLEM Grund lesbar.
   WICHTIG: .button--ghost gehört der Foundation und wird auch außerhalb dieses
   Projekts benutzt — unter anderem vom Cookie-Dialog für „Einstellungen" und
   „Auswahl speichern". Eine globale Umfärbung auf Weiß macht diese Buttons auf
   dem weißen Dialog unsichtbar. Die weiße Variante gilt deshalb ausschließlich
   dort, wo der Untergrund dunkel ist. */
.button--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--tl-navy);
  --btn-border: rgba(7, 3, 49, 0.35);
}
.button--ghost:hover {
  --btn-bg: var(--tl-soft-2); --btn-fg: var(--tl-navy); --btn-border: var(--tl-navy);
}

/* Weiße Ghost-Variante nur auf dunklem Grund (Fahrtkarten, Navy-Sections). */
.on-navy .button--ghost,
.ride .button--ghost,
.site-footer--dark .button--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--tl-white);
  --btn-border: rgba(255, 255, 255, 0.45);
}
/* Beim Auswählen springt sie auf den Primary-Stil des Abschnitts. */
.on-navy .button--ghost:hover,
.ride .button--ghost:hover,
.ride:hover .button--ghost,
.ride:focus-within .button--ghost {
  --btn-bg: var(--tl-yellow); --btn-fg: var(--tl-navy); --btn-border: var(--tl-yellow);
}

.button-row { display: flex; flex-wrap: wrap; gap: 12px; }


/* =============================================================================
   4  HEADER  (Spec §2 · §12)
   ========================================================================== */
.site-header {
  background: var(--tl-navy);
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  color: var(--tl-white);
  z-index: 60;
}
.nav-sticky .site-header { box-shadow: 0 8px 24px -18px rgba(0, 0, 0, 0.7); }

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 18px;
  /* NICHT --header-height: main.js schreibt dort die gemessene Höhe hinein.
     Beides zu verbinden erzeugt eine Rückkopplung — der Header wächst dann
     bei jedem ResizeObserver-Durchlauf um sein eigenes Padding weiter und
     schiebt die ganze Seite langsam nach unten. */
  min-height: var(--tl-header-min);
  padding-block: 10px;
  justify-content: flex-start;
}

.brand { display: inline-flex; align-items: center; flex: none; text-decoration: none; }
.brand img { height: 34px; width: auto; display: block; }

/* Hauptnavigation */
.site-header .nav { margin-left: auto; }
.site-header .nav > ul { gap: 4px; }
.site-header .nav > ul a {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.97rem;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.82);
  padding: 10px 13px;
  border-radius: 8px;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.site-header .nav > ul a:hover { color: var(--tl-yellow); background: rgba(255, 255, 255, 0.07); }
.site-header .nav > ul a::after { display: none; }   /* Unterstrich-Signatur hier nicht */

/* Header-Werkzeuge: Textgröße + Sprache */
.header-tools { display: flex; align-items: center; gap: 10px; flex: none; }

/* --- Textgrößen-Umschalter (Spec §12) --- */
.textsize { display: flex; align-items: center; gap: 2px; }
.textsize__btn {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 8px;
  color: rgba(255, 255, 255, 0.85);
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.textsize__btn:first-child { border-radius: 8px 0 0 8px; }
.textsize__btn:last-child  { border-radius: 0 8px 8px 0; }
.textsize__btn + .textsize__btn { margin-left: -1px; }
.textsize__btn:hover { background: rgba(255, 255, 255, 0.1); color: var(--tl-yellow); }
.textsize__btn[aria-pressed="true"] {
  background: var(--tl-yellow); color: var(--tl-navy); border-color: var(--tl-yellow);
}
.textsize__btn:nth-child(1) { font-size: 0.72rem; }
.textsize__btn:nth-child(2) { font-size: 0.86rem; }
.textsize__btn:nth-child(3) { font-size: 1rem; }
/* Ohne JavaScript ist der Umschalter wirkungslos — dann gar nicht erst zeigen. */
html:not(.js) .textsize { display: none; }

/* --- Sprachumschalter: echte Links, kein JS (KIT.md, i18n) --- */
.site-header .lang-switch__list {
  display: flex; align-items: center; gap: 0;
  list-style: none; margin: 0; padding: 0;
}
.site-header .lang-switch__current,
.site-header .lang-switch__link {
  display: grid; place-items: center;
  /* min-block-size: 0 hebt das 40-px-Fingerziel der Foundation (styles.css
     Zeile 1966) NUR in der Kopfzeile auf. Ohne das gewann die Mindesthöhe
     gegen die 32 px hier, und der Sprachumschalter stand 8 px höher als der
     Textgrößen-Umschalter direkt daneben. In der reduzierten Kopfzeile
     stehen die beiden allein nebeneinander — dort fällt jeder Pixel auf.
     32 px bleiben über dem WCAG-Mindestziel von 24 px. */
  min-block-size: 0;
  min-width: 34px; height: 32px; padding-inline: 8px;
  font-family: var(--font-display); font-weight: 600; font-size: 0.8rem;
  border: 1px solid rgba(255, 255, 255, 0.22);
  text-decoration: none;
}
.site-header .lang-switch__list li:first-child :where(a, span) { border-radius: 8px 0 0 8px; }
.site-header .lang-switch__list li:last-child  :where(a, span) { border-radius: 0 8px 8px 0; margin-left: -1px; }
.site-header .lang-switch__current { background: var(--tl-yellow); color: var(--tl-navy); border-color: var(--tl-yellow); }
.site-header .lang-switch__link    { color: rgba(255, 255, 255, 0.85); }
.site-header .lang-switch__link:hover { background: rgba(255, 255, 255, 0.1); color: var(--tl-yellow); }

/* --- Telefon + Buchen: nebeneinander, Desktop wie Mobil (Spec §2.3) --- */
/* align-items: stretch statt center — damit ist die Höhe der beiden Knöpfe
   nicht mehr eine Rechnung, die bei jeder Textgröße aufgehen muss, sondern
   ein Fakt: der höhere gibt die Höhe vor, der andere zieht mit. */
.header__cta { display: flex; align-items: stretch; gap: 10px; flex: none; }
/* Die Rufnummer ist ein Ghost-Button: transparente Fläche, weißer Rand,
   weiße Schrift — dieselbe Höhe und derselbe Radius wie „Fahrt buchen"
   daneben, nur eine Stufe leiser. */
.tel-link {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  text-decoration: none; color: var(--tl-white);
  font-family: var(--font-display); font-weight: 600; font-size: 1rem;
  line-height: var(--btn-leading);
  min-height: var(--btn-h); padding: var(--btn-pad-block) 20px;
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.55);
  border-radius: var(--radius-control);
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.tel-link:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--tl-white); }
.tel-link .ico { width: 18px; height: 18px; stroke: var(--tl-yellow); }

.nav-toggle { color: var(--tl-white); }

/* --- Ab wann die Kopfzeile kompakt wird ------------------------------------
   Kitty klappt die Navigation erst unter 48em (768px) ins Flyout; diesen
   Umschaltpunkt legt styles.css fest, und die Foundation fassen wir nicht an.
   Zwischen 768 und 1120 px stand deshalb die VOLLE Kopfzeile in einer zu
   engen Zeile: Logo + Navigation + Werkzeuge + Telefon + „Fahrt buchen"
   brauchen rund 995 px. Der erste Versuch war, alles zusammenzurücken und die
   Zeile als Netz umbrechen zu lassen — dabei entstand aber ein zweizeiliger
   Kopf (oben Logo und Navigation, unten Telefon und „Fahrt buchen"). Zwei
   Reihen sind keine Kopfzeile mehr, sondern ein Stapel.

   Entscheidung (Valeria, 15.09.2026): sobald es eng wird, gilt dieselbe
   REDUZIERTE Fassung wie auf dem Handy — Logo, die beiden Aktionen, Menütaste.
   Die Umschaltbreite liegt damit bei 70em (1120px) statt 48em.

   Die Regeln im Block „Flyout auch oberhalb von 48em" weiter unten sind eine
   BEWUSSTE KOPIE von styles.css (dort Zeile 687 ff.) für das Band 48em–70em.
   Sie sind die einzige Stelle im Projekt, die bei einem Kit-Update mit der
   Foundation abgeglichen werden muss. main.js bleibt unberührt: initMenu
   kennt keine Breite und schaltet data-open bei jeder Größe.

   Ab 70em (Desktop) steht wieder die vollständige Kopfzeile.
   ========================================================================== */

/* Im kompakten Kopf sitzt die Navigation im Flyout — kein Auto-Rand mehr. */
@media (max-width: 69.99em) {
  .site-header .nav { margin-left: 0; }
}

/* --- Flyout auch oberhalb von 48em (Kopie aus styles.css, s. o.) ----------- */
@media (min-width: 48em) and (max-width: 69.99em) {
  .js .nav-toggle { display: block; }
  .nav {
    position: static;
    width: 100%;
    border-top: var(--border);
    display: block;
  }
  .js .nav {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    width: auto;
    border-top: 0;
    border-bottom: var(--border);
    box-shadow: var(--shadow-card);
    display: none;
  }
  .js .nav[data-open="true"] { display: block; }
  .nav a::after { display: none; }
}

/* --- Die kompakte Kopfzeile (Handy UND Tablet) ----------------------------- */
@media (max-width: 69.99em) {
  /* Bezugsrahmen für das absolut gesetzte Flyout. Unter 48em setzt styles.css
     das ebenfalls; hier gilt es für das ganze Band. */
  .site-header__inner {
    position: relative;
    justify-content: space-between;
    flex-wrap: nowrap;
    gap: 12px;
  }
  /* Reihenfolge in der Kopfzeile: Logo · Werkzeuge · Menütaste.
     Der Umschalter gehört ans rechte Ende, sonst greift der Daumen daneben.

     Telefon und „Fahrt buchen" stehen hier NICHT mehr (Entscheidung Valeria,
     15.09.2026). Sie standen zweimal auf demselben Schirm — oben in der Zeile
     und noch einmal im aufgeklappten Menü — während Sprache und Textgröße im
     Menü verschwanden, wo sie niemand vermutet. Jetzt ist es umgekehrt: die
     beiden Werkzeuge sind immer sichtbar, die beiden Aktionen stehen im Menü
     und in der festen Leiste am unteren Rand (§12). Beide bleiben damit auf
     jeder Breite einen Fingertipp entfernt. */
  .brand        { order: 1; }
  /* Etwas mehr Luft als im Desktop-Kopf: hier stehen die beiden Gruppen ganz
     allein am rechten Rand und verschmelzen sonst optisch zu einer Kette
     aus fünf Kästchen. */
  .header-tools { order: 2; margin-left: auto; display: flex; gap: 14px; }
  .js .nav-toggle { order: 3; display: block; position: static; transform: none; margin-left: 0; }
  .site-header .nav { order: 4; }
  .header__cta  { display: none; }
  /* Ohne JavaScript gibt es keine Menütaste; die Navigation steht dann
     dauerhaft aufgeklappt unter der Kopfzeile (Kitty: „JS trägt nie den
     Kerninhalt"). Dafür muss die Zeile umbrechen dürfen — sonst quetscht
     sich die volle Navigation neben das Logo und schiebt die Seite quer. */
  html:not(.js) .site-header__inner { flex-wrap: wrap; }
  html:not(.js) .site-header .nav { flex-basis: 100%; }

  /* --- Das aufgeklappte Menü --- */
  .site-header .nav,
  .js .site-header .nav {
    background: var(--tl-navy);
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    border-bottom: 0;
    box-shadow: 0 18px 32px -18px rgba(0, 0, 0, 0.8);
  }
  /* align-items: stretch und display: block setzen zurück, was die Foundation
     ab 48em für die waagerechte Navigation vorgibt (styles.css Zeile 661 ff.) —
     dort teilen sich die Punkte eine Zeilenbox, hier stehen sie untereinander. */
  .site-header .nav > ul {
    padding-inline: var(--pad-inline);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  .site-header .nav > ul > li {
    display: block;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
  }
  .site-header .nav > ul a {
    display: flex; align-items: center; justify-content: space-between;
    block-size: auto;
    padding: 16px 0; border-radius: 0; font-size: 1.05rem;
    line-height: var(--leading-ui);
  }
  /* Chevron NUR an den echten Navigationszeilen — nicht an Buttons,
     Telefon-Link oder Sprachumschalter, die ebenfalls in .nav liegen. */
  .site-header .nav > ul a::before {
    content: ""; order: 2; width: 8px; height: 8px;
    border-right: 2px solid var(--tl-yellow); border-bottom: 2px solid var(--tl-yellow);
    transform: rotate(-45deg);
  }
  /* Die beiden Aktionen im geöffneten Menü. Seit dem 15.09.2026 stehen hier
     NUR noch Telefon und „Fahrt buchen"; Sprache und Textgröße sind nach oben
     in die Kopfzeile gewandert (s. o.), die Zeile .nav__extras-row ist aus dem
     HTML entfernt. Damit steht im Dokument auch nur noch EIN Sprachumschalter
     — vorher war die Landmark „Sprachauswahl" doppelt vorhanden.
     Kitty macht im Mobil-Layout aus JEDEM .nav a ein display:block — für die
     Buttons und den Telefon-Link im Flyout stellen wir das wieder her. */
  .nav__extras :where(a, button) { padding-block: 0; }
  .nav__extras .button,
  .nav__extras .tel-link {
    display: inline-flex; align-items: center; justify-content: center;
    width: 100%; padding-block: 14px;
  }
  .nav__extras a::before, .nav__extras a::after { content: none; }
  .nav__extras {
    padding: 18px var(--pad-inline) calc(20px + env(safe-area-inset-bottom));
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    display: grid; gap: 12px;
  }
  .nav__extras .button { width: 100%; }
  /* Im Flyout ist wieder Platz: volle Buttonhöhe und Schriftgröße. */
  .nav__extras .tel-link,
  .nav__extras .button { font-size: 1rem; padding-inline: 20px; }
  /* Der Anruf-Button im Menü ist ein vollwertiger Secondary-Button
     (weiße Fläche, navy Schrift) — wie überall sonst auf Navy. Der frühere
     weiche weiße Rahmen war ein Sonderfall ohne Grund. */
  .site-header .nav__extras .tel-link {
    justify-content: center; width: 100%; min-height: var(--btn-h);
    background: var(--tl-white);
    color: var(--tl-navy);
    border: 2px solid var(--tl-white);
    border-radius: var(--radius-control);
    font-weight: 600;
  }
  .site-header .nav__extras .tel-link:hover { background: var(--tl-soft); border-color: var(--tl-soft); }
  .site-header .nav__extras .tel-link .ico { stroke: var(--tl-navy); }
}

/* --- Nur Handy: alles eine Nummer kleiner --------------------------------
   Logo, Textgrößen- und Sprachumschalter und die Menütaste müssen bei 360 px
   nebeneinander in eine Zeile passen — mit Reserve, denn die Vorlese-Geräte
   mancher Nutzer stehen auf der größten Textstufe.

   Die Maße hier sind bewusst in PIXELN und nicht in rem: diese beiden
   Umschalter sind Symbole, keine Fließtexte. Wüchsen sie mit der Textstufe
   mit, schöbe ausgerechnet A+ die Menütaste über den Rand — der Knopf, der
   dann am dringendsten gebraucht wird. Die Beschriftungen darin (A, DE, EN)
   bleiben davon unberührt, die stehen weiterhin in rem. */
@media (max-width: 47.99em) {
  :root { --tl-header-min: 60px; }
  .site-header__inner { gap: 8px; }
  .brand img { height: 26px; }
  .header-tools { gap: 10px; }
  /* Die Umschalter werden SCHMALER, nicht flacher: die Foundation gibt ihnen
     40 px Höhe als Fingerziel (styles.css: min-block-size), und das bleibt so.
     Am Daumen wird nicht gespart, nur an der Breite. */
  .textsize__btn { width: 30px; }
  .site-header .lang-switch__current,
  .site-header .lang-switch__link { min-width: 30px; padding-inline: 5px; }
  /* Die Foundation rechnet damit, dass der Sprachumschalter unter 48em DIREKT
     in der Kopfzeile steht, und legt ihn dort mit flex-basis: 100% auf eine
     eigene Zeile (styles.css Zeile 2001 ff.). Bei uns steht er in
     .header-tools — dort bläst dieselbe Regel ihn auf die volle Breite des
     Kastens auf und schob die Seite um 17 px quer. Deshalb hier zurück auf
     die natürliche Breite. */
  .header-tools .lang-switch { flex-basis: auto; order: 0; }
  .header-tools .lang-switch__list { justify-content: flex-start; }
  /* Ganz schmale Geräte (unter 400 px) bei größter Textstufe. */
  @media (max-width: 400px) {
    .site-header__inner { gap: 6px; }
    .brand img { height: 24px; }
    .header-tools { gap: 8px; }
    .textsize__btn { width: 28px; }
    .site-header .lang-switch__current,
    .site-header .lang-switch__link { min-width: 28px; padding-inline: 4px; }
  }
}
@media (min-width: 70em) {
  .nav__extras { display: none; }
}


/* =============================================================================
   5  HERO  (Spec §4)
   Desktop: das Auto fährt von rechts ins Bild, leicht geneigt, die Räder
   stehen auf dem gelben Schwung. Mobil: Auto vollständig unter Text/Buttons.

   Alle Stellschrauben der Auto-Position stehen als Variablen ganz oben —
   Feinjustage nach der visuellen Vorlage ist damit ein Zahlenwechsel.
   ========================================================================== */
.hero-taxi {
  /* EINE Kette steuert die ganze Hero-Geometrie:
     --wave-h  ist die sichtbare Höhe des gelben Schwungs. Daraus leiten sich
               der Freiraum unter dem Text und die Standlinie des Autos ab.
     Der Schwung wird über object-fit beschnitten statt frei zu skalieren —
     sonst wächst er auf breiten Screens auf 600 px und schiebt sich hinter
     Absatz und Buttons, wo gelb hinter weißer Schrift unlesbar wird. */
  --wave-h:     clamp(90px, 20vw, 300px);
  --wave-gap:   48px;   /* Luft zwischen Buttons und Oberkante des Schwungs */
  --car-width:  54%;    /* Breite relativ zur Hero-Breite            */
  --car-right:  -8%;    /* negativ = ragt über die rechte Kante hinaus */
  --car-bottom: calc(var(--wave-h) * 0.42);  /* Radaufstandslinie im Schwung */
  --car-tilt:   -2.5deg;

  position: relative;
  background: var(--tl-navy);
  color: var(--tl-white);
  padding-top: clamp(36px, 5vw, 72px);
  padding-bottom: 0;
  overflow: hidden;
  isolation: isolate;
}
.hero-taxi__grid { position: relative; z-index: 4; max-width: 640px; }
.hero-taxi h1 { color: var(--tl-white); font-size: var(--text-h1); line-height: var(--leading-h1); }
.hero-taxi h1 em { font-style: normal; color: var(--tl-yellow); }
.hero-taxi__sub {
  margin-top: 18px;
  font-size: clamp(1rem, 1.35vw, 1.13rem);
  color: rgba(255, 255, 255, 0.78);
  max-width: 48ch;
}
.hero-taxi__actions { margin-top: 26px; }
/* Spec §4.1: „side by side on both desktop and mobile". Auf schmalen Screens
   teilen sich beide Buttons die Zeile zu gleichen Teilen statt umzubrechen. */
@media (max-width: 430px) {
  .hero-taxi__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  .hero-taxi__actions .button {
    padding-inline: 10px; font-size: 0.92rem; gap: 7px; min-width: 0;
  }
  .hero-taxi__actions .button .ico { width: 17px; height: 17px; }
}

/* Der gelbe Schwung aus der Fahrzeuglackierung — Signaturelement, volle
   Breite, sitzt am unteren Rand des Hero. */
.hero-taxi__wave {
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  z-index: 2;
  line-height: 0;
  pointer-events: none;
}
.hero-taxi__wave img {
  width: 100%;
  height: var(--wave-h);
  object-fit: cover;          /* beschneidet oben/unten statt zu skalieren */
  object-position: 50% 45%;
  display: block;
}

/* Auto — Desktop: absolut, angeschnitten, geneigt. */
.hero-taxi__car {
  position: absolute;
  right: var(--car-right);
  bottom: var(--car-bottom);
  width: var(--car-width);
  max-width: 760px;
  z-index: 3;
  transform: rotate(var(--car-tilt));
  transform-origin: 60% 100%;
  pointer-events: none;
}
.hero-taxi__car img {
  width: 100%; height: auto; display: block;
  filter: drop-shadow(0 26px 32px rgba(0, 0, 0, 0.5));
}
/* Platz unter der Textspalte, damit Auto und Schwung nicht in die Buttons
   laufen. Wächst mit der Viewportbreite, weil das Auto prozentual skaliert. */
.hero-taxi__spacer { height: calc(var(--wave-h) + var(--wave-gap)); }

@media (max-width: 900px) {
  /* MOBIL IST DAS SPIEGELBILD DES DESKTOPS.
     Desktop: der Schwung passt ins Bild, das AUTO ragt rechts heraus und
              fährt dadurch sichtbar ins Bild hinein.
     Mobil:   das Auto passt ins Bild, der SCHWUNG ragt links und rechts
              heraus und wird dadurch zur Straße, auf der es steht.

     Der Schwung darf also NICHT auf die Bildschirmbreite gequetscht werden.
     Gequetscht bleibt von der Kurve nur ein dünner Haken übrig, ihre Steigung
     verschwindet, und das Auto scheint über einem Strich zu schweben.
     Stattdessen bekommt er hier eine feste Breite als Vielfaches der
     Bildschirmbreite; die Höhe folgt dem Seitenverhältnis der Grafik
     (3300 : 833 = 3.962), damit nichts verzerrt. */
  .hero-taxi {
    /* Der Überstand ist ein fester Zuschlag, kein Vielfaches: auf dem Handy
       ragt der Schwung dadurch deutlich heraus, auf dem Tablet wächst er nicht
       ins Unermessliche. --wave-left schneidet immer bei 30 % der Grafik an,
       damit der Haken auf jeder Breite an derselben Stelle sitzt. */
    --wave-w:     calc(100vw + 500px);
    --wave-left:  calc(var(--wave-w) * -0.30);
    --wave-h:     calc(var(--wave-w) / 3.962);  /* Höhe folgt dem Bild        */
    padding-top: 32px;
  }
  .hero-taxi__grid { max-width: none; }
  .hero-taxi__wave {
    left: var(--wave-left);
    right: auto;
    width: var(--wave-w);
  }
  .hero-taxi__wave img {
    width: 100%;
    height: auto;             /* natürliches Verhältnis, kein Beschnitt */
    object-fit: fill;
  }
  /* Das Auto steht im Fluss und wird per negativem Rand so weit nach unten
     gezogen, dass die Räder auf dem Schwung stehen. Der Wert hängt an
     --wave-h, damit Straße und Auto bei jeder Breite zusammenbleiben. */
  .hero-taxi__car {
    /* relative statt static: das Auto bleibt im Fluss, behält aber seinen
       z-index — sonst malt der absolut gesetzte Schwung quer über die Karosse
       statt hinter ihr zu liegen. */
    position: relative;
    right: auto; bottom: auto;
    width: min(104%, 560px);
    margin: 18px auto calc(var(--wave-h) * -0.21);
    /* Leichte Neigung wie auf dem Desktop: der Schwung steigt nach rechts an,
       ein waagerecht stehendes Auto würde vorne von der Straße abheben.
       Der Wert steht in derselben Variablen wie auf dem Desktop, damit die
       Einfahr-Animation weiter unten mit EINER Regel für beide auskommt. */
    --car-tilt: -2deg;
    transform: rotate(var(--car-tilt));
    transform-origin: 50% 100%;
  }
  .hero-taxi__spacer { height: calc(var(--wave-h) * 0.62); }
}


/* --- Fakten-Band unter dem Hero ------------------------------------------
   Vier Kernaussagen als eigenes gelbes Vollbreiten-Band direkt unter dem
   Hero (Vorbild: lakis-v1). Bewusst NICHT als Pillen unter den Buttons: dort
   standen sie im Weg des Autos und gingen im Hero unter. Aufbau je Spalte
   eine kurze, fette Schlagzeile plus eine erklärende Zeile darunter. */
.facts-band { padding-block: clamp(40px, 5vw, 64px); }
.facts-band__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 3vw, 40px);
  margin: 0; padding: 0; list-style: none;
}
.facts-band__grid > li { min-width: 0; }
.facts-band__grid > li { display: flex; flex-direction: column; }
.facts-band b {
  display: block;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.4rem, 0.9rem + 1.1vw, 1.95rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--tl-navy);
  margin-bottom: 6px;         /* Schlagzeile steht dicht über ihrem Text */
}
.facts-band span {
  display: block;
  font-size: 0.97rem;
  line-height: 1.55;
  color: rgba(7, 3, 49, 0.78);
  max-width: 26ch;
}
@media (max-width: 900px) { .facts-band__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .facts-band__grid { grid-template-columns: 1fr; gap: 22px; } }


/* =============================================================================
   6  SECTION-RHYTHMUS
   ========================================================================== */
.section__head { max-width: var(--measure); margin-bottom: clamp(28px, 4vw, 44px); }
.section__head h2 { font-size: var(--text-h2); line-height: var(--leading-h2); }
.section__head .lede { margin-top: 16px; }


/* =============================================================================
   7  FAHRTKARTEN  (Spec §5 Top 3 · §6 alle acht)
   Beide Sets sind Navy-Karten mit einer einzigen Ghost-CTA. Jede Karte ist
   als Ganzes klickbar: die Karte selbst ist KEIN Button (das würde einen
   Button in einem Button ergeben), stattdessen deckt die CTA per ::after die
   Kartenfläche ab. Ohne JavaScript bleibt die CTA ein normaler Link auf die
   Telefonnummer — der Inhalt trägt sich also auch ohne JS.
   ========================================================================== */
.rides, .services {
  display: grid;
  gap: 16px;
  padding: 0; margin: 0; list-style: none;
}
.rides    { grid-template-columns: repeat(3, 1fr); }
.services { grid-template-columns: repeat(4, 1fr); }
/* Sobald mehr als eine Spalte steht, sind alle Zeilen gleich hoch — sonst
   richtet sich jede Zeile nach ihrer längsten Karte und das Raster franst aus.
   Einspaltig (Handy) bleibt es bei der natürlichen Höhe, sonst entstünde
   unter kurzen Texten viel Leerraum. */
@media (min-width: 561px) {
  .rides, .services { grid-auto-rows: 1fr; }
}

.ride {
  position: relative;
  display: flex; flex-direction: column; gap: 10px;
  background: var(--tl-navy-2);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-container);
  padding: 24px 22px 22px;
  color: var(--tl-white);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
/* Hervorhebung ohne Bewegung: Rand und Fläche wechseln, die Karte bleibt
   stehen. Ein translateY hier ließ beim Überstreichen der Maus alle elf
   Karten nacheinander hochspringen — siehe Abschnitt „Bewegung" unten. */
.ride:hover,
.ride:focus-within {
  border-color: var(--tl-yellow);
  background: var(--tl-navy-3);
  box-shadow: var(--shadow-card);
}
.ride__ico {
  width: 56px; height: 56px; flex: none;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.12);
  display: grid; place-items: center;
  margin-bottom: 4px;
  color: var(--tl-yellow);
}
.ride__ico .ico-svc { width: 30px; height: 30px; }
.ride h3 { font-size: 1.12rem; color: var(--tl-white); }
.ride p  { font-size: 0.94rem; line-height: 1.5; color: rgba(255, 255, 255, 0.76); }
.ride p strong { color: var(--tl-white); font-weight: 800; }
.ride .button { margin-top: auto; align-self: flex-start; }
/* Die CTA deckt die ganze Karte ab -> Klick auf die Karte öffnet das Modal. */
.ride .button::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }

/* --- Die acht Leistungskarten: HELL --------------------------------------
   Achtmal Navy nebeneinander wirkt zu schwer. Die Top 3 bleiben dunkel und
   behalten damit ihr Gewicht; die vollständige Liste steht auf Weiß und hebt
   sich beim Auswählen durch Schatten und Rand hervor — nicht durch Farbe.
   Das Icon-Plättchen bleibt navy, damit die gelben Ikonen ihren Kontrast
   behalten und die Bildsprache über beide Kartensorten dieselbe ist. */
.services .ride {
  padding: 22px 20px 20px;
  background: var(--tl-white);
  border: 1px solid var(--tl-line);
  color: var(--tl-navy);
  box-shadow: none;
}
.services .ride:hover,
.services .ride:focus-within {
  background: var(--tl-white);
  border-color: var(--tl-navy);
  box-shadow: var(--shadow-card);
}
.services .ride__ico {
  width: 48px; height: 48px; border-radius: 12px;
  background: var(--tl-navy);
  border-color: var(--tl-navy);
  color: var(--tl-yellow);
}
.services .ride__ico .ico-svc { width: 26px; height: 26px; }
.services .ride h3 { font-size: 1.04rem; color: var(--tl-navy); }
.services .ride p  { font-size: 0.9rem; color: var(--tl-muted); }
.services .ride p strong { color: var(--tl-navy); }

/* CTA als Outline-Button — als Schaltfläche eindeutiger erkennbar als ein
   Textlink mit Pfeil. Beim Auswählen der Karte füllt sie sich navy. */
.services .ride .button--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--tl-navy);
  --btn-border: var(--tl-navy);
  align-self: flex-start;
}
.services .ride:hover .button--ghost,
.services .ride:focus-within .button--ghost,
.services .ride .button--ghost:hover {
  --btn-bg: var(--tl-navy);
  --btn-fg: var(--tl-white);
  --btn-border: var(--tl-navy);
}

@media (max-width: 1000px) {
  .rides    { grid-template-columns: 1fr; }
  .services { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .services { grid-template-columns: 1fr; gap: 12px; }
}

/* Abschluss-Leiste der Leistungssektion: Zahlung & Krankenkasse. */
/* Zwei gleich breite Spalten — nicht flex-basiert, sonst richtet sich die
   Breite nach der Textmenge und die beiden Leisten werden ungleich. */
.svc-notes { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 20px; }
@media (max-width: 700px) { .svc-notes { grid-template-columns: 1fr; } }
/* Dunkel und gleich hoch: die beiden Leisten sind ein Paar und sollen als
   eines gelesen werden. `height: 100%` füllt die Rasterzeile — ohne das
   richtet sich jede nach ihrer eigenen Textmenge. */
.svc-note {
  display: flex; align-items: center; gap: 14px;
  height: 100%; margin: 0;
  background: var(--tl-navy);
  border-radius: var(--radius-container);
  padding: 20px 22px;
  font-size: 0.95rem; font-weight: 600; line-height: 1.5;
  color: rgba(255, 255, 255, 0.88);
}
.svc-note .badge {
  width: 42px; height: 42px; flex: none;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  display: grid; place-items: center; color: var(--tl-yellow);
}
.svc-note .badge .ico-svc { width: 21px; height: 21px; }


/* =============================================================================
   8  ÜBER UNS · FUHRPARK  (Spec §7) — keine Buttons, keine Modal-Trigger
   ========================================================================== */
/* Drei Kennzahlen, GLEICHES Gewicht: kein Zahl/Label-Split (Spec §7). */
/* Drei einzelne Kennzahl-Karten, im Aufbau wie das gelbe Fakten-Band unter
   dem Hero: große Zahl, erklärende Zeile darunter.
   ABWEICHUNG von Landingpage-Spec §7 („kein Zahl/Label-Split, gleiches
   Gewicht") — auf ausdrücklichen Wunsch, in PROJECT.md vermerkt. */
.facts {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 2.2vw, 28px);
  margin: 32px 0 0; padding: 0; list-style: none;
}
.facts li {
  display: flex; flex-direction: column;
  background: var(--tl-yellow);
  border-radius: var(--radius-container);
  padding: 24px 24px 26px;
}
.facts b {
  display: block;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.6rem, 1rem + 1.3vw, 2.2rem);
  line-height: 1.05; letter-spacing: -0.02em;
  color: var(--tl-navy);
  margin-bottom: 6px;
}
/* Auf Gelb muss der Fließtext kräftiger sein als auf Softblau — ein auf 72 %
   heruntergezogenes Navy wirkt dort stumpf und verliert Kontrast. */
.facts span {
  display: block;
  font-size: 0.95rem; line-height: 1.5;
  color: rgba(7, 3, 49, 0.82);
}
@media (max-width: 640px) { .facts { grid-template-columns: 1fr; } }

/* Zwei Fahrzeugkarten: freigestelltes Foto, das auf seiner Info-Box STEHT —
   dasselbe Prinzip wie im Hero, wo das Auto auf dem Schwung steht.

   Damit das trägt, mussten zuerst die beiden Bilder zusammenpassen: sie hatten
   unterschiedlich viel Leerraum, dadurch standen die Wagen in verschiedenen
   Größen und auf verschiedenen Höhen. Beide liegen jetzt auf derselben
   Leinwand (880 × 500), auf dieselbe Breite gebracht und unten auf derselben
   Standlinie. Der Caddy ist also höher als der Kombi, weil er es wirklich ist,
   und nicht, weil das Foto anders beschnitten war. */
.fleet {
  display: grid; grid-template-columns: repeat(2, 1fr);
  /* Großzügiger als bei den anderen Rastern, und zwar mit Grund: die
     freigestellten Fotos laufen bis an den Rand ihrer Spalte, das Heck des
     Kombis endete also fast am Bug des Caddys. Zwischen zwei Karten reichen
     20 px — zwischen zwei Autos nicht. */
  gap: clamp(28px, 5vw, 72px);
  /* Der senkrechte Abstand zu den gelben Kennzahlen darüber muss größer sein
     als ein normaler Rasterabstand: der Caddy füllt seine Leinwand fast bis
     zur Oberkante aus, sein Taxischild begann also unmittelbar unter der
     gelben Karte. */
  margin: clamp(48px, 7vw, 96px) 0 0; padding: 0; list-style: none;
  grid-auto-rows: 1fr;                 /* beide Karten exakt gleich hoch */
}
.veh { display: flex; flex-direction: column; height: 100%; }
.veh__img {
  position: relative; z-index: 2;      /* das Auto liegt VOR seiner Box */
  /* Auto und Box stehen auseinander. Der Weg dahin ging über −30 px (die
     Oberkante schnitt quer durch die Karosse) und −10 px (setzte gerade
     eben auf). Jetzt liegen echte Luft dazwischen. Im Bild selbst stecken
     unten noch 8 px Leerraum, sichtbar sind also rund 26 px. */
  margin-bottom: 18px;
  pointer-events: none;
}
.veh__img img { width: 100%; height: auto; display: block; }
.veh__body {
  position: relative; z-index: 1;
  flex: 1;                             /* füllt die Karte bis unten aus */
  background: var(--tl-soft);
  border: 1px solid var(--tl-line);
  border-radius: var(--radius-container);
  padding: 26px 26px 28px;
  color: var(--tl-navy);
}
/* .on-navy färbt jede Überschrift weiß — auf der hellen Box wäre sie damit
   unsichtbar. Gilt für beide Zeilen, deshalb hier ausdrücklich. */
.veh__body h3 { color: var(--tl-navy); font-size: 1.25rem; margin-bottom: 8px; }
.veh__body p  { font-size: 1.05rem; line-height: 1.55; color: rgba(7, 3, 49, 0.8); }
@media (max-width: 720px) {
  /* Untereinander gestapelt bringt gleiche Höhe nichts und kostet nur Platz. */
  .fleet { grid-template-columns: 1fr; gap: 26px; grid-auto-rows: auto; }
  .veh__img { margin-bottom: 14px; }
}

/* Kennzeichen: EIN Block, nicht vier lose Zeilen.
   Vorher stand zwischen Bild, Überschrift, Subline und Erklärung überall
   derselbe Abstand von 18 px — dadurch gehörte optisch nichts zusammen.
   Jetzt: Bild, deutliche Lücke, dann der Text als eng gesetzte Einheit.
   Der Schatten am Bild ist weg. Er lag auf einem freigestellten PNG und
   zeichnete deshalb ein RECHTECK hinter das Schild — was wie eine weiße
   Karte aussah, die dort nie gedacht war. */
.plate-card {
  margin-top: clamp(36px, 5vw, 60px);
  display: grid; justify-items: center; text-align: center; gap: 0;
}
.plate-card img {
  width: min(100%, 380px); height: auto; display: block;
  margin-bottom: 26px;
}
/* Alle Eigenabstände zurücksetzen und dann bewusst setzen — sonst schiebt
   der Standardabstand der Absätze den Text wieder auseinander. */
.plate-card > * { margin: 0; }
.plate-card h3 { font-size: 1.7rem; margin-bottom: 10px; }
.plate-card .plate-sub {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.14rem;
  color: var(--tl-yellow);
  margin-bottom: 14px;
}
.plate-card p { max-width: 52ch; font-size: 1.08rem; line-height: 1.65; }


/* =============================================================================
   9  KONTAKT / BUCHUNGS-CTA  (Spec §8) — gelbes Band vor der FAQ
   ========================================================================== */
.cta-final { text-align: center; display: grid; justify-items: center; gap: 8px; }
.cta-final h2 { max-width: 18ch; font-size: var(--text-h2); line-height: var(--leading-h2); }
.cta-final p  { max-width: 52ch; font-size: 1.06rem; color: rgba(7, 3, 49, 0.78); }
.cta-final .button-row { justify-content: center; margin-top: 26px; }
.cta-final__meta {
  display: flex; flex-wrap: wrap; gap: 10px 28px; justify-content: center;
  margin-top: 30px; font-size: 0.95rem; color: rgba(7, 3, 49, 0.76);
}
.cta-final__meta a { font-weight: 600; }


/* =============================================================================
   10  FAQ  (Spec §9)
   10a Landingpage-Teaser: acht kuratierte Fragen, STATISCH offen, kein
       Accordion — die Antworten sollen ohne Interaktion lesbar (und für
       Suchmaschinen/AI-Engines direkt extrahierbar) sein.
   10b Vollseite: zweistufiges Accordion aus nativen <details>. Kein
       JavaScript nötig — Kategorie zu, Fragen darin offen.
   ========================================================================== */
.faq-teaser {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 28px 48px; margin: 0; padding: 0;
}
.faq-teaser > div { border-top: 2px solid var(--tl-line); padding-top: 18px; }
.faq-teaser dt {
  font-family: var(--font-display); font-weight: 800; font-size: 1.05rem;
  color: var(--tl-navy); margin-bottom: 8px;
}
.faq-teaser dd { margin: 0; font-size: 0.97rem; line-height: 1.6; color: var(--tl-muted); }
@media (max-width: 780px) { .faq-teaser { grid-template-columns: 1fr; gap: 22px; } }

/* --- Vollseite: Kategorie (Ebene 1) --- */
.faq-cat {
  border: 1px solid var(--tl-line);
  border-radius: var(--radius-container);
  background: var(--tl-white);
  margin-bottom: 12px;
  overflow: hidden;
}
.faq-cat > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 20px 22px;
  font-family: var(--font-display); font-weight: 800; font-size: 1.12rem;
  color: var(--tl-navy);
  background: var(--tl-soft-2);
  transition: background-color var(--dur) var(--ease);
}
.faq-cat > summary::-webkit-details-marker { display: none; }
.faq-cat > summary:hover { background: var(--tl-soft); }
.faq-cat > summary::after {
  content: ""; flex: none; width: 11px; height: 11px;
  border-right: 2.4px solid var(--tl-navy); border-bottom: 2.4px solid var(--tl-navy);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur) var(--ease);
}
.faq-cat[open] > summary::after { transform: rotate(-135deg) translate(-3px, -3px); }
.faq-cat[open] > summary { background: var(--tl-soft); border-bottom: 1px solid var(--tl-line); }
.faq-cat__body { padding: 6px 22px 14px; }

/* --- Vollseite: Frage (Ebene 2) --- */
.faq-q { border-bottom: 1px solid var(--tl-line); }
.faq-q:last-child { border-bottom: 0; }
.faq-q > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 16px 0;
  font-family: var(--font-display); font-weight: 600; font-size: 1rem;
  color: var(--tl-navy);
}
.faq-q > summary::-webkit-details-marker { display: none; }
.faq-q > summary::after {
  content: "+"; flex: none;
  font-family: var(--font-body); font-size: 1.4rem; line-height: 1;
  color: var(--tl-muted);
}
.faq-q[open] > summary::after { content: "\2013"; }
.faq-q__answer { padding: 0 0 18px; font-size: 0.97rem; line-height: 1.65; color: var(--tl-muted); }
.faq-q__answer p { margin: 0 0 10px; }
.faq-q__answer p:last-child { margin-bottom: 0; }
.faq-q__answer ul { margin: 8px 0 10px; padding-left: 20px; }
.faq-q__answer li { margin-bottom: 4px; }
.faq-q__answer strong { color: var(--tl-navy); }
.faq-q__answer a { color: var(--tl-navy); font-weight: 600; }

/* Inhaltsverzeichnis der FAQ-Seite */
.faq-toc { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 32px; padding: 0; list-style: none; }
.faq-toc a {
  display: inline-block; padding: 8px 14px;
  background: var(--tl-soft-2); border: 1px solid var(--tl-line);
  border-radius: 999px; font-size: 0.88rem; font-weight: 600;
  color: var(--tl-navy); text-decoration: none;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.faq-toc a:hover { background: var(--tl-soft); border-color: var(--tl-navy); }


/* =============================================================================
   11  FOOTER  (Spec §10)
   ========================================================================== */
.site-footer--dark { background: var(--tl-navy); color: rgba(255, 255, 255, 0.72); }
.site-footer--dark .footer-top {
  display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr 1fr; gap: 34px;
  padding-block: clamp(44px, 6vw, 64px) 0;
}
.site-footer--dark .footer-col :where(h2, .footer-title) {
  font-family: var(--font-display); font-size: 0.78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--tl-yellow); margin-bottom: 14px;
}
.site-footer--dark .footer-col a:not(.button),
.site-footer--dark .footer-col address { color: rgba(255, 255, 255, 0.72); }
/* styles.css färbt JEDES a in .footer-col hell ein (Spezifität 0,3,1) und
   überstimmt damit die Buttonfarbe. Hier gleiche Spezifität, aber später —
   sonst steht „Fahrt buchen" weiß auf Gelb und „Jetzt anrufen" weiß auf Weiß. */
.site-footer--dark .footer-col a.button { color: var(--btn-fg); }
/* Dieselbe Stelle hatte zwei Hälften. Die Farbe war repariert, die
   Unterstreichung nicht: styles.css unterstreicht jedes .footer-col a beim
   Überfahren, also bekam auch „Fahrt buchen" im Fuß einen Strich unter der
   Beschriftung — mitten im gefüllten Knopf. */
.site-footer--dark .footer-col a.button:hover { text-decoration: none; }
.site-footer--dark .footer-col a:not(.button):hover { color: var(--tl-yellow); text-decoration: none; }
.site-footer--dark .footer-col address { font-style: normal; line-height: 1.7; }
/* Beschriftung vor einer Rufnummer im Fuß (Kundenwunsch vom 15.09.2026:
   „sonst versteht man nicht, was was ist"). Steht als reiner Text im SELBEN
   <li> wie die Nummer — kein Link, kein eigener Listenpunkt: so liest eine
   Sprachausgabe „Telefon: 07152 26621" in einem Zug, und der Fingertipp
   trifft weiterhin nur die Nummer.
   Etwas leiser als die Nummer selbst (0,58 statt 0,72 Deckkraft) — auf Navy
   sind das 7,2 : 1, also weit über den geforderten 4,5 : 1. Die lange dritte
   Beschriftung darf umbrechen; die Nummer rutscht dann auf die nächste
   Zeile und bleibt als Block zusammen. */
.site-footer--dark .footer-col .footer-label {
  color: rgba(255, 255, 255, 0.58);
  margin-right: 2px;
}
.site-footer--dark .footer-col li:has(.footer-label) {
  line-height: 1.45;
  max-width: 26ch;
}
/* Eine Rufnummer wird NIE umgebrochen. Ohne das riss die lange dritte
   Beschriftung die Nummer mitten entzwei: „0151 500 60" in der einen Zeile,
   „237" in der nächsten — unlesbar und nicht zum Abtippen. Passt die Nummer
   nicht mehr neben die Beschriftung, rutscht sie als Ganzes eine Zeile
   tiefer, und genau so soll es sein. */
.site-footer--dark .footer-col li:has(.footer-label) a { white-space: nowrap; }
.footer-brand img { height: 34px; width: auto; margin-bottom: 16px; display: block; }
.footer-col .button { width: 100%; }
.footer-col .button + .button { margin-top: 10px; }
.footer-consent {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
  text-decoration: underline; text-decoration-color: var(--tl-yellow);
  text-underline-offset: 0.18em;
}
.footer-consent:hover { color: var(--tl-yellow); }
.site-footer--dark .footer-bottom { border-top: 1px solid rgba(255, 255, 255, 0.14); margin-top: 40px; }
.site-footer--dark .footer-bottom__inner {
  padding-block: 20px 24px; font-size: 0.88rem; color: rgba(255, 255, 255, 0.55);
}
.site-footer--dark .footer-bottom a { color: rgba(255, 255, 255, 0.72); }
.site-footer--dark .heart { color: var(--tl-yellow); font-size: 1.1em; line-height: 1; }
@media (max-width: 1000px) { .site-footer--dark .footer-top { grid-template-columns: 1fr 1fr 1fr; } }
@media (max-width: 640px)  { .site-footer--dark .footer-top { grid-template-columns: 1fr; gap: 26px; } }


/* =============================================================================
   12  STICKY ACTION BAR (mobil)  (Spec §3)
   Steht auf schmalen Bildschirmen von Anfang an unten am Rand. Navy-Grund,
   zwei beschriftete Buttons nebeneinander — bewusst NICHT die nackte Nummer.

   Die Leiste gilt seit dem 15.09.2026 bis 70em (1120px) statt bis 860px:
   genau so weit, wie die Kopfzeile reduziert ist. Seit Telefon und
   „Fahrt buchen" dort oben nicht mehr stehen (§4), wäre sonst zwischen 860
   und 1120 px keine Aktion mehr sichtbar. „Reduziert" heißt jetzt überall
   dasselbe: Menütaste oben, die beiden Aktionen unten.

   Kein Hereinfahren mehr: die Leiste ist sofort da, schon beim ersten
   Bildaufbau. Das ist Absicht und hängt NICHT mehr an JavaScript-Zustand.
   Früher stand sie auf transform: translateY(110%) und wurde erst durch
   [data-visible="true"] hereingeholt — da main.js mit defer lädt, wäre sie
   bei jedem Seitenaufruf sichtbar von unten hereingerutscht. Das sieht
   wie ein Nachladen aus, nicht wie ein fester Bestandteil der Seite.
   ========================================================================== */
.sticky-bar { display: none; }
@media (max-width: 69.99em) {
  .js .sticky-bar {
    /* minmax(0, 1fr) statt 1fr: ein nacktes 1fr lässt die Spalte nie unter
       die Mindestbreite ihres Inhalts schrumpfen. Der rechte Knopf stand
       dadurch auf 320-px-Geräten neun Pixel über dem Bildschirmrand und
       seine Beschriftung war abgeschnitten. */
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
    background: var(--tl-navy);
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    box-shadow: 0 -6px 24px rgba(7, 3, 49, 0.35);
  }
  .sticky-bar .button { min-height: 52px; font-size: 0.98rem; padding-inline: 12px; min-width: 0; }
  /* Sehr schmale Geräte: der Platz kommt aus Polstern und Abständen, nicht
     aus der Schriftgröße — die gehört dem Nutzer und seiner Textstufe. */
  @media (max-width: 380px) {
    .js .sticky-bar { gap: 8px; padding-inline: 10px; }
    .sticky-bar .button { padding-inline: 8px; gap: 6px; }
  }
  /* Platz, damit die Leiste nie den letzten Absatz der Seite verdeckt. */
  .js body { padding-bottom: 84px; }
}


/* =============================================================================
   13  BUCHUNGS-MODAL  (taxi-lakis-booking-modal-spec.md)
   Baut auf Kitty's .scrim/.modal auf (Kitty.overlay.open/close). Modal-Chrome
   bleibt weiß; Markenfarbe ist reserviert für Submit-Button, Sofort-Hinweis
   und Telefon-Pille (Spec §9 des Modal-Dokuments).
   ========================================================================== */
/* PROGRESSIVE ENHANCEMENT — der Kern des Bausteins.
   Das Buchungsformular ist Kerninhalt, es darf also nicht von JavaScript
   abhängen (KIT.md: „JS trägt nie den Kerninhalt").

   OHNE JS  → .booking-layer ist ein ganz normaler Seitenabschnitt am Ende der
              Seite. Jede „Fahrt buchen"-CTA ist ein Anker auf #buchung und
              springt dorthin. Das Formular postet klassisch an buchung.php,
              die Bestätigung kommt über danke.html.
   MIT JS   → das Modul in main.js hängt .scrim an dieselbe Hülle; damit greift
              Kitty's Overlay-API (Fokusfalle, Escape, Scroll-Lock, inert) und
              die CTAs öffnen das Modal statt zu springen.                     */
/* Solange main.js die Hülle noch nicht zum Overlay gemacht hat, wäre das
   Formular für einen Moment als voller Abschnitt am Seitenende zu sehen. Die
   .js-Klasse setzt das Inline-Script im <head> vor dem ersten Rendern —
   damit ist der Abschnitt für JS-Browser von Anfang an aus dem Weg, und ohne
   JavaScript bleibt er sichtbar. (Gleiches Muster wie Kitty's .js .nav.) */
html.js .booking-layer:not(.scrim) { display: none; }

.booking-layer {
  background: var(--tl-soft-2);
  padding-block: clamp(48px, 6vw, 80px);
  scroll-margin-top: var(--scroll-offset);
}
.booking-layer > .booking-modal {
  width: 100%;
  max-width: 660px;
  margin-inline: auto;
  background: var(--tl-white);
  box-shadow: var(--shadow-card);
}
/* Sobald die Hülle zum Scrim geworden ist, gelten wieder Kitty's Overlay-Regeln. */
.booking-layer.scrim { background: var(--color-scrim); padding-block: var(--space-24); }

.scrim { background: var(--color-scrim); backdrop-filter: blur(3px); }
.booking-modal {
  max-width: 660px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-large);
  display: flex; flex-direction: column;
}
/* Höhenbegrenzung und Innen-Scroll gelten NUR im Overlay-Zustand — inline
   soll das Formular in voller Länge im Seitenfluss stehen. */
.scrim > .booking-modal { max-height: 90dvh; overflow: hidden; }
/* overflow-x MUSS hier ausgeschrieben stehen. Sobald eine Achse auf einen
   anderen Wert als visible gesetzt wird, rechnet CSS die andere Achse von
   visible auf auto hoch — mit overflow-y: auto allein war der Formularkörper
   also auch WAAGERECHT ziehbar. Am Rechner fällt das nie auf, weil die Maus
   keine Seitwärtsgeste kennt; auf dem Handy rutscht das Formular beim Wischen
   nach links und rechts. Gemeldet von Valeria am 15.09.2026. */
.scrim > .booking-modal .booking__body { overflow-y: auto; overflow-x: hidden; }
.booking-layer:not(.scrim) .booking__body { overflow: visible; }

/* Kitty parkt den Bot-Köder auf left: -9999px (styles.css Zeile 1072). Das ist
   die zweite Hälfte desselben Problems: ein Element weit außerhalb des Kastens,
   in einem Behälter, der scrollen darf. Mobile Browser lassen sich davon zu
   einem seitlichen Gummiband überreden. Die Foundation fassen wir nicht an —
   hier im Formular steht der Köder deshalb an seiner normalen Stelle im Fluss
   und wird mit der üblichen clip-path-Technik unsichtbar gemacht. Er bleibt
   im HTML, bleibt für Bots ausfüllbar, ragt aber in keine Richtung heraus.
   aria-hidden und tabindex="-1" stehen am Markup und halten ihn weiterhin von
   Sprachausgabe und Tabulator fern. */
.booking .honeypot {
  position: absolute;
  left: auto; right: auto; top: auto; bottom: auto;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.booking-layer:not(.scrim) .modal__close { display: none; }
@media (max-width: 47.999em) {
  .scrim--fullscreen-mobile { place-items: end center; }
  .scrim--fullscreen-mobile > .booking-modal {
    height: auto; max-height: 94dvh;
    border-radius: 22px 22px 0 0;
    padding: 0;
  }
}

.booking__head {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 22px 24px 16px;
  border-bottom: 1px solid var(--tl-line);
  flex: none;
}
.booking__head h2 { font-size: 1.5rem; margin-bottom: 4px; color: var(--tl-navy); }
.booking__head p  { font-size: 0.92rem; color: var(--tl-muted); }
.booking__head .modal__close { margin-left: auto; width: 42px; height: 42px; border-radius: 10px; }

.booking { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.booking__body { -webkit-overflow-scrolling: touch; padding: 20px 24px 8px; flex: 1; min-height: 0; }
.booking__foot {
  flex: none;
  padding: 16px 24px calc(18px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--tl-line);
  background: var(--tl-white);
  display: grid; gap: 10px;
}
.booking__foot .hint { font-size: 0.83rem; color: var(--tl-muted); text-align: center; }
.booking__foot .button { width: 100%; }

/* Sofort-Hinweis (immer sichtbar, direkt unter dem Kopf) */
.urgent {
  display: flex; align-items: center; gap: 14px;
  background: var(--tl-soft);
  border-radius: var(--radius-control);
  padding: 14px 16px; margin-bottom: 22px;
}
.urgent__txt { font-size: 0.92rem; line-height: 1.45; flex: 1; color: var(--tl-navy); }
.urgent__txt b { font-family: var(--font-display); display: block; }
.urgent__txt .en { color: var(--tl-muted); }
.urgent .button { flex: none; }
@media (max-width: 520px) {
  .urgent { flex-direction: column; align-items: stretch; }
  .urgent .button { width: 100%; }
}

/* --- Formularfelder --- */
.booking .field { margin-bottom: 18px; }
.booking .field > label:not(.check),
.booking .field__legend {
  display: block;
  font-family: var(--font-display); font-weight: 600; font-size: 0.93rem;
  margin-bottom: 7px; color: var(--tl-navy);
}
/* 500 statt 400: die Beschriftungen laufen in Jost, und von Jost ist keine
   400er-Datei dabei. Der Browser hätte die 400 aus der 500 selbst berechnet —
   künstlich verdünnte Buchstaben neben echten sieht man. */
.booking .field .opt { font-weight: 600; color: var(--tl-muted); font-size: 0.86rem; }
.booking .field small { display: block; font-size: 0.83rem; color: var(--tl-muted); margin-top: 6px; line-height: 1.45; }
/* EIN Feld pro Zeile, auch auf dem Desktop (Modal-Spec §3: „single column —
   desktop included, no two-column rows"). Beim Ausfüllen unter Zeitdruck ist
   eine einzige Spalte deutlich einfacher zu verfolgen. */
.booking .row { display: block; }
.booking fieldset { border: 0; margin: 0; padding: 0; }

.booking input[type="text"], .booking input[type="tel"], .booking input[type="email"],
.booking input[type="date"], .booking input[type="time"], .booking input[type="number"],
.booking select, .booking textarea {
  width: 100%;
  font-family: var(--font-body); font-size: 16px; color: var(--tl-navy);
  padding: 13px 14px; min-height: 50px;
  background: var(--tl-white);
  border: 1.5px solid var(--tl-line);
  border-radius: var(--radius-small);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.booking textarea { min-height: 88px; resize: vertical; line-height: 1.5; }
.booking :where(input, select, textarea):focus {
  outline: none; border-color: var(--tl-navy); box-shadow: var(--shadow-focus);
}
.booking :where(input, select, textarea):focus-visible { outline: 3px solid var(--tl-yellow); outline-offset: 1px; }
.booking select {
  appearance: none; padding-right: 44px;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23070331' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 18px;
}
.booking ::placeholder { color: #9C9AB4; }

/* Zähler / Stepper — quadratische Tasten im .count-Stil des Entwurfs,
   als −/Zahl/+ ausgeführt, weil Großraum & Events keine feste Obergrenze
   haben (Modal-Spec §6). Die Zahl in der Mitte ist direkt editierbar. */
/* stretch, nicht center: das Zahlenfeld wächst mit der Textgröße, die beiden
   Tasten müssen mitwachsen — sonst steht bei A+ ein hohes Feld zwischen zwei
   zu kleinen Quadraten. */
.count { display: flex; align-items: stretch; gap: 8px; }
.count button {
  width: 52px; min-height: 52px; height: auto; flex: none;
  display: grid; place-items: center;
  border: 1.5px solid var(--tl-line); border-radius: 11px;
  background: var(--tl-white); color: var(--tl-navy);
  font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.count button:hover { border-color: var(--tl-navy); }
.count button:active,
.count button:focus-visible { background: var(--tl-navy); color: var(--tl-yellow); border-color: var(--tl-navy); }
.count button[disabled] { opacity: 0.4; cursor: not-allowed; }
.booking .count input {
  width: 72px; min-height: 52px; flex: none;
  text-align: center;
  font-family: var(--font-display); font-weight: 600; font-size: 1.05rem;
  border: 1.5px solid var(--tl-line); border-radius: 11px;
  -moz-appearance: textfield;
}
.count input::-webkit-outer-spin-button,
.count input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Checkbox */
.booking .check {
  display: flex; gap: 12px; align-items: flex-start;
  cursor: pointer; font-size: 0.93rem; line-height: 1.5; margin-bottom: 14px;
  font-family: var(--font-body); font-weight: 600; color: var(--tl-navy);
}
.booking .field > label.check { margin-bottom: 0; }
.booking .check input {
  appearance: none; flex: none; width: 24px; height: 24px; margin: 0;
  border: 1.5px solid var(--tl-line); border-radius: 6px;
  background: var(--tl-white); cursor: pointer;
  display: grid; place-items: center;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.booking .check input:checked { background: var(--tl-navy); border-color: var(--tl-navy); }
.booking .check input:checked::after {
  content: ""; width: 11px; height: 6px;
  border-left: 2.4px solid var(--tl-yellow); border-bottom: 2.4px solid var(--tl-yellow);
  transform: rotate(-45deg) translate(1px, -1px);
}
.booking .check input:focus-visible { outline: 3px solid var(--tl-yellow); outline-offset: 2px; }
.booking .check a { color: var(--tl-navy); font-weight: 600; }
.booking .check small { font-weight: 600; }

/* Bedingte Feldgruppen.

   WICHTIG: das Verstecken hängt an html.js.
   Nur JavaScript setzt .is-on wieder. Ohne JavaScript wären diese Gruppen
   also DAUERHAFT unsichtbar — und weil buchung.php „Richtung" (Flughafen)
   und „Transportgut" (Kurier) für diese Kategorien verlangt, konnte man
   ohne JavaScript in diesen beiden Fällen überhaupt nicht buchen: der
   Server wies die Buchung ab und das Feld dazu war nirgends zu sehen.
   Ohne JavaScript stehen jetzt alle Gruppen offen; man füllt aus, was zur
   eigenen Fahrt passt. Das ist das Kitty-Prinzip „JS trägt nie den
   Kerninhalt", buchstäblich genommen. */
html.js .cond { display: none; }
html.js .cond.is-on { display: block; animation: tl-fade-in 200ms var(--ease); }
@keyframes tl-fade-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* Validierung */
.err {
  display: none;
  color: var(--tl-error-ink);
  font-size: 0.85rem; margin-top: 6px;
}
.err.is-on { display: block; }
/* Der Rahmen ist eine Kante, keine Schrift — hier steht der volle Wert.
   Die Rahmenbreite bleibt bei 1,5 px; kräftiger wird die Kante über einen
   inneren Schatten. Der Grund ist handfest: die Felder sind nicht
   randkastenbemessen, ein breiterer Rahmen hätte das Feld beim Fehler um
   2 px wachsen lassen und alles darunter verschoben. Ein Schatten kostet
   kein Layout. */
.booking :where(input, select, textarea)[aria-invalid="true"] {
  border-color: var(--tl-error);
  box-shadow: inset 0 0 0 1px var(--tl-error);
}

/* Bestätigung nach dem Absenden */
.done { display: none; text-align: center; padding: 26px 4px 8px; }
.done.is-on { display: block; }
.done__ico {
  width: 72px; height: 72px; border-radius: 50%;
  background: var(--tl-yellow); color: var(--tl-navy);
  display: grid; place-items: center; margin: 0 auto 20px;
}
.done__ico .ico { width: 34px; height: 34px; stroke-width: 2.6; }
.done h3 { font-size: 1.4rem; margin-bottom: 10px; }
.done p  { color: var(--tl-muted); max-width: 44ch; margin: 0 auto 20px; }

/* Server-Rückmeldung (Kitty's .form__status) im Modalfuß.
   Kitty färbt den Fehlerzustand in Softblau — er sah damit genauso aus wie
   eine neutrale Meldung. Eine fehlgeschlagene Buchung muss sich davon
   unterscheiden. */
.booking .form__status { margin: 0; }
.booking .form__status[data-state="error"] {
  border-inline-start-color: var(--tl-error);
  background: var(--tl-error-soft);
  color: var(--tl-navy);
}

/* Das hidden-Attribut ist nur ein Browser-Standardwert (display: none) und
   verliert gegen JEDE eigene display-Angabe, egal wie spezifisch. Nach einer
   erfolgreichen Buchung versteckt main.js die Formularteile über hidden —
   ohne diese Zeilen blieben der Absende-Knopf, der Eil-Kasten und die Zeilen
   mit Datum und Telefon stehen, und dieselbe Buchung ließe sich ein zweites
   Mal abschicken. Steht bewusst ganz am Ende des Abschnitts, damit es auch
   .cond.is-on und .done.is-on schlägt (gleiche Spezifität, spätere Zeile). */
.booking [hidden],
.booking__foot[hidden],
.booking-modal [hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .cond.is-on { animation: none; }
}


/* =============================================================================
   14  RECHTSTEXTE / INHALTSSEITEN
   ========================================================================== */
.page-hero { background: var(--tl-navy); color: var(--tl-white); padding-block: clamp(40px, 6vw, 72px); }
.page-hero h1 { color: var(--tl-white); font-size: clamp(2rem, 4.4vw, 3rem); }
.page-hero .lede { margin-top: 14px; }
.page-hero a { color: var(--tl-yellow); font-weight: 600; }

.prose { max-width: 74ch; }
.prose h2 { font-size: 1.5rem; margin: 40px 0 12px; }
.prose h3 { font-size: 1.15rem; margin: 28px 0 10px; }
.prose p, .prose li { font-size: 1rem; line-height: 1.7; color: var(--tl-navy); }
.prose p { margin: 0 0 14px; }
.prose ul, .prose ol { margin: 0 0 16px; padding-left: 22px; }
.prose li { margin-bottom: 6px; }
/* In der Datenschutzerklärung stehen ausgeschriebene Adressen, die länger
   sind als ein Handy breit ist. Ohne diese Zeile brechen sie nicht um und
   schieben die ganze Seite nach rechts — man konnte quer scrollen. */
.prose a { color: var(--tl-navy); font-weight: 600; text-decoration: underline; text-decoration-color: var(--tl-yellow); text-underline-offset: 0.18em; overflow-wrap: anywhere; }
.prose table { width: 100%; border-collapse: collapse; margin: 0 0 20px; font-size: 0.95rem; }
.prose th, .prose td { border: 1px solid var(--tl-line); padding: 10px 12px; text-align: left; vertical-align: top; }
.prose th { background: var(--tl-soft-2); font-family: var(--font-display); font-weight: 600; }
.prose__note {
  background: var(--tl-soft); border-radius: var(--radius-container);
  padding: 18px 22px; margin: 0 0 24px;
}
.prose__note p:last-child { margin-bottom: 0; }

/* =============================================================================
   15  BEWEGUNG — was sich bewegen darf und was nicht
   -----------------------------------------------------------------------------
   Die Seite soll ruhig stehen. Bewegung gibt es nur dort, wo sie etwas
   ERKLÄRT oder BEGLEITET: das Modal, das aufgeht; ein Feld, das nach einer
   Auswahl erscheint; ein Abschnitt, der beim Heranscrollen einmal aufblendet.
   Alles andere ist abgeschaltet.

   Wenn eine dieser Regeln wieder weg soll: einfach den jeweiligen Block hier
   löschen — die Foundation bringt das Verhalten dann von selbst zurück.
   ========================================================================== */

/* --- Aufblenden beim Heranscrollen ---------------------------------------
   Elemente mit data-appear starten leicht versetzt und blenden EINMAL auf,
   sobald sie ins Bild kommen. Danach bleiben sie stehen; beim Zurückscrollen
   passiert nichts mehr. Bewegt werden ausschließlich opacity und transform —
   beides kostet kein Layout, erzeugt also keinen Versatz und kann die
   Höhenmessung der Kopfzeile nicht anstoßen.

   Versteckt wird unter `.appear-on` — und diese Klasse setzt ausschließlich
   das Modul in main.js, als allererste Handlung. Das ist Absicht und der
   Kern der Sache:

   · Läuft main.js nicht (Netzfehler, Blocker, Fehler weiter oben), wird die
     Klasse nie gesetzt und NICHTS ist versteckt. Inhalt hängt damit unter
     keinen Umständen an JavaScript — Kitty-Prinzip, nicht Geschmackssache.
   · Ein Aufblitzen gibt es trotzdem nicht: was beim Start schon im Bild
     steht, bekommt im selben Arbeitsschritt sofort .is-in. Alles andere
     steht zu diesem Zeitpunkt unterhalb des Bildrands — dort sieht niemand,
     dass es kurz vorher noch sichtbar war.

   VORSICHT bei einer früheren Fassung: dort hing das Verstecken an `.js`
   (gesetzt im <head>) und eine CSS-„Notbremse" holte den Inhalt nach 2,5 s
   von selbst hervor. Das war falsch gedacht — die Notbremse lief ab dem
   Seitenaufbau und blendete nach 2,5 Sekunden ALLES auf einmal ein, auch
   ohne einen einzigen Scroll. Wer kurz auf der Seite verweilte, sah die
   ganze Animation auf einen Schlag. Nicht wieder einbauen. */
@media (prefers-reduced-motion: no-preference) {
  .appear-on [data-appear] {
    opacity: 0;
    transform: translateY(22px);
  }
  .appear-on [data-appear].is-in {
    opacity: 1;
    transform: none;
    /* Ruhig, nicht flink. 560 ms wirkten wie ein Zucken; auf dieser Länge
       liest sich die Bewegung als Heranschweben. */
    transition: opacity 1000ms var(--ease), transform 1000ms var(--ease);
    transition-delay: calc(var(--appear-i, 0) * 120ms);
  }
}

/* 1) Kein Einblenden des Seiteninhalts beim Laden.
      styles.css setzt `main { animation: kitty-fade-in 300ms both }`. Auf
      jeder Seite, bei jedem Klick, blendete der gesamte Inhalt auf. */
main { animation: none; }

/* 2) Kein Überblenden zwischen den Seiten.
      styles.css aktiviert `@view-transition { navigation: auto }`; Chrome und
      Safari kreuzblenden dann bei jedem Seitenwechsel. */
@view-transition { navigation: none; }

/* 3) Kein weiches Scrollen zu Ankern.
      Mit sticky Header wirkt das Gleiten zu #leistungen & Co. wie ein
      unerwartetes Wegrutschen der Seite. Der Sprung ist eindeutiger. */
html { scroll-behavior: auto; }

/* 4) Karten und Kacheln heben sich farblich hervor, nicht räumlich.
      (Regeln stehen bei den Komponenten; hier nur der Nachtrag für Kitty's
      eigene .card, falls sie später einmal benutzt wird.) */
a.card:hover, a.card:focus-visible { transform: none; }

/* 5) Das Icon in der Karte nickt — die Karte selbst nicht.
      Ein translateY auf .ride ließ beim Überstreichen der Maus alle elf
      Karten nacheinander hochspringen; deshalb steht die Karte fest. Das
      Icon ist klein, sitzt fest in seiner Ecke und kann nichts verschieben —
      dort darf die Seite freundlich sein. */
@media (prefers-reduced-motion: no-preference) {
  .ride__ico {
    transition: transform 220ms var(--ease), background-color var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
  }
  .ride:hover .ride__ico,
  .ride:focus-within .ride__ico {
    transform: translateY(-3px) scale(1.05) rotate(-3deg);
  }
}
.ride:hover .ride__ico,
.ride:focus-within .ride__ico {
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.3);
}
.services .ride:hover .ride__ico,
.services .ride:focus-within .ride__ico {
  background: var(--tl-navy-3);
  border-color: var(--tl-navy-3);
}

/* 6) Der Hero-Text blendet beim Laden auf — dieselbe Bewegung wie die
      Abschnitte weiter unten: 22 px tiefer starten, aufblenden, ankommen.
      Gleiche Wegstrecke, gleiche Kurve (--ease), gleicher Versatz von rund
      120 ms zwischen den Teilen.

      Der Unterschied zum Rest der Seite liegt nur im Auslöser: unten wartet
      ein Beobachter, bis etwas ins Bild scrollt. Der Hero steht beim Laden
      schon da, also gibt es nichts abzuwarten — reines CSS, kein Zustand.

      WICHTIG, die Überschrift bekommt KEINE Verzögerung.
      Sie ist mit hoher Wahrscheinlichkeit das Element, an dem Google die
      Ladezeit misst (Largest Contentful Paint). Elemente mit opacity: 0
      zählen dabei nicht — jede Verzögerung hier würde die gemessene Ladezeit
      um genau diesen Betrag verschlechtern, ohne dass die Seite langsamer
      wäre. Absatz und Knöpfe dürfen versetzt kommen, die Überschrift startet
      sofort.

      Fällt die Animation aus, steht der Text von Anfang an an seinem Platz:
      der Endzustand IST der normale Zustand. */
@media (prefers-reduced-motion: no-preference) {
  .hero-taxi h1,
  .hero-taxi__sub,
  .hero-taxi__actions {
    animation: tl-hero-auf 900ms var(--ease) both;
  }
  .hero-taxi__sub     { animation-delay: 130ms; }
  .hero-taxi__actions { animation-delay: 260ms; }
}
@keyframes tl-hero-auf {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

/* 6) Das Auto fährt einmal ins Bild.
      Reines CSS, keine Zeile JavaScript: eine Keyframe-Animation beim Laden.
      Das ist hier die ehrlichere Lösung als ein Beobachter — der Hero steht
      beim Laden ohnehin im Bild, es gibt nichts abzuwarten, und ohne Zustand
      kann sich auch nichts verstellen.

      Bewegt wird ausschließlich transform. Kein Layout, kein Versatz, keine
      Rückkopplung mit der Höhenmessung der Kopfzeile. Der Hero ist
      overflow: hidden, das Auto startet also außerhalb und wird bis dahin
      abgeschnitten — es blitzt nirgends am Bildrand auf.

      Die Neigung MUSS in den Keyframes mitstehen: eine Animation auf
      transform ersetzt die Eigenschaft komplett, ohne rotate() stünde das
      Auto am Ende gerade statt auf dem Schwung.

      Fällt die Animation aus (alte Browser, reduzierte Bewegung), steht das
      Auto einfach von Anfang an an seinem Platz — der Endzustand IST der
      normale Zustand. */
@media (prefers-reduced-motion: no-preference) {
  .hero-taxi__car {
    /* Dritter und letzter Anlauf bei der Kurve — die Begründung lohnt sich,
       damit niemand im Kreis läuft:
         cubic-bezier(0.16,1,0.3,1)  zu hart: sofort los, schlagartig Halt.
         ease-in                     zu zäh in der Mitte: nach der halben
                                     Zeit war erst ein Viertel des Weges
                                     geschafft, das Auto kroch und schnappte
                                     dann ins Ziel.
         ease-in-out                 genau die Mitte davon: weiche Enden,
                                     gleichmäßiges Tempo dazwischen. Nach der
                                     halben Zeit ist exakt der halbe Weg
                                     zurückgelegt.
       Dazu 100 ms kürzer, damit die Fahrt nicht steht. */
    animation: tl-auto-einfahrt 1100ms ease-in-out 220ms both;
  }
}
@keyframes tl-auto-einfahrt {
  from { transform: translateX(74%) rotate(var(--car-tilt)); }
  to   { transform: translateX(0)   rotate(var(--car-tilt)); }
}

/* Was bewusst BLEIBT:
     · [data-appear]            — Abschnitte blenden beim Heranscrollen auf
     · .booking-layer / .scrim  — das Modal fährt auf, das erklärt den Wechsel
     · .cond.is-on              — ein neu erschienenes Feld blendet kurz auf
     · .ride__ico               — das Icon nickt, wenn man die Karte berührt
     · .faq-cat summary::after  — der Pfeil dreht sich beim Auf- und Zuklappen
     · .button:active           — 1 px Tastendruck-Feedback
   Alle respektieren zusätzlich prefers-reduced-motion. */
