/*
Theme Name:  AZB Performance
Theme URI:   https://autozentrum-bensheim.de
Author:      Bergstrasse Digital
Author URI:  https://www.bergstrasse-digital.de
Description: Theme fuer AZB Performance — Autozentrum Bensheim. Werkstatt,
             Tuning und Gebrauchtwagen-Marktplatz. Enthaelt den Inhaltstyp
             "Fahrzeug" mit 42 Feldern und Mediathek-Galerie.
Version:     1.0.0
Requires PHP: 8.0
Text Domain: azb
*/

/* =============================================================================
   BASIS — uebernommen aus assets/shared.css des statischen Standes.
   Unveraendert, damit das Erscheinungsbild identisch bleibt; jede Aenderung
   hier ist eine bewusste, keine Nebenwirkung der Portierung.
   ========================================================================== */

/* Fonts self-gehostet (2026-08-04, Review P2/DSGVO): vorher lud ein @import die Google-CSS
   render-blockend nach (HTML -> shared.css -> Google-CSS -> woff2, 2 Fremd-Origins) UND
   widersprach dem Datenschutztext. Variable-Font-Dateien, latin-Subset (deckt Umlaute +
   U+2000-206F-Interpunktion). Archivo/Archivo Black liegen hier mit, werden aber nur auf
   index/tuning benutzt — @font-face allein lädt nichts. */
@font-face {
  font-family: 'Anton'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('assets/fonts/anton-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url('assets/fonts/inter-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url('assets/fonts/jbmono-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Archivo'; font-style: italic; font-weight: 400 900; font-stretch: 62% 125%; font-display: swap;
  src: url('assets/fonts/archivo-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Archivo Black'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('assets/fonts/archivoblack-latin.woff2') format('woff2');
}

:root {
  --bg-base: #050505;
  --bg-base-2: #0a0a0a;
  --surface-1: #0f0f0f;
  --surface-2: #161616;
  --surface-3: #1f1f1f;
  --surface-elev: #262626;
  --text-primary: #f5f5f5;
  --text-secondary: #a8a8a8;
  /* Kontrast-Sanierung 2026-08-03 — gemessen gegen die tatsaechlich gerenderten
     Untergruende (#050505 Buehne, #0f0f0f–#161616 Karten, #000 Footer-Fuss).
     Schwelle 4.5:1 fuer Text < 24px. Belege: _work/_bericht-farbsystem.md */
  --text-muted: #909090;   /* war #7a7a7a, dann #8a8a8a — gegen das hellste Pixel des
                              Tuning-Platinen-Stapels (rgb(80,17,17)) hielt #8a8a8a nur
                              4,48:1 (0,02 unter der Schwelle). #909090 = 4,60:1 dort,
                              5,5:1 auf Karten; optisch nicht unterscheidbar. */
  --text-faint: #808080;   /* war #404040 (1.84–2.03:1) — jetzt 5.32:1 auf #000 (Footer-Claim).
                              NUR fuer Untergruende bis #101010 (dort 4.91:1). Auf #161616
                              waeren es 4.51:1 = zu knapp -> dort --text-muted nehmen. */
  /* Deko-Ziffern (/01../06) liegen als Literale in den Seiten; Pflicht bleibt aria-hidden="true"
     am Element, sonst gilt 4.5:1. (Der fruehere --deko-ziffer-Token war unbenutzt — entfernt.) */
  --red-bright: #ff1a1a;   /* Kleintext-Rot: 4.67–5.38:1 auf allen gemessenen Untergruenden */
  --red: #e10600;          /* Marken-/Flaechenrot. Als KLEINTEXT prinzipiell unbrauchbar:
                              max. 4.23:1 selbst auf reinem Schwarz. Nur >= 24px oder Flaeche. */
  --red-deep: #a30000;
  --red-glow: rgba(225, 6, 0, 0.45);
  --red-soft: rgba(225, 6, 0, 0.12);
  --border-1: rgba(255, 255, 255, 0.06);
  --border-2: rgba(255, 255, 255, 0.10);
  --border-red: rgba(225, 6, 0, 0.40);
  --shadow-md: 0 12px 24px -8px rgba(0,0,0,.7), 0 2px 4px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.04) inset;
  --shadow-lg: 0 32px 64px -16px rgba(0,0,0,.8), 0 8px 16px -4px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.04) inset;
  --shadow-red: 0 24px 48px -16px rgba(225,6,0,.35), 0 8px 16px -4px rgba(0,0,0,.6), 0 0 0 1px rgba(225,6,0,.20) inset;
  --shadow-glow: 0 0 32px -4px rgba(225,6,0,.55);
  --r-sm: 4px; --r-md: 8px; --r-lg: 14px; --r-xl: 22px;
  --font-display: 'Anton', 'Bebas Neue', Impact, sans-serif;
  --font-body: 'Inter', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);

  /* v6 tokens */
  --brand-warm: #c9a35f;          /* matte gold — only on dark bg (7.8:1 on #050505) */
  --section-y-sm: 64px;
  --section-y-md: 96px;
  --section-y-lg: 128px;
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { background: var(--bg-base); color-scheme: dark; scroll-behavior: smooth; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; }
/* EIN Anker-Offset statt drei Konventionen (0 / 104-116 / 120, Review 20/10 Z8):
   Nav-Hoehe 88 + 28 Luft. Seitenlokale Werte (Impressum-TOC) gewinnen in der Kaskade. */
[id] { scroll-margin-top: 116px; }
body {
  font-family: var(--font-body); font-weight: 400; font-size: 16px; line-height: 1.7;
  color: var(--text-primary); background: var(--bg-base); min-height: 100vh; overflow-x: hidden;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: var(--red); color: #fff; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg-base); }
::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--red-deep); }

.display { font-family: var(--font-display); font-style: italic; font-weight: 400; letter-spacing: -0.02em; line-height: 0.92; text-transform: uppercase; }
.display-md { font-size: clamp(36px, 5vw, 72px); letter-spacing: -0.03em; }
.display-sm { font-size: clamp(28px, 4vw, 48px); letter-spacing: -0.02em; }
/* Zweizeilige Display-Headline, deren Zeile 2 mit Umlaut beginnt: Anton setzt die
   Umlautpunkte ueber die Versalhoehe — bei lh .92 stehen sie in der Zeile darueber.
   Gemessen: erst ab 1.1 sind die Ink-Baender getrennt (Index-Finetune §1.2). */
.display-2z { line-height: 1.1; }
.eyebrow { font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: var(--red-bright); }
.lede { font-size: clamp(17px, 1.4vw, 22px); line-height: 1.55; color: var(--text-secondary); }
.body-lg { font-size: 18px; line-height: 1.7; color: var(--text-secondary); }
.num { font-family: var(--font-mono); font-feature-settings: "tnum"; }

.grain { position: relative; }
.grain::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0.06; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/></filter><rect width='200' height='200' filter='url(%23n)' opacity='0.9'/></svg>");
}

.wrap { width: 100%; max-width: 1320px; margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 880px; }
@media (min-width: 768px) { .wrap { padding: 0 40px; } }
@media (min-width: 1280px) { .wrap { padding: 0 56px; } }

.btn {
  --btn-bg: var(--red); --btn-fg: #fff;
  display: inline-flex; align-items: center; gap: 12px;
  padding: 16px 28px;
  font-family: var(--font-body); font-weight: 700; font-size: 14px; letter-spacing: 0.14em; text-transform: uppercase;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid transparent; border-radius: var(--r-md);
  position: relative; isolation: isolate; transform: translateZ(0);
  transition: transform .35s var(--ease-spring), box-shadow .35s var(--ease-out), background-color .25s var(--ease-out);
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(255,255,255,.06) inset;
}
.btn::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,.18), transparent 40%);
  border-radius: inherit; pointer-events: none; opacity: 0.7; transition: opacity .25s; z-index: -1;
}
.btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-red); }
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.btn-ghost { --btn-bg: transparent; --btn-fg: var(--text-primary); border: 1px solid var(--border-2); box-shadow: none; }
.btn-ghost:hover { background: var(--surface-2); border-color: var(--border-red); box-shadow: var(--shadow-md); }
.btn-arrow svg { transition: transform .35s var(--ease-spring); }
.btn-arrow:hover svg { transform: translateX(6px); }

.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  background: rgba(5,5,5,0.72);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  border-bottom: 1px solid var(--border-1);
}
.nav-inner { display: flex; align-items: center; justify-content: space-between; height: 76px; }
.nav-logo { display: flex; align-items: center; gap: 12px; height: 44px; }
.nav-logo svg, .nav-logo img { height: 32px; width: auto; max-width: 220px; object-fit: contain; }
@media (max-width: 480px) { .nav-logo svg, .nav-logo img { height: 26px; max-width: 170px; } }
.nav-list { display: none; gap: 4px; list-style: none; }
.nav-link {
  position: relative; padding: 10px 14px;
  font-size: 13px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-secondary); transition: color .2s;
}
.nav-link::after {
  content:''; position: absolute; left: 14px; right: 14px; bottom: 4px; height: 2px;
  background: var(--red); transform: scaleX(0); transform-origin: left; transition: transform .35s var(--ease-out);
}
.nav-link:hover { color: var(--text-primary); }
.nav-link:hover::after, .nav-link.is-active::after { transform: scaleX(1); }
.nav-link.is-active { color: var(--text-primary); }
.nav-cta { display: none; }
.nav-burger { width: 44px; height: 44px; display: grid; place-items: center; border: 1px solid var(--border-2); border-radius: var(--r-md); }
.nav-burger span { display: block; width: 18px; height: 2px; background: var(--text-primary); position: relative; }
.nav-burger span::before, .nav-burger span::after { content:''; position: absolute; left: 0; width: 18px; height: 2px; background: var(--text-primary); }
.nav-burger span::before { top: -6px; }
.nav-burger span::after { top: 6px; }
/* Telefon-Knopf neben dem Burger: mobil gab es im ersten Viewport keinen Anruf-Weg —
   der Werkstatt-Hauptkanal kostete 2 Taps auf ein 14px-Ziel (Review 2 M1 / 7 A5). */
.nav-tel { display: none; width: 44px; height: 44px; border: 1px solid var(--border-2); border-radius: var(--r-md); place-items: center; color: var(--text-primary); }
.nav-tel:hover { border-color: var(--border-red); color: var(--red-bright); }
@media (max-width: 1023px) { .nav-tel { display: grid; } }
.menu-tel { display: inline-flex; align-items: center; min-height: 44px; padding: 10px 0; font-family: var(--font-mono); font-size: 13px; color: var(--text-muted); letter-spacing: 0.18em; }
@media (min-width: 1024px) { .nav-list { display: flex; } .nav-cta { display: inline-flex; } .nav-burger { display: none; } }

/* overflow-y: auto ist Pflicht — im Landscape (844x390) ist das Menue 625px hoch,
   Kontakt/CTA/Telefon lagen sonst unerreichbar ausserhalb (Review 9 H3).
   padding-bottom mit safe-area: Telefonzeile kollidierte sonst mit dem iOS-Home-Indicator. */
.mobile-menu {
  position: fixed; inset: 0; background: var(--bg-base); z-index: 60; display: none;
  flex-direction: column; padding: 100px 24px 40px;
  padding-bottom: max(40px, calc(env(safe-area-inset-bottom) + 24px));
  overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.mobile-menu.is-open { display: flex; }
@media (max-height: 500px) { .mobile-menu { padding-top: 60px; } }
@media (prefers-reduced-motion: no-preference) {
  .mobile-menu.is-open { animation: menuIn 200ms var(--ease-out); }
  .mobile-menu.is-open > a, .mobile-menu.is-open > div { animation: menuItemIn 260ms var(--ease-out); }
  /* Exit-Fade (Review 20/10 Z4): funktional ist das Menue beim Klick sofort zu
     (site.js raeumt inert/Scroll/Fokus) — nur die Flaeche blendet noch aus.
     pointer-events: none, damit die ausblendende Flaeche keine Klicks frisst. */
  .mobile-menu.is-closing { display: flex; pointer-events: none; animation: menuOut 180ms var(--ease-out) forwards; }
}
@keyframes menuIn { from { opacity: 0; } }
@keyframes menuItemIn { from { opacity: 0; transform: translateY(10px); } }
@keyframes menuOut { to { opacity: 0; } }
.mobile-menu a {
  font-family: var(--font-display); font-style: italic; font-size: 36px; line-height: 1.1; letter-spacing: -0.02em; text-transform: uppercase;
  padding: 14px 0; border-bottom: 1px solid var(--border-1);
  display: flex; justify-content: space-between; align-items: center;
}
.mobile-menu a .num { color: var(--red-bright); font-size: 12px; font-style: normal; }
/* Aktuelle Seite auch im Mobile-Menue markieren (Review 20/10 Z7): Desktop zeigt
   is-active als roten Unterstrich — mobil hatte derselbe Zustand keine Form.
   Der Unterstrich sitzt am Label-Span, nicht am ganzen Eintrag (der traegt schon
   die Trennlinie unten). */
.mobile-menu a[aria-current="page"] > span:first-child { box-shadow: inset 0 -3px 0 var(--red); padding-bottom: 2px; }
.mobile-menu .close { position: absolute; top: 22px; right: 22px; width: 44px; height: 44px; border: 1px solid var(--border-2); border-radius: var(--r-md); display: grid; place-items: center; }

/* .section-Padding: EINZIGE gueltige Definition steht unten im Token-Block (v6).
   Der fruehere px-Block hier war tot (gleiche Spezifitaet, frueher im File) und hat mit
   seinem 80px-Desktop-Wert fuer .section-sm nur in die Irre gefuehrt (Review 4 F5). */
.section { position: relative; }
.section-marker { display: flex; align-items: center; gap: 16px; margin-bottom: 32px; }
.section-marker .num { font-size: 12px; color: var(--red-bright); letter-spacing: 0.18em; }
.section-marker .label { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--text-muted); }

.footer { position: relative; background: linear-gradient(180deg, var(--bg-base), #000); border-top: 1px solid var(--border-1); padding: 80px 0 32px; overflow: hidden; }
.footer-grid { display: grid; gap: 48px; grid-template-columns: 1fr; }
@media (min-width: 768px) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; } }
.footer h4 { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 18px; }
.footer-links { list-style: none; }
.footer-links li { padding: 6px 0; }
.footer-links a { color: var(--text-secondary); transition: color .2s; }
.footer-links a:hover { color: var(--red-bright); }
.footer-bottom { margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--border-1); display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: center; font-size: 13px; color: var(--text-muted); }

.chip { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; background: var(--surface-2); border: 1px solid var(--border-1); border-radius: 999px; color: var(--text-secondary); }

/* Pressed-Familie (Review 20/10 Z2): auf Touch existiert hover nicht — bis hierher
   quittierte ausser .btn nichts einen Tap (bzw. mit dem markenfremden Chrome-Blau-Flash,
   der oben am html abgeschaltet ist). Dezente Rücknahme statt Neu-Design.
   .azb-js in den Karten-Selektoren ist Absicht: hebt die Spezifitaet ueber die
   seitenlokalen :hover-Regeln (gleiche Kaskaden-Stufe, spaeter geladen). */
.azb-js .veh-card:active, .azb-js .veh-card-btn:active,
.azb-js .azb-card:active, .azb-js .halle-karte:active {
  transform: translateY(0) scale(.985);
  transition-duration: .12s;
}
.azb-js .status-tabs button:active { transform: scale(.97); transition: transform .12s var(--ease-out); }
.mobile-menu a:active { opacity: .55; }
.nav-burger:active, .nav-tel:active, .mobile-menu .close:active { transform: scale(.92); transition: transform .12s var(--ease-out); }
.dot { display: inline-block; width: 6px; height: 6px; border-radius: 999px; background: var(--red); box-shadow: 0 0 12px var(--red); }


/* Versteck NUR unter html.azb-js (Review 20/7 R1): die Klasse setzt site.js in seiner
   ersten Zeile. Faellt site.js aus, war [data-reveal]{opacity:0} vorher ein Totalschaden —
   7 Sektionen fuer immer unsichtbar. Ohne JS ist die Seite jetzt statisch komplett. */
.azb-js [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); }
[data-reveal].is-in { opacity: 1; transform: none; }
/* is-sofort vergibt site.js an alles, was beim Laden schon im Viewport steht (At-Rest):
   ohne Transition sichtbar — der .8s-Fade um die Hero-H1 kostete 0,9-1,4 s LCP auf
   4 Seiten und verlor sein Rennen gegen den ersten Paint (Review 20/4 W1).
   Muss NACH der .azb-js-Regel stehen (gleiche Spezifitaet, Kaskade entscheidet). */
[data-reveal].is-sofort { transition: none; }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; }
  /* Anker-Spruenge duerfen fuer reduce-Nutzer nicht gleiten — einzige Luecke der
     sonst vollstaendigen reduce-Abdeckung (Review 3 M2). */
  html { scroll-behavior: auto; }
}
.spotlight { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(ellipse 70% 50% at 80% 20%, rgba(225,6,0,.18), transparent 60%), radial-gradient(ellipse 60% 40% at 20% 80%, rgba(225,6,0,.10), transparent 60%); }

/* ============================================================
   Leiterbahn divider — section-marker bar (carry-over from v2)
   ============================================================ */
.section-marker .bar {
  position: relative;
  flex: 0 0 88px;
  height: 12px;
  background: transparent;
  background-image: linear-gradient(90deg, transparent 0, transparent 10%, var(--red) 10%, var(--red) 42%, transparent 42%, transparent 58%, var(--red) 58%, var(--red) 90%, transparent 90%);
  background-size: 100% 1px;
  background-repeat: no-repeat;
  background-position: 0 50%;
}
.section-marker .bar::before,
.section-marker .bar::after {
  content: '';
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 8px var(--red);
}
.section-marker .bar::before { left: 42%; }
.section-marker .bar::after  { left: 58%; transform: translate(-100%, -50%); }

/* ============================================================
   Vehicle placeholder — carry-over
   ============================================================ */
.veh-placeholder {
  width: 100%; height: 100%;
  display: grid; place-items: center;
  position: relative;
  background:
    radial-gradient(ellipse 80% 60% at 50% 50%, rgba(225,6,0,.08), transparent 70%),
    linear-gradient(135deg, var(--surface-2), var(--surface-3));
  border-bottom: 1px solid var(--border-1);
  overflow: hidden;
}
.veh-placeholder::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(45deg, rgba(255,255,255,.025) 0 1px, transparent 1px 6px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,.025) 0 1px, transparent 1px 6px);
  pointer-events: none;
}
.veh-placeholder svg {
  width: 96px; height: auto; opacity: 0.18; color: var(--red);
  position: relative; z-index: 1;
}
.veh-placeholder .ph-label {
  position: absolute; bottom: 18px; left: 18px; right: 18px;
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-secondary);
  z-index: 2;
}
.veh-placeholder .ph-tag {
  background: var(--red); color: #fff;
  padding: 4px 8px; border-radius: var(--r-sm);
  letter-spacing: 0.2em; font-weight: 700;
}

/* content-visibility was too aggressive — removed */
/* ============================================================
   v6 — Skip link, forced-colors, motion defaults, type variants
   ============================================================ */

/* Skip link — visible only on focus */
.skip-link {
  position: fixed;
  top: 8px; left: 8px;
  z-index: 9999;
  padding: 12px 18px;
  background: var(--bg-base);
  color: #fff;
  border: 2px solid var(--red);
  border-radius: var(--r-md);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.08em;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform .2s var(--ease-out);
}
.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 3px solid var(--red);
  outline-offset: 2px;
}

/* Forced-colors mode — Windows High Contrast */
@media (forced-colors: active) {
  .btn,
  .btn-ghost {
    border: 2px solid CanvasText !important;
    box-shadow: none !important;
    forced-color-adjust: none;
  }
  .btn:focus-visible,
  .btn-ghost:focus-visible,
  a:focus-visible,
  button:focus-visible,
  input:focus-visible,
  textarea:focus-visible,
  select:focus-visible {
    outline: 3px solid Highlight !important;
    outline-offset: 2px !important;
    box-shadow: none !important;
  }
  .nav-link.is-active::after { background: Highlight !important; }
  .veh-tag, .chip { border: 1px solid CanvasText; }
}

/* Display-roman — same Anton family but non-italic, for repeated section headings */
.display-roman {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 0.92;
  text-transform: uppercase;
}
.display-roman.display-md { font-size: clamp(36px, 5vw, 72px); letter-spacing: -0.03em; }
.display-roman.display-sm { font-size: clamp(28px, 4vw, 48px); letter-spacing: -0.02em; }

/* Karten-Fliesstext: 15px/1.65 ist der Standard. Seiten-lokale 14.5px-Overrides wurden
   entfernt (Review 4 F7) — hier gilt, was man sieht. */
.veh-card .veh-body,
.review .text,
.val p,
.team-card p {
  font-size: 15px;
  line-height: 1.65;
}

/* Vehicle-meta icons 14px — CSS-width schlaegt das SVG-Praesentationsattribut, !important unnoetig */
.veh-meta svg { width: 14px; height: 14px; }

/* Section padding token-driven */
.section { padding: var(--section-y-md) 0; }
.section-sm { padding: var(--section-y-sm) 0; }
@media (min-width: 1024px) {
  .section { padding: var(--section-y-lg) 0; }
}

/* Footer-phone touch target */
.footer-phone-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 0;
  font-family: var(--font-mono);
  font-size: 15px;
  letter-spacing: 0.14em;
  color: var(--text-primary);
  font-weight: 600;
}
.footer-phone-link:hover { color: var(--red-bright); }

/* Form inline error styles */
.form .field.is-invalid input,
.form .field.is-invalid select,
.form .field.is-invalid textarea {
  border-color: var(--red);
  box-shadow: 0 0 0 3px var(--red-soft);
}
.form .field-error {
  font-size: 12.5px;
  color: #ff6b6b;
  margin-top: 6px;
  font-weight: 500;
  min-height: 16px;
  font-family: var(--font-body);
}
.form-summary {
  display: none;
  padding: 12px 16px;
  margin-bottom: 16px;
  background: rgba(225,6,0,.12);
  border: 1px solid var(--border-red);
  border-radius: var(--r-md);
  font-size: 14px;
  color: #ff8888;
}
.form-summary.is-shown { display: block; }

/* Mobile filter collapse */
.filter-toggle {
  display: none;
  width: 100%;
  margin-top: 10px;
  padding: 10px 14px;
  background: transparent;
  border: 1px solid var(--border-2);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-primary);
  cursor: pointer;
}
.filter-toggle:hover { border-color: var(--border-red); color: var(--red-bright); }
@media (max-width: 767px) {
  .filter-toggle { display: block; }
  .filters-grid .field-extra[hidden] { display: none; }
  .filters-grid .field-extra { grid-column: 1 / -1; }
}

/* Map consent button container.
   KEIN festes aspect-ratio im Textzustand: der Einwilligungs-Text passte @390 nicht in 16/9,
   beide Buttons lagen abgeschnitten unterhalb der Kante (Kontakt-Finetune §1). Die feste
   Form braucht erst der iframe (is-loaded). */
.map-consent {
  position: relative;
  min-height: 288px;
  border-radius: var(--r-xl);
  overflow: hidden;
  border: 1px solid var(--border-2);
  background: linear-gradient(135deg, var(--surface-1), var(--surface-2));
  display: grid; place-items: center;
  text-align: center;
  padding: 32px 24px;
}
.map-consent .ic { width: 44px; height: 44px; color: var(--red); margin: 0 auto 16px; }
.map-consent .heading { font-family: var(--font-display); font-style: italic; font-size: 24px; line-height: 1; letter-spacing: -0.02em; text-transform: uppercase; margin-bottom: 8px; }
.map-consent .note { font-size: 13px; color: var(--text-muted); max-width: 320px; margin: 0 auto 20px; line-height: 1.5; }
.map-consent .map-iframe-wrap { display: none; position: absolute; inset: 0; }
.map-consent .map-iframe-wrap iframe { width: 100%; height: 100%; border: 0; }
.map-consent.is-loaded { aspect-ratio: 16/9; min-height: 0; }
.map-consent.is-loaded .map-text { display: none; }
.map-consent.is-loaded .map-iframe-wrap { display: block; }

/* Formularfeld-Fokus: 1px-Border-Wechsel + 12%-Schatten allein war der schwaechste
   Indikator der Site (Review 7 A7) — Outline konsistent zum Rest (ueberall 2-3px).
   WEISS statt Rot (Review 20/10 Z1): Fokus und Fehler waren am Feld pixelidentisch
   (beide rot + red-soft). Jetzt: Fokus = weisse Outline AUSSEN, Fehler = rote Border +
   red-soft-Fuellung INNEN — beide gleichzeitig bleiben lesbar. Die frueher toten
   seitenlokalen outline:0-Regeln (kontakt/marktplatz/admin) sind entfernt. */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* ============================================================
   v7 — 3D-Logo (<azb-logo-3d>)  ·  NUR ADDITIV
   ------------------------------------------------------------
   Der geteilte WebGL-Canvas liegt fix ueber dem Viewport und malt jede
   Logo-Instanz per Scissor an die Stelle ihres Platzhalters. Daraus folgen
   die beiden einzigen heiklen Werte hier:

   z-index 55  = UEBER der Nav (50), damit das Logo in der Leiste sichtbar ist,
                 und UNTER dem Mobile-Menue (60), damit dort nichts durchscheint.
   pointer-events: none = der Link unter dem Canvas bleibt klickbar.

   Die Platzhalter-Boxen haben feste Masse. Vor dem Start der Engine fuellt sie
   das PNG, danach malt WebGL in dieselbe Box — deshalb ist der Layout-Shift
   null (gemessen: Nav-Hoehe vorher/nachher identisch).
   ============================================================ */

/* ACHTUNG, teuer gelernt: <canvas> ist ein ERSETZTES Element. Bei width/height
   auto zieht es seine INTRINSISCHE Groesse (300x150) — `inset: 0` sizt es NICHT,
   anders als bei einem <div>. Ohne die expliziten 100% blieb der Canvas 300x150
   gross, und vom Logo war ab x=300 nichts mehr da (gemessen: das "B" fehlte). */
.azb-logo3d-canvas {
  position: fixed; left: 0; top: 0;
  width: 100%; height: 100%; display: block;
  z-index: 55; pointer-events: none;
}

.logo3d { position: relative; display: block; flex: none; }
.logo3d azb-logo-3d { position: absolute; inset: 0; display: block; }

/* Der PNG-Fallback traegt die Marke, bis die Engine laeuft — und wieder,
   falls WebGL wegbricht (contextlost). scale(.943) gleicht den Rand aus, den
   die Kamera fuer das Aufklappen freihaelt; so springt beim Wechsel nichts. */
.logo3d .logo3d-png {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  transform: scale(0.943);
  transition: opacity .4s var(--ease-out);
}
.logo3d.is-live .logo3d-png { opacity: 0; }

/* --- Nav: Marke (3D) ueber der Wortmarke, gestapelt wie im Original-Logo --- */
.nav-logo.is-stack { height: auto; display: block; }
.nav-logo .logo3d--nav { width: 172px; height: 32px; }
.nav-logo .logo3d-word {
  display: block; width: 172px; height: auto;
  aspect-ratio: 2727 / 192; margin-top: 1px;
  max-width: none;
}
@media (min-width: 1024px) {
  .nav-logo .logo3d--nav { width: 200px; height: 36px; }
  .nav-logo .logo3d-word { width: 200px; }
  /* Die Leiste waechst genau um den Zuwachs der Marke — 76 -> 88. Auf Mobil
     bleibt sie bei 76px, dort passt der Stapel (45px) ohnehin hinein. */
  .nav-inner { height: 88px; }
}

/* --- Footer: groesseres Mark, spielt beim Reinscrollen --- */
.footer .nav-logo .logo3d--footer { width: 200px; height: 38px; }
.footer .nav-logo .logo3d-word { width: 200px; }
@media (min-width: 768px) {
  .footer .nav-logo .logo3d--footer { width: 240px; height: 44px; }
  .footer .nav-logo .logo3d-word { width: 240px; }
}

/* --- Timeline "2017 · AZB Performance": die Marke dreht sich dort, wo sie
       historisch entsteht. Kein Wortmarken-Zusatz, sonst wird der Eintrag laut. */
.logo3d--tl { width: 132px; height: 26px; margin: 0 0 10px; opacity: .95; }
@media (min-width: 768px) { .logo3d--tl { width: 150px; height: 28px; } }

/* admin.html haengt als einzige Seite an einer festen Nav-Hoehe (inline
   body{padding-top:76px}) und rendert dieselbe Nav. Mit der 88px-Leiste ab
   1024px fehlten ihr 12px, der Inhalt waere unter die Leiste gerutscht.
   `html body:has(.admin-shell)` ist spezifischer als das inline `body` und
   trifft nur diese eine Seite — admin.html selbst bleibt unangetastet. */
@media (min-width: 1024px) {
  html body:has(.admin-shell) { padding-top: 88px; }
}

/* Druck: der fixe Canvas druckt nicht mit — dann traegt wieder das PNG. */
@media print {
  .azb-logo3d-canvas { display: none !important; }
  .logo3d.is-live .logo3d-png { opacity: 1 !important; }
}

/* ==========================================================================
   Plaketten v2 — konsolidiert aus index + tuning (Review 4 F2)
   --------------------------------------------------------------------------
   Dieser Block stand bis 2026-08-04 ZWEIMAL im Quelltext: index.html 487-576
   und tuning.html 361-439, zeilenweise identisch bis auf zwei Kommentar-
   Formulierungen. Zwei Kopien einer 90-Zeilen-Kachel sind kein Stilproblem,
   sondern eine Zeitbombe: wer die Gravur-Kante auf einer Seite anfasst, hat
   die andere still auseinanderlaufen lassen.

   Hier steht nur der KERN — alles, was beide Seiten gleich brauchen. Seiten-
   eigenes bleibt in der jeweiligen Seite:
     index.html : .services-grid (Raster) + .azb-cta / .azb-arrow
                  (die Kacheln sind dort Links und tragen einen CTA)
     tuning.html: .svc-grid (Raster) + .azb-liste / .svc-marken + die
                  Mobil-Straffung (die Kacheln sind dort <article> ohne Ziel)

   .azb-card:focus-visible stand nur in index. Es steht jetzt im Kern, weil
   es auf tuning nichts tun KANN (dort sind die Kacheln nicht fokussierbar) —
   optisch also eine Null-Aenderung, aber die Regel ist da, sobald eine Kachel
   dort einmal ein Ziel bekommt.

   Position am DATEIENDE ist Absicht: .azb-title traegt im Markup zusaetzlich
   .display (shared.css:92, gleiche Spezifitaet). Nur weil dieser Block
   spaeter steht, gewinnt seine line-height:1. Wer den Block nach oben
   verschiebt, macht die Plaketten-Ueberschriften unbemerkt hoeher.
   ========================================================================== */
:root { --red-rgb: 225, 6, 0; }   /* = --red #e10600, kanalweise fuer rgba() */

.azb-card {
  position: relative; display: flex; flex-direction: column;
  padding: 26px 24px 22px;
  min-height: 274px;
  background: linear-gradient(180deg, #151517 0%, #101012 62%, #0e0e10 100%);
  border: 1px solid var(--border-1);
  border-radius: 12px;
  overflow: hidden; isolation: isolate;
  /* .4s = die EINE Karten-Lift-Dauer der Site (Review 20/10 Z10; vorher .35/.4/.45 gemischt) */
  transition: transform .4s cubic-bezier(.2,.7,.2,1), border-color .3s, box-shadow .35s, background .35s;
}
.azb-card:hover {
  transform: translateY(-3px);
  border-color: rgba(var(--red-rgb), .5);
  box-shadow: 0 0 0 1px rgba(var(--red-rgb), .14),
              0 26px 60px -26px rgba(var(--red-rgb), .55),
              0 2px 0 rgba(255,255,255,.03) inset;
}
.azb-card:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }

/* Gravur-Kante: der helle Anriss oben, der die Plakette "eingelassen" wirken laesst */
.azb-edge {
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg,
    rgba(var(--red-rgb), 0),
    rgba(var(--red-rgb), .9) 18%,
    rgba(var(--red-rgb), .25) 55%,
    rgba(var(--red-rgb), 0));
  opacity: .55; transition: opacity .35s; pointer-events: none;
}
.azb-card:hover .azb-edge { opacity: 1; }
.azb-halo {
  position: absolute; top: -70px; left: -60px; width: 210px; height: 210px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(var(--red-rgb), .16), rgba(var(--red-rgb), 0) 70%);
  opacity: .5; transition: opacity .4s; pointer-events: none;
}
.azb-card:hover .azb-halo { opacity: 1; }

.azb-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.azb-plate {
  position: relative; display: grid; place-items: center;
  width: 52px; height: 52px; border-radius: 13px;
  color: var(--red-bright);
  background: linear-gradient(160deg, rgba(var(--red-rgb), .3), rgba(var(--red-rgb), .05) 65%), #141416;
  border: 1px solid rgba(var(--red-rgb), .4);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.12), 0 8px 20px -12px rgba(var(--red-rgb), .7);
  transition: color .3s, border-color .3s, box-shadow .35s, transform .4s cubic-bezier(.2,.7,.2,1);
}
.azb-card:hover .azb-plate {
  color: #fff;
  border-color: rgba(var(--red-rgb), .8);
  transform: scale(1.04);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 12px 26px -12px rgba(var(--red-rgb), .95);
}
/* Ordnungsziffer = reine Dekoration (aria-hidden am Element), traegt keine
   Information: die Kachel ist ueber Plakette + Ueberschrift eindeutig, die
   Reihenfolge steht schon im Layout. Deshalb von WCAG 1.4.3 ausgenommen —
   dieselbe Begruendung wie beim bisherigen .num in --deko-ziffer.          */
.azb-num {
  font-family: var(--font-mono); letter-spacing: .14em; font-size: 9.5px;
  color: rgba(255,255,255,.26);
  display: flex; align-items: center; gap: 7px;
  transition: color .3s;
}
.azb-card:hover .azb-num { color: rgba(255,255,255,.5); }
.azb-num span { display: block; width: 16px; height: 1px; background: currentColor; opacity: .55; }

.azb-title { font-size: 24px; line-height: 1; margin: 20px 0 0; max-width: 15ch; }
.azb-body { margin: 11px 0 0; font-size: 13.5px; line-height: 1.56; color: rgba(255,255,255,.55); text-wrap: pretty; }

.azb-foot { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 18px; }
.azb-rule {
  flex: 1; height: 1px;
  background: linear-gradient(90deg, rgba(255,255,255,.1), rgba(255,255,255,0));
  transition: background .35s;
}
.azb-card:hover .azb-rule { background: linear-gradient(90deg, rgba(var(--red-rgb), .55), rgba(var(--red-rgb), 0)); }

/* ============================================================================
   PARTNER-/HERSTELLER-LEISTE
   Verschoben aus dem <style>-Block von index.html nach shared.css (2026-08-23),
   weil die Sektion seither auf ZWEI Seiten steht (index + tuning). Duplizieren
   haette eine neunte doppelt gepflegte Wahrheit erzeugt; und beim geplanten
   WordPress-Port wird aus shared.css ohnehin EIN Stylesheet, waehrend jeder
   Inline-<style>-Block von Hand aufgeloest werden muesste. Die Arbeit faellt
   also so oder so an — jetzt ist sie ein Ausschneiden.
   Seitenspezifische Abweichungen stehen NICHT hier, sondern als
   body.seite-tuning-Overrides im <style> von tuning.html (dort begruendet).
   ========================================================================= */
/* ===== Partner (Design 7c60bfb7) ===== */
.partner { padding: 88px 0 84px; border-top: 1px solid var(--border-1); background: var(--bg-base); }
.p-kopf { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 48px; margin-bottom: 52px; }
.p-marker { display: flex; align-items: center; gap: 14px; margin-bottom: 22px; }
.p-marker b { font: 700 12px/1 var(--font-body); letter-spacing: .14em; color: var(--red-bright); }
.p-marker span { font: 500 12px/1 var(--font-body); letter-spacing: .24em; text-transform: uppercase; color: var(--text-secondary); }
.p-marker i { width: 64px; height: 1px; background: var(--border-2); }
.p-h2 { margin: 0 0 18px; font: 700 clamp(33px,4vw,54px)/1.04 var(--font-body); letter-spacing: -.028em; color: #fff; }
.p-h2 span { color: rgba(255,255,255,.38); }
.p-lede { margin: 0; max-width: 58ch; font: 400 clamp(15px,1.2vw,17px)/1.62 var(--font-body); color: var(--text-secondary); text-wrap: pretty; }
.p-cta { display: inline-flex; align-items: center; gap: 14px; padding: 17px 28px; border: 1px solid var(--border-2); font: 500 12px/1 var(--font-body); letter-spacing: .2em; text-transform: uppercase; color: #fff; white-space: nowrap; transition: background .2s, border-color .2s; }  /* .22s war der einzige Ausreisser der 0.2s-Familie (Review 20/10) */
.p-cta:hover { background: var(--red); border-color: var(--red); }
.p-band { position: relative; border-top: 1px solid rgba(255,255,255,.14); border-bottom: 1px solid rgba(255,255,255,.14); background: #0f0f0f; overflow: hidden; -webkit-mask-image: linear-gradient(90deg,transparent 0,#000 11%,#000 89%,transparent 100%); mask-image: linear-gradient(90deg,transparent 0,#000 11%,#000 89%,transparent 100%); }
.p-spur { display: flex; width: max-content; }
@media (prefers-reduced-motion: no-preference) {
  .p-spur { animation: p-tick 40s linear infinite; }
  .p-spur-rev { animation: p-tick 26s linear infinite reverse; }
}
/* DREI Saetze, Versatz um ein Drittel — nicht mehr zwei Saetze um die Haelfte.
   GEMESSEN war das ein echter Fehler: ein Satz ist 5 x 272 px = 1360 px breit.
   Bei zwei Saetzen wandert die Spur um 1360 px, es bleiben also 1360 px
   Inhalt stehen — auf einem 1440er-Bildschirm ist das Band aber 1430 px
   breit. Am Ende jedes Umlaufs lief rechts eine Luecke von rund 70 px mit,
   die mit dem Fenster mitwaechst. Mit drei Saetzen bleiben nach dem Versatz
   2720 px stehen, das deckt jede uebliche Fensterbreite.
   Der frueher hier stehende Hover-Stopp (`.p-band:hover .p-spur {
   animation-play-state: paused }`) ist auf Inhaber-Wunsch entfallen — das
   Band soll durchlaufen. Fuer Nutzer, die Bewegung nicht vertragen, greift
   weiterhin die Klammer `prefers-reduced-motion` daruber: dort wird die
   Animation gar nicht erst deklariert und das Band steht still. */
@keyframes p-tick { from { transform: translate3d(0,0,0); } to { transform: translate3d(-33.3333%,0,0); } }
.p-satz { display: flex; align-items: stretch; }
.pz { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; width: 272px; height: 172px; border-right: 1px solid rgba(255,255,255,.07); transition: background .25s; }
.pz:hover { background: #161616; }
.pz img { opacity: .82; transition: opacity .25s; width: auto; max-width: 200px; object-fit: contain; }
.pz:hover img { opacity: 1; }
.pz span { font: 500 11px/1 var(--font-body); letter-spacing: .18em; text-transform: uppercase; color: var(--text-secondary); }
.p-band-b { display: none; border-top: 0; }
.pzm { display: flex; align-items: center; justify-content: center; width: 156px; height: 96px; border-right: 1px solid rgba(255,255,255,.07); }
.pzm img { opacity: .86; width: auto; max-width: 120px; object-fit: contain; }
.p-fuss { display: flex; align-items: center; gap: 20px; padding-top: 26px; }
.p-fuss .strich { width: 26px; height: 2px; background: var(--red); }
.p-fuss .txt { font: 500 11px/1 var(--font-body); letter-spacing: .18em; text-transform: uppercase; color: var(--text-secondary); }
.p-fuss .linie { flex: 1; height: 1px; background: rgba(255,255,255,.08); }
.p-fuss .mono { font: 500 11px/1 var(--font-mono); letter-spacing: .14em; color: var(--text-muted); }
@media (max-width: 767px) {
  /* 58/54 war der einzige Off-Scale-Wert der Site und mobil spuerbar knapp:
     155 px Inhalts-Gap nach einem 192-236er Takt (Review 20/5 B2). 64 ist die
     vorhandene sm-Stufe (--section-y-sm) — minimal-invasiv, landet auf der
     Skala, aendert den Charakter des Bandes nicht. Desktop bleibt 88/84. */
  .partner { padding: 64px 0; }
  .p-kopf { grid-template-columns: 1fr; gap: 0; margin-bottom: 32px; }
  .p-cta { display: flex; justify-content: center; min-height: 54px; margin-top: 24px; background: var(--red); border-color: var(--red); }
  .pz { width: 156px; height: 96px; gap: 0; }
  .pz img { transform: scale(.68); }
  .pz span { display: none; }
  .p-band-b { display: block; }
  .p-fuss .txt { letter-spacing: .1em; }
  .p-fuss .mono, .p-fuss .linie { display: none; }
}
