/*
Theme Name: BIKE ABK
Theme URI: https://bike-abk.at
Author: BIKE ABK
Author URI: https://bike-abk.at
Description: Eigenständiges Theme für Fahrradverkauf und Werkstatt-Service. Dark Theme mit Hi-Vis-Akzent, ohne Fremd-Theme, ohne Page-Builder und ohne externe Requests. Fonts werden lokal geladen, es werden keine Cookies gesetzt.
Version: 1.0.0
Requires at least: 6.4
Tested up to: 6.8
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: bike-abk
Tags: e-commerce, custom-menu, custom-colors, translation-ready, dark-mode
*/

/* ============================================================================
   BIKE ABK — BASIS
   ============================================================================
   Diese Datei enthält Design-Tokens, Fonts, Nav, Footer und alle gemeinsamen
   Komponenten. Seitenspezifische Abschnitte liegen in assets/css/pages.css.

   Farben und Schriften änderst du ausschließlich im :root-Block unten.

   FONTS: Die woff2-Dateien gehören nach assets/fonts/. Anleitung und
   Download-Quellen stehen in assets/fonts/README.txt.
   Es wird NIE von fonts.googleapis.com geladen — das würde die IP-Adresse
   jedes Besuchers ohne Einwilligung an Google übertragen und ist in AT/DE
   abmahnfähig (LG München I, 20.01.2022, 3 O 17493/20).
   Fehlen die Dateien, greift automatisch der Fallback-Stack: Layout bleibt
   intakt, nur die Schrift sieht anders aus.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   1. FONTS (lokal, Pfade relativ zu dieser Datei)
   --------------------------------------------------------------------------- */

@font-face {
  font-family: 'Space Grotesk Local';
  src: url('assets/fonts/space-grotesk-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk Local';
  src: url('assets/fonts/space-grotesk-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter Local';
  src: url('assets/fonts/inter-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter Local';
  src: url('assets/fonts/inter-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono Local';
  src: url('assets/fonts/ibm-plex-mono-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}


/* ---------------------------------------------------------------------------
   2. DESIGN-TOKENS — die einzige Stelle für Farben und Schriften
   --------------------------------------------------------------------------- */

:root {
  --th-ink: #0f1210;

  /*
   * Schriftfarbe auf HELLEN Flächen — Akzentfarbe, Paper, aktive Zustände.
   *
   * WARUM DAS EIN EIGENES TOKEN IST
   * Vorher stand an diesen 17 Stellen --th-ink. Dieselbe Variable ist im
   * Customizer aber als „Footer und tiefster Hintergrund" einstellbar. Wer den
   * Footer aufhellt, hätte damit unbemerkt die Schrift aller Primär-Buttons,
   * Filter, Kalendertage und Warenkorb-Zähler unlesbar gemacht — grün auf grün.
   *
   * Ein Hintergrund-Token und eine Schriftfarbe dürfen nicht dieselbe Variable
   * sein, auch wenn sie zufällig denselben Wert haben.
   */
  --th-on-accent: #0f1210;

  /*
   * KARTEN — gemeinsame Werte
   * ==========================================================================
   * Das Theme hat sechs Kartenvarianten: .th-card (Bento), .th-bike-card,
   * .th-post-card, .th-review-card, .th-value-card und .th-panel. Jede ist an
   * ihrem Ort richtig — eine Produktkarte braucht eine Bildfläche, ein Panel
   * nicht.
   *
   * WARUM SIE NICHT ZU EINER KLASSE ZUSAMMENGEFÜHRT SIND
   * Der naheliegende Schritt wäre, alle sechs durch eine Basisklasse mit
   * Modifikatoren zu ersetzen. Dagegen spricht das Verhältnis von Nutzen zu
   * Risiko: Es müssten sechs CSS-Blöcke und die Auszeichnung in acht Templates
   * gleichzeitig geändert werden — ohne dass sich am Ergebnis etwas sieht. Genau
   * solche Umbauten brechen Layouts an Stellen, die man erst Wochen später
   * bemerkt.
   *
   * Das eigentliche Ziel war ein anderes: „Kartendesign einmal ändern statt
   * sechsmal." Das leisten diese Tokens. Wer die Kartenfläche, den Innenabstand
   * oder die Rahmenfarbe ändern will, ändert hier eine Zeile — und alle sechs
   * Varianten folgen. Die Klassennamen bleiben, wo sie sind.
   */
  --th-card-bg: #1c2020;
  --th-card-pad: 30px;
  --th-card-border: rgba(236, 233, 222, 0.14);
  --th-card-gap: 2px;

  /*
   * Größe der Kleinbeschriftungen — Kategorien, Kennzahlen-Labels, Brotkrumen.
   *
   * 0.72rem sind bei 16px Grundgröße etwa 11,5 Pixel. Das ist die untere Grenze
   * des Lesbaren, besonders in Versalien und auf dem Handy. Erhöhen auf 0.78rem
   * ist spürbar angenehmer; ich habe es nicht von mir aus geändert, weil an
   * mehreren Stellen der Platz knapp bemessen ist und ich das Ergebnis hier nicht
   * sehen kann. Wer es probieren will, ändert diese eine Zeile.
   */
  --th-label-size: 0.72rem;
  --th-graphite: #14171a;
  --th-graphite-2: #1c2020;
  --th-hivis: #c8ff3d;
  --th-hivis-bright: #d8ff70;
  --th-rust: #b54a2c;
  --th-paper: #ece9de;
  --th-paper-2: #d8d5c8;
  --th-paper-3: #cfccc0;
  --th-stone: #8f8c80;
  --th-error: #ff8a6b;
  --th-line: rgba(236, 233, 222, 0.14);

  --th-font-body: 'Inter Local', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  --th-font-disp: 'Space Grotesk Local', 'Inter Local', system-ui, 'Segoe UI', Arial, sans-serif;
  --th-font-mono: 'IBM Plex Mono Local', ui-monospace, 'Cascadia Mono', Consolas, 'Courier New', monospace;

  --th-gutter: 6vw;
  --th-gutter-mobile: 24px;
  --th-nav-height: 73px;
}


/* ---------------------------------------------------------------------------
   3. RESET UND GRUNDLAGEN
   --------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--th-font-body);
  font-size: 16px;
  line-height: 1.6;
  color: var(--th-paper);
  background: var(--th-graphite);
  overflow-x: hidden;
}

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

a { color: var(--th-hivis); }

h1, h2, h3, h4 {
  font-family: var(--th-font-disp);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.disp { font-family: var(--th-font-disp); font-weight: 700; letter-spacing: -0.02em; }
.mono { font-family: var(--th-font-mono); letter-spacing: 0.08em; text-transform: uppercase; }

/* Sichtbarer Fokus-Ring. Pflicht für Tastaturbedienung (WCAG 2.4.7) und ab 2025
   für Onlineshops über den European Accessibility Act relevant. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--th-hivis);
  outline-offset: 3px;
}

/* Skip-Link für Screenreader und Tastaturnutzer */
.th-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  padding: 12px 20px;
  background: var(--th-hivis);
  color: var(--th-on-accent);
  font-family: var(--th-font-disp);
  font-weight: 600;
  text-decoration: none;
}
.th-skip-link:focus { left: 0; }

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

/*
 * Hinweis zum Container: Den seitlichen Abstand liefern die Abschnitte selbst
 * über --th-gutter (.th-section, .th-page-body, .th-hero, .th-footer). Eine
 * zusätzliche Wrapper-Klasse gibt es absichtlich nicht — sie war vorhanden,
 * wurde aber von keinem Template genutzt und ist entfernt.
 */


/* ---------------------------------------------------------------------------
   4. BUTTONS
   --------------------------------------------------------------------------- */

.th-btn {
  font-family: var(--th-font-disp);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 15px 28px;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease, border-color 0.2s ease;
}
.th-btn--primary {
  background: var(--th-hivis);
  color: var(--th-on-accent);
  border-color: var(--th-hivis);
}
.th-btn--primary:hover { transform: translateY(-2px); background: var(--th-hivis-bright); }
.th-btn--ghost {
  background: transparent;
  color: var(--th-paper);
  border-color: var(--th-line);
}
.th-btn--ghost:hover { border-color: var(--th-paper); transform: translateY(-2px); }
.th-btn--block { width: 100%; }
.th-btn[disabled] { opacity: 0.45; cursor: not-allowed; transform: none; }


/* ---------------------------------------------------------------------------
   5. NAVIGATION
   --------------------------------------------------------------------------- */

.th-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 16px var(--th-gutter);
  background: rgba(15, 18, 16, 0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--th-line);
}
.th-nav-logo {
  font-family: var(--th-font-disp);
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--th-paper);
  text-decoration: none;
  white-space: nowrap;
  letter-spacing: -0.02em;
}

/*
 * Hochgeladenes Logo.
 *
 * Diese Grundwerte greifen, bevor jemand etwas einstellt — sonst würde ein
 * 1200 Pixel breites Logo die Navigation auseinanderziehen und den Burger vom
 * Bildschirm schieben. Höhe und Breite lassen sich unter
 * Design → Anpassen → Website-Informationen anpassen; die Angaben von dort
 * werden hinter diesem Stylesheet ergänzt und gewinnen dadurch.
 *
 * object-fit: contain hält die Proportionen — auch dann, wenn Höhe und Breite
 * zusammen nicht zum Seitenverhältnis der Datei passen. Das Logo wird dann
 * kleiner dargestellt, aber nie verzerrt.
 *
 * max-width in vw als zweite Grenze: Auf einem schmalen Bildschirm zählt nicht
 * die eingestellte Breite, sondern der verfügbare Platz neben dem Burger.
 */
.th-nav-logo img {
  display: block;
  height: 40px;
  width: auto;
  max-width: min(220px, 46vw);
  object-fit: contain;
}
.th-nav-logo .custom-logo-link { display: block; line-height: 0; }
.th-nav-links {
  display: flex;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1;
  justify-content: center;
}
.th-nav-links a {
  display: inline-block;
  font-size: 0.84rem;
  color: var(--th-paper);
  text-decoration: none;
  border: 1px solid var(--th-line);
  border-radius: 22px;
  padding: 9px 18px;
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.th-nav-links a:hover { border-color: var(--th-hivis); color: var(--th-hivis); }
.th-nav-links .current-menu-item > a,
.th-nav-links .current_page_item > a {
  background: var(--th-hivis);
  border-color: var(--th-hivis);
  color: var(--th-on-accent);
  font-weight: 500;
}

.th-nav-actions { display: flex; align-items: center; gap: 10px; }

.th-nav-icon-btn {
  position: relative;
  width: 40px; height: 40px;
  border: 1px solid var(--th-line);
  border-radius: 50%;
  background: transparent;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: border-color 0.2s ease;
  text-decoration: none;
}
.th-nav-icon-btn:hover { border-color: var(--th-hivis); }
.th-nav-icon-btn svg {
  width: 18px; height: 18px;
  stroke: var(--th-paper); fill: none; stroke-width: 1.6;
  transition: stroke 0.2s ease;
}
.th-nav-icon-btn:hover svg { stroke: var(--th-hivis); }

/* ---------------------------------------------------------------------------
   SAISONHINWEIS
   ---------------------------------------------------------------------------
   Über der Navigation, in der Akzentfarbe. Auffällig genug, um gesehen zu werden,
   und flach genug, um nicht zu drängen — ein Streifen, kein Banner.

   Beim Drucken fällt er weg, siehe den Druckabschnitt am Ende der Datei.
   --------------------------------------------------------------------------- */

.th-season {
  background: var(--th-hivis);
  color: var(--th-on-accent);
  text-align: center;
  padding: 10px var(--th-gutter-mobile);
  font-family: var(--th-font-disp);
  font-weight: 600;
  font-size: 0.88rem;
  line-height: 1.4;
}
.th-season a {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  gap: 8px;
  align-items: center;
}
.th-season a:hover { text-decoration: underline; }
.th-season a:focus-visible { outline: 2px solid var(--th-on-accent); outline-offset: 3px; }

/*
 * Anruf-Knopf. Bewusst in der Akzentfarbe und damit auffälliger als Konto und
 * Warenkorb: Bei einem Werkstattbetrieb ist der Anruf die wichtigste Handlung
 * auf der ganzen Seite, nicht der Kauf.
 *
 * Mindesthöhe 40 Pixel wie die Nachbarn — über der Mindestgröße von 24 × 24 für
 * Klickziele (WCAG 2.5.8) und auf dem Handy zuverlässig zu treffen.
 */
.th-nav-call {
  display: flex; align-items: center; gap: 8px;
  height: 40px;
  padding: 0 15px;
  border-radius: 22px;
  border: 1px solid var(--th-hivis);
  color: var(--th-hivis);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.2s ease, color 0.2s ease;
}
.th-nav-call svg { width: 18px; height: 18px; stroke: currentColor; fill: none; }
.th-nav-call-label { font-family: var(--th-font-disp); font-weight: 600; font-size: 0.85rem; }
.th-nav-call:hover,
.th-nav-call:focus-visible { background: var(--th-hivis); color: var(--th-on-accent); }

@media (max-width: 900px) {
  /* Auf schmalen Bildschirmen nur das Symbol — der Platz ist für Menü und
     Warenkorb nötiger, und angerufen wird ohnehin per Antippen. */
  .th-nav-call { padding: 0; width: 40px; justify-content: center; }
  .th-nav-call-label { display: none; }
}

.th-login-btn {
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--th-line);
  border-radius: 22px;
  padding: 0 16px 0 6px;
  height: 40px;
  background: transparent;
  cursor: pointer;
  transition: border-color 0.2s ease;
}
.th-login-btn:hover { border-color: var(--th-hivis); }
.th-login-btn span { font-size: 0.85rem; color: var(--th-paper); }
.th-login-btn svg { width: 18px; height: 18px; stroke: var(--th-paper); fill: none; stroke-width: 1.6; }

@media (max-width: 700px) {
  .th-login-btn span { display: none; }
  .th-login-btn { width: 40px; padding: 0; justify-content: center; }
}

.th-cart-badge {
  position: absolute;
  top: -5px; right: -5px;
  min-width: 17px; height: 17px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--th-hivis);
  color: var(--th-on-accent);
  font-family: var(--th-font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}

/* Dropdowns (Konto, Warenkorb) */
.th-dropdown-wrap { position: relative; }
.th-dropdown {
  position: absolute;
  top: 52px; right: 0;
  width: 280px;
  background: var(--th-graphite-2);
  border: 1px solid var(--th-line);
  padding: 22px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
  z-index: 60;
}
.th-dropdown.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
.th-dropdown h4 { font-size: 0.95rem; margin: 0 0 6px; }
.th-dropdown p { font-size: 0.84rem; color: var(--th-paper-3); line-height: 1.5; margin: 0 0 16px; }
.th-dropdown .th-btn { width: 100%; font-size: 0.9rem; padding: 12px 20px; }
.th-dropdown-link {
  font-size: 0.76rem;
  color: var(--th-stone);
  text-decoration: none;
  display: block;
  text-align: center;
  margin-top: 12px;
}
.th-dropdown-link:hover { color: var(--th-paper); }

/* Mini-Warenkorb */
.th-mini-cart-list { list-style: none; margin: 0 0 16px; padding: 0; }
.th-mini-cart-list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.82rem;
  padding: 8px 0;
  border-bottom: 1px solid var(--th-line);
}
.th-mini-cart-list li span:last-child { font-family: var(--th-font-mono); white-space: nowrap; }
.th-mini-cart-total {
  display: flex;
  justify-content: space-between;
  font-size: 0.88rem;
  margin-bottom: 16px;
  padding-top: 4px;
}
.th-mini-cart-total strong { font-family: var(--th-font-disp); color: var(--th-hivis); }


/* ---------------------------------------------------------------------------
   6. MOBILES BURGER-MENÜ
   Ersetzt das, wofür man sonst ein Theme wie Astra oder ein Extra-Plugin
   bräuchte. Reines CSS/JS, keine Abhängigkeit.
   --------------------------------------------------------------------------- */

.th-burger {
  display: none;
  width: 40px; height: 40px;
  border: 1px solid var(--th-line);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  padding: 0;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 4px;
  transition: border-color 0.2s ease;
}
.th-burger:hover { border-color: var(--th-hivis); }
.th-burger span {
  display: block;
  width: 17px; height: 1.5px;
  background: var(--th-paper);
  transition: transform 0.25s ease, opacity 0.2s ease;
}
.th-burger.is-open span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.th-burger.is-open span:nth-child(2) { opacity: 0; }
.th-burger.is-open span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

.th-mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--th-ink);
  padding: 84px var(--th-gutter-mobile) 40px;
  display: flex;
  flex-direction: column;
  gap: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
  overflow-y: auto;
}
.th-mobile-menu.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
.th-mobile-menu ul { list-style: none; margin: 0; padding: 0; }
.th-mobile-menu a {
  display: block;
  font-family: var(--th-font-disp);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--th-paper);
  text-decoration: none;
  padding: 16px 0;
  border-bottom: 1px solid var(--th-line);
}
.th-mobile-menu a:hover { color: var(--th-hivis); }
.th-mobile-close {
  position: absolute;
  top: 18px; right: var(--th-gutter-mobile);
  width: 40px; height: 40px;
  border: 1px solid var(--th-line);
  border-radius: 50%;
  background: transparent;
  color: var(--th-paper);
  font-size: 1.1rem;
  cursor: pointer;
}
.th-mobile-close:hover { border-color: var(--th-hivis); color: var(--th-hivis); }
.th-mobile-contact {
  margin-top: auto;
  padding-top: 30px;
  font-size: 0.85rem;
  color: var(--th-stone);
}
.th-mobile-contact a {
  font-family: var(--th-font-body);
  font-weight: 400;
  font-size: 0.95rem;
  border: none;
  padding: 4px 0;
  color: var(--th-paper-2);
}

@media (max-width: 760px) {
  .th-nav-links { display: none; }
  .th-burger { display: flex; }
}
@media (min-width: 761px) {
  .th-mobile-menu { display: none; }
}
body.th-menu-open { overflow: hidden; }


/* ---------------------------------------------------------------------------
   7. SECTION-BAUSTEINE
   --------------------------------------------------------------------------- */

.th-section {
  padding: 80px var(--th-gutter);
  border-top: 1px solid var(--th-line);
}
.th-section--flush { border-top: none; }
.th-section--ink { background: var(--th-ink); }

.th-section-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 18px;
  margin-bottom: 40px;
}
.th-section-head h2 { font-size: clamp(1.7rem, 3vw, 2.4rem); margin: 0; }

.th-tag {
  font-family: var(--th-font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.68rem;
  color: var(--th-hivis);
  margin-bottom: 14px;
  display: block;
}

.th-lead {
  font-size: clamp(1rem, 1.6vw, 1.2rem);
  line-height: 1.55;
  color: var(--th-paper-2);
  max-width: 46ch;
}

@media (max-width: 700px) {
  .th-section { padding-left: var(--th-gutter-mobile); padding-right: var(--th-gutter-mobile); }
}


/* ---------------------------------------------------------------------------
   8. PREISLISTE
   --------------------------------------------------------------------------- */

.th-price-list { border-top: 1px solid var(--th-line); max-width: 820px; }
.th-price-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--th-line);
}
.th-price-row .th-price-service { font-size: 1rem; }
.th-price-row .th-price-service span {
  display: block;
  font-size: 0.78rem;
  color: var(--th-stone);
  margin-top: 4px;
}
.th-price-row .th-price-value {
  font-family: var(--th-font-disp);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--th-hivis);
  white-space: nowrap;
}

/* Pflichthinweise unter Preisen, Bewertungen etc. */
.th-note {
  font-size: 0.76rem;
  color: var(--th-stone);
  line-height: 1.6;
  margin-top: 18px;
  max-width: 820px;
}
.th-note a { color: var(--th-stone); text-decoration: underline; }


/* ---------------------------------------------------------------------------
   9. FORMULARE inkl. DSGVO-Consent
   --------------------------------------------------------------------------- */

.th-form-row { margin-bottom: 18px; }
.th-form-row--2col { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.th-form-row label {
  display: block;
  font-family: var(--th-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--th-stone);
  margin-bottom: 6px;
}
/*
 * Feldtypen einzeln aufzählen, damit Kontrollkästchen und Knöpfe nicht
 * mitgestaltet werden. Dabei fehlten „search", „date" und „url" — search auf der
 * 404-Seite und in der Suche, date als Rückfallfeld im Terminformular, wenn der
 * eigene Kalender nicht läuft. Diese Felder standen dadurch unformatiert in
 * einem sonst durchgestalteten Formular.
 */
.th-form-row input[type="text"],
.th-form-row input[type="email"],
.th-form-row input[type="tel"],
.th-form-row input[type="number"],
.th-form-row input[type="search"],
.th-form-row input[type="date"],
.th-form-row input[type="url"],
.th-form-row select,
.th-form-row textarea {
  width: 100%;
  background: var(--th-ink);
  border: 1px solid var(--th-line);
  color: var(--th-paper);
  padding: 11px 13px;
  font-family: var(--th-font-body);
  font-size: 0.9rem;
}
.th-form-row textarea { resize: vertical; min-height: 90px; }

/* Suchfeld und Knopf nebeneinander. Der Knopf schrumpft nicht mit (flex: none),
   sonst würde bei „Suchen" mitten im Wort umgebrochen. */
.th-search-field { display: flex; gap: 10px; }
.th-search-field input[type="search"] { flex: 1 1 auto; min-width: 0; }
.th-search-field .th-btn { flex: none; padding-top: 0; padding-bottom: 0; }

@media (max-width: 480px) {
  /* Nebeneinander bleibt für Feld und Knopf zu eng — untereinander mit einem
     Knopf über die volle Breite ist auf dem Handy besser zu treffen. */
  .th-search-field { flex-direction: column; }
  .th-search-field .th-btn { padding-top: 13px; padding-bottom: 13px; }
}
.th-form-row input:focus, .th-form-row select:focus, .th-form-row textarea:focus {
  outline: none;
  border-color: var(--th-hivis);
}
.th-form-row input[aria-invalid="true"],
.th-form-row select[aria-invalid="true"],
.th-form-row textarea[aria-invalid="true"] { border-color: var(--th-error); }

/* Consent-Checkbox.
   RECHT: niemals mit "checked" vorbelegen — ein vorausgewähltes Häkchen ist
   keine wirksame Einwilligung (EuGH C-673/17, Planet49). */
.th-consent {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 6px 0 8px;
}
.th-consent input[type="checkbox"] {
  flex: none;
  width: 18px; height: 18px;
  margin-top: 2px;
  accent-color: var(--th-hivis);
  cursor: pointer;
}
.th-consent label {
  font-family: var(--th-font-body);
  font-size: 0.82rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--th-paper-3);
  line-height: 1.5;
  margin: 0;
}
.th-consent label a { color: var(--th-hivis); text-decoration: underline; }


/* ---------------------------------------------------------------------------
   STERNE ALS EINGABE
   ---------------------------------------------------------------------------
   Fünf Optionsfelder, die wie Sterne aussehen. Bewusst kein JavaScript-Widget:

   Die Optionsfelder bleiben echte Optionsfelder. Damit funktioniert die Auswahl
   mit der Tastatur (Pfeiltasten innerhalb der Gruppe), ein Screenreader liest
   „1 Stern" bis „5 Sterne" statt fünfmal dasselbe Symbol, das Formular sendet
   auch ohne JavaScript, und die Pflichtprüfung des Browsers greift von selbst.

   Ein nachgebautes Widget aus <span>-Elementen kann das alles nicht, ohne es
   Stück für Stück von Hand nachzurüsten — und genau daran scheitern die meisten.

   DIE FÜLLUNG BIS ZUM GEWÄHLTEN STERN
   Bei Bewertungen sollen alle Sterne BIS zum gewählten leuchten, nicht nur der
   eine. Im Quelltext steht 1 zuerst, gefüllt werden müssten also die
   VORHERGEHENDEN Geschwister — und dafür gibt es in CSS keinen Selektor.
   Der übliche Trick ist, die Reihenfolge im Quelltext umzudrehen; dann läge sie
   aber auch für Tastatur und Screenreader verdreht vor (5, 4, 3 …).

   Deshalb :has() am Container. Fünf Regeln statt eines Tricks, dafür bleibt die
   Reihenfolge im Quelltext richtig. Kennt ein Browser :has() nicht, greift die
   Regel darunter: Dann leuchtet nur der gewählte Stern. Weniger schön, aber
   vollständig benutzbar — die Auswahl ist sichtbar, und darauf kommt es an.
   --------------------------------------------------------------------------- */

.th-rate { border: none; padding: 0; margin: 0 0 18px; }
.th-rate legend {
  font-family: var(--th-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--th-stone);
  padding: 0;
  margin-bottom: 8px;
}

.th-rate-stars { display: flex; gap: 4px; }

/*
 * Das Optionsfeld selbst wird nicht ausgeblendet (display: none würde es aus der
 * Tastaturreihenfolge nehmen), sondern hinter den Stern gelegt. Der Fokusrahmen
 * erscheint dadurch am Stern, nicht an einer unsichtbaren Stelle daneben.
 */
.th-rate-stars input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

.th-rate-stars label {
  /* 2.5rem statt em: em würde sich auf die eigene Schriftgröße beziehen und
     wäre in einem Kontext mit font-size: 0 wirkungslos. */
  font-size: 2.5rem;
  line-height: 1;
  color: var(--th-line);
  cursor: pointer;
  margin: 0;
  padding: 0 2px;
  transition: color 0.15s ease;
}
.th-rate-stars label:hover { color: var(--th-paper-3); }

/* Rückfall ohne :has(): nur der gewählte Stern leuchtet. */
.th-rate-stars input:checked + label { color: var(--th-hivis); }

/* Fokus muss sichtbar sein, auch wenn das Feld selbst unsichtbar ist (WCAG 2.4.7). */
.th-rate-stars input:focus-visible + label {
  outline: 2px solid var(--th-hivis);
  outline-offset: 3px;
}

/* Mit :has(): alle Sterne bis zum gewählten. */
.th-rate-stars:has(input[value="1"]:checked) label[for="th-rate-1"],
.th-rate-stars:has(input[value="2"]:checked) label[for="th-rate-1"],
.th-rate-stars:has(input[value="2"]:checked) label[for="th-rate-2"],
.th-rate-stars:has(input[value="3"]:checked) label[for="th-rate-1"],
.th-rate-stars:has(input[value="3"]:checked) label[for="th-rate-2"],
.th-rate-stars:has(input[value="3"]:checked) label[for="th-rate-3"],
.th-rate-stars:has(input[value="4"]:checked) label[for="th-rate-1"],
.th-rate-stars:has(input[value="4"]:checked) label[for="th-rate-2"],
.th-rate-stars:has(input[value="4"]:checked) label[for="th-rate-3"],
.th-rate-stars:has(input[value="4"]:checked) label[for="th-rate-4"],
.th-rate-stars:has(input[value="5"]:checked) label[for="th-rate-1"],
.th-rate-stars:has(input[value="5"]:checked) label[for="th-rate-2"],
.th-rate-stars:has(input[value="5"]:checked) label[for="th-rate-3"],
.th-rate-stars:has(input[value="5"]:checked) label[for="th-rate-4"],
.th-rate-stars:has(input[value="5"]:checked) label[for="th-rate-5"] {
  color: var(--th-hivis);
}

/*
 * Unsichtbare Sprungmarke.
 *
 * scroll-margin-top ist hier der eigentliche Zweck: Die Navigation klebt oben am
 * Bildschirm. Ohne diesen Abstand scrollt der Browser das Ziel exakt an den
 * oberen Rand — also unter die Navigationsleiste, wo es verdeckt ist. Der Sprung
 * funktioniert dann scheinbar nicht.
 */
.th-anchor {
  display: block;
  height: 0;
  scroll-margin-top: 120px;
}

/*
 * Die Auftragsnummer in der Erfolgsmeldung. Als eigener Block abgesetzt, nicht
 * im Fließtext: Sie ist das Einzige in dieser Meldung, das der Kunde abschreiben
 * muss, und darf deshalb nicht wie ein Nebensatz aussehen.
 */
.th-job-handover {
  display: block;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--th-line);
}
.th-job-handover-label {
  display: block;
  font-family: var(--th-font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--th-stone);
  margin-bottom: 4px;
}
.th-job-handover code {
  font-family: var(--th-font-mono);
  font-size: 1.35rem;
  letter-spacing: 0.14em;
  color: var(--th-hivis);
  background: none;
  padding: 0;
}
.th-job-handover-hint {
  display: block;
  margin-top: 6px;
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--th-paper-3);
}

.th-feedback-own blockquote {
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--th-paper-2);
  border-left: 2px solid var(--th-line);
  padding-left: 14px;
}

/* Art.-13-Kurzinfo über dem Absenden-Button */
.th-privacy-note {
  font-size: 0.76rem;
  color: var(--th-stone);
  line-height: 1.6;
  margin: 0 0 22px;
  padding: 14px 16px;
  border-left: 2px solid var(--th-line);
}
.th-privacy-note a { color: var(--th-stone); text-decoration: underline; }

.th-field-error {
  display: none;
  font-family: var(--th-font-body);
  font-size: 0.76rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--th-error);
  margin: 5px 0 0;
}
.th-field-error.is-visible { display: block; }

/* Serverseitige Sammelmeldung */
.th-form-notice {
  padding: 16px 18px;
  margin-bottom: 24px;
  font-size: 0.88rem;
  line-height: 1.5;
  border-left: 3px solid var(--th-error);
  background: rgba(255, 138, 107, 0.07);
}
.th-form-notice--ok {
  border-left-color: var(--th-hivis);
  background: rgba(200, 255, 61, 0.07);
}
.th-form-notice ul { margin: 8px 0 0; padding-left: 20px; }

/* ---------------------------------------------------------------------------
   POPUP-FENSTER
   ---------------------------------------------------------------------------
   Auf dem <dialog>-Element aufgebaut. Fokus-Falle, Escape und das Ausblenden
   des Hintergrunds für Screenreader übernimmt der Browser — deshalb steht hier
   nur das Aussehen.
   --------------------------------------------------------------------------- */

.th-modal {
  width: min(680px, calc(100vw - 32px));
  max-height: min(88vh, 900px);
  padding: 0;
  border: 1px solid var(--th-line);
  border-radius: 0;
  background: var(--th-graphite-2);
  color: var(--th-paper);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
  overflow: hidden;
}

/* Ein geschlossenes <dialog> ist von sich aus unsichtbar. Nur beim geöffneten
   brauchen wir Flexbox, damit der Kopf stehen bleibt und der Inhalt scrollt. */
.th-modal[open] {
  display: flex;
  flex-direction: column;
}

.th-modal::backdrop {
  background: rgba(9, 11, 10, 0.78);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

/*
 * Der Rahmen im Popup. Höhe kommt vom <dialog>, nicht von hier.
 *
 * Vorher stand max-height: inherit — der Wert des Elternteils also nochmals als
 * eigene Grenze. Das geht nur gut, solange das <dialog> selbst nicht größer als
 * der Bildschirm ist. Sobald es das war, hatte der Kopf mit dem Schließen-Knopf
 * keine Höhengrenze mehr und wurde oben abgeschnitten.
 *
 * Belastbar ist flex: 1 1 auto zusammen mit min-height: 0. Der Rahmen nimmt die
 * Höhe seines Inhalts und schrumpft, sobald das <dialog> seine Grenze erreicht —
 * dann scrollt der Body darin. min-height: 0 ist dafür nötig, weil ein
 * Flex-Element von sich aus nicht unter seinen Inhalt schrumpft; ohne das würde
 * der Body überlaufen statt zu scrollen.
 *
 * Bewusst nicht die Kurzform flex: 1. Die bedeutet flex-basis: 0, und in einem
 * senkrechten Flex-Container ohne feste Höhe kann der Rahmen damit auf null
 * zusammenfallen — das Popup wäre leer. Mit basis: auto kann das nicht passieren.
 */
.th-modal-inner {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.th-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 28px 30px 20px;
  border-bottom: 1px solid var(--th-line);
  flex: none;
}
.th-modal-head h2 {
  margin: 0;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
}
.th-modal-head .th-tag { margin-bottom: 8px; }

.th-modal-close {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--th-line);
  background: var(--th-ink);
  color: var(--th-paper);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.th-modal-close:hover { border-color: var(--th-hivis); color: var(--th-hivis); }

.th-modal-body {
  padding: 26px 30px 30px;
  overflow-y: auto;
  /* Auf Touchgeräten weiterscrollen, wenn das Ende erreicht ist, unterdrücken */
  overscroll-behavior: contain;
}

/* Das Formular sitzt schon im Popup — sein eigener Rahmen wäre ein Rahmen im
   Rahmen. */
.th-modal-body .th-panel {
  background: none;
  border: none;
  padding: 0;
  max-width: none;
}

/* Der Kalender darf aus dem Popup nicht herausragen; im Popup klappt er
   deshalb im Fluss auf statt darüber. */
.th-modal-body .th-datepick-panel {
  position: static;
  width: 100%;
  margin-top: 8px;
  box-shadow: none;
}

/* Hintergrund nicht mitscrollen lassen, solange das Popup offen ist. */
/*
 * Seite hinter dem Popup festhalten.
 *
 * position: fixed statt nur overflow: hidden, weil Safari auf iOS ein
 * overflow: hidden am body ignoriert — die Seite scrollte dort hinter dem Popup
 * weiter, und nach dem Schließen stand man an einer anderen Stelle. Genau das
 * fühlt sich an, als würde das Fenster hängen.
 *
 * Den nötigen Versatz nach oben setzt bike-abk.js, sonst springt die Seite beim
 * Öffnen an den Anfang. Beim Schließen wird die alte Position wiederhergestellt.
 */
body.th-modal-open {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}

@media (max-width: 600px) {
  /*
   * Auf dem Handy als Blatt vom unteren Rand statt bildschirmfüllend.
   *
   * Vorher stand hier height: 100vh. Drei Probleme auf einmal:
   *
   *   1. 100vh ist auf Handys NICHT die sichtbare Höhe. Die Adressleiste zählt
   *      mit, das Fenster war also höher als der Bildschirm. Ein <dialog> wird
   *      per margin: auto zentriert — wenn es nicht passt, wandert der obere
   *      Rand aus dem Bild. Dort saß der Schließen-Knopf. Deshalb ließ sich das
   *      Fenster nicht schließen.
   *   2. 100vw rechnet eine etwaige Bildlaufleiste mit und ergab waagrechtes
   *      Überlaufen.
   *   3. Bildschirmfüllend gab es keinen Hintergrund zum Antippen — der zweite
   *      übliche Weg zum Schließen fiel damit auch weg.
   *
   * Jetzt: unten angedockt über inset, margin: 0, und höchstens 92 % der
   * WIRKLICH sichtbaren Höhe. Oben bleibt ein Streifen Hintergrund sichtbar —
   * antippen schließt. Der Kopf mit dem Knopf ist immer im Bild.
   */
  .th-modal {
    inset: auto 0 0 0;
    margin: 0;
    width: auto;
    max-width: none;
    height: auto;
    /* Rückfallwert für Browser ohne dvh, danach der genaue Wert. */
    max-height: 92vh;
    max-height: 92dvh;
    border-width: 1px 0 0;
  }
  .th-modal-head { padding: 20px 20px 16px; }
  .th-modal-body { padding: 20px 20px calc(20px + env(safe-area-inset-bottom)); }
}


/* ---------------------------------------------------------------------------
   COOKIE-HINWEIS
   ---------------------------------------------------------------------------
   Als Leiste am unteren Rand, nicht als Fenster über der Seite. Ein Overlay,
   das die Seite blockiert, bis man klickt, ist eine Cookie-Wall — die
   Einwilligung wäre dann nicht freiwillig (Art. 4 Z 11 DSGVO). Die Seite bleibt
   hier vollständig lesbar und bedienbar, auch ohne Antwort.
   --------------------------------------------------------------------------- */

.th-cookie {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 60; /* über der Navigation (50), unter dem Popup */
  background: var(--th-graphite-2);
  border-top: 1px solid var(--th-line);
  box-shadow: 0 -18px 48px rgba(0, 0, 0, 0.5);
  padding: 22px var(--th-gutter) calc(22px + env(safe-area-inset-bottom));
}
.th-cookie[hidden] { display: none; }

.th-cookie-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  flex-wrap: wrap;
}

.th-cookie-copy { flex: 1 1 460px; }
.th-cookie h2 { margin: 0 0 6px; font-size: 1.05rem; }
.th-cookie p {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--th-paper-3);
  max-width: 78ch;
}
.th-cookie a { color: var(--th-hivis); }

.th-cookie-actions { display: flex; gap: 12px; flex: none; }

/*
 * Beide Knöpfe absichtlich identisch: gleiche Größe, gleiche Schrift, gleiche
 * Farbe. Ein blasses „Ablehnen" neben einem leuchtenden „Zustimmen" gilt als
 * unzulässige Beeinflussung — die Einwilligung wäre dann nicht freiwillig.
 * Bitte nicht "verschönern", indem einer davon hervorgehoben wird.
 */
.th-cookie-btn {
  font-family: var(--th-font-disp);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 13px 26px;
  min-width: 140px;
  border: 1px solid var(--th-paper);
  background: transparent;
  color: var(--th-paper);
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.th-cookie-btn:hover {
  background: var(--th-paper);
  color: var(--th-on-accent);
}

/* Der WhatsApp-Knopf sitzt fest unten rechts, also genau über den Knöpfen des
   Banners — und mit z-index 80 darüber. Solange der Banner offen ist, tritt er
   zurück. Ihn stattdessen nach oben zu schieben hieße, die Höhe des Banners zu
   raten; die hängt von Textlänge und Bildschirmbreite ab. */
.th-cookie-visible .th-whatsapp-fab { display: none; }

@media (max-width: 700px) {
  .th-cookie { padding-left: var(--th-gutter-mobile); padding-right: var(--th-gutter-mobile); }
  .th-cookie-inner { gap: 18px; }
  .th-cookie-actions { width: 100%; }
  /* Beide gleich breit — auch hier darf keiner bevorzugt wirken. */
  .th-cookie-btn { flex: 1 1 0; min-width: 0; padding: 14px 12px; }
}


/* ---------------------------------------------------------------------------
   TERMINKALENDER
   ---------------------------------------------------------------------------
   Wird über einen Knopf geöffnet. Das native Datumsfeld bleibt im Markup und
   wird nur versteckt, wenn das JavaScript läuft — ohne JavaScript ist es also
   weiterhin bedienbar.
   --------------------------------------------------------------------------- */

.th-datepick { position: relative; }

.th-datepick-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  background: var(--th-ink);
  border: 1px solid var(--th-line);
  color: var(--th-paper);
  padding: 12px 14px;
  font-family: var(--th-font-body);
  font-size: 0.92rem;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.2s ease;
}
.th-datepick-toggle:hover { border-color: var(--th-hivis); }
.th-datepick-toggle[aria-expanded="true"] { border-color: var(--th-hivis); }

.th-datepick-panel {
  position: absolute;
  z-index: 40;
  top: calc(100% + 6px);
  left: 0;
  width: min(360px, 100%);
  background: var(--th-graphite-2);
  border: 1px solid var(--th-line);
  padding: 16px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}

.th-datepick-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.th-datepick-head strong {
  font-family: var(--th-font-disp);
  font-size: 0.95rem;
  color: var(--th-paper);
}
.th-datepick-nav {
  background: transparent;
  border: 1px solid var(--th-line);
  color: var(--th-paper);
  width: 32px;
  height: 32px;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.th-datepick-nav:hover { border-color: var(--th-hivis); color: var(--th-hivis); }
/* Am Rand des erlaubten Zeitraums bleibt der Platz erhalten, damit die
   Kopfzeile nicht springt. */
.th-datepick-nav.is-off { opacity: 0.25; cursor: default; }

.th-datepick-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 3px;
}
.th-datepick-dow {
  font-family: var(--th-font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--th-stone);
  text-align: center;
  padding-bottom: 6px;
}
.th-datepick-day {
  background: var(--th-ink);
  border: 1px solid transparent;
  color: var(--th-paper);
  font-family: var(--th-font-body);
  font-size: 0.85rem;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}
.th-datepick-day:hover { border-color: var(--th-hivis); color: var(--th-hivis); }
.th-datepick-day.is-chosen {
  background: var(--th-hivis);
  border-color: var(--th-hivis);
  color: var(--th-on-accent);
  font-weight: 600;
}
/* Gesperrter Tag: sichtbar, aber klar als nicht wählbar erkennbar. Ein
   ausgeblendeter Tag würde das Kalenderraster zerreißen. */
.th-datepick-day.is-off {
  background: transparent;
  color: var(--th-stone);
  opacity: 0.35;
  cursor: not-allowed;
  text-decoration: line-through;
}

/* Das native Feld verstecken, sobald der Kalender läuft. Nicht per display:none
   auf dem Element im HTML, sondern erst durch das Skript — sonst wäre es ohne
   JavaScript unerreichbar. */
.th-datepick-native {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Honeypot — für Menschen unsichtbar, Bots füllen es aus.
   Absichtlich nicht display:none, weil manche Bots das erkennen. */
.th-hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Foto-Upload */
.th-dropzone {
  border: 1.5px dashed var(--th-line);
  padding: 30px 20px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.th-dropzone.is-dragover { border-color: var(--th-hivis); background: rgba(200, 255, 61, 0.05); }
.th-dropzone svg {
  width: 26px; height: 26px;
  stroke: var(--th-stone); fill: none; stroke-width: 1.6;
  margin-bottom: 10px;
}
.th-dropzone p { margin: 0; font-size: 0.85rem; color: var(--th-stone); }
.th-dropzone p strong { color: var(--th-hivis); font-weight: 500; }

.th-thumbs { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.th-thumb {
  position: relative;
  width: 70px; height: 70px;
  border: 1px solid var(--th-line);
  overflow: hidden;
}
.th-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.th-thumb button {
  position: absolute;
  top: 2px; right: 2px;
  width: 18px; height: 18px;
  background: rgba(15, 18, 16, 0.85);
  border: none;
  color: var(--th-paper);
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
}
.th-thumb button:hover { background: var(--th-rust); }

@media (max-width: 600px) {
  .th-form-row--2col { grid-template-columns: 1fr; }
}


/* ---------------------------------------------------------------------------
   9b. INHALTE AUS DEM BLOCK-EDITOR
   ---------------------------------------------------------------------------
   Die Theme-Abschnitte (Hero, Karten, Preise …) bringen ihren Seitenabstand
   selbst mit und sollen über die volle Breite laufen. Alles, was du als
   normalen Block einfügst — Absätze, Überschriften, Bilder, Listen — bekommt
   dagegen Lesebreite und Seitenrand. Ohne diese Regel klebten Editor-Texte
   am linken Bildschirmrand.
   --------------------------------------------------------------------------- */

.th-page-content > *:not(section):not(.th-section):not(.th-bento):not(.th-tradein) {
  max-width: calc(820px + 2 * var(--th-gutter));
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--th-gutter);
  padding-right: var(--th-gutter);
}

/* Erster und letzter Block brauchen Luft zur Navigation bzw. zum Footer */
.th-page-content > *:first-child:not(section):not(.th-section) { margin-top: 60px; }
.th-page-content > *:last-child:not(section):not(.th-section):not(.th-tradein) { margin-bottom: 80px; }

.th-page-content h2 { font-size: clamp(1.7rem, 3vw, 2.4rem); margin: 48px 0 16px; }
.th-page-content h3 { font-size: 1.3rem; margin: 36px 0 12px; }
.th-page-content p { color: var(--th-paper-2); margin: 0 0 18px; }
.th-page-content ul,
.th-page-content ol { color: var(--th-paper-2); }
.th-page-content li { margin-bottom: 8px; }

@media (max-width: 700px) {
  .th-page-content > *:not(section):not(.th-section):not(.th-bento):not(.th-tradein) {
    padding-left: var(--th-gutter-mobile);
    padding-right: var(--th-gutter-mobile);
  }
}


/* ---------------------------------------------------------------------------
   9b2. GUTENBERG-STANDARDBLÖCKE
   ---------------------------------------------------------------------------
   Damit auch frei eingefügte Blöcke zum Design passen — ohne dass du für jede
   Seite etwas einstellen musst.
   --------------------------------------------------------------------------- */

/* Buttons */
.wp-block-button__link,
.wp-element-button {
  font-family: var(--th-font-disp);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 15px 28px;
  border-radius: 0;
  background: var(--th-hivis);
  color: var(--th-on-accent);
  text-decoration: none;
  transition: transform 0.2s ease, background 0.2s ease;
}
.wp-block-button__link:hover { background: var(--th-hivis-bright); transform: translateY(-2px); }

.wp-block-button.is-style-outline .wp-block-button__link {
  background: transparent;
  color: var(--th-paper);
  border: 1px solid var(--th-line);
}
.wp-block-button.is-style-outline .wp-block-button__link:hover {
  border-color: var(--th-paper);
  background: transparent;
}

/* Aufklappbare Details — für Fragen und Antworten ohne JavaScript */
.wp-block-details {
  border-bottom: 1px solid var(--th-line);
  padding: 0;
  margin: 0;
}
.wp-block-details summary {
  font-family: var(--th-font-disp);
  font-weight: 700;
  font-size: 1rem;
  color: var(--th-paper);
  padding: 20px 0;
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
}
.wp-block-details summary::-webkit-details-marker { display: none; }
/* Eigenes Plus-Zeichen, das sich beim Aufklappen zum Kreuz dreht */
.wp-block-details summary::after {
  content: "+";
  color: var(--th-hivis);
  font-size: 1.2rem;
  flex: none;
  transition: transform 0.2s ease;
}
.wp-block-details[open] summary::after { transform: rotate(45deg); }
.wp-block-details > *:not(summary) { padding-bottom: 20px; margin: 0; }

/* Zitate */
.wp-block-quote {
  border-left: 3px solid var(--th-hivis);
  padding: 4px 0 4px 20px;
  margin: 24px 0;
  font-style: normal;
  color: var(--th-paper);
}
.wp-block-quote cite {
  display: block;
  font-size: 0.85rem;
  color: var(--th-stone);
  font-style: normal;
  margin-top: 10px;
}

/* Tabellen */
.wp-block-table table { width: 100%; border-collapse: collapse; }
.wp-block-table th,
.wp-block-table td {
  text-align: left;
  padding: 12px 14px;
  border-bottom: 1px solid var(--th-line);
  font-size: 0.92rem;
  color: var(--th-paper-2);
}
.wp-block-table th { color: var(--th-paper); font-weight: 500; }
/* Breite Tabellen scrollen im eigenen Container statt die Seite zu sprengen */
.wp-block-table { overflow-x: auto; }

/* Bilder */
.wp-block-image figcaption {
  font-size: 0.82rem;
  color: var(--th-stone);
  margin-top: 10px;
}

/* Trennlinien */
.wp-block-separator {
  border: none;
  border-top: 1px solid var(--th-line);
  margin: 44px 0;
  max-width: none;
}

/* Spalten: auf schmalen Bildschirmen untereinander statt gequetscht */
@media (max-width: 780px) {
  .wp-block-columns { flex-wrap: wrap !important; }
  .wp-block-column { flex-basis: 100% !important; }
}

/* Code */
.wp-block-code,
.wp-block-preformatted {
  background: var(--th-graphite-2);
  border: 1px solid var(--th-line);
  padding: 18px;
  font-family: var(--th-font-mono);
  font-size: 0.85rem;
  overflow-x: auto;
}


/* ---------------------------------------------------------------------------
   9c. KONTAKT- UND ZEITEN-BAUSTEINE
   Werden von den Shortcodes [bike_abk_kontakt] und
   [bike_abk_oeffnungszeiten] ausgegeben, etwa auf der Kontaktseite.
   --------------------------------------------------------------------------- */

.th-contact-block {
  font-style: normal;
  font-size: 1rem;
  line-height: 1.9;
  color: var(--th-paper-2);
}
.th-contact-block a { color: var(--th-paper-2); text-decoration: none; }
.th-contact-block a:hover { color: var(--th-hivis); }

.th-hours-block { max-width: 420px; }
.th-hours-block .th-status { margin-bottom: 20px; }


/* ---------------------------------------------------------------------------
   10. FOOTER
   --------------------------------------------------------------------------- */

.th-footer {
  border-top: 1px solid var(--th-line);
  background: var(--th-ink);
  padding: 60px var(--th-gutter) 0;
}
.th-footer-top {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: 40px;
  padding-bottom: 44px;
}
.th-footer-brand .th-footer-logo {
  font-family: var(--th-font-disp);
  font-weight: 700;
  font-size: 1.5rem;
  margin-bottom: 12px;
}
.th-footer-brand p {
  font-size: 0.9rem;
  color: var(--th-paper-3);
  max-width: 32ch;
  line-height: 1.55;
  margin: 0 0 22px;
}
.th-social { display: flex; gap: 12px; }
.th-social a {
  width: 38px; height: 38px;
  border: 1px solid var(--th-line);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.th-social a:hover { border-color: var(--th-hivis); transform: translateY(-2px); }
.th-social svg { width: 17px; height: 17px; stroke: var(--th-paper); fill: none; stroke-width: 1.6; }

.th-footer address {
  font-style: normal;
  font-size: 0.92rem;
  line-height: 1.9;
  color: var(--th-paper-2);
}
.th-footer address a { color: var(--th-paper-2); text-decoration: none; }
.th-footer address a:hover { color: var(--th-hivis); }

.th-status {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 18px;
  font-family: var(--th-font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.72rem;
}
.th-status .th-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--th-stone);
  flex: none;
}
.th-status.is-open .th-dot { background: var(--th-hivis); box-shadow: 0 0 8px 1px rgba(200, 255, 61, 0.6); }
.th-status.is-closed .th-dot { background: var(--th-rust); box-shadow: 0 0 8px 1px rgba(181, 74, 44, 0.5); }

.th-hours-list { list-style: none; margin: 0; padding: 0; }
.th-hours-list li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--th-line);
  font-size: 0.88rem;
}
.th-hours-list li:last-child { border-bottom: none; }
.th-hours-list li span:first-child { color: var(--th-stone); }
.th-hours-list li span:last-child { font-family: var(--th-font-mono); }
.th-hours-list li.is-today span:first-child { color: var(--th-paper); }

.th-footer-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 22px 0;
  border-top: 1px solid var(--th-line);
  font-family: var(--th-font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.7rem;
  color: var(--th-stone);
}
.th-footer-links { display: flex; gap: 20px; flex-wrap: wrap; }
.th-footer-links a { color: var(--th-stone); text-decoration: none; }
.th-footer-links a:hover { color: var(--th-paper); }

/* Umsetzungshinweis neben dem Copyright. Der Trennpunkt bekommt Luft, damit
   „e.U. · Umsetzung" nicht zusammenklebt. */
.th-credit { margin-left: 4px; }
.th-credit a { color: var(--th-stone); text-decoration: none; }
.th-credit a:hover { color: var(--th-paper); }

@media (max-width: 860px) {
  .th-footer-top { grid-template-columns: 1fr; gap: 34px; }
}
@media (max-width: 700px) {
  .th-footer { padding-left: var(--th-gutter-mobile); padding-right: var(--th-gutter-mobile); }
}


/* ---------------------------------------------------------------------------
   11. KARTE — 2-Klick-Lösung
   RECHT: Ein direkt eingebettetes Karten-iframe lädt beim Seitenaufruf Skripte
   und setzt teils Cookies beim Anbieter. Ohne vorherige Einwilligung ist das
   nicht zulässig (§ 165 Abs 3 TKG 2021, Art. 6 DSGVO). Deshalb wird das iframe
   erst nach aktivem Klick erzeugt — dadurch braucht die Karte kein Cookie-Banner.
   --------------------------------------------------------------------------- */

.th-map { border-top: 1px solid var(--th-line); padding: 28px 0; }
.th-map-wrap { position: relative; }
.th-map-wrap iframe {
  width: 100%;
  height: 240px;
  border: 1px solid var(--th-line);
  filter: grayscale(1) invert(0.92) contrast(0.9);
  display: block;
}
.th-map-placeholder {
  height: 240px;
  border: 1px solid var(--th-line);
  background:
    repeating-linear-gradient(45deg, transparent 0 12px, rgba(236, 233, 222, 0.03) 12px 24px),
    var(--th-graphite-2);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
  padding: 24px;
}
.th-map-placeholder p {
  font-size: 0.82rem;
  color: var(--th-stone);
  max-width: 48ch;
  line-height: 1.55;
  margin: 0;
}
.th-map-placeholder p a { color: var(--th-hivis); text-decoration: underline; }
.th-map-placeholder .th-btn { font-size: 0.85rem; padding: 12px 22px; }
.th-map-wrap.is-loaded .th-map-placeholder { display: none; }


/* ---------------------------------------------------------------------------
   12. WHATSAPP-BUTTON
   Reiner Link — es wird nichts von Meta geladen, solange niemand klickt.
   Daher nicht consent-pflichtig.
   --------------------------------------------------------------------------- */

/*
 * Der Stapel kennt die Position, die Knöpfe nur ihre Größe. Damit lässt sich
 * jeder einzelne weglassen, ohne dass eine Lücke bleibt (siehe footer.php).
 * column-reverse: erster im Quelltext = unterster auf dem Schirm.
 */
.th-fab-stack {
  position: fixed;
  right: 24px; bottom: 24px;
  z-index: 80;
  display: flex;
  flex-direction: column-reverse;
  gap: 12px;
}

/*
 * Solange der Cookie-Hinweis unten liegt, würden die Knöpfe darauf sitzen. Die
 * Leiste ist zwischen einer und drei Zeilen hoch, je nach Fensterbreite — ein
 * fester Wert wäre also auf dem Handy zu klein und am Rechner zu groß. Deshalb
 * ein großzügiger Sprung, solange sie da ist; sie verschwindet nach der Antwort
 * ohnehin dauerhaft.
 */
body:has(.th-cookie) .th-fab-stack { bottom: 150px; }

@media (min-width: 700px) {
  body:has(.th-cookie) .th-fab-stack { bottom: 110px; }
}

.th-fab {
  width: 56px; height: 56px;
  flex: none;
  border: none;
  border-radius: 50%;
  background: var(--th-hivis);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  transition: transform 0.2s ease;
}
.th-fab:hover { transform: scale(1.06); }
.th-fab svg { width: 26px; height: 26px; fill: var(--th-ink); }

/*
 * Der Bewertungsknopf steht über dem WhatsApp-Knopf und muss sich davon
 * unterscheiden — zwei gleiche grüne Kreise übereinander liest niemand als zwei
 * verschiedene Funktionen. Dunkel mit Rand statt gefüllt: Bewerten ist der
 * seltenere Vorgang und soll den Kontaktknopf nicht überstimmen.
 */
.th-fab--feedback {
  background: var(--th-graphite-2);
  border: 1px solid var(--th-line);
}
.th-fab--feedback svg { fill: var(--th-hivis); }
.th-fab--feedback:hover { border-color: var(--th-hivis); }


/* ---------------------------------------------------------------------------
   13. BEWEGUNG REDUZIEREN (WCAG 2.3.3)
   --------------------------------------------------------------------------- */

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


/* ---------------------------------------------------------------------------
   DRUCK
   ---------------------------------------------------------------------------
   Was tatsächlich ausgedruckt wird, ist überschaubar und trotzdem wichtig:
   Rechtstexte, die Preisliste und die Bestellbestätigung. Alle drei sind Belege,
   die Kunden aufbewahren.

   Ohne diese Regeln wären sie unbenutzbar: Dunkles Design bedeutet auf Papier
   volle Tonerdeckung, und heller Text auf weißem Grund ist schlicht unsichtbar —
   viele Browser drucken Hintergründe nämlich gar nicht, die Schrift aber schon.
   Genau diese Kombination führt zu leeren Blättern.

   Weiß auf Papier ist deshalb keine Geschmacksfrage, sondern Voraussetzung.
   --------------------------------------------------------------------------- */

@media print {
  /*
   * Farben zurücksetzen. Die Tokens selbst umzustellen ist gründlicher, als
   * einzelne Regeln zu überschreiben: Alles, was aus ihnen liest — Karten,
   * Tabellen, Panels, WooCommerce —, wird damit in einem Schritt lesbar.
   */
  :root {
    --th-graphite: #ffffff;
    --th-graphite-2: #ffffff;
    --th-ink: #ffffff;
    --th-card-bg: #ffffff;
    --th-paper: #000000;
    --th-paper-2: #1a1a1a;
    --th-paper-3: #333333;
    --th-stone: #555555;
    --th-line: #bbbbbb;
    --th-card-border: #bbbbbb;
    --th-hivis: #000000;
    --th-on-accent: #ffffff;
  }

  body { background: #fff; color: #000; font-size: 11pt; line-height: 1.45; }

  /* Was auf Papier nichts beiträgt oder störte. */
  .th-nav,
  .th-skip-link,
  .th-footer-links,
  .th-cookie,
  .th-season,
  .th-whatsapp-fab,
  .th-modal,
  .th-crumbs,
  .th-hero-media,
  .th-card-media,
  .th-page-header-media,
  .th-elev,
  .th-cta-row,
  .th-btn,
  .woocommerce .button,
  form,
  .th-faq-icon { display: none !important; }

  /*
   * Aufklappbare Antworten IMMER offen drucken. Ein Ausdruck mit zugeklappten
   * Fragen wäre eine Seite mit sieben Überschriften und keinem Inhalt.
   */
  .th-faq-a { display: block !important; }

  /* Abstände zusammenziehen — Bildschirmluft verschwendet auf Papier Blätter. */
  .th-section,
  .th-hero,
  .th-page-header { padding: 0 0 18pt !important; min-height: 0 !important; }

  .th-page-header { border: none; }

  h1 { font-size: 20pt; }
  h2 { font-size: 14pt; margin-top: 16pt; }
  h3 { font-size: 12pt; }

  /*
   * Überschriften nicht allein am Seitenende stehen lassen, und Tabellenzeilen
   * nicht mitten durchschneiden. Bei einer Preisliste über zwei Seiten ist das
   * der Unterschied zwischen lesbar und Rätselraten.
   */
  h1, h2, h3 { break-after: avoid; page-break-after: avoid; }
  tr, .th-price-row, .th-faq-item, .th-used-specs > div { break-inside: avoid; page-break-inside: avoid; }

  /*
   * Zieladresse hinter Links ausschreiben — aber nur in Rechtstexten. Auf Papier
   * ist ein Link ohne Adresse wertlos, und gerade in Impressum und
   * Datenschutzerklärung stehen Verweise, die man nachlesen können muss.
   *
   * Interne Anker und mailto bleiben ausgenommen: „(#kontakt)" hilft niemandem.
   */
  .th-page-body--legal a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 9pt;
    color: #555;
    word-break: break-all;
  }

  /* Fußzeile: Firmenname und Adresse bleiben, sie gehören auf jeden Beleg. */
  .th-footer { border-top: 1pt solid #bbb; padding-top: 10pt; font-size: 9pt; }
}
