@charset "UTF-8";
/* =====================================================================
   KFZ Eckel Meisterbetrieb – Gestaltung

   Durchgehend dunkel, weil das Wappen dunkel ist: neutrales Graphit als
   Grundton, aufgehellte Flächen für Karten, poliertes Silber als einziger
   Akzent. Die Seite ist einfarbig wie das Wappen – schwarzes Email,
   silberne Prägung, sonst nichts. Auszeichnung entsteht dadurch allein
   über Helligkeit, nicht über einen zweiten Farbton. Ein getönter
   Grundton (früher Petrol, dann Messing) legt sich über jedes Foto und
   jede Statusfarbe und macht sie schmutzig.

   Typografie: Archivo für alles Gesetzte, IBM Plex Mono für Messwerte –
   Uhrzeiten, Preise, Kennzeichen. Zahlen sind hier Technik, keine Deko.
   Die Breitenachse der Schrift bleibt auf Normalbreite; gedehnte oder
   gestauchte Buchstabenformen sind der schnellste Weg zu billigem Satz.
   Auszeichnung passiert über Gewicht, Größe und Laufweite.

   Bewegung: Alles leitet sich von mechanischer Bewegung ab. Überschriften
   wandern wie ein Kolben im Zylinder nach oben ins Bild, Linien laufen aus
   wie ein Messschieber, Zahlen pendeln sich ein wie ein Zeiger. Nichts
   federt, nichts hüpft. Siehe Abschnitt "Bewegung" ganz unten.
   ===================================================================== */

/* ---------------------------------------------------------------------
   Schriften – lokal gehostet, kein Aufruf an fremde Server
   --------------------------------------------------------------------- */
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-400-800.woff2') format('woff2-variations');
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-ext-400-800.woff2') format('woff2-variations');
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('../fonts/plexmono-latin-400.woff2') format('woff2');
  font-weight: 400; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('../fonts/plexmono-latin-ext-400.woff2') format('woff2');
  font-weight: 400; font-display: swap;
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+2020, U+20A0-20AB, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('../fonts/plexmono-latin-600.woff2') format('woff2');
  font-weight: 600; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('../fonts/plexmono-latin-ext-600.woff2') format('woff2');
  font-weight: 600; font-display: swap;
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+2020, U+20A0-20AB, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------------
   Gestaltungsvariablen
   --------------------------------------------------------------------- */
:root {
  /* Flächen, von tief nach hoch – neutrales Graphit ohne Farbstich */
  --sunk:     #0a0a0b;   /* abgesetzte Bänder, Fußzeile */
  --void:     #111113;   /* Grundfläche der Seite */
  --raise:    #191a1d;   /* Karten */
  --raise-2:  #222327;   /* Karten im Hover, Eingabefelder */
  --graphite: #1d1e22;   /* Markenfläche, Aufmacher */

  --line:      #2b2c31;
  --line-soft: rgba(230, 233, 237, .085);

  /* Schrift – kühles Silber, kein Elfenbein. Der Ton folgt dem Wappen:
     weiße Prägung auf schwarzem Email, ohne Gelbstich. */
  --enamel:    #e6e9ed;
  --steel:     #979ca2;
  --steel-dim: #6b7076;

  /* Akzent: poliertes Silber statt Messing. Drei Stufen, weil Silber
     seine Auszeichnung allein über die Helligkeit macht – eine zweite
     Farbe, die den Unterschied trüge, gibt es hier nicht mehr.
       dim  steht unter der Lauftextfarbe: Auszeichnungszeilen, Marken
       hell steht als Fläche und Linie für sich: Kanten, Fäden, Knöpfe
       lit  ist das Spitzlicht beim Überfahren */
  --chrome-dim:  #a9b0b8;
  --chrome:      #dfe4ea;
  --chrome-lit:  #ffffff;
  --chrome-wash: rgba(223, 228, 234, .10);
  --chrome-edge: rgba(223, 228, 234, .34);

  /* Zustandsfarben. Bewusst stark heruntergesetzt: Sie sind kein
     Gestaltungsmittel mehr, sondern nur noch das Nötigste, damit ein
     Formularfehler nicht wie ein Hinweis aussieht. */
  --rust:      #bf6d5b;
  --rust-wash: rgba(191, 109, 91, .13);
  --ok:        #7fa694;
  --ok-wash:   rgba(127, 166, 148, .12);

  /* Dunkler Gegenpart auf Silberflächen – neutral wie der Grund des
     Wappens, damit die Schrift nicht gegen das Silber kippt. */
  --on-chrome: #0b0c0d;

  /* Typografie */
  --font-sans: 'Archivo', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --font-mono: 'Plex Mono', 'SFMono-Regular', Consolas, monospace;

  /* Raster */
  --page:    76rem;
  --page-sm: 60rem;
  --gutter:  clamp(1.25rem, 4vw, 3rem);

  /* Abstände */
  --sp-1: .25rem;  --sp-2: .5rem;   --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;
  --sp-9: 6rem;

  --radius: 4px;
  --radius-lg: 6px;

  --ring: 0 0 0 3px rgba(223, 228, 234, .32);
  --shadow-card: 0 1px 1px rgba(0, 0, 0, .4), 0 18px 40px -28px rgba(0, 0, 0, .9);

  /* Bewegung: entschlossen anfahren, weich auslaufen – wie ein
     gut eingestellter Mechanismus, nicht wie eine Feder. */
  --ease:      cubic-bezier(.16, .84, .44, 1);
  --ease-mech: cubic-bezier(.62, .02, .2, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
  background: var(--void);
  color-scheme: dark;
}

body {
  margin: 0;
  background: var(--void);
  color: var(--enamel);
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  /* Normalbreite, überall. Wird nirgends mehr überschrieben. */
  font-variation-settings: 'wdth' 100;
  font-kerning: normal;
  font-variant-ligatures: common-ligatures contextual;
  /* Kein künstliches Fetten oder Kursivieren – die Schrift bringt beides
     selbst mit, die synthetische Fassung sieht ausgefranst aus. */
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

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

a { color: inherit; text-underline-offset: .18em; }

:focus-visible {
  outline: 2px solid var(--chrome-lit);
  outline-offset: 3px;
  border-radius: 2px;
}

hr { border: 0; border-top: 1px solid var(--line); margin: var(--sp-6) 0; }

::selection { background: var(--chrome); color: var(--sunk); }

::-webkit-scrollbar { width: 12px; height: 10px; }
::-webkit-scrollbar-track { background: var(--sunk); }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; border: 3px solid var(--sunk); }
::-webkit-scrollbar-thumb:hover { background: var(--chrome); }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--chrome); color: var(--sunk);
  padding: .75rem 1.25rem; font-weight: 700;
}
.skip-link:focus { left: .5rem; top: .5rem; }

/* Überschriften, die die Gliederung für Screenreader und Suchmaschinen
   vollständig machen, ohne im Satzbild aufzutauchen. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------
   Typografische Bausteine
   --------------------------------------------------------------------- */
/* Auszeichnung über Gewicht und Größe, nicht über die Breitenachse.
   Große Grade brauchen etwas engere Laufweite als kleine – deshalb ist
   das Negativ-Kerning gestaffelt und nicht pauschal. */
h1, h2, h3, h4 {
  margin: 0 0 var(--sp-4);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.011em;
  text-wrap: balance;
  color: var(--enamel);
}

.t-display {
  font-size: clamp(2.35rem, 5.6vw, 4rem);
  font-weight: 700;
  letter-spacing: -.021em;
  line-height: 1.07;
}
.t-h2 {
  font-size: clamp(1.7rem, 3.2vw, 2.4rem);
  letter-spacing: -.016em;
  line-height: 1.16;
}
.t-h3 { font-size: 1.2rem; letter-spacing: -.008em; line-height: 1.3; }

/* Abschnittskennzeichnung. Gesperrter Versalsatz in kleinem Grad – die
   Laufweite macht die Auszeichnung, nicht eine gedehnte Schriftbreite. */
.eyebrow {
  display: block;
  margin: 0 0 var(--sp-3);
  font-size: .715rem;
  font-weight: 600;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--chrome-dim);
}
.eyebrow--onDark { color: var(--chrome); }

.lede {
  font-size: clamp(1.06rem, 1.6vw, 1.25rem);
  line-height: 1.6;
  color: var(--steel);
  max-width: 46ch;
  text-wrap: pretty;
}
.lede--onDark { color: rgba(230, 233, 237, .74); }

/* Messwerte: Uhrzeiten, Preise, Dauer, Kennzeichen, Referenzen */
/* Kein Negativ-Kerning: Eine Festbreitenschrift hat ihre Laufweite in der
   Vorbreite jedes Zeichens, Zusammenziehen bringt die Ziffern nur außer
   Tritt mit ihrem eigenen Raster. */
.data {
  font-family: var(--font-mono);
  font-size: .92em;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.muted { color: var(--steel); }
.small { font-size: .875rem; }

/* ---------------------------------------------------------------------
   Layout
   --------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: var(--page-sm); }

.section { padding-block: clamp(3.5rem, 8vw, var(--sp-9)); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 3.5rem); }
.section--dark { background: var(--sunk); }
/* Wechselfläche. Folgt direkt auf das Oldtimer-Band – wäre sie ebenfalls
   abgesenkt, würden beide Abschnitte zu einer Fläche verschwimmen. */
.section--alt { background: var(--void); }

.section-head { max-width: 44rem; margin-bottom: var(--sp-7); }

.stack > * + * { margin-top: var(--sp-4); }

/* ---------------------------------------------------------------------
   Kopfleiste

   Verdichtet sich beim Scrollen: Sie wird flacher, legt sich vor den
   Inhalt und blendet die Unterzeile aus. Das ist keine Spielerei – es
   gibt beim Lesen spürbar Fläche zurück.
   --------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(9, 9, 10, .82);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid transparent;
  transition: border-color .35s var(--ease), background-color .35s var(--ease);
}
.site-header[data-scrolled='true'] {
  background: rgba(9, 9, 10, .94);
  border-bottom-color: var(--line);
}

.site-header__inner {
  display: flex; align-items: center; gap: var(--sp-5);
  min-height: 4.75rem;
  transition: min-height .35s var(--ease);
}
/* Beim Scrollen rückt die Zeile spürbar zusammen: 3,4 rem sind knapp
   fünf Pixel mehr, als der Knopf am rechten Rand hoch ist. Enger geht
   nur, wenn auch der Knopf kleiner wird – und ein Knopf, der beim
   Scrollen schrumpft, ist ein Ziel, das sich unter dem Zeiger wegzieht. */
.site-header[data-scrolled='true'] .site-header__inner { min-height: 3.4rem; }

/* Lesefortschritt als Silberfaden an der Unterkante */
.site-header__progress {
  position: absolute; inset: auto 0 -1px 0;
  height: 2px;
  background: var(--chrome);
  transform: scaleX(var(--progress, 0));
  transform-origin: left;
  opacity: 0;
  transition: opacity .3s var(--ease);
}
.site-header[data-scrolled='true'] .site-header__progress { opacity: 1; }

.brand {
  display: flex; align-items: center; gap: .75rem;
  text-decoration: none; color: inherit;
  margin-right: auto;
}
.brand__text { display: flex; flex-direction: column; line-height: 1; }
.brand__name {
  font-size: 1.08rem; font-weight: 700;
  letter-spacing: .085em; text-transform: uppercase;
  transition: font-size .35s var(--ease);
}
.brand__sub {
  margin-top: .34rem;
  font-size: .625rem; font-weight: 600;
  letter-spacing: .155em; text-transform: uppercase;
  color: var(--chrome-dim);
  max-height: 1.2em; opacity: 1;
  overflow: hidden;
  transition: max-height .35s var(--ease), opacity .25s var(--ease),
              margin-top .35s var(--ease);
}
.site-header[data-scrolled='true'] .brand__sub {
  max-height: 0; opacity: 0; margin-top: 0;
}

/* --- Bildmarke: der laufende Kurbeltrieb -----------------------------
   Pleuellänge 70 Einheiten, Kurbelradius 8, daraus Hub 16 und höchstens
   6,56 Grad Pleuelschwenk. Der Aufbau des SVG steht in piston-mark.php.

   Zwei getrennte Bewegungen, gleiche Dauer, gleiche Phase: der Kolben
   gleitet in der Laufbahn, das Pleuel schwenkt um den Bolzen. Erst beides
   zusammen führt das große Pleuelauge auf einem Kreis um die Kurbelmitte –
   die Bewegung, an der man einen Kurbeltrieb erkennt. Eine einzelne
   Verschiebung der ganzen Gruppe sieht dagegen aus, wie sie ist: ein
   verschobenes Bild.

   Die Drehzahl steuert site.js über die Abspielrate, damit sie beim
   Überfahren weich hochläuft. Ohne JavaScript bleibt es beim Leerlauf.
   --------------------------------------------------------------------- */
.piston-mark {
  width: 2.5rem; height: 2.5rem; flex: none;
  color: var(--enamel);
  transition: width .35s var(--ease), height .35s var(--ease), color .3s var(--ease);
}
.site-header[data-scrolled='true'] .piston-mark { width: 2.05rem; height: 2.05rem; }

/* Der vordere Kolben wirft einen Schatten auf den hinteren. Ohne ihn
   kreuzen sich an der Überschneidung nur zwei Striche und es ist nicht zu
   sehen, welcher Kolben oben liegt.

   Der Filter sitzt auf der ungeneigten Hülle, nicht auf dem Zylinder
   selbst: Ein Versatz im gedrehten System würde mit der Neigung kippen,
   das Licht käme dann bei jedem Kolben aus einer anderen Richtung. So
   fällt der Schatten für beide nach unten links, passend zur Lichtführung
   des Wappens im Aufmacher.

   Längen sind hier viewBox-Einheiten, nicht Bildschirmpixel: Bei 2,5 rem
   Darstellung entspricht eine Einheit knapp einem Drittel Pixel. */
.piston-mark__front {
  filter: drop-shadow(-3.5px 4.5px 3px rgba(0, 0, 0, .85));
}

.piston-mark__slide,
.piston-mark__rod {
  animation-duration: 1.5s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform;
}
.piston-mark__slide { animation-name: piston-slide; }
.piston-mark__rod   { animation-name: piston-rod; }

.brand:hover .piston-mark { color: var(--chrome-lit); }

/* Stützstellen alle 15 Grad Kurbelwinkel, gerechnet aus
   s(θ) = r(1−cos θ) + l(1−√(1−λ² sin²θ))  und  β(θ) = arcsin(λ sin θ)
   mit λ = r/l = 8/70. Die Zeitkennlinie ist deshalb linear: Der Kolben
   steht ungleichförmig, weil das Pleuel endlich lang ist, nicht weil eine
   Beschleunigungskurve darüber liegt. Am oberen Totpunkt kehrt er schneller
   um als am unteren – nach einem Viertel der Umdrehung hat er schon mehr
   als die Hälfte des Hubs hinter sich. */
@keyframes piston-slide {
  0%       { transform: translateY(0); }
  4.1667%  { transform: translateY(0.303px); }
  8.3333%  { transform: translateY(1.186px); }
  12.5%    { transform: translateY(2.572px); }
  16.6667% { transform: translateY(4.344px); }
  20.8333% { transform: translateY(6.357px); }
  25%      { transform: translateY(8.459px); }
  29.1667% { transform: translateY(10.498px); }
  33.3333% { transform: translateY(12.344px); }
  37.5%    { transform: translateY(13.886px); }
  41.6667% { transform: translateY(15.043px); }
  45.8333% { transform: translateY(15.758px); }
  50%      { transform: translateY(16px); }
  54.1667% { transform: translateY(15.758px); }
  58.3333% { transform: translateY(15.043px); }
  62.5%    { transform: translateY(13.886px); }
  66.6667% { transform: translateY(12.344px); }
  70.8333% { transform: translateY(10.498px); }
  75%      { transform: translateY(8.459px); }
  79.1667% { transform: translateY(6.357px); }
  83.3333% { transform: translateY(4.344px); }
  87.5%    { transform: translateY(2.572px); }
  91.6667% { transform: translateY(1.186px); }
  95.8333% { transform: translateY(0.303px); }
  100%     { transform: translateY(0); }
}

/* Der Schwenk steht bei halbem Hub am Anschlag und ist am Totpunkt null –
   deshalb ist er gegen den Hub um eine Vierteldrehung versetzt. */
@keyframes piston-rod {
  0%       { transform: rotate(0deg); }
  4.1667%  { transform: rotate(1.695deg); }
  8.3333%  { transform: rotate(3.276deg); }
  12.5%    { transform: rotate(4.635deg); }
  16.6667% { transform: rotate(5.68deg); }
  20.8333% { transform: rotate(6.338deg); }
  25%      { transform: rotate(6.562deg); }
  29.1667% { transform: rotate(6.338deg); }
  33.3333% { transform: rotate(5.68deg); }
  37.5%    { transform: rotate(4.635deg); }
  41.6667% { transform: rotate(3.276deg); }
  45.8333% { transform: rotate(1.695deg); }
  50%      { transform: rotate(0deg); }
  54.1667% { transform: rotate(-1.695deg); }
  58.3333% { transform: rotate(-3.276deg); }
  62.5%    { transform: rotate(-4.635deg); }
  66.6667% { transform: rotate(-5.68deg); }
  70.8333% { transform: rotate(-6.338deg); }
  75%      { transform: rotate(-6.562deg); }
  79.1667% { transform: rotate(-6.338deg); }
  83.3333% { transform: rotate(-5.68deg); }
  87.5%    { transform: rotate(-4.635deg); }
  91.6667% { transform: rotate(-3.276deg); }
  95.8333% { transform: rotate(-1.695deg); }
  100%     { transform: rotate(0deg); }
}

/* --- Navigation ----------------------------------------------------- */
.nav { display: flex; align-items: center; gap: clamp(.9rem, 2vw, 1.9rem); }
/* Ohne :not(.btn) greift diese Regel auch auf die Schaltfläche in der
   Leiste durch – sie ist spezifischer als .btn und würde deren
   Bewegungsliste auf ein einzelnes „color" eindampfen. Die Schaltfläche
   stünde dann als einzige der Seite still. */
.nav > a:not(.btn),
.nav-services > summary {
  position: relative;
  text-decoration: none;
  font-size: .9rem; font-weight: 600;
  color: rgba(230, 233, 237, .74);
  padding-block: .45rem;
  transition: color .2s var(--ease);
}
.nav > a:not(.btn)::after,
.nav-services > summary::after {
  content: '';
  position: absolute; inset: auto 0 0 0;
  height: 2px; background: var(--chrome);
  transform: scaleX(0); transform-origin: left;
  transition: transform .32s var(--ease);
}
.nav > a:not(.btn):hover,
.nav-services > summary:hover { color: var(--enamel); }
.nav > a:not(.btn):hover::after,
.nav > a:not(.btn)[aria-current='page']::after,
.nav-services:hover > summary::after,
.nav-services[open] > summary::after,
.nav-services[data-current='true'] > summary::after { transform: scaleX(1); }
.nav > a:not(.btn)[aria-current='page'],
.nav-services[open] > summary,
.nav-services[data-current='true'] > summary { color: var(--enamel); }

/* Leistungsmenü: Auf großen Bildschirmen als ruhiges Mega-Menü, auf dem
   Handy als nativer, per Tastatur bedienbarer Aufklappbereich. */
.nav-services { position: relative; }
.nav-services > summary {
  display: flex; align-items: center; gap: .48rem;
  list-style: none;
  cursor: pointer;
}
.nav-services > summary::-webkit-details-marker { display: none; }
.nav-services > summary:focus-visible {
  outline: 2px solid var(--chrome);
  outline-offset: .3rem;
}
.nav-services__chevron {
  width: .42rem; height: .42rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-.12rem);
  transition: transform .22s var(--ease);
}
.nav-services[open] .nav-services__chevron {
  transform: rotate(-135deg) translate(-.05rem, -.05rem);
}
.nav-services__panel {
  /* `display` überschreibt die Browserregel für geschlossene details. Die
     unsichtbare Fläche bleibt dank visibility auch aus der Tab-Reihenfolge. */
  display: grid;
  position: absolute;
  top: 100%; left: 50%;
  width: min(46rem, calc(100vw - 2 * var(--gutter)));
  padding-top: .8rem;
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translate(-55%, -.4rem);
  transition: opacity .2s var(--ease), transform .25s var(--ease), visibility .2s;
  z-index: 30;
}
.nav-services:hover > .nav-services__panel,
.nav-services:focus-within > .nav-services__panel,
.nav-services[open] > .nav-services__panel {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translate(-55%, 0);
}
.nav-services__surface {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: .8rem;
  background:
    radial-gradient(circle at 100% 0, rgba(230, 233, 237, .09), transparent 34%),
    linear-gradient(145deg, rgba(255, 255, 255, .045), transparent 42%),
    rgba(13, 13, 15, .99);
  border: 1px solid rgba(230, 233, 237, .16);
  border-top-color: rgba(230, 233, 237, .34);
  border-radius: calc(var(--radius) + 2px);
  box-shadow: 0 24px 55px rgba(0, 0, 0, .48);
}
.nav-services__surface::before {
  content: '';
  position: absolute; inset: 0 12% auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .78), transparent);
  opacity: .68;
  pointer-events: none;
}
.nav-services__all,
.nav-services__item {
  position: relative;
  color: var(--enamel);
  text-decoration: none;
  border-radius: var(--radius);
  transition: color .2s var(--ease), background-color .2s var(--ease),
              border-color .2s var(--ease), transform .2s var(--ease),
              box-shadow .2s var(--ease);
}
.nav-services__all {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin-bottom: .65rem;
  padding: .82rem .9rem .82rem 1rem;
  background:
    linear-gradient(100deg, rgba(230, 233, 237, .11), rgba(230, 233, 237, .035));
  border: 1px solid rgba(230, 233, 237, .14);
}
.nav-services__all-copy { display: grid; gap: .12rem; min-width: 0; }
.nav-services__all-copy small {
  color: var(--chrome);
  font-size: .57rem; font-weight: 700; line-height: 1.2;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.nav-services__all-copy strong { font-size: .94rem; line-height: 1.25; }
.nav-services__all-copy > span {
  color: rgba(230, 233, 237, .58);
  font-size: .71rem; font-weight: 400; line-height: 1.35;
}
.nav-services__all-arrow {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 2.15rem; height: 2.15rem;
  color: var(--enamel);
  background: rgba(230, 233, 237, .08);
  border: 1px solid rgba(230, 233, 237, .18);
  border-radius: 50%;
  transition: color .2s var(--ease), background-color .2s var(--ease),
              transform .25s var(--ease);
}
.nav-services__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .38rem;
}
.nav-services__item {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) 1.15rem;
  align-items: center;
  gap: .68rem;
  min-height: 4.35rem;
  padding: .62rem .7rem;
  background: rgba(230, 233, 237, .018);
  border: 1px solid rgba(230, 233, 237, .065);
}
.nav-services__number {
  display: grid; place-items: center;
  width: 2rem; height: 2rem;
  color: rgba(230, 233, 237, .48);
  background: rgba(0, 0, 0, .2);
  border: 1px solid rgba(230, 233, 237, .11);
  border-radius: 50%;
  font-family: var(--font-data); font-size: .63rem; line-height: 1;
  letter-spacing: .03em;
  transition: color .2s var(--ease), border-color .2s var(--ease),
              background-color .2s var(--ease);
}
.nav-services__copy { display: grid; gap: .16rem; min-width: 0; }
.nav-services__copy strong { font-size: .82rem; line-height: 1.3; }
.nav-services__copy small {
  color: rgba(230, 233, 237, .5);
  font-size: .68rem; font-weight: 400; line-height: 1.35;
}
.nav-services__item-arrow {
  color: var(--chrome);
  font-size: .9rem;
  opacity: 0;
  transform: translateX(-.3rem);
  transition: opacity .2s var(--ease), transform .22s var(--ease);
}
.nav-services__all:hover,
.nav-services__all:focus-visible,
.nav-services__item:hover,
.nav-services__item:focus-visible,
.nav-services__all[aria-current='page'],
.nav-services__item[aria-current='page'] {
  color: #fff;
  background: rgba(230, 233, 237, .085);
  border-color: rgba(230, 233, 237, .19);
  transform: translateY(-1px);
  box-shadow: inset 2px 0 0 rgba(230, 233, 237, .72);
  outline: none;
}
.nav-services__all:hover .nav-services__all-arrow,
.nav-services__all:focus-visible .nav-services__all-arrow {
  color: var(--on-chrome);
  background: var(--chrome);
  transform: translateX(.15rem);
}
.nav-services__item:hover .nav-services__number,
.nav-services__item:focus-visible .nav-services__number,
.nav-services__item[aria-current='page'] .nav-services__number {
  color: var(--enamel);
  background: rgba(230, 233, 237, .075);
  border-color: rgba(230, 233, 237, .28);
}
.nav-services__item:hover .nav-services__item-arrow,
.nav-services__item:focus-visible .nav-services__item-arrow {
  opacity: 1;
  transform: translateX(0);
}
.nav-services__item:hover small,
.nav-services__item:focus-visible small { color: rgba(230, 233, 237, .72); }

.nav-toggle {
  display: none;
  position: relative;
  width: 2.9rem; height: 2.4rem;
  background: none; border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  cursor: pointer;
}
.nav-toggle span {
  position: absolute; left: 50%; translate: -50% 0;
  width: 1.1rem; height: 2px; background: var(--enamel);
  transition: transform .3s var(--ease), opacity .2s var(--ease);
}
.nav-toggle span:nth-child(1) { top: .75rem; }
.nav-toggle span:nth-child(2) { top: 1.15rem; }
.nav-toggle span:nth-child(3) { top: 1.55rem; }
.nav-toggle[aria-expanded='true'] span:nth-child(1) { transform: translateY(.4rem) rotate(45deg); }
.nav-toggle[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded='true'] span:nth-child(3) { transform: translateY(-.4rem) rotate(-45deg); }

@media (max-width: 60rem) {
  .nav-toggle { display: block; }
  .nav {
    position: absolute; inset: 100% 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: rgba(9, 9, 10, .98);
    backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--line);
    padding: var(--sp-2) var(--gutter) var(--sp-5);
    max-height: calc(100svh - 4.5rem);
    overflow-y: auto;
    /* Fährt herunter statt zu erscheinen */
    display: flex;
    transform-origin: top;
    transform: scaleY(0);
    opacity: 0;
    pointer-events: none;
    transition: transform .3s var(--ease), opacity .2s var(--ease);
  }
  .nav[data-open='true'] { transform: scaleY(1); opacity: 1; pointer-events: auto; }
  /* Die Trennlinien und die größere Zeilenhöhe gelten für die Einträge,
     nicht für die Schaltfläche – die bringt ihre eigene Form mit. */
  .nav > a:not(.btn),
  .nav-services > summary {
    padding: .9rem 0; font-size: 1rem;
    border-bottom: 1px solid var(--line-soft);
  }
  .nav-services { width: 100%; }
  .nav-services > summary { justify-content: space-between; }
  .nav-services > summary::after { display: none; }
  .nav-services__panel {
    display: none;
    position: static;
    width: 100%;
    padding: 0;
    opacity: 1; visibility: visible; pointer-events: auto;
    transform: none;
    transition: none;
  }
  .nav-services[open] > .nav-services__panel { display: block; }
  .nav-services__surface {
    padding: .4rem 0 .7rem 1rem;
    background: transparent;
    border: 0;
    border-left: 2px solid rgba(230, 233, 237, .16);
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
  }
  .nav-services__surface::before { display: none; }
  .nav-services__all { margin: 0; border: 0; }
  .nav-services__grid { grid-template-columns: 1fr; gap: 0; }
  .nav-services__all,
  .nav-services__item {
    padding: .62rem .75rem;
    background: transparent;
    border-color: transparent;
    transform: none;
    box-shadow: none;
  }
  .nav-services__all { min-height: 2.9rem; }
  .nav-services__all-copy small,
  .nav-services__all-copy > span,
  .nav-services__copy small { display: none; }
  .nav-services__all-copy strong,
  .nav-services__copy strong { font-size: .9rem; }
  .nav-services__all-arrow { width: 1.85rem; height: 1.85rem; }
  .nav-services__item {
    grid-template-columns: 1.7rem minmax(0, 1fr);
    min-height: 2.85rem;
    gap: .62rem;
  }
  .nav-services__number { width: 1.7rem; height: 1.7rem; font-size: .57rem; }
  .nav-services__item-arrow { display: none; }
  /* Hereinfahren gilt für alle, auch für die Schaltfläche. Bei ihr kommt
     die Bewegung zu ihrer eigenen Liste dazu, statt sie zu ersetzen. */
  .nav > a,
  .nav > .nav-services { opacity: 0; translate: 0 -8px; }
  .nav > a:not(.btn),
  .nav > .nav-services { transition: opacity .3s var(--ease), translate .3s var(--ease); }
  .nav > a.btn {
    transition: opacity .3s var(--ease), translate .3s var(--ease),
                transform .2s var(--ease), background-color .24s var(--ease),
                background-position .7s var(--ease-mech), color .24s var(--ease),
                border-color .24s var(--ease), box-shadow .24s var(--ease);
  }
  .nav[data-open='true'] > a,
  .nav[data-open='true'] > .nav-services { opacity: 1; translate: 0 0; }
  .nav[data-open='true'] > :nth-child(1) { transition-delay: .06s; }
  .nav[data-open='true'] > :nth-child(2) { transition-delay: .1s; }
  .nav[data-open='true'] > :nth-child(3) { transition-delay: .14s; }
  .nav[data-open='true'] > :nth-child(4) { transition-delay: .18s; }
  .nav[data-open='true'] > :nth-child(5) { transition-delay: .22s; }
  .nav[data-open='true'] > :nth-child(6) { transition-delay: .26s; }
  .nav > a:not(.btn)::after { display: none; }
  .nav > .btn { margin-top: var(--sp-4); text-align: center; justify-content: center; }
}

/* ---------------------------------------------------------------------
   Schaltflächen

   Zwei Bauteile, ein Prinzip. Die volle Fläche ist ein Stück geschliffenes
   Silber, die Umriss-Fassung dasselbe Blech, nur unpoliert.

   Auf dem Silber wandert beim Überfahren eine Spiegelung durch. Sie ist
   NICHT aus Weiß gebaut, sondern aus Abdunklung: Auf einer Fläche, die
   schon fast weiß ist, sieht man einen hellen Streifen nicht – auf
   poliertem Metall erkennt man eine Bewegung ohnehin daran, dass sich
   etwas Dunkles darin spiegelt, nicht daran, dass es heller wird. Zwei
   dunkle Bänder mit einem hellen Grat dazwischen laufen über die volle
   Breite; gebaut ist das als Verlauf mit doppelter Breite, der von rechts
   nach links geschoben wird (background-position, nicht Position eines
   Elements – das läuft auf der Kompositionsebene).

   Alles Bewegte hängt an Farbe, Schatten und zwei Pixeln Weg. Kein Federn,
   kein Wachsen: Eine Schaltfläche, die ihre Größe ändert, schiebt die
   Zeile daneben mit.
   --------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--chrome);
  --btn-fg: var(--on-chrome);
  --btn-bd: var(--chrome);

  /* Ebene 1: Licht von oben, steht fest. Ebene 2: die wandernde Spiegelung. */
  --btn-sheen:
    linear-gradient(180deg,
      rgba(255, 255, 255, .45) 0%,
      rgba(255, 255, 255, 0) 44%,
      rgba(0, 0, 0, .10) 100%),
    linear-gradient(100deg,
      rgba(0, 0, 0, 0) 0%,
      rgba(0, 0, 0, .16) 30%,
      rgba(0, 0, 0, .05) 44%,
      rgba(255, 255, 255, .9) 50%,
      rgba(0, 0, 0, .05) 56%,
      rgba(0, 0, 0, .16) 70%,
      rgba(0, 0, 0, 0) 100%);
  --btn-roll: 96%;

  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  gap: .55rem;
  padding: .82rem 1.5rem;
  background-color: var(--btn-bg);
  background-image: var(--btn-sheen);
  background-size: 100% 100%, 220% 100%;
  background-position: 0 0, var(--btn-roll) 0;
  background-repeat: no-repeat;
  color: var(--btn-fg);
  border: 2px solid var(--btn-bd); border-radius: var(--radius);
  font: inherit; font-size: .95rem; font-weight: 700;
  letter-spacing: .01em;
  text-decoration: none; cursor: pointer;
  overflow: hidden;
  transition: transform .2s var(--ease), background-color .24s var(--ease),
              background-position .7s var(--ease-mech),
              color .24s var(--ease), border-color .24s var(--ease),
              box-shadow .24s var(--ease);
}

/* Angehoben, aufgehellt, die Spiegelung läuft durch */
.btn:hover, .btn:focus-visible {
  --btn-bg: var(--chrome-lit);
  --btn-bd: var(--chrome-lit);
  --btn-roll: 4%;
  transform: translateY(-2px);
  box-shadow: 0 12px 26px -16px var(--chrome), 0 2px 0 -1px rgba(0, 0, 0, .5);
}
/* Beim Drücken setzt sie auf – kein Federn, nur Weg */
.btn:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 6px -2px rgba(0, 0, 0, .45);
  transition-duration: .06s;
}

.btn[disabled], .btn[aria-disabled='true'] {
  opacity: .38; cursor: not-allowed; transform: none; box-shadow: none;
}

/* --- Umriss auf heller wie auf dunkler Fläche ------------------------ */
.btn--ghost, .btn--ghostLight {
  --btn-bg: transparent;
  --btn-fg: var(--enamel);
  --btn-bd: var(--line);
  --btn-sheen: none;
}
.btn--ghostLight { --btn-bd: rgba(230, 233, 237, .3); }

/* Fläche und Schrift wechseln gemeinsam, nicht nacheinander.
   Eine Fläche, die von links einfährt, sähe mechanischer aus – aber solange
   sie unter der Schrift durchwandert, steht die eine Hälfte des Wortes auf
   Silber und die andere auf Graphit. Eine der beiden Hälften ist dabei immer
   unlesbar. Lieber ein sauberer Wechsel als ein hübscher Zwischenzustand. */
.btn--ghost:hover, .btn--ghost:focus-visible,
.btn--ghostLight:hover, .btn--ghostLight:focus-visible {
  --btn-bg: var(--chrome);
  --btn-fg: var(--on-chrome);
  --btn-bd: var(--chrome);
  box-shadow: 0 12px 26px -18px var(--chrome);
}

.btn--danger {
  --btn-bg: transparent; --btn-fg: var(--rust); --btn-bd: var(--rust);
  --btn-sheen: none;
}
.btn--danger:hover, .btn--danger:focus-visible {
  --btn-bg: var(--rust); --btn-fg: #fff; --btn-bd: var(--rust);
  box-shadow: 0 12px 26px -18px var(--rust);
}

.btn--sm { padding: .55rem 1rem; font-size: .85rem; }
.btn--block { display: flex; width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }

/* ---------------------------------------------------------------------
   Bestätigungsdialoge

   Ersetzt die vom Browser gezeichneten Rückfragen. Der sichere Ausweg steht
   zuerst und erhält beim Öffnen den Fokus; folgenschwere Aktionen behalten
   ihre rostrote Kennzeichnung.
   --------------------------------------------------------------------- */
.confirm-modal {
  width: min(30rem, calc(100vw - 2rem));
  max-width: none;
  margin: auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--enamel);
  overflow: visible;
}
.confirm-modal[open] { animation: confirm-modal-in .18s var(--ease) both; }
.confirm-modal::backdrop {
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(3px);
}
.confirm-modal__panel {
  overflow: hidden;
  background: var(--raise);
  border: 1px solid var(--chrome-edge);
  border-radius: var(--radius-lg);
  box-shadow: 0 1.5rem 5rem rgba(0, 0, 0, .65);
}
.confirm-modal--danger .confirm-modal__panel { border-color: rgba(176, 91, 68, .58); }
.confirm-modal__head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  background: var(--sunk);
}
.confirm-modal__head h2 {
  margin: 0;
  color: var(--enamel);
  font-size: 1.1rem;
}
.confirm-modal__icon {
  display: grid;
  place-items: center;
  width: 1.65rem;
  height: 1.65rem;
  flex: 0 0 auto;
  border: 1px solid var(--chrome-edge);
  border-radius: 50%;
  color: var(--chrome);
  font: 700 .82rem/1 var(--font-mono);
}
.confirm-modal--danger .confirm-modal__icon {
  border-color: var(--rust);
  color: var(--rust);
}
.confirm-modal__message {
  margin: 0;
  padding: var(--sp-5);
  color: var(--steel);
  line-height: 1.65;
}
.confirm-modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-3);
  padding: 0 var(--sp-5) var(--sp-5);
}

@keyframes confirm-modal-in {
  from { opacity: 0; transform: translateY(.4rem) scale(.985); }
  to { opacity: 1; transform: none; }
}

@media (max-width: 30rem) {
  .confirm-modal { width: calc(100vw - 1rem); }
  .confirm-modal__head,
  .confirm-modal__message { padding: var(--sp-4); }
  .confirm-modal__actions {
    display: grid;
    grid-template-columns: 1fr;
    padding: 0 var(--sp-4) var(--sp-4);
  }
  .confirm-modal__actions .btn { width: 100%; }
}

/* Im Fließtext gewinnt sonst `.prose a` mit seiner höheren Spezifität und
   färbt die Schrift der Schaltfläche hell – hell auf Silber liest niemand.
   Dasselbe gilt für die Zusammenfassungskarte. */
.prose a.btn, .prose a.btn:hover,
.summary a.btn, .summary a.btn:hover,
.info-list a.btn, .info-list a.btn:hover {
  color: var(--btn-fg);
  text-decoration: none;
}

/* ---------------------------------------------------------------------
   Aufmacher
   --------------------------------------------------------------------- */
.hero {
  /* Der Aufmacher füllt das Fenster, abzüglich der Kopfleiste, die in ihrer
     ungescrollten Form 4.75rem hoch ist. Was darin steht, steht vollständig
     darin: Bild, Satz, das Kennfeld mit den freien Terminen und der Hinweis
     nach unten. Erst danach beginnt die Seite.

     svh und nicht vh: Auf dem Telefon ist vh die Höhe ohne die Leisten des
     Browsers, und der Aufmacher wäre dort um deren Höhe zu hoch.

     min-height und nicht height: Wird der Inhalt höher als das Fenster – im
     Querformat, bei großer Schrift, mit vielen freien Terminen –, wächst
     der Abschnitt mit, statt seinen eigenen Inhalt abzuschneiden. */
  min-height: calc(100svh - 4.75rem);
  display: flex;
  flex-direction: column;

  position: relative;
  background: var(--graphite);
  overflow: hidden;
  /* Eigener Stapelraum: darin liegen Halle (0), Licht und Bänder (1) und
     der Inhalt (2) in fester Reihenfolge, ohne den Rest der Seite zu
     berühren. */
  isolation: isolate;
}

/* Hier lag ein Verlauf über die untersten acht Zentimeter, der den
   Aufmacher in die Grundfläche überführte. Er ist weg, und das mit Absicht:
   Ein Verlauf über einem Bild deckt nicht, er trübt – zu sehen war ein
   grauer Schleier quer über die Unterkante, hinter dem das Bild weder
   verschwand noch stehenblieb. Ohne ihn endet der Aufmacher an seiner
   eigenen Kante, und darunter beginnt sauber die Fahrbahnmarkierung. */

/* --- Die Bühne: Halle, Fahrzeug, Licht -------------------------------
   Zwei Aufnahmen, nicht eine: hinten die leere Werkstatthalle, davor das
   freigestellte Fahrzeug. Der Grund für die Trennung steht in dem, was sie
   ersetzt: Ein Foto, das nur einen Teil des Aufmachers deckt, muss an
   seinen Kanten auslaufen, und dieses Auslaufen war überall zu sehen – als
   Strich unter dem Wagen, als senkrechte Kante rechts, als milchiger
   Übergang links. Ebenen, die sich nicht überlappen, haben das Problem
   nicht, und nur getrennt lässt sich das Fahrzeug ganz nach rechts setzen,
   ohne die Halle mitzunehmen.

   1. Schwarz hinter allem, als Grund.

   2. Die Halle ist `hero-halle`, 1536 × 1584: die Aufnahme mit Hebebühne,
      Deckenstrahler und dem Lichtfleck auf dem Beton, nach oben und unten
      verlängert. Von links nimmt der Weichzeichner zu – dort steht der
      Satz, dort soll der Hintergrund zurückgehen; rechts, hinter dem
      Fahrzeug, bleibt der Beton scharf. Ihre linke Kante läuft auf Schwarz
      aus, deshalb darf sie schmaler sein als die Bühne.

   3. Das Fahrzeug ist `hero-fahrzeug`, 1536 × 1024 mit Alphakanal. Es hat
      keine Maske; seine Kante steckt im Alpha und folgt der Silhouette.

   Die Prozentwerte des Lichts beziehen sich auf den Rahmen, und der bildet
   die vollen 1536 × 1024 der Fahrzeugaufnahme ab – deshalb gelten dort die
   im Foto ausgemessenen Positionen unverändert.

   Die Halle hängt am Rahmen und nicht an der Bühne. Das ist der Kern der
   Anordnung: Fahrzeugbreite und Hintergrundmaßstab stehen in einem festen
   Verhältnis (--halle-s), also sitzt der Lichtfleck auf dem Beton bei jeder
   Fensterbreite hinter derselben Stelle der Karosserie. Hing sie an der
   Bühne, wanderte er mit dem Fenster vom Wagen weg.

   Die Herkunft der Dateien, die Messwerte und die Fehler, die dabei
   entstanden sind, stehen in design/bildnachweis.md.                  */
.hero__stage {
  /* Die Größe des Fahrzeugs. Sie steht hier und nicht am Rahmen, weil
     Boden und Licht sie mitlesen.

     Die Deckelung auf 62rem ist der Grund, warum das auf einem sehr
     breiten Bildschirm nicht kippt: Ohne sie wüchse der Wagen mit der
     Fensterbreite mit und wäre auf einem Fernseher zwei Meter lang. Die
     Untergrenze hält ihn auf dem Telefon groß genug, um ein Fahrzeug zu
     bleiben. */
  --frame-w: clamp(24rem, 78cqw, 82rem);
  --frame-h: calc(var(--frame-w) / 1.5);
  /* Die Höhenlage der Bildmitte, als eigenes Maß, weil der Boden sie
     mitliest: Fährt das Fahrzeug beim Scrollen ein Stück mit und der Boden
     nicht, wandert der Wagen aus seinem eigenen Schatten heraus. */
  --frame-y: calc(50% + var(--parallax, 0) * 40px);
  /* Der Abstand des Rahmens zur rechten Kante. Als eigenes Maß, weil die
     Halle ihn mitliest.

     Null, und das ist keine Nachlässigkeit: Die Karosserie endet in der
     Bilddatei bei 98.44 % der Breite, es bleibt also von selbst ein
     Sechzigstel der Rahmenbreite Luft – auf einem großen Bildschirm rund
     zwanzig Pixel. Das Fahrzeug steht damit so weit rechts, wie es stehen
     kann, ohne angeschnitten zu wirken. */
  --frame-off: 0px;

  /* Der Hintergrundmaßstab: Die Hallenaufnahme wird --halle-s mal so breit
     gezeichnet wie der Fahrzeugrahmen. Über eins, weil das Fahrzeug in der
     Halle steht und nicht die Halle im Fahrzeug: Bei 1 wäre der Raum genau
     so breit wie der Wagen lang.

     --halle-x verschiebt sie in Rahmenbreiten nach rechts über die Bühne
     hinaus. Der Wert entscheidet, welche Stelle der Halle hinter dem Wagen
     liegt, und 0.1 ist die Stelle, an der beide Lichtquellen der Aufnahme
     zum Fahrzeug passen: Der Deckenstrahler (90 % der Hallenbreite) bleibt
     über dem rechten Kotflügel im Bild, sein Fleck auf dem Beton (82 %)
     liegt hinter der rechten Fahrzeughälfte. Bei 0.18 stand der Fleck schon
     richtig, der Strahler aber außerhalb der Bühne – und mit ihm der Grund,
     warum der Boden dort überhaupt hell ist. */
  --halle-s: 1.62;
  --halle-x: .1;

  position: absolute; inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  container-type: size;
}

/* Schwarz hinter allem. Der Lichthof der Halle stand hier als Verlauf und
   ist in die Bilddatei gewandert – dort kann er sich nach dem Horizont
   richten, statt ihn zu erraten. Was bleibt, ist der Grund für den Fall,
   dass die Halle den Fuß oder Kopf der Bühne einmal nicht erreicht: Ihre
   äußersten Zeilen sind selbst schwarz, eine Kante kommt dadurch nicht
   dazu. */
.hero__wand {
  position: absolute; inset: 0;
  background: #000;
}

.hero__frame {
  position: absolute;
  /* Rechts und senkrecht in der Mitte. Der Abstand zur Kante ist nötig,
     nicht kosmetisch: Die Karosserie reicht in der Bilddatei bis 99.1 %
     der Breite, bündig gesetzt steht sie also praktisch auf der
     Fensterkante und liest sich als angeschnitten. */
  right: var(--frame-off);
  /* Beim Scrollen fährt das Fahrzeug ein Stück mit. Über top und nicht
     über translate, damit die Zentrierung die Eigenschaft für sich
     behält. */
  top: var(--frame-y);
  width: var(--frame-w);
  height: var(--frame-h);
  translate: 0 -50%;
}

/* Die Halle. Ihre Maße stehen alle im Verhältnis zum Rahmen, und zwar in
   einem einzigen Maßstab für Breite und Höhe – sonst verzerrt die
   Perspektive: Die Aufnahme hat mit 1536 × 1024 dasselbe Seitenverhältnis
   wie der Rahmen, also ist die Breite --halle-s Rahmenbreiten und die Höhe
   --halle-s mal 1.546875 Rahmenhöhen (1584 Zeilen der Bilddatei zu 1024 der
   Aufnahme darin).

   Die senkrechte Lage folgt aus einer Entscheidung: Das Fahrzeug soll im
   vorderen Drittel des Bodens stehen, seine Radaufstandsfläche (97 % der
   Rahmenhöhe) also auf 85 % der Hallenaufnahme. Daraus ergibt sich die
   Oberkante der Aufnahme zu --frame-y + (0.47 − 0.85 · --halle-s)
   Rahmenhöhen, und weil über der Aufnahme noch 260 der 1584 Zeilen liegen
   (0.253906 Bildhöhen), steht die Ebene um diesen Betrag höher.

   Waagrecht steht sie rechts wie der Rahmen, um --halle-x nach rechts
   verschoben. Links darf sie enden: Ihre Kante läuft in der Bilddatei auf
   Schwarz aus, und dahinter liegt Schwarz – auf einem sehr breiten
   Bildschirm bleibt dort einfach die dunkle Halle stehen, ohne Naht. Genau
   das ging nicht, solange sie an der Bühne hing und beliebig breit gezogen
   werden musste. */
.hero__halle {
  position: absolute;
  right: calc(var(--frame-off) - var(--frame-w) * var(--halle-x));
  top: calc(var(--frame-y) + var(--frame-h) * (.47 - 1.103906 * var(--halle-s)));
  width: calc(var(--frame-w) * var(--halle-s));
  height: calc(var(--frame-h) * var(--halle-s) * 1.546875);
  /* Mit Fassungsnummer, und die muss hier von Hand stehen: Bilddateien
     gehen mit immutable und einem Jahr Gueltigkeit hinaus, eine Stilvorlage
     kann ASSETS_VERSION aber nicht lesen. Ohne die Nummer bliebe bei jedem
     Besucher, der schon einmal hier war, ein Jahr lang die alte Halle hinter
     einem Fahrzeug stehen, das fuer die neue gesetzt ist. Beim Austausch der
     Bilddatei mit ASSETS_VERSION hochzaehlen. */
  background:
    image-set(url('/assets/img/hero-halle.webp?v=21') type('image/webp'),
              url('/assets/img/hero-halle.jpg?v=21')  type('image/jpeg'))
    50% 0 / 100% 100% no-repeat;
}

/* --- Die Kamera ------------------------------------------------------
   Die Bühne steht nicht auf einem Stativ. Halle und Fahrzeug tragen
   dieselbe Bewegung: ein kaum merkliches Wandern, wie es eine Kamera hat,
   die von Hand gehalten auf ihr Motiv zielt – dazu ein Hauch Zoom und ein
   Zehntelgrad Neigung.

   Beide Ebenen mit derselben Regel, derselben Dauer und derselben
   Verzögerung, und das ist die eigentliche Bedingung: Liefe das Fahrzeug
   auf einer anderen Bahn als der Raum dahinter, schwämme es in der Halle,
   statt darin zu stehen. Nicht an der Bühne selbst, weil deren Kanten die
   Kanten des Fensters sind – verschöbe man sie, liefe an einer Seite ein
   Streifen Grundfläche mit.

   Das Maß ist cqw, also ein Anteil der Bühnenbreite: So bleibt der
   Ausschlag auf dem Telefon so klein wie auf dem großen Bildschirm groß.
   Ein Drittel Prozent – mehr wird aus dem Zielen ein Schwanken.

   Die Stützstellen liegen mit Absicht ungleich: Eine Hand hält nicht im
   Takt. */
.hero__halle,
.hero__frame { animation: kamera-halten 19s ease-in-out infinite; }
@keyframes kamera-halten {
  0%   { transform: translate3d(0, 0, 0) scale(1); rotate: 0deg; }
  13%  { transform: translate3d(-.18cqw, .09cqw, 0) scale(1.0016); rotate: .03deg; }
  27%  { transform: translate3d(.11cqw, .17cqw, 0) scale(1.0031); rotate: -.05deg; }
  38%  { transform: translate3d(.27cqw, -.06cqw, 0) scale(1.0024); rotate: -.08deg; }
  52%  { transform: translate3d(.06cqw, -.19cqw, 0) scale(1.0009); rotate: -.02deg; }
  64%  { transform: translate3d(-.24cqw, -.11cqw, 0) scale(1.0022); rotate: .06deg; }
  79%  { transform: translate3d(-.09cqw, .14cqw, 0) scale(1.0034); rotate: .09deg; }
  91%  { transform: translate3d(.14cqw, .04cqw, 0) scale(1.0013); rotate: .04deg; }
  100% { transform: translate3d(0, 0, 0) scale(1); rotate: 0deg; }
}

/* Die Abschattung zu den Rändern, auf der Mitte der Karosserie. Die liegt
   34.9 % der Rahmenbreite vor der rechten Rahmenkante (das Fahrzeug belegt
   31.8 bis 98.4 % der Bilddatei), und die Ebene selbst steht um --halle-x
   Rahmenbreiten weiter rechts – beides zusammen ergibt den Abstand von
   ihrer eigenen rechten Kante. Die Prozentwerte hier zählen in der Ebene
   und nicht in der Bühne, deshalb kommt --frame-off darin nicht mehr vor.

   Nur noch die Abschattung, kein Lichthof mehr: Den bringt die Aufnahme
   jetzt selbst mit – Deckenstrahler und Fleck auf dem Beton stehen im Bild.
   Ein zweiter Hof darüber hellte dieselbe Stelle doppelt auf und nahm dem
   echten Licht seine Form. */
.hero__halle::after {
  content: '';
  position: absolute; inset: 0;
  --mitte: calc(100% - var(--frame-w) * (var(--halle-x) + .349));
  background: radial-gradient(104% 84% at var(--mitte) 62%,
    transparent 38%, rgba(0, 0, 0, .5) 100%);
}

/* Das Fahrzeug. Keine Maske mehr – das ist der ganze Gewinn der Trennung.
   Die Kante steckt im Alphakanal der Bilddatei und folgt der Silhouette,
   statt als Verlauf über das Bild zu laufen.

   Die Datei hat die vollen Maße der Aufnahme und deckt sich deshalb genau
   mit dem Rahmen. Ihre unterste Kante ist im Alpha ausgeblendet: Der
   Schattenfuß war dort noch deckend, und seit dahinter eine andere Aufnahme
   liegt als die, aus der er stammt, stand an dieser Kante ein Rechteck aus
   fremdem Beton auf dem Hallenboden. */
.hero__car {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%; height: 100%;
}

/* Die Absicherung für die Schrift. Sie trägt weniger als früher, und das ist
   der Zweck des Weichzeichners in der Bilddatei: Links steht der Satz auf
   einem Hintergrund, der ohnehin schon zurückgetreten ist – unscharf und
   nach der Kante hin schwarz. Der Verlauf muss deshalb nur noch den unteren
   linken Bereich abfangen, wo der Boden aufhellt.

   Dazu die Randabschattung, die den Blick auf das Fahrzeug zieht. */
.hero__stage::after {
  content: '';
  position: absolute; inset: 0;
  background:
    linear-gradient(96deg,
      rgba(17, 17, 19, .55) 0%,
      rgba(17, 17, 19, .32) 24%,
      rgba(17, 17, 19, .1) 42%,
      rgba(17, 17, 19, 0) 58%),
    radial-gradient(120% 105% at 72% 56%, transparent 42%, rgba(0, 0, 0, .42) 100%);
}

/* --- Fernlicht -------------------------------------------------------
   Alles Licht sitzt auf den im Foto ausgemessenen Mitten der beiden
   Hauptscheinwerfer: 36.70 % und 92.89 % der Bildbreite, 56.35 % der Höhe.
   Gemessen als Schwerpunkt der beiden größten zusammenhängenden Flecken mit
   einer Luminanz über 235 – nicht als Mittel aller hellen Pixel je
   Bildhälfte, denn Chromstoßstange und Motorhaube sind ebenfalls hell und
   zogen den Wert um mehrere Prozent zur Bildmitte.

   Die Werte standen hier lange auf 33.88 % und 85.09 %: umgerechnet für
   eine Zwischenfassung, deren Bilddatei rechts um 140 Pixel Halle
   verlängert war. Diese Fassung gibt es nicht mehr, die Umrechnung blieb
   stehen – das Licht saß dadurch gut zwei Prozent der Bildbreite links
   neben der linken und über sieben Prozent neben der rechten Lampe. Wird
   das Fahrzeug ersetzt, ist dieser Block die erste Stelle, die nachgemessen
   werden muss.

   Das Fahrzeug steht rechts, deshalb liegen die Werte nicht symmetrisch um
   die Bildmitte, sondern um 64.8 %.

   Die Form des Kegels kommt aus einem conic-gradient als Maske und nicht
   aus einem clip-path. Das ist der entscheidende Punkt: der Browser wendet
   filter vor clip-path an, ein weichgezeichneter Kegel wurde an der
   Schnittkante also wieder hart abgeschnitten – genau die scharfe Kante,
   die ein Lichtkegel nie hat. Die Maske dagegen greift nach dem Filter und
   verläuft selbst weich. Das Licht hat damit überhaupt keine Kante mehr,
   nur noch einen Rand, der ausläuft.

   Ein Scheinwerfer wirft nicht einen Kegel, sondern zwei ineinander: außen
   das weite, schwache Streulicht, das die Luft davor aufhellt und nach
   nichts Bestimmtem aussieht, innen den engen hellen Kern. Das war vorher
   ein einziger Kegel – der sah dadurch aus wie ein aufgelegtes Dreieck.
   Beide zusammen ergeben den Verlauf, den echtes Licht hat: hell in der
   Mitte, ohne erkennbaren Rand nach außen.

   Die Aufnahme steht auf Scheinwerferhöhe. Die Lichtflecken, die das Foto
   auf dem Boden mitbringt, liegen bei etwa 33 % und 96 % – also acht Grad
   nach außen versetzt gegenüber den Lampen. Genau um diesen Winkel sind
   die Kegel geneigt, und die Bodenflecken setzen dort auf. Sie verstärken
   das Licht, das im Bild schon ist, statt ein zweites daneben zu
   behaupten.

   screen als Mischung, weil Licht sich addiert: so hellt der Kegel den
   Boden auf, statt eine milchige Folie darüberzulegen. Die Mischung sitzt
   an der Schicht und nicht an den einzelnen Teilen – sobald darauf eine
   Deckkraft animiert wird, bildet die Schicht ohnehin eine eigene Gruppe,
   und die Kinder fänden darin nur noch sich selbst als Hintergrund.   */
.hero__beams {
  /* Ein eigenes Maß für alle Weichzeichner: ein Hundertstel der Bildbreite.
     Vorher standen dort feste Pixel, und die sind bei einem Bild, das vom
     Telefon bis zum großen Bildschirm um das Vierfache wächst, entweder
     dort zu weich oder hier zu hart. So ist die Unschärfe immer derselbe
     Anteil des Lichtkegels. */
  --u: calc(var(--frame-w) / 100);

  position: absolute; inset: 0;
  mix-blend-mode: screen;
  pointer-events: none;
}
/* Kein overflow: hidden hier, und das ist wichtig geworden: Der Bodenfleck
   sitzt auf 95 % der Rahmenhöhe und ist 15 % hoch, reicht also über die
   Unterkante des Rahmens hinaus – abgeschnitten läge dort eine waagrechte
   Kante mitten auf dem Hallenboden. Begrenzt wird das Licht von der Bühne,
   und deren Kanten sind die Kanten des Fensters, an denen ein Schnitt
   nichts verrät. */
.hero__beam,
.hero__lamp,
.hero__glow,
.hero__pool,
.hero__streak {
  position: absolute;
  pointer-events: none;
}

/* Gemeinsame Geometrie beider Kegel: Sie beginnen an der Lampe und fallen
   nach vorn, transform-origin an der Spitze, damit die Neigung dort
   ansetzt, wo das Licht austritt, und nicht in der Mitte des Kastens.

   Dazu die Sperre, die das Wesentliche entscheidet: --frei blendet den
   Kegel über seine ersten Zehntel aus. Er beginnt weiterhin an der Lampe –
   dort gehört seine Spitze hin, sonst stimmt der Öffnungswinkel nicht –,
   ist aber erst zu sehen, wo er die Stoßstange hinter sich hat.

   Ohne diese Sperre lag ein heller Keil quer über Stoßstange und
   Kühlergrill, und das ist bei einer Aufnahme von vorn schlicht falsch:
   Der Kegel steht in der Luft zwischen Lampe und Boden, also hinter dem
   Fahrzeug in Blickrichtung – nicht davor. Zu sehen ist von vorn die
   Blendung an der Lampe und das Licht auf dem Boden. Genau dazwischen
   liegt nichts, und genau das nimmt die Sperre weg. */
.hero__beam {
  top: 56.35%;
  transform-origin: 50% 0;
  translate: -50% 0;
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
.hero__beam--l { left: 36.70%; rotate: -8deg; }
.hero__beam--r { left: 92.89%; rotate: 8deg; }

/* Der Kern: eng, warm, mit deutlichem Abfall über die Strecke.
   Die Öffnung beträgt 22°, die Flanken laufen über je 6° aus.

   Zwei Lagen im Hintergrund, nicht eine. Unten der Abfall über die
   Strecke, darüber eine feine Streifung aus einem wiederholten
   conic-gradient: die Strahlen, die entstehen, wenn Licht durch Staub
   fällt. Sie sitzen im selben Sektor, weil die Maske auf das ganze Element
   greift, und der Weichzeichner verwischt sie gerade so weit, dass sie
   nicht als Muster lesbar sind – aber genau so weit, dass der Kegel
   aufhört, eine glatte Fläche zu sein. Das war der eigentliche Grund,
   warum das Licht vorher wie aufgelegt aussah. */
.hero__beam--core {
  width: 20.16%; height: 40%;
  background:
    repeating-conic-gradient(from 169deg at 50% 0%,
      rgba(255, 248, 232, .1) 0deg .9deg,
      transparent .9deg 2.4deg),
    linear-gradient(to bottom,
      rgba(255, 246, 228, .9) 0%,
      rgba(253, 241, 221, .52) 15%,
      rgba(250, 237, 217, .26) 36%,
      rgba(246, 234, 214, .1) 62%,
      transparent 100%);
  /* Der Sektor mal der Sperre: Die Stoßstange endet bei 78 % der Bildhöhe,
     der Kegel beginnt bei 56.25 % und ist 40 % hoch – die 78 % liegen also
     auf 54 % seiner Länge. Bis 40 % ist er weg, ab 68 % ganz da. */
  -webkit-mask-image:
    conic-gradient(from 169deg at 50% 0%,
      transparent 0deg, rgba(0, 0, 0, .35) 3deg, #000 7deg,
      #000 15deg, rgba(0, 0, 0, .35) 19deg, transparent 22deg),
    linear-gradient(to bottom, transparent 40%, #000 68%);
          mask-image:
    conic-gradient(from 169deg at 50% 0%,
      transparent 0deg, rgba(0, 0, 0, .35) 3deg, #000 7deg,
      #000 15deg, rgba(0, 0, 0, .35) 19deg, transparent 22deg),
    linear-gradient(to bottom, transparent 40%, #000 68%);
  filter: blur(calc(var(--u) * 1.1));
}

/* Das Streulicht darum: weiter geöffnet, ein Fünftel der Helligkeit,
   kräftig weichgezeichnet. Es soll nicht als Kegel zu erkennen sein,
   sondern nur die Luft vor dem Wagen aufhellen.

   Deutlich schmaler und schwächer als zuerst gesetzt (42 % Breite, .34
   Deckkraft). So breit legte es einen milchigen Schleier über die halbe
   Bühne, und alles darin – Kern, Fleck, Blendung – verlor seinen Kontrast.
   Streulicht ist das, was man nicht bemerkt; sobald man es sieht, ist es
   Nebel. */
.hero__beam--spill {
  width: 28%; height: 46%;
  background: linear-gradient(to bottom,
    rgba(255, 244, 226, .27) 0%,
    rgba(252, 239, 220, .13) 24%,
    rgba(248, 235, 216, .05) 54%,
    transparent 100%);
  -webkit-mask-image:
    conic-gradient(from 158deg at 50% 0%,
      transparent 0deg, rgba(0, 0, 0, .3) 7deg, #000 17deg,
      #000 27deg, rgba(0, 0, 0, .3) 37deg, transparent 44deg),
    linear-gradient(to bottom, transparent 36%, #000 66%);
          mask-image:
    conic-gradient(from 158deg at 50% 0%,
      transparent 0deg, rgba(0, 0, 0, .3) 7deg, #000 17deg,
      #000 27deg, rgba(0, 0, 0, .3) 37deg, transparent 44deg),
    linear-gradient(to bottom, transparent 36%, #000 66%);
  filter: blur(calc(var(--u) * 3));
}

/* Wo der Kegel aufsetzt: ein Fleck auf dem Hallenboden, breiter als hoch,
   weil der Kegel den Boden flach trifft. Zwei Lagen: der harte helle Kern
   dort, wo der Kegel wirklich auftrifft, und darunter das weite Aufhellen
   des Bodens ringsum – das Licht, das von dort zurückgeworfen wird und dem
   Wagen den Stoßfänger von unten aufhellt.

   Die Stellen sind nicht gewählt, sondern gerechnet: Der Kegel verlässt die
   Lampe bei 56.35 % der Höhe und trifft den Boden bei 95 %, das sind 38.65 %
   der Bildhöhe oder – bei einem Seitenverhältnis von 1.5 – 25.8 % der
   Bildbreite. Um acht Grad geneigt versetzt ihn das um 3.6 % nach außen:
   33.08 % und 96.51 %. Seit das Fahrzeug freigestellt ist, liegt darunter der
   Beton der Halle und kein Lichtfleck aus der Fahrzeugaufnahme mehr –
   dieser Fleck ist jetzt das ganze Licht auf dem Boden und nicht mehr die
   Verstärkung eines vorhandenen. Deshalb ist er kräftiger als in der
   Fassung davor: Auf dem hellen Fleck der alten Bilddatei genügte ein
   Hauch, auf unbelichtetem Beton war derselbe Hauch nicht mehr zu sehen.

   Drei Lagen statt zwei. Die dritte ist die Spiegelung der Lampe im
   geschliffenen Beton: schmal, senkrecht gezogen, deutlich schwächer als
   der Auftreffpunkt. Sie gehört auf die Höhe der Lampe und nicht auf die
   des Kegels, ihre 3.6 % Unterschied liegen aber innerhalb des
   Weichzeichners – dafür ein eigenes Element aufzumachen wäre eine
   Genauigkeit, die man nicht sehen kann. Dass der Boden überhaupt
   spiegelt, steht in der Aufnahme: Die Hebebühne wirft dort ihr Bild. */
.hero__pool {
  top: 96%;
  width: 32%; height: 22%;
  translate: -50% -50%;
  background:
    radial-gradient(ellipse 26% 30% at 50% 40%,
      rgba(255, 245, 226, .66) 0%,
      rgba(252, 238, 216, .26) 44%,
      transparent 78%),
    radial-gradient(ellipse 52% 46% at 50% 44%,
      rgba(250, 236, 214, .19) 0%,
      rgba(246, 233, 212, .07) 46%,
      transparent 76%),
    radial-gradient(ellipse 9% 54% at 50% 70%,
      rgba(253, 241, 222, .17) 0%,
      rgba(250, 237, 216, .07) 52%,
      transparent 88%);
  filter: blur(calc(var(--u) * 1.5));
}
.hero__pool--l { left: 33.08%; }
.hero__pool--r { left: 96.51%; }

/* Der Hof um die Lampe: das, was eine helle Quelle in der Streuung der
   Luft und in der Optik des Auges um sich herum erzeugt. Weit und schwach –
   ohne ihn sitzt der Glühkern wie ein aufgeklebter Punkt auf dem Glas. */
.hero__glow {
  top: 56.35%;
  width: 21.5%; aspect-ratio: 1;
  translate: -50% -50%;
  background: radial-gradient(circle,
    rgba(255, 246, 228, .46) 0%,
    rgba(251, 238, 216, .2) 30%,
    rgba(247, 234, 212, .06) 58%,
    transparent 78%);
  filter: blur(calc(var(--u) * 2.4));
}
.hero__glow--l { left: 36.70%; }
.hero__glow--r { left: 92.89%; }

/* Der waagrechte Streifen quer durch die Lampe. Er hat keine Entsprechung
   in der Halle, sondern im Objektiv: Eine sehr helle Quelle zieht in jeder
   Optik einen Strich in die Breite, und das Auge kennt dieses Zeichen als
   »das ist wirklich hell«. Ohne ihn bleibt der Scheinwerfer ein heller
   Punkt; mit ihm blendet er. Deshalb ist er hier das Einzige, was nicht
   aus der Physik der Halle kommt, sondern aus der der Aufnahme. */
.hero__streak {
  top: 56.35%;
  width: 38%; height: 1.3%;
  translate: -50% -50%;
  border-radius: 50%;
  background: linear-gradient(to right,
    transparent 0%,
    rgba(255, 244, 224, .14) 18%,
    rgba(255, 250, 238, .72) 50%,
    rgba(255, 244, 224, .14) 82%,
    transparent 100%);
  filter: blur(calc(var(--u) * .5));
}
.hero__streak--l { left: 36.70%; }
.hero__streak--r { left: 92.89%; }

/* Der Scheinwerfer selbst: ein Kern, der über das Glas hinausstrahlt, wie
   eine Lampe, die man nicht direkt ansehen kann. */
.hero__lamp {
  top: 56.35%;
  width: 5.96%; aspect-ratio: 1;
  translate: -50% -50%;
  background: radial-gradient(circle,
    rgba(255, 252, 244, .86) 0%,
    rgba(255, 248, 232, .5) 18%,
    rgba(253, 242, 222, .22) 34%,
    rgba(249, 237, 216, .07) 54%,
    transparent 72%);
  filter: blur(calc(var(--u) * .9));
}
.hero__lamp--l { left: 36.70%; }
.hero__lamp--r { left: 92.89%; }

/* --- Wie das Licht angeht und dann brennt ----------------------------
   Vorher lief eine Runde von sechzehn Sekunden, die das Licht am Ende
   vollständig abschaltete und nach einer Pause neu zündete. Das war der
   Fehler: Ein Aufmacher, der alle sechzehn Sekunden dunkel wird, blinkt –
   und wer nach zwölf Sekunden ankommt, sieht das Licht überhaupt nicht.

   Jetzt zündet es genau einmal, beim Laden, und brennt danach durch. Die
   Zündung ist der Ablauf eines Gasentladungsscheinwerfers: der Blitz beim
   Überschlag, das Einbrechen danach, der Anlauf auf volle Stärke.

   Und der Überschlag bleibt nicht beim Laden: beam-flash wiederholt ihn
   alle knapp neun Sekunden. Der Unterschied zur alten Runde, die sechzehn
   Sekunden lang aus- und wieder anging, ist der, auf den es ankommt – das
   Licht geht nicht aus. Es blitzt über seine eigene Helligkeit hinaus
   (brightness weit über eins, das reißt die Kerne kurz auf Weiß auf),
   bricht für zwei Zehntel ein wie eine Lampe, die neu zündet, schlägt ein
   zweites Mal durch und läuft an. Der tiefste Punkt liegt bei .38 und
   nicht bei null: Sichtbar bleibt es die ganze Zeit.

   Zwei Animationen auf derselben Schicht, beide an der Deckkraft: Ohne
   both greift beam-flash erst nach seiner Verzögerung, und die liegt
   hinter dem Ende der Zündung. Bis dahin gilt beam-ignite allein, danach
   gewinnt beam-flash als die spätere der beiden.                       */
.hero__beams {
  animation:
    beam-ignite 2.4s var(--ease) .25s both,
    beam-flash 8.8s linear 2.6s infinite;
}
@keyframes beam-ignite {
  0%   { opacity: 0; }
  6%   { opacity: .62; }   /* der Überschlag */
  11%  { opacity: .08; }   /* und das Einbrechen danach */
  20%  { opacity: .34; }
  46%  { opacity: .8; }
  62%  { opacity: .93; }
  74%  { opacity: .86; }   /* der letzte Rest Unruhe im Anlauf */
  100% { opacity: 1; }
}
/* Ein Prozent sind hier 88 Millisekunden. Der ganze Überschlag dauert
   knapp zwei Sekunden, die übrigen sieben brennt das Licht ruhig. */
@keyframes beam-flash {
  0%, 54% { opacity: 1;   filter: brightness(1); }
  55.5%   { opacity: 1;   filter: brightness(3.4); }   /* der Überschlag */
  57.5%   { opacity: .38; filter: brightness(1); }     /* und der Einbruch */
  59.5%   { opacity: 1;   filter: brightness(2.7); }   /* der zweite Schlag */
  61.5%   { opacity: .62; filter: brightness(1.05); }
  64%     { opacity: 1;   filter: brightness(1.95); }
  68%     { opacity: .93; filter: brightness(1.3); }   /* der Anlauf */
  75%     { opacity: 1;   filter: brightness(1); }
  100%    { opacity: 1;   filter: brightness(1); }
}

/* Danach steht das Licht nicht still. Ein brennender Scheinwerfer
   schwankt minimal – deshalb atmen Kern, Lampe und Fleck weiter, aber nur
   noch in den obersten Prozenten der Helligkeit.

   Die beiden Seiten laufen mit verschiedenen Dauern (7.3 s und 8.9 s) und
   verschiedenen Verzögerungen. Das ist der ganze Trick: Zwei Zyklen, deren
   Dauern kein gemeinsames Vielfaches in Sichtweite haben, treffen sich nie
   wieder an derselben Stelle. Das Ergebnis liest sich als Licht und nicht
   als Schleife – bei gleicher Dauer flackerten beide Lampen im Gleichtakt,
   und ein Gleichtakt verrät die Animation sofort.

   Die Verzögerung deckt die Zündung ab, damit sich beide nicht
   überlagern. Kein both: Vorher gilt einfach der ruhende Zustand. */
.hero__beam--core,
.hero__lamp,
.hero__glow,
.hero__pool { animation: beam-live 7.3s ease-in-out 2.6s infinite; }
.hero__beam--r.hero__beam--core,
.hero__lamp--r,
.hero__glow--r,
.hero__pool--r { animation-duration: 8.9s; animation-delay: 3.1s; }
@keyframes beam-live {
  0%   { opacity: 1; }
  18%  { opacity: .93; }
  31%  { opacity: .99; }
  44%  { opacity: .89; }   /* das tiefste Schwanken der Runde */
  53%  { opacity: .97; }
  71%  { opacity: .91; }
  100% { opacity: 1; }
}

/* Der Streifen atmet nicht mit, er zieht sich in der Länge. Ein Blendstrich
   ist keine Lichtquelle, sondern eine Eigenschaft der Optik: Er wird länger
   und kürzer, wenn die Quelle heller und dunkler wird, aber er flackert
   nicht mit ihr. Vierte Dauer, wieder teilerfremd zu den übrigen. */
.hero__streak { animation: streak-stretch 9.7s ease-in-out 2.6s infinite; }
.hero__streak--r { animation-duration: 11.3s; animation-delay: 3.1s; }
@keyframes streak-stretch {
  0%   { opacity: .85; scale: 1 1; }
  34%  { opacity: 1;   scale: 1.14 1; }
  67%  { opacity: .78; scale: .92 1; }
  100% { opacity: .85; scale: 1 1; }
}

/* Das Streulicht schwankt nicht in der Helligkeit, sondern in der Weite:
   Es zieht sich kaum merklich zusammen und wieder auf, wie warme Luft vor
   der Lampe. Sehr langsam und auf einer dritten, wieder teilerfremden
   Dauer, damit auch das nicht mit dem Atmen des Kerns zusammenfällt. */
.hero__beam--spill { animation: beam-drift 13s ease-in-out 2.6s infinite; }
.hero__beam--spill.hero__beam--r { animation-duration: 16s; }
@keyframes beam-drift {
  0%   { opacity: .9;  scale: 1 1; }
  38%  { opacity: 1;   scale: 1.07 1.03; }
  69%  { opacity: .86; scale: .97 1; }
  100% { opacity: .9;  scale: 1 1; }
}

/* --- Reifenspur des Zeigers ------------------------------------------
   Der Zeiger hinterlässt kurze Profilstücke, die verblassen – dasselbe
   Motiv, das früher als Band vor dem Abschluss lag, hier aber mit Anlass:
   Es entsteht, wo sich etwas bewegt. site.js legt die Stücke ab, die Form
   und das Verblassen stehen hier. */
.hero__trail {
  position: absolute; inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}
/* Ein Stück Mittellinie, kein Reifenprofil mehr. Vorher lag hier ein
   gestreifter Block, und je enger die Striche, desto mehr sah die Spur nach
   Schraffur aus – vor allem, wenn sich mehrere Stücke bei schneller
   Bewegung überlagerten.

   Jetzt ist es dieselbe Markierung wie zwischen den Abschnitten: 22 Pixel
   Strich, ein einzelner, mit weichen Enden. site.js setzt den Abstand
   zwischen zwei Stücken auf die volle Musterlänge, damit sich Strich und
   Lücke abwechseln, statt aneinanderzustoßen.

   Dazu deutlich zurückgenommen: 2 Pixel hoch statt 6.7. Die Fläche eines
   Stücks ist damit ein Drittel der alten, und genau darin liegt das
   Dezente – nicht in einer blasseren Farbe. --chrome-wash stand hier
   kurzzeitig und war der Fehler: Sie hat selbst nur ein Zehntel Deckkraft
   und ist auf dem hellen Beton der Halle gedacht, nicht auf einem Streifen
   von zwei Pixeln über dem dunklen Bild. */
.hero__trailMark {
  position: absolute;
  width: 1.375rem; height: 2px;
  margin: -1px 0 0 -.6875rem;
  background: rgba(230, 233, 237, .5);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  opacity: 0;
}
/* Kürzer als die 1.15 s davor und ohne das Aufblähen am Ende: Ein Strich,
   der beim Verschwinden anderthalbmal so lang wird, zieht den Blick genau
   dann auf sich, wenn er gehen soll. Er verblasst nur noch. */
.hero__trailMark.is-live { animation: trail-fade .9s var(--ease) forwards; }
@keyframes trail-fade {
  0%   { opacity: .62; }
  30%  { opacity: .4; }
  100% { opacity: 0; }
}

/* Einspaltig: der Satz steht links, das Fahrzeug steht frei. Die Begrenzung
   sitzt am Textblock und nicht am Aufmacher – .wrap hält weiter die Ränder
   der Seite, sonst rutschte der Satz aus dem Raster. */
.hero__inner {
  position: relative; z-index: 2;
  padding-block: clamp(2.5rem, 6vw, 4rem) clamp(1.5rem, 3vw, 2.25rem);
  /* Nimmt die Höhe, die Kennfeld und Hinweis übriglassen, und trägt den
     Satz darin in der Mitte. Der Aufmacher ist ein Flexstapel: Was hier
     nicht als flex-grow steht, bliebe oben kleben und ließe unter dem Satz
     eine Lücke stehen. */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
/* 37rem und nicht mehr: Bei 40rem stieß die letzte Zeile an den linken
   Kotflügel, und Schrift, die ein Fahrzeug anschneidet, liest sich als
   Versehen.

   margin-block: auto hält den Satz in der Mitte der Höhe, die Kennfeld und
   Hinweis übriglassen. */
.hero__inner > [data-stagger] { max-width: 37rem; margin-block: auto; }

/* --- Der Hinweis nach unten -------------------------------------------
   Ein Aufmacher, der genau das Fenster füllt, verschweigt, dass darunter
   noch etwas kommt. Der Hinweis sagt es – als Wort und als Fahrbahn, die
   aus dem Bild nach unten läuft: dieselbe Markierung, die zwischen den
   Abschnitten liegt, hier um neunzig Grad gedreht.

   Ganz unten und in der Mitte: Er gehört nicht zum Satz, sondern zur
   Fensterkante – dorthin, wo der Blick hingeht, wenn er unten angekommen
   ist. */
.hero__more {
  align-self: center;
  margin-bottom: clamp(.6rem, 1.4vh, 1.5rem);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .8rem;
  text-decoration: none;
  color: var(--chrome-dim);
  font-size: .7rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  transition: color .3s var(--ease);
}
.hero__more:hover,
.hero__more:focus-visible { color: var(--chrome-lit); }

/* Der Strich: eine Fahrbahn von oben nach unten, in derselben Teilung wie
   die Markierung zwischen den Abschnitten – 12 Pixel Strich, 10 Pixel
   Lücke. Sie läuft nach unten, und der Weg einer Runde ist genau eine
   Musterlänge: Danach steht dasselbe Bild wieder da, die Schleife ist nicht
   zu sehen.

   overflow hidden und die Reserve nach oben sind der Grund, warum unten
   kein Strich abgeschnitten auftaucht: Das Muster kommt oben aus dem Nichts
   und verschwindet unten in der Maske. */
.hero__moreLine {
  position: relative;
  width: 2px;
  height: clamp(1.75rem, 4.5vh, 3rem);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 45%, transparent);
          mask-image: linear-gradient(180deg, #000 45%, transparent);
}
.hero__moreLine::before {
  content: '';
  position: absolute; inset: -22px 0 0 0;
  /* currentColor: Der Strich hellt beim Überfahren mit dem Wort zusammen
     auf – zwei Teile eines Verweises, nicht ein Wort und ein Ornament.
     --chrome-wash wäre hier zu schwach, sie trägt nur ein Zehntel
     Deckkraft. */
  background: repeating-linear-gradient(180deg,
    currentColor 0 12px,
    transparent 12px 22px);
  animation: fahrbahn-lauf 2.4s linear infinite;
}
@keyframes fahrbahn-lauf {
  from { translate: 0 0; }
  to   { translate: 0 22px; }   /* genau eine Musterlänge: kein Sprung */
}

/* Der Abstand der Knöpfe zum Absatz. Stand als style-Attribut im Markup und
   ließ sich von dort aus nirgends anpassen – gebraucht wird er aber genau
   dann kleiner, wenn das Fenster flach ist. */
.hero__actions { margin-top: 2rem; }

/* Seit die Halle deutlich durchkommt, trägt die Fläche allein den Text
   nicht mehr überall: über dem hellen Beton fiele der Kontrast sonst unter
   das Nötige. Der Schatten löst das dort, wo es auftritt,
   ohne das Bild wieder zuzudunkeln. drop-shadow und nicht text-shadow,
   weil die hervorgehobenen Wörter ihre Schrift transparent stellen und
   den Verlauf durchscheinen lassen – ein text-shadow läge mitten in der
   Glyphe, drop-shadow arbeitet auf der fertigen Form. */
.hero__title {
  margin-bottom: var(--sp-5);
  filter: drop-shadow(0 3px 16px rgba(0, 0, 0, .8));
}
.hero .lede--onDark,
.hero .eyebrow--onDark,
.hero .availability__note {
  text-shadow: 0 1px 12px rgba(0, 0, 0, .85), 0 1px 2px rgba(0, 0, 0, .6);
}
/* Die hervorgehobenen Wörter tragen einen Verlauf von Hochglanz nach
   Mattsilber. In einer einfarbigen Palette ist das die einzige
   Auszeichnung, die neben der übrigen Schrift überhaupt noch auffällt –
   ein bloß helleres Grau ginge im Fließtext unter.
   background-clip: text braucht die transparente Schriftfarbe; das
   -webkit-Paar bleibt stehen, Safari kennt die kurze Form nicht. */
.hero__title em {
  font-style: normal;
  background: linear-gradient(160deg, var(--chrome-lit) 0%, var(--chrome) 42%, var(--chrome-dim) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

/* Jede Zeile fährt einzeln ins Bild – wie ein Kolben im Zylinder.

   Der verschobene Ausgangszustand hängt an .js, und das ist keine
   Kleinigkeit: Er stand vorher frei, zusammen mit overflow: hidden an der
   Zeile. Lief die Animation nicht – ohne JavaScript, oder wenn sie aus
   irgendeinem Grund nicht startet –, blieb die Überschrift der Startseite
   unter der Kante und damit unsichtbar. Für den Rest der Seite gilt dieser
   Grundsatz längst (siehe Abschnitt "Bewegung"): Versteckt wird nur, was
   auch wieder hervorgeholt werden kann. */
.hero__line {
  display: block;
  overflow: hidden;
  padding-bottom: .04em;
}
.hero__line > span { display: block; }
.js .hero__line > span {
  translate: 0 100%;
  animation: line-stroke .85s var(--ease-mech) both;
}
.js .hero__line:nth-child(1) > span { animation-delay: .1s; }
.js .hero__line:nth-child(2) > span { animation-delay: .22s; }
.js .hero__line:nth-child(3) > span { animation-delay: .34s; }
@keyframes line-stroke {
  from { translate: 0 100%; }
  to   { translate: 0 0; }
}

/* Das Wappen ist ein Schild, kein Strichzeichen: schwarzes Email, silberne
   Prägung, eigene Lichtführung. Es kommt fertig aus der Bilddatei und wird
   hier nicht eingefärbt – ein invert-Filter würde die Politur umkehren und
   das Silber schwarz werden lassen. Nur der Schlagschatten kommt von hier.

   Es steht dort, wo ein Absender hingehört: über der
   Kennzeichnung, in Schriftgröße gedacht statt als Bild neben dem Satz. So
   verdeckt es das Fahrzeug nicht und braucht auch keine Fläche unter sich –
   die Prägung trägt sich auf dunklem Grund selbst. */
.hero__marks {
  display: flex;
  align-items: center;
  gap: clamp(.8rem, 1.6vw, 1.25rem);
  width: fit-content;
  margin-bottom: var(--sp-3);
}
.hero__crest {
  display: block;
  width: clamp(3.6rem, 7vw, 5rem);
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, .8));
}
.hero__seal {
  width: clamp(2.85rem, 5vw, 3.65rem);
  opacity: .72;
  filter: saturate(.82) drop-shadow(0 8px 18px rgba(0, 0, 0, .72));
}
.js .hero__crest {
  animation: crest-settle 1s var(--ease) .15s both;
}
@keyframes crest-settle {
  from { opacity: 0; scale: .9; rotate: -3deg; }
  to   { opacity: 1; scale: 1; rotate: 0deg; }
}

/* --- Flaches Fenster --------------------------------------------------
   Der Aufmacher soll ins Fenster passen, und auf einem gewöhnlichen
   Bildschirm mit 1080 Zeilen bleiben davon nach Kopfleiste und
   Browserleisten keine 900 übrig – in der großzügigen Fassung braucht er
   gut 1050. Also zieht er sich hier zusammen, und zwar an jedem Maß ein
   wenig statt an einem viel.

   Alles davon ist Luft und Schriftgröße, nichts ist Inhalt: Es fällt keine
   Zeile weg, kein Termin, kein Knopf. Auf hohen Bildschirmen bleibt die
   großzügige Fassung stehen; auf schmalen greift die Regel gar nicht erst,
   denn dort steht der Satz über dem Fahrzeug und der Aufmacher darf länger
   werden als das Fenster.

   Am Ende des Aufmacher-Abschnitts und nicht mitten darin: Wappen, Siegel
   und Abstände bekommen ihre Maße weiter oben, und bei gleicher Spezifität
   gewinnt die spätere Regel. Stünde dieser Block davor, wäre die Hälfte
   davon wirkungslos – was er auch war, bis genau das auffiel. */
@media (min-width: 60rem) and (max-height: 75rem) {
  .hero__inner { padding-block: clamp(.75rem, 2.4vh, 2.5rem) clamp(.5rem, 1.2vh, 1.25rem); }
  .hero__marks { margin-bottom: clamp(.25rem, .8vh, .75rem); }
  .hero__crest { width: clamp(2.25rem, 4.2vh, 3.75rem); }
  .hero__seal  { width: clamp(1.9rem, 3.4vh, 2.9rem); }
  .hero__title {
    font-size: clamp(2.05rem, 4.7vh, 3.5rem);
    margin-bottom: clamp(.55rem, 1.6vh, 1.2rem);
  }
  .hero .lede--onDark {
    font-size: clamp(.95rem, 1.95vh, 1.15rem);
    margin-block: clamp(.3rem, 1vh, .65rem) 0;
  }
  .hero__actions { margin-top: clamp(.85rem, 2.2vh, 1.6rem); }
  .hero__moreLine { height: clamp(1.25rem, 3.4vh, 3rem); }
  .hero .availability {
    padding-block: clamp(.55rem, 1.6vh, 1.4rem) clamp(.55rem, 1.6vh, 1.4rem);
  }
}

/* Die engere Stufe, für Bildschirme mit 768 Zeilen und für jedes Fenster,
   das jemand flach gezogen hat. Hier sind die Schriftgrößen schon an ihrer
   Untergrenze angekommen – kleiner werden dürfen sie nicht, sonst liest es
   niemand mehr. Was bleibt, ist der Zeilenabstand des Absatzes und die Luft
   in den Terminkarten. */
@media (min-width: 60rem) and (max-height: 46rem) {
  .hero .lede--onDark { line-height: 1.45; }
  .hero .slot-card { padding-block: .6rem; }
  .hero .availability__head { margin-bottom: .35rem; }
}

@media (max-width: 60rem) {
  /* Im schmalen Fenster steht der Satz über dem Fahrzeug und nicht daneben.
     Der Wagen darf deshalb breiter werden, rückt aus der rechten Ecke in
     die Mitte und sitzt tiefer – unter dem Satz, nicht hinter ihm. Die
     Deckelung in rem fällt hier weg: Auf dem Telefon soll das Bild
     mitwachsen. */
  /* Der Hintergrundmaßstab fällt mit: Auf dem Telefon ist der Wagen breiter
     als die Bühne, und 1.62 Rahmenbreiten Halle wären fast das Doppelte
     davon – zu sehen wäre dann nur noch ein Ausschnitt Beton ohne Wand und
     ohne Hebebühne. Bei 1.15 bleibt der Raum als Raum erkennbar.
     --halle-x wird dabei negativ: Bei kleinerem Maßstab reicht die Ebene
     weniger weit über die Bühne hinaus, und der Deckenstrahler sitzt sonst
     rechts daneben. */
  .hero__stage {
    --frame-w: 112cqw;
    /* Tiefer als die 66 % davor. Der Satz endet auf dem Telefon mit den
       beiden Knöpfen, und die lagen auf dem Kühlergrill – heller Chrom
       hinter einem Knopf mit hellem Grund ist keine Schaltfläche mehr,
       sondern ein Fleck. Bei 78 % liegen Knöpfe und Kennzeichnung über der
       Windschutzscheibe, und die Scheinwerfer stehen hinter den Karten des
       Kennfelds statt hinter deren Beschriftung. */
    --frame-y: calc(78% + var(--parallax, 0) * 30px);
    --frame-off: -9cqw;
    --halle-s: 1.15;
    --halle-x: -.03;
  }

  /* Der Satz steht jetzt über dem Fahrzeug, nicht daneben – also zieht der
     Verlauf von oben zu und lässt unten das Licht frei. */
  .hero__stage::after {
    background:
      linear-gradient(to bottom,
        rgba(17, 17, 19, .68) 0%,
        rgba(17, 17, 19, .46) 28%,
        rgba(17, 17, 19, .1) 50%,
        rgba(17, 17, 19, 0) 66%),
      radial-gradient(130% 70% at 58% 72%, transparent 36%, rgba(0, 0, 0, .42) 100%);
  }

  /* Auf dem Telefon gibt es keinen Zeiger, der eine Spur ziehen könnte. */
  .hero__trail { display: none; }

  /* Und keinen Hinweis nach unten: Der Aufmacher steht hier untereinander
     statt nebeneinander und reicht in jedem Fall über die Fensterkante
     hinaus. Ein Hinweis, dass es weitergeht, wäre die Auskunft, die das
     Bild selbst schon gibt. */
  .hero__more { display: none; }
}

/* --- Kennfeld: die nächsten wirklich freien Termine -------------------
   Herzstück der Startseite. Keine Behauptung, sondern der echte
   Kalenderstand aus dem Buchungssystem.                                */
.availability {
  position: relative; z-index: 2;
  padding-block: var(--sp-5) clamp(2rem, 4vw, 2.75rem);
}
/* Trennlinie läuft aus wie ein Messschieber */
.availability::before {
  content: '';
  position: absolute; inset: 0 var(--gutter) auto var(--gutter);
  height: 1px; background: var(--line-soft);
  transform: scaleX(0); transform-origin: left;
}
.js .availability::before { animation: rule-draw .9s var(--ease-mech) .45s both; }
@keyframes rule-draw { to { transform: scaleX(1); } }

.availability__head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-4);
}
.availability__head .eyebrow { margin: 0; }
/* Vor der aufgehellten Halle war die Zeitangabe bei halber Deckkraft nur
   noch zu erraten. */
.availability__note { font-size: .82rem; color: rgba(230, 233, 237, .62); }

/* Ein Behälter mit overflow-x schneidet auch oben und unten ab – nicht nur
   seitlich. Die Karten hoben sich beim Überfahren also in eine Kante
   hinein und wurden angeschnitten, samt Schatten und Silberkante. Das
   Polster gibt ihnen den Platz, der negative Rand nimmt ihn optisch wieder
   heraus, damit der Streifen im Raster bleibt, wo er war. */
.slot-strip {
  display: flex; gap: var(--sp-3);
  overflow-x: auto;
  padding: .55rem .3rem 1.1rem;
  margin: -.55rem -.3rem 0;
  scrollbar-width: thin;
  /* Beim Blättern soll eine Karte nicht an der Kante kleben. */
  scroll-padding-inline: .3rem;
}

.slot-card {
  flex: 0 0 auto;
  min-width: 9.5rem;
  position: relative;
  display: flex; flex-direction: column; gap: .1rem;
  padding: .9rem 1.15rem;
  /* Die Karten liegen über der Werkstatthalle, und Uhrzeiten müssen sich
     auf den ersten Blick lesen lassen. Also getöntes Glas statt eines
     hellen Films: die Halle bleibt dahinter erkennbar, aber gedämpft und
     unscharf, sodass die Karte als eigene Fläche steht. Der frühere helle
     Schleier verschwand vor dem Foto einfach. */
  background: rgba(9, 9, 10, .62);
  backdrop-filter: blur(10px) saturate(115%);
  -webkit-backdrop-filter: blur(10px) saturate(115%);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  color: var(--enamel);
  text-decoration: none;
  overflow: hidden;
  /* Die Übergänge für den Zeiger stehen nicht hier, sondern im Abschnitt
     "Bewegung" bei den Einblendungen: deren Auswahl ist spezifischer als
     diese und würde eine Angabe an dieser Stelle überschreiben. */
}
/* Die Kinder über den Lichtschleier heben, sonst legt er sich mit auf die
   Schrift. */
.slot-card > * { position: relative; z-index: 1; }

/* Silberkante fährt beim Überfahren von unten ein */
.slot-card::before {
  content: '';
  position: absolute; inset: 0 auto 0 0;
  width: 3px; background: var(--chrome);
  transform: scaleY(0); transform-origin: bottom;
  transition: transform .28s var(--ease-mech);
  z-index: 2;
}
.slot-card:hover::before,
.slot-card:focus-visible::before { transform: scaleY(1); }

/* Der Lichthauch beim Überfahren liegt als eigene Schicht darüber und wird
   über die Deckkraft eingeblendet. Über den Hintergrund ging das nicht:
   zwischen einer Farbe und einer Farbe plus Verlauf kann der Browser nicht
   überblenden, der Wechsel sprang hart um. Das Licht fällt von oben links
   ein, aus derselben Richtung wie die Werkstattleuchte im Aufmacher. */
.slot-card::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(150deg,
    rgba(230, 233, 237, .13) 0%,
    rgba(230, 233, 237, .04) 55%,
    transparent 100%);
  opacity: 0;
  transition: opacity .26s var(--ease);
  pointer-events: none;
}
.slot-card:hover::after,
.slot-card:focus-visible::after { opacity: 1; }

.slot-card:hover,
.slot-card:focus-visible {
  border-color: var(--chrome-edge);
  transform: translateY(-2px);
}
.slot-card__day {
  font-size: .73rem; font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase;
  color: rgba(230, 233, 237, .58);
}
.slot-card__time {
  font-family: var(--font-mono); font-weight: 600;
  font-size: 1.45rem; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--chrome);
}
.slot-card__service { font-size: .8rem; color: rgba(230, 233, 237, .68); }

.slot-strip__empty {
  padding: 1rem 1.25rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  font-size: .95rem; color: rgba(230, 233, 237, .78);
  /* Dieselbe getönte Scheibe wie die Terminkarten – der Hinweis steht an
     ihrer Stelle und darf nicht schwächer stehen. */
  background: rgba(9, 9, 10, .62);
  backdrop-filter: blur(10px) saturate(115%);
  -webkit-backdrop-filter: blur(10px) saturate(115%);
}

/* ---------------------------------------------------------------------
   Zusagen-Band
   --------------------------------------------------------------------- */
/* Der Hinweis im Aufmacher springt hierher. Die Reserve hält die
   Fahrbahnmarkierung darüber mit im Bild – ohne sie stünde die erste Zusage
   direkt unter der Kopfleiste und der Sprung sähe aus wie ein Schnitt. */
.pledges { background: var(--sunk); border-block: 1px solid var(--line); scroll-margin-top: 8rem; }
.pledges__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.pledge {
  position: relative;
  padding: var(--sp-5) var(--sp-5) var(--sp-5) 0;
  border-right: 1px solid var(--line);
}
.pledge:last-child { border-right: 0; }
.pledge + .pledge { padding-left: var(--sp-5); }
.pledge__title { font-size: .95rem; font-weight: 700; margin-bottom: .2rem; }
.pledge__text { font-size: .85rem; color: var(--steel); line-height: 1.5; }

@media (max-width: 48rem) {
  .pledge { border-right: 0; border-bottom: 1px solid var(--line); padding: var(--sp-4) 0; }
  .pledge + .pledge { padding-left: 0; }
  .pledge:last-child { border-bottom: 0; }
}

/* ---------------------------------------------------------------------
   Leistungen
   --------------------------------------------------------------------- */
.service-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17.5rem, 1fr));
  gap: var(--sp-4);
}

.service-card {
  position: relative;
  display: flex; flex-direction: column;
  padding: var(--sp-5);
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  /* Die Übergänge stehen im Abschnitt "Bewegung" bei den Einblendungen:
     deren Auswahl ist spezifischer als diese hier. */
}
/* Der Inhalt liegt über dem Lichtstreif, sonst zieht der über die Schrift. */
.service-card > * { position: relative; z-index: 1; }

/* Silberfaden an der Oberkante, läuft von links ein. Er nimmt sich jetzt
   knapp die doppelte Zeit: der Faden ist eine Kante, die aufleuchtet, und
   Licht, das zu schnell da ist, wirkt geschaltet statt angegangen. */
.service-card::before {
  content: '';
  position: absolute; inset: 0 0 auto 0; height: 2px;
  z-index: 2;
  background: linear-gradient(to right,
    var(--chrome-lit) 0%, var(--chrome) 45%, var(--chrome-dim) 100%);
  transform: scaleX(0); transform-origin: left;
  transition: transform .75s var(--ease);
}
.service-card:hover::before,
.service-card:focus-within::before { transform: scaleX(1); }

/* Und der Auftritt selbst: ein Lichtstreif, der einmal langsam über die
   Karte streicht – ein Reflex, wie er über einen Lack läuft, wenn man
   daran vorbeigeht. Er läuft einmal und bleibt dann weg; ein Streif, der
   im Kreis läuft, wird nach dem zweiten Mal zum Blinken. */
.service-card::after {
  content: '';
  position: absolute; inset: -1px;
  background: linear-gradient(102deg,
    transparent 34%,
    rgba(230, 233, 237, .05) 44%,
    rgba(230, 233, 237, .12) 50%,
    rgba(230, 233, 237, .05) 56%,
    transparent 66%);
  translate: -115% 0;
  opacity: 0;
  pointer-events: none;
}
.service-card:hover::after,
.service-card:focus-within::after {
  animation: card-sheen 1.5s var(--ease) forwards;
}
@keyframes card-sheen {
  0%   { translate: -115% 0; opacity: 0; }
  14%  { opacity: 1; }
  82%  { opacity: 1; }
  100% { translate: 115% 0; opacity: 0; }
}

.service-card:hover,
.service-card:focus-within {
  background: var(--raise-2);
  border-color: var(--chrome-edge);
  box-shadow: var(--shadow-card);
  transform: translateY(-3px);
}
.service-card__title { font-size: 1.15rem; margin-bottom: var(--sp-2); }
.service-card__text {
  font-size: .93rem; color: var(--steel); line-height: 1.6;
  margin: 0 0 var(--sp-4);
}
.service-card__meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  margin-top: auto;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-family: var(--font-mono); font-size: .82rem;
  color: var(--steel);
}
.service-card__price { color: var(--enamel); font-weight: 600; }
.service-card__link {
  margin-top: var(--sp-4);
  font-size: .9rem; font-weight: 700; color: var(--enamel);
  text-decoration: none;
  align-self: flex-start;
  padding-bottom: 2px;
  border-bottom: 2px solid var(--chrome);
  transition: color .2s var(--ease), gap .2s var(--ease);
}
.service-card__link::after {
  content: ' →';
  display: inline-block;
  transition: translate .25s var(--ease);
}
.service-card:hover .service-card__link { color: var(--chrome-lit); }
.service-card:hover .service-card__link::after { translate: .25rem 0; }

/* Die §57a-Plakette – das einzige gegenständliche Bildzeichen der Seite.
   Steht nur auf der Pickerl-Karte, sonst nirgends. */
.pickerl {
  width: 3.4rem; height: 3.4rem; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--chrome-wash);
  border: 2px solid var(--chrome);
  margin-bottom: var(--sp-4);
  font-family: var(--font-mono); font-weight: 600;
  font-size: 1.05rem; color: var(--chrome);
  letter-spacing: -.04em;
  box-shadow: inset 0 0 0 3px var(--raise);
  transition: transform .4s var(--ease-mech), box-shadow .3s var(--ease);
}
.service-card:hover .pickerl {
  transform: rotate(-9deg);
  box-shadow: inset 0 0 0 3px var(--raise-2), 0 0 22px -6px var(--chrome);
}

/* ---------------------------------------------------------------------
   Oldtimer-Band
   --------------------------------------------------------------------- */
.classic {
  position: relative;
  background: var(--sunk);
  border-block: 1px solid var(--line);
  overflow: hidden;
}
/* Das Licht kommt von oben aus dem Band heraus, nicht aus der Mitte der
   rechten Spalte. Ein Punkt auf halber Höhe lag genau hinter der Merkliste
   und legte dort einen weichen Fleck über Text und Trennlinien. Mit dem
   Zentrum über dem oberen Rand und einem Abfall in zwei Stufen bleibt die
   Aufhellung eine Kante und wird nicht als eigene Form gelesen. */
.classic::before {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(85% 130% at 88% 0%,
    rgba(255, 255, 255, .055) 0%,
    rgba(255, 255, 255, .026) 40%,
    transparent 74%);
  pointer-events: none;
}
.classic__inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
/* Merkliste mit Rautenmarken. Kommt im Oldtimer-Band der Startseite und
   auf den Inhaltsseiten vor, deshalb steht sie für sich. */
.marklist {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-3);
}
.marklist li {
  position: relative;
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3);
  align-items: baseline;
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-size: .95rem;
  color: rgba(230, 233, 237, .8);
  transition: color .25s var(--ease);
}
.marklist li::before {
  content: '';
  width: .5rem; height: .5rem;
  background: var(--chrome-dim);
  rotate: 45deg;
  translate: 0 -.1rem;
  transition: scale .3s var(--ease-mech), background-color .25s var(--ease);
}
/* Die Trennlinie läuft beim Hover von links hell durch – der Text bleibt
   dabei stehen, sonst ruckelt die ganze Liste. */
.marklist li::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -1px;
  border-top: 1px solid var(--chrome-dim);
  transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease-mech);
}
.marklist li:hover { color: var(--enamel); }
.marklist li:hover::before { scale: 1.25; background: var(--chrome-lit); }
.marklist li:hover::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .marklist li::before, .marklist li::after { transition: none; }
  .marklist li:hover::after { transform: none; }
}

@media (max-width: 56rem) {
  .classic__inner { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
   Ablauf – fünf sauber gefasste Arbeitsschritte
   --------------------------------------------------------------------- */
.steps {
  counter-reset: step;
  display: grid;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  gap: clamp(.625rem, 1.15vw, 1rem);
  margin: 0; padding: 0; list-style: none;
}
.steps--four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.steps--four .step { grid-column: auto; }

.step {
  counter-increment: step;
  grid-column: span 2;
  position: relative;
  min-width: 0;
  min-height: 15.75rem;
  padding: 1.25rem clamp(1rem, 1.45vw, 1.35rem) 1.45rem;
  overflow: hidden;
  background:
    linear-gradient(145deg, rgba(230, 233, 237, .045), transparent 46%),
    var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card), inset 0 1px 0 rgba(255, 255, 255, .025);
}

/* Nummer und Kanal bilden einen ruhigen Kopf. Der Silberfaden darunter
   übernimmt die vorhandene gestaffelte Einblendung des Ablaufs. */
.step::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  top: 1.25rem; left: clamp(1rem, 1.45vw, 1.35rem);
  font-family: var(--font-mono);
  font-size: .73rem; font-weight: 600;
  line-height: 1;
  letter-spacing: .08em;
  color: var(--chrome);
}
.step::after {
  content: '';
  position: absolute;
  top: 3.25rem;
  left: clamp(1rem, 1.45vw, 1.35rem);
  right: clamp(1rem, 1.45vw, 1.35rem);
  height: 1px;
  background: linear-gradient(90deg, var(--chrome-edge), var(--line) 74%);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .75s var(--ease-mech);
  transition-delay: calc(var(--i, 0) * 110ms + 180ms);
}
.step.is-in::after { transform: scaleX(1); }

.step__meta {
  display: flex;
  min-height: .8rem;
  margin-left: 2.7rem;
  justify-content: flex-end;
  font-family: var(--font-mono);
  font-size: .64rem; font-weight: 600;
  line-height: 1.2;
  letter-spacing: .08em;
  text-align: right;
  text-transform: uppercase;
  color: var(--steel-dim);
}
.step__title {
  margin: 2.35rem 0 .65rem;
  font-size: clamp(1.02rem, 1.25vw, 1.16rem);
  font-weight: 700;
  line-height: 1.25;
  text-wrap: balance;
}
.step__text {
  max-width: 30ch;
  margin: 0;
  font-size: .88rem;
  line-height: 1.62;
  color: var(--steel);
  text-wrap: pretty;
}

/* Zwischen fünf und einer Spalte bleibt die Verteilung ausgewogen: oben
   drei, darunter zwei gleich breite Karten. */
@media (max-width: 70rem) {
  .steps { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .step { grid-column: span 2; min-height: 14rem; }
  .step:nth-child(n + 4) { grid-column: span 3; }
  .step__text { max-width: 36ch; }

  .steps--four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .steps--four .step,
  .steps--four .step:nth-child(n + 4) { grid-column: auto; }
}

@media (max-width: 42rem) {
  .steps { grid-template-columns: 1fr; gap: var(--sp-3); }
  .steps--four { grid-template-columns: 1fr; }
  .step,
  .step:nth-child(n + 4) {
    grid-column: 1;
    min-height: 0;
    padding: 1.2rem 1.2rem 1.25rem 4.35rem;
  }
  .step::before { top: 1.42rem; left: 1.2rem; }
  .step::after {
    top: 1.2rem; bottom: 1.2rem;
    left: 3.35rem; right: auto;
    width: 1px; height: auto;
    background: linear-gradient(180deg, var(--chrome-edge), var(--line) 76%);
    transform: scaleY(0);
    transform-origin: top;
  }
  .step.is-in::after { transform: scaleY(1); }
  .step__meta {
    min-height: auto;
    margin: 0 0 .45rem;
    justify-content: flex-start;
    text-align: left;
  }
  .step__title { margin: 0 0 .45rem; }
  .step__text { max-width: 42ch; }
}

/* ---------------------------------------------------------------------
   Häufige Fragen – <details>, damit es ohne JavaScript funktioniert
   --------------------------------------------------------------------- */
.faq { border-top: 1px solid var(--line); max-width: 52rem; }
.faq__item { border-bottom: 1px solid var(--line); }
.faq__q {
  cursor: pointer;
  list-style: none;
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-4) 0;
  font-weight: 700; font-size: 1.02rem; line-height: 1.45;
  color: var(--enamel);
}
.faq__q::-webkit-details-marker { display: none; }
/* Das Kreuz wird beim Öffnen zum Minus. Eine Vierteldrehung reicht, weil der
   waagrechte Balken dabei auf den senkrechten fällt. */
.faq__q::before {
  content: '+';
  flex: 0 0 auto;
  font-family: var(--font-data, inherit);
  font-weight: 400; font-size: 1.25rem; line-height: 1;
  color: var(--chrome-lit);
  transition: transform .3s var(--ease-mech);
}
.faq__item[open] .faq__q::before { transform: rotate(45deg); }
.faq__q:hover { color: var(--chrome-lit); }
.faq__q:focus-visible { outline: 2px solid var(--chrome-lit); outline-offset: 3px; }
.faq__a {
  padding: 0 0 var(--sp-4) 1.9rem;
  color: var(--steel); line-height: 1.75; max-width: 44rem;
}
.faq__a p { margin: 0; }

/* ---------------------------------------------------------------------
   Kontakt & Öffnungszeiten
   --------------------------------------------------------------------- */
.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}
@media (max-width: 56rem) { .contact-grid { grid-template-columns: 1fr; } }

.info-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.info-list dt, .info-list__label {
  font-size: .715rem; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase;
  color: var(--steel-dim);
  margin-bottom: .25rem;
}
.info-list a { color: var(--enamel); text-decoration-color: var(--chrome); }
.info-list a:hover { color: var(--chrome-lit); }

.hours { width: 100%; border-collapse: collapse; font-size: .95rem; }
.hours th, .hours td {
  padding: .55rem 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
}
.hours th { font-weight: 600; }
.hours td { font-family: var(--font-mono); font-size: .88rem; text-align: right; color: var(--steel); }
.hours tr[data-today='true'] th,
.hours tr[data-today='true'] td { color: var(--chrome); font-weight: 600; }
.hours td.is-closed { color: var(--steel-dim); }

/* --- Standortkarte ---------------------------------------------------
   Ein Bild, kein Kartengerüst. Der Ausschnitt liegt fertig eingefärbt im
   Verzeichnis, die Werkstatt genau in seiner Mitte – deshalb sitzt die
   Nadel auf 50 % / 50 % und nicht an gerechneten Koordinaten.

   Was hier nicht mehr steht, ist der eigentliche Gewinn: Leaflets
   Ebenenstaffelung bis z-index 800, der Filter auf der Kachelebene, die
   Gegenwehr gegen ein fremdes Grundgerüst, die Sonderregel für eine
   Quellenangabe, die aus einem später geladenen Blatt kam. Ein Bild
   braucht davon nichts.
   --------------------------------------------------------------------- */
.map-figure { margin: 0; }

.map-frame {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--raise);
  aspect-ratio: 4 / 3;
}
.map__image {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
}

/* Die Nadel: Silber mit dunklem Kern, wie die Prägung im Wappen. Der
   Fußpunkt der Spitze liegt auf dem Standort, deshalb der ganze Versatz
   nach oben und nur die Hälfte nach links. */
.map__pin {
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -100%;
  line-height: 0;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, .7));
}
.map__pin svg { width: 20px; height: auto; }
.map__pin svg path { fill: #c9342f; }
.map__pin svg circle { fill: #fff; }

/* Die Anschrift steht fest im Bild, statt in einer Sprechblase zu warten,
   bis jemand die Nadel findet. */
.map__card {
  position: absolute;
  left: auto; bottom: var(--sp-4);
  right: var(--sp-4);
  max-width: 20rem;
  display: grid; gap: .15rem;
  padding: .85rem 1.05rem;
  background: rgba(9, 9, 10, .82);
  backdrop-filter: blur(10px) saturate(115%);
  -webkit-backdrop-filter: blur(10px) saturate(115%);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
}
.map__cardTitle { color: var(--enamel); font-size: .95rem; }
.map__cardAddress { color: var(--steel); font-size: .88rem; line-height: 1.5; }
.map__route {
  margin-top: .4rem;
  justify-self: start;
  color: var(--chrome-lit); font-weight: 600; font-size: .88rem;
  text-decoration: none;
  border-bottom: 1px solid var(--chrome-edge);
  transition: border-color .2s var(--ease);
}
.map__route:hover { border-bottom-color: var(--chrome-lit); }
.map__route::after { content: ' →'; }

/* Die Namensnennung ist Bedingung der ODbL und bleibt als kleine Aufschrift
   oben rechts im Kartenbild sichtbar. */
.map__credit {
  position: absolute;
  top: .45rem; right: .55rem;
  z-index: 1;
  padding: .16rem .35rem;
  color: rgba(255, 255, 255, .78);
  background: rgba(9, 9, 10, .58);
  border-radius: .2rem;
  font-size: .62rem; line-height: 1.25;
  text-decoration: none;
  white-space: nowrap;
}
.map__credit:hover { color: #fff; }

@media (max-width: 40rem) {
  /* Auf dem Telefon nimmt die Karte sonst mehr Höhe als Inhalt. */
  .map-frame { aspect-ratio: 1 / 1; }
  .map__card {
    left: auto; right: var(--sp-3); bottom: var(--sp-3);
    width: min(20rem, calc(100% - 2 * var(--sp-3)));
    padding: .7rem .85rem;
  }
}

/* ---------------------------------------------------------------------
   Fußzeile
   --------------------------------------------------------------------- */
.site-footer {
  background: var(--sunk);
  border-top: 1px solid var(--line);
  color: var(--steel);
  padding-block: var(--sp-7) var(--sp-5);
  font-size: .9rem;
}
.site-footer__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--sp-6);
  padding-bottom: var(--sp-6);
  border-bottom: 1px solid var(--line);
}
.site-footer h2 {
  font-size: .715rem; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase;
  color: var(--chrome-dim);
  margin-bottom: var(--sp-4);
}
.site-footer__workshop {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--sp-4);
}
.site-footer__logo {
  width: clamp(3.5rem, 5vw, 4.25rem);
  filter: drop-shadow(0 8px 16px rgba(0, 0, 0, .55));
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.site-footer a { color: inherit; text-decoration: none; transition: color .18s var(--ease); }
.site-footer a:hover { color: var(--chrome-lit); }
.site-footer__base {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-5);
  align-items: center;
  justify-content: space-between;
  padding-top: var(--sp-5);
  font-size: .82rem; color: var(--steel-dim);
}
.site-footer__seal {
  width: clamp(3.75rem, 6vw, 4.75rem);
  opacity: .8;
  filter: saturate(.88);
}

/* ---------------------------------------------------------------------
   Formulare
   --------------------------------------------------------------------- */
.field { display: block; margin-bottom: var(--sp-4); }
.field__label {
  display: block; margin-bottom: .4rem;
  font-size: .82rem; font-weight: 700;
  letter-spacing: .02em;
}
.field__hint { display: block; margin-top: .35rem; font-size: .8rem; color: var(--steel); }
.field__error {
  display: block; margin-top: .35rem;
  font-size: .82rem; font-weight: 600; color: var(--rust);
}
.req { color: var(--rust); font-weight: 700; }

.input, .select, .textarea {
  width: 100%;
  padding: .72rem .85rem;
  font: inherit; font-size: 1rem;
  color: var(--enamel);
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease),
              background-color .18s var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--steel-dim); }
.input:hover, .select:hover, .textarea:hover { border-color: #3b3c43; }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  background: var(--raise-2);
  border-color: var(--chrome);
  box-shadow: var(--ring);
}
.input[aria-invalid='true'], .select[aria-invalid='true'], .textarea[aria-invalid='true'] {
  border-color: var(--rust);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--rust) 45%, transparent);
}
.textarea { min-height: 7rem; resize: vertical; line-height: 1.6; }
.select {
  appearance: none;
  padding-right: 2.4rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23979ca2' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .9rem center;
}
/* Datums- und Zeitfelder: das Browser-Symbol ist sonst schwarz auf dunkel */
input[type='date'], input[type='time'], input[type='datetime-local'] { color-scheme: dark; }

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: 0 var(--sp-4);
}

/* Honigtopf gegen Formularbots – für Menschen unsichtbar, aber nicht per
   display:none (das erkennen manche Bots) */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px; overflow: hidden;
}

.check {
  display: grid; grid-template-columns: auto 1fr; gap: .7rem;
  align-items: start;
  font-size: .9rem; line-height: 1.55;
  cursor: pointer;
}
.check input { margin-top: .25rem; width: 1.05rem; height: 1.05rem; accent-color: var(--chrome); }

/* ---------------------------------------------------------------------
   Angabenliste: Bezeichnung links, Wert rechts

   Die Grundregel fehlte, obwohl `.kv` an sechs Stellen steht – auch
   öffentlich. Ohne sie fällt die Liste in den Textfluss zurück und der
   Browser rückt jeden Wert um seine eigene Vorgabe ein; die Spalte, an der
   das Auge entlanglaufen soll, gibt es dann gar nicht. Der Werkstattbereich
   verschmälert das Raster über `.kv--tight`.
   --------------------------------------------------------------------- */
.kv {
  display: grid; grid-template-columns: auto 1fr;
  gap: .5rem 1.5rem;
  margin: 0;
  align-items: baseline;
}
.kv dt { color: var(--steel-dim); }
.kv dd { margin: 0; color: var(--enamel); }

/* --- Sicherheitsprüfung ----------------------------------------------
   Der eigene Botschutz (app/BotGuard.php) hat keinen eigenen Kasten mehr.
   Er sitzt als Unterzeile im Absendeknopf: Dorthin schaut ohnehin, wer
   abschicken will, und dort steht die Auskunft, auf die es ankommt –
   nämlich ob das Formular jetzt rausgeht oder noch einen Wimpernschlag
   braucht. Zu drücken gibt es an der Prüfung nichts, sie rechnet selbst.

   Das Element hier trägt nur noch die verborgenen Felder, die Meldung für
   Vorlesegeräte und – wenn JavaScript aus ist – die Ersatzfrage.
   --------------------------------------------------------------------- */
.guard { display: block; }

/* Nur für Vorlesegeräte – der Zustand steht sonst nur im Bild. */
.guard__status {
  position: absolute; left: -9999px;
  width: 1px; height: 1px; overflow: hidden;
}

/* Ohne JavaScript rechnet niemand, dann steht statt der Unterzeile eine
   Frage im Formular. */
.guard__fallback { display: block; margin: var(--sp-5) 0; }
.guard__fallback .input { max-width: 16rem; }

/* --- Die Unterzeile im Knopf -----------------------------------------
   Angehängt von assets/js/guard.js, deshalb steht davon nichts im HTML.

   Gesetzt wie eine Beschriftung mit Zusatz: links das Prüfzeichen über
   beide Zeilen, rechts daneben Titel und Unterzeile an derselben Kante.
   Zentriert stünde die kürzere Zeile eingerückt unter der längeren, und
   das Zeichen hinge aus – zwei linke Kanten sind eine zu viel.

   Alle Zustandstexte liegen übereinander im selben Rasterfeld: Der Knopf
   ist damit so breit wie sein längster Text und bleibt es beim Wechsel.
   Ein Knopf, der beim Umschalten wächst, schöbe die Schaltfläche daneben
   weg – und das mitten in der Bewegung, die er gerade meldet.
   --------------------------------------------------------------------- */
/* Das Zustandsattribut hängt ohnehin am Knopf, sobald er die Unterzeile
   trägt – damit braucht es hier kein :has(). */
.btn[data-guard-state] { justify-content: flex-start; }

.btn__stack {
  display: grid;
  grid-template-columns: auto auto;
  column-gap: .6rem;
  align-items: center;
  text-align: left;
}
.btn__mark { grid-column: 1; grid-row: 1 / span 2; }
.btn__label {
  grid-column: 2;
  line-height: 1.2;
}
.btn__sub {
  grid-column: 2;
  display: grid;
  margin-top: .1rem;
  font-size: .74rem; font-weight: 500;
  letter-spacing: 0; text-transform: none;
  line-height: 1.2;
  opacity: .6;
  transition: opacity .3s var(--ease);
}
.btn[data-guard-state='ok'] .btn__sub { opacity: .75; }

.btn__sub > span {
  grid-area: 1 / 1;
  white-space: nowrap;
  opacity: 0;
  transition: opacity .25s var(--ease);
}
.btn[data-guard-state='working'] [data-guard-text='working'],
.btn[data-guard-state='busy']    [data-guard-text='busy'],
.btn[data-guard-state='ok']      [data-guard-text='ok'] { opacity: 1; }

/* Das Prüfzeichen: ein Ring, der sich dreht, solange gerechnet wird, und
   danach zum Haken wird. Beides aus Rändern gebaut, kein zusätzliches Bild.
   Gefärbt wird mit currentColor: Auf Silber liest sich Grün schlecht, und
   der Zustand steht ohnehin im Text daneben. */
.btn__mark {
  position: relative;
  width: 1.05rem; height: 1.05rem;
  border-radius: 50%;
  border: 1.5px solid transparent;
  border-top-color: currentColor;
  opacity: 0;
  transition: opacity .2s var(--ease);
}
.btn[data-guard-state='working'] .btn__mark,
.btn[data-guard-state='busy'] .btn__mark {
  opacity: 1;
  animation: guard-spin .8s linear infinite;
}
@keyframes guard-spin { to { transform: rotate(360deg); } }

/* Der Haken wird gezeichnet, nicht eingeblendet: zwei Striche, die als
   ein Zug durchlaufen. */
.btn__mark::after {
  content: '';
  position: absolute; left: 26%; top: 4%;
  width: 40%; height: 75%;
  border: solid currentColor;
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg) scale(0);
  transform-origin: center;
  transition: transform .3s var(--ease-mech);
}
.btn[data-guard-state='ok'] .btn__mark {
  opacity: 1;
  border-color: transparent;
}
.btn[data-guard-state='ok'] .btn__mark::after { transform: rotate(45deg) scale(1); }

/* Wer weniger Bewegung eingestellt hat, bekommt den Ring stehend. */
@media (prefers-reduced-motion: reduce) {
  .btn[data-guard-state='working'] .btn__mark,
  .btn[data-guard-state='busy'] .btn__mark { animation: none; }
}

.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip { position: relative; display: inline-flex; }
.chip input {
  position: absolute; opacity: 0; width: 100%; height: 100%;
  margin: 0; cursor: pointer;
}
.chip span {
  padding: .45rem .85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--raise);
  font-size: .87rem; font-weight: 600;
  transition: background-color .18s var(--ease), border-color .18s var(--ease),
              color .18s var(--ease);
}
.chip input:checked + span {
  background: var(--chrome); border-color: var(--chrome); color: var(--on-chrome);
}
.chip input:focus-visible + span { box-shadow: var(--ring); }

/* ---------------------------------------------------------------------
   Meldungen
   --------------------------------------------------------------------- */
.alert {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--line);
  border-left: 4px solid var(--steel-dim);
  border-radius: var(--radius);
  background: var(--raise);
  margin-bottom: var(--sp-5);
  font-size: .95rem; line-height: 1.6;
}
.alert p { margin: 0 0 .4rem; }
.alert p:last-child { margin-bottom: 0; }
.alert strong { display: block; margin-bottom: .2rem; }
.alert--ok { border-left-color: var(--ok); background: var(--ok-wash); }
.alert--error { border-left-color: var(--rust); background: var(--rust-wash); }
.alert--info { border-left-color: var(--chrome); background: var(--chrome-wash); }
.alert__icon { font-size: 1.1rem; line-height: 1.5; }

.form-feedback__summary {
  scroll-margin-top: 6rem;
}
.form-feedback__toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 1.25rem);
  z-index: 90;
  width: max-content;
  max-width: min(30rem, calc(100vw - 2rem));
  translate: -50% 0;
  margin: 0;
  box-shadow: 0 .6rem 2rem rgba(0, 0, 0, .5);
  animation: form-feedback-in .28s var(--ease) both;
}
form[data-inline-submitting] { cursor: progress; }

@keyframes form-feedback-in {
  from { opacity: 0; translate: -50% .6rem; }
  to   { opacity: 1; translate: -50% 0; }
}

@media (max-width: 64rem) {
  .adm .form-feedback__toast {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 4.8rem);
  }
}

.badge {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .22rem .6rem;
  border-radius: 999px;
  font-size: .74rem; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  background: rgba(230, 233, 237, .07); color: var(--steel);
  border: 1px solid var(--line);
}
.badge--ok { background: var(--ok-wash); color: var(--ok); border-color: transparent; }
.badge--wait { background: var(--chrome-wash); color: var(--chrome); border-color: transparent; }
.badge--off { background: var(--rust-wash); color: var(--rust); border-color: transparent; }

/* ---------------------------------------------------------------------
   Inhaltsseiten
   --------------------------------------------------------------------- */
.prose { max-width: 44rem; }
.prose h2 { font-size: 1.5rem; margin-top: var(--sp-7); }
.prose h3 { font-size: 1.1rem; margin-top: var(--sp-5); }
.prose p, .prose li { color: var(--steel); }
.prose p { margin: 0 0 var(--sp-4); }
.prose ul, .prose ol { padding-left: 1.25rem; margin: 0 0 var(--sp-4); }
.prose li { margin-bottom: .4rem; }
.prose li::marker { color: var(--chrome-dim); }
.prose strong { color: var(--enamel); }
.prose a { color: var(--enamel); text-decoration-color: var(--chrome); }
.prose a:hover { color: var(--chrome-lit); }
.prose code { font-family: var(--font-mono); font-size: .88em; color: var(--chrome); }

/* --- Rechtstexte mit Verzeichnis -------------------------------------
   Impressum und Datenschutz sind lang und werden nicht gelesen, sondern
   durchsucht: Jemand will wissen, was mit seiner Telefonnummer passiert,
   nicht die vollständige Erklärung. Deshalb steht der Text links und
   rechts daneben ein Verzeichnis, das mitläuft und zeigt, wo man ist.

   Der Text bekommt eine eigene Spaltenbreite statt der 44rem aus .prose –
   sonst stünde die Spalte im Raster und der Satz nochmals eingerückt
   darin.                                                               */
.legal {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 15rem;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.legal__body { max-width: 46rem; }
/* Der erste Abschnitt braucht keinen Vorlauf, er beginnt die Seite. */
.legal__body > h2:first-child { margin-top: 0; }

/* Angesprungene Abschnitte dürfen nicht unter der Kopfleiste verschwinden.
   scroll-margin und nicht padding: Der Abstand gilt nur beim Springen,
   nicht im Satzbild. */
.legal__body h2 { scroll-margin-top: 6rem; }
/* tabindex="-1" macht die Überschrift anspringbar, damit eine Sprachausgabe
   nach dem Sprung an der richtigen Stelle weiterliest. Der Fokusrahmen wäre
   dabei aber irritierend – man hat nicht getabbt, sondern geklickt. */
.legal__body h2:focus { outline: none; }

.legal__aside {
  position: sticky;
  top: 5.5rem;
  /* Ein Verzeichnis, das länger ist als das Fenster, muss selbst scrollen
     können – sonst sind die letzten Abschnitte nicht erreichbar. */
  max-height: calc(100vh - 7rem);
  overflow-y: auto;
  scrollbar-width: thin;
}
.legal__nav {
  padding-left: var(--sp-4);
  border-left: 1px solid var(--line);
}
.legal__navTitle {
  margin: 0 0 var(--sp-3);
  font-size: .72rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--steel-dim);
}
.legal__navList {
  list-style: none;
  margin: 0; padding: 0;
  display: grid; gap: .1rem;
}
.legal__navLink {
  display: block;
  position: relative;
  padding: .3rem 0 .3rem .9rem;
  color: var(--steel);
  font-size: .86rem; line-height: 1.4;
  text-decoration: none;
  transition: color .2s var(--ease);
}
/* Der Strich vor dem Eintrag ist im Ruhezustand kurz und blass. Beim
   aktiven Abschnitt fährt er auf volle Länge aus – dieselbe Bewegung wie
   die Silberkante an den Karten, nur kleiner. */
.legal__navLink::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 4px; height: 1px;
  background: var(--line);
  translate: 0 -50%;
  transition: width .25s var(--ease-mech), background-color .25s var(--ease);
}
.legal__navLink:hover { color: var(--enamel); }
.legal__navLink:hover::before { width: 8px; background: var(--chrome-dim); }

.legal__navLink.is-current {
  color: var(--chrome-lit);
  font-weight: 600;
}
.legal__navLink.is-current::before {
  width: 12px;
  background: var(--chrome);
}

@media (max-width: 62rem) {
  /* Einspaltig hat ein mitlaufendes Verzeichnis keinen Platz mehr neben dem
     Text. Es wandert nach oben und wird zu dem, was es dann ist: eine
     Sprungliste, einmal am Anfang. */
  .legal { grid-template-columns: 1fr; }
  .legal__aside {
    position: static;
    max-height: none;
    order: -1;
    width: 100%;
  }
  .legal__nav {
    padding: var(--sp-4);
    border-left: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--raise);
  }
  .legal__navList {
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0 var(--sp-4);
  }
}

.page-head {
  --page-head-image:
    image-set(url('/assets/img/subpage-hero-halle.webp?v=2') type('image/webp'),
              url('/assets/img/subpage-hero-halle.jpg?v=2') type('image/jpeg'));
  --page-head-image-position: center 16%;
  --page-head-image-blur: 6px;
  position: relative;
  min-height: clamp(19rem, 31vw, 27rem);
  display: flex;
  align-items: center;
  padding-block: clamp(3.25rem, 7vw, 5.5rem);
  background: #000;
  overflow: hidden;
  isolation: isolate;
}
.page-head::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(90deg,
      rgba(0, 0, 0, .82) 0%,
      rgba(0, 0, 0, .66) 34%,
      rgba(0, 0, 0, .18) 68%,
      rgba(0, 0, 0, .08) 100%),
    linear-gradient(180deg,
      rgba(0, 0, 0, .06) 0%,
      transparent 52%,
      rgba(17, 17, 19, .58) 100%),
    var(--page-head-image);
  background-position: center, center, var(--page-head-image-position);
  background-size: cover;
  background-repeat: no-repeat;
  filter: saturate(.78) contrast(1.02) brightness(1.03) blur(var(--page-head-image-blur));
  transform: scale(1.035);
  transform-origin: center;
  pointer-events: none;
  z-index: -2;
}
.page-head--pickerl {
  --page-head-image:
    image-set(url('/assets/img/pickerl-hero.webp?v=1') type('image/webp'),
              url('/assets/img/pickerl-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--leistungen {
  --page-head-image:
    image-set(url('/assets/img/leistungen-hero.webp?v=2') type('image/webp'),
              url('/assets/img/leistungen-hero.jpg?v=2') type('image/jpeg'));
}
.page-head--oldtimer {
  --page-head-image:
    image-set(url('/assets/img/oldtimer-hero.webp?v=1') type('image/webp'),
              url('/assets/img/oldtimer-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--werkstatt {
  --page-head-image:
    image-set(url('/assets/img/werkstatt-hero.webp?v=1') type('image/webp'),
              url('/assets/img/werkstatt-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--termin {
  --page-head-image:
    image-set(url('/assets/img/termin-hero.webp?v=1') type('image/webp'),
              url('/assets/img/termin-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--kontakt {
  --page-head-image:
    image-set(url('/assets/img/kontakt-hero.webp?v=1') type('image/webp'),
              url('/assets/img/kontakt-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--raederwechsel {
  --page-head-image:
    image-set(url('/assets/img/reifenwechsel-hero.webp?v=1') type('image/webp'),
              url('/assets/img/reifenwechsel-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--diagnose {
  --page-head-image:
    image-set(url('/assets/img/diagnose-hero.webp?v=2') type('image/webp'),
              url('/assets/img/diagnose-hero.jpg?v=2') type('image/jpeg'));
}
.page-head--gebrauchtwagencheck {
  --page-head-image:
    image-set(url('/assets/img/gebrauchtwagencheck-hero.webp?v=1') type('image/webp'),
              url('/assets/img/gebrauchtwagencheck-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--service-inspektion {
  --page-head-image:
    image-set(url('/assets/img/service-inspektion-hero.webp?v=1') type('image/webp'),
              url('/assets/img/service-inspektion-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--bremsen {
  --page-head-image:
    image-set(url('/assets/img/bremsenservice-hero.webp?v=1') type('image/webp'),
              url('/assets/img/bremsenservice-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--klimaservice {
  --page-head-image:
    image-set(url('/assets/img/klimaservice-hero.webp?v=1') type('image/webp'),
              url('/assets/img/klimaservice-hero.jpg?v=1') type('image/jpeg'));
}
.page-head--pickerl,
.page-head--leistungen,
.page-head--oldtimer,
.page-head--werkstatt,
.page-head--termin,
.page-head--kontakt,
.page-head--raederwechsel,
.page-head--diagnose,
.page-head--gebrauchtwagencheck,
.page-head--service-inspektion,
.page-head--bremsen,
.page-head--klimaservice {
  --page-head-image-position: center 44%;
  --page-head-image-blur: 3px;
}
.page-head--kontakt {
  --page-head-image-position: center 28%;
}
/* Die Rechteseiten bleiben bewusst frei von Fotomotiven. Der weiche,
   konzentrische Lichthof rechts gibt der schwarzen Fläche Tiefe, ohne mit
   den langen und sachlichen Seitentiteln zu konkurrieren. */
.page-head--legal::before {
  background:
    radial-gradient(ellipse 48% 95% at 106% 50%,
      rgba(236, 240, 245, .07) 0%,
      rgba(223, 228, 234, .048) 25%,
      rgba(223, 228, 234, .02) 52%,
      rgba(223, 228, 234, .006) 72%,
      transparent 88%),
    linear-gradient(90deg, #000 0%, #000 62%, #020202 100%);
  background-position: center;
  background-size: cover;
  filter: none;
  transform: none;
}
.page-head::after {
  content: '';
  position: absolute; inset: auto 0 0 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    var(--line) 14%,
    var(--chrome-edge) 56%,
    var(--line) 86%,
    transparent 100%);
  opacity: .72;
  pointer-events: none;
  z-index: 0;
}
.page-head > * { position: relative; z-index: 1; }
.page-head h1 {
  filter: drop-shadow(0 3px 18px rgba(0, 0, 0, .86));
}
.page-head .lede {
  color: rgba(230, 233, 237, .78);
  text-shadow: 0 1px 12px rgba(0, 0, 0, .9), 0 1px 2px rgba(0, 0, 0, .7);
}
.page-head .eyebrow {
  text-shadow: 0 1px 10px rgba(0, 0, 0, .92);
}

@media (max-width: 42rem) {
  .page-head {
    --page-head-image-position: 58% center;
    min-height: 18rem;
    padding-block: 3rem;
  }
  .page-head::before {
    background-image:
      linear-gradient(90deg,
        rgba(0, 0, 0, .76) 0%,
        rgba(0, 0, 0, .56) 64%,
        rgba(0, 0, 0, .34) 100%),
      linear-gradient(180deg,
        rgba(0, 0, 0, .05) 0%,
        transparent 44%,
        rgba(17, 17, 19, .62) 100%),
      var(--page-head-image);
    background-position: center, center, var(--page-head-image-position);
  }
  .page-head--pickerl,
  .page-head--leistungen,
  .page-head--oldtimer,
  .page-head--werkstatt,
  .page-head--termin,
  .page-head--raederwechsel,
  .page-head--diagnose,
  .page-head--gebrauchtwagencheck,
  .page-head--service-inspektion,
  .page-head--bremsen,
  .page-head--klimaservice {
    --page-head-image-position: 58% 62%;
  }
  .page-head--kontakt {
    --page-head-image-position: 58% 42%;
  }
  .page-head--legal::before {
    background:
      radial-gradient(ellipse 82% 94% at 126% 50%,
        rgba(236, 240, 245, .07) 0%,
        rgba(223, 228, 234, .04) 32%,
        rgba(223, 228, 234, .012) 62%,
        transparent 88%),
      linear-gradient(90deg, #000 0%, #000 72%, #010101 100%);
  }
}

/* Schlichter Abschluss für Seitenköpfe ohne Kennwerte. */
.page-divider {
  height: 2.25rem;
  background: var(--sunk);
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line);
}

/* --- Zusammenfassungskarte -------------------------------------------
   Steht neben dem Fließtext und bleibt beim Scrollen stehen: die harten
   Angaben (Dauer, Preis, was mitzubringen ist) sollen im Blick bleiben,
   während man liest. Kam aus dem Buchungsassistenten und gehört deshalb
   hierher, nicht in booking.css – sonst steht sie auf Inhaltsseiten ohne
   jede Gestaltung da.
   --------------------------------------------------------------------- */
.summary {
  position: sticky; top: 6rem;
  background: var(--graphite);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
}
.summary h2 {
  font-size: .7rem; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase;
  color: var(--chrome-lit);
  margin-bottom: var(--sp-4);
}
/* Bezeichnung und Wert je Zeile nebeneinander: Das ist ein Datenblatt,
   keine Aufzählung. Die Standardeinrückung von <dd> muss dafür weg. */
.summary dl { margin: 0; display: grid; gap: var(--sp-3); }
.summary dl > div {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-4);
  align-items: baseline;
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line-soft);
}
.summary dl > div:last-child { padding-bottom: 0; border-bottom: 0; }
.summary dt {
  font-size: .7rem; font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase;
  color: rgba(230, 233, 237, .5);
}
.summary dd {
  margin: 0; font-size: .96rem; font-weight: 600;
  text-align: right; text-wrap: balance;
}
.summary dd.data { font-size: 1.02rem; color: var(--chrome-lit); }
.summary__foot {
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 1px solid var(--line-soft);
  font-size: .82rem; color: rgba(230, 233, 237, .6); line-height: 1.55;
}

/* Steht in der Spalte noch etwas unter der Karte – Öffnungszeiten etwa –,
   klebt nicht die Karte allein, sondern die ganze Spalte. Sonst schöbe
   sich der Rest beim Scrollen unter die stehende Karte. */
.aside-sticky { position: sticky; top: 6rem; }
.aside-sticky .summary { position: static; top: auto; }

@media (max-width: 54rem) {
  .summary { position: static; }
  .aside-sticky { position: static; }
}
@media (max-width: 26rem) {
  .summary dl > div { grid-template-columns: 1fr; gap: .15rem; }
  .summary dd { text-align: left; }
}

/* --- Kennwerte direkt unter dem Seitenkopf ---------------------------
   Dieselbe Idee wie das Kennfeld auf der Startseite: harte Angaben statt
   Adjektive, gleich zu Beginn und ohne dass man scrollen muss.
   --------------------------------------------------------------------- */
.spec-strip { background: var(--sunk); border-bottom: 1px solid var(--line); }
.spec-strip__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}
.spec {
  padding: var(--sp-5) var(--sp-5) var(--sp-5) 0;
  border-right: 1px solid var(--line);
}
.spec:last-child { border-right: 0; }
.spec + .spec { padding-left: var(--sp-5); }
.spec__key {
  display: block; margin-bottom: .3rem;
  font-size: .68rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--steel-dim);
}
.spec__value { font-size: 1.02rem; font-weight: 700; line-height: 1.3; }
.spec__value .data { font-weight: 600; color: var(--chrome); }

@media (max-width: 48rem) {
  .spec { border-right: 0; border-bottom: 1px solid var(--line); padding: var(--sp-4) 0; }
  .spec + .spec { padding-left: 0; }
  .spec:last-child { border-bottom: 0; }
}

/* --- Grundsätze ------------------------------------------------------
   Nummeriert, weil es eine Aufzählung mit Anspruch ist: Jeder Punkt ist
   eine Zusage, keine Aufzählung von Eigenschaften.
   --------------------------------------------------------------------- */
.tenets {
  counter-reset: tenet;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--sp-5) var(--sp-6);
  margin: 0; padding: 0; list-style: none;
}
.tenet {
  counter-increment: tenet;
  position: relative;
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  transition: border-color .3s var(--ease);
}
.tenet::before {
  content: counter(tenet, decimal-leading-zero);
  position: absolute; top: .7rem; left: 0;
  font-family: var(--font-mono); font-size: .78rem; font-weight: 600;
  letter-spacing: .06em;
  color: var(--chrome-dim);
  transition: color .3s var(--ease);
}
.tenet:hover { border-top-color: var(--chrome-edge); }
.tenet:hover::before { color: var(--chrome-lit); }
.tenet__title { font-size: 1.05rem; font-weight: 700; margin: var(--sp-4) 0 .35rem; }
.tenet__text { margin: 0; font-size: .93rem; line-height: 1.6; color: var(--steel); }

/* --- Zweispaltiges Band ---------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
@media (max-width: 56rem) { .split { grid-template-columns: 1fr; } }

/* --- Ausstattungsliste: Bezeichnung links, Angabe rechts -------------- */
.facts { list-style: none; margin: 0; padding: 0; }
.facts li {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  justify-content: space-between; align-items: baseline;
  padding: .7rem 0;
  border-bottom: 1px solid var(--line);
  font-size: .95rem;
}
.facts li > span:last-child {
  font-family: var(--font-mono); font-size: .84rem;
  color: var(--steel);
}

/* --- Mitbringliste ---------------------------------------------------- */
.checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.checklist li {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3);
  align-items: start;
  font-size: .95rem; color: var(--steel);
}
.checklist li::before {
  content: '';
  width: .58rem; height: .95rem;
  margin-top: .15rem;
  border: solid var(--chrome-dim);
  border-width: 0 2px 2px 0;
  transform: rotate(40deg);
}

/* --- Handlungsband am Seitenende -------------------------------------- */
.cta-band {
  position: relative;
  background: var(--graphite);
  border-block: 1px solid var(--line);
  overflow: hidden;
}
.cta-band::before {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(65% 120% at 82% 0%, rgba(255, 255, 255, .085) 0%, transparent 64%);
  pointer-events: none;
}
.cta-band__inner {
  position: relative;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-5);
  padding-block: clamp(2.5rem, 6vw, 3.75rem);
}
.cta-band__inner > div { max-width: 38rem; }
.cta-band h2 { margin-bottom: .5rem; }
.cta-band p { margin: 0; color: rgba(230, 233, 237, .74); }

/* =====================================================================
   Fahrzeugthema

   Zwei Stücke, die dieselbe Rechnung teilen wie das Rad in der Kopfleiste:
   Alles, was sich dreht oder wandert, ist an den gescrollten Weg gekoppelt.
   Nichts läuft von selbst. Ein Rad, das sich dreht, während die Seite
   stillsteht, ist Dekoration; eines, das beim Zurückscrollen zurückdreht,
   ist Mechanik.
   ===================================================================== */

/* --- Fahrbahnmarkierung als Abschnittsgrenze --------------------------
   Vorher lag hier ein Profilmuster über die ganze Höhe des Bandes, mit zwei
   verschiedenen Strichbreiten. Zwei Breiten nebeneinander sind genau das,
   was einen Strichcode ausmacht – und danach sah es auch aus. Jetzt ist es
   eine einzelne Mittellinie mit gleich langen Strichen und großen Lücken:
   die Markierung einer Fahrbahn, die unter dem Abschnitt durchläuft.

   Sie wandert beim Scrollen seitlich, gekoppelt an den gescrollten Weg wie
   alles andere hier. Das Muster wiederholt sich alle 40 Pixel, deshalb
   reicht site.js nur den Rest der Division durch 40 herein: So bleibt die
   Zahl klein und die Genauigkeit auch nach zehntausend Pixeln erhalten.

   Die seitliche Reserve von 60 Pixeln ist der Platz, in den das Muster
   hineinwandert; ohne sie liefe an der linken Kante eine Lücke ein. */
.tread {
  position: relative;
  height: 2.25rem;
  overflow: hidden;
  background: var(--sunk);
  /* Nur oben eine Kante: Unten folgt in jedem Fall ein Band, das seine
     eigene mitbringt – zwei Linien nebeneinander sähen aus wie ein
     Versehen. */
  border-top: 1px solid var(--line);
}
.tread::before {
  content: '';
  position: absolute;
  inset: 50% -60px auto;
  height: 2px;
  margin-top: -1px;
  background:
    repeating-linear-gradient(90deg,
      var(--chrome-wash) 0 22px,
      transparent 22px 40px);
  translate: calc(var(--tread, 0) * -1px) 0;
  /* An den Rändern auslaufen lassen: Ein Muster, das an der Kante hart
     abbricht, sieht nach abgeschnittener Kachel aus statt nach Fahrbahn. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
  will-change: translate;
}

/* --- Die Fahrt über dem Ablauf ----------------------------------------
   Das Fahrzeug fährt die Strecke ab, während der Abschnitt durchs Bild
   läuft, und zieht die Fahrbahn hinter sich her. Der Ablauf darunter
   wird damit wörtlich zu einer Fahrt.

   --drive ist der Fortschritt von 0 bis 1, --span der Weg in Pixeln und
   --turns die Zahl der Radumdrehungen auf diesem Weg. Alle drei setzt
   site.js; --turns wird aus Radhalbmesser und Darstellungsgröße
   ausgerechnet, damit das Rad wirklich abrollt und nicht bloß dreht. */
/* Die Höhe bestimmt alles andere: Das Fahrzeug füllt sie ganz aus, seine
   Räder messen ein knappes Halb davon. Nach unten begrenzt das die
   Zeichnung – unter etwa zweiundzwanzig Pixeln Raddurchmesser laufen
   Reifen, Speichen und Nabe zu einem grauen Kreis zusammen, und dann
   sieht man der Drehung nichts mehr an. Die Höhe hier liegt knapp
   darüber: klein genug, um Beiwerk zu bleiben, groß genug, dass sich
   sichtbar etwas dreht. */
.drive {
  position: relative;
  height: clamp(2.4rem, 4.6vw, 3.1rem);
  margin-bottom: var(--sp-6);
}
/* Die Fahrbahn wird gezogen, nicht eingeblendet: Sie endet immer genau
   unter dem Fahrzeug. */
.drive__road {
  position: absolute; inset: auto 0 0 0;
  height: 1px;
  background: linear-gradient(90deg, var(--line) 0%, var(--steel-dim) 100%);
  transform: scaleX(var(--drive, 0));
  transform-origin: left;
}
/* Gedämpfte Farbe, nicht die des Fließtextes: Das Fahrzeug ist Beiwerk
   und soll die Überschrift darüber nicht anfahren. Ein Strichbild in
   voller Helligkeit zieht in einem ruhigen Satzbild sofort den Blick. */
.car-mark {
  position: absolute; bottom: 0; left: 0;
  height: 100%; width: auto;
  color: var(--steel-dim);
  translate: calc(var(--drive, 0) * var(--span, 0) * 1px) 0;
  will-change: translate;
}
/* Drehpunkt je Rad, in viewBox-Einheiten aus car-mark.php. Die Gruppen
   hängen bewusst direkt am SVG: Ein transform-Attribut am Elternteil
   würde den Bezugsrahmen verschieben und die Räder um einen Punkt neben
   dem Fahrzeug kreisen lassen. */
.car-mark__wheel {
  transform-box: view-box;
  transform-origin: var(--cx) var(--cy);
  rotate: calc(var(--drive, 0) * var(--turns, 0) * 1turn);
}

/* =====================================================================
   Bewegung

   Ein einziges System, gesteuert über data-reveal. Sichtbar wird alles
   erst, wenn JavaScript läuft (Klasse .js am <html>) – ohne JavaScript
   steht der Inhalt sofort da, es wird nichts versteckt.
   ===================================================================== */

/* Ausgangszustand */
.js [data-reveal] {
  --d: calc(var(--i, 0) * 80ms);
  will-change: opacity, transform;
}

/* --- rise: der ruhige Standard -------------------------------------- */
.js [data-reveal='rise'] {
  opacity: 0;
  translate: 0 18px;
  transition: opacity .7s var(--ease) var(--d), translate .7s var(--ease) var(--d);
}

/* --- stroke: Kolbenhub. Längerer Weg und härtere Kennlinie als bei
       rise – für Überschriften, die den Abschnitt eröffnen.

       Bewusst ohne clip-path: Ein Clip, der die Fläche leer macht, ist
       für den IntersectionObserver dasselbe wie "nicht sichtbar", das
       Element würde nie auslösen. Der echte Maskeneffekt läuft dort, wo
       er hingehört – im Aufmacher über .hero__line mit overflow. */
.js [data-reveal='stroke'] {
  opacity: 0;
  translate: 0 30px;
  transition: opacity .5s var(--ease) var(--d),
              translate .85s var(--ease-mech) var(--d);
}

/* --- rule: eine Linie läuft aus wie ein Messschieber ---------------- */
.js [data-reveal='rule'] {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .9s var(--ease-mech) var(--d);
}

/* --- deal: Karten werden hereingeschoben --------------------------- */
.js [data-reveal='deal'] {
  opacity: 0;
  translate: -26px 0;
  transition: opacity .55s var(--ease) var(--d), translate .7s var(--ease) var(--d);
}

/* --- settle: Sperrsatz zieht sich zusammen, wie ein Zeiger, der
       einrastet. Nur für Abschnittskennzeichnungen.                    */
.js [data-reveal='settle'] {
  opacity: 0;
  letter-spacing: .5em;
  transition: opacity .5s var(--ease) var(--d),
              letter-spacing .9s var(--ease-mech) var(--d);
}

/* Endzustand – bewusst je Variante, nicht gesammelt.
   Ein gemeinsamer Block würde jedem eingeblendeten Element eine
   Laufweite und eine Transformation aufzwingen: Der Fließtext liefe
   gesperrt wie eine Abschnittskennzeichnung, und weil die Auswahl
   spezifischer ist als .karte:hover, bliebe der Karten-Hover wirkungslos. */
.js [data-reveal].is-in { opacity: 1; translate: 0 0; }
.js [data-reveal='rule'].is-in   { transform: scaleX(1); }
.js [data-reveal='settle'].is-in { letter-spacing: .17em; }

/* Nach dem Einblenden die Kompositionsebene wieder freigeben */
.js [data-reveal].is-done { will-change: auto; }

/* --- Karten, die einblenden UND auf den Zeiger reagieren ---------------
   Hier lag ein Fehler, der beide Kartenarten betraf. Einblenden und Hover
   laufen über dieselbe Eigenschaft, transition, und die Auswahl der
   Einblendung oben ist spezifischer als .slot-card oder .service-card. Die
   Angaben in den Kartenblöcken wurden also überschrieben: Rahmenfarbe,
   Hebung, Schatten und Fläche hatten überhaupt keine Dauer und sprangen
   hart um. Deshalb stehen die vollständigen Listen hier, hinter der
   Einblendung.

   Die Aufteilung bleibt dabei sauber: translate gehört dem Einblenden,
   transform dem Zeiger. So kommen sich die beiden nicht in die Quere.   */
.js .slot-card[data-reveal] {
  transition: opacity .55s var(--ease) var(--d),
              translate .7s var(--ease) var(--d),
              border-color .22s var(--ease),
              transform .22s var(--ease);
}
/* Solange der Zeiger auf der Karte steht, hält sie eine eigene Ebene: eine
   Glasfläche, die sich bewegt und ihren Hintergrund dabei neu rechnet,
   zuckt sonst im ersten Einzelbild. */
.js .slot-card[data-reveal]:hover { will-change: transform; }

/* Die Leistungskarten dürfen sich Zeit nehmen: das Licht, das über sie
   läuft, ist der Auftritt, nicht der Wechsel der Fläche. Deshalb liegen
   Fläche, Rahmen und Schatten bei einer halben Sekunde und die Hebung
   etwas darüber – langsam genug, dass man das Aufhellen sieht. */
.js .service-card[data-reveal] {
  transition: opacity .7s var(--ease) var(--d),
              translate .7s var(--ease) var(--d),
              background-color .5s var(--ease),
              border-color .5s var(--ease),
              box-shadow .55s var(--ease),
              transform .6s var(--ease);
}

/* ---------------------------------------------------------------------
   Bewegung abschalten, wenn das System darum bittet
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .js [data-reveal],
  .js [data-reveal].is-in {
    opacity: 1 !important;
    translate: none !important;
    transform: none !important;
    letter-spacing: normal;
    transition: none !important;
  }
  .js [data-reveal='settle'], .js [data-reveal='settle'].is-in { letter-spacing: .17em; }

  /* Das Fahrzeug fährt beim Scrollen nicht mit. Über --parallax und nicht
     über top, damit die Halle stehenbleibt: Sie hängt an derselben
     Höhenlage, und ein top am Rahmen allein ließe sie weiterfahren. */
  .hero__stage { --parallax: 0 !important; }

  /* Die Kamera steht auf dem Stativ: Halle und Fahrzeug in ihrer
     Ruhelage, ohne Wandern, Zoom und Neigung. */
  .hero__halle,
  .hero__frame {
    animation: none !important;
    transform: none !important;
    rotate: none !important;
  }

  /* Das Fernlicht brennt durch, es zündet nur nicht: kein Blitz, kein
     Atmen, kein Ziehen im Streulicht. Das Licht selbst gehört zum Bild und
     bleibt – in voller Stärke, damit die Scheinwerfer nicht auf einem
     zufälligen Zwischenwert der Runde stehenbleiben. */
  .hero__beams,
  .hero__beam,
  .hero__lamp,
  .hero__glow,
  .hero__pool,
  .hero__streak {
    animation: none !important;
    opacity: 1;
    scale: none;
  }
  .hero__beams { filter: none !important; }

  /* Die Reifenspur des Zeigers entfällt ganz – sie ist nichts als
     Bewegung. site.js legt sie in diesem Fall auch nicht an. */
  .hero__trail { display: none; }

  /* Die Fahrbahn im Hinweis läuft nicht, sie liegt. Der Strich bleibt: Er
     ist die Auskunft, nicht die Bewegung. */
  .hero__moreLine::before { animation: none !important; }

  /* Der Motor steht. Kolben und Pleuel bleiben im oberen Totpunkt. */
  .piston-mark__slide, .piston-mark__rod {
    animation: none !important;
    transform: none !important;
  }

  /* Die Reifenspur steht still, das Fahrzeug hat seine Strecke hinter
     sich: Fahrbahn durchgezogen, Wagen am Ziel. So bleibt das Bild
     vollständig, statt einen halb gefahrenen Weg zu zeigen. */
  .tread::before { translate: none !important; }
  .drive { --drive: 1; --turns: 0; }

  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .hero__line > span { translate: 0 0 !important; }
}

/* ---------------------------------------------------------------------
   Druck
   --------------------------------------------------------------------- */
@media print {
  /* Reifenspur und Fahrt sind reine Bewegung – auf Papier bleibt davon
     nur ein grauer Streifen und ein Strichauto ohne Anlass. */
  .site-header, .site-footer, .nav, .btn-row, .no-print, .page-divider,
  .tread, .drive { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .section { padding-block: 1rem; }
  [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 9pt; color: #555; }
}
