/* Selbst gehostete Variable Fonts – kein Aufruf an Google, DSGVO-konform.
   Syne  (400–800) → Headlines, Navigation
   Inter (100–900) → Fließtext, Bedienelemente

   Bewusst hier und nicht per @import aus einer eigenen Datei: ein @import
   wird erst entdeckt, wenn diese Datei geladen und geparst ist – der
   Browser müsste also styles.css holen, dann die Font-Datei, und erst dann
   die Schriften selbst. Drei Roundtrips hintereinander, bevor der erste
   Buchstabe steht. Direkt hier stehen die @font-face-Regeln mit dem ersten
   Parse-Durchlauf fest; die beiden Latin-Dateien sind zusätzlich im
   <head> vorgeladen.                                                    */

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

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

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

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

/* =========================================================================
   Kolb Lichttechnik — Design-System
   Palette aus der Marke abgeleitet: das Logo-Schiefergrau #4A595C wird zur
   dunklen Basis, das Logo-Rot zur Signalfarbe, dazu ein warmes Lichtgold
   als zweiter Akzent. Licht als Gestaltungsmittel, nicht nur als Thema.
   ========================================================================= */

:root {
  /* --- Umgebungslicht ---------------------------------------------------
     Die Seite ist eine einzige Dimmkurve: oben liegt sie im warmen Dunkel
     des Heros, unten im kühlen, klaren Arbeitslicht der Kontaktsektion.
     --dim (0…1) schreibt main.js aus dem Scrollfortschritt, in Stufen statt
     stufenlos – ein Wert pro Frame würde die großflächigen Verläufe der
     Abschnitte bei jedem Pixel neu rechnen lassen.
     Alle Flächen mischen denselben Ton bei, deshalb wandert die Stimmung,
     ohne dass ein einzelner Abschnitt aus der Reihe fällt.                */
  --dim: 0;
  --amb-warm: #ffb35e;   /* ~2200 K – Glühlampe */
  --amb-cool: #d3e7ff;   /* ~6000 K – Tageslichtweiß */
  --amb: color-mix(in oklab, var(--amb-cool) calc(var(--dim) * 100%), var(--amb-warm));
  /* Der Anteil wächst mit: unten steht mehr Licht im Raum als oben. */
  --amb-mix: calc(1.5% + var(--dim) * 5.5%);

  /* Flächen – kühles Schiefer-Ink unter dem Umgebungslicht */
  --ink-900: color-mix(in oklab, var(--amb) var(--amb-mix), #0c1214);
  --ink-850: color-mix(in oklab, var(--amb) var(--amb-mix), #0f171a);
  --ink-800: color-mix(in oklab, var(--amb) var(--amb-mix), #111a1d);
  --ink-700: color-mix(in oklab, var(--amb) var(--amb-mix), #162126);
  --ink-600: color-mix(in oklab, var(--amb) var(--amb-mix), #1e2c31);
  /* Der Flächenwechsel der Abschnitte. Etwas heller als --ink-850, weil der
     Ton jetzt über einen Verlauf einläuft: eine weiche Kante braucht mehr
     Abstand zur Grundfläche als eine harte, sonst verschwindet sie ganz. */
  --ink-band: color-mix(in oklab, var(--amb) var(--amb-mix), #131d21);
  --line: color-mix(in oklab, var(--amb) var(--amb-mix), #24343a);
  --line-soft: color-mix(in oklab, var(--amb) var(--amb-mix), #1a262b);

  /* Text – nimmt dasselbe Umgebungslicht auf wie die Flächen. Nicht nur der
     Stimmung wegen: die Flächen werden nach unten hin heller, ein fixer
     Grauton verlöre dort Kontrast. --faint stand am unteren Ende der Seite
     sonst nur noch bei 4.57:1 und damit hart an der AA-Grenze; mit dem
     Umgebungslicht bleibt der schwächste Wert über die ganze Kurve bei
     5.15–5.27:1 auf --ink-band. */
  --text: color-mix(in oklab, var(--amb) calc(var(--dim) * 10%), #e8edee);
  --muted: color-mix(in oklab, var(--amb) calc(var(--dim) * 10%), #93a6ab);
  /* aufgehellt von #6b7f85: das ergab auf --ink-850 nur 4.3:1 und lag damit
     unter WCAG AA – betrifft Fact-Labels, Öffnungszeiten, Footer, Formular */
  --faint: color-mix(in oklab, var(--amb) calc(var(--dim) * 14%), #7e9298);

  /* Marke */
  --slate: #4a595c;
  --red: #e04e36;
  --red-deep: #be3a2e;
  /* Auch der Akzent kühlt nach unten hin ab – wenig genug, dass er Gold
     bleibt. Die Flächen holen dabei etwas auf (10.3:1 oben, 9.4:1 unten),
     der Abstand bleibt aber weit über allem, was AA verlangt.            */
  --glow: color-mix(in oklab, var(--amb-cool) calc(var(--dim) * 10%), #f2c46b);

  /* Maße */
  --wrap: 1240px;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --radius: 4px;
  --radius-lg: 8px;
  --header-h: 76px;

  /* Typografie */
  --display: "Syne", "Trebuchet MS", sans-serif;
  --body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* leichter Überschwinger – für alles, was „einrastet“: Druckpunkt von
     Buttons, Icons, die nachziehen. Bewusst schwächer als der Zug an der
     Lampenkordel im Intro, damit die Seite ruhig bleibt.                  */
  --ease-snap: cubic-bezier(0.34, 1.42, 0.64, 1);
}

/* Rückfall ohne Dimmkurve. Nicht kosmetisch, sondern notwendig: kann eine
   Engine das calc() in der Mischungsangabe nicht auflösen, ist der ganze
   color-mix()-Ausdruck ungültig. Ein Custom Property fällt dann nicht auf
   den vorherigen Wert zurück, sondern wird „unset" – die Flächenfarben
   wären schlicht weg und die Seite stünde weiß da. Hier stehen deshalb
   dieselben Töne noch einmal fest, so wie die Seite oben aussieht.      */
@supports not (color: color-mix(in oklab, #ffffff calc(1 * 100%), #000000)) {
  :root {
    --ink-900: #0c1214;
    --ink-850: #0f171a;
    --ink-800: #111a1d;
    --ink-700: #162126;
    --ink-600: #1e2c31;
    --ink-band: #131d21;
    --line: #24343a;
    --line-soft: #1a262b;
    --text: #e8edee;
    --muted: #93a6ab;
    --faint: #7e9298;
    --glow: #f2c46b;
  }
}

/* ---------------------------------------------------------------- Basis */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
  -webkit-text-size-adjust: 100%;
  /* Die Fläche hinter dem Dokument trägt den Footer-Ton: sonst schneidet
     der Footer gegen die Grundfläche ab, sobald das Fenster höher ist als
     der Inhalt oder beim Überziehen am unteren Rand (iOS, Trackpad). */
  background-color: var(--ink-band);
}

body {
  margin: 0;
  background: var(--ink-900);
  color: var(--text);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.7;
  font-feature-settings: "kern", "liga", "calt";
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a { color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
  overflow-wrap: break-word;
}

p { margin: 0 0 1.1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

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

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--glow);
  color: var(--ink-900);
  padding: 0.75rem 1.25rem;
  font-weight: 600;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* ------------------------------------------------------------- Bausteine */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(4.5rem, 10vw, 8.5rem); position: relative; }

/* Weicher Flächenwechsel statt harter Kante: der Bandton läuft über
   --fade-top/--fade-bottom aus der Grundfläche ein und wieder heraus. Die
   Zwischenstopps bilden eine Smoothstep-Kurve nach – ein reiner Verlauf von
   A nach B knickt an seinen beiden Enden und wird dort als Mach-Band wieder
   als Kante sichtbar. Die Verlaufszone bleibt kleiner als das Padding des
   Abschnitts, der Inhalt steht also immer auf dem vollen Ton.
   Gemischt wird gegen --ink-900 statt gegen transparent: `transparent` ist
   durchsichtiges Schwarz und würde die Mitte des Verlaufs abdunkeln. */
.section--alt {
  --band-fade: clamp(3rem, 8vw, 7rem);
  --fade-top: var(--band-fade);
  --fade-bottom: var(--band-fade);
  background-color: var(--ink-band); /* Rückfall, falls color-mix fehlt */
  background-image: linear-gradient(
    to bottom,
    var(--ink-900) 0,
    color-mix(in oklab, var(--ink-band) 16%, var(--ink-900)) calc(var(--fade-top) * 0.25),
    color-mix(in oklab, var(--ink-band) 50%, var(--ink-900)) calc(var(--fade-top) * 0.5),
    color-mix(in oklab, var(--ink-band) 84%, var(--ink-900)) calc(var(--fade-top) * 0.75),
    var(--ink-band) var(--fade-top),
    var(--ink-band) calc(100% - var(--fade-bottom)),
    color-mix(in oklab, var(--ink-band) 84%, var(--ink-900)) calc(100% - var(--fade-bottom) * 0.75),
    color-mix(in oklab, var(--ink-band) 50%, var(--ink-900)) calc(100% - var(--fade-bottom) * 0.5),
    color-mix(in oklab, var(--ink-band) 16%, var(--ink-900)) calc(100% - var(--fade-bottom) * 0.25),
    var(--ink-900) 100%
  );
}

/* Der letzte Abschnitt geht direkt in den Footer über – die beiden bilden
   eine durchgehende Fläche, ein Auslaufen dazwischen wäre genau die Kante,
   die hier verschwinden soll. */
main > .section--alt:last-child { --fade-bottom: 0px; }

/* Trennlinie, die an den Rändern ausläuft – eine randlose Linie über die
   volle Breite würde die weiche Fläche darunter wieder hart abschneiden. */
.section--line::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: linear-gradient(to right,
              transparent, var(--line-soft) 15%, var(--line-soft) 85%, transparent);
  pointer-events: none;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--glow);
  margin: 0 0 1.25rem;
}
.eyebrow::before {
  content: "";
  width: 28px;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
}

.section-head { max-width: 60ch; margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.section-head h2 { font-size: clamp(2rem, 4.6vw, 3.25rem); }
.section-head .lead { margin-top: 1.25rem; color: var(--muted); font-size: 1.0625rem; }

.lead { font-size: 1.125rem; line-height: 1.75; color: var(--muted); }

/* Buttons */

.btn {
  /* je Variante gesetzt: Farbe des Lichtstreifs und des Lichthofs */
  --sheen: rgb(255 255 255 / 0.32);
  --halo: transparent;

  position: relative;
  /* eigener Stapelkontext: die beiden Pseudoelemente liegen dadurch über
     der Buttonfläche, aber unter der Beschriftung – ohne overflow:hidden,
     das sonst den Lichthof nach außen abschneiden würde.                  */
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.9rem 1.6rem;
  font-family: var(--body);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease),
              color 0.25s var(--ease), transform 0.25s var(--ease-snap);
}

/* Lichtstreif: der Verlauf ist gut doppelt so breit wie der Button und
   steht im Ruhezustand rechts außerhalb der Fläche. Wie weit „außerhalb“
   liegt, hängt vom Seitenverhältnis des Buttons ab – ein schräger Verlauf
   ragt in einen breiten, flachen Button schon bei 0 % hinein. Deshalb
   zusätzlich opacity:0 im Ruhezustand: das gilt für jede Buttonbreite.   */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(100deg, transparent 38%, var(--sheen) 50%, transparent 62%);
  background-size: 220% 100%;
  background-repeat: no-repeat;
  background-position: -60% 0;
  opacity: 0;
  pointer-events: none;
}

/* Lichthof – getrennt vom box-shadow des Buttons, weil das Licht-Intro
   den Hero-Buttons dort bereits eigene Schatten gibt.                    */
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: inherit;
  box-shadow: 0 8px 26px -6px var(--halo);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}

@media (hover: hover) {
  .btn:hover { transform: translateY(-2px); }
  .btn:hover::before { animation: btnSheen 0.75s var(--ease); }
  .btn:hover::after { opacity: 1; }
  .btn:hover svg { translate: 3px 0; }
}
@keyframes btnSheen {
  from { background-position: -60% 0; opacity: 1; }
  82%  { opacity: 1; }
  to   { background-position: 160% 0; opacity: 0; }
}

/* Druckpunkt: kurz und ohne Überschwinger, damit der Klick sitzt */
.btn:active {
  transform: translateY(0) scale(0.975);
  transition-duration: 0.09s;
}
.btn:active::after { opacity: 0.6; }

.btn--primary { background: var(--red); color: #fff; --halo: rgb(224 78 54 / 0.55); }
.btn--primary:hover { background: #ee5c43; }

.btn--ghost {
  border-color: var(--line);
  color: var(--text);
  background: transparent;
  --sheen: rgb(242 196 107 / 0.14);
  --halo: rgb(242 196 107 / 0.28);
}
.btn--ghost:hover { border-color: var(--glow); color: var(--glow); }

.btn--glow { background: var(--glow); color: var(--ink-900); --halo: rgb(242 196 107 / 0.5); }
.btn--glow:hover { background: #f7d287; }

/* Anfrage raus = Licht an. Der Absende-Button durchläuft dieselbe Zündkurve
   wie die Lampe im Hero: aus dem Signalrot wird das warme Lichtgold, und der
   Button steht am Ende in seinem eigenen Lichthof. --lit schreibt main.js.
   Doppelte Klasse, damit die Regel nach dem Zünden auch den :hover-Zustand
   der Variante überstimmt – der Button soll leuchten bleiben.             */
.btn.btn--ignite {
  --lit: 0;
  --halo: rgb(242 196 107 / 0.55);
  background: color-mix(in oklab, var(--glow) calc(var(--lit) * 100%), var(--red));
  color: color-mix(in oklab, var(--ink-900) calc(var(--lit) * 100%), #fff);
  box-shadow:
    0 0 calc(var(--lit) * 32px) calc(var(--lit) * -4px) rgb(242 196 107 / 0.7),
    0 0 0 calc(var(--lit) * 3px) rgb(242 196 107 / 0.12);
}
.btn.btn--ignite.is-igniting { transition: none; }
.btn.btn--ignite.is-warming {
  transition: background 0.8s linear, color 0.8s linear, box-shadow 0.8s linear;
}
.btn.btn--ignite.is-lit::after { opacity: 1; }

.btn svg { width: 1em; height: 1em; flex: none; transition: translate 0.25s var(--ease-snap); }

/* ---------------------------------------------------------------- Header */

.header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  transition: background 0.35s var(--ease), border-color 0.35s var(--ease),
              backdrop-filter 0.35s var(--ease);
  border-bottom: 1px solid transparent;
}
.header.is-stuck {
  background: rgb(12 18 20 / 0.88);
  backdrop-filter: blur(14px) saturate(1.3);
  border-bottom-color: var(--line-soft);
}

/* Lichtleiste: läuft mit dem Scrollfortschritt an der Unterkante des
   Headers entlang. Das Element setzt main.js – ohne JS gibt es keinen
   Fortschritt anzuzeigen und damit auch keine Leiste.
   scale statt width: keine Layoutarbeit pro Scroll-Frame.               */
.header__beam {
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 100%;
  height: 2px;
  transform-origin: left;
  scale: var(--progress, 0) 1;
  background: linear-gradient(90deg, var(--red), var(--glow));
  box-shadow: 0 0 12px rgb(242 196 107 / 0.4);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  pointer-events: none;
}
.header.is-stuck .header__beam { opacity: 0.9; }

.header .wrap {
  display: flex;
  align-items: center;
  gap: 2rem;
}

.brand { flex: none; line-height: 0; }
.brand img { width: clamp(132px, 15vw, 168px); }

.nav { margin-left: auto; }
.nav ul {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.1rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav a {
  position: relative;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--muted);
  text-decoration: none;
  padding-block: 0.4rem;
  transition: color 0.2s var(--ease);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 0;
  background: var(--glow);
  transition: width 0.28s var(--ease);
}
.nav a:hover,
.nav a[aria-current="true"] { color: var(--text); }
.nav a:hover::after,
.nav a[aria-current="true"]::after { width: 100%; }

/* der CTA im Menü ist nur die mobile Variante des Buttons rechts */
.nav__cta { display: none; }

.header-actions { display: flex; align-items: center; gap: 1rem; flex: none; }

.header-tel {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s var(--ease);
}
.header-tel:hover { color: var(--glow); }
.header-tel svg { width: 15px; height: 15px; }

.header .btn { padding: 0.7rem 1.25rem; font-size: 0.875rem; }

/* Burger */

.burger {
  display: none;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--text);
}
.burger span {
  display: block;
  width: 22px;
  height: 1.5px;
  margin: 5px auto;
  background: currentColor;
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* ------------------------------------------------------------------ Hero */

.hero {
  position: relative;
  min-height: min(92svh, 900px);
  display: flex;
  align-items: flex-end;
  padding-top: calc(var(--header-h) + 4rem);
  padding-bottom: clamp(3rem, 7vw, 6rem);
  overflow: hidden;
  isolation: isolate;
}

/* min-width:0 ist zwingend: sonst erzwingt die Mindestbreite der H1 als
   Flex-Item eine Breite über dem Viewport und schiebt alles über den Rand. */
.hero__inner {
  width: 100%;
  min-width: 0;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Gewicht 700 wie bei allen anderen Überschriften – und nicht mehr:
   Synes avar-Tabelle staucht die Achse bis 700 auf ein Drittel des
   Designraums und legt den Rest in die letzten 100 Einheiten. „Professionelle"
   ist bei 800 um 46 % breiter als bei 700, die Schrift kippt dort in einen
   Extended-Schnitt und wirkt gestreckt. Das enge Tracking war nur die
   Gegenwehr dagegen und kann mit weg.
   Der vw-Anteil ist so gewählt, dass „Professionelle" auch auf 360px-Geräten
   in eine Zeile passt und nicht mitten im Wort umbrochen wird.              */
.hero h1 {
  font-size: clamp(1.75rem, 9vw, 6.25rem);
  font-weight: 700;
  letter-spacing: -0.022em;
  max-width: 16ch;
  overflow-wrap: break-word;
}
.hero h1 em {
  font-style: normal;
  color: var(--glow);
  /* dezentes Leuchten – Licht als Typo-Mittel */
  text-shadow: 0 0 42px rgb(242 196 107 / 0.35);
}

.hero__text { max-width: 54ch; margin-top: 1.75rem; font-size: clamp(1rem, 1.6vw, 1.1875rem); color: #c3cfd2; }

.hero__cta { display: flex; flex-wrap: wrap; gap: 0.875rem; margin-top: 2.5rem; }

.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 5vw, 4rem);
  margin-top: clamp(3rem, 6vw, 4.5rem);
  padding-top: 2rem;
  border-top: 1px solid rgb(255 255 255 / 0.1);
}
.hero__facts div { min-width: 0; }
.hero__facts dt {
  font-family: var(--display);
  font-size: clamp(1.75rem, 3.4vw, 2.5rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text);
  /* Die Jahreszahl zählt beim Einschalten hoch – mit Proportionalziffern
     würde die Zeile dabei bei jedem Zwischenwert leicht zappeln. */
  font-variant-numeric: tabular-nums;
}
.hero__facts dd {
  margin: 0.55rem 0 0;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
}

/* --------------------------------------------------------------- Zitat */

.pullquote { display: grid; grid-template-columns: 1.05fr 1fr; gap: clamp(2.5rem, 6vw, 5rem); align-items: center; }

.pullquote blockquote {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.5rem, 3.2vw, 2.375rem);
  font-weight: 600;
  line-height: 1.28;
  letter-spacing: -0.025em;
}
.pullquote blockquote strong { color: var(--glow); font-weight: 600; }
.pullquote cite {
  display: block;
  margin-top: 1.75rem;
  font-family: var(--body);
  font-size: 0.8125rem;
  font-style: normal;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint);
}

/* --------------------------------------------------------- Leistungen */

/* Sechs Spalten als Grundraster statt drei gleich großer: die beiden
   Bereiche, in denen gerechnet wird, bekommen Platz für das Ergebnis der
   Rechnung. 2+4 / 2+2+2 / 6 geht ohne Leerzelle auf.                    */
.services {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

/* --- Die Lichtkette -------------------------------------------------
   01 bis 06 ist eine Reihenfolge, keine Aufzählung. Beim Eintritt in den
   Viewport läuft deshalb ein Licht durch das Raster – Feld für Feld in
   der Reihenfolge der Nummern –, und unter jedem bleibt ein schmaler
   warmer Streifen stehen: die Leitung, die die sechs verbindet.

   --lit ist die Helligkeit, --delay der Versatz des einzelnen Feldes;
   beides schreibt main.js. Übergänge tragen den Versatz fest im Wert,
   dann genügt ein einziger Klassenwechsel am Raster, um alle sechs
   nacheinander anzuschalten. Ohne JS, ohne IntersectionObserver und bei
   reduzierter Bewegung bleibt --lit auf 1 – dann steht alles im Licht. */
.service { --lit: 1; }
.js .services.is-dark .service { --lit: 0; }

.service {
  --pad: clamp(1.75rem, 3vw, 2.5rem);
  position: relative;
  isolation: isolate;
  grid-column: span 2;
  background: color-mix(in oklab, var(--ink-850) calc(var(--lit) * 100%), var(--ink-900));
  padding: var(--pad);
  transition: background 0.55s var(--ease) var(--delay, 0ms);
}

/* Der Zeiger wird zur Lichtquelle: ein weicher Schein folgt ihm über die
   Kachel. --mx/--my setzt main.js, z-index:-1 hält den Schein unter der
   Schrift. Nur für Zeigergeräte – auf Touch gäbe es nichts zu folgen.   */
@media (hover: hover) and (pointer: fine) {
  .service::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 0%),
                rgb(242 196 107 / 0.07), transparent 68%);
    opacity: 0;
    transition: opacity 0.35s var(--ease);
    pointer-events: none;
  }
  .service:hover::after { opacity: 1; }
}
/* Der Streifen an der Unterkante: zieht sich auf, wenn das Licht das Feld
   erreicht, und bleibt danach gedämpft stehen. Beim Hover geht er voll an. */
.service::before {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: linear-gradient(90deg, var(--red), var(--glow));
  transform: scaleX(var(--lit));
  transform-origin: left;
  opacity: calc(var(--lit) * 0.28);
  transition: transform 0.55s var(--ease) var(--delay, 0ms),
              opacity 0.55s var(--ease) var(--delay, 0ms);
}
.service:hover { background: var(--ink-700); }
.service:hover::before { transform: scaleX(1); opacity: 1; }

.service__icon {
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  margin-bottom: 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: color-mix(in oklab, var(--glow) calc(var(--lit) * 100%), var(--line));
  background: var(--ink-900);
  /* der Lichthof wächst mit: aus dem dunklen Zustand kommt gar keiner */
  box-shadow: 0 0 calc(var(--lit) * 20px) calc(var(--lit) * -8px) rgb(242 196 107 / 0.55);
  transition: color 0.55s var(--ease) var(--delay, 0ms),
              box-shadow 0.55s var(--ease) var(--delay, 0ms),
              border-color 0.3s var(--ease);
}
.service__icon svg { width: 24px; height: 24px; }
.service:hover .service__icon { color: var(--red); border-color: var(--slate); }

.service h3 {
  font-size: 1.1875rem;
  letter-spacing: -0.015em;
  color: color-mix(in oklab, var(--text) calc(var(--lit) * 100%), var(--ink-600));
  transition: color 0.55s var(--ease) var(--delay, 0ms);
}
.service p {
  margin-top: 0.75rem;
  margin-bottom: 0;
  font-size: 0.9375rem;
  color: color-mix(in oklab, var(--muted) calc(var(--lit) * 100%), var(--ink-600));
  transition: color 0.55s var(--ease) var(--delay, 0ms);
}

.service__no {
  position: absolute;
  top: var(--pad);
  right: var(--pad);
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--line);
  letter-spacing: 0.05em;
  transition: color 0.3s var(--ease);
}
.service:hover .service__no { color: var(--faint); }

/* --- Die beiden großen Felder ---------------------------------------
   Zusätzliches Polster oben: die Nummer sitzt frei in der Ecke, sonst
   liefe ihr die Grafik hinein.                                         */
.service--feature,
.service--wide {
  display: grid;
  gap: clamp(1.5rem, 3.5vw, 3rem);
  padding-top: calc(var(--pad) + 1.5rem);
}

.service--feature {
  grid-column: span 4;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr);
  align-items: start;
}
/* Text oben, Grafik unten bündig – die Nummer behält ihre Ecke */
.service--feature .service__figure { align-self: end; }

.service--wide {
  grid-column: span 6;
  grid-template-columns: minmax(0, 1fr) minmax(200px, 330px);
  align-items: center;
}

.service__figure {
  color: var(--glow);
  /* die Grafik rechnet sich mit dem Licht heraus */
  opacity: calc(0.14 + 0.86 * var(--lit));
  transition: opacity 0.55s var(--ease) var(--delay, 0ms);
}
.service__figure svg { display: block; width: 100%; height: auto; }

.service__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.15rem;
  margin: 0.85rem 0 0;
  font-size: 0.75rem;
  color: var(--faint);
}
.service__legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
.service__legend span::before {
  content: "";
  width: 13px;
  height: 2px;
  border-radius: 1px;
  background: var(--faint);
}
.service__legend .is-bestand::before { background: var(--red); }
.service__legend .is-led::before { background: var(--glow); }
.service__legend .is-amort::before {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: none;
  border: 2px solid var(--glow);
}

/* ----------------------------------------------------------- Projekte */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2.5rem;
}
.filter {
  padding: 0.55rem 1.1rem;
  font-family: var(--body);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 100px;
  cursor: pointer;
  transition: all 0.25s var(--ease);
}
.filter:hover { color: var(--text); border-color: var(--slate); transform: translateY(-1px); }
.filter:active { transform: translateY(0) scale(0.97); transition-duration: 0.09s; }
.filter[aria-pressed="true"] {
  background: var(--text);
  border-color: var(--text);
  color: var(--ink-900);
  /* der gewählte Filter liegt in einem schwachen Lichtkranz */
  box-shadow: 0 0 0 4px rgb(232 237 238 / 0.06), 0 6px 20px -8px rgb(232 237 238 / 0.35);
}

/* Festes Zeilenraster statt aspect-ratio: nur so entstehen keine Lücken,
   wenn einzelne Kacheln mehrere Spalten oder Zeilen belegen.              */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  grid-auto-rows: clamp(150px, 16vw, 232px);
  grid-auto-flow: dense;
  gap: 1rem;
  margin: 0;
}

.tile {
  position: relative;
  display: block;
  margin: 0;
  padding: 0;
  height: 100%;
  border: 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--ink-700);
  cursor: pointer;
  isolation: isolate;
}
.tile.is-hidden { display: none; }
/* Über der Mengenbegrenzung – getrennt von is-hidden, weil Filter und
   „Mehr anzeigen" unabhängig voneinander zurückgenommen werden. */
.tile.is-over { display: none; }

.gallery-more { display: flex; justify-content: center; margin-top: clamp(1.75rem, 4vw, 2.75rem); }
.gallery-more[hidden] { display: none; }
.gallery-more__count { color: var(--faint); font-weight: 500; font-variant-numeric: tabular-nums; }

/* Nach einem Filterwechsel gehen die verbleibenden Kacheln nacheinander
   an, statt schlagartig umzuspringen. --i vergibt main.js in der neuen
   Reihenfolge, die Klasse wird bei jedem Klick neu gesetzt.
   Das .js davor ist kein Zierrat: die Regel muss die Einblend-Animation
   der Staffelung überstimmen, und die trägt dieselbe Spezifität.        */
.js .gallery.is-filtering .tile:not(.is-hidden) {
  animation: tileIn 0.5s var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * 45ms);
}
@keyframes tileIn {
  from { opacity: 0; scale: 0.96; }
  to   { opacity: 1; scale: 1; }
}

/* Format folgt dem Motiv: Panoramen breit, Hochformate hoch, Leitbild groß */
.tile--wide { grid-column: span 2; }
.tile--tall { grid-row: span 2; }
.tile--big  { grid-column: span 2; grid-row: span 2; }

/* --- Die Lichtkante ------------------------------------------------
   Über die Galerie läuft beim Scrollen eine einzige Lichtkante: die
   Kacheln stehen halbdunkel und werden hell, sobald die Kante über sie
   hinwegzieht – Zeile für Zeile, in jeder Zeile von links nach rechts.
   Kein Flackern: eine zündende Leuchtstoffröhre hieße „defekt", und die
   Firma verkauft LED. Der dunkle Zustand bleibt bewusst hell genug, dass
   jedes Motiv lesbar ist – die Fotos sind das Kapital der Seite, sie
   dürfen nicht verschwinden, nur warten.
   --lit ist die Helligkeit, --warm die Farbtemperatur (0 = 2000 K),
   --delay der Versatz aus der Bildschirmposition; alle drei schreibt
   main.js pro Kachel. Ohne JS oder ohne IntersectionObserver bleiben die
   Vorgaben stehen und die Bilder sind von Anfang an hell.             */
.gallery .tile { --lit: 1; --warm: 1; }
.js .gallery.is-dark .tile { --lit: 0; --warm: 0; }

.tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Ein Filterausdruck für alles: der Hover-Aufheller steckt als --hov mit
     drin, statt die Kette per eigener filter-Regel zu ersetzen – sonst
     risse ein Hover die Kachel schlagartig aus dem Wartezustand.
     Die Helligkeit geht quadratisch in --lit ein, wie bei einem echten
     Dimmer: linear gerechnet sieht schon eine halbe Stufe fast voll hell
     aus und die Kante verlöre ihre Kontur.                             */
  filter:
    brightness(calc((0.45 + 0.55 * var(--lit) * var(--lit)) * var(--hov, 1)))
    saturate(calc(0.55 + 0.45 * var(--lit)))
    contrast(calc(1.06 - 0.06 * var(--lit)))
    sepia(calc(0.3 * (1 - var(--warm))))
    hue-rotate(calc(-10deg * (1 - var(--warm))));
  transition: transform 0.7s var(--ease), filter 0.4s var(--ease);
}
/* Während die Kante läuft: linear und mit dem Versatz aus der Position.
   Linear, weil sich nur so mehrere Kacheln zu einer durchgehenden Kante
   überlagern – jede eigene Ein-/Ausschwingkurve zerlegte sie wieder in
   einzelne Ereignisse.                                                 */
.tile.is-lighting img {
  transition: filter 0.75s linear var(--delay, 0ms), transform 0.7s var(--ease);
}

/* Hover nur dort, wo es Hover gibt: auf Touch bliebe der Zustand sonst
   nach dem Antippen hängen. */
@media (hover: hover) {
  .tile { transition: box-shadow 0.35s var(--ease), translate 0.35s var(--ease); }
  .tile:hover img { transform: scale(1.055); --hov: 1.06; }
  .tile:hover { translate: 0 -3px; box-shadow: 0 18px 36px -18px rgb(0 0 0 / 0.75); }

  /* warme Innenkante – als läge Licht auf dem Rand der Kachel */
  .tile::after {
    content: "";
    position: absolute;
    inset: 0;
    box-shadow: inset 0 0 0 1px rgb(242 196 107 / 0);
    transition: box-shadow 0.35s var(--ease);
    pointer-events: none;
  }
  .tile:hover::after,
  .tile:focus-visible::after { box-shadow: inset 0 0 0 1px rgb(242 196 107 / 0.35); }
}

.tile figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 2.5rem 1.125rem 1.05rem;
  text-align: left;
  background: linear-gradient(to top, rgb(6 10 11 / 0.92), transparent);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text);
  translate: 0 6px;
  opacity: 0;
  transition: opacity 0.3s var(--ease), translate 0.3s var(--ease);
}
@media (hover: hover) {
  .tile:hover figcaption { opacity: 1; translate: 0 0; }
}
.tile:focus-visible figcaption { opacity: 1; translate: 0 0; }
/* Touch-Geräte (auch iPad im Querformat) sehen die Bildunterschrift immer */
@media (hover: none) {
  .tile figcaption { opacity: 1; translate: 0 0; }
}
.tile figcaption span { display: block; font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--glow); margin-bottom: 0.2rem; }

/* Lightbox */

/* Das Browser-Stylesheet gibt <dialog> width/height:fit-content und
   margin:auto – inset:0 allein füllt den Viewport deshalb nicht, die Box
   bliebe inhaltsgroß und die Seite ringsum sichtbar. Maße und max-* müssen
   explizit zurückgesetzt werden.                                          */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 150;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  padding-bottom: max(clamp(1rem, 4vw, 3rem), env(safe-area-inset-bottom));
  background: rgb(6 10 11 / 0.92);
  backdrop-filter: blur(6px);
  border: 0;
  overscroll-behavior: contain;
  touch-action: pan-y;
  opacity: 0;
  /* transition-behavior separat: kennt der Browser es nicht, fallen nur die
     beiden diskreten Einträge weg – die Opacity-Transition bleibt gültig. */
  transition: opacity 0.3s var(--ease), display 0.3s, overlay 0.3s;
  transition-behavior: allow-discrete;
}
/* display:grid überschreibt das UA-`dialog:not([open]){display:none}` – der
   geschlossene Dialog läge sonst unsichtbar (opacity:0) über der ganzen Seite
   und würde jeden Klick schlucken, u. a. den auf die Hero-Bühne. */
/* pointer-events zusätzlich, weil `display` per allow-discrete erst am Ende
   der Ausblendung umschaltet – bis dahin wäre die Seite weiter geblockt. */
.lightbox:not([open]) { display: none; pointer-events: none; }
.lightbox[open] { opacity: 1; }
@starting-style { .lightbox[open] { opacity: 0; } }
/* deckt die Seite auch dann ab, wenn der Dialog selbst noch einblendet */
.lightbox::backdrop { background: rgb(6 10 11 / 0.9); }

.lightbox img {
  max-width: 100%;
  max-height: 76svh;
  width: auto;
  border-radius: var(--radius);
  box-shadow: 0 30px 80px rgb(0 0 0 / 0.6);
}
/* Das Bild wechselt nicht hart und blendet auch nicht einfach auf: es wird
   hochgedimmt. Die Kurve ist die eines echten Dimmers – am unteren Ende
   passiert lange wenig, dann zieht die Helligkeit durch – und die Farbe
   läuft dabei von Glühlampenwarm nach neutral, wie bei der Lampe im Hero.
   Die Klasse setzt main.js bei jedem Bildwechsel neu.                   */
.lightbox img.is-swap { animation: lbDim 0.52s cubic-bezier(0.42, 0, 0.3, 1); }
@keyframes lbDim {
  from { opacity: 0.35; filter: brightness(0.1) saturate(0.3) contrast(1.16) sepia(0.4) hue-rotate(-14deg); }
  45%  { opacity: 1;    filter: brightness(0.55) saturate(0.62) contrast(1.09) sepia(0.22) hue-rotate(-8deg); }
  to   { opacity: 1;    filter: none; }
}
.lightbox__caption { margin-top: 1.25rem; text-align: center; font-size: 0.9375rem; color: var(--muted); }
.lightbox__caption span { display: block; font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--glow); margin-bottom: 0.35rem; }

.lightbox__btn {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  background: rgb(255 255 255 / 0.07);
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--text);
  cursor: pointer;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease),
              box-shadow 0.25s var(--ease), scale 0.25s var(--ease-snap);
}
.lightbox__btn:hover {
  background: rgb(255 255 255 / 0.14);
  border-color: var(--slate);
  scale: 1.08;
  box-shadow: 0 0 22px -4px rgb(242 196 107 / 0.35);
}
.lightbox__btn:active { scale: 0.96; transition-duration: 0.09s; }
.lightbox__btn--prev { left: clamp(0.5rem, 2vw, 2rem); }
.lightbox__btn--next { right: clamp(0.5rem, 2vw, 2rem); }
.lightbox__close { top: clamp(0.75rem, 2vw, 1.5rem); right: clamp(0.75rem, 2vw, 1.5rem); translate: 0; position: absolute; }

/* --------------------------------------------------------- Unternehmen */

.about { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2.5rem, 6vw, 5rem); align-items: center; }
.about__media { position: relative; }
.about__media img { border-radius: var(--radius-lg); }
.about__media figcaption {
  margin-top: 0.875rem;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Chronik: Zeitstrahl links, Porträt des Geschäftsführers rechts daneben */

.chronik { display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: start; }

.chronik__person figure { margin: 0; }
.chronik__person img {
  width: 100%;
  border-radius: var(--radius-lg);
  object-fit: cover;
  object-position: center 25%;
  aspect-ratio: 1;
}
.chronik__person figcaption { margin-top: 1.125rem; }
.chronik__person strong { display: block; font-family: var(--display); font-size: 1.125rem; }
.chronik__person figcaption span { font-size: 0.875rem; color: var(--muted); }
.chronik__person p {
  margin: 1.125rem 0 0;
  padding-top: 1.125rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.9375rem;
  color: var(--muted);
}
.chronik__link {
  display: inline-block;
  margin-top: 1.125rem;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--glow);
  text-decoration: none;
  border-bottom: 1px solid rgb(242 196 107 / 0.35);
  transition: border-color 0.2s var(--ease);
}
.chronik__link:hover { border-color: var(--glow); }

@media (min-width: 1000px) {
  .chronik { grid-template-columns: minmax(0, 1fr) minmax(240px, 320px); }
  /* das Porträt läuft neben dem entstehenden Zeitstrahl mit */
  .chronik__person { position: sticky; top: calc(var(--header-h) + 2.5rem); }
}

@media (max-width: 999px) {
  .chronik__person { max-width: 420px; }
}

/* Zeitstrahl – ersetzt das Bild der alten Seite durch echtes Markup.
   Die Linie wächst beim Scrollen mit: --tl (0…1) setzt main.js, jeder
   erreichte Punkt bekommt .is-lit. Ohne JS steht alles auf sichtbar.      */

.timeline {
  --dot: 38px;          /* Durchmesser der Marker */
  --rail-x: 19px;       /* Mitte der Linie, = Mitte des Markers */
  position: relative;
  margin-top: clamp(3rem, 6vw, 5rem);
}

/* ruhende Spur – läuft exakt von der Mitte des ersten bis zur Mitte des
   letzten Markers; die genauen Maße misst main.js (--rail-top/--rail-h).   */
.timeline__rail {
  position: absolute;
  left: var(--rail-x);
  top: var(--rail-top, calc(var(--dot) / 2));
  height: var(--rail-h, calc(100% - var(--dot)));
  width: 2px;
  translate: -1px 0;
  background: var(--line-soft);
  border-radius: 2px;
}

/* der wachsende, leuchtende Teil */
.timeline__rail::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(to bottom, var(--red), var(--glow) 45%, var(--glow));
  box-shadow: 0 0 14px rgb(242 196 107 / 0.45);
  transform-origin: top;
  scale: 1 var(--tl, 0);
  transition: scale 0.35s linear;
}

/* Lichtpunkt an der Spitze der Linie */
.timeline__rail i {
  position: absolute;
  z-index: 2;            /* der Lichtpunkt läuft über die Marker hinweg */
  left: 50%;
  top: calc(var(--tl, 0) * 100%);
  width: 9px;
  height: 9px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: var(--glow);
  box-shadow: 0 0 18px 4px rgb(242 196 107 / 0.55);
  opacity: calc(1 - var(--tl, 0) * var(--tl, 0));
  transition: top 0.35s linear, opacity 0.35s linear;
}

.timeline__list { list-style: none; margin: 0; padding: 0; }

.timeline__item {
  display: grid;
  grid-template-columns: var(--dot) 1fr;
  column-gap: 1.25rem;
  align-items: start;
  padding-bottom: clamp(2rem, 4vw, 2.75rem);
}
.timeline__item:last-child { padding-bottom: 0; }

.timeline__marker {
  position: relative;
  z-index: 1;            /* deckt die Linie ab, statt von ihr durchkreuzt zu werden */
  display: grid;
  place-items: center;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--ink-800);
  border: 1px solid var(--line);
  /* Zeichenfarbe des Icons – wandert beim Einschalten auf --glow mit, wie
     Rand und Schein. Systememoji standen hier vorher: die rendern auf
     jeder Plattform anders und tragen ihre eigene Farbigkeit mit, an der
     die Dimmkurve der Seite abprallt.                                  */
  color: var(--faint);
  scale: 0.7;
  opacity: 0;
  transition: scale 0.45s var(--ease), opacity 0.3s var(--ease),
              border-color 0.45s var(--ease), box-shadow 0.45s var(--ease),
              background-color 0.45s var(--ease), color 0.45s var(--ease);
}
.timeline__marker svg {
  width: 20px;
  height: 20px;
  overflow: visible;   /* Strichenden dürfen an der viewBox anstehen */
}

.timeline__year {
  grid-column: 2;
  display: block;
  padding-top: 0.3rem;   /* setzt die Jahreszahl optisch auf die Marker-Mitte */
  font-family: var(--display);
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--faint);
  transition: color 0.45s var(--ease);
}

.timeline__body { grid-column: 2; opacity: 0; translate: 0 10px; transition: opacity 0.5s var(--ease), translate 0.5s var(--ease); }
.timeline__body h4 { font-size: 1.0625rem; margin: 0.35rem 0 0; }
.timeline__body p { margin: 0.35rem 0 0; color: var(--muted); font-size: 0.9375rem; max-width: 52ch; }

/* erreichter Punkt */
.timeline__item.is-lit .timeline__marker {
  scale: 1;
  opacity: 1;
  background: var(--ink-700);
  border-color: var(--glow);
  color: var(--glow);
  box-shadow: 0 0 0 4px rgb(242 196 107 / 0.09), 0 0 22px rgb(242 196 107 / 0.28);
}
.timeline__item.is-lit .timeline__year { color: var(--glow); }
.timeline__item.is-lit .timeline__body { opacity: 1; translate: 0 0; transition-delay: 0.12s; }

/* letzter Eintrag „Heute“ trägt das Markenrot */
.timeline__item:last-child.is-lit .timeline__marker {
  border-color: var(--red);
  color: var(--red);
  box-shadow: 0 0 0 4px rgb(224 78 54 / 0.12), 0 0 22px rgb(224 78 54 / 0.3);
}
.timeline__item:last-child.is-lit .timeline__year { color: var(--red); }

.timeline-head { margin-top: clamp(3.5rem, 7vw, 6rem); }
.timeline-head h3 { font-size: clamp(1.5rem, 2.6vw, 2rem); margin-top: 0.75rem; }

@media (min-width: 760px) {
  .timeline { --rail-x: calc(6.5rem + 1.5rem + var(--dot) / 2); }

  .timeline__item {
    grid-template-columns: 6.5rem var(--dot) 1fr;
    column-gap: 1.5rem;
  }
  .timeline__marker { grid-column: 2; grid-row: 1; }
  .timeline__year { grid-column: 1; grid-row: 1; text-align: right; }
  .timeline__body { grid-column: 3; grid-row: 1; padding-top: 0.4rem; }
  .timeline__body h4 { margin-top: 0; }
}

/* ohne JS bzw. bei reduzierter Bewegung ist der Strahl komplett sichtbar */
.no-js .timeline__marker,
.no-js .timeline__body { scale: 1; opacity: 1; translate: none; }
.no-js .timeline__rail::after { scale: 1 1; }
.no-js .timeline__rail i { display: none; }
.no-js .timeline__year { color: var(--glow); }

/* ----------------------------------------------------------- Kontakt */

.contact { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(2.5rem, 6vw, 5rem); align-items: start; }

.info-block + .info-block { margin-top: 2.25rem; padding-top: 2.25rem; border-top: 1px solid var(--line-soft); }
.info-block h3 {
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 0.875rem;
}
.info-block p, .info-block a { font-size: 1rem; color: var(--text); }
.info-block a { text-decoration: none; border-bottom: 1px solid var(--line); transition: border-color 0.2s var(--ease), color 0.2s var(--ease); }
.info-block a:hover { color: var(--glow); border-color: var(--glow); }

.hours { display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 1.5rem; font-size: 0.9375rem; }
.hours dt { color: var(--muted); }
.hours dd { margin: 0; }
.hours .closed { color: var(--faint); }

/* Formular */

.form { display: grid; gap: 1.125rem; }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.125rem; }

.field { display: grid; gap: 0.45rem; }
.field label { font-size: 0.8125rem; font-weight: 500; letter-spacing: 0.03em; color: var(--muted); }
.field label .req { color: var(--red); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.8rem 0.95rem;
  font-family: var(--body);
  font-size: 0.9375rem;
  color: var(--text);
  background: var(--ink-850);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease),
              box-shadow 0.25s var(--ease);
}
/* Safari auf iPhone/iPad zoomt beim Fokussieren jedes Feldes unter 16px
   automatisch hinein und lässt den Nutzer im verschobenen Layout zurück. */
@media (pointer: coarse) {
  .field input,
  .field select,
  .field textarea { font-size: 1rem; }
}

.field textarea { resize: vertical; min-height: 132px; line-height: 1.6; }
.field select { appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2393a6ab' stroke-width='1.5'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 12px;
  padding-right: 2.5rem;
}
.field select option { background: var(--ink-800); color: var(--text); }

.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--slate); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--glow);
  background: var(--ink-800);
  /* das fokussierte Feld liegt im Licht */
  box-shadow: 0 0 0 3px rgb(242 196 107 / 0.1);
}
.field:focus-within label { color: var(--glow); }
.field label { transition: color 0.2s var(--ease); }
.field input::placeholder, .field textarea::placeholder { color: var(--faint); }

.form__note { font-size: 0.8125rem; color: var(--faint); margin: 0; }
.form__note a { color: var(--muted); }

.form__status {
  padding: 0.9rem 1.1rem;
  font-size: 0.9375rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--ink-850);
  animation: statusIn 0.45s var(--ease);
}
.form__status[hidden] { display: none; }
@keyframes statusIn {
  from { opacity: 0; translate: 0 -8px; }
  to   { opacity: 1; translate: 0 0; }
}

/* --------------------------------------------------------------- Footer */

/* Der Footer trägt denselben Bandton. Auf den Rechtsseiten stößt er direkt
   auf die Grundfläche, deshalb läuft er oben genauso weich ein wie ein
   Abschnitt; folgt er dagegen auf einen Bandabschnitt (Startseite), sind
   beide eine Fläche und der Verlauf entfällt. */
.footer {
  --fade-top: clamp(2.5rem, 6vw, 5rem);
  padding-block: clamp(3.5rem, 7vw, 5rem) 2rem;
  background-color: var(--ink-band);
  background-image: linear-gradient(
    to bottom,
    var(--ink-900) 0,
    color-mix(in oklab, var(--ink-band) 16%, var(--ink-900)) calc(var(--fade-top) * 0.25),
    color-mix(in oklab, var(--ink-band) 50%, var(--ink-900)) calc(var(--fade-top) * 0.5),
    color-mix(in oklab, var(--ink-band) 84%, var(--ink-900)) calc(var(--fade-top) * 0.75),
    var(--ink-band) var(--fade-top)
  );
  background-repeat: no-repeat;
  font-size: 0.9375rem;
}
main:has(> .section--alt:last-child) + .footer { background-image: none; }

.footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
}
.footer__grid img { width: 156px; margin-bottom: 1.25rem; }
.footer__grid p { color: var(--muted); max-width: 38ch; font-size: 0.9375rem; }

.footer h4 {
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 1.1rem;
}
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.footer a { color: var(--muted); text-decoration: none; transition: color 0.2s var(--ease); }
.footer a:hover { color: var(--glow); }

/* Unterstrich läuft von links ein – dasselbe Prinzip wie in der Navigation */
.footer ul a { position: relative; display: inline-block; }
.footer ul a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  scale: 0 1;
  transition: scale 0.3s var(--ease);
}
.footer ul a:hover::after { scale: 1 1; }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.8125rem;
  color: var(--faint);
}
.footer__bottom p { margin: 0; }

/* --------------------------------------------------------- Rechtsseiten */

.page-head {
  padding-top: calc(var(--header-h) + clamp(3.5rem, 8vw, 6.5rem));
  padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
  border-bottom: 1px solid var(--line-soft);
}
.page-head h1 { font-size: clamp(2.25rem, 5.5vw, 3.75rem); }

.prose { max-width: 78ch; padding-block: clamp(3rem, 6vw, 4.5rem); }
.prose h2 {
  font-size: clamp(1.375rem, 2.6vw, 1.75rem);
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--line-soft);
}
.prose > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.prose h3 { font-size: 1.125rem; margin-top: 2.25rem; color: var(--text); }
.prose p, .prose li { color: var(--muted); }
.prose p { margin-top: 1rem; }
.prose ul, .prose ol { padding-left: 1.25rem; margin-top: 1rem; }
.prose li { margin-bottom: 0.5rem; }
.prose a { color: var(--glow); text-decoration: underline; text-underline-offset: 3px; }
.prose strong { color: var(--text); font-weight: 600; }
.prose address { font-style: normal; color: var(--muted); margin-top: 1rem; }

/* Nummerierte AGB-Abschnitte – die Ziffernfolge des Originals bleibt erhalten */
.prose ol.agb { counter-reset: none; list-style: none; padding-left: 0; margin-top: 2.5rem; }
.prose ol.agb > li {
  position: relative;
  padding: 1.75rem 0 0 3.25rem;
  margin: 0;
  border-top: 1px solid var(--line-soft);
}
.prose ol.agb > li::before {
  content: counter(list-item) ".";
  position: absolute;
  left: 0;
  top: 1.75rem;
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--glow);
}
.prose ol.agb > li > p:first-of-type { margin-top: 0; }

/* ------------------------------------------------------------- Animation */

/* Nur bei aktivem JavaScript ausblenden – ohne JS bliebe der Inhalt sonst unsichtbar */
.js .reveal {
  opacity: 0;
  translate: 0 22px;
  transition: opacity 0.7s var(--ease), translate 0.7s var(--ease),
              scale 0.8s var(--ease);
}
.js .reveal.is-in { opacity: 1; translate: 0 0; scale: 1; }

/* Richtungsvarianten – die beiden Spaltenlayouts kommen von ihrer Seite
   herein, statt beide von unten.                                        */
.js .reveal--left  { translate: -26px 0; }
.js .reveal--right { translate:  26px 0; }
/* Bilder wachsen leicht auf, statt zu wandern */
.js .reveal--zoom  { translate: 0 14px; scale: 0.97; }

/* --- Staffelung -----------------------------------------------------
   Der Container selbst bleibt stehen, seine Kinder laufen nacheinander
   ein. --i vergibt main.js (bei 12 gedeckelt, damit lange Listen nicht
   ewig brauchen).

   Bewusst als animation und nicht als transition: die Kurzschrift
   `transition` würde die eigenen Übergänge der Kinder ersetzen – die
   Filter-Pills, die Leistungsfelder und die Kacheln verlören damit ihr
   weiches Hover-Verhalten an eine Regel, die nur das Einblenden meint.
   `backwards` hält den Startzustand während der Verzögerung.           */
.js .reveal[data-stagger] { opacity: 1; translate: none; }
.js .reveal[data-stagger] > * { opacity: 0; }
.js .reveal[data-stagger].is-in > * {
  opacity: 1;
  animation: revealUp 0.7s var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes revealUp {
  from { opacity: 0; translate: 0 18px; }
  to   { opacity: 1; translate: 0 0; }
}

/* Das Leistungsraster läuft nicht über dieses System: es blendet nicht
   ein, es geht an – siehe „Die Lichtkette" weiter oben.                */

/* Der Strich vor der Rubrik zieht sich beim Einblenden auf – ein kurzer
   Lichtstrahl, der die Überschrift ankündigt.                          */
.js .reveal .eyebrow::before { width: 0; transition: width 0.55s var(--ease) 0.2s; }
.js .reveal.is-in .eyebrow::before { width: 28px; }

/* ------------------------------------------------------------ Responsive */

/* Dieselbe Komposition auf drei Spalten: 1+2 / 1+1+1 / 3. Erst darunter
   wird das große Feld zu schmal, um Text und Grafik nebeneinander zu
   tragen.                                                              */
@media (max-width: 1080px) {
  .services { grid-template-columns: repeat(3, 1fr); }
  .service { grid-column: span 1; }
  .service--feature { grid-column: span 2; }
  .service--wide { grid-column: span 3; }
}

@media (max-width: 1000px) {
  .pullquote, .about, .contact { grid-template-columns: 1fr; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__grid > :first-child { grid-column: 1 / -1; }
}

@media (max-width: 860px) {
  :root { --header-h: 66px; }

  .burger { display: block; }
  .header-tel, .header .btn { display: none; }

  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto;
    margin: 0;
    background: rgb(12 18 20 / 0.98);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--line-soft);
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.4s var(--ease);
  }
  .nav.is-open { max-height: calc(100svh - var(--header-h)); overflow-y: auto; }

  .nav ul { flex-direction: column; align-items: stretch; gap: 0; padding: 0.5rem var(--gutter) 1.75rem; }

  /* die Einträge laufen nacheinander ein, während das Menü aufklappt –
     --i setzt main.js auf jeder Seite                                   */
  .nav li {
    border-bottom: 1px solid var(--line-soft);
    opacity: 0;
    translate: 0 -10px;
    transition: opacity 0.25s var(--ease), translate 0.25s var(--ease);
  }
  .nav.is-open li {
    opacity: 1;
    translate: 0 0;
    transition-delay: calc(var(--i, 0) * 45ms + 80ms);
  }
  .nav li:last-child { border-bottom: 0; }
  .nav a { display: block; padding: 1.05rem 0; font-size: 1rem; }
  .nav a::after { display: none; }
  .nav .nav__cta { display: block; margin-top: 1.25rem; border-bottom: 0; }
  /* display muss mitgesetzt werden: `.header .btn { display:none }` ein paar
     Zeilen weiter oben blendet auch diesen Button aus – der CTA am Ende des
     Menüs blieb dadurch unsichtbar.                                         */
  .nav .nav__cta .btn { display: flex; width: 100%; }

  .header.is-nav-open { background: rgb(12 18 20 / 0.98); backdrop-filter: blur(14px); }

  .tile--wide, .tile--big { grid-column: span 2; }
  .form__row { grid-template-columns: 1fr; }
}

/* Zwei Spalten, alle sechs gleich groß: eine hervorgehobene Zelle ließe
   hier eine Lücke, weil fünf einfache und eine doppelte Zelle in einem
   zweispaltigen Raster nicht aufgehen. Die Grafiken rücken unter ihren
   Text.                                                                */
@media (max-width: 780px) {
  .services { grid-template-columns: repeat(2, 1fr); }
  .service, .service--feature, .service--wide { grid-column: span 1; }
  .service--feature, .service--wide {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 1.5rem;
  }
  .service__figure { max-width: 300px; }
}

@media (max-width: 620px) {
  .services { grid-template-columns: 1fr; }
  .services > * { grid-column: 1 / -1; }

  /* feste Zweispaltigkeit: sonst würde auto-fill auf eine Spalte fallen und
     die span-2-Kacheln hätten eine implizite zweite Spalte erzeugt */
  .gallery {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: clamp(112px, 30vw, 168px);
    gap: 0.625rem;
  }
  .tile figcaption { padding: 1.75rem 0.75rem 0.7rem; font-size: 0.75rem; opacity: 1; translate: 0 0; }
  .tile figcaption span { font-size: 0.625rem; }
}

@media (max-width: 560px) {
  .hero { min-height: 88svh; }
  .hero__facts { gap: 1.5rem 2rem; }
  .hero__facts > div { flex: 1 1 40%; }
  .hero__cta { display: grid; gap: 0.75rem; }
  .hero__cta .btn { width: 100%; }
  .gallery { gap: 0.625rem; }
  .lightbox__btn { width: 42px; height: 42px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    animation-delay: 0ms !important;
  }
  /* alles, was sonst erst durch eine Bewegung sichtbar wird, steht hier
     von Anfang an da – inklusive der gestaffelten Kinder und der
     Menüeinträge, die ihre Sichtbarkeit sonst aus der Staffelung ziehen */
  /* .js mitschreiben: ohne das Präfix bliebe die Regel unter der des
     Reveal-Systems und würde nichts sichtbar machen                     */
  .js .reveal,
  .js .reveal[data-stagger] > *,
  .nav li { opacity: 1; translate: none; scale: none; }
  .js .reveal .eyebrow::before { width: 28px; }
  .header__beam { display: none; }
}

@media print {
  .header, .footer, .li-layer, .filters, .lightbox { display: none !important; }
  body { background: #fff; color: #000; }
  .prose p, .prose li { color: #333; }
}
