/* ============================================================
   EPIC VISION — Luxury Editorial
   Palette: Nachtblau / Elfenbein / Walchensee-Türkis
   ============================================================ */

:root {
  --night:    #0a0d12;
  --night-2:  #0e131b;
  --ivory:    #ece7dc;
  --ivory-bg: #f4f1ea;
  --ink:      #16181d;
  --muted:    #8d8878;
  --muted-d:  #6f7480;
  --gold:     #8a7317;   /* Logo-Gold */
  --accent:   #b8951f;   /* etwas heller — trägt auf hellem wie dunklem Grund */
  --line-l:   rgba(22, 24, 29, .14);
  --line-d:   rgba(236, 231, 220, .14);
  /* Eine Schrift fuer die ganze Seite: Jost — die Schrift des Statement-Bandes
     ("Starten Sie Ihre Zukunft jetzt mit uns!"). --serif/--hand bleiben als
     Aliasse bestehen, damit die bestehenden Regeln unveraendert greifen. */
  --sans:  'Jost', 'Segoe UI', sans-serif;
  --serif: var(--sans);
  --hand:  var(--sans);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scrollbar-gutter: stable; }
/* Solange der Schriftzug fliegt, bleibt die Seite stehen.
   Der Platz der Scrollleiste bleibt dabei reserviert (scrollbar-gutter),
   sonst springt das Layout um deren Breite, sobald die Sperre fällt. */
html.is-loading, html.is-loading body { overflow: hidden; height: 100%; }
body {
  margin: 0;
  font-family: var(--sans);
  font-weight: 300;
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--night);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

.wrap      { max-width: 860px;  margin: 0 auto; padding: 0 24px; }
.wrap-wide { max-width: 1280px; margin: 0 auto; padding: 0 24px; }

/* ---------- Funke ----------
   Beim Eintritt eines Abschnitts läuft ein feiner Lichtpunkt einmal an der
   Oberkante entlang; die Richtung wechselt von Abschnitt zu Abschnitt (.spark-rev). */
.spark { position: relative; overflow: hidden; }
.spark::after {
  content: "";
  position: absolute; top: 0; left: 0;
  width: 140px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  box-shadow: 0 0 8px rgba(184,149,31,.55);
  opacity: 0; pointer-events: none; z-index: 3;
  transform: translateX(-15vw);
}
/* läuft wiederholt, solange der Abschnitt im Bild ist: 2,6 s Flug, dann Pause */
.spark.spark-on::after       { animation: sparkRun 7s cubic-bezier(.35,0,.15,1) .3s infinite; }
.spark.spark-rev.spark-on::after { animation-name: sparkRunRev; }

@keyframes sparkRun {
  0%   { opacity: 0;   transform: translateX(-15vw); }
  5%   { opacity: .85; }
  30%  { opacity: .6; }
  37%  { opacity: 0;   transform: translateX(105vw); }
  100% { opacity: 0;   transform: translateX(-15vw); }   /* Pause bis zum nächsten Funken */
}
@keyframes sparkRunRev {
  0%   { opacity: 0;   transform: translateX(105vw); }
  5%   { opacity: .85; }
  30%  { opacity: .6; }
  37%  { opacity: 0;   transform: translateX(-15vw); }
  100% { opacity: 0;   transform: translateX(105vw); }
}
@media (prefers-reduced-motion: reduce) { .spark::after { display: none; } }

/* ---------- Kinetische Typografie ----------
   Überschriften kommen wortweise herein, leicht versetzt und minimal gekippt.
   Ohne JS bleibt der Satz einfach stehen (die Wörter werden erst per JS gewrappt). */
.kin .w {
  display: inline-block;
  opacity: 0; transform: translateY(22px) rotate(1.2deg);
  transition: opacity .8s cubic-bezier(.16,1,.3,1), transform .8s cubic-bezier(.16,1,.3,1);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.kin.is-in .w { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .kin .w { opacity: 1; transform: none; transition: none; }
}

/* ---------- Zeiger-Feinheiten (nur mit echter Maus) ----------
   Karten kippen leicht zum Cursor, Buttons folgen ihm ein Stück ("magnetisch"). */
/* Die Leistungs-Karten kippten und hoben sich frueher zum Cursor. Das ist mit dem
   Video-Fenster nicht mehr vereinbar: die Maske ist ein Rechteck im Seiten-Layout,
   sie kann einer perspektivisch gekippten Karte nicht folgen — die Karte wuerde aus
   ihrem eigenen Fenster wandern. Ein Fenster hebt sich nicht aus der Wand; das
   Hover-Echo tragen jetzt Goldrand, Gold-Nummer und die einfahrende Liste. */
@media (hover: hover) {
  /* Nur die Kontakt-Buttons — der Hero-Button hat eine eigene Einblend-Animation */
  .btn-solid, .btn-line {
    transform: translate(var(--mx, 0px), var(--my, 0px));
  }
}

/* ---------- Reveal on scroll ---------- */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .9s ease, transform .9s cubic-bezier(.16,1,.3,1); }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* ---------- Loader ----------
   Der Schriftzug im Loader ist derselbe wie im Hero (gleiche Klasse, gleiche Größe).
   Beim Start wird er per FLIP auf die Position des Hero-Titels geschoben; erst wenn er
   deckungsgleich sitzt, übernimmt der echte Titel — so ist kein Sprung sichtbar. */
.loader {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.loader.is-done { visibility: hidden; }
/* Der Vorhang oeffnet, sobald das Logo seine Endgroesse erreicht hat (main.js gibt
   mit is-open das Kommando bei 880 ms). Bogen, Landung und Vorhang laufen bewusst
   INEINANDER statt nacheinander — nacheinander abgehakt fuehlte sich zaeh an, obwohl
   jeder Schritt fuer sich gut aussah. */
.loader-veil {
  position: absolute; inset: 0;
  background: var(--night);
  transition: opacity .42s ease;
}
.loader.is-open .loader-veil { opacity: 0; }

/* Das Logo startet klein, wächst in einem Zug auf Hero-Größe und gleitet dabei
   an seine Position — eine einzige durchgehende Bewegung, kein zweiter Ansatz.

   ACHTUNG bei der Kurve — hier steckt die ganze Geschichte drin:
   Frueher lief 4,2s cubic-bezier(.16,1,.3,1) (Apple-Scroll-Kurve). Deren Auslauf ist
   so flach, dass das Logo nach 1,8 s optisch stand und danach 2,4 s unsichtbar
   weiterkroch — es sah aus, als haenge die Seite. Die Lehre ist NICHT "kurz = gut",
   sondern: die Bewegung muss bis zuletzt SICHTBAR bleiben. Ein easeOut wird mit
   laengerer Dauer zwangslaeufig zaeh, weil sein Ende flach ist.
   Deshalb jetzt eine Dolly-Kurve (Kamerafahrt auf Schienen, Basti-Wunsch "wie bei
   Movies"): sanft an, gleichmaessig durch, weich aus. Gemessen bei 1,4 s Flug
   (Schwelle 1,2 px Zuwachs je 50 ms bei 520 px Logo-Breite):
     easeOutQuart (.25,1,.5,1)   steht ab 1000 ms  -> 400 ms tot
     easeOutCubic (.33,1,.68,1)  steht ab 1150 ms  -> 250 ms tot
     Dolly        (.5,.05,.25,1) steht ab 1300 ms  -> 100 ms tot   << gewaehlt
   Sie ist also langsamer UND hat weniger Stillstand. Wer nicht warten will, kommt
   weiterhin mit dem ersten Scrollen, Tippen oder Tastendruck sofort durch (skip()).
   ACHTUNG: Diese Dauer und die Timer in main.js gehoeren zusammen — wird nur eine
   Seite geaendert, uebernimmt der Hero-Titel mitten im Flug und das Logo springt. */
.loader-figure {
  position: relative;
  isolation: isolate;              /* der Bogen blendet mit dem Logo, nicht mit dem Vorhang */
  width: min(62vw, 520px);
  transform-origin: center center;
  will-change: transform, opacity;

  opacity: 0;
  transform: translateY(0) scale(.42);
  transition:
    opacity .5s ease,
    transform 1.4s cubic-bezier(.5,.05,.25,1);
}
.loader.is-flying .loader-figure {
  opacity: 1;
  transform: translate(var(--dx, 0px), var(--dy, 0px)) scale(var(--sc, 1));
}
.loader.is-landed .loader-figure { opacity: 0; transition: opacity .25s ease; }
.loader .loader-mark { width: 100%; height: auto; }

/* Lichtbogen ueber dem goldenen VISION. Das Logo ist ein PNG, kein Text — der
   background-clip-Trick der Ueberschriften greift hier nicht. Der Streifen laeuft
   deshalb ueber eine Ebene, die per Maske auf die golden eingefaerbten Pixel des
   Logos beschnitten ist (vision-mask.webp, erzeugt von build-vision-mask.py).
   Das weisse EPIC bleibt dadurch unberuehrt. Laeuft WAEHREND des Flugs (550–1300 ms) und
   ist ABGESCHLOSSEN, wenn das Logo seine Endgroesse hat (Basti-Wunsch) — erst danach
   kommt das Video. Ein Light-Sweep soll das Logo einmal ueberstreichen und es dann in
   die Ruhe entlassen, nicht ueber dem stehenden Logo weiterlaufen. */
.loader-shine {
  position: absolute; inset: 0;
  pointer-events: none;
  background-image: linear-gradient(100deg,
    transparent 40%, rgba(255, 246, 220, .28) 46%, rgba(255, 252, 240, .95) 50%,
    rgba(255, 246, 220, .28) 54%, transparent 60%);
  background-size: 300% 100%;
  background-position: 0% 50%;
  background-repeat: no-repeat;
  -webkit-mask-image: url('../assets/brand/vision-mask.webp?v=1');
          mask-image: url('../assets/brand/vision-mask.webp?v=1');
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  mix-blend-mode: screen;
  opacity: 0;
}
.loader.is-shining .loader-shine {
  animation: ev-vision-shine .75s cubic-bezier(.36, 0, .18, 1) both;
}
/* Der Streifen wandert von links nach rechts durch das Wort und blendet an beiden
   Enden weg, damit er nicht am Rand stehenbleibt. */
@keyframes ev-vision-shine {
  0%   { opacity: 0; background-position: 0% 50%; }
  10%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { opacity: 0; background-position: 100% 50%; }
}
.loader.is-done { visibility: hidden; }

/* Das Hero-Logo wartet, bis der Loader es übergibt; der Rest fliegt danach nach.
   Der Titel schaltet OHNE Transition hart auf sichtbar: er liegt zu dem Zeitpunkt noch
   komplett unter dem deckenden Loader-Abdruck, der Sprung ist also unsichtbar — und
   das Ueberblenden beider deckungsgleicher Bilder wuerde sonst kurz auf ~75 % Deckung
   absacken und das Video durchs Logo blitzen lassen (der Vorhang ist jetzt schon auf). */
.hero-title { opacity: 0; }
body.is-ready .hero-title { opacity: 1; transition: none; }
.hero-eyebrow, .hero-sub, .btn-ghost { animation-play-state: paused; }
body.is-ready .hero-eyebrow,
body.is-ready .hero-sub,
body.is-ready .btn-ghost { animation-play-state: running; }
@media (prefers-reduced-motion: reduce) {
  .hero-title { opacity: 1; }
  .loader { display: none; }
  .loader-shine { display: none; }
}

/* ---------- Navigation ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  padding: 22px 0;
  transition: background .4s ease, padding .4s ease, box-shadow .4s ease;
}
.nav.is-scrolled {
  background: rgba(10, 13, 18, .88);
  backdrop-filter: blur(12px);
  padding: 12px 0;
  box-shadow: 0 1px 0 var(--line-d);
}
.nav-inner {
  max-width: 1280px; margin: 0 auto; padding: 0 24px;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
}
.nav-mark { display: block; line-height: 0; }
.nav-mark img {
  height: 26px; width: auto;
  transition: opacity .3s, transform .3s;
}
.nav.is-scrolled .nav-mark img { height: 22px; }
.nav-mark:hover img { opacity: .82; transform: scale(1.03); }
.nav-links { list-style: none; margin: 0; padding: 0; display: flex; gap: 34px; }
.nav-links-left  { justify-content: flex-end;  padding-right: 48px; }
.nav-links-right { justify-content: flex-start; padding-left: 48px; }
.nav-links a {
  color: var(--ivory); font-size: 12px; font-weight: 400;
  letter-spacing: .22em; text-transform: uppercase;
  position: relative; padding: 4px 0;
}
.nav-links a::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px; background: var(--accent);
  transform: scaleX(0); transform-origin: right;
  transition: transform .35s cubic-bezier(.16,1,.3,1);
}
.nav-links a:hover::after { transform: scaleX(1); transform-origin: left; }
.nav-burger { display: none; }

/* Mobile menu */
.mobilemenu {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(10, 13, 18, .97);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden;
  transition: opacity .4s ease, visibility .4s ease;
}
.mobilemenu.is-open { opacity: 1; visibility: visible; }
.mobilemenu ul { list-style: none; margin: 0; padding: 0; text-align: center; }
.mobilemenu a {
  display: block; padding: 14px;
  font-family: var(--serif); font-size: 32px; color: var(--ivory);
  letter-spacing: .12em;
}
.mobilemenu a:hover { color: var(--accent); }

@media (max-width: 860px) {
  .nav-links { display: none; }
  .nav-inner { grid-template-columns: auto 1fr; gap: 16px; }
  .nav-mark { justify-self: center; grid-column: 2; margin-right: 40px; }
  .nav-burger {
    display: flex; flex-direction: column; gap: 6px;
    background: none; border: 0; padding: 8px; cursor: pointer; z-index: 95;
  }
  .nav-burger span { width: 26px; height: 1.5px; background: var(--ivory); transition: transform .3s, opacity .3s; }
  .nav-burger[aria-expanded="true"] span:first-child { transform: translateY(4px) rotate(45deg); }
  .nav-burger[aria-expanded="true"] span:last-child  { transform: translateY(-3.5px) rotate(-45deg); }
}

/* ---------- Hero ---------- */
.hero {
  position: relative; height: 100vh; height: 100svh;
  min-height: 560px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
/* Drohnen-Loop als Hintergrund; solange er lädt (oder gar nicht geladen wird),
   steht das Poster als Standbild. */
.hero-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  background: #0a0d12 url('../assets/video/hero-poster.jpg?v=2') center/cover no-repeat;
}
.hero-shade {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(10,13,18,.55) 0%, rgba(10,13,18,.15) 35%, rgba(10,13,18,.2) 65%, var(--night) 100%);
}
.hero-content { position: relative; text-align: center; padding: 0 24px; color: var(--ivory); }
.hero-eyebrow {
  font-size: 12px; font-weight: 400; letter-spacing: .34em; text-transform: uppercase;
  color: rgba(236,231,220,.85); margin: 0 0 18px;
  animation: fadeUp 1.2s .5s cubic-bezier(.16,1,.3,1) both;
}
/* Hero-Logo — Auftritt übernimmt der Loader (FLIP) */
.hero-title {
  margin: 0 auto;
  width: min(62vw, 520px);
  transition: opacity .25s ease;
}
.hero-title img { width: 100%; height: auto; }

@media (max-width: 700px) {
  .hero-title { width: min(78vw, 420px); }
}
.hero-sub {
  font-size: clamp(15px, 2vw, 19px); font-weight: 300; letter-spacing: .1em;
  margin: 22px 0 34px; color: rgba(236,231,220,.9);
  animation: fadeUp 1.2s .9s cubic-bezier(.16,1,.3,1) both;
}
.btn-ghost {
  display: inline-block; padding: 14px 44px;
  border: 1px solid rgba(236,231,220,.55); color: var(--ivory);
  font-size: 12px; letter-spacing: .28em; text-transform: uppercase; text-indent: .28em;
  transition: background .35s, color .35s, border-color .35s;
  animation: fadeUp 1.2s 1.1s cubic-bezier(.16,1,.3,1) both;
}
.btn-ghost:hover { background: var(--ivory); color: var(--night); border-color: var(--ivory); }
@keyframes fadeUp { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

.hero-scroll {
  position: absolute; bottom: 34px; left: 50%; transform: translateX(-50%);
  width: 1px; height: 64px; overflow: hidden;
}
.hero-scroll span {
  position: absolute; top: -50%; left: 0; width: 1px; height: 50%;
  background: linear-gradient(180deg, transparent, var(--ivory));
  animation: scrollcue 2.2s ease-in-out infinite;
}
@keyframes scrollcue { to { top: 100%; } }
/* Auf dem Desktop entfaellt der Scroll-Hinweis (Basti-Wunsch) — am Handy bleibt er,
   dort ist der Hinweis auf weiteren Inhalt unter der Falz noch nuetzlich. */
@media (min-width: 861px) {
  .hero-scroll { display: none; }
}

/* ---------- Morph-Zone (Agentur + Leistungen) ----------
   Wie auf der GT3-Seite: der Hintergrund wird beim Scrollen pro Frame
   zwischen Elfenbein und Nachtblau interpoliert, die Schriftfarben laufen
   über Tokens mit. Ohne JS bleiben die Ausgangsfarben stehen. */
.morph {
  position: relative; isolation: isolate;
  --m-fg:      var(--ink);          /* Überschriften */
  --m-body:    #4c4a42;             /* Fließtext */
  /* Eyebrow: --muted (#8d8878) hielt ueber dem Bergfoto nur 2,4:1 und selbst auf
     reinem Elfenbein nur 3,1:1 — unter WCAG AA. Dieser Ton haelt 4,8:1. */
  --m-kicker:  #33312b;             /* Eyebrow */
  --m-card:    #ffffff;             /* Leistungs-Karten */
  --m-card-bd: var(--line-l);
}
.morph.is-dark {
  --m-fg:      var(--ivory);
  --m-body:    rgba(236,231,220,.62);
  --m-kicker:  rgba(236,231,220,.75);
  --m-card:    var(--night-2);
  --m-card-bd: var(--line-d);
}
.morph-bg {
  position: absolute; inset: 0; z-index: 0;
  background: var(--ivory-bg);
}
.morph > section { position: relative; z-index: 1; background: transparent; }

/* Farben dieser beiden Sektionen kommen aus den Tokens und faden weich mit */
.morph .eyebrow                        { color: var(--m-kicker); transition: color .5s ease; }
.morph .statement,
.morph .section-title,
.morph .card-name                      { color: var(--m-fg);     transition: color .5s ease; }
.morph .manifest-copy,
.morph .card p                         { color: var(--m-body);   transition: color .5s ease; }
.morph .card {
  background: var(--m-card);
  border-color: var(--m-card-bd);
  transition: background .5s ease, border-color .5s ease,
              transform .5s cubic-bezier(.16,1,.3,1), box-shadow .5s;
}
.morph .card-no  { color: var(--m-fg); transition: color .5s ease; }
/* Die Leistungs-Blende ist deckend — sie muss denselben Ton halten wie die Karte,
   sonst steht im hellen Abschnitt ein nachtblauer Block in der weissen Kachel. */
.morph .card-panel {
  background: var(--m-card);
  transition: background .5s ease, border-color .5s ease, transform .55s cubic-bezier(.16,1,.3,1);
}
.morph .card-panel li     { color: var(--m-body);    transition: color .5s ease; }
/* Nur die Trennstriche zwischen den Punkten laufen mit — die goldene Oberkante
   der Blende bleibt gold und darf hier nicht mitgefaerbt werden. */
.morph .card-panel li + li { border-top-color: var(--m-card-bd); }

/* ---------- Manifest (hell) ----------
   Der Innenabstand ist bewusst groesser als die Verlaufszonen des Schleiers
   (oben 190px, unten 200px) — nur so bleibt der Text ausserhalb des Bereichs,
   in dem der Grund von dunkel nach hell wandert. */
.manifest { padding: 230px 0 240px; }
/* Bergfoto als Grund der Agentur-Sektion. Darueber liegt ein Schleier in genau der
   Farbe, die der Morph gerade haelt (--morph-rgb, von main.js gesetzt) — so bleibt
   der Uebergang Hero → hell → dunkel erhalten, das Foto wandert mit.
   Die Deckkraft von .82 ist nicht geraten: bei diesem Foto haelt der Fliesstext
   (#4c4a42) damit 5,5:1 und das Label (#575344) 4,8:1 — beides ueber WCAG AA (4,5:1). */
.manifest-bg {
  position: absolute; inset: 0; z-index: 0;
  background-image: url('../assets/img/agentur-berg3.webp');
  background-size: cover;
  background-position: center 30%;
}
/* Der Schleier hat drei Zonen:
   oben   — deckendes Nachtblau, das den Hero fortsetzt und nach unten aufklart;
   Mitte  — konstanter Elfenbein-Schleier (.82), auf dem der Text steht;
   unten  — laeuft in die aktuelle Morph-Farbe aus, sodass die Naht zu den Leistungen
            verschwindet, egal ob der Grund dort gerade hell oder dunkel ist.
   Der Hell-Dunkel-Wechsel passiert damit ausschliesslich in den textfreien Randzonen
   (oben 120px, unten 110px Innenabstand) — der Text sitzt nie auf halbem Grau. */
.manifest-bg::after {
  content: "";
  position: absolute; inset: 0;
  background:
    /* 1. Naehte: oben aus dem Hero-Dunkel heraus, unten in die Morph-Farbe hinein */
    linear-gradient(to bottom,
      rgb(10, 13, 18) 0,
      rgba(10, 13, 18, 0) 190px,
      rgba(var(--morph-rgb, 244, 241, 234), 0) calc(100% - 200px),
      rgba(var(--morph-rgb, 244, 241, 234), 1) 100%),
    /* 2. Schleier nur dort, wo Text steht: in der Textspalte .55, an den Raendern .28.
       Die Stops haengen an der halben Textbreite (.wrap = 860px) plus Puffer, NICHT an
       Prozenten — sonst wandert die dichte Zone auf breiten Schirmen unter dem Text weg.
       Der dunkelste Punkt des Fotos haelt so unter dem Fliesstext (#1c1a16) ueber 5:1,
       waehrend das Foto aussen fast unverdeckt steht. */
    linear-gradient(90deg,
      rgba(244, 241, 234, .28) 0,
      rgba(244, 241, 234, .55) calc(50% - 480px),
      rgba(244, 241, 234, .55) calc(50% + 480px),
      rgba(244, 241, 234, .28) 100%);
}
.manifest > .wrap { position: relative; z-index: 1; }
/* Der Agentur-Text bleibt dunkel — er liegt immer auf dem hellen Teil des Schleiers
   und darf deshalb NICHT mit dem Morph nach Hell umschlagen. */
.morph .manifest .eyebrow      { color: #33312b; }
.morph .manifest .statement    { color: var(--ink); }
/* Fast schwarz statt mittelgrau: das war der Hebel, mit dem der Schleier ueber dem
   Bergfoto von 82 % auf 55 % sinken konnte — das Foto ist dadurch doppelt so praesent,
   der Kontrast trotzdem hoeher als vorher (5,5:1 statt 5,5:1 bei viel mehr Bild). */
.morph .manifest .manifest-copy { color: #1c1a16; }
.morph .manifest .manifest-copy strong { color: #0f0e0b; }
@media (max-width: 700px) {
  /* Schmale Schirme: der Text laeuft ueber die volle Breite, es gibt also kein
     freies Randfenster — der Schleier deckt durchgehend (gemessen 6,3:1). */
  .manifest-bg::after {
    background:
      linear-gradient(to bottom,
        rgb(10, 13, 18) 0,
        rgba(10, 13, 18, 0) 150px,
        rgba(var(--morph-rgb, 244, 241, 234), 0) calc(100% - 150px),
        rgba(var(--morph-rgb, 244, 241, 234), 1) 100%),
      linear-gradient(rgba(244, 241, 234, .6), rgba(244, 241, 234, .6));
  }
}
.eyebrow {
  font-size: 12px; font-weight: 500; letter-spacing: .34em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 26px; text-align: center;
}
.eyebrow.light { color: rgba(236,231,220,.55); }
.statement {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(30px, 5vw, 54px); line-height: 1.18;
  text-align: center; margin: 0 0 32px; color: var(--ink);
}
.statement em, .section-title em { font-style: italic; color: var(--accent); }
/* Fliesstext einer Agentur, die von sich selbst erzaehlt:
   - linksbuendig, nicht zentriert (zentrierter Mehrzeiler bremst das Auge)
   - Zeilenlaenge in ch gemessen: 66 Zeichen ist das Optimum (50–75), vorher 72
   - erster Absatz als Lead: er traegt die Positionierung und wird zuerst gelesen
   - die Leistungen als halbfette Anker — man erfasst sie beim Ueberfliegen,
     ohne dass der Satz zerfaellt */
.manifest-copy {
  max-width: 66ch; margin: 0 auto 22px; text-align: left;
  color: #1c1a16; font-size: 17px; line-height: 1.75;
}
.manifest-lead {
  max-width: 58ch;
  font-size: clamp(19px, 1.55vw, 22px);
  line-height: 1.6;
  margin-bottom: 30px;
}
.manifest-copy strong { font-weight: 600; color: #0f0e0b; }
.manifest-copy:last-child { margin-bottom: 0; }
.manifest-copy:nth-of-type(2) { transition-delay: .08s; }
.manifest-copy:nth-of-type(3) { transition-delay: .16s; }
.manifest-copy:nth-of-type(4) { transition-delay: .24s; }

/* ---------- Leistungen (dunkel, Porsche-Karten) ---------- */
.services { padding: 120px 0; }
.section-title {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(30px, 4.6vw, 50px); line-height: 1.15;
  text-align: center; margin: 0 0 70px; color: var(--ink);
}
.section-title.light { color: var(--ivory); }
.services .section-title { color: var(--ivory); }

/* Acht gleichwertige Leistungen, vier Spalten, zwei Reihen. Der frühere Zickzack
   (4-2-2-4) lebte davon, dass breite und hohe Kacheln unterschiedliche Bildformate
   trugen — ohne Fotos gäbe es nichts mehr zu rhythmisieren, ein unruhiges Raster
   wäre dann nur noch unruhig. Keine der acht Leistungen steht über den anderen,
   also bekommt auch keine mehr Fläche. */
.cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}
.card {
  position: relative; display: flex; flex-direction: column;
  min-height: 360px;
  border: 1px solid var(--line-d);
  border-radius: 10px; overflow: hidden;
  transition: border-color .4s, box-shadow .5s;
}
.card:hover,
.card:focus-within { border-color: rgba(184,149,31,.5); box-shadow: 0 24px 60px rgba(0,0,0,.5); }

/* ---------- Video-Fenster ----------
   EIN Video liegt viewport-fest hinter der Seite; die acht Karten sind Fenster
   hinein. Der Layer wird per clip-path auf genau die acht Kartenrechtecke
   beschnitten (main.js), der Grund zwischen ihnen bleibt frei.

   Warum viewport-fest und nicht ueber das Raster gespannt: bei zwei oder einer
   Spalte ist der Rasterbereich hochformatig (am Handy ~390 × 3200 px). Ein 16:9-Video
   darin mit `cover` waere 8-fach hineingezoomt — man saehe einen Betonstreifen.
   Viewport-fest zeigt das Video immer in seinem eigenen Format, und beim Scrollen
   wandert das Motiv hinter den Kacheln durch.

   Deckkraft 18 %: nachgemessen, nicht geschaetzt — Schrift ausgeblendet, hellsten
   bzw. dunkelsten Grundpunkt hinter dem Fliesstext gesucht, Kontrast dagegen
   gerechnet, und zwar ueber die ganzen 54 s Laufzeit im echten Lauf:
     dunkler Morph-Zustand — 5,26:1 … 6,3:1 (knappster Fall: Pipe-Flug bei t≈34 s)
     heller Morph-Zustand  — 5,49:1 … 7,2:1
   Beides ueber WCAG AA (4,5:1). Voraussetzung ist die Tonwertkompression beim
   Enkodieren (Lichter auf 200 gedeckelt — im Original 255 —, Schatten angehoben,
   Saettigung 55 %): ohne sie erschlagen die weissen Wolken des Pipe-Flugs den Text,
   und die Nachtszene verschwindet ganz. Das Rezept steht in build-video.sh neben
   deploy.py. Wer die Deckkraft anhebt oder ein anderes Video einhaengt: neu messen.
   Ohne JS bleibt der Layer unsichtbar. */
.cards-stage { position: relative; }
.cards-video {
  position: fixed; top: 0; left: 0;
  width: 100vw; height: 100vh;
  object-fit: cover;
  opacity: 0;
  z-index: 0;
  pointer-events: none;
  clip-path: inset(50%);          /* ohne JS: nichts sichtbar */
  visibility: hidden;             /* ausserhalb der Leistungen kein Compositing-Layer */
  transition: opacity .6s ease;
}
/* is-on setzt main.js, solange die Leistungen im Bild sind. Die Blende verhindert,
   dass die Fenster schon stehen, waehrend die Karten selbst noch einfliegen. */
.cards-video.is-on { visibility: visible; opacity: .18; }
.cards { position: relative; z-index: 1; }
/* Die Karte ist ein Loch, kein Kasten — ihr Grund muss durchsichtig sein,
   sonst deckt sie das Video ab, das sie zeigen soll. */
.card, .morph .card { background: transparent; }

/* Die Nummer sitzt ganz in der Karte (vorher ragte sie oben heraus und wurde
   von `overflow: hidden` abgeschnitten). Der Titel liegt per z-index darueber. */
.card-no {
  position: absolute; top: 14px; right: 16px;
  font-family: var(--serif); font-style: italic;
  font-size: clamp(64px, 5.6vw, 88px); line-height: .92;
  color: var(--ivory); opacity: .1;
  pointer-events: none;
  transition: opacity .5s ease;
}

.card-body { position: relative; z-index: 1; padding: 30px 28px 26px; }
/* Schrift, Schnitt und Sperrung setzt der Nachtrag weiter unten (Jost 700) —
   hier nur Groesse und Abstaende. */
.card-name {
  font-size: clamp(19px, 1.5vw, 23px); line-height: 1.22;
  text-transform: uppercase;
  margin: 0 0 14px;
}
/* Ausgeschriebene Bezeichnung unter einem Kürzel (SEO) */
.card-full {
  display: block; margin-top: 7px;
  font-size: 12px; font-weight: 400; letter-spacing: .16em;
  text-transform: uppercase; opacity: .55;
}
.card p { margin: 0; color: rgba(236,231,220,.62); font-size: 14.5px; line-height: 1.6; }

/* Leistungs-Liste. Ohne Zeigergerät (Touch) steht sie unten in der Karte und ist
   immer sichtbar — sonst käme man an sie nie heran. */
.card-panel {
  margin-top: auto; padding: 20px 28px 26px;
  border-top: 1px solid var(--m-card-bd, var(--line-d));
}
.card-panel-label {
  margin: 0 0 10px;
  font-size: 11px; font-weight: 600; letter-spacing: .22em;
  text-transform: uppercase; color: var(--accent);
}
.card-panel ul { list-style: none; margin: 0; padding: 0; }
.card-panel li {
  font-size: 13.5px; line-height: 1.45; padding: 5px 0;
  color: rgba(236,231,220,.72);
}
.card-panel li + li { border-top: 1px solid rgba(236,231,220,.07); }

.card-arrow {
  position: absolute; right: 24px; bottom: 22px; z-index: 3;
  color: var(--accent); font-size: 22px;
  transition: opacity .4s, transform .4s;
}

/* Mit echter Maus: die Liste liegt als Blende unter der Karte und fährt beim
   Hovern über die Beschreibung — die Karte bleibt kompakt, die Reihe springt nicht.
   :focus-within nimmt die Tastatur mit, sonst wäre die Liste ohne Maus unerreichbar. */
@media (hover: hover) {
  .card { min-height: 330px; }
  .card-panel {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
    margin-top: 0;
    background: var(--night-2);
    border-top: 1px solid rgba(184,149,31,.55);
    transform: translateY(101%);
    transition: transform .55s cubic-bezier(.16,1,.3,1);
  }
  .card:hover .card-panel,
  .card:focus-within .card-panel { transform: none; }
  /* Die Blende deckt die unteren Zeilen der Beschreibung ab — ein Satz, der hinter
     der Goldkante mitten im Wort endet, sieht nach Fehler aus. Also weicht die
     Beschreibung, sobald die Liste kommt: Titel und Nummer tragen die Karte. */
  .card-body p { transition: opacity .35s ease; }
  .card:hover .card-body p,
  .card:focus-within .card-body p { opacity: 0; }
  .card-arrow { opacity: 0; transform: translateX(-10px); }
  .card:hover .card-arrow,
  .card:focus-within .card-arrow { opacity: 1; transform: none; }
}
/* Fährt nichts ein, steht die Liste offen — sonst bliebe sie unsichtbar.
   Sie ist dann Teil der Karte und nicht mehr Blende: der Grund bleibt durchsichtig,
   damit die Textur nicht auf halber Höhe abreisst. */
@media (prefers-reduced-motion: reduce) {
  .card-panel, .morph .card-panel {
    position: static; transform: none; margin-top: auto; background: transparent;
  }
  .card-arrow { opacity: 1; transform: none; }
  .card-tex img { transition: none; }
  .card:hover .card-tex img { transform: none; }
}

.card.reveal:nth-child(4n+2) { transition-delay: .08s; }
.card.reveal:nth-child(4n+3) { transition-delay: .16s; }
.card.reveal:nth-child(4n+4) { transition-delay: .24s; }

@media (max-width: 1100px) {
  .cards { grid-template-columns: repeat(2, 1fr); }
  .card.reveal:nth-child(n) { transition-delay: 0s; }
  .card.reveal:nth-child(2n) { transition-delay: .08s; }
}
@media (max-width: 620px) {
  .cards { grid-template-columns: 1fr; gap: 16px; }
  .card { min-height: 0; }
  /* Am Handy trägt die Blende nicht: sie verdeckte die Beschreibung dauerhaft.
     Ohne Deckung darunter läuft die Textur durch die ganze Karte. */
  .card-panel, .morph .card-panel {
    position: static; transform: none; margin-top: auto; background: transparent;
    border-top-color: var(--m-card-bd, var(--line-d));
  }
  .card-arrow { opacity: 1; transform: none; }
  .card-no { font-size: 92px; }
}

/* ---------- Team ----------
   Editorial im Wechsel: Portrait und Text tauschen von Kopf zu Kopf die Seite. Drei
   Spalten nebeneinander schieden aus — die Texte sind zu lang, sie wuerden zu drei
   duennen Saeulen. So bleibt die Zeilenlaenge im lesbaren Bereich. */
.team { padding: 130px 0 130px; background: var(--night); }
.team .section-title { margin-bottom: 90px; }
.member {
  display: grid;
  grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
  gap: clamp(30px, 4vw, 64px);
  align-items: center;
  margin-bottom: 96px;
}
.member:last-child { margin-bottom: 0; }
/* Der zweite Kopf spiegelt sich — Foto rechts, Text links. Dabei muessen die
   Spaltenbreiten mitspiegeln: sonst rutscht das Foto in die 1fr-Spalte und der Text
   in die 40%-Spalte, und der gespiegelte Kopf steht 38 % groesser da als die anderen
   (gemessen 682 statt 493 px). */
/* Beim gespiegelten Kopf haengt die Textspalte an ihrem Inhalt (max-content), nicht
   an 1fr. Grund: der Fliesstext ist auf 62 Zeichen begrenzt und fuellt seine Spalte
   nicht aus — bei 1440 px bleiben 101 px Spalte ungenutzt. Steht der Text links
   (ungespiegelt), liegt diese Luft aussen am Seitenrand und faellt nicht auf. Steht
   er rechts, liegt sie mitten zwischen Text und Portrait: gemessen klafften dort
   162 px statt der 91 px der anderen beiden.
   Mit max-content ist die Spalte so breit wie der Text wirklich ist, das Portrait
   rueckt genau um die ungenutzte Breite nach — und zwar auf jeder Schirmbreite von
   selbst. Ein fester Versatz haette bei schmalen Schirmen ins Textfeld gegriffen,
   weil die Luft dort gar nicht existiert. */
.member:nth-child(even) { grid-template-columns: minmax(0, max-content) minmax(0, 40%); }
.member:nth-child(even) .member-photo { grid-column: 2; grid-row: 1; }
.member:nth-child(even) .member-text  { grid-column: 1; grid-row: 1; }

/* Die Portraits tragen ihren Freisteller im Alphakanal (build-team.py rechnet den
   frueheren `mix-blend-mode: screen` dort hinein, pixelgleich). Der Blend-Mode
   selbst ist bewusst raus: er blendet nur innerhalb des eigenen Stacking-Kontexts,
   und `.member` bekommt beim Einblenden per `.reveal` sowohl opacity als auch
   transform — beides oeffnet so einen Kontext. Fuer die vollen 0,9 s der
   Einblendung stand deshalb ein schwarzer Kasten um jeden Kopf. Mit Alpha ist das
   Bild von der Stapelordnung unabhaengig und darf beliebig animiert werden. */
/* min-width: 0 — Rasterzellen schrumpfen von Haus aus nicht unter ihren Inhalt,
   und der Inhalt ist hier ein 800 px breites Bild. */
.member-photo { min-width: 0; }
.member-photo img {
  width: 100%; height: auto;
}
.member-role {
  margin: 0 0 10px;
  font-size: 12px; font-weight: 600; letter-spacing: .22em;
  text-transform: uppercase; color: var(--accent);
}
.member-name {
  font-family: var(--sans); font-weight: 700;
  font-size: clamp(26px, 3vw, 38px); line-height: 1.1;
  letter-spacing: .06em; text-transform: uppercase;
  margin: 0 0 20px; color: var(--ivory);
}
.member-text p:not(.member-role) {
  margin: 0 0 16px; max-width: 62ch;
  color: rgba(236,231,220,.66);
  font-size: 16px; font-weight: 400; line-height: 1.75;
}
.member-text p:last-child { margin-bottom: 0; }

@media (max-width: 860px) {
  /* Einspaltig: Portrait immer ueber dem Text — auch beim gespiegelten Kopf, sonst
     stuende dort der Text vor dem Gesicht, zu dem er gehoert.
     Die :nth-child(even)-Regel MUSS hier mitgenannt werden: sie ist spezifischer
     (0,2,0) als `.member` (0,1,0) und behielte sonst ihre zwei Spalten — der
     gespiegelte Kopf landete dann am Handy in der 40%-Spalte und waere ein Drittel
     so gross wie die anderen. */
  /* minmax(0, 1fr) statt 1fr: Rasterzellen schrumpfen sonst nicht unter ihren
     Inhalt — hier ein 800 px breites Bild. */
  .member,
  .member:nth-child(even) { grid-template-columns: minmax(0, 1fr); gap: 6px; margin-bottom: 72px; }
  .member:nth-child(even) .member-photo,
  .member:nth-child(even) .member-text { grid-column: 1; grid-row: auto; }
  /* Einspaltig steht das Portrait mittig — die Verschiebung zum Text ergibt hier
     keinen Sinn mehr und wuerde es aus der Mitte ruecken. */
  .member:nth-child(even) .member-photo { transform: none; }
  /* `width: 100%` ist hier nicht redundant: `margin: 0 auto` schaltet bei einem
     Rasterelement das Strecken ab, es nimmt dann seine Inhaltsbreite an — beim
     800-px-Bild also die 420 px der max-width. Das Portrait stand damit 54 px
     ueber dem rechten Schirmrand eines 390-px-Schirms. */
  .member-photo { width: 100%; max-width: 420px; margin: 0 auto; }
  .team { padding: 100px 0; }
  .team .section-title { margin-bottom: 60px; }
}

/* ---------- Statement-Band ---------- */
.band {
  position: relative; overflow: hidden;
  min-height: 94vh;                 /* höher, damit die Gondel im Bild bleibt */
  display: flex; align-items: center; justify-content: center;
}
.band-img {
  position: absolute; inset: -12% 0;
  background-size: cover; background-position: center 62%;
  will-change: transform;
}
.band-shade { position: absolute; inset: 0; background: rgba(8, 12, 16, .45); }
.band-content { position: relative; text-align: center; color: #fff; padding: 120px 24px; }
.band-content h2 {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(34px, 6vw, 72px); line-height: 1.1; margin: 0 0 18px;
  text-shadow: 0 2px 30px rgba(0,0,0,.45);
}
.band-content em { font-style: italic; }
/* gleiche Anmutung wie die Zeile im Hero ("Marketing · Content · Kampagnen"),
   als alleiniger Inhalt des Bandes aber deutlich größer */
.band-content p {
  font-family: var(--sans);
  font-size: clamp(18px, 2.7vw, 34px); font-weight: 400;
  letter-spacing: .3em; text-transform: uppercase;
  color: #fff;
  text-shadow: 0 2px 26px rgba(0,0,0,.5);
  margin: 0;
}

/* ---------- Arbeiten / Polaroids ---------- */
.works { background: var(--night-2); padding: 120px 0 140px; }
.polaroids {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 38px 26px; margin-top: 70px;
}
.pol {
  margin: 0; background: #faf8f2; padding: 12px 12px 14px;
  width: min(320px, 78vw);
  transform: rotate(var(--rot, 0deg));
  box-shadow: 0 14px 40px rgba(0,0,0,.45);
  transition: transform .5s cubic-bezier(.16,1,.3,1), box-shadow .5s;
}
.pol:hover { transform: rotate(0deg) scale(1.05); box-shadow: 0 26px 70px rgba(0,0,0,.6); z-index: 2; position: relative; }
.pol img { aspect-ratio: 4/3; object-fit: cover; width: 100%; }
.pol figcaption {
  font-family: var(--hand); font-size: 22px; color: #33312b;
  text-align: center; padding-top: 10px;
}

/* ---------- Referenzen ---------- */
.clients { background: var(--night); padding: 110px 0 130px; border-top: 1px solid var(--line-d); }
.logo-grid {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 14px; margin-top: 60px;
}
.logo-tile {
  background: var(--night);
  border: 1px solid var(--line-d);
  width: 250px; aspect-ratio: 3/2;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  transition: background .4s, border-color .4s;
}
@media (max-width: 560px) { .logo-tile { width: calc(50% - 8px); } }
.logo-tile img {
  max-height: 118px; max-width: 92%; object-fit: contain;
  filter: brightness(0) invert(1); opacity: .55;
  transition: filter .45s ease, opacity .45s ease, transform .45s ease;
}
.logo-tile img.no-invert { filter: grayscale(1) brightness(1.5); }
/* Nur ein Teil der Referenzen fuehrt zu einer Seite — ohne Hinweis klickt man
   sonst auf die anderen ins Leere. Der Pfeil erscheint erst beim Hovern, damit die
   Logowand ruhig bleibt. */
a.logo-tile { position: relative; }
a.logo-tile::after {
  content: "↗";
  position: absolute; top: 7px; right: 10px;
  font-size: 12px; line-height: 1; color: var(--accent);
  opacity: 0; transform: translate(-3px, 3px);
  transition: opacity .3s ease, transform .3s ease;
}
a.logo-tile:hover::after,
a.logo-tile:focus-visible::after { opacity: .9; transform: none; }
a.logo-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.logo-tile:hover { background: var(--night-2); border-color: rgba(184,149,31,.4); }
.logo-tile:hover img { filter: none; opacity: 1; transform: scale(1.06); }

/* ---------- Kontakt ---------- */
.contact { background: var(--ivory-bg); padding: 130px 0; text-align: center; }
.contact-title {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(52px, 9vw, 110px); line-height: 1; margin: 0 0 48px;
}
.contact-actions { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
.btn-solid, .btn-line {
  display: inline-block; padding: 16px 40px;
  font-size: 13px; letter-spacing: .18em; text-transform: uppercase;
  transition: all .35s;
}
.btn-solid { background: var(--ink); color: var(--ivory); border: 1px solid var(--ink); }
.btn-solid:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-line { border: 1px solid var(--line-l); color: var(--ink); }
.btn-line:hover { border-color: var(--ink); }

/* ---------- Footer ---------- */
.footer { background: #06080c; color: rgba(236,231,220,.6); padding: 90px 0 40px; overflow: hidden; }
.footer-grid {
  display: grid; grid-template-columns: auto repeat(3, 1fr);
  gap: 48px; margin-bottom: 90px; align-items: start;
}

/* ---------- Instagram-Knopf (Footer, links neben der Navigation) ----------
   Steht, wo frueher das drehende Fassaden-Prisma sass. Die Rasterspalte ist deshalb
   von 300 px auf `auto` umgestellt: ein 46-px-Knopf in einer 300-px-Spalte haette
   ein Loch hinterlassen. Dezent im Ruhezustand, beim Hovern waechst er und hellt
   vom Logo-Gold (#8a7317, die Farbe der Vorlage) auf den helleren Akzent auf —
   brightness(1.35) trifft ziemlich genau --accent (184,149,31). */
.footer-social { grid-row: 1 / span 2; }
.social-btn {
  display: block; width: 46px; line-height: 0;
  opacity: .75;
  transition: opacity .35s ease, transform .4s cubic-bezier(.16,1,.3,1);
}
.social-btn img {
  width: 100%; height: auto;
  transition: filter .35s ease;
}
.social-btn:hover,
.social-btn:focus-visible { opacity: 1; transform: scale(1.18); }
.social-btn:hover img,
.social-btn:focus-visible img { filter: brightness(1.35); }
.social-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 8px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
  .social-btn { transition: opacity .35s ease; }
  .social-btn:hover, .social-btn:focus-visible { transform: none; }
}

/* Trennpunkte zwischen den Navigationszielen im Fuss. Sie stehen im CSS und nicht im
   Markup, damit beim Hinzufuegen oder Entfernen eines Punktes nie ein Trenner allein
   am Ende steht. Nur diese eine Spalte — in "Kontakt" trennt bereits ein Punkt die
   Anschrift, dort waere es doppelt.
   Der Punkt haengt hinten am Link (::after), nicht vorne am naechsten (::before):
   die Zeile bricht hier um, und ein vorangestellter Trenner rutschte mit auf die
   naechste Zeile — dort stand dann "· Kontakt". So bleibt er beim Wort davor.
   pointer-events: none, damit er nicht Teil der Klickflaeche wird. */
.footer-nav a:not(:last-of-type)::after {
  content: "·";
  color: var(--accent);
  opacity: .55;
  margin: 0 5px 0 9px;
  pointer-events: none;
}

.footer-mark {
  grid-column: 2 / -1; grid-row: 2;
  align-self: end; justify-self: end;
  width: min(100%, 520px);
  user-select: none;
}
.footer-mark img { width: 100%; height: auto; opacity: .28; }
@media (max-width: 980px) {
  .footer-mark { grid-column: 1 / -1; grid-row: auto; justify-self: center; width: min(100%, 380px); }
}
.footer-line {
  text-align: center; font-size: 12.5px; letter-spacing: .08em;
  color: rgba(236,231,220,.35); margin: 26px 0 0;
}

/* ---------- Legal Modal ---------- */
.legal {
  border: 0; border-radius: 8px; padding: 0;
  max-width: 640px; width: calc(100% - 48px);
  background: var(--ivory-bg); color: var(--ink);
}
.legal::backdrop { background: rgba(6, 8, 12, .8); backdrop-filter: blur(4px); }
.legal-body { padding: 44px 44px 40px; max-height: 82vh; overflow-y: auto; }
/* Die Datenschutzerklaerung ist lang — Gliederung muss lesbar bleiben. */
.legal-body h4 {
  font-family: var(--sans); font-weight: 600;
  font-size: 13px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--gold); margin: 26px 0 8px;
}
.legal-body h4:first-of-type { margin-top: 18px; }
.legal-body p + p { margin-top: 10px; }
.legal-body a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }
.legal-body strong { font-weight: 600; }
/* Noch fehlende Pflichtangaben sind bewusst als Luecke sichtbar, nicht erfunden. */
.legal-todo {
  display: inline-block; padding: 1px 8px; border-radius: 3px;
  background: rgba(184,149,31,.16); border: 1px dashed rgba(184,149,31,.55);
  color: #6d5a11; font-size: 13px; letter-spacing: .04em;
}
.legal-body h3 { font-family: var(--serif); font-size: 30px; margin: 0 0 18px; }
.legal-body p { font-size: 15px; color: #4c4a42; }
.legal-close {
  position: absolute; top: 12px; right: 16px;
  background: none; border: 0; font-size: 30px; cursor: pointer; color: var(--ink);
  font-family: var(--sans);
}

/* Schmale Schirme: alles einspaltig und mittig. */
@media (max-width: 700px) {
  .footer-grid { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; }
  .footer-col { min-width: 0; }
  .footer-social { grid-column: 1; grid-row: auto; margin: 0 auto 20px; }
  .footer-mark { grid-column: 1; grid-row: auto; justify-self: center; width: min(80%, 300px); }
}

/* ============================================================
   Typografie-Feinschliff — alles in Jost
   Die Ueberschriften waren auf eine Serifenschrift abgestimmt (Gewicht 500).
   Jost ist geometrisch und traegt in grossen Graden deutlich mehr Farbe,
   deshalb hier leichter und mit etwas mehr Laufweite.
   ============================================================ */
/* Alle grossen Ueberschriften laufen in Versalien — dieselbe Anmutung wie das
   Statement-Band ("STARTEN SIE IHRE ZUKUNFT JETZT MIT UNS!"), nur weniger weit
   gesperrt, weil hier ganze Saetze stehen und nicht eine einzelne Zeile. */
.statement, .section-title, .contact-title, .band-content h2 {
  text-transform: uppercase;
  font-weight: 500;
  letter-spacing: .07em;
  line-height: 1.3;
}
/* Grundschrift eine Stufe kraeftiger — Jost 300 wirkt auf hellem Grund duenn. */
body { font-weight: 400; }
.manifest-copy, .card p, .footer-col a, .footer-col span, .legal-body p { font-weight: 400; }
.band-content p { font-weight: 500; }
.mobilemenu a { font-weight: 400; }
/* Versalien bauen breiter: eine Spur kleiner, damit die Zeilen so umbrechen,
   wie es der Satz vorgibt, und nicht mitten im Gedanken. */
.statement     { font-size: clamp(26px, 3.9vw, 44px); }
.section-title { font-size: clamp(26px, 3.6vw, 42px); }
/* "Reden Sie mit uns." war mit bis zu 110px mehr als doppelt so gross wie die
   uebrigen Ueberschriften — in Versalien erschlagend. Jetzt nur noch eine Stufe
   ueber ihnen, damit es Schlusspunkt bleibt, ohne die Seite zu sprengen. */
.contact-title {
  font-size: clamp(32px, 5.2vw, 62px);
  letter-spacing: .06em;
  line-height: 1.15;
  margin-bottom: 40px;
}
/* Die Abschnitts-Label ("Die Agentur", "Leistungen", "Referenzen", "Kontakt")
   waren mit 12px die kleinste Schrift der Seite und gingen unter. Groesser und
   kraeftiger — die weite Sperrung haelt den Label-Charakter. */
.eyebrow {
  font-size: clamp(13px, 1.15vw, 16px);
  font-weight: 600;
  letter-spacing: .3em;
  color: #33312b;
  margin-bottom: 22px;
}
.eyebrow.light { color: rgba(236, 231, 220, .72); }
.legal-body h3 { font-weight: 500; letter-spacing: .06em; text-transform: uppercase; }
.card-no { font-weight: 400; }
/* Karten-Titel trug Fugaz One — jetzt Jost, kraeftig gesetzt statt fremder Schrift */
.card-name {
  font-family: var(--sans);
  font-weight: 700;
  letter-spacing: .06em;
}

/* ---------- Gold-Woerter: dezenter elektrischer Effekt ----------
   Die hervorgehobenen Woerter (sichtbar / bewegen / vertrauen) bekommen einen
   Gold-Verlauf, durch den in grossen Abstaenden ein Lichtbogen laeuft, begleitet
   von einem kurzen Flackern. Ohne background-clip-Unterstuetzung bleibt es
   schlicht goldfarben. */
.statement em, .section-title em {
  font-style: italic;
  color: var(--accent);
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  /* Der Verlauf sitzt auf dem Wort-Span (.w), nicht auf dem <em>: die kinetische
     Typografie laesst die Woerter einzeln einfliegen (transform), und ein am <em>
     haengender, per background-clip freigestellter Hintergrund fliegt dabei NICHT
     mit — das Wort erschiene dann sichtbar spaeter als seine Nachbarn.
     Wenn kein JS laeuft, gibt es keine .w-Spans; dann traegt das <em> selbst den
     Verlauf (Regel unten greift dann mangels .kin nicht). */
  .statement em .w, .section-title em .w,
  .statement em, .section-title em {
    /* Ruhezustand ist durchgehend Gold: die Raender des Verlaufs haben dieselbe
       Farbe wie die Mitte, nur in der Mitte sitzt der Lichtbogen. Dadurch steht
       das Wort von der ersten Sekunde an voll da — der Bogen laeuft nur hindurch.
       Auf dem hellen Elfenbein-Grund braucht der Bogen dunkle Flanken, sonst
       verschwindet sein heller Kern im Hintergrund. */
    background-image: linear-gradient(100deg,
      var(--accent) 0%, var(--accent) 38%, #6d5a11 44%, #f7e6a8 50%,
      #6d5a11 56%, var(--accent) 62%, var(--accent) 100%);
    background-size: 300% 100%;
    background-position: 0% 50%;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
  /* Auf Nachtblau ist der helle Kern selbst der Kontrast — keine dunklen Flanken.
     Das Statement-Band steht auf einem dunklen Bergfoto und bekommt dieselbe
     helle Fassung. */
  .section-title.light em .w, .section-title.light em,
  .band-content em {
    background-image: linear-gradient(100deg,
      var(--accent) 0%, var(--accent) 40%, #f2dc9a 47%, #fffaea 50%,
      #f2dc9a 53%, var(--accent) 60%, var(--accent) 100%);
  }
  /* Das Band wird von der kinetischen Typografie nicht erfasst (main.js zerlegt nur
     .statement/.section-title/.contact-title in Woerter) — der Verlauf haengt hier
     also direkt am <em>, nicht an einem Wort-Span. */
  .band-content em {
    background-size: 300% 100%;
    background-position: 0% 50%;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    /* Der Schatten der Zeile wuerde als dunkler Abdruck durch den freigestellten
       Text schlagen. */
    text-shadow: none;
  }
  .band-content.is-in em {
    animation: ev-gold-arc 9s ease-out .25s infinite,
               ev-gold-flicker 9s linear .25s infinite;
  }
  /* Sobald JS die Woerter gewrappt hat (.kin), traegt nur noch der Wort-Span den
     Verlauf. Das <em> muss seinen dann abgeben — sonst zeichnet es einen zweiten,
     unbewegten Gold-Abdruck an der Ausgangsposition. */
  .kin em {
    background-image: none;
    -webkit-text-fill-color: currentColor;
    color: var(--accent);
  }
  /* Der Bogen laeuft direkt mit dem Einfliegen der Zeile — er wartet nicht ab. */
  .statement.is-in em .w, .section-title.is-in em .w,
  .statement.is-in em, .section-title.is-in em {
    animation: ev-gold-arc 9s ease-out .25s infinite,
               ev-gold-flicker 9s linear .25s infinite;
  }
  .kin.is-in em { animation: none; }

  /* Dieselbe Gold-Mechanik auf der Karten-Nummer, aber erst beim Hovern: die Zahl
     liegt im Ruhezustand blass hinter dem Titel und zuendet dann golden durch.
     Die helle Verlaufs-Variante, weil sie immer auf dunklem Grund steht.
     Deckkraft .5 statt voll: der Titel liegt darueber, und auf vollem Gold
     (#b8951f) haelt Elfenbein nur 2,4:1 — halbdeckend bleibt er bei 6,5:1.
     Der Bogen laeuft hier alle 3,5 s statt alle 9 s: ein Hover dauert selten
     neun Sekunden, sonst saehe man den Effekt nie. */
  .card:hover .card-no,
  .card:focus-within .card-no {
    opacity: .5;
    background-image: linear-gradient(100deg,
      var(--accent) 0%, var(--accent) 40%, #f2dc9a 47%, #fffaea 50%,
      #f2dc9a 53%, var(--accent) 60%, var(--accent) 100%);
    background-size: 300% 100%;
    background-position: 0% 50%;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: ev-gold-arc 3.5s ease-out infinite,
               ev-gold-flicker 3.5s linear infinite;
  }
}
/* Ohne background-clip bleibt die Zahl beim Hovern schlicht goldfarben. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .card:hover .card-no,
  .card:focus-within .card-no { opacity: .5; color: var(--accent); }
}
@media (prefers-reduced-motion: reduce) {
  .card:hover .card-no, .card:focus-within .card-no { animation: none; }
}
@keyframes ev-gold-arc {
  0%        { background-position: 0% 50%; }
  20%, 100% { background-position: 100% 50%; }
}
/* Der Blitz: waehrend der Bogen durchlaeuft, zuckt die Helligkeit zweimal kurz —
   nicht als Blinken, sondern als kurzer Stromstoss. */
@keyframes ev-gold-flicker {
  0%       { filter: brightness(1)    drop-shadow(0 0 3px rgba(184, 149, 31, .16)); }
  7%       { filter: brightness(1.28) drop-shadow(0 0 10px rgba(240, 214, 130, .5)); }
  9%       { filter: brightness(.96)  drop-shadow(0 0 2px rgba(184, 149, 31, .1)); }
  14%      { filter: brightness(1.34) drop-shadow(0 0 14px rgba(255, 246, 220, .55)); }
  18%      { filter: brightness(1.04) drop-shadow(0 0 5px rgba(184, 149, 31, .2)); }
  22%, 100% { filter: brightness(1)   drop-shadow(0 0 3px rgba(184, 149, 31, .16)); }
}
@media (prefers-reduced-motion: reduce) {
  .statement.is-in em, .section-title.is-in em {
    animation: none;
    background-position: 100% 50%;
    filter: none;
  }
}

/* Reserve: Logos mit fast schwarzen Anteilen wuerden im Hover (Originalfarben)
   in der dunklen Kachel verschwinden — diese Klasse haelt sie als weisse
   Silhouette. Aktuell benutzt sie niemand; die neue Box'n-Stop-Fassung ist hell. */
.logo-tile:hover img.keep-invert { filter: brightness(0) invert(1); }

/* Mobil: die Leiste soll beim Scrollen nicht einklappen — Hoehe und Logo
   bleiben konstant, nur der dunkle Hintergrund kommt dazu. */
@media (max-width: 860px) {
  .nav, .nav.is-scrolled { padding: 22px 0; }
  .nav.is-scrolled .nav-mark img { height: 26px; }
}

/* ---------- Baukasten-CTA unter den Leistungen ----------
   Anklickbarer Satz, der zur interaktiven Lego-Unterseite fuehrt. Liegt in der
   Morph-Zone und uebernimmt deren Hell/Dunkel-Tokens; das Gold-Wort nutzt
   denselben elektrischen Lichtbogen wie die Section-Titles. */
.brickcta {
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  margin: clamp(80px,10vw,132px) auto 8px; padding: 0 24px; max-width: 940px;
  text-align: center; text-decoration: none; color: var(--m-fg); cursor: pointer;
}
.brickcta-studs { display: flex; gap: 7px; margin-bottom: .5rem; }
.brickcta-studs i {
  width: 10px; height: 10px; border-radius: 50%;
  border: 1px solid var(--accent); opacity: .45;
  transition: opacity .35s ease, transform .45s cubic-bezier(.5,.05,.25,1);
}
.brickcta:hover .brickcta-studs i, .brickcta:focus-visible .brickcta-studs i { opacity: 1; }
.brickcta:hover .brickcta-studs i:nth-child(1) { transform: translateY(-2px); }
.brickcta:hover .brickcta-studs i:nth-child(2) { transform: translateY(-6px); }
.brickcta:hover .brickcta-studs i:nth-child(3) { transform: translateY(-6px); }
.brickcta:hover .brickcta-studs i:nth-child(4) { transform: translateY(-2px); }
.brickcta-eyebrow {
  font-size: .74rem; letter-spacing: .32em; text-transform: uppercase;
  color: var(--m-kicker);
}
.brickcta-line {
  font-size: clamp(1.9rem, 3.6vw, 3.1rem); font-weight: 300; line-height: 1.1; letter-spacing: .01em;
}
.brickcta-line em { font-style: normal; color: var(--accent); }
.brickcta-hint {
  margin-top: 1rem; display: inline-flex; align-items: center; gap: .6em;
  font-size: .78rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--m-kicker); position: relative; padding-bottom: 7px;
}
.brickcta-hint::after {
  content: ""; position: absolute; left: 50%; bottom: 0; height: 1px; width: 0;
  background: var(--accent); transform: translateX(-50%);
  transition: width .45s cubic-bezier(.5,.05,.25,1);
}
.brickcta:hover .brickcta-hint::after, .brickcta:focus-visible .brickcta-hint::after { width: 100%; }
.brickcta-arrow { transition: transform .3s ease; }
.brickcta:hover .brickcta-arrow, .brickcta:focus-visible .brickcta-arrow { transform: translateX(7px); }

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .brickcta-line em {
    background-image: linear-gradient(100deg,
      var(--accent) 0%, var(--accent) 38%, #6d5a11 44%, #f7e6a8 50%,
      #6d5a11 56%, var(--accent) 62%, var(--accent) 100%);
    background-size: 300% 100%; background-position: 0% 50%; background-repeat: no-repeat;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: ev-gold-arc 9s ease-out infinite, ev-gold-flicker 9s linear infinite;
  }
  .morph.is-dark .brickcta-line em {
    background-image: linear-gradient(100deg,
      var(--accent) 0%, var(--accent) 40%, #f2dc9a 47%, #fffaea 50%,
      #f2dc9a 53%, var(--accent) 60%, var(--accent) 100%);
  }
}
@media (prefers-reduced-motion: reduce) { .brickcta-line em { animation: none; } }
