/* =========================================================================
   D.Sign — drittes Konzept ("dsign-hell")
   Rasterlogik: Fibonacci (8 · 13 · 21 · 34 · 55 · 89 · 144 · 233), wie in
   jedem Projekt des Hauses. Typoskala im Verhältnis 1,618 (φ).

   Bewusster Bruch mit den beiden anderen D.Sign-Konzepten: hell statt
   dunkel, verspielt statt nüchtern oder laut-technisch. Eigene Farben,
   eigene Schriften (Fredoka/Nunito statt Bricolage/Newsreader oder
   Cormorant/Jost) — Konzepte dieser Marke teilen bewusst keinen Code.

   Kontraste sind gerechnet, nicht geschätzt (WCAG-Formel, sRGB):
     --tinte / --grund           14,24 : 1
     --tinte / --grund-tief      12,72 : 1
     --tinte-mute / --grund       5,64 : 1
     --tinte auf --akzent         5,06 : 1   (Knopftext auf Aktionsfarbe)
     Weiß auf --gas                5,98 : 1   (heller Text auf Prüf-Farbe)
     --gas als Text / --grund      5,35 : 1
   --akzent selbst erreicht als Textfarbe auf --grund nur 2,82 : 1 und
   bleibt deshalb reine Flächenfarbe (Knöpfe, aktiver Reiter, Rahmen) —
   nie Schriftfarbe auf hellem Grund. Nachrechnen: assets/css/README enthält
   das Skript nicht, siehe Spec-Dokument im Wurzel-Repo unter
   docs/superpowers/specs/2026-09-14-dsign-hell-design.md.
   ========================================================================= */

:root {
  /* Farbe */
  --grund:      #FBF1E4;  /* warme Cremefläche, kein reines Weiß */
  --grund-tief: #F3E4CE;  /* Karten, Mockup-Rahmen, zurücktretende Flächen */
  --grund-hi:   #FFFFFF;  /* erhobene Flächen: Eingaben, Tooltips */
  --tinte:      #2B2016;  /* Fließtext, warmes Dunkelbraun statt Schwarz */
  --tinte-mute: #6B5E4E;  /* gedämpfter Text, Meta-Zeilen */

  --akzent:      #EC6A34; /* warm — Aktionen: CTA, aktiver Reiter, Fokus */
  --akzent-lite: #F6AD8A; /* Hover/Rahmen, wo keine Textfarbe gebraucht wird */
  --gas:         #106E76; /* kühl — Prüfbares: "Prüfkriterium", Live-Links */
  --gas-lite:    #6FB3B8;

  /* Abstände — Fibonacci */
  --s1: 8px;  --s2: 13px; --s3: 21px; --s4: 34px;
  --s5: 55px; --s6: 89px; --s7: 144px; --s8: 233px;

  /* Typoskala — Schritte im Verhältnis 1,618 */
  --t-xs: clamp(12px, .2vw + 11px, 14px);
  --t-s:  clamp(15px, .3vw + 13px, 18px);
  --t-m:  clamp(18px, .55vw + 15px, 23px);
  --t-l:  clamp(28px, 3.2vw + 13px, 54px);
  --t-xl: clamp(37px, 6.6vw + 8px, 98px);

  /* Motion — Delays ebenfalls Fibonacci */
  --d1: 89ms; --d2: 144ms; --d3: 233ms; --d4: 377ms; --d5: 610ms;
  --ease: cubic-bezier(.22, .61, .36, 1);

  /* Radien — spielerisch statt scharfkantig */
  --r-s: 10px; --r-m: 18px; --r-l: 28px; --r-pille: 999px;

  --display: 'Fredoka', ui-rounded, 'SF Pro Rounded', system-ui, sans-serif;
  --text:    'Nunito', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;

  --edge: clamp(var(--s3), 5.5vw, var(--s7));
  /* asymmetrischer Split, nie 50/50, nie Prozent. minmax(0, …) statt
     nacktem fr: bare fr-Spuren haben eine implizite min-content-Grenze —
     ein langes Wort ohne Umbruchstelle (z. B. "herausstechen." im
     Hero-Titelwechsel) hätte die schmale Spalte sonst über ihren
     fr-Anteil hinaus aufgedrückt und das Mockup nach rechts verschoben.
     minmax(0, …) erzwingt den Anteil, der Inhalt bricht/überläuft
     innerhalb seiner eigenen Box statt die Spur zu sprengen. */
  --spur: minmax(0, 0.382fr) minmax(0, 0.618fr);
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  background: var(--grund);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--grund);
  color: var(--tinte);
  font-family: var(--text);
  font-weight: 400;
  font-size: var(--t-s);
  line-height: 1.618;
  -webkit-font-smoothing: antialiased;
}

img, svg, video, canvas { display: block; max-width: 100%; }
h1, h2, h3, p, dl, dd, ul, figure { margin: 0; }
ul { list-style: none; padding: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

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

.sprung {
  position: fixed; top: var(--s2); left: var(--s2); z-index: 200;
  padding: var(--s2) var(--s3);
  background: var(--tinte); color: var(--grund);
  font-family: var(--display); font-weight: 600;
  font-size: var(--t-xs); letter-spacing: .04em; text-transform: uppercase;
  border-radius: var(--r-s);
  transform: translateY(calc(-100% - var(--s4)));
  transition: transform var(--d3) var(--ease);
}
.sprung:focus-visible { transform: none; }

/* Dunkelmodus-Hinweis — TASKS.md Idee 2 (Danja, 17.09.2026): dsign-hell
   bleibt bewusst hell (siehe "Gestaltung" oben), zeigt Besucher:innen mit
   OS-Dunkelmodus aber einen Link zum eigenen dunklen Konzept
   (dsign-dunkel). Reines CSS, keine echte Weiterleitung (ein OS im
   Dunkelmodus heißt nicht automatisch "diese Seite soll dunkel sein") und
   kein JavaScript/LocalStorage nötig — bleibt damit im Rahmen des
   Datenschutz-Versprechens "kein LocalStorage" aus datenschutz.html. */
.dunkel-hinweis {
  display: none;
  background: var(--tinte); color: var(--grund);
  text-align: center; font-size: var(--t-xs);
  padding: var(--s2) var(--edge);
}
.dunkel-hinweis a { color: var(--akzent-lite); text-decoration: underline; text-underline-offset: .2em; }
@media (prefers-color-scheme: dark) {
  .dunkel-hinweis { display: block; }
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------- Branchen-Marquee */
/* Achtes bewegte Ding (Entscheidung Danja, 16.09.2026) — anders als die
   anderen sieben eine endlose statt einmalige Bewegung, reines CSS, kein
   JS: transform-Schleife, vom Compositor animiert, kein Layout-Thrashing.
   Deshalb trotzdem hier gelistet, nicht nur als Kommentar wie Fade-Pop —
   "endlos" ist genau der Fall, den prefers-reduced-motion abfangen muss. */
.branchen {
  overflow: hidden;
  background: var(--tinte);
  padding-block: var(--s2);
}
.branchen__spur {
  display: flex; width: max-content;
  animation: branchen-lauf 34s linear infinite;
}
@keyframes branchen-lauf {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.branchen__wort {
  white-space: nowrap; font-size: var(--t-m); color: var(--grund);
}
/* ::after auf jedem Wort, nicht nur :not(:last-child) — sonst hat die
   Spur nur an der EINEN echten letzten Position keinen Trenner, aber an
   der Naht zwischen den beiden Wiederholungen (nach dem letzten Wort der
   ersten Hälfte) schon. Die beiden Hälften wären dann unterschiedlich
   breit (eine mit, eine ohne Trenner-Marge), der -50%-Loop hätte an der
   Naht einen sichtbaren Sprung statt eines glatten Übergangs — gemessen
   per getBoundingClientRect, nicht vermutet (17.09.2026). */
.branchen__wort::after {
  content: '·'; display: inline-block;
  margin-inline: var(--s3); color: var(--akzent-lite);
}
.branchen__wort:nth-child(odd)  { font-family: 'Playfair Display', serif; font-weight: 700; }
.branchen__wort:nth-child(even) { font-family: 'Spectral', serif; font-style: italic; font-weight: 500; }
@media (prefers-reduced-motion: reduce) {
  .branchen__spur { animation: none; }
}

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

.mitte { max-width: 1180px; margin-inline: auto; padding-inline: var(--edge); }

.h2 {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-l); line-height: 1.08; letter-spacing: -.01em;
}
.augenbraue {
  font-family: var(--display); font-weight: 600;
  font-size: var(--t-xs); letter-spacing: .12em; text-transform: uppercase;
  color: var(--gas);
  margin-block-end: var(--s2);
}
.fliess { font-size: var(--t-m); color: var(--tinte-mute); max-width: 62ch; }
.fliess + .fliess { margin-block-start: var(--s3); }

.knopf {
  position: relative; overflow: hidden; isolation: isolate;
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s5);
  border-radius: var(--r-pille);
  font-family: var(--display); font-weight: 600;
  font-size: var(--t-s);
  border: 2px solid var(--tinte);
  color: var(--tinte);
  transition: transform var(--d2) var(--ease), color var(--d2) var(--ease);
  min-height: 44px;
}
.knopf--voll {
  --mx: 0px; --my: 0px;
  background: var(--akzent); border-color: var(--akzent); color: var(--tinte);
  transform: translate(var(--mx), var(--my));
  transition: transform var(--d2) var(--ease), background var(--d2) var(--ease), border-color var(--d2) var(--ease);
}
.knopf--ghost { background: transparent; }
.knopf--ghost::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--knopf-ghost-fill, var(--grund-tief)); transform: scaleX(0); transform-origin: left;
  transition: transform var(--d3) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .knopf--ghost:hover { transform: translateY(-2px); }
  .knopf--voll:hover { background: var(--akzent-lite); border-color: var(--akzent-lite); }
  .knopf--ghost:hover::before { transform: scaleX(1); }
}

.pruef {
  margin-block-start: var(--s2);
  font-size: var(--t-xs); color: var(--gas);
  padding-inline-start: var(--s3);
  border-inline-start: 2px solid var(--gas-lite);
}
.pruef b { font-family: var(--display); font-weight: 600; }

/* -------------------------------------------------------------- Reveal */
/* Grundzustand sichtbar: geht fx.js kaputt oder JS ist aus, bleibt der
   Inhalt da. main.js setzt `.fx-ready` auf <html>, erst dann verstecken
   .reveal-Elemente sich vor dem Einblenden. Kräftiger als vorher
   (Danja, 16.09.2026: "alles soll quasi einfliegen") — größere Strecke,
   leichtes Einschrumpfen, längere Laufzeit (--d5 statt --d4). Karten-
   Raster bekommen zusätzlich einen Fibonacci-Stagger, damit sie
   nacheinander statt gleichzeitig ankommen. */
.reveal { opacity: 1; transform: none; }
html.fx-ready .reveal {
  opacity: 0; transform: translateY(var(--s6)) scale(.94);
  transition: opacity var(--d5) var(--ease), transform var(--d5) var(--ease);
}
html.fx-ready .reveal.ist-sichtbar { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.fx-ready .reveal { opacity: 1; transform: none; transition: none; }
}

/* Zwischenüberschriften schwingen im Gewicht mit ein, dieselbe Variable-
   Font-Interpolation wie Kopf/Hero-Titel oben, hier über die schon
   vorhandene .reveal-Transition statt eine eigene Keyframe — "mehr Motion
   Graphics", Danja 17.09.2026. Nur .h2, nicht alle .reveal-Elemente: ein
   Absatz, der beim Einblenden dünner wirkt, liest sich wie ein Fehler. */
html.fx-ready .h2.reveal {
  font-variation-settings: 'wght' 300;
  transition: opacity var(--d5) var(--ease), transform var(--d5) var(--ease), font-variation-settings var(--d5) var(--ease);
}
html.fx-ready .h2.reveal.ist-sichtbar { font-variation-settings: 'wght' 700; }
@media (prefers-reduced-motion: reduce) {
  html.fx-ready .h2.reveal { font-variation-settings: 'wght' 700; transition: none; }
}

.karten .karte:nth-child(2) { transition-delay: var(--d1); }
.karten .karte:nth-child(3) { transition-delay: var(--d2); }
.karten .karte:nth-child(4) { transition-delay: var(--d3); }
.karten .karte:nth-child(5) { transition-delay: var(--d3); }
.karten .karte:nth-child(6) { transition-delay: var(--d3); }

/* ----------------------------------------------------------------- Kopf */

.kopf-fest { position: sticky; top: 0; z-index: 100; }
.kopf {
  background: color-mix(in oklab, var(--grund) 88%, transparent);
  backdrop-filter: blur(8px);
  border-block-end: 2px solid var(--grund-tief);
}
.kopf__innen {
  max-width: 1180px; margin-inline: auto; padding: var(--s3) var(--edge);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3);
}
/* Fade-Pop beim Laden: reines CSS-@keyframes, kein JS, kein Observer —
   fällt nicht unter "Was sich bewegt" in CLAUDE.md (das gilt für
   JS-Mechaniken). Ohne Animation-Unterstützung bleibt der Grundzustand
   (opacity:1, keine Transform-Regel außerhalb der Keyframes) sichtbar. */
@keyframes kopf-pop {
  from { opacity: 0; transform: scale(.88) translateY(calc(var(--s3) * -1)); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
.marke, .kopf__nav a, .kopf .knopf {
  animation-name: kopf-pop; animation-duration: var(--d4);
  animation-timing-function: var(--ease); animation-fill-mode: both;
}
.marke { animation-delay: 0ms; }
.kopf__nav a:nth-child(1) { animation-delay: var(--d1); }
.kopf__nav a:nth-child(2) { animation-delay: var(--d2); }
.kopf__nav a:nth-child(3) { animation-delay: var(--d3); }
.kopf .knopf { animation-delay: var(--d3); }

/* Schrift-Gewicht schwingt beim Einblenden mit — "mehr Motion Graphics"
   (Danja, 17.09.2026), Variable-Font-Interpolation statt neuer Effekt-
   Bibliothek, weil Fredoka/Nunito das schon als Datei mitbringen (siehe
   fonts.css). Nur auf Fließtext-Überschriften, nicht auf Knöpfe/Logo-Bild —
   ein Knopf, der beim Einblenden "dünner" wirkt, läse sich wie ein
   Render-Fehler, keine Absicht. */
@keyframes text-gewicht {
  from { font-variation-settings: 'wght' 300; }
  to   { font-variation-settings: 'wght' 700; }
}
.kopf__nav a {
  animation-name: kopf-pop, text-gewicht;
  animation-duration: var(--d4), var(--d5);
  animation-timing-function: var(--ease), var(--ease);
  animation-fill-mode: both, both;
}
@media (prefers-reduced-motion: reduce) {
  .marke, .kopf__nav a, .kopf .knopf,
  .hero__intro > *, .hero__hinweis, .mockup, .hero__titel, .h2 { animation: none; }
}

.marke { display: flex; align-items: center; cursor: pointer; }
.marke img { height: 30px; width: auto; display: block; }
.kopf__nav { display: none; gap: var(--s5); font-size: var(--t-s); }
.kopf__nav a {
  padding-block: var(--s1);
  background-image: linear-gradient(var(--akzent), var(--akzent));
  background-repeat: no-repeat; background-position: 0 100%; background-size: 0% 2px;
}
@media (hover: hover) and (pointer: fine) {
  .kopf__nav a { transition: background-size var(--d3) var(--ease); }
  .kopf__nav a:hover { background-size: 100% 2px; }
}
@media (min-width: 900px) { .kopf__nav { display: flex; } }

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

.hero { position: relative; height: 300vh; }
.hero--still { height: auto; }

.hero__stage {
  position: sticky; top: 0; min-height: 100vh;
  display: grid; grid-template-columns: 1fr; align-items: start;
  gap: var(--s6);
  padding: var(--s8) var(--edge) var(--s6);
  overflow: hidden;
}
.hero--still .hero__stage { position: static; }
/* Mobil gestapelt ist der Stage-Inhalt höher als ein Bildschirm — Video
   zuerst, Text danach, sonst wird das Sticky-Fenster erst nach dem
   Text-Block sichtbar und der Scrub-Fortschritt (an der ganzen
   Wrapper-Höhe gemessen) läuft schon einen Teil mit, bevor das Video
   überhaupt im Bild ist. Nur mobil, ab 900px greift --spur ohnehin
   nebeneinander. Gemessen mit Playwright, 375px, 16.09.2026. */
@media (max-width: 899px) {
  .mockup { order: -1; }
}
@media (min-width: 900px) {
  .hero__stage { grid-template-columns: var(--spur); padding-block-start: var(--s7); }
}

.hero__kicker {
  font-family: var(--display); font-weight: 600;
  font-size: var(--t-xs); letter-spacing: .14em; text-transform: uppercase;
  color: var(--gas);
}
.hero__titel {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-xl); line-height: .98; letter-spacing: -.015em;
  margin-block: var(--s3);
}
.hero__titel span {
  color: var(--akzent-lite); background: var(--tinte); padding-inline: .15em;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
  transition: opacity var(--d4) var(--ease), filter var(--d4) var(--ease);
}
.hero__titel span.hero__titel--wechsel { opacity: 0; filter: blur(6px); }
@media (prefers-reduced-motion: reduce) { .hero__titel span { transition: none; } }
.hero__lead { font-size: var(--t-m); color: var(--tinte-mute); max-width: 46ch; }
.hero__aktionen { display: flex; flex-wrap: wrap; gap: var(--s3); margin-block-start: var(--s5); }
.hero__hinweis {
  position: absolute; inset-inline: 0; bottom: var(--s2);
  text-align: center; font-size: var(--t-xs); color: var(--tinte-mute);
}
.hero--still .hero__hinweis { position: static; margin-block-start: var(--s3); }

/* Hero-Einblendung: dieselbe kopf-pop-Keyframe wie im Kopf, gestaffelt
   über Kicker/Titel/Lead/Knöpfe. Grundzustand ohne Animation-Support
   bleibt sichtbar, siehe Kommentar bei .kopf__innen. */
.hero__intro > * {
  animation-name: kopf-pop; animation-duration: var(--d4);
  animation-timing-function: var(--ease); animation-fill-mode: both;
}
.hero__intro > *:nth-child(1) { animation-delay: 0ms; }
.hero__intro > *:nth-child(2) { animation-delay: var(--d1); }
.hero__intro > *:nth-child(3) { animation-delay: var(--d2); }
.hero__intro > *:nth-child(4) { animation-delay: var(--d3); }
.hero__intro > .hero__titel {
  animation-name: kopf-pop, text-gewicht;
  animation-duration: var(--d4), var(--d5);
  animation-timing-function: var(--ease), var(--ease);
  animation-fill-mode: both, both;
}
.hero__hinweis {
  animation-name: kopf-pop; animation-duration: var(--d4);
  animation-timing-function: var(--ease); animation-fill-mode: both;
  animation-delay: var(--d4);
}

@keyframes mockup-pop {
  from { opacity: 0; transform: scale(.85) translateY(var(--s5)) rotate(-1.5deg); }
  to   { opacity: 1; transform: scale(1) translateY(0) rotate(-1.5deg); }
}
.mockup {
  background: var(--tinte); border-radius: var(--r-l);
  padding: var(--s2); box-shadow: 0 var(--s4) var(--s6) -20px rgb(43 32 22 / .35);
  transform: rotate(-1.5deg);
  animation-name: mockup-pop; animation-duration: var(--d4);
  animation-timing-function: var(--ease); animation-fill-mode: both;
  animation-delay: var(--d2);
}
.mockup__leiste {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3);
}
.mockup__punkt { width: 10px; height: 10px; border-radius: 50%; background: var(--tinte-mute); }
.mockup__url {
  margin-inline-start: var(--s3);
  font-size: var(--t-xs); color: var(--grund-tief);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mockup__glas {
  aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--r-m);
  background: var(--tinte);
}
.mockup__video { width: 100%; height: 100%; object-fit: cover; }
.mockup__reiter {
  display: flex; gap: var(--s2); padding: var(--s3) var(--s2) var(--s2);
}
.reiter {
  flex: 1; padding: var(--s2) var(--s3); border-radius: var(--r-pille);
  font-family: var(--display); font-weight: 600; font-size: var(--t-xs);
  color: var(--grund-tief); border: 2px solid transparent;
  transition: background var(--d2) var(--ease), color var(--d2) var(--ease), border-color var(--d2) var(--ease);
}
.reiter[aria-selected="true"] { background: var(--akzent); color: var(--tinte); border-color: var(--akzent); }

/* ------------------------------------------------------------- Raster */

.lage { padding-block: var(--s7); scroll-margin-top: var(--s7); }
.lage--tief { background: var(--grund-tief); }

.raster {
  max-width: 1180px; margin-inline: auto; padding-inline: var(--edge);
  display: grid; gap: var(--s6);
}
@media (min-width: 900px) { .raster { grid-template-columns: var(--spur); } }

/* ------------------------------------------------------------ Karten */

.karten {
  margin-block-start: var(--s6);
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.karte {
  background: var(--grund-hi); border-radius: var(--r-m);
  padding: var(--s5); border: 2px solid var(--grund-tief);
}
.karte__h { font-family: var(--display); font-weight: 700; font-size: var(--t-m); margin-block-end: var(--s2); }
.karte__t { color: var(--tinte-mute); }

/* "Warum wir": Bento-Raster statt Gleichverteilung, Glas statt Flachfarbe —
   nur diese vier Karten, "Leistungen" bleibt bei .karten unverändert.
   Glas braucht Kontur zum Durchscheinen: weiche Flecken hinter der Sektion. */
#warum-wir { position: relative; overflow: hidden; }
#warum-wir::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(circle at 18% 15%, color-mix(in oklab, var(--akzent) 32%, transparent) 0%, transparent 42%),
    radial-gradient(circle at 82% 65%, color-mix(in oklab, var(--gas) 28%, transparent) 0%, transparent 42%);
}
#warum-wir > .mitte, #warum-wir > .karten { position: relative; z-index: 1; }
#warum-wir .karte {
  background: color-mix(in oklab, var(--grund-hi) 55%, transparent);
  backdrop-filter: blur(14px) saturate(1.3); -webkit-backdrop-filter: blur(14px) saturate(1.3);
  border-color: color-mix(in oklab, var(--grund-hi) 70%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in oklab, white 55%, transparent);
}
/* Kippkarte: main.js setzt --kipp-x/--kipp-y per mousemove, nur bei
   hover:hover+pointer:fine und ohne reduced-motion (siehe main.js) —
   ohne JS bleibt die Karte flach, kein toter Zustand. */
@media (hover: hover) and (pointer: fine) {
  #warum-wir .karte {
    --kipp-x: 0deg; --kipp-y: 0deg;
    transform: perspective(800px) rotateX(var(--kipp-x)) rotateY(var(--kipp-y));
    transition: transform var(--d3) var(--ease);
  }
}
@media (min-width: 900px) {
  #warum-wir .karten { grid-template-columns: repeat(6, 1fr); }
  #warum-wir .karte:nth-child(1) { grid-column: span 4; }
  #warum-wir .karte:nth-child(2) { grid-column: span 2; }
  #warum-wir .karte:nth-child(3) { grid-column: span 2; }
  #warum-wir .karte:nth-child(4) { grid-column: span 4; }
}

/* ------------------------------------------------------------ Portfolio */

.werke { margin-block-start: var(--s6); }

/* Jede Karte eine eigene Pin-Bühne, wie der Hero (Entscheidung Danja,
   16.09.2026 — "gestapelt, volle Bühne pro Karte"). Gleiche Technik wie
   assets/js/scrub.js: IntersectionObserver an/aus, rAF liest die Position
   jedes Bild frisch, kein scroll-Listener. --werk-buehne-h einheitlich
   wie .hero (300vh), fürs gleiche Scrub-Tempo sitework. */
.werk-buehne { position: relative; height: 300vh; }
.werk-buehne--still { height: auto; }
.werk-buehne + .werk-buehne { margin-block-start: var(--s6); }
.werk-buehne--still + .werk-buehne--still { margin-block-start: var(--s7); }

.werk-stage {
  position: sticky; top: 0; min-height: 100vh;
  display: grid; grid-template-columns: 1fr; align-items: center;
  gap: var(--s6); padding-block: var(--s6);
  overflow: hidden;
}
.werk-buehne--still .werk-stage { position: static; }
/* Gleicher Grund wie bei .hero__stage: Mockup zuerst, Info-Text danach,
   sonst ist das Video mobil erst nach halbem Scrub-Fortschritt sichtbar. */
@media (max-width: 899px) {
  .werk__mockup { order: -1; }
}
@media (min-width: 900px) {
  .werk-stage { grid-template-columns: var(--spur); }
}

.werk-info { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); }
.werk__marke {
  padding: var(--s1) var(--s2); border-radius: var(--r-pille);
  background: var(--grund-tief); color: var(--tinte-mute);
  font-size: var(--t-xs); font-family: var(--display); font-weight: 600;
}
.werk__h { font-family: var(--display); font-weight: 700; font-size: var(--t-l); }
.werk__t { color: var(--tinte-mute); }
.werk__link { display: inline-flex; align-items: center; gap: var(--s1); color: var(--gas); font-weight: 700; font-size: var(--t-s); margin-block-start: var(--s2); }
.werk__link svg { width: 1em; height: 1em; }
.werk__link--offen { color: var(--tinte-mute); font-weight: 600; font-style: italic; cursor: default; }

/* Videorahmen: dieselbe Optik wie .mockup, eigene Klasse statt Wiederverwendung
   — .mockup trägt die Fade-Pop-Ladeanimation, die hier ungesehen abliefe
   (Portfolio-Bühnen liegen beim Laden außerhalb des Viewports). Versatz-Kontur
   wie zuvor bei den Karten, jetzt hier als Markenzeichen der Bühne. */
.werk__mockup {
  background: var(--tinte); border-radius: var(--r-l);
  padding: var(--s2); box-shadow: 0 var(--s4) var(--s6) -20px rgb(43 32 22 / .35), 6px 6px 0 0 var(--akzent-lite);
  transform: rotate(1deg);
}
.werk-buehne:nth-child(even) .werk__mockup { transform: rotate(-1deg); }
.werk__glas {
  aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--r-m); background: var(--tinte);
}
.werk__video { width: 100%; height: 100%; object-fit: cover; }

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

.kontakt {
  margin-block-start: var(--s6);
  background: var(--tinte); color: var(--grund);
  border-radius: var(--r-l); padding: var(--s6) var(--s5);
  display: grid; gap: var(--s4);
}
.kontakt .h2 { color: var(--grund); }
.kontakt .fliess { color: var(--grund-tief); }
.kontakt__reihe { display: flex; flex-wrap: wrap; gap: var(--s3); margin-block-start: var(--s3); }
.kontakt .knopf--voll { color: var(--tinte); }
.kontakt .knopf--ghost { border-color: var(--grund); color: var(--grund); --knopf-ghost-fill: color-mix(in oklab, var(--grund) 12%, transparent); }
.kontakt__adresse { font-size: var(--t-xs); color: var(--grund-tief); }

/* --------------------------------------------------------------- Fuß */

.fuss { padding-block: var(--s6); border-block-start: 2px solid var(--grund-tief); }
.fuss__innen {
  max-width: 1180px; margin-inline: auto; padding-inline: var(--edge);
  display: flex; flex-wrap: wrap; gap: var(--s3);
  align-items: center; justify-content: space-between;
  font-size: var(--t-xs); color: var(--tinte-mute);
}
.fuss__links { display: flex; gap: var(--s4); }

/* ------------------------------------------------------ Rechtstexte */

.rechtstext {
  max-width: 72ch; margin-inline: auto; padding: var(--s7) var(--edge) var(--s8);
}
.rechtstext h1 { font-family: var(--display); font-weight: 700; font-size: var(--t-l); margin-block-end: var(--s5); }
.rechtstext h2 { font-family: var(--display); font-weight: 700; font-size: var(--t-m); margin-block: var(--s6) var(--s2); }
.rechtstext p, .rechtstext li { color: var(--tinte-mute); margin-block-end: var(--s3); }
.rechtstext a { color: var(--gas); text-decoration: underline; text-underline-offset: 2px; }
.rechtstext ul { list-style: disc; padding-inline-start: var(--s4); }
.rechtstext__hinweis { margin-block-start: var(--s6); font-size: var(--t-xs); }

/* Augenbraue auf dunklem Grund (Kontakt-Karte) statt auf hellem --grund */
.augenbraue--hell { color: var(--gas-lite); }

/* --------------------------------------------------------- Anfrage-Formular */
/* anfrage.html, seit 16.09.2026 — läuft ohne eigenen Server über Web3Forms
   (fetch in main.js), kein neuer Next.js-Build nötig. Honeypot-Feld .hp
   statt Inline-Style, damit die CSP ohne 'unsafe-inline' auskommt. */

.rechtstext .formular { max-width: 62ch; display: grid; gap: var(--s5); margin-block-start: var(--s6); }
.feld { display: grid; gap: var(--s2); }
.feld label { font-family: var(--display); font-weight: 600; font-size: var(--t-s); }
.feld input, .feld textarea {
  font: inherit; font-size: var(--t-m); color: var(--tinte);
  background: var(--grund-hi); border: 2px solid var(--grund-tief);
  border-radius: var(--r-m); padding: var(--s3); min-height: 44px;
  transition: border-color var(--d2) var(--ease);
}
.feld textarea { min-height: 144px; resize: vertical; }
.feld input:focus-visible, .feld textarea:focus-visible { outline: 3px solid var(--akzent); outline-offset: 2px; border-color: var(--akzent); }
.hp { position: absolute; left: -9999px; }

.budget__optionen { display: grid; gap: var(--s2); }
.budget__stufe {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-m); border: 2px solid var(--grund-tief);
  background: var(--grund-hi); cursor: pointer;
  transition: border-color var(--d2) var(--ease), background var(--d2) var(--ease);
}
.budget__stufe input { accent-color: var(--akzent); width: 20px; height: 20px; flex-shrink: 0; }
.budget__stufe:has(input:checked) {
  border-color: var(--akzent);
  background: color-mix(in oklab, var(--akzent-lite) 25%, var(--grund-hi));
}

.formular__hinweis { font-size: var(--t-xs); color: var(--tinte-mute); }
.formular__status { font-size: var(--t-s); font-weight: 600; min-height: 1.5em; }
.formular__status[data-state="ok"] { color: var(--gas); }
.formular__status[data-state="error"] { color: var(--akzent); }

/* Lade-Bühne — Visitenkarten-Artefakt (https://claude.ai/artifact/Sb4wHpyLw5dXjN8FF2MQsq),
   in den hellen Farben und mit der echten Fredoka/Nunito-Schrift der Seite
   statt Gold/Bodoni Moda des Artefakts. Reines CSS, kein JS (gleiches
   Muster wie kopf-pop/mockup-pop): Karte blendet sich per @keyframes
   selbst ein und nach 1,1 s wieder aus (animation-fill-mode: forwards).
   Ohne Animation-Unterstützung bleibt die Karte stehen, statt die Seite
   dauerhaft zu verdecken — deshalb unter reduzierter Bewegung nicht
   einfach "animation: none", sondern explizit ausgeblendet, das ist
   hier der sichere Grundzustand, nicht der unsichtbare.

   pointer-events: none von Anfang an (Danja, iPhone/Safari, 17.09.2026:
   Klick auf den Dunkelmodus-Hinweis tat nichts). Grund: `visibility`
   ist bei @keyframes ein diskreter Wert, der erst bei 100% der Laufzeit
   kippt — die letzte Strecke des Fade-outs ist optisch fast weg, aber
   `.lade` liegt mit pointer-events:auto (Default) noch komplett über
   der Seite und schluckt genau in dem Moment jeden Tap, in dem der
   Inhalt schon sichtbar aussieht. Gemessen per elementFromPoint, nicht
   vermutet: traf `.lade` statt den Link darunter. */
.lade {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  background: var(--grund);
  pointer-events: none;
  animation-name: lade-weg; animation-duration: var(--d5);
  animation-timing-function: var(--ease); animation-fill-mode: forwards;
  animation-delay: 1.1s;
}
@keyframes lade-weg { to { opacity: 0; visibility: hidden; } }
.lade__karte {
  position: relative; display: grid; place-items: center; gap: var(--s2);
  width: min(300px, 80vw); height: 200px; border-radius: var(--r-l);
  background: var(--grund-hi);
  box-shadow: 0 20px 40px rgba(43, 32, 22, .12);
}
.lade__rahmen {
  position: absolute; inset: 0; border: 2px solid var(--akzent);
  border-radius: var(--r-m); opacity: 0; transform: rotate(6deg);
  animation-name: lade-rahmen; animation-duration: var(--d5);
  animation-timing-function: var(--ease); animation-fill-mode: forwards;
  animation-delay: var(--d1);
}
@keyframes lade-rahmen { to { inset: 14px; opacity: 1; transform: rotate(0); } }
.lade__wort {
  font-family: var(--display); font-weight: 700; font-size: var(--t-l);
  color: var(--tinte);
  animation-name: lade-wort; animation-duration: var(--d5);
  animation-timing-function: var(--ease); animation-fill-mode: forwards;
  animation-delay: var(--d1);
}
@keyframes lade-wort { to { transform: translateY(-6px); } }
.lade__wort em { font-style: italic; color: var(--akzent); }
.lade__motto {
  font-family: var(--text); font-size: var(--t-xs); letter-spacing: .04em;
  color: var(--tinte-mute); opacity: 0;
  animation-name: lade-motto; animation-duration: var(--d5);
  animation-timing-function: var(--ease); animation-fill-mode: forwards;
  animation-delay: var(--d2);
}
@keyframes lade-motto { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .lade { animation: none; opacity: 0; visibility: hidden; }
  .lade__rahmen, .lade__wort, .lade__motto { animation: none; }
}
