/* =========================================================
   MOVE2 — "Neon Blueprint" design system
   Static site. No framework, no build step.
   Sections:
   1. Fonts & tokens        11. Trust bar & floating badges
   2. Reset & base           12. Section head
   3. Layout utilities       13. Diff / before-after
   4. Buttons                14. Service list
   5. Icons                  15. Chip row (Branchen)
   6. Nav                    16. Process list
   7. Blueprint background   17. Word-reveal line
   8. Scroll progress bar    18. Demo / referenzen cards
   9. Hero                   19. Pricing cards
   10. Live Build panel      20. FAQ accordion
                             21. CTA band
                             22. Footer
                             23. Legal / todo-note
                             24. Forms (Kontakt)
                             25. Scroll reveal
                             26. Responsive
                             27. Reduced motion
                             28. Prozess-Schritte
                             29. Leistungs-Abschnitte
                             30. Oberflächen-Ebenen + Nähte
                             31. Fokus-Ring (generisch)
                             32. Team-Sektion
                             33. Mobile Kontaktleiste
   ========================================================= */

/* ---------------------------------------------------------
   1. Fonts & tokens
--------------------------------------------------------- */
/* Schriften kommen lokal aus assets/fonts/, NICHT mehr von fonts.googleapis.com.
   Grund: jede Verbindung zu Google beim Seitenaufruf überträgt die IP des
   Besuchers, in Deutschland ein bekanntes DSGVO-Thema, und die Regeln in
   claude.md-files verlangen ausdrücklich "Web-Fonts lokal gehostet".
   Wer hier wieder einen externen @import einsetzt, macht die Seite
   einwilligungspflichtig. Herkunft und Lizenzen: assets/fonts/README.md */
@import url('../fonts/fonts.css');

:root{
  /* base — Farbschema von Test Webseite 1 übernommen (siehe CLAUDE.md) */
  --bg: #07090D;
  --bg-2: #0A0D13;
  --surface: #11151D;
  --elevated: #161B25;

  /* text */
  --text: #EEF1F6;
  --text-2: #B4BCCB;
  --text-3: #8A93A6; /* war #7C8598 — riss auf --surface-raised mit 4.28:1, jetzt 5.14:1. Auf --surface-deep 6.46:1, weiterhin dezent genug für Fußnoten-Text. */

  /* accent — v1s zurückhaltendes Indigo statt Neon-Teal/Violet */
  --accent: #8B93FF;
  --accent-rgb: 139,147,255;
  --accent-2: #B28EFF;
  --accent-2-rgb: 178,142,255;

  /* diff — bleiben rot/grün, semantisch unabhängig vom Markenakzent */
  --diff-add: #34D399;
  --diff-remove: #FB7185;

  /* Oberflächen-Ebenen (Redesign-Pass: Sektionen voneinander abheben) */
  --surface-deep: #07090D;    /* = --bg, unverändert, Raster bleibt sichtbar */
  --surface-raised: #1B2233;  /* deckend, blockt das Raster */
  --surface-light: #A2AEDE;   /* deckend, vierte Verdunklungsstufe auf Kundenwunsch (war #B0BDEE) */

  /* Textfarben ausschließlich für die direkte Prosa auf surface-light —
     bewusst eigene Namen statt --text/--accent lokal zu überschreiben,
     s. CLAUDE.md: eingebettete dunkle Karten (.price-card, .talk-bubble …)
     sollen dunkle Inseln bleiben und dürfen NICHT mitkippen.
     Werte gegen die reale --surface-light gemessen (sRGB relative
     luminance) — bei jeder weiteren Verdunklung von --surface-light hier
     neu nachmessen, die Marge wird mit jeder Stufe kleiner. */
  --ink: #14151D;        /* 8.35:1 auf --surface-light (gemessen) */
  --ink-2: #2C2F3C;      /* 6.11:1 — klar dunkler als zuvor (#484B5D war nur 4.66:1, Fließtext auf dem hellen Blau schwer lesbar) */
  --accent-ink: #2E2680; /* 5.66:1 auf --surface-light, 5.05:1 auf der getönten compare-Spalte (war #4337B4) */
  /* --ink-3 entfernt (Pass 3, Teil A1): war #494C5F, nur 1 Hex-Schritt von
     --ink-2 entfernt, keine echte dritte Stufe. Alle vier Verwendungen
     (.lcaption, .price-note, .concept-label, .compare-hint) laufen jetzt
     über --ink-2. Falls hier wieder eine dritte, sichtbar hellere/dunklere
     Stufe gebraucht wird: neu und mit echtem Abstand ansetzen, nicht
     denselben Fehler wiederholen. */

  --slant: clamp(2.5rem, 5vw, 4.5rem);

  /* structure */
  --border: rgba(238,241,246,.10);
  --border-strong: rgba(238,241,246,.18);
  --grid-line: rgba(139,147,255,.08);

  /* Glas — nur für die Buttons (Abschnitt 4), 1:1 aus v1 übernommen */
  --glass: rgba(255,255,255,0.055);
  --blur: 16px;
  --hairline: rgba(255,255,255,0.075);
  --hairline-strong: rgba(255,255,255,0.14);
  --r-full: 999px;
  --p-cyan: 120,225,255;
  --p-blue: 122,162,255;
  --p-violet: 178,142,255;
  --p-pink: 255,158,206;

  /* fonts */
  --font-display: "Space Grotesk", "Segoe UI", sans-serif;
  --font-body: "Manrope", "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", "Consolas", monospace;
  --font-accent: "Instrument Serif", Georgia, serif;

  /* motion */
  --ease: cubic-bezier(.22,1,.36,1);
  --ease-out: cubic-bezier(.16,1,.3,1);
  --t-fast: 160ms;
  --t-med: 320ms;
  --t-slow: 640ms;

  --radius: 14px;
  --radius-sm: 8px;
  --container: 1240px;
}

/* ---------------------------------------------------------
   2. Reset & base
--------------------------------------------------------- */
*, *::before, *::after{ box-sizing: border-box; margin: 0; padding: 0; }

html{
  background: var(--bg);
  scroll-behavior: smooth;
  /* Reserviert die Breite der Scrollbar dauerhaft (auf fast jeder Seite hier
     ohnehin da, da die Seiten höher als der Viewport sind). Dadurch springt
     nichts, wenn das mobile Menü den Hintergrund per .nav-locked sperrt. */
  scrollbar-gutter: stable;
  /* Blaues Antipp-Rechteck auf Mobile/WebKit weg. Kein Ersatz für Fokus:
     Tastaturnutzer bekommen ihren Ring weiterhin über :focus-visible unten,
     das hier betrifft ausschliesslich die Touch-Antipp-Markierung. */
  -webkit-tap-highlight-color: transparent;
}
a, button, [role="button"], input, select, textarea, label, summary{
  -webkit-tap-highlight-color: transparent;
}
.nav-locked{ overflow: hidden; }
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
}

/* Ersatz-Feedback fürs fehlende Antipp-Rechteck: dezentes Abdunkeln beim
   Drücken. .btn ausgenommen -- die Glas-Buttons haben mit
   .btn-wrap:active .btn{ transform: scale(.985) } (Abschnitt 4) bereits ihr
   eigenes Press-Feedback, zusätzliches Abdunkeln würde sich damit beißen. */
a:not(.btn):active, button:not(.btn):active, [role="button"]:not(.btn):active, summary:active{
  opacity: .72;
  transition: opacity 100ms var(--ease);
}

body{
  background: transparent; /* html carries the background — see CLAUDE.md */
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  position: relative;
}

img, svg, canvas{ display: block; max-width: 100%; }
a{ color: inherit; text-decoration: none; }
ul, ol{ list-style: none; }
button{ font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, textarea{ font: inherit; color: inherit; background: none; border: 0; }

h1, h2, h3, h4{
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.02em;
  hyphens: auto;
  overflow-wrap: break-word;
}
h1{ font-size: clamp(2.6rem, 5vw + 1rem, 4.6rem); font-weight: 700; }
h2{ font-size: clamp(1.9rem, 2.6vw + 1rem, 2.9rem); }
h3{ font-size: 1.25rem; }

p{ color: var(--text-2); }
.lede{ font-size: 1.15rem; color: var(--text-2); max-width: 46ch; }
.prose-link{ color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

.grad-word{
  background: linear-gradient(100deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.accent-serif{
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  letter-spacing: 0;
}

/* ---------------------------------------------------------
   3. Layout utilities
--------------------------------------------------------- */
/* Ankerziele der Startseite (Leistungen/Prozess/Referenzen/Preise):
   Abstand zur festen Nav, damit die Überschrift beim Sprung nicht
   darunter verschwindet. */
#leistungen, #prozess, #referenzen, #preise{ scroll-margin-top: 84px; }
.container{ max-width: var(--container); margin-inline: auto; padding-inline: 1.5rem; }
main > section{ --section-pad: clamp(4rem, 8vw, 7rem); padding-block: var(--section-pad); }
.split-head{ display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 4vw, 4rem); align-items: center; }

/* ---------------------------------------------------------
   4. Buttons — Glaskörper, 1:1 aus Test Webseite 1 übernommen
   (deren CLAUDE.md, Abschnitt "Glass buttons"). Vierschichtiger Aufbau,
   bewusst nicht zusammengelegt:

     .btn-wrap        Positionsrahmen, isoliert den Stapel
       .btn           der Glaskörper (backdrop-filter, volle Rundung)
         ::before     spektraler Kantenring (wandert langsam, @property)
         ::after      wandernde Lichtwelle beim Hover
         .btn-text    Beschriftung — bleibt hier im Mono-Font der Seite,
           ::before   Glanzlicht in der oberen Hälfte     das ist bewusst
       .btn-shadow    Schlagschatten als EIGENES Element  keine v1-Kopie

   .btn-shadow liegt bewusst nicht als box-shadow am Button: zusammen mit
   backdrop-filter gibt das Artefakte an der Rundung, und als eigene,
   frei weichgezeichnete Ebene kann der Schatten beim Hover unabhängig
   vom Glaskörper wandern. JEDER Button braucht darum die volle Struktur
   `<span class="btn-wrap"><a class="btn ..."><span class="btn-text">…</span></a><span class="btn-shadow" aria-hidden="true"></span></span>` —
   ein bloßes `<a class="btn">` verliert Glanz, Schatten und Rand.
--------------------------------------------------------- */
@property --shine-angle{
  syntax: '<angle>';
  initial-value: 135deg;
  inherits: false;
}
@keyframes rimLight{ to{ --shine-angle: 495deg; } }

/* align-self: flex-start verhindert, dass .btn-wrap sich in einem
   Flex-Column-Elternteil (z. B. .price-card, .contact-form) auf dessen
   volle Breite streckt — sonst berechnet .btn-shadow seine prozentualen
   Insets von dieser zu breiten Box statt vom sichtbaren Button, und der
   Schatten sitzt größer und versetzt neben statt hinter dem Button. */
.btn-wrap{ display: inline-flex; align-self: flex-start; position: relative; isolation: isolate; border-radius: var(--r-full); }

.btn{
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  border-radius: var(--r-full);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.btn:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }

/* Spektrale Kante — dieselbe Mask-Composite-Technik wie in v1 */
.btn::before{
  content: '';
  position: absolute; inset: 0; z-index: 1;
  border-radius: inherit;
  padding: 1px;
  pointer-events: none;
  background: linear-gradient(var(--shine-angle),
    rgba(255,255,255,0.70) 0%,
    rgba(var(--p-cyan),   0.55) 16%,
    rgba(255,255,255,0.10) 32%,
    rgba(var(--p-violet), 0.52) 50%,
    rgba(var(--p-pink),   0.40) 64%,
    rgba(255,255,255,0.14) 80%,
    rgba(var(--p-blue),   0.50) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  opacity: .55;
  transition: opacity var(--t-med) var(--ease);
  animation: rimLight 22s linear infinite;
}
.btn:hover::before{ opacity: 1; }

/* Lichtwelle beim Hover */
.btn::after{
  content: '';
  position: absolute; inset: -1px; z-index: 2;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(105deg,
    transparent 32%,
    rgba(255,255,255,0.34) 43%,
    rgba(var(--p-cyan),  0.26) 47%,
    rgba(var(--p-violet),0.24) 51%,
    rgba(var(--p-pink),  0.20) 55%,
    transparent 68%);
  transform: translateX(-115%);
  opacity: 0;
  transition: transform 980ms cubic-bezier(.38,.12,.32,1), opacity var(--t-med) var(--ease);
}
.btn:hover::after{ transform: translateX(115%); opacity: 1; }

.btn-text{
  position: relative;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  padding: .85rem 1.5rem;
  font-family: var(--font-mono);
  font-size: .9rem;
  font-weight: 500;
  letter-spacing: -0.01em;
}
/* Glanzlicht in der oberen Hälfte, hinter der Schrift */
.btn-text::before{
  content: '';
  position: absolute; inset: 1px 1px 42% 1px; z-index: -1;
  border-radius: var(--r-full);
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,0.30), rgba(255,255,255,0));
  opacity: .7;
  transition: opacity var(--t-med) var(--ease);
}
.btn:hover .btn-text::before{ opacity: 1; }

/* Schlagschatten als eigenes, frei bewegliches Element */
/* Pass 3, Teil C: war eine inset+filter-Transition. inset ist ein Layout-
   Shorthand (top/right/bottom/left) und filter zählt explizit zu den
   verbotenen Properties — beide erzwingen Layout- bzw. teure Paint-Arbeit,
   auf JEDEM Button der Seite bei jedem Hover. Jetzt fester Blur (Mittelwert
   der alten zwei Werte), das Wachsen/Sinken kommt aus scaleX + translateY,
   beides reine Compositor-Arbeit. Die Zielgeometrie (94% Breite, 8% tiefer)
   ist aus den alten inset-Werten zurückgerechnet, sieht also identisch aus. */
.btn-shadow{
  position: absolute; z-index: -1;
  inset: 14% 6% -14% 6%;
  border-radius: var(--r-full);
  background: rgba(0,0,0,.6);
  filter: blur(17px);
  opacity: .7;
  pointer-events: none;
  transform: translateY(0) scaleX(1);
  transition: transform var(--t-med) var(--ease), opacity var(--t-med) var(--ease);
}
.btn-wrap:hover .btn-shadow{ transform: translateY(8%) scaleX(1.07); opacity: .85; }
.btn-wrap:hover .btn{ transform: translateY(-2px); }
.btn-wrap:active .btn{ transform: translateY(0) scale(.985); }

/* primär: heller Glaskörper, auf Dunkel ist Licht der Kontrastanker */
.btn-primary{
  background: linear-gradient(180deg, rgba(255,255,255,.97) 0%, rgba(223,229,240,.9) 100%);
  backdrop-filter: blur(12px) saturate(180%);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,1), inset 0 -1px 1px rgba(140,150,175,.35);
}
.btn-primary .btn-text{ color: #080A0F; font-weight: 600; }
.btn-primary .btn-text::before{ background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,0)); }
.btn-wrap:hover .btn-primary{ background: linear-gradient(180deg, #fff 0%, rgba(232,237,246,.95) 100%); }
.btn-wrap:hover .btn-primary ~ .btn-shadow{ background: rgba(150,165,220,.45); }

/* sekundär: dunkles Glas, zurückhaltender */
.btn-ghost{
  background: var(--glass);
  backdrop-filter: blur(var(--blur)) saturate(170%) brightness(1.1);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(170%) brightness(1.1);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), inset 0 0 0 1px var(--hairline);
}
.btn-ghost .btn-text{ color: var(--text); }
.btn-wrap:hover .btn-ghost{ background: rgba(255,255,255,.1); }

.btn-sm .btn-text{ padding: .6rem 1.1rem; font-size: .82rem; }
.btn-lg .btn-text{ padding: 1.05rem 1.9rem; font-size: 1rem; }

@media (prefers-reduced-motion: reduce){
  .btn::before{ animation: none; }
}

/* ---------------------------------------------------------
   5. Icons
--------------------------------------------------------- */
.icon-svg{ width: 20px; height: 20px; flex-shrink: 0; }

/* ---------------------------------------------------------
   6. Nav
--------------------------------------------------------- */
.nav-shell{
  position: sticky; top: 0; z-index: 65;
  /* Höher als .nav-sheet (z-index 60): sonst deckt das geöffnete Mobile-Menü
     die Kopfzeile samt Burger/X-Button komplett zu und lässt sich nicht mehr
     schließen (genau das war auf Android der Fall, s. Mobile-Optimierung). */
  /* Fest statt beim Scrollen zu schrumpfen (Pass 3, Teil C): das schrumpfte
     vorher per padding-Transition, eine der explizit verbotenen Layout-
     Properties, bei jedem Über-/Unterschreiten der Scroll-Schwelle. Nav
     bleibt jetzt bei konstanter Höhe, nur Hintergrund/Rahmen blenden noch
     ein — beides unverändert erlaubt, da reine Paint-Properties. */
  padding-block: .9rem;
  transition: background var(--t-med) var(--ease), border-color var(--t-med) var(--ease);
  border-bottom: 1px solid transparent;
}
/* Am Seitenanfang ist der Nav transparent (Hintergrund kommt erst mit
   .is-scrolled) — genau dort liegt aber die Shader-Fahne dahinter. Derselbe
   Verlauf wie unter dem Hero, nur weiter nach rechts gezogen, weil die Nav-
   Zeile näher am hellen Kern sitzt. Über den Links bleibt die Deckkraft nicht
   unter .70; damit halten sie selbst im hellstmöglichen Frame des Rauschens
   6.1:1 (gerechnet gegen die hellste Farbe, die der Shader ausgeben kann).
   Rechts läuft er aus: dort steht nur der deckende "Projekt starten"-Button. */
.nav-shell::before{
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(100deg,
    rgba(7,9,13,.95) 0%,
    rgba(7,9,13,.92) 45%,
    rgba(7,9,13,.72) 66%,
    rgba(7,9,13,0) 88%);
}
.nav-shell.is-scrolled{
  background: rgba(7,11,13,.82);
  border-bottom-color: var(--border);
}
.nav{ max-width: var(--container); margin-inline: auto; padding-inline: 1.5rem; display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; }

.brand{ display: inline-flex; align-items: center; gap: .55rem; }
/* Neues MOVE2-Logo (weiss/transparentes PNG, nur auf dunklem Grund verwendet).
   Nav: M2-Monogramm + Firmenname als Text. Footer: das gestapelte Logo mit Schriftzug. */
.brand-logo{ height: 30px; width: auto; display: block; }
.brand-lockup{ height: 46px; width: auto; display: block; }
.brand-name{
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
  letter-spacing: .04em; color: var(--text); line-height: 1; white-space: nowrap;
}

.nav-links{ display: flex; align-items: center; gap: 2rem; }
.nav-links a{ font-size: .92rem; color: var(--text-2); position: relative; transition: color var(--t-fast) var(--ease); }
.nav-links a::after{
  content:""; position: absolute; left: 0; right: 0; bottom: -6px; height: 1px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-med) var(--ease-out);
}
.nav-links a:hover{ color: var(--text); }
.nav-links a:hover::after{ transform: scaleX(1); }

.nav-right{ display: flex; align-items: center; gap: 1rem; }

/* Preis-Chip in der Kopfzeile, nur Mobil (index.html) -- am Desktop gibt es
   dafür bereits den Nav-Punkt "Preise". Bleibt visuell klein/kompakt (soll
   nicht auffälliger als das Logo wirken); die geforderte 44×44px-Trefferfläche
   kommt über ein unsichtbares ::before, nicht über die sichtbare Chip-Größe
   selbst (gleiches Muster wie beim Vorher/Nachher-Griff). */
.nav-price-chip{
  display: none; /* per Media Query unten eingeblendet */
  position: relative;
  align-items: center;
  flex-shrink: 0;
  padding: .35rem .7rem;
  border-radius: var(--r-full);
  border: 1px solid rgba(var(--accent-rgb), .4);
  background: rgba(var(--accent-rgb), .12);
  color: var(--accent);
  font-family: var(--font-mono); font-size: .74rem; font-weight: 600;
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.nav-price-chip::before{
  content: ""; position: absolute; inset: 50% auto auto 50%;
  transform: translate(-50%, -50%);
  width: max(100%, 44px); height: max(100%, 44px);
}
.nav-price-chip:hover{ background: rgba(var(--accent-rgb), .2); border-color: rgba(var(--accent-rgb), .6); }
.nav-price-chip .npc-short{ display: none; }
@media (max-width: 768px){
  .nav-price-chip{ display: inline-flex; }
}
/* Ab hier reicht der Platz neben Logo und Burger nicht mehr für "ab 990 €" --
   kürzerer Chip-Text, ohne dass Logo/Burger gequetscht werden. */
@media (max-width: 380px){
  .nav-price-chip{ padding: .35rem .55rem; }
  .nav-price-chip .npc-full{ display: none; }
  .nav-price-chip .npc-short{ display: inline; }
}

.nav-burger{ display: none; position: relative; width: 24px; height: 18px; }
.nav-burger i, .nav-burger i::before, .nav-burger i::after{
  content:""; position: absolute; left: 0; right: 0; height: 2px; background: var(--text);
  transition: transform var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
.nav-burger i{ top: 8px; }
.nav-burger i::before{ top: -8px; }
.nav-burger i::after{ top: 8px; }
.nav-burger[aria-expanded="true"] i{ background: transparent; }
.nav-burger[aria-expanded="true"] i::before{ transform: translateY(8px) rotate(45deg); }
.nav-burger[aria-expanded="true"] i::after{ transform: translateY(-8px) rotate(-45deg); }

.nav-sheet{
  position: fixed; inset: 0; z-index: 60;
  /* Overlay statt Ersatz: die Seite bleibt durch Verdunkelung + Weichzeichner
     hindurch schemenhaft sichtbar, statt komplett durch eine deckende Fläche
     ersetzt zu wirken (das las sich auf Android wie ein Seitenwechsel). */
  background: rgba(7,9,13,.55);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 1.6rem;
  padding: 2rem 1.75rem;
  transform: translateY(-8px) scale(.98);
  opacity: 0; visibility: hidden;
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease), visibility var(--t-med);
}
.nav-sheet.is-open{ opacity: 1; visibility: visible; transform: translateY(0) scale(1); }
.nav-sheet a{ font-family: var(--font-display); font-size: 1.6rem; font-weight: 600; }
/* Damit die Links auf dem jetzt durchscheinenden, unruhigen Hintergrund
   trotzdem sicher lesbar bleiben, auch mitten in einer Verlaufsfarbe. */
.nav-sheet a{ text-shadow: 0 2px 16px rgba(7,9,13,.6); }

/* ---------------------------------------------------------
   7. Blueprint background — Shader-Fahne + CSS-Raster + Circuit-Canvas

   Drei gestapelte Ebenen, von hinten nach vorn:
     -3  .hero-shader    WebGL-Plasma, nur oben, scrollt mit (absolute)
     -2  .blueprint-grid Rasterlinien, fix im Viewport
     -1  .circuit-canvas driftende Knotenpunkte, fix im Viewport
   Der Shader ist deckend und trifft in den dunklen Zonen exakt --bg, deshalb
   entsteht an seiner Unterkante trotz Maske keine sichtbare Naht.
--------------------------------------------------------- */
.hero-shader{
  position: absolute; top: 0; left: 0;
  width: 100%; height: 118vh;
  z-index: -3; pointer-events: none;
  mask-image: linear-gradient(to bottom, #000 0%, #000 48%, transparent 97%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 48%, transparent 97%);
}

.blueprint-grid{
  position: fixed; inset: 0; z-index: -2; overflow: hidden; pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, var(--grid-line) 0 1px, transparent 1px 88px),
    repeating-linear-gradient(0deg, var(--grid-line) 0 1px, transparent 1px 88px);
  mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, black 40%, transparent 90%);
}

.circuit-canvas{
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: .55;
}

/* ---------------------------------------------------------
   8. Scroll progress bar
--------------------------------------------------------- */
/* Reiner Positionsrahmen, unskaliert -- die eigentliche Leiste UND der
   Leucht-Punkt sind eigene Pseudo-Elemente, die von main.js ausschliesslich
   ueber die Custom Property --progress (0..1) gesteuert werden, per
   transform/opacity statt left/width -- kein Layout-Trigger pro Scroll-Event.
   .scroll-progress selbst nie transformieren: sonst wuerde ::after (der
   Punkt) mit skaliert und aus einem Kreis eine Ellipse werden. */
.scroll-progress{
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 70;
  pointer-events: none;
}
/* Der "Kometenschweif": am Seitenanfang (links) transparent/blass, an der
   Spitze (rechts -- durch transform-origin:left bleibt die Spitze bei jedem
   Fortschritt exakt der 100%-Stop des Verlaufs) hell/leuchtend. */
.scroll-progress::before{
  content: ""; position: absolute; inset: 0;
  transform-origin: left; transform: scaleX(var(--progress, 0));
  background: linear-gradient(90deg,
    rgba(var(--accent-rgb), 0) 0%,
    var(--accent) 45%,
    var(--accent-2) 80%,
    #fff 100%);
}
/* Leuchtender Punkt exakt an der Fortschritts-Spitze. translateX ueber
   100vw statt left/width, damit er wie die Leiste selbst nur ueber
   transform bewegt wird; opacity folgt --progress, damit bei 0 (Seitenanfang,
   noch nicht gescrollt) kein Punkt sichtbar ist. */
.scroll-progress::after{
  content: ""; position: absolute; top: 50%; left: 0;
  width: 8px; height: 8px; border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 2px rgba(var(--accent-rgb), .9), 0 0 14px 4px rgba(var(--accent-rgb), .5);
  opacity: var(--progress, 0);
  transform: translate(calc(var(--progress, 0) * 100vw - 4px), -50%);
}

/* ---------------------------------------------------------
   9. Hero
--------------------------------------------------------- */
/* Lesbarkeits-Abdunkler über der Shader-Fahne.
   Der Shader ist animiert: eine Kontrastmessung an einem einzelnen Frame sagt
   nichts über den nächsten. Statt die Fahne so weit zu dämpfen, dass sie in
   jedem denkbaren Frame passt (dann wäre der Effekt weg), liegt hier ein
   weicher Verlauf unter der Textspalte — links deckend, ab ~68 % transparent.
   Damit ist der Kontrast unabhängig vom Animationsstand garantiert und die
   Fahne bleibt rechts, wo kein Fließtext steht, voll sichtbar.
   Gemessen: ohne diesen Verlauf fiel die Eyebrow auf website-erstellung.html
   auf 3.79:1. */
.hero, .page-hero{ position: relative; }
.hero::before, .page-hero::before{
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(100deg,
    rgba(7,9,13,.93) 0%,
    rgba(7,9,13,.78) 34%,
    rgba(7,9,13,.35) 55%,
    rgba(7,9,13,0) 72%);
}

.hero{ padding-top: clamp(3rem, 6vw, 5rem); padding-bottom: clamp(3rem, 6vw, 5rem); }
/* Eigener, etwas breiterer Max-width als .container (1240px), nur fuer den
   Hero-Inhalt: verhindert, dass Headline und Live-Build-Panel auf sehr
   breiten Bildschirmen zu weit auseinandergezogen wirken. */
.hero-grid{ display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(2rem, 5vw, 4rem); align-items: center; max-width: 87.5rem; }
.hero-grid > *{ min-width: 0; }

.eyebrow{
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: .82rem; letter-spacing: .02em;
  color: var(--accent);
  margin-bottom: 1rem;
}
.eyebrow::before{ content:"// "; opacity: .8; }

.hero-copy h1{ margin-bottom: 1.1rem; }
.hero-copy .lede{ margin-bottom: 1.8rem; }
.hero-actions{ display: flex; gap: 1rem; flex-wrap: wrap; }

/* Preiszeile zwischen Lede und Buttons: bewusst kleiner als der Fließtext
   und ohne eigenes Gewicht (keine Karte, kein Button) -- nur der Preis-Teil
   ist als Link zur #preise-Sektion hervorgehoben. margin-top übernimmt das
   .lede-margin-bottom (1.8rem) darüber, margin-bottom hier hält denselben
   Abstand zu den Buttons darunter. */
.hero-price-note{ font-size: .92rem; color: var(--text-3); margin-bottom: 1.8rem; }
.hero-price-link{
  color: var(--accent); font-weight: 700;
  text-decoration: underline; text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--t-fast) var(--ease);
}
.hero-price-link:hover{ text-decoration-color: currentColor; }

/* page hero — subpages */
.page-hero{ padding-block: clamp(6rem, 10vw, 8.5rem) clamp(2.5rem, 5vw, 4rem); }
.page-hero .container{ max-width: 760px; }
.page-hero .lede{ max-width: 60ch; }

/* ---------------------------------------------------------
   10. Live Build panel — hero centerpiece
--------------------------------------------------------- */
.live-build{
  position: relative;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-width: 0;
}
.live-build::before{
  content:""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .12);
}

.lb-code{ padding: 1.1rem 1.2rem; border-right: 1px solid var(--border); background: var(--bg-2); min-width: 0; overflow-x: hidden; }
.lb-bar{ display: flex; align-items: center; gap: .5rem; margin-bottom: .9rem; }
.lb-bar .dot{ width: 9px; height: 9px; border-radius: 50%; background: var(--border-strong); }
.lb-bar .file{ margin-left: .6rem; font-family: var(--font-mono); font-size: .72rem; color: var(--text-3); }

.lb-lines{ font-family: var(--font-mono); font-size: .78rem; line-height: 1.75; }
.lb-line{ display: flex; align-items: flex-start; gap: .7rem; opacity: 0; }
.lb-line .ln{ color: var(--text-3); opacity: .5; user-select: none; width: 1.2em; text-align: right; flex-shrink: 0; }
/* War white-space:pre + overflow-x:auto auf .lb-code (Guardrail gegen einen
   wachsenden Grid-Track, s. CLAUDE.md) -- lief bei der laengsten Zeile (6,
   "Modern gestaltet, schnell geladen.") sichtbar über den Rand und zeigte
   eine horizontale Scrollbar. pre-wrap erhaelt die Einrueckungs-Leerzeichen,
   bricht aber lange Zeilen sauber um; .lb-code braucht overflow-x darum
   nicht mehr, min-width:0 (Guardrail) bleibt trotzdem stehen. */
.lb-line .code{ white-space: pre-wrap; overflow-wrap: break-word; }
.lb-line .tag{ color: var(--accent-2); }
.lb-line .attr{ color: var(--accent); }
.lb-line .str{ color: #FFD479; }
.lb-line .plain{ color: var(--text-2); }
.lb-line.is-in{ opacity: 1; }

.lb-preview{ position: relative; padding: 1.1rem; display: flex; flex-direction: column; gap: .7rem; background: var(--bg); }
.lb-preview .ph-nav{ height: 10px; border-radius: 4px; background: var(--border-strong); width: 55%; opacity: 0; transform: translateY(6px); transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out); }
.lb-preview .ph-h{ height: 20px; border-radius: 4px; background: linear-gradient(90deg, var(--accent), var(--accent-2)); width: 78%; opacity: 0; transform: translateY(6px); transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out); margin-top: .5rem; }
.lb-preview .ph-p{ height: 8px; border-radius: 4px; background: var(--border-strong); opacity: 0; transform: translateY(6px); transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out); }
.lb-preview .ph-p.w1{ width: 90%; } .lb-preview .ph-p.w2{ width: 65%; }
.lb-preview .ph-btn{ margin-top: .75rem; width: 108px; height: 34px; border-radius: 7px; background: var(--accent); opacity: 0; transform: translateY(6px) scale(.9); transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out); box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0); }
.lb-preview .is-in{ opacity: 1; transform: translateY(0) scale(1); }
.lb-preview .ph-btn.is-in{ box-shadow: 0 0 24px 0 rgba(var(--accent-rgb),.45); }

/* ---------------------------------------------------------
   11. Trust bar & floating badges
--------------------------------------------------------- */
.trust-bar{ border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding-block: 1.5rem; }
.trust-row{ display: flex; flex-wrap: wrap; gap: 2rem 2.5rem; justify-content: center; font-size: .88rem; color: var(--text-3); }
.trust-row b{ color: var(--text); }

.badge-field{ position: relative; min-height: 160px; display: flex; flex-wrap: wrap; gap: 1rem 1.25rem; justify-content: center; align-items: center; padding-block: 1rem; }
.chip-float{
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .6rem 1.05rem; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface);
  font-size: .85rem; color: var(--text-2);
  animation: floaty 6s ease-in-out infinite;
}
.chip-float .spark{ width: 6px; height: 6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px 1px rgba(var(--accent-rgb),.7); }
.chip-float:nth-child(2n){ animation-duration: 7.5s; animation-delay: -1.5s; }
.chip-float:nth-child(3n){ animation-duration: 5.2s; animation-delay: -3s; }
.chip-float:nth-child(4n){ animation-duration: 8.5s; animation-delay: -.6s; }

@keyframes floaty{
  0%, 100%{ transform: translateY(0) rotate(0deg); }
  50%{ transform: translateY(-10px) rotate(-1.2deg); }
}

/* ---------------------------------------------------------
   12. Section head
--------------------------------------------------------- */
.section-head{ max-width: 660px; margin-bottom: 2.6rem; }
.section-head.center{ margin-inline: auto; text-align: center; }
.section-head h2{ margin-bottom: .75rem; }

/* ---------------------------------------------------------
   13. Click-Reveal — Cursor klickt eine Beispielseite an und lässt sie
   neu erstrahlen. Ersetzt die frühere Wisch-Diff-Vorschau: eine einzelne
   Seite statt zwei nebeneinander, ein Cursor statt eines Schnitts.

   Wichtig: das Grundlayout (keine Modifier-Klasse) IST bereits der neue,
   fertige Zustand — das ist der Ruhezustand ohne JS/bei Reduced-Motion.
   `.is-old` wird nur von JS gesetzt, kurz bevor die Animation losläuft,
   und beschreibt den GEDRÄNGTEN Vorher-Zustand, aus dem heraus animiert
   wird. Der Cursor selbst startet unsichtbar (opacity 0) und wird nur
   von JS sichtbar gemacht, wenn er auch wirklich bewegt wird.
--------------------------------------------------------- */
.click-reveal{ position: relative; padding-block: 1.5rem 2.5rem; }

/* Schein, der über .cr-frame hinaus in den Sektionshintergrund ausstrahlt.
   Der bisherige .cr-flash saß NUR innerhalb des Rahmens (overflow:hidden),
   der Klick wirkte dadurch zu lokal auf ein kleines Rechteck begrenzt statt
   spürbar auf den ganzen Bereich. Liegt als eigenes Element hinter dem
   Rahmen, dessen deckender Hintergrund deckt die Mitte des Glows ab —
   sichtbar bleibt nur der Teil, der über den Rahmen hinausreicht.
   Mittelpunkt ist seit dem Wellen-Umbau die MITTE DES RAHMENS (live-build.js
   setzt --click-x/--click-y auf den Rahmenmittelpunkt), nicht mehr der links
   sitzende .cr-cta-mock: der Klick ist nur der Auslöser, der Aufschlagpunkt
   der Welle liegt mittig auf der Fläche. */
.cr-ambient{
  position: absolute; inset: -22% -12%; z-index: 0; pointer-events: none;
  background: radial-gradient(circle at var(--click-x, 50%) var(--click-y, 50%), rgba(var(--accent-rgb), .5), transparent 62%);
  filter: blur(34px);
  opacity: 0;
}
/* Läuft bewusst so lang wie die Welle selbst und wächst leicht mit: der
   Schein ist das, was von der Welle nach außen in die Sektion abstrahlt. */
.click-reveal.is-flashing .cr-ambient{ animation: crambient 1.5s var(--ease-out); }
@keyframes crambient{
  0%{ opacity: 0; transform: scale(.72); }
  22%{ opacity: 1; }
  100%{ opacity: 0; transform: scale(1.08); }
}

.cr-frame{
  position: relative; z-index: 1; max-width: 640px; margin-inline: auto;
  border: 1px solid rgba(var(--accent-rgb), .35); border-radius: var(--radius);
  background: var(--bg-2); overflow: hidden;
  box-shadow: 0 20px 60px -24px rgba(var(--accent-rgb), .35);
  transition: border-color var(--t-slow) var(--ease), box-shadow var(--t-slow) var(--ease);
}
.click-reveal.is-old .cr-frame{ border-color: var(--border-strong); box-shadow: none; }
/* Sichtbarer "Druck": der Rahmen wird beim Klick kurz eingedrückt und federt
   danach leicht über die Ausgangsgröße zurück, statt nur farblich umzuschalten. */
.click-reveal.is-flashing .cr-frame{ animation: crpress var(--t-slow) var(--ease-out); }
@keyframes crpress{ 0%{ transform: scale(1); } 20%{ transform: scale(.965); } 55%{ transform: scale(1.012); } 100%{ transform: scale(1); } }

.cr-bar{ display: flex; align-items: center; gap: .45rem; padding: .9rem 1.1rem; border-bottom: 1px solid var(--border); }
.cr-bar span{ width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); flex-shrink: 0; }
/* Adressleiste bewusst als reine Form ohne Text: macht den Rahmen als
   Browserfenster lesbar, ohne eine Domain zu behaupten, die es nicht gibt. */
.cr-url{
  flex: 1; max-width: 58%; height: 10px; margin-left: .45rem;
  border-radius: 999px; border: 1px solid var(--border); background: rgba(236,245,243,.08);
  transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease);
}
.click-reveal.is-old .cr-url{ border-radius: 2px; background: rgba(236,245,243,.04); }

.cr-body{ padding: 1.6rem 1.8rem 1.9rem; display: flex; flex-direction: column; gap: .7rem; }

/* Kopfzeile der Beispielseite: Logo-Kachel links, drei Menüpunkte rechts.
   Vorher war das ein einzelner grauer Balken. */
.cr-nav{ display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.cr-logo{
  width: 22px; height: 22px; flex-shrink: 0; border-radius: 7px;
  background: linear-gradient(140deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 14px rgba(var(--accent-rgb), .40);
  transition: background var(--t-slow) var(--ease), border-radius var(--t-med) var(--ease), box-shadow var(--t-slow) var(--ease);
}
.click-reveal.is-old .cr-logo{ background: rgba(236,245,243,.12); border-radius: 2px; box-shadow: none; }
.cr-menu{ display: flex; gap: .5rem; margin-left: auto; }
.cr-menu i{
  width: 26px; height: 6px; border-radius: 3px; background: rgba(236,245,243,.16);
  transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease);
}
.cr-menu i:nth-child(2){ width: 34px; }
.click-reveal.is-old .cr-menu i{ border-radius: 1px; background: rgba(236,245,243,.07); }

.cr-hero{
  position: relative; overflow: hidden;
  min-height: 78px; padding: .9rem 1.05rem;
  display: flex; flex-direction: column; justify-content: center; gap: .4rem;
  border-radius: 9px;
  background: linear-gradient(100deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 26px rgba(var(--accent-rgb), .30);
  transition: background var(--t-slow) var(--ease), border-radius var(--t-med) var(--ease), box-shadow var(--t-slow) var(--ease);
}
/* Diagonaler Glanz, dasselbe Mittel wie über dem Laptop-Screenshot in den
   Referenzen (.showcase-screen::after) — gibt der Fläche Tiefe. */
.cr-hero::after{
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(118deg, rgba(255,255,255,.20) 0%, transparent 44%);
  transition: opacity var(--t-slow) var(--ease);
}
.cr-hl{ height: 8px; border-radius: 4px; background: rgba(7,9,13,.42); transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease); }
.cr-hl.a{ width: 56%; }
.cr-hl.b{ width: 36%; height: 6px; background: rgba(7,9,13,.26); }
.cr-hpill{
  margin-top: .3rem; width: 64px; height: 15px; border-radius: 999px;
  background: rgba(255,255,255,.58);
  transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease);
}
.click-reveal.is-old .cr-hero{ background: rgba(236,245,243,.08); border-radius: 4px; box-shadow: none; }
.click-reveal.is-old .cr-hero::after{ opacity: 0; }
.click-reveal.is-old .cr-hl{ background: rgba(236,245,243,.10); border-radius: 1px; }
.click-reveal.is-old .cr-hl.b{ background: rgba(236,245,243,.07); }
.click-reveal.is-old .cr-hpill{ background: rgba(236,245,243,.12); border-radius: 2px; }

.cr-line{ height: 7px; border-radius: 4px; background: rgba(236,245,243,.17); transition: background var(--t-slow) var(--ease), border-radius var(--t-med) var(--ease); }
.cr-line.w1{ width: 90%; } .cr-line.w2{ width: 64%; }
.click-reveal.is-old .cr-line{ background: rgba(236,245,243,.07); border-radius: 2px; }

.cr-row{ display: flex; gap: .7rem; margin-top: .3rem; }
.cr-card{
  flex: 1; min-height: 64px; padding: .6rem .65rem; border-radius: 8px;
  display: flex; flex-direction: column; gap: .34rem;
  border: 1px solid var(--border); background: rgba(236,245,243,.045);
  transition: border-radius var(--t-med) var(--ease), border-color var(--t-slow) var(--ease), background var(--t-slow) var(--ease);
}
.cr-ic{
  width: 15px; height: 15px; border-radius: 5px; margin-bottom: .1rem;
  background: rgba(var(--accent-rgb), .55);
  transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease);
}
.cr-cl{ height: 5px; border-radius: 3px; background: rgba(236,245,243,.15); transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease); }
.cr-cl.a{ width: 86%; } .cr-cl.b{ width: 58%; }
.click-reveal.is-old .cr-card{ border-radius: 2px; border-color: rgba(236,245,243,.07); background: rgba(236,245,243,.03); }
.click-reveal.is-old .cr-ic{ border-radius: 1px; background: rgba(236,245,243,.12); }
.click-reveal.is-old .cr-cl{ border-radius: 1px; background: rgba(236,245,243,.07); }

/* Fußzeile der Beispielseite: schließt das Mockup unten sauber ab, statt
   dass es nach dem CTA einfach aufhört. */
.cr-foot{
  display: flex; align-items: center; gap: .5rem;
  margin-top: .8rem; padding-top: .75rem; border-top: 1px solid var(--border);
}
.cr-foot span{
  height: 5px; border-radius: 3px; background: rgba(236,245,243,.11);
  transition: border-radius var(--t-med) var(--ease), background var(--t-slow) var(--ease);
}
.cr-foot span:nth-child(1){ width: 66px; }
.cr-foot span:nth-child(2){ width: 42px; }
.cr-foot span:nth-child(3){ width: 30px; margin-left: auto; }
.click-reveal.is-old .cr-foot span{ border-radius: 1px; background: rgba(236,245,243,.06); }

.cr-cta-mock{
  align-self: flex-start; margin-top: .5rem;
  width: 118px; height: 26px; border-radius: 6px;
  background: var(--accent);
  box-shadow: 0 0 18px rgba(var(--accent-rgb), .4);
  transition: background var(--t-slow) var(--ease), box-shadow var(--t-slow) var(--ease), border-radius var(--t-med) var(--ease);
}
.click-reveal.is-old .cr-cta-mock{ background: rgba(236,245,243,.12); box-shadow: none; border-radius: 3px; }

/* Aufschlag: kurzer Lichtkern im Moment des "Eintauchens", sitzt mittig auf
   der Fläche (50% 50%) und nicht mehr am links liegenden .cr-cta-mock.
   Kurz und klein gehalten — die eigentliche Wirkung tragen die Wellen. */
.cr-flash{
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: radial-gradient(circle at 50% 50%, rgba(var(--accent-rgb),.70), transparent 54%);
  opacity: 0;
}
.click-reveal.is-flashing .cr-flash{ animation: crflash 900ms var(--ease-out); }
@keyframes crflash{
  0%{ opacity: 0; transform: scale(.35); }
  16%{ opacity: 1; }
  100%{ opacity: 0; transform: scale(1); }
}

/* --- Wellen wie ein Tropfen, der auf Wasser aufschlägt ---------------------
   Drei Ringe laufen nacheinander aus der Mitte der Mockup-Fläche nach außen:
   eine kräftige Bugwelle plus zwei schwächere Nachläufer.

   Bewusst KEIN skalierter border-Kreis: ein Rahmen wächst beim Skalieren mit,
   der Ring würde nach außen hin immer fetter — echte Wasserwellen werden
   dünner und schwächer. Stattdessen wandert über eine registrierte @property
   ein schmales, gleich dickes Helligkeitsband im radial-gradient nach außen.

   Falle: Farbstopps dürfen nicht negativ werden, sonst ist der ganze Gradient
   ungültig und es wird gar nichts gezeichnet. Deshalb startet --cr-wave bei
   7% statt 0% — die halbe Bandbreite (max. 6%) passt darunter. Optisch ist
   das sogar näher am Vorbild: ein Tropfen erzeugt einen kleinen Kranz, keinen
   mathematischen Punkt. */
@property --cr-wave{
  syntax: '<percentage>';
  initial-value: 7%;
  inherits: false;
}

.cr-ripple{ position: absolute; inset: 0; z-index: 3; pointer-events: none; mix-blend-mode: screen; }
.cr-ripple span{
  position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(circle at 50% 50%,
    transparent calc(var(--cr-wave) - 4%),
    rgba(var(--accent-rgb), .55) var(--cr-wave),
    transparent calc(var(--cr-wave) + 4%));
}
/* Nachläufer: später, breiter, schwächer — die Energie nimmt ab */
.cr-ripple span:nth-child(2){
  background: radial-gradient(circle at 50% 50%,
    transparent calc(var(--cr-wave) - 5%),
    rgba(var(--accent-rgb), .34) var(--cr-wave),
    transparent calc(var(--cr-wave) + 5%));
}
.cr-ripple span:nth-child(3){
  background: radial-gradient(circle at 50% 50%,
    transparent calc(var(--cr-wave) - 6%),
    rgba(var(--accent-rgb), .20) var(--cr-wave),
    transparent calc(var(--cr-wave) + 6%));
}
.click-reveal.is-flashing .cr-ripple span{ animation: crwave 1.5s var(--ease-out); }
.click-reveal.is-flashing .cr-ripple span:nth-child(2){ animation-delay: 150ms; }
.click-reveal.is-flashing .cr-ripple span:nth-child(3){ animation-delay: 310ms; }
@keyframes crwave{
  0%{ --cr-wave: 7%; opacity: 0; }
  10%{ opacity: 1; }
  100%{ --cr-wave: 98%; opacity: 0; }
}

.cr-cursor{
  position: absolute; top: 0; left: 0; z-index: 5;
  width: 26px; height: 26px; opacity: 0; pointer-events: none;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,.45));
  transition: opacity var(--t-med) var(--ease);
}
.cr-cursor.is-visible{ opacity: 1; }
.cr-cursor.is-clicking{ animation: crclick var(--t-med) var(--ease-out); }
@keyframes crclick{ 0%{ transform: scale(1); } 45%{ transform: scale(.78); } 100%{ transform: scale(1); } }

/* Der frühere .cr-ring (kleiner Klick-Ping) ist am 20.09.2026 ersatzlos
   entfernt worden. Er war kaputt und fiel erst mit der neuen Welle auf:
   fireClick() setzte per Inline-Style ein transform: translate(x,y) auf die
   CTA-Position, seine Keyframes setzten aber selbst transform: scale(...) —
   und das überschreibt das translate vollständig. Der Ring poppte dadurch
   immer in der linken oberen Ecke von .click-reveal auf, direkt unter der
   letzten Überschriftenzeile, statt am Klickpunkt. Das Klick-Feedback tragen
   jetzt der Cursor-Stauch-Effekt und die Welle; wer so einen Ping wieder
   einbaut, muss die Verschiebung IN die Keyframes schreiben
   (translate(...) scale(...)), nicht daneben. */

.diff-block{ border: 1px solid var(--border); border-radius: var(--radius); padding: 1.75rem; background: var(--surface); }
.diff-block.is-old{ border-color: var(--border); }
.diff-block.is-new{ border-color: rgba(var(--accent-rgb),.35); }
.diff-title{ font-family: var(--font-mono); font-size: .85rem; color: var(--text-3); margin-bottom: 1rem; }
.diff-block.is-new .diff-title{ color: var(--accent); }
.diff-block li{ display: flex; gap: .7rem; padding-block: .5rem; border-top: 1px solid var(--border); font-size: .92rem; }
.diff-block li:first-child{ border-top: 0; }
.diff-block .mark{ font-family: var(--font-mono); flex-shrink: 0; width: 1em; }
.diff-block.is-old .mark{ color: var(--diff-remove); }
.diff-block.is-new .mark{ color: var(--diff-add); }
.diff-block.is-old .txt{ color: var(--text-3); }

/* ---------------------------------------------------------
   14. Service list — corner-bracket rows
--------------------------------------------------------- */
.service-list{ display: flex; flex-direction: column; }
.service-row{
  position: relative;
  display: grid; grid-template-columns: 1fr auto; gap: 1rem 2rem; align-items: start;
  padding: 1.6rem 1.4rem;
  border-top: 1px solid var(--border);
  transition: background var(--t-fast) var(--ease);
}
.service-list li:last-child{ border-bottom: 1px solid var(--border); }
.service-row::before, .service-row::after{
  content:""; position: absolute; width: 14px; height: 14px; opacity: 0; transition: opacity var(--t-fast) var(--ease);
}
.service-row::before{ top: -1px; left: 0; border-top: 1px solid var(--accent); border-left: 1px solid var(--accent); }
.service-row::after{ bottom: -1px; right: 0; border-bottom: 1px solid var(--accent); border-right: 1px solid var(--accent); }
.service-row:hover{ background: rgba(var(--accent-rgb),.04); }
.service-row:hover::before, .service-row:hover::after{ opacity: 1; }
.service-copy h3{ font-size: 1.15rem; margin-bottom: .4rem; }
.service-copy h3 a{ transition: color var(--t-fast) var(--ease); }
.service-copy h3 a:hover{ color: var(--accent); }
.service-copy p{ max-width: 52ch; }
.service-tag{ justify-self: start; font-family: var(--font-mono); font-size: .72rem; color: var(--accent); border: 1px solid rgba(var(--accent-rgb),.35); border-radius: 999px; padding: .3rem .7rem; height: fit-content; white-space: nowrap; }
.service-row.no-tag{ grid-template-columns: 1fr; }
.service-row.no-tag h3{ font-size: 1.15rem; margin-bottom: .4rem; }
.service-row.no-tag p{ max-width: 52ch; }

/* ---------------------------------------------------------
   15. Chip row (Branchen)
--------------------------------------------------------- */
.chip-row{ display: flex; flex-wrap: wrap; gap: .8rem; }
.chip{ padding: .6rem 1.1rem; border-radius: 999px; border: 1px solid var(--border-strong); font-size: .88rem; color: var(--text-2); background: var(--surface); }

/* Branchen-Statement: bewusst kein Klassifizierungsraster mehr, ein
   kurzer, einladender Satz statt einer Liste, in der man erst die
   eigene Branche suchen muss. */
.industries-statement{ text-align: center; max-width: 720px; margin-inline: auto; }
.industries-statement h2{ margin-bottom: .6rem; }
.industries-statement .lede{ margin-inline: auto; }

/* ---------------------------------------------------------
   16. Process list — numbered, mono
--------------------------------------------------------- */
.process-list{ display: flex; flex-direction: column; }
.process-item{ display: grid; grid-template-columns: 88px 1fr; gap: 1.5rem; padding-block: 1.7rem; border-top: 1px solid var(--border); }
.process-list > *:first-child{ border-top: 0; }
.process-num{ font-family: var(--font-mono); font-size: 2.2rem; font-weight: 500; color: transparent; -webkit-text-stroke: 1px var(--border-strong); line-height: 1; }
.process-item h3{ margin-bottom: .4rem; }
.process-item p{ max-width: 56ch; }

/* ---------------------------------------------------------
   17. Word-reveal line
--------------------------------------------------------- */
.word-reveal .w{ display: inline-block; opacity: .25; filter: blur(3px); }

/* ---------------------------------------------------------
   18. Demo / referenzen cards
--------------------------------------------------------- */
.demo-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.demo-card{ position: relative; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface); transition: border-color var(--t-fast) var(--ease); }
.demo-card::before, .demo-card::after{ content:""; position: absolute; width: 16px; height: 16px; opacity: 0; transition: opacity var(--t-fast) var(--ease); z-index: 2; }
.demo-card::before{ top: 10px; left: 10px; border-top: 1px solid var(--accent); border-left: 1px solid var(--accent); }
.demo-card::after{ bottom: 10px; right: 10px; border-bottom: 1px solid var(--accent); border-right: 1px solid var(--accent); }
.demo-card:hover{ border-color: rgba(var(--accent-rgb),.3); }
.demo-card:hover::before, .demo-card:hover::after{ opacity: 1; }
.demo-thumb{ position: relative; padding: 1.75rem; background: var(--bg-2); border-bottom: 1px solid var(--border); }
.demo-body{ padding: 1.4rem; }
.kicker{ font-family: var(--font-mono); font-size: .72rem; color: var(--accent); }
.demo-body h3{ font-size: 1.05rem; margin-block: .5rem .5rem; }

/* ---------------------------------------------------------
   19. Pricing cards
   Optik nach dem 21st.dev-"Aurora"-Muster, auf Neon Blueprint übertragen:
   weich blurrender Farbverlauf-Schein hinter jeder Karte (Ruhezustand dezent,
   auf Hover kräftiger), grosse Mono-Preiszahl, Haken in getönten Kreisen,
   Hover hebt die Karte an (translateY). Bewusst NICHT übernommen: der
   Monats/Jahres-Umschalter samt "-20 %" — unser Modell ist Einmalpreis plus
   optionale Monatsbetreuung, nicht Abo. Der Schein ist ein dekoratives
   ::before mit filter: blur(), KEIN backdrop-filter; die Kartenfläche selbst
   bleibt undurchsichtig (Glas gibt es auf dieser Seite nur an den Buttons).
--------------------------------------------------------- */
.pricing-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; align-items: stretch; }
.price-card{
  position: relative; z-index: 0;
  display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 2rem; background: var(--surface);
}
/* Aurora-Schein hinter der Karte. Der weiche Rand kommt aus dem blur, -1 hält
   ihn hinter der undurchsichtigen Kartenfläche — er tritt also nur als Halo an
   den gerundeten Kanten aus, nicht über die Schrift.
   Gilt auch für .care-tier-card, damit die Betreuungsstufen optisch zur
   selben Kartenfamilie gehören wie die drei Paketkarten darüber. */
.price-card::before,
.care-tier-card::before{
  content: ""; position: absolute; inset: -14px; z-index: -1;
  border-radius: calc(var(--radius) + 12px);
  background: linear-gradient(120deg, var(--accent), var(--accent-2), var(--accent));
  background-size: 300% 300%;
  filter: blur(28px);
  opacity: .13;
  transition: opacity .5s var(--ease-out);
  animation: price-aurora 14s ease infinite;
}
.price-card.is-highlight,
.care-tier-card.is-highlight{
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(var(--accent-rgb),.25), 0 20px 60px -20px rgba(var(--accent-rgb),.35);
}
.price-card.is-highlight::before,
.care-tier-card.is-highlight::before{ opacity: .27; }
@keyframes price-aurora{
  0%   { background-position: 0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

.price-badge{
  position: absolute; top: -12px; right: 1.5rem; left: auto;
  font-family: var(--font-mono); font-size: .66rem; letter-spacing: .08em; text-transform: uppercase;
  background: var(--accent); color: #0a0b12;
  padding: .32rem .7rem; border-radius: 999px;
  box-shadow: 0 6px 18px -6px rgba(var(--accent-rgb), .6);
}
.price-sub{ color: var(--text-3); font-size: .88rem; margin-bottom: 1.2rem; }

.price-value{ font-family: var(--font-mono); font-size: 1.6rem; color: var(--text); margin-bottom: 1.4rem; }
.price-value span{ font-size: .8rem; color: var(--text-3); font-weight: 400; }
/* Grosse Preiszahl in den drei Paketkarten (eigene, noch größere Stufe unten
   bei .care-tier-card .price-value, dort bewusst kleiner gehalten als hier). */
.price-card .price-value{
  display: flex; align-items: baseline; white-space: nowrap;
  font-size: clamp(1.85rem, 1.25rem + 1.5vw, 2.2rem); font-weight: 700;
  letter-spacing: -.02em; line-height: 1.08;
}
.price-card .price-value span{ letter-spacing: 0; margin-left: .35rem; }
.price-list{ display: flex; flex-direction: column; gap: .7rem; margin-bottom: 1.6rem; flex: 1; }
/* Inklusive-Zeile (3 Monate Betreuung) unter der Haken-Liste. Bewusst als
   deutlich sichtbarer Baustein, kein leiser Fußnoten-Hinweis: das ist einer
   der Gründe, warum das Angebot attraktiv wirken soll, also Icon in
   getöntem Kreis (wie die Haken-Icons, aber Geschenk-Motiv statt Haken,
   damit "Bonus" statt "Standard-Leistung" gelesen wird), kräftigerer
   Akzent-Rahmen + -Hintergrund, größere Schrift, zweifarbige Auszeichnung. */
.price-included{
  display: flex; align-items: center; gap: .7rem;
  margin-bottom: 1.6rem; padding: .8rem 1rem;
  border-radius: var(--radius-sm);
  background: rgba(var(--accent-rgb), .16);
  border: 1px solid rgba(var(--accent-rgb), .4);
  color: var(--text-2); font-size: .88rem; line-height: 1.4;
}
.price-included svg{
  flex-shrink: 0; box-sizing: border-box; width: 26px; height: 26px; padding: 5px;
  border-radius: 50%; background: rgba(var(--accent-rgb), .22); color: var(--accent);
}
.price-included .lead{ color: var(--accent); font-weight: 700; }
.price-included b{ color: var(--text); font-weight: 700; }
.price-list li{ display: flex; align-items: center; gap: .6rem; font-size: .88rem; color: var(--text-2); }
/* Haken im getönten Kreis (Aurora-Muster: CheckCircle) — nur CSS, die 15
   Inline-SVGs bleiben unangetastet. */
.price-list li svg{
  box-sizing: border-box; width: 20px; height: 20px; padding: 3.5px;
  border-radius: 50%; background: rgba(var(--accent-rgb), .14);
  color: var(--accent); flex-shrink: 0;
}

/* Hover-Anhebung: Karte fährt hoch (translateY, Aurora-Muster whileHover
   y:-10) und skaliert leicht, die Leistungsliste "atmet", der Schein wird
   kräftiger. Nur echte Maus-Hover, sonst bliebe der Zustand auf Touch hängen. */
@media (hover: hover) and (pointer: fine){
  .price-card{
    transform-origin: center;
    transition: transform .35s var(--ease-out), box-shadow .35s var(--ease-out);
  }
  .price-list{ transition: gap .3s cubic-bezier(.25, .8, .25, 1); }
  .price-card:hover{ transform: translateY(-10px) scale(1.02); z-index: 1; }
  .price-card.is-highlight:hover{ transform: translateY(-10px) scale(1.015); }
  .price-card:hover::before{ opacity: .32; }
  .price-card.is-highlight:hover::before{ opacity: .44; }
  .price-card:hover .price-list{ gap: .85rem; }
  .care-tier-card{
    transform-origin: center;
    transition: transform .35s var(--ease-out), box-shadow .35s var(--ease-out);
  }
  .care-tier-card:hover{ transform: translateY(-6px); }
  .care-tier-card:hover::before{ opacity: .24; }
  .care-tier-card.is-highlight:hover::before{ opacity: .36; }
}
@media (prefers-reduced-motion: reduce){
  .price-card{ transition: none; }
  .price-list{ transition: none; }
  .care-tier-card{ transition: none; }
  .price-card::before,
  .care-tier-card::before{ animation: none; }
}
.price-note{ color: var(--text-3); }

/* Betreuungsstufen (Basis/Standard/Premium) — drei schmale Karten in derselben
   Kartenfamilie wie die Pakete (Rahmen, Radius, Aurora-Schein identisch zu
   .price-card), aber ohne Button: die Stufe wird im Erstgespräch gewählt,
   nicht direkt hier gebucht. Kopfblock (Überschrift/Erklärsatz/Hinweis)
   steht direkt auf der hellen #preise-Fläche, deshalb eigene Ink-Farben
   unten unter "surface-light" statt der dunklen Kartentexte. */
.care-tiers-head{ text-align: center; max-width: 46ch; margin: clamp(2.5rem, 5vw, 3.5rem) auto 0; }
.care-tiers-head h3{ font-size: clamp(1.3rem, 1vw + 1.05rem, 1.6rem); margin-block: .5rem .5rem; }
.care-tiers-head p{ font-size: .96rem; line-height: 1.55; }
.care-tiers-hint{ display: block; margin-top: .6rem; font-family: var(--font-mono); font-size: .78rem; }
.surface-light .care-tiers-head .eyebrow{ color: var(--accent-ink); }
.surface-light .care-tiers-head h3{ color: var(--ink); }
.surface-light .care-tiers-head p,
.surface-light .care-tiers-hint{ color: var(--ink-2); }

.care-tier-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; align-items: stretch; margin-top: 2.5rem; }
.care-tier-card{
  position: relative; z-index: 0;
  display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 1.5rem; background: var(--surface);
}
.care-tier-card h4{ font-size: 1rem; margin-bottom: .3rem; }
.care-tier-card .price-value{
  font-size: clamp(1.5rem, 1.1rem + 1.1vw, 1.9rem); font-weight: 700;
  letter-spacing: -.02em; line-height: 1.08; margin-bottom: 1rem;
}
.care-tier-card .price-list{ margin-bottom: 0; gap: .6rem; }
.care-tier-card .price-list li{ font-size: .85rem; }

.care-tiers-cta{ display: flex; justify-content: center; margin-top: 2rem; }

@media (max-width: 760px){
  .care-tier-card.is-highlight{ margin-top: 1.75rem; }
}

/* ---------------------------------------------------------
   20. FAQ accordion
--------------------------------------------------------- */
.faq-list{ display: flex; flex-direction: column; border-top: 1px solid var(--border); }
.faq-item{ border-bottom: 1px solid var(--border); }
.faq-q{ width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-block: 1.3rem; text-align: left; font-size: 1.02rem; font-weight: 500; }
.faq-q .plus{ font-family: var(--font-mono); flex-shrink: 0; color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.faq-q .plus::before{ content: "+"; }
.faq-item.is-open .faq-q .plus{ transform: rotate(45deg); }
.faq-a{ max-height: 0; overflow: hidden; transition: max-height var(--t-med) var(--ease-out); }
.faq-a p{ padding-bottom: 1.3rem; font-family: var(--font-mono); font-size: .88rem; line-height: 1.7; max-width: 62ch; }

/* ---------------------------------------------------------
   21. CTA band
--------------------------------------------------------- */
.cta-band{ border: 1px solid var(--border-strong); border-radius: var(--radius); padding: clamp(2.5rem, 5vw, 4rem); text-align: center; background: radial-gradient(ellipse 80% 100% at 50% 0%, rgba(var(--accent-rgb),.08), transparent 70%), var(--surface); }
.cta-band h2{ margin-block: .75rem 1rem; }
.cta-band .lede{ margin-inline: auto; margin-bottom: 1.8rem; }
.cta-band .hero-actions{ justify-content: center; }

/* Bild-Banner (ersetzt den frueheren surface-light-CTA "Wir sagen Ihnen ehrlich").
   Muster von der Referenz-Demo beckmanns-krug-nachher.html (.band): Foto als
   Hintergrund, dunkler Verlauf drueber fuer Textkontrast, Inhalt zentriert.
   Verlauf oben/unten dunkler (blendet in #unterschied bzw. #referenzen), in der
   Mitte plus ein radialer Abdunkler hinter dem Textblock. Kein
   background-attachment:fixed (ruckelt auf Mobil). */
.banner{
  position: relative;
  padding: clamp(4.5rem, 10vw, 8rem) 1.5rem;
  text-align: center; color: var(--text);
  background-color: var(--bg);
  background-image:
    radial-gradient(ellipse 68% 62% at 50% 50%, rgba(7,9,13,.5), transparent 78%),
    linear-gradient(180deg, rgba(7,9,13,.93), rgba(7,9,13,.62) 40%, rgba(7,9,13,.68) 66%, rgba(7,9,13,.97)),
    url("../img/beratung-banner.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.banner-inner{ max-width: 44rem; margin-inline: auto; }
.banner-inner h2{ margin-block: .8rem 1.5rem; }
.banner-inner .hero-actions{ justify-content: center; }
.banner-credit{
  position: absolute; right: .8rem; bottom: .55rem;
  font-family: var(--font-mono); font-size: .6rem; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase;
  color: rgba(238,241,246,.42);
}
/* ab 1100px sitzt rechts die .section-rail (fixed) — Credit weiter nach innen */
@media (min-width: 1100px){ .banner-credit{ right: 4.2rem; } }

/* ---------------------------------------------------------
   22. Footer
--------------------------------------------------------- */
.site-footer{ border-top: 1px solid var(--border); padding-block: 3.5rem 2rem; }
.footer-grid{ display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 2.5rem; margin-bottom: 2.5rem; }
.footer-brand p{ margin-top: .9rem; font-size: .88rem; max-width: 32ch; }
.footer-col h3{ font-family: var(--font-mono); font-size: .78rem; color: var(--text-3); font-weight: 500; margin-bottom: 1rem; text-transform: uppercase; letter-spacing: .04em; }
.footer-col ul{ display: flex; flex-direction: column; gap: .65rem; }
.footer-col a, .footer-col li{ font-size: .9rem; color: var(--text-2); }
.footer-col a:hover{ color: var(--accent); }
.footer-bottom{ display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem; padding-top: 1.6rem; border-top: 1px solid var(--border); font-size: .82rem; color: var(--text-3); }
.footer-bottom a:hover{ color: var(--accent); }

/* ---------------------------------------------------------
   23. Legal / todo-note
--------------------------------------------------------- */
.legal-content{ max-width: 760px; }
.legal-content h2{ font-size: 1.4rem; margin-block: 2.2rem .8rem; }
.legal-content h3{ font-size: 1.15rem; margin-block: 1.8rem .6rem; }
.legal-content h4{ font-size: 1rem; margin-block: 1.3rem .5rem; }
.legal-content h5{ font-size: .95rem; font-weight: 600; margin-block: 1rem .4rem; }
.legal-content p, .legal-content li{ font-size: .95rem; margin-bottom: .8rem; }
.legal-content ul{ padding-left: 1.2rem; list-style: disc; }
.todo-note{
  display: flex; gap: .8rem;
  border: 1px dashed rgba(var(--accent-2-rgb),.5);
  background: rgba(var(--accent-2-rgb),.06);
  border-radius: var(--radius-sm);
  padding: 1rem 1.2rem;
  margin-block: 1rem 1.6rem;
  font-size: .85rem;
  color: var(--text-2);
}
.todo-note .tag{ font-family: var(--font-mono); font-size: .72rem; color: var(--accent-2); flex-shrink: 0; }

/* ---------------------------------------------------------
   24. Forms (Kontakt)
--------------------------------------------------------- */
.contact-form{ display: flex; flex-direction: column; gap: 1.3rem; max-width: 560px; }
.form-field{ display: flex; flex-direction: column; gap: .5rem; }
.form-field label{ font-family: var(--font-mono); font-size: .78rem; color: var(--text-3); }
.form-field select{
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); padding: .85rem 1rem; font-size: .95rem;
  transition: border-color var(--t-fast) var(--ease);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%2386A19C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
}
.form-field select:focus-visible{ outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.15); }
.form-field input, .form-field textarea{
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); padding: .85rem 1rem; font-size: .95rem;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.form-field input:focus-visible, .form-field textarea:focus-visible{ outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.15); }
.form-field textarea{ min-height: 140px; resize: vertical; }
.form-status{ font-family: var(--font-mono); font-size: .85rem; padding: .9rem 1rem; border-radius: var(--radius-sm); border: 1px solid var(--border-strong); display: none; }
.form-status.is-visible{ display: block; }
/* Erfolg und Fehler auch farblich unterscheiden, nicht nur im Text: die Farbe
   ist dabei die Zugabe, die Aussage steht im Text selbst. */
.form-status.is-ok{ border-color: rgba(52,211,153,.5); color: var(--diff-add); }
.form-status.is-error{ border-color: rgba(251,113,133,.5); color: var(--diff-remove); }

/* Custom-Select ("Was benötigen Sie?"): ersetzt das native <select>, dessen
   aufgeklappte Liste je nach Betriebssystem/Browser-Theme schwarz auf
   schwarz gerendert wurde -- native <option>-Listen lassen sich per CSS
   nicht zuverlässig einfärben. --cs-bg/--cs-bg-open sind bewusst neue,
   lokal auf .custom-select begrenzte Tokens: --surface/--elevated sind für
   dieses Feld zu dunkel (fast schwarz wie der Seitenhintergrund), das Feld
   soll sich sichtbar von der Fläche abheben. Rand, Fokusring, Radius und
   Schrift übernehmen dagegen bewusst dieselben Variablen wie die
   Nachbarfelder (--border-strong, --accent, --accent-rgb, --radius-sm).
   Ausgangswert kommt aus einem verstecktem <input type="hidden"> mit
   demselben name="need" wie vorher das <select> -- am Versand (natives
   Formular-POST, kein Fetch/AJAX) ändert sich dadurch nichts. */
.custom-select{
  --cs-bg: #262a38;
  --cs-bg-open: #2f3446;
  position: relative;
}
.cs-trigger{
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  width: 100%; min-height: 56px; padding: .95rem 1.15rem;
  font: inherit; font-size: 1.05rem; color: var(--text); text-align: left;
  background: var(--cs-bg);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.cs-trigger:hover{ background: var(--cs-bg-open); }
.cs-trigger:focus-visible{ outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.15); }
.custom-select.is-open .cs-trigger{
  background: var(--cs-bg-open); border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.15);
}
.cs-value{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-chevron{ flex-shrink: 0; color: var(--text-3); transition: transform var(--t-fast) var(--ease); }
.custom-select.is-open .cs-chevron{ transform: rotate(180deg); }

/* Panel bleibt im DOM (nicht [hidden]), sonst liesse sich display:none nicht
   animieren -- geschlossen ist es über opacity/visibility/transform
   unsichtbar UND per pointer-events nicht klickbar. visibility bekommt eine
   Verzögerung, die exakt zur jeweiligen Richtung passt: beim Öffnen sofort
   sichtbar, beim Schliessen erst NACH der Ausblend-Transition, sonst
   verschwindet der Inhalt ruckartig, bevor die Bewegung fertig ist. */
.cs-panel{
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 75;
  max-height: min(320px, 60vh); overflow-y: auto;
  margin: 0; padding: .4rem;
  list-style: none;
  background: var(--cs-bg-open);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  box-shadow: 0 20px 45px -20px rgba(0,0,0,.55);
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateY(-6px) scaleY(.97); transform-origin: top;
  transition: opacity .18s cubic-bezier(.16,1,.3,1), transform .18s cubic-bezier(.16,1,.3,1), visibility 0s linear .18s;
}
.custom-select.is-open .cs-panel{
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateY(0) scaleY(1);
  transition: opacity .22s cubic-bezier(.16,1,.3,1), transform .22s cubic-bezier(.16,1,.3,1), visibility 0s linear 0s;
}
.cs-option{
  display: flex; align-items: center; gap: .65rem;
  padding: .75rem .8rem; border-radius: calc(var(--radius-sm) - 3px);
  font-size: .95rem; color: var(--text);
  cursor: pointer;
}
.cs-option svg{ flex-shrink: 0; color: var(--accent); opacity: 0; }
.cs-option.is-selected svg{ opacity: 1; }
.cs-option.is-selected{ font-weight: 600; }
.cs-option.is-active, .cs-option:hover{ background: rgba(255,255,255,.10); }

@media (prefers-reduced-motion: reduce){
  .cs-panel, .custom-select.is-open .cs-panel{ transition: none; }
  .cs-chevron{ transition: none; }
}

/* Bot-Falle. Nicht display:none: manche Bots erkennen das und lassen das Feld
   dann in Ruhe. Stattdessen aus dem Sichtfeld geschoben, dazu aria-hidden und
   tabindex="-1" im Markup, damit Screenreader und Tastatur es nicht erreichen. */
.hp-field{
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  pointer-events: none;
}

/* Datenschutz-Hinweis am Formular (Checkliste: "Formulare: nur nötige Felder,
   Datenschutz-Hinweis"). Bis 22.09.2026 eine Pflicht-Checkbox (.form-consent,
   Kästchen + Label nebeneinander im Grid) — entfernt, weil die Rechtsgrundlage
   für die Formularverarbeitung Art. 6 Abs. 1 lit. b/f DSGVO ist, keine
   Einwilligung. Ersatzlos aus CSS/HTML entfernt statt nur ausgeblendet, s.
   `.form-privacy-hint` für den reinen Hinweistext, der seitdem an ihrer
   Stelle steht (unter dem Absende-Button). Gleiche Typografie wie vorher das
   Checkbox-Label, damit der Ton an dieser Stelle unverändert bleibt. */
.form-privacy-hint{
  font-size: .85rem;
  line-height: 1.55;
  color: var(--text-2);
}

/* ---------------------------------------------------------
   25. Scroll reveal
--------------------------------------------------------- */
.reveal{ opacity: 0; transform: translateY(24px); transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out); }
.reveal.is-visible{ opacity: 1; transform: translateY(0); }

/* ---------------------------------------------------------
   26. Responsive
--------------------------------------------------------- */
@media (max-width: 1024px){
  .demo-grid, .pricing-grid, .care-tier-grid{ grid-template-columns: repeat(2, 1fr); }
  .footer-grid{ grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px){
  .nav-links{ display: none; }
  .nav-burger{ display: block; }
  .hero-grid{ grid-template-columns: 1fr; }
  .live-build{ grid-template-columns: 1fr; }
  .lb-code{ border-right: 0; border-bottom: 1px solid var(--border); }
  .split-head{ grid-template-columns: 1fr; }
  .demo-grid, .pricing-grid, .care-tier-grid{ grid-template-columns: 1fr; }
  .process-item{ grid-template-columns: 56px 1fr; }
  .process-num{ font-size: 1.6rem; }
}

@media (max-width: 560px){
  .footer-grid{ grid-template-columns: 1fr; }
  .service-row{ grid-template-columns: 1fr; }
  .trust-row{ justify-content: flex-start; }
  /* Auf schmalen Screens den Nav-CTA ausblenden: er ist über das Burger-Menü und
     die fixe .mobile-contact-bar ohnehin erreichbar und würde sonst den
     Firmennamen aus der Kopfzeile drängen. */
  .nav-right .btn-wrap{ display: none; }
}

/* ---------------------------------------------------------
   27. Reduced motion
--------------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  .chip-float{ animation: none; }
  .reveal{ opacity: 1; transform: none; transition: none; }
  .scroll-progress{ display: none; }
  .talk-item{ opacity: 1; transform: none; transition: none; }
  .talk-dots i{ animation: none; opacity: .6; }
  .ce-line.is-active .ce-caret{ animation: none; }
  .support-chips .chip-float{ animation: none; }
}

/* ---------------------------------------------------------
   28. Prozess-Schritte (nur prozess.html)
   Jeder der sechs Schritte ist ein eigener, gehobener Abschnitt
   mit einer eigenen Visualisierung. Der Ruhezustand jeder
   Animation ist immer ein vollständig lesbarer statischer Zustand.
--------------------------------------------------------- */
.pstep{ --section-pad: clamp(3.5rem, 7vw, 6rem); padding-block: var(--section-pad); border-top: 1px solid var(--border); }
.pstep:first-of-type{ border-top: 0; }
.pstep-grid{ display: grid; grid-template-columns: .85fr 1.15fr; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; }
.pstep-grid > *{ min-width: 0; }
.pstep.is-flip .pstep-copy{ order: 2; }

.pstep-index{ display: inline-flex; align-items: center; gap: .6rem; font-family: var(--font-mono); font-size: .8rem; color: var(--accent); margin-bottom: .9rem; }
.pstep-index::before{ content: ""; width: 26px; height: 1px; background: var(--accent); opacity: .6; }
/* Groesser gesetzt (war max 1.7rem): seit dem Kuerzungs-Pass steht darunter nur
   noch ein Satz, die Ueberschrift darf die freie Flaeche fuellen. Bleibt aber
   klar unter der Sektions-h2 (clamp bis 2.9rem) — sonst liest sich "Erstgespraech"
   beim Scrollen auf derselben Ebene wie "So arbeiten wir zusammen" und die Seite
   wirkt unuebersichtlich. */
.pstep-copy h2{ font-size: clamp(1.6rem, 1.5vw + 1rem, 2.25rem); margin-bottom: 1rem; }
.pstep-copy p{ max-width: 46ch; }
.pstep-points{ display: flex; flex-direction: column; gap: .55rem; margin-top: 1.3rem; }
.pstep-points li{ display: flex; gap: .6rem; font-size: .9rem; color: var(--text-2); }
.pstep-points li::before{ content: "+"; font-family: var(--font-mono); color: var(--accent); flex-shrink: 0; }

/* Bewusst ohne Rahmen, Hintergrund und Radius: die Visualisierungen sollen
   in die Seite übergehen und nicht als abgeschottete Karten wirken.
   Wo etwas beschnitten werden muss (Zoom, Laufband), übernimmt das eine
   weiche Maske (.soft-mask) statt einer harten Kante. */
.pstep-visual{
  position: relative;
  min-height: 320px; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}

/* Weiche Kanten statt sichtbarer Schnittkante */
.soft-mask{
  -webkit-mask-image: radial-gradient(ellipse 94% 94% at 50% 50%, #000 58%, transparent 100%);
  mask-image: radial-gradient(ellipse 94% 94% at 50% 50%, #000 58%, transparent 100%);
}

/* --- 01 Erstgespräch: Gesprächsblasen ------------------------------- */
.talk-stage{ width: 100%; padding: 1.6rem; display: flex; flex-direction: column; gap: .9rem; }
.talk-item{
  display: flex; gap: .7rem; align-items: flex-end;
  opacity: 0; transform: translateY(10px) scale(.97);
  transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out);
}
.talk-item.is-in{ opacity: 1; transform: none; }
.talk-item.is-me{ flex-direction: row-reverse; }
.talk-av{
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center;
  font-family: var(--font-mono); font-size: .6rem;
  border: 1px solid var(--border-strong); color: var(--text-3); background: var(--bg-2);
}
.talk-item.is-me .talk-av{ background: var(--accent); color: #04120E; border-color: var(--accent); }
.talk-bubble{
  max-width: 76%; padding: .7rem .95rem; border-radius: 12px;
  font-size: .88rem; line-height: 1.5;
  border: 1px solid var(--border); background: var(--bg-2); color: var(--text-2);
}
.talk-item.is-me .talk-bubble{ background: rgba(var(--accent-rgb), .10); border-color: rgba(var(--accent-rgb), .3); color: var(--text); }
.talk-dots{ display: inline-flex; gap: 4px; align-items: center; height: 1.1em; }
.talk-dots i{ width: 5px; height: 5px; border-radius: 50%; background: var(--text-3); animation: talkdot 1.2s infinite; }
.talk-dots i:nth-child(2){ animation-delay: .15s; }
.talk-dots i:nth-child(3){ animation-delay: .3s; }
@keyframes talkdot{
  0%, 60%, 100%{ opacity: .3; transform: translateY(0); }
  30%{ opacity: 1; transform: translateY(-3px); }
}

/* --- 02 Analyse: Lupe über dem Text --------------------------------
   Wichtig: .lens-stage hat KEIN padding. Das Padding sitzt auf
   .lens-text, damit Original und Klon exakt deckungsgleich sind
   (absolut positionierte Kinder messen ab der Padding-Kante). */
.lens-stage{ position: relative; width: 100%; overflow: hidden; }
.lens-text{ padding: 1.2rem .4rem; font-size: 1.12rem; line-height: 1.7; color: var(--text-2); }
.lens-text b{ color: var(--text); font-weight: 600; }
.lens-text .hl{ color: var(--accent); font-weight: 600; }
.lens{
  position: absolute; border-radius: 50%; overflow: hidden; pointer-events: none;
  background: var(--bg); /* deckend, sonst schimmert der Originaltext durch */
  opacity: 0; transition: opacity var(--t-med) var(--ease);
  box-shadow:
    0 0 0 1px rgba(var(--accent-rgb), .55),
    0 0 34px rgba(var(--accent-rgb), .26),
    inset 0 0 26px rgba(var(--accent-rgb), .10);
}
.lens.is-on{ opacity: 1; }
.lens-inner{ position: absolute; }

/* --- 03 Konzept: schematisch wechselnde Fläche ---------------------- */
.concept-stage{ position: relative; width: 100%; padding: .4rem; display: flex; flex-direction: column; gap: .75rem; }
.concept-frame{
  position: relative; width: 100%; aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  background: rgba(236,245,243,.035); border: 1px solid var(--border);
  box-shadow: 0 24px 50px -30px rgba(0,0,0,.5);
}
.cb{
  position: absolute; border-radius: 6px;
  border: 1px solid var(--border-strong); background: rgba(236,245,243,.06);
}
.cb.is-key{
  background: linear-gradient(120deg, rgba(var(--accent-rgb), .4), rgba(var(--accent-2-rgb), .4));
  border-color: rgba(var(--accent-rgb), .6);
  box-shadow: 0 0 22px -4px rgba(var(--accent-rgb), .55);
}
/* Zwei schmale Balken im hervorgehobenen Block, damit er wie ein
   angedeuteter Hero-Text statt wie eine leere Fläche aussieht. */
.cb-line{
  position: absolute; left: 8%; height: 9%; border-radius: 3px;
  background: rgba(255,255,255,.55);
}
.cb-line.l1{ top: 30%; width: 62%; }
.cb-line.l2{ top: 50%; width: 38%; }

.concept-label{
  align-self: flex-end;
  font-family: var(--font-mono); font-size: .7rem; color: var(--text-3);
}
.concept-label b{ color: var(--accent); font-weight: 500; }

/* Kleine Farbmuster, die andeuten, dass es zum Entwurf mehrere
   Farbrichtungen gibt — cyclen synchron zu Entwurf A/B/C (process.js). */
.concept-swatches{ display: flex; gap: .5rem; align-self: flex-end; }
.concept-swatch{
  width: 15px; height: 15px; border-radius: 50%;
  background: rgb(var(--sw)); opacity: .3; transform: scale(.8);
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease);
}
.concept-swatch.is-active{
  opacity: 1; transform: scale(1);
  box-shadow: 0 0 0 3px rgba(var(--sw), .22), 0 0 14px rgba(var(--sw), .55);
}

/* --- 04 Entwicklung: Code, der bearbeitet wird ---------------------- */
.code-edit{ width: 100%; padding: .4rem; font-family: var(--font-mono); font-size: .76rem; }
.ce-bar{ display: flex; align-items: center; gap: .45rem; margin-bottom: .9rem; }
.ce-dot{ width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); }
.ce-file{ margin-left: .5rem; color: var(--text-3); font-size: .7rem; }
.ce-lines{ display: flex; flex-direction: column; }
.ce-line{ display: flex; gap: .7rem; line-height: 1.9; padding-inline: .35rem; border-radius: 4px; }
.ce-n{ color: var(--text-3); opacity: .45; width: 1.7em; text-align: right; flex-shrink: 0; user-select: none; }
.ce-c{ white-space: pre; color: var(--text-2); }
.ce-line.is-active{ background: rgba(var(--accent-rgb), .08); }
/* inline-grid, nicht grid: als Block-Box würde .ce-swap den Caret in eine
   eigene Zeile drücken und eine Lücke in den Code reißen. Das Stapeln beider
   Varianten in derselben Grid-Zelle gibt der Zeile die Breite der längeren. */
.ce-swap{ display: inline-grid; vertical-align: top; }
.ce-old, .ce-new{ grid-area: 1 / 1; transition: opacity var(--t-med) var(--ease); }
.ce-new{ opacity: 0; }
.ce-line.is-done .ce-old{ opacity: 0; }
.ce-line.is-done .ce-new{ opacity: 1; }
.ce-ins{ height: 0; opacity: 0; overflow: hidden; }
.ce-ins.is-done{ height: auto; opacity: 1; }
.ce-caret{ display: inline-block; width: 2px; height: 1em; background: var(--accent); vertical-align: -.15em; opacity: 0; }
.ce-line.is-active .ce-caret{ opacity: 1; animation: ceblink .9s steps(1) infinite; }
@keyframes ceblink{ 50%{ opacity: 0; } }
.ce-tag{ color: var(--accent-2); }
.ce-attr{ color: var(--accent); }
.ce-str{ color: #FFD479; }

/* --- 05 Launch: rotierender Globus --------------------------------- */
.globe-section .pstep-visual{ flex-direction: column; gap: 1.1rem; padding: 1.8rem; min-height: 460px; }
.globe-wrap{ width: min(340px, 80%); }
.globe-canvas{ width: 100%; aspect-ratio: 1; }
.globe-caption{ text-align: center; max-width: 36ch; font-size: .92rem; color: var(--text-2); }
.globe-caption b{ color: var(--accent); font-weight: 600; }

/* --- 06 Betreuung: Fragezeichen ------------------------------------ */
.support-stage{ position: relative; width: 100%; min-height: 340px; display: grid; place-items: center; }
.support-mark{
  font-family: var(--font-display); font-weight: 700; font-size: clamp(7rem, 14vw, 11rem); line-height: 1;
  color: transparent; -webkit-text-stroke: 1.5px rgba(var(--accent-rgb), .38);
}
.support-chips{ position: absolute; inset: 0; }
.support-chips .chip-float{ position: absolute; font-size: .76rem; padding: .5rem .85rem; }
.support-chips .s1{ top: 12%; left: 6%; }
.support-chips .s2{ top: 26%; right: 7%; }
.support-chips .s3{ bottom: 24%; left: 9%; }
.support-chips .s4{ bottom: 12%; right: 10%; }

@media (max-width: 980px){
  .pstep-grid{ grid-template-columns: 1fr; }
  .pstep.is-flip .pstep-copy{ order: 0; }
  .pstep-visual{ min-height: 300px; }
  .globe-section .pstep-visual{ min-height: 400px; }
  .support-chips .chip-float{ font-size: .72rem; }
}

@media (max-width: 560px){
  .lens-text{ padding: 1rem .2rem; font-size: 1rem; }
  .code-edit{ font-size: .68rem; }
  .support-chips .s1, .support-chips .s3{ left: 2%; }
  .support-chips .s2, .support-chips .s4{ right: 2%; }
}

/* ---------------------------------------------------------
   29. Leistungs-Abschnitte (leistungen.html)
   Nutzt das .pstep-Raster mit, hat aber eigene Visualisierungen.
   Alles rahmenlos, Beschnitt nur über weiche Masken.
--------------------------------------------------------- */
.lcaption{ margin-top: 1.2rem; font-size: .86rem; line-height: 1.6; color: var(--text-3); max-width: 44ch; text-align: center; }
.lmore{ display: inline-block; margin-top: 1.2rem; font-family: var(--font-mono); font-size: .82rem; color: var(--accent); }
.lmore:hover{ text-decoration: underline; text-underline-offset: 4px; }

/* --- gemeinsame Mini-Website-Bausteine -----------------------------
   Nur von .wb-site (Leistung 01) benutzt. Die Bausteine tragen bewusst
   Innenleben (Logo, Menue, Hero-Zeilen, Karten-Icons): als reine graue
   Kaesten wirkte das Mockup billig. Alles reine Form, kein Text. */
.mock{ display: flex; flex-direction: column; gap: .55rem; width: 100%; }

.mock-nav{ display: flex; align-items: center; gap: .5rem; }
.mock-logo{
  flex-shrink: 0; width: 20px; height: 20px; border-radius: 6px;
  background: linear-gradient(140deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 12px rgba(var(--accent-rgb), .35);
}
.mock-menu{ display: flex; gap: .45rem; margin-left: auto; }
.mock-menu i{ width: 24px; height: 5px; border-radius: 3px; background: rgba(236,245,243,.16); }
.mock-menu i:nth-child(2){ width: 30px; }

.mock-hero{
  position: relative; overflow: hidden;
  height: 44px; border-radius: 8px; padding: .7rem .9rem;
  display: flex; flex-direction: column; justify-content: center; gap: .35rem;
  background: linear-gradient(100deg, var(--accent), var(--accent-2)); opacity: .9;
}
.mock-hero::after{
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(118deg, rgba(255,255,255,.18) 0%, transparent 44%);
}
.mock-hl{ position: relative; z-index: 1; height: 7px; border-radius: 4px; background: rgba(7,9,13,.38); }
.mock-hl.a{ width: 54%; }
.mock-hl.b{ width: 34%; height: 5px; background: rgba(7,9,13,.24); }
.mock-pill{
  position: relative; z-index: 1; margin-top: .2rem;
  width: 56px; height: 13px; border-radius: 999px; background: rgba(255,255,255,.55);
}

.mock-l{ height: 7px; border-radius: 4px; background: rgba(236,245,243,.14); }
.mock-l.w1{ width: 88%; } .mock-l.w2{ width: 64%; }
.mock-row{ display: flex; gap: .55rem; margin-top: .2rem; }
.mock-card{
  flex: 1; height: 46px; border-radius: 8px; padding: .55rem .6rem;
  display: flex; flex-direction: column; gap: .3rem;
  border: 1px solid var(--border); background: rgba(236,245,243,.04);
}
.mock-ic{ flex-shrink: 0; width: 13px; height: 13px; border-radius: 4px; background: rgba(var(--accent-rgb), .5); }
.mock-cl{ height: 4px; border-radius: 2px; background: rgba(236,245,243,.14); }
.mock-cl.a{ width: 84%; } .mock-cl.b{ width: 56%; }
.mock-btn{ width: 92px; height: 24px; border-radius: 6px; background: var(--accent); margin-top: .3rem; }

/* --- 01 Website-Erstellung: Code geht in die fertige Seite über ----- */
.wb-stage{ position: relative; width: 100%; aspect-ratio: 4 / 3.1; --wb: .55; }
.wb-layer{ position: absolute; inset: 0; }
.wb-code{
  font-family: var(--font-mono); font-size: .72rem; line-height: 1.95; color: var(--text-2);
  clip-path: inset(calc(var(--wb) * 100%) 0 0 0);
}
.wb-code .cl{ white-space: pre; }
.wb-code .t{ color: var(--accent-2); } .wb-code .a{ color: var(--accent); } .wb-code .s{ color: #FFD479; }
.wb-site{ clip-path: inset(0 0 calc(100% - var(--wb) * 100%) 0); justify-content: flex-start; }
/* der Hero nimmt die Resthöhe auf, damit die Mock-Seite die Fläche füllt
   und beim Übergang keine tote Zone entsteht */
/* Der Hero nimmt hier die Resthöhe auf und wird dadurch sehr hoch. Sein
   Innenleben gehört deshalb an den unteren Rand (wie in einem echten Hero),
   mittig zentriert wirkte es in der großen Fläche verloren. */
.wb-site .mock-hero{ flex: 1; min-height: 90px; justify-content: flex-end; }
.wb-site .mock-card{ height: 74px; }
.wb-scan{
  position: absolute; left: -2%; right: -2%; top: calc(var(--wb) * 100%); height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  box-shadow: 0 0 14px rgba(var(--accent-rgb), .75);
}

/* --- 02 Redesign: Farbe und Aufbau ändern sich -------------------- */
.rd-stage{ position: relative; width: 100%; display: flex; flex-direction: column; }
.rd-frame{ position: relative; width: 100%; aspect-ratio: 4 / 3; }
/* overflow:hidden ist hier Pflicht: GSAP schrumpft die Bloecke im alten
   Zustand deutlich (z. B. Hero von 40% auf 18% Hoehe), das Innenleben darf
   dabei nicht herausragen. */
.rb{ position: absolute; overflow: hidden; }
.rb-glow{ position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(100deg, var(--accent), var(--accent-2)); }

/* Innenleben der Redesign-Bloecke. KEINE weiteren .rb-Elemente anlegen —
   services.js prueft blocks.length !== 6 und steigt sonst stillschweigend
   aus. Die Zeilen sind hell statt dunkel gehalten, damit sie sowohl auf der
   grauen Vorher-Flaeche als auch auf dem hellen Nachher-Verlauf lesbar
   bleiben; ein Klassenwechsel je Zustand gibt es hier nicht, die Animation
   laeuft ausschliesslich ueber Inline-Styles auf den .rb selbst. */
.rb-nav{ display: flex; align-items: center; gap: 6px; padding: 0 8px; }
.rd-dot{ flex-shrink: 0; width: 11px; height: 11px; border-radius: 3px; background: rgba(var(--accent-rgb), .6); }
.rd-bar{ flex-shrink: 0; width: 15px; height: 4px; border-radius: 2px; background: rgba(236,245,243,.24); }
.rd-bar.is-first{ margin-left: auto; }

.rb-hero{ display: flex; flex-direction: column; justify-content: center; gap: 7px; padding: 0 14px; }
/* ueber .rb-glow legen: der Glow ist position:absolute und wuerde die
   in-flow-Kinder sonst verdecken, sobald er eingeblendet wird. */
.rd-hl, .rd-pill{ position: relative; z-index: 1; }
.rd-hl{ height: 7px; border-radius: 4px; background: rgba(255,255,255,.45); }
.rd-hl.a{ width: 52%; }
.rd-hl.b{ width: 34%; height: 5px; background: rgba(255,255,255,.28); }
.rd-pill{ margin-top: 2px; width: 58px; height: 13px; border-radius: 999px; background: rgba(255,255,255,.55); }

.rb-card{ display: flex; flex-direction: column; justify-content: center; gap: 5px; padding: 0 10px; }
.rd-ic{ flex-shrink: 0; width: 13px; height: 13px; border-radius: 4px; background: rgba(var(--accent-rgb), .55); margin-bottom: 2px; }
.rd-ln{ height: 4px; border-radius: 2px; background: rgba(236,245,243,.20); }
.rd-ln.a{ width: 82%; } .rd-ln.b{ width: 55%; }
.rd-tag{
  align-self: flex-end; font-family: var(--font-mono); font-size: .7rem; color: var(--text-3); margin-bottom: .6rem;
}
.rd-tag b{ color: var(--accent); font-weight: 500; }

/* --- 03 Mobile: aus dem Laptop ins Handy zoomen ------------------- */
/* Der ganze Aufbau (.mo-zoom) wird beim Scrollen hochskaliert; Zielpunkt ist
   die Bildmitte = Mittelpunkt des Handys. Scharnier (.mo-hinge) und Deck
   (.mo-base) hängen per position:absolute UNTER dem Deckel und zählen damit
   NICHT zur Zentrierung — so trifft place-items:center exakt die
   Bildschirmmitte, und mit transform-origin: 50% 50% wächst das Handy beim
   Zoom auf der Stelle, wandert also nicht nach unten aus der .soft-mask
   heraus (das war die Ursache für den abgeschnittenen unteren Handyrand).
   Der --mz-Endwert in services.js ist so gewählt, dass das Handy am Ende rund
   80 % der Bühnenhöhe füllt und mit Rand komplett sichtbar bleibt. */
.mo-stage{ position: relative; width: 100%; aspect-ratio: 4 / 3; overflow: hidden; --mz: 1.25; }
.mo-zoom{
  position: absolute; inset: 0; display: grid; place-items: center;
  transform: scale(var(--mz)); transform-origin: 50% 50%;
}

/* Laptop */
.mo-laptop{ position: relative; width: 56%; }
.mo-lid{
  position: relative;
  border: 1.5px solid var(--border-strong); border-radius: 10px 10px 7px 7px;
  background: linear-gradient(180deg, rgba(238,241,246,.10), var(--bg-2) 30%);
  padding: 7px 7px 8px;
  box-shadow:
    0 26px 46px -20px rgba(0,0,0,.7),
    0 0 44px -14px rgba(var(--accent-rgb), .20),
    inset 0 1px 0 rgba(238,241,246,.10);
}
/* Kamera im oberen Rahmen — macht den Deckel als solchen erkennbar */
.mo-cam{
  position: absolute; top: 3px; left: 50%; transform: translateX(-50%);
  width: 3.5px; height: 3.5px; border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(238,241,246,.6), rgba(238,241,246,.12) 60%, transparent);
}
.mo-screen{
  position: relative; aspect-ratio: 16 / 10;
  border-radius: 3px; overflow: hidden;
  background: radial-gradient(120% 140% at 50% 0%, #0e1220, var(--bg) 70%);
  border: 1px solid rgba(238,241,246,.06);
  display: grid; place-items: center;
}
/* Glasglanz über dem Screen */
.mo-screen::after{
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(120deg, rgba(238,241,246,.10), transparent 44%);
  box-shadow: inset 0 0 30px rgba(0,0,0,.5);
}
/* Scharnier + Deck: absolut unter dem Deckel, ohne die Zentrierung zu verschieben */
.mo-hinge{
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  width: 22%; height: 4px; border-radius: 0 0 3px 3px;
  background: linear-gradient(180deg, var(--border-strong), rgba(0,0,0,.5));
}
.mo-base{
  position: absolute; top: calc(100% + 3px); left: 50%; transform: translateX(-50%);
  width: 122%; height: 10px; border-radius: 2px 2px 11px 11px;
  background: linear-gradient(180deg, var(--elevated), var(--border-strong) 40%, rgba(0,0,0,.55));
  box-shadow: 0 14px 22px -12px rgba(0,0,0,.7);
}
/* Trackpad-Andeutung an der Vorderkante */
.mo-pad{
  position: absolute; top: 2px; left: 50%; transform: translateX(-50%);
  width: 24%; height: 3px; border-radius: 0 0 4px 4px; background: rgba(0,0,0,.4);
}

/* Handy im Laptop-Screen — klar als Smartphone erkennbar:
   Dynamic Island, Seitentaste, Home-Indikator, gerundete Ecken. */
.mo-phone{
  position: relative;
  width: 24%; aspect-ratio: 9 / 18.5; border-radius: 17% / 8%;
  border: 1.5px solid rgba(var(--accent-rgb), .6);
  background: linear-gradient(180deg, #12131c, var(--surface));
  padding: 9% 8% 9%;
  display: flex; flex-direction: column; gap: 5%;
  box-shadow:
    0 0 20px rgba(var(--accent-rgb), .26),
    inset 0 1px 0 rgba(238,241,246,.14);
}
/* Dynamic Island */
.mo-island{
  position: absolute; top: 3.4%; left: 50%; transform: translateX(-50%);
  width: 34%; height: 4.2%; border-radius: 999px; background: #000;
}
/* Seitentaste */
.mo-side{
  position: absolute; right: -3px; top: 25%; width: 2.5px; height: 12%;
  border-radius: 2px; background: rgba(var(--accent-rgb), .55);
}
/* Reine Draht-Andeutung einer mobilen Seite im Handy — kein Text, damit nichts
   über das Format hinauswachsen kann; der Erklärsatz steht links in .pstep-copy. */
.mo-bar{ height: 7%; border-radius: 3px; background: linear-gradient(90deg, var(--accent), var(--accent-2)); flex-shrink: 0; }
.mo-block{ height: 30%; border-radius: 4px; background: rgba(var(--accent-rgb), .16); flex-shrink: 0; }
.mo-line{ height: 4.5%; border-radius: 3px; background: rgba(236,245,243,.18); flex-shrink: 0; }
.mo-line.is-short{ width: 58%; }
.mo-cta{ margin-top: auto; height: 9%; width: 66%; border-radius: 999px; background: rgba(var(--accent-rgb), .5); flex-shrink: 0; }
/* Home-Indikator */
.mo-home{
  position: absolute; bottom: 2.6%; left: 50%; transform: translateX(-50%);
  width: 30%; height: 2%; border-radius: 999px; background: rgba(236,245,243,.4);
}

/* --- 04 SEO: Trefferliste fährt nach oben, Platz 1 leuchtet ------- */
.seo-screen{
  position: relative; width: 100%; aspect-ratio: 4 / 3; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%);
}
/* padding-top schiebt Platz 1 aus der oberen Weichzeichnung der Maske
   heraus, sonst endet der Lauf mit einem halb ausgeblendeten Treffer */
.seo-list{ position: absolute; left: 0; right: 0; top: 0; display: flex; flex-direction: column; gap: .5rem; padding: 4.6rem .2rem .2rem; }
.seo-result{
  display: flex; align-items: center; gap: .7rem; padding: .65rem .75rem; border-radius: 9px;
  border: 1px solid var(--border); background: rgba(236,245,243,.03);
}
.seo-rank{ font-family: var(--font-mono); font-size: .7rem; color: var(--text-3); width: 1.5em; flex-shrink: 0; }
.seo-lines{ flex: 1; display: flex; flex-direction: column; gap: .32rem; min-width: 0; }
.seo-l{ height: 6px; border-radius: 3px; background: rgba(236,245,243,.11); }
.seo-l.a{ width: 62%; } .seo-l.b{ width: 88%; }
.seo-result.is-mine{ border-color: rgba(var(--accent-rgb), .5); background: rgba(var(--accent-rgb), .08); }
.seo-result.is-mine .seo-rank{ color: var(--accent); }
.seo-result.is-mine .seo-l{ background: linear-gradient(90deg, var(--accent), var(--accent-2)); opacity: .9; }
.seo-badge{ font-family: var(--font-mono); font-size: .62rem; color: var(--accent); white-space: nowrap; }
.seo-result.is-lit{ box-shadow: 0 0 0 1px rgba(var(--accent-rgb), .55), 0 0 38px rgba(var(--accent-rgb), .40); }

/* --- 05 Conversion: Kundenchat (nutzt .talk-* mit) ---------------- */
.talk-done{
  align-self: center; margin-top: .5rem;
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--font-mono); font-size: .72rem; color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .4); background: rgba(var(--accent-rgb), .10);
  border-radius: 999px; padding: .4rem .85rem;
  opacity: 0; transform: translateY(8px) scale(.96);
  transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out);
}
.talk-done.is-in{ opacity: 1; transform: none; }

/* --- 06 Betreuung: Notizblock mit neuen Wünschen ------------------ */
.note-pad{ width: 100%; max-width: 420px; }
.note-head{ display: flex; align-items: center; gap: .55rem; font-family: var(--font-mono); font-size: .72rem; color: var(--text-3); margin-bottom: 1rem; }
.note-head::before{ content: ""; width: 7px; height: 7px; border-radius: 2px; background: var(--accent); }
.note-item{
  display: flex; align-items: center; gap: .8rem;
  padding: .68rem 0; border-bottom: 1px solid var(--border);
  font-size: .92rem; color: var(--text-2);
}
.note-box{
  width: 17px; height: 17px; border-radius: 5px; flex-shrink: 0;
  border: 1px solid var(--border-strong); display: grid; place-items: center;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.note-box svg{ width: 10px; height: 10px; color: var(--accent); opacity: 0; transform: scale(.5); transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out); }
.note-item.is-done .note-box{ border-color: rgba(var(--accent-rgb), .55); background: rgba(var(--accent-rgb), .12); }
.note-item.is-done .note-box svg{ opacity: 1; transform: none; }
.note-item.is-done .note-text{ color: var(--text-3); text-decoration: line-through; text-decoration-color: rgba(236,245,243,.28); }
.note-item.is-fresh{ color: var(--text); }
.note-item.is-fresh .note-box{ border-color: rgba(var(--accent-rgb), .5); }
.note-new{ opacity: 0; transform: translateY(-8px); transition: opacity var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-out); }
.note-new.is-in{ opacity: 1; transform: none; }

@media (max-width: 980px){
  .lcaption{ text-align: left; }
  .wb-stage, .mo-stage, .seo-screen, .rd-frame{ aspect-ratio: 4 / 3.2; }
}

@media (max-width: 560px){
  .wb-code{ font-size: .62rem; line-height: 1.8; }
  .seo-result{ padding: .5rem .6rem; }
}

/* ---------------------------------------------------------
   30. Oberflächen-Ebenen (Redesign-Pass)
   surface-deep bleibt unangetastet (= var(--bg), Raster sichtbar).
   surface-raised/-light sind DECKEND — das verdeckt das animierte
   Hintergrund-Raster innerhalb der Sektion und ist selbst schon der
   Haupt-Kontrast, nicht nur die Farbe.

   Die Naht ist eine schräge Kante statt eines Verlaufs (passt zum
   Blueprint/Schaltplan-Charakter der Seite). Technik: ein ::before/::after
   auf der Sektion, das NICHT den echten Content clippt, sondern nur einen
   flächigen, gleichfarbigen Keil in die Nachbarsektion hinein schiebt.
   .slant-top/.slant-bottom werden nur an den tatsächlichen Farbwechseln
   von Hand gesetzt (nicht pauschal auf jede surface-raised/-light-Sektion),
   sonst zerschneidet die Naht auch gleichfarbige Nachbarn.
--------------------------------------------------------- */
/* position:relative + z-index:0 erzwingt einen eigenen Stacking-Context für
   jede Sektion: nur dadurch landet ein Kind-::before mit z-index:-1 (die
   Gradient-Mesh-Blobs, Abschnitt 44) garantiert VOR der eigenen
   background-color, aber HINTER dem Content. Ohne den eigenen Context könnte
   das Kind stattdessen hinter einen entfernteren Vorfahren rutschen und
   dauerhaft unsichtbar bleiben. */
.surface-raised{ background-color: var(--surface-raised); position: relative; z-index: 0; }
.surface-light{ background-color: var(--surface-light); position: relative; z-index: 0; }

.slant-top, .slant-bottom{ position: relative; }
.slant-top{ padding-top: calc(var(--section-pad, 4rem) + var(--slant)); margin-top: calc(var(--slant) * -1); }
.slant-bottom{ padding-bottom: calc(var(--section-pad, 4rem) + var(--slant)); margin-bottom: calc(var(--slant) * -1); }
.slant-top::before, .slant-bottom::after{
  content: ""; position: absolute; left: 0; right: 0; height: var(--slant);
  background-color: inherit; pointer-events: none;
}
/* -99% statt -100% war als kleiner Sicherheits-Überlapp gedacht, ist aber
   ein Prozentwert der eigenen Höhe (--slant, 2.5-4.5rem) — auf hochauf-
   lösenden Android-Bildschirmen (hier getestet: 1080x2340, DPR ~3) bleiben
   davon oft weniger als 1 Gerätepixel übrig, sichtbar als feine Naht/Linie.
   calc(-100% + 1px) überlappt stattdessen um einen festen Geräte-Pixel,
   unabhängig von --slant und der Bildschirmauflösung. */
.slant-top::before{ top: 0; transform: translateY(calc(-100% + 1px)); clip-path: polygon(0 100%, 100% 0%, 100% 100%); }
.slant-bottom::after{ bottom: 0; transform: translateY(calc(100% - 1px)); clip-path: polygon(0 0%, 100% 100%, 0% 100%); }

/* Direkte Prosa auf surface-light: eigene Ink-Farben, präzise auf die
   Container gezielt, die WIRKLICH direkt auf der hellen Fläche stehen
   (.section-head, .pstep-copy) — bewusst NICHT als blanke h1/h2/h3/p/
   .eyebrow-Regel, sonst greift sie auch in eingebettete dunkle Karten
   hinein (.price-card, .care-tier-card hatten genau das: schwarzer Text auf
   dunkler Karte, praktisch unsichtbar — beim Screenshot-Check gefunden). */
.surface-light .section-head .eyebrow,
.surface-light .pstep-index{ color: var(--accent-ink); }
.surface-light .section-head h2,
.surface-light .pstep-copy h2{ color: var(--ink); }
.surface-light .section-head .lede,
.surface-light .pstep-copy p,
.surface-light .pstep-points li{ color: var(--ink-2); }
.surface-light .pstep-points li::before{ color: var(--accent-ink); }
.surface-light .lcaption{ color: var(--ink-2); }
.surface-light .price-note{ color: var(--ink-2); }
.surface-light a.prose-link{ color: var(--accent-ink); }
.surface-light a.prose-link:hover{ text-decoration-color: var(--accent-ink); }

/* Kundenfeedback: seit dem Kuerzungs-Pass steht unter jeder Prozess-Ueberschrift
   nur noch ein Satz, die helle surface-light-Flaeche wirkt dadurch leer im
   Verhaeltnis zum Text. Nur hier (.pstep.surface-light, trifft ausschliesslich
   die sechs Prozess-Schritte, nicht #leistungen) Typografie und Innenabstand
   nochmal angehoben, Farben/Flaeche selbst bleiben unveraendert. Die
   .pstep-copy-h2-Obergrenze bleibt bewusst bei 2.35rem, mindestens 0.5rem
   unter der Sektions-h2 (clamp bis 2.9rem) -- siehe Guardrail in CLAUDE.md,
   sonst liest sich eine Schritt-Ueberschrift wieder wie die Sektionsueberschrift
   darueber. */
.pstep.surface-light{ --section-pad: clamp(2.75rem, 5vw, 4.5rem); }
.surface-light .pstep-index{ font-size: 1.05rem; font-weight: 700; margin-bottom: 1.1rem; }
.surface-light .pstep-index::before{ width: 34px; height: 2px; }
.surface-light .pstep-copy h2{ font-size: clamp(1.75rem, 1.6vw + 1.05rem, 2.35rem); }
.surface-light .pstep-copy p{ font-size: clamp(1rem, .3vw + .92rem, 1.08rem); max-width: 36ch; }

/* Zwei .pstep-visual-Ausnahmen ohne eigenen dunklen Hintergrund (Analyse-
   Lupentext, Betreuung-Fragezeichen): Farbe angepasst, damit sie auf
   hellem Grund lesbar bleiben. Verhalten/Animation unverändert. */
.surface-light .lens-text{ color: var(--ink-2); }
.surface-light .lens-text b{ color: var(--ink); }
.surface-light .lens-text .hl{ color: var(--accent-ink); }
.surface-light .lens{ background-color: var(--surface-light); }
.surface-light .support-mark{ -webkit-text-stroke-color: rgba(86,71,224,.45); }

/* Drei weitere .pstep-visual-Ausnahmen im Prozess-Schritt: durch die
   frühere "Kästen entfernen"-Aufgabe haben diese KEINEN eigenen
   Hintergrund mehr und wurden für einen dunklen Seitenhintergrund
   eingefärbt (heller Weiß-Ton bei niedriger Deckkraft). Auf hellem
   Grund unsichtbar bzw. der Code-Editor unlesbar. Konzept-Flächen und
   Beschriftung bekommen dunkel getönte Werte, der Code-Editor bekommt
   gezielt seine dunkle Insel zurück — ein Code-Editor darf dunkel
   bleiben, das ist kein Rückfall in den Kästen-Look von vorher. */
.surface-light .concept-frame{
  background: rgba(20,21,29,.05); border-color: rgba(20,21,29,.16);
  box-shadow: 0 20px 46px -28px rgba(20,21,29,.35);
}
.surface-light .cb{ background: rgba(20,21,29,.07); border-color: rgba(20,21,29,.16); }
/* .cb.is-key blieb hier bisher ungezielt beim hellen Akzent-Verlauf aus dem
   Grundzustand (rgba(accent-rgb) auf einem selbst hell-blauvioletten
   Seitenhintergrund) — kaum vom Rest zu unterscheiden. Eigener, deutlich
   dunklerer Ton, damit der hervorgehobene Block auf surface-light wirklich
   heraussticht statt fast zu verschwinden. */
.surface-light .cb.is-key{
  background: linear-gradient(120deg, rgba(20,21,29,.2), rgba(46,38,128,.32));
  border-color: rgba(20,21,29,.42);
  box-shadow: 0 0 20px -4px rgba(20,21,29,.35);
}
.surface-light .concept-label{ color: var(--ink-2); }
.surface-light .concept-label b{ color: var(--accent-ink); }
.surface-light .code-edit{
  background: var(--bg-2); border-radius: var(--radius-sm);
  padding: 1rem 1.2rem; box-shadow: 0 20px 50px -26px rgba(20,21,29,.4);
}
.surface-light .globe-caption{ color: var(--ink-2); }
.surface-light .globe-caption b{ color: var(--accent-ink); }
/* .is-me-Blase ist nur 10% Akzent-getönt, keine echte dunkle Insel —
   ihr Text war auf --text (fast-weiß) getrimmt und wird auf hellem
   Grund unsichtbar. */
.surface-light .talk-item.is-me .talk-bubble{ color: var(--ink); }

/* Kein pauschaler Button-Override für surface-light: fast jeder Button auf
   dieser Seite sitzt in einer dunklen Karte (.price-card, .care-tier-card),
   nie direkt auf der hellen Fläche — die normale (dunkle) Button-Optik ist
   dort schon richtig. Ein früherer Versuch, sie hier zu "invertieren",
   hat stattdessen dunklen Text auf dunklen Karten erzeugt (praktisch
   unsichtbar, per Screenshot gefunden).
   Eine Ausnahme gibt es seit den Betreuungsstufen: .care-tiers-cta legt den
   "Im Erstgespräch klären"-Button direkt auf surface-light. Kein Override
   nötig, weil .btn-primary ein eigenes, fast deckendes helles Glas mitbringt
   (kein transparentes .btn-ghost) — geprüft per Screenshot, liest sich auch
   dort klar vom Hintergrund ab. Falls hier künftig auch mal .btn-ghost direkt
   auf surface-light landet, gezielt neu behandeln, nicht pauschal. */

/* Gefundener Bug beim Nachziehen dieses Kommentars: er schloss vorher nicht,
   dadurch verschluckte er die komplette Fokus-Ring-Regel direkt darunter
   (samt echtem CSS) unbemerkt, kein Parser-Fehler, nur stumm keine
   :focus-visible-Ringe site-weit. Jetzt geschlossen — Vorsicht bei künftigen
   Bearbeitungen dieses Kommentars. */

/* ---------------------------------------------------------
   31. Fokus-Ring — generisch, alle drei Oberflächen
--------------------------------------------------------- */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible{
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px;
}
/* --accent misst nur 1.25:1 auf --surface-light (braucht 3:1 als UI-Element). NICHT als
   ".surface-light :focus-visible" lösen — das ist ein Nachfahren-Selektor und träfe auch
   Buttons innerhalb dunkler Inseln (.price-card, .cta-band, .care-tier-card), die selbst auf
   --accent focus-visible weiterhin gut stehen (6.72:1); dort auf --accent-ink zu wechseln
   würde sie auf 2.13:1 kaputt machen. Deshalb gezielt nur auf .prose-link — die einzige
   für nackten Text auf surface-light vorgesehene Link-Klasse (s. Abschnitt 30), aktuell
   nirgends aber schon reserviert. --accent-ink misst 5.66:1 auf --surface-light. */
.surface-light a.prose-link:focus-visible{ outline-color: var(--accent-ink); }

/* ---------------------------------------------------------
   32. Team-Sektion ("Wer dahinter steckt")
   Bewusst kein Karten-Grid mit gleich großen Kacheln — zwei große
   Personen-Blöcke, kein Icon/Badge-Look.
--------------------------------------------------------- */
.team-section{ overflow: hidden; }

/* Bild 8, seit 17.09.2026 ein echtes Foto (vorher Platzhalter mit
   gestricheltem Rahmen, `.tp-label`/`.tp-path` — beide Regeln entfernt,
   `.team-photo` ist damit die letzte offene Bildfläche der Seite und wird
   nicht mehr gebraucht). Ein gemeinsames Foto statt zweier getrennter
   Porträts, da beide Gründer sich keine Aufgaben aufteilen, sondern
   gleichmäßig zusammenarbeiten — die Bildsprache soll das spiegeln. */
.team-photo-duo{
  position: relative; overflow: hidden;
  aspect-ratio: 16 / 10; max-width: 640px; border-radius: var(--radius);
  margin: 0 auto clamp(2rem, 4vw, 2.75rem);
}
.team-photo-duo img{ width: 100%; height: 100%; object-fit: cover; display: block; }

/* Zwei eigene Bios statt einer gemeinsamen Überschrift + Rollentext (bis
   17.09.2026 stand hier "wir teilen uns keine festen Rollen …", auf
   Kundenwunsch ersetzt: Leon links, Julian rechts, spiegelt ihre Position
   im gemeinsamen Foto darüber). Max-width matcht die Fotobreite, damit die
   beiden Spalten optisch unter den beiden Personen im Bild stehen. */
.team-bios{
  display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;
  max-width: 640px; margin: 0 auto clamp(2.5rem, 5vw, 4rem);
}
.team-bio{ text-align: center; }
.team-bio h3{ font-size: 1.2rem; margin-bottom: .3rem; }
.team-bio .team-role{ font-family: var(--font-mono); font-size: .76rem; color: var(--accent); margin-bottom: .6rem; }
.team-bio p:last-child{ font-size: .92rem; color: var(--text-2); }

@media (max-width: 560px){
  .team-bios{ grid-template-columns: 1fr; gap: 1.75rem; }
}

.team-outro{ max-width: 62ch; margin: 0 auto; text-align: center; }
.team-outro p{ margin-bottom: .6rem; }
.team-outro p:last-child{ margin-bottom: 0; }

/* `ueber-uns.html`: eigenes Team-Bild je Person statt des gemeinsamen
   Duo-Fotos von der Startseite — dort gibt es mehr Platz, um beide
   einzeln vorzustellen. `.team-role` bewusst dieselbe Regel wie
   `.team-bio .team-role` (Mono-Font, Akzentfarbe), nur auf diesen neuen
   Kartentyp erweitert, damit beide Stellen konsistent aussehen. */
.about-team{ display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem; margin-top: 2.5rem; }
.about-team-photo{
  position: relative; overflow: hidden;
  aspect-ratio: 1 / 1; max-width: 280px; border-radius: var(--radius);
  margin-bottom: 1.25rem;
}
.about-team-photo img{ width: 100%; height: 100%; object-fit: cover; display: block; }
.about-team-card h3{ font-size: 1.3rem; margin-bottom: .3rem; }
.about-team-card .team-role,
.team-bio .team-role{ font-family: var(--font-mono); font-size: .78rem; color: var(--accent); margin-bottom: .7rem; }
.about-team-card p:last-child{ color: var(--text-2); max-width: 42ch; }

@media (max-width: 700px){
  .about-team{ grid-template-columns: 1fr; gap: 2rem; }
  .about-team-photo{ max-width: 220px; }
}

/* Grundsätze-Liste (`ueber-uns.html`, "Wie wir arbeiten"): bewusst keine
   Chip-Bubbles (wirkte laut Kundenfeedback "billig") und keine
   1-2-3-4-Aufzählung (zu generisch). Stattdessen eine ruhige, editorielle
   Liste mit Haarlinie zwischen den Zeilen und demselben kurzen Akzent-Strich
   wie `.pstep-index::before` an anderer Stelle der Seite — Wiederverwendung
   des bestehenden "Blueprint-Tick"-Motivs statt eines neuen Icons. */
.principles-list{ max-width: 640px; margin-top: .5rem; border-top: 1px solid var(--border); }
.principles-list li{
  position: relative;
  padding: 1.05rem 0 1.05rem 1.85rem;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-display); font-size: 1.05rem; font-weight: 600;
}
.principles-list li::before{
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 22px; height: 2px; background: var(--accent); opacity: .8;
}

/* ---------------------------------------------------------
   33. Mobile Kontaktleiste
   Fixe Leiste, erst sichtbar sobald der Hero aus dem Bild scrollt
   (main.js), nur unter 768px. Body-Padding verhindert, dass sie den
   Footer verdeckt.
--------------------------------------------------------- */
.mobile-contact-bar{
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  padding: .7rem .9rem; padding-bottom: calc(.7rem + env(safe-area-inset-bottom, 0px));
  background: rgba(7,9,13,.92);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border-top: 1px solid var(--border-strong);
  gap: .7rem;
  transform: translateY(100%);
  transition: transform var(--t-med) var(--ease-out);
}
.mobile-contact-bar.is-visible{ transform: translateY(0); }
.mcb-row{ display: flex; gap: .7rem; }
.mcb-link{
  flex: 1; display: flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .8rem 1rem; border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: .85rem; font-weight: 500;
  border: 1px solid var(--border-strong); color: var(--text);
}
.mcb-link.is-primary{ background: var(--accent); color: #04120E; border-color: var(--accent); }
.mcb-link svg{ width: 17px; height: 17px; flex-shrink: 0; }

@media (max-width: 768px){
  .mobile-contact-bar{ display: flex; }
  /* + safe-area-inset-bottom: auf Geräten mit Home-Indicator/Gesten-Leiste
     ist die Leiste selbst durch ihr eigenes padding-bottom (s. oben) höher
     als die hier reservierten 76px allein abdecken würden. */
  body{ padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
}
@media (prefers-reduced-motion: reduce){
  .mobile-contact-bar{ transition: none; }
}

/* ---------------------------------------------------------
   34. (entfernt) Laufband — Pass 3, A3.
   War eine durchlaufende Leiste mit den Leistungsnamen zwischen Leistungen
   und Referenzen. Auf Kundenwunsch entfernt: wiederholte nur die Sektion
   direkt darüber, war Dauerbewegung ohne Nutzerauslöser, und ist eines der
   am häufigsten kopierten Deko-Elemente überhaupt — kostet Aufmerksamkeit,
   liefert keine Information. main.js: initMarquee() und der zugehörige
   Aufruf sind ebenfalls entfernt.
--------------------------------------------------------- */

/* ---------------------------------------------------------
   35. Hilfsklassen
--------------------------------------------------------- */
.visually-hidden{
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------
   36. Paket-Vergleichstabelle (#preise)
   Die drei .price-card listen je fünf *verschiedene* Stichpunkte und sind
   dadurch nicht vergleichbar. Diese Tabelle ordnet dieselben Aussagen auf
   gemeinsame Zeilen. Karten = emotionale Ebene mit CTA, Tabelle = rationale
   Vergleichsebene. Keine neuen Leistungsversprechen.

   Liegt auf surface-light: Textfarben über --ink/--ink-2, nie über --text.
   Alle Selektoren sind auf .compare-* begrenzt, greifen also nicht in die
   dunklen Inseln (.price-card, .care-tier-card) hinein — s. Guardrail Abschnitt 30.
--------------------------------------------------------- */
.compare-wrap{ margin-top: clamp(2.5rem, 5vw, 3.5rem); }

/* Eingeklappt per <details>: die Tabelle steht nicht mehr dauerhaft offen da,
   sondern erscheint erst auf Klick. Das Ausrollen/Einrollen animiert
   main.js (initCompareAccordion) ueber grid-template-rows (0fr -> 1fr) statt
   ueber eine Hoehen-Eigenschaft wie max-height: das braucht keinen per JS
   gemessenen/geschaetzten Px-Wert und ruckelt bei der grossen Tabelle nicht,
   weil pro Frame nur eine Grid-Spur- statt eine Layout-Neuberechnung des
   kompletten Tabelleninhalts anfaellt. Natives <details> schaltet Inhalte
   sonst abrupt per display:none/block um, daher faengt main.js den Klick ab. */
.compare-summary{
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1rem 1.25rem;
  border: 1px solid rgba(20,21,29,.22); border-radius: var(--radius);
  background: rgba(20,21,29,.045);
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.02rem, 1vw + .78rem, 1.2rem);
  color: var(--ink);
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.compare-summary::-webkit-details-marker{ display: none; }
.compare-summary:hover{ background: rgba(20,21,29,.08); border-color: rgba(20,21,29,.34); }
.compare-wrap[open] .compare-summary{
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
  border-bottom-color: transparent;
}
.compare-caret{
  flex-shrink: 0; color: var(--ink-2);
  transition: transform var(--t-med) var(--ease-out);
}
/* .is-open statt [open]: main.js setzt/entfernt die Klasse genau im Moment,
   in dem die Hoehen-Animation tatsaechlich startet, waehrend das open-Attribut
   waehrend des Einrollens bewusst noch gesetzt bleibt (s. initCompareAccordion).
   So dreht der Pfeil synchron mit, statt erst am Ende der Schliess-Animation
   zurueckzuspringen. */
.compare-wrap.is-open .compare-caret{ transform: rotate(180deg); }

/* Grid-Rows-Trick: .compare-body ist die Grid-Spur (animiert 0fr -> 1fr),
   .compare-body-inner das eigentliche Inhaltselement. min-height:0 + overflow:
   hidden auf .compare-body-inner sind Pflicht, sonst verhindert die intrinsische
   Inhaltsgroesse (min-height:auto ist der Grid-Item-Default) das Schrumpfen auf
   0 -- ohne die zwei Regeln würde die Spur trotz 0fr nicht kleiner als die
   Tabelle werden. Padding sitzt bewusst auf .compare-body-inner statt hier:
   auf dem Grid-Container selbst würde es die 0fr-Spur umschliessen statt
   mitschrumpfen und bliebe als sichtbarer Rest stehen. */
.compare-body{
  display: grid;
  grid-template-rows: 0fr;
  border: 1px solid rgba(20,21,29,.22); border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  transition: grid-template-rows var(--t-med) var(--ease-out);
}
.compare-wrap.is-open .compare-body{ grid-template-rows: 1fr; }
.compare-body-inner{
  min-height: 0;
  overflow: hidden;
  padding: 1.25rem;
  opacity: 0;
  transition: opacity var(--t-med) var(--ease-out);
}
.compare-wrap.is-open .compare-body-inner{ opacity: 1; }
/* Beim Einrollen die Gegenrichtung: ease-in statt ease-out, für Spur und Fade
   gleichermassen. */
.compare-wrap.is-closing .compare-body,
.compare-wrap.is-closing .compare-body-inner{
  transition-timing-function: cubic-bezier(.4, 0, 1, 1);
}
@media (prefers-reduced-motion: reduce){
  .compare-caret{ transition: none; }
  .compare-body, .compare-body-inner{ transition: none; }
}

/* Die Tabelle darf schmal werden, die Seite aber nicht horizontal überlaufen. */
.compare-scroll{
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Unterhalb der Tabellenbreite (620px + Rand) ist nicht erkennbar, dass rechts
   noch zwei Pakete stehen. Der Hinweis erscheint genau dort, wo tatsächlich
   gescrollt werden muss, und bleibt sonst aus. */
.compare-hint{
  display: none;
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--ink-2);
  margin-bottom: .9rem;
}
@media (max-width: 700px){
  .compare-hint{ display: block; }
}

.compare-table{
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  font-size: .95rem;
}

.compare-table th,
.compare-table td{
  padding: .85rem 1rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid rgba(20,21,29,.14);
}

.compare-table thead th{
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  border-bottom-width: 2px;
  border-bottom-color: rgba(20,21,29,.3);
  white-space: nowrap;
}

.compare-table tbody th{
  font-family: var(--font-body);
  font-weight: 500;
  color: var(--ink);
  width: 30%;
}

.compare-table td{ color: var(--ink-2); }

.compare-table tbody tr:last-child th,
.compare-table tbody tr:last-child td{ border-bottom: none; }

/* Preiszeile als Abschluss betonen */
.compare-table tbody tr:last-child th,
.compare-table tbody tr:last-child td{
  font-weight: 600;
  color: var(--ink);
  padding-top: 1.1rem;
}

/* Empfohlene Spalte hervorheben, gleiche Aussage wie das Badge auf der Karte */
.compare-table .is-highlight{
  background: rgba(67,55,180,.09);
  color: var(--ink);
}
/* Der Tint (rgba(67,55,180,.09)) verdunkelt den Untergrund von #A2AEDE auf
   #99A3DA. Das aktuelle --accent-ink (#2E2680) hält darauf noch 5.05:1 und
   braucht deshalb keinen eigenen Sonderton mehr (früher #382E97, als
   --accent-ink noch #4337B4 war und auf dem Tint auf 4.13:1 fiel). */
.compare-table thead .is-highlight{ color: var(--accent-ink); }

@media (max-width: 560px){
  .compare-table{ font-size: .88rem; }
  .compare-table th,
  .compare-table td{ padding: .7rem .8rem; }
}

/* Kompakte FAQ unter den Betreuungsstufen (#preise). Nutzt dieselbe
   .faq-list/.faq-item-Struktur wie die Haupt-FAQ, steht aber direkt auf der
   hellen surface-light-Fläche statt in einer dunklen Karte — .faq-q/.faq-a
   erben sonst --text/--border (helltheme-Werte fürs dunkle Grundthema),
   auf hellem Grund praktisch unsichtbar. Eigene Ink-Farben, scoped auf
   .price-faq, s. Guardrail zu surface-light in CLAUDE.md. */
.price-faq{ margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.surface-light .price-faq .faq-list{ border-top-color: rgba(20,21,29,.2); }
.surface-light .price-faq .faq-item{ border-bottom-color: rgba(20,21,29,.2); }
.surface-light .price-faq .faq-q{ color: var(--ink); }
.surface-light .price-faq .faq-q .plus{ color: var(--accent-ink); }
.surface-light .price-faq .faq-a p{ color: var(--ink-2); }

/* ---------------------------------------------------------
   37. Kapitel-Navigation (.section-rail)
   Die Startseite ist rund 18.000 px hoch bei 14 Abschnitten und bot bisher
   keinerlei Orientierung. Ein Punkt je Hauptabschnitt, aktiver hervorgehoben.

   Wichtig: die Leiste liegt fix über allen drei Flächen (deep, raised, light).
   Sie darf ihre Farben deshalb NICHT vom Untergrund beziehen, sonst
   verschwindet sie über surface-light. Sie bringt ihren eigenen dunklen
   Hintergrund als Pille mit und ist damit unabhängig vom Abschnitt darunter.
--------------------------------------------------------- */
.section-rail{
  position: fixed;
  right: clamp(1rem, 2vw, 2rem);
  top: 50%;
  transform: translateY(-50%);
  z-index: 45;
  display: none;
  padding: .85rem .7rem;
  border-radius: 999px;
  background: rgba(7,9,13,.72);
  border: 1px solid var(--border);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.section-rail ul{ display: flex; flex-direction: column; gap: .1rem; }

.section-rail a{
  display: flex; align-items: center; justify-content: flex-end; gap: .6rem;
  padding: .4rem .45rem;
  border-radius: 999px;
  color: var(--text-3);
  position: relative; /* Anker für die frei schwebende Beschriftung unten */
  transition: color var(--t-fast) var(--ease);
}

.rail-dot{
  width: 8px; height: 8px; flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}

/* Pass 3, Teil C: war eine max-width-Transition (0 -> 9rem), das erzwingt bei
   jedem Rail-Hover echtes Reflow. Jetzt eine frei schwebende, absolut
   positionierte Karte mit eigenem dunklen Hintergrund, die per transform
   (translateX) und opacity einfliegt — layoutneutral, der Nachbar-Dot
   bewegt sich nie mit. Bleibt im Fluss erreichbar (kein display:none), für
   Screenreader/Tastatur unverändert. */
.rail-label{
  position: absolute;
  top: 50%; right: calc(100% + .5rem);
  transform: translateY(-50%) translateX(8px);
  font-family: var(--font-mono);
  font-size: .72rem;
  white-space: nowrap;
  background: rgba(7,9,13,.92);
  border-radius: 999px;
  padding: .35rem .75rem;
  opacity: 0;
  pointer-events: none;
  transition: transform var(--t-med) var(--ease-out), opacity var(--t-fast) var(--ease);
}

.section-rail:hover .rail-label,
.section-rail:focus-within .rail-label{
  transform: translateY(-50%) translateX(0);
  opacity: 1;
}

.section-rail a:hover{ color: var(--text); }
.section-rail a:hover .rail-dot{ background: var(--text); }

.section-rail a.is-active{ color: var(--accent); }
.section-rail a.is-active .rail-dot{
  background: var(--accent);
  transform: scale(1.35);
}

@media (min-width: 1100px){
  .section-rail{ display: block; }
}

@media (prefers-reduced-motion: reduce){
  .rail-label,
  .rail-dot,
  .section-rail a{ transition: none; }
}

/* ---------------------------------------------------------
   38. Bild-Platzhalter (.img-ph)
   Gemeinsames Muster für alle noch nicht gelieferten Bilder, angelehnt an
   .team-photo: gestrichelter Rahmen, Icon, Hinweis und sichtbarer Ziel-
   Dateiname. Der Dateiname steht bewusst im Bild, damit das spätere Einsetzen
   eindeutig ist. Die Fläche trägt ihr Seitenverhältnis vom Elternteil, damit
   beim Austausch gegen ein echtes <img> kein Layout-Sprung entsteht.
   s. assets/img/README.md für die Liste der offenen Dateien.
--------------------------------------------------------- */
.img-ph{
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .6rem; padding: 1.2rem; text-align: center;
  border: 1.5px dashed rgba(var(--accent-rgb), .40);
  border-radius: var(--radius-sm);
  background: rgba(var(--accent-rgb), .045);
}
.img-ph svg{ width: 30px; height: 30px; color: var(--accent); opacity: .8; }
.img-ph-label{ font-family: var(--font-mono); font-size: .8rem; color: var(--text-2); }
.img-ph-path{
  font-family: var(--font-mono); font-size: .66rem; color: var(--text-3);
  word-break: break-all; max-width: 100%;
}

/* Laufende Nummer je Platzhalter. Baustandard aus webseiten-aspekte.md:
   "immer eine Nummer hinzufügen angefangen mit 1 (Bessere Zuordnung)".
   Damit kann beim Nachliefern "das ist Bild 4" gesagt werden, ohne den Pfad
   abzutippen. Die Nummern 1 bis 9 stehen auch in assets/img/README.md und
   müssen dort synchron bleiben. */
.img-ph-num{
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .45);
  border-radius: 999px;
  padding: .18rem .6rem;
}
.surface-light .img-ph-num{
  color: var(--accent-ink);
  border-color: rgba(67, 55, 180, .45);
}
/* Auf der blassen Vorher-Seite soll die Nummer nicht heller leuchten als der
   Rest des Platzhalters, sonst zieht sie den Blick auf sich. */
.img-ph.is-muted .img-ph-num{
  color: var(--text-3);
  border-color: rgba(238,241,246,.28);
}
/* Die Vorher-Seite des Vergleichs soll erkennbar der blassere Zustand sein */
.img-ph.is-muted{
  border-color: rgba(238,241,246,.22);
  background: rgba(238,241,246,.04);
}
.img-ph.is-muted svg{ color: var(--text-3); }

/* Im Vorher/Nachher-Regler liegen zwei Platzhalter deckungsgleich übereinander.
   Zentriert würden sich ihre Beschriftungen in der Mitte überlagern und zu
   unlesbarem Text verschmelzen (genau so gebaut und im Screenshot gesehen).
   Deshalb wandert der Inhalt je Seite nach außen: bei halb gezogenem Regler
   steht "Vorher" links und "Nachher" rechts, beides vollständig lesbar. */
.img-ph.is-left{ align-items: flex-start; padding-left: 8%; }
.img-ph.is-right{ align-items: flex-end; padding-right: 8%; }
.img-ph.is-left .img-ph-path,
.img-ph.is-right .img-ph-path{ max-width: 24ch; }

/* ---------------------------------------------------------
   39. Referenzen: Showcase-Mockup und Galerie

   ACHTUNG Namensraum: services.js macht document.querySelector('.mo-stage'),
   also erster Treffer im Dokument. Dieses Mockup darf deshalb KEINE .mo-*-
   Klassen verwenden, sonst bindet die "Mobile Optimierung"-Animation der
   Leistungen an das falsche Element. Nur der CSS-Ansatz ist übernommen.
--------------------------------------------------------- */
.showcase{ margin-bottom: clamp(3rem, 6vw, 4.5rem); }

/* 90% statt 100%: der Fuss unten ist bewusst breiter als der Deckel (sonst
   sieht es nicht nach Laptop aus). 110% von 90% bleiben unter der vollen
   Breite, damit ragt nichts aus der Seite heraus. Der aus .mo-base uebernommene
   Wert 112% bei voller Breite hatte genau das verursacht. */
.showcase-laptop{ width: min(720px, 90%); margin-inline: auto; }
.showcase-lid{
  position: relative;
  border: 1px solid var(--border-strong); border-radius: 13px;
  /* leichter Verlauf + Lichtkante oben statt flacher Fläche, plus ein weicher
     Akzent-Schein wie bei .mo-phone, damit das Mockup „gerendert" wirkt */
  background: linear-gradient(180deg, rgba(238,241,246,.06), var(--bg-2) 34%);
  padding: 10px 9px 9px;
  box-shadow:
    0 42px 72px -26px rgba(0,0,0,.66),
    0 0 64px -16px rgba(var(--accent-rgb), .22),
    inset 0 1px 0 rgba(238,241,246,.09);
}
/* Kamera-Punkt im oberen Rahmen */
.showcase-lid::after{
  content: ""; position: absolute; top: 3.5px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(238,241,246,.55), rgba(238,241,246,.14) 60%, transparent);
}
.showcase-screen{
  position: relative; aspect-ratio: 16 / 10;
  border-radius: 6px; background: var(--bg); overflow: hidden;
  border: 1px solid rgba(238,241,246,.06);
}
/* Vignette + diagonaler Glanz über dem Screenshot, damit er „hinter Glas" sitzt */
.showcase-screen::after{
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(118deg, rgba(238,241,246,.08), transparent 42%);
  box-shadow: inset 0 0 42px rgba(0,0,0,.5), inset 0 2px 3px rgba(0,0,0,.4);
}
/* Der lange Screenshot läuft hierin durch, gesteuert von showcase.js */
.showcase-shot{ position: absolute; inset: 0; }
.showcase-shot img{
  width: 100%; height: auto; display: block;
}
/* will-change hing hier dauerhaft — für ein 1340x8692px großes Bild heißt das
   eine permanent vorgehaltene Compositing-Ebene (~46 MB), auch wenn die
   Sektion gar nicht im Bild ist. showcase.js setzt .is-live jetzt über einen
   eigenen ScrollTrigger, der früh genug (start: top bottom) greift, damit die
   Ebene fertig steht, bevor die Fahrt beginnt. */
.showcase-shot.is-live img{ will-change: transform; }
/* margin-left statt margin:auto: auto-Margins zentrieren NICHT, wenn das
   Element breiter ist als sein Elternteil (sie werden dann zu 0 und das
   Element laeuft nur nach rechts aus). Genau das hat hier 5px Seitenueberlauf
   erzeugt. -5% ist die Haelfte des Ueberstands von 110%. */
.showcase-base{
  position: relative;
  width: 110%; height: 11px; margin: 5px 0 0 -5%;
  border-radius: 0 0 11px 11px;
  background: linear-gradient(180deg, var(--elevated), var(--border-strong) 42%, rgba(0,0,0,.5));
  box-shadow: 0 16px 26px -14px rgba(0,0,0,.7);
}
/* Griffmulde an der Vorderkante */
.showcase-base::after{
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 15%; height: 4px; border-radius: 0 0 6px 6px;
  background: rgba(0,0,0,.5);
}
.showcase-caption{
  margin-top: 1.2rem; text-align: center;
  font-size: .9rem; color: var(--text-3);
  max-width: 46ch; margin-inline: auto;
}

/* Dezenter Hinweis unter selbst erstellten Demo-/Konzept-Screenshots, damit
   sie nicht als echte, live geschaltete Kundenseiten missverstanden werden.
   Bewusst als Text statt Badge/Sticker: soll auffindbar, nicht auffällig sein. */
.demo-note{ margin-top: .5rem; text-align: center; font-size: .72rem; color: var(--text-3); }

/* Hinweis auf KI-generierte Bilder: gleiche Familie wie .demo-note, aber
   kräftigerer Grauton und etwas größer, damit er als bewusster Hinweis
   auffällt statt völlig unterzugehen. */
.ai-note{ margin-top: .3rem; text-align: center; font-size: .78rem; color: var(--text-2); }

.gallery-hint{
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--text-3);
  margin-bottom: 1rem;
}
/* Zwei Textvarianten, per Media Query getauscht (s. Abschnitt 45): "mit der
   Maus ziehen" ist auf einem Touchscreen irreführend. */
.gh-mobile{ display: none; }

/* --- Galerie ---
   Frei scrollbar auf ALLEN Breiten, kein ScrollTrigger-Pin mehr. Der Pin hielt
   die Seite fest, bis die Galerie durchgelaufen war, und brachte den Seitenlauf
   damit zum Stocken. Nativ gescrollt bleibt der vertikale Lauf ununterbrochen:
   das Mausrad scrollt immer die Seite, die Spur wird gewischt oder gezogen.
   Randlos bis an die Fensterkante, damit sichtbar ist, dass es weitergeht. */
.ref-gallery{
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  /* Bewusst KEIN scroll-snap: das zog kurze Zieh-Bewegungen wieder auf den
     letzten Haltepunkt zurück und fühlte sich genauso klebrig an wie der
     Pin vorher. Frei laufen lassen ist hier das Flüssigere. */
  /* 1.5rem = padding-inline von .container, s. Abschnitt 3 */
  margin-inline: -1.5rem;
  padding-inline: 1.5rem;
  padding-bottom: .5rem;
  cursor: grab;
  /* schmale, dezente Leiste statt der dicken Systemvariante */
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--accent-rgb), .45) transparent;
}
.ref-gallery::-webkit-scrollbar{ height: 6px; }
.ref-gallery::-webkit-scrollbar-track{ background: transparent; }
.ref-gallery::-webkit-scrollbar-thumb{
  background: rgba(var(--accent-rgb), .40);
  border-radius: 999px;
}
.ref-gallery.is-grabbing{ cursor: grabbing; }
/* Waehrend des Ziehens keine Textmarkierung, sonst markiert die Maus Absaetze */
.ref-gallery.is-grabbing,
.ref-gallery.is-grabbing *{ user-select: none; }

/* Die Spur muss BREITER sein als ihr Container, sonst gibt es nichts
   seitwärts zu schieben und showcase.js legt (korrekterweise) gar keinen Pin
   an. Ein 3-Spalten-Raster, das genau aufgeht, hatte genau das verursacht. */
.ref-track{
  display: flex;
  width: max-content;
  gap: clamp(1.2rem, 2.5vw, 2rem);
}

.ref-card{
  display: flex; flex-direction: column; gap: 1.1rem;
  flex: 0 0 auto;
  width: clamp(360px, 34vw, 520px);
}

.ref-frame{
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); overflow: hidden;
}
.ref-bar{
  display: flex; align-items: center; gap: .35rem;
  padding: .5rem .7rem;
  border-bottom: 1px solid var(--border);
}
.ref-dot{ width: 7px; height: 7px; border-radius: 50%; background: var(--border-strong); }
.ref-url{
  margin-left: .5rem; font-family: var(--font-mono); font-size: .64rem;
  font-style: normal; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ref-shot{ position: relative; aspect-ratio: 16 / 10; }
/* Bilder sind per Browser-Default selbst per HTML5-Drag ziehbar (Ghost-
   Vorschau) — das kapert die Zieh-Geste, bevor showcase.js' eigenes
   Pointer-Handling (scrollLeft auf .ref-gallery) überhaupt zum Zug kommt.
   draggable="false" im Markup reicht browserübergreifend nicht zuverlässig,
   deshalb hier zusätzlich per CSS deaktiviert. */
.ref-shot img{ width: 100%; height: 100%; object-fit: cover; display: block; -webkit-user-drag: none; user-select: none; }

.ref-body h3{ font-size: 1.15rem; margin-block: .35rem .5rem; }
.ref-body p{ font-size: .93rem; color: var(--text-2); }

/* Unter 900px kein Pin, sondern nativer Touch-Swipe. Gepinnter
   Horizontalscroll ist auf Touch unangenehm und bricht leicht. */
@media (max-width: 900px){
  .ref-card{ width: min(78vw, 340px); }
}

/* ---------------------------------------------------------
   40. Vorher/Nachher-Regler (#vorher-nachher)
   Der sichtbare Griff ist reine Deko; bedient wird ein echtes
   input[type=range], das unsichtbar darüberliegt. Damit funktioniert
   Tastatur (Pfeiltasten), Maus und Touch ohne eigene Zeigerlogik.
--------------------------------------------------------- */
.ba{ position: relative; }

.ba-stage{
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--border-strong);
  --ba: 50%;
}

.ba-layer{ position: absolute; inset: 0; }
.ba-layer img{ width: 100%; height: 100%; object-fit: cover; display: block; }

/* Vorher liegt oben und wird von rechts her beschnitten */
.ba-before{ clip-path: inset(0 calc(100% - var(--ba)) 0 0); }

.ba-handle{
  position: absolute; top: 0; bottom: 0;
  left: var(--ba);
  width: 2px; margin-left: -1px;
  background: var(--accent);
  pointer-events: none;
  z-index: 3;
}
.ba-grip{
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 4px 18px rgba(var(--accent-rgb), .45);
}
/* Zwei Pfeile im Griff, rein aus CSS */
.ba-grip::before,
.ba-grip::after{
  content: ""; position: absolute; top: 50%;
  width: 0; height: 0;
  border-block: 4px solid transparent;
  transform: translateY(-50%);
}
.ba-grip::before{ left: 9px; border-right: 6px solid #0B0D12; }
.ba-grip::after{ right: 9px; border-left: 6px solid #0B0D12; }

/* Das echte Bedienelement: unsichtbar, aber voll funktionsfähig */
.ba-range{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  margin: 0; padding: 0;
  opacity: 0;
  cursor: ew-resize;
  z-index: 4;
  -webkit-appearance: none; appearance: none;
  background: transparent;
  /* Ohne das kann eine nicht perfekt waagerechte Wischbewegung vom Browser
     als Seiten-Scroll statt als Regler-Zug interpretiert werden, der
     Regler wirkt auf Touch dann zäh oder reagiert gar nicht. */
  touch-action: none;
}
.ba-range::-webkit-slider-thumb{
  -webkit-appearance: none; appearance: none;
  width: 44px; height: 100%; cursor: ew-resize;
}
.ba-range::-moz-range-thumb{
  width: 44px; height: 100%; border: 0; cursor: ew-resize;
}
/* Fokus muss sichtbar sein, obwohl das Element selbst unsichtbar ist:
   der Ring wandert auf den Griff. */
.ba-range:focus-visible{ outline: none; }
.ba-stage:has(.ba-range:focus-visible) .ba-grip{
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Touch: das bildgroße .ba-range fing bisher JEDE Berührung im Bild ab und
   blockierte damit das Scrollen (touch-action:none griff aufs ganze
   Element). Auf grobem Zeiger wird .ba-range hier zeiger-transparent, das
   Ziehen übernimmt main.js stattdessen ausschliesslich über .ba-grip
   (touchstart nur dort, s. initBeforeAfter). Maus/Desktop (pointer: fine)
   ist von diesem Block nicht betroffen -- dort bedient weiterhin allein
   die native Range oben, unverändert. */
@media (pointer: coarse){
  .ba-range{ pointer-events: none; touch-action: auto; }
  /* .ba-grip erbt sonst pointer-events:none von seinem Elternelement .ba-handle */
  .ba-grip{ pointer-events: auto; touch-action: none; }
}

.ba-labels{
  display: flex; justify-content: space-between;
  margin-top: .9rem;
  font-family: var(--font-mono); font-size: .78rem; color: var(--text-3);
}

/* Ruhe-Animation am Griff: der einzige Ort auf der Seite, an dem Bewegung
   ohne Nutzerauslöser vorgesehen ist (Pass 3, B3) — sie zeigt, dass sich
   etwas ziehen lässt, dort wo es sonst nicht offensichtlich wäre. Endet mit
   der ersten Berührung (main.js entfernt die Klasse ba-hint bei pointerdown/
   touchstart/keydown auf dem Regler) und läuft nie erneut. */
@keyframes ba-hint{
  0%, 82%, 100% { transform: translate(-50%, -50%) translateX(0); }
  86% { transform: translate(-50%, -50%) translateX(-6px); }
  90% { transform: translate(-50%, -50%) translateX(5px); }
  94% { transform: translate(-50%, -50%) translateX(-3px); }
  97% { transform: translate(-50%, -50%) translateX(0); }
}
.ba-grip.ba-hint{ animation: ba-hint 3.6s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce){
  .ba-grip.ba-hint{ animation: none; }
}

/* ---------------------------------------------------------
   41. Stapel-Karten (.stack-list, "Warum uns")
   Die fünf Zeilen stapeln sich beim Scrollen übereinander, jede bleibt etwas
   tiefer kleben als die vorherige, sodass die Kanten der darunter liegenden
   sichtbar bleiben.

   Bewusst reines CSS über position:sticky, kein GSAP: der Effekt ist eine
   Layout-Eigenschaft, kein Bewegungsablauf. Dadurch funktioniert er ohne JS,
   ohne ScrollTrigger und braucht keinen eigenen Reduced-Motion-Rückfall (es
   wird nichts animiert, die Karten liegen nur gestapelt). Der Zusatz kommt auf
   .stack-list statt auf .service-list, damit die Basiskomponente unverändert
   bleibt, falls sie anderswo wiederverwendet wird.
--------------------------------------------------------- */
.stack-list .service-row{
  position: sticky;
  /* Eigener, deckender Hintergrund ist Pflicht: ohne ihn würden die
     gestapelten Ebenen durcheinanderscheinen. Dunkle Insel auf surface-raised. */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: .9rem;
  box-shadow: 0 20px 45px -32px rgba(0,0,0,.95);
}
/* Die Trennlinien der Basiskomponente ergäben zusammen mit dem Rahmen
   doppelte Kanten. */
.stack-list .service-row{ border-top: 1px solid var(--border); }
.stack-list li:last-child{ border-bottom: 1px solid var(--border); }
.stack-list .service-row:last-child{ margin-bottom: 0; }

/* Gestaffelter Haltepunkt: 96px Grundabstand unter der Navigation, je Karte
   14px tiefer, damit der Stapel als Treppe sichtbar wird. */
.stack-list .service-row:nth-child(1){ top: 96px; }
.stack-list .service-row:nth-child(2){ top: 110px; }
.stack-list .service-row:nth-child(3){ top: 124px; }
.stack-list .service-row:nth-child(4){ top: 138px; }
.stack-list .service-row:nth-child(5){ top: 152px; }

/* Die Überschrift läuft mit, sonst steht die linke Spalte leer da, während
   rechts gestapelt wird. */
.stack-head{ position: sticky; top: 120px; }

/* Auf kurzen und schmalen Schirmen lohnt der Stapel nicht: dort steht schlicht
   die Liste, sonst klebt die halbe Sektion am oberen Rand fest. */
@media (max-width: 860px), (max-height: 640px){
  .stack-list .service-row{ position: static; }
  .stack-head{ position: static; }
}

/* ---------------------------------------------------------
   42. Seitenübergang (.page-fade)
   Weiches Abblenden beim Wechsel zwischen den Seiten.

   Der riskanteste Baustein der Seite, deshalb defensiv: die Fläche ist im
   Normalzustand NICHT sichtbar und NICHT klickbar (pointer-events:none), sie
   wird nur für den Moment der Navigation eingeblendet. Bleibt sie durch einen
   Fehler stehen, ist die Seite trotzdem bedienbar, statt unter einer toten
   dunklen Schicht zu verschwinden. Das JS setzt sie zusätzlich bei jedem Laden
   und bei Rückkehr aus dem bfcache zurück, s. initPageTransitions().
--------------------------------------------------------- */
.page-fade{
  position: fixed; inset: 0; z-index: 80;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-med) var(--ease-out);
}
.page-fade.is-leaving{ opacity: 1; }

@media (prefers-reduced-motion: reduce){
  .page-fade{ display: none; }
}

/* ---------------------------------------------------------
   43. Grain-Overlay (site-weit, reines CSS)
   Feines Filmkorn über der ganzen Seite, macht die Flächen "teurer". Reine
   SVG-feTurbulence-Textur als Data-URI, kein Rasterbild, praktisch 0 KB
   zusätzlich. Liegt über allem (auch über .page-fade), pointer-events:none,
   also nie im Weg für Klicks.

   mix-blend-mode:screen statt overlay: overlay verhält sich bei einer fast
   schwarzen Basis (unser --bg) wie multiply und bleibt praktisch wirkungslos
   (gemessen: Helligkeits-Standardabweichung ~0, kein sichtbares Korn).
   screen macht auf Dunkel sichtbares Korn (gemessen ~1.7 von 255) und bleibt
   auf der hellen surface-light dezenter (~0.5) — das ist dort sogar
   erwünscht, die Textkontraste sind auf dieser Fläche ohnehin knapp bemessen
   (s. Abschnitt 30), ein kräftigeres Korn dort wäre riskanter, nicht besser.
--------------------------------------------------------- */
/* body::after statt einer eigenen Klasse: braucht dadurch KEIN Element in
   irgendeiner der 8 HTML-Dateien, kein Python-Glob-Durchlauf nötig. */
body::after{
  content: "";
  /* inset: -180px statt 0 — genau eine Kachelbreite Reserve nach allen
     Seiten. Das Korn wird unten per transform verschoben statt per
     background-position (siehe @keyframes); ohne diese Reserve liefe an den
     Rändern eine ungekörnte Kante ins Bild. Weil die Reserve exakt der
     Kachelgröße entspricht, bleibt die Kornphase gegenüber vorher identisch.
     position:fixed erzeugt dabei keinen scrollbaren Überlauf. */
  position: fixed; inset: -180px; z-index: 95;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  mix-blend-mode: screen;
  opacity: .09;
}

/* Leichtes Flimmern wie echtes Filmkorn: die Kachel springt zwischen ein paar
   Positionen. steps() macht es hart statt weich, das ist bei Korn richtig,
   ein weiches Überblenden sähe aus wie Nebel, nicht wie Filmkorn.

   Verschoben wird per transform statt per background-position: dieselben
   Versatzwerte, dasselbe Bild, aber der Browser muss die Kachel nicht bei
   jedem der vier Schritte über die ganze Fensterfläche neu rastern. */
@media (prefers-reduced-motion: no-preference){
  body::after{ animation: grain-flicker 900ms steps(4) infinite; }
}
@keyframes grain-flicker{
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(45px, 20px, 0); }
  50%  { transform: translate3d(-30px, 45px, 0); }
  75%  { transform: translate3d(20px, -35px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* ---------------------------------------------------------
   44. Gradient-Mesh-Blobs (.surface-raised / .surface-light)
   Der Hero hat bereits den echten WebGL-Shader (hero-shader.js). Diese
   Flächen hier sind reine Einzelfarben ohne jede Tiefe — genau die
   Sektionen, die beim letzten Durchgang als "am wenigsten visuell reich"
   auffielen (Der Unterschied, Branchen, Team, Warum uns, FAQ; strukturell
   dieselbe Behandlung für #prozess/#preise, deren Flächenfarbe genauso flach
   ist, auch wenn der Inhalt dort schon reicher ist).

   Reines CSS, kein Canvas/WebGL: 3 weich auslaufende radial-gradients in den
   Markenfarben, sehr langsame Drift-Animation. Der weiche Rand kommt vom
   Gradienten-Falloff selbst (transparent-Stop), NICHT von filter:blur() —
   das ist GPU-günstiger und kann nie über die Sektionsgrenze hinausragen,
   also auch kein Risiko für horizontalen Seitenüberlauf.

   z-index:-1 wirkt hier nur, WEIL .surface-raised/-light selbst einen
   eigenen Stacking-Context bekommen haben (s. Abschnitt 30) — sonst würde
   das Pseudo-Element hinter einen entfernteren Vorfahren rutschen.
--------------------------------------------------------- */
.surface-raised::before,
.surface-light::before{
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(circle at 12% 18%, rgba(var(--accent-rgb), .16), transparent 40%),
    radial-gradient(circle at 88% 78%, rgba(var(--accent-2-rgb), .14), transparent 42%),
    radial-gradient(circle at 55% 8%, rgba(var(--accent-rgb), .09), transparent 36%);
  animation: mesh-drift 26s ease-in-out infinite alternate;
}

/* Pass 3, Teil C: bis zu 7 Sektionen tragen dieses ::before gleichzeitig,
   jede mit eigenem 26s-Loop. Ohne Pausierung liefen alle permanent weiter,
   auch die, die gerade weit außerhalb des sichtbaren Bereichs liegen (main.js
   initMeshPause() setzt is-offscreen per IntersectionObserver). */
.surface-raised.is-offscreen::before,
.surface-light.is-offscreen::before{
  animation-play-state: paused;
}

/* Performance-Pass: dieselbe Pausierung für alle übrigen Endlosanimationen.
   Sie liefen bisher auf der ganzen Seite gleichzeitig weiter, auch weit
   außerhalb des Bildes — allein rimLight auf 11 Buttons (Gradient-Repaint
   über eine registrierte @property) und price-aurora auf 4 Preiskarten
   (animierte background-position auf einer blur(28px)-Ebene). Sichtbar
   ändert das nichts: pausiert wird ausschließlich, was gerade niemand sieht.
   Buttons in der fixierten Navigation bleiben dauerhaft im Bild und laufen
   darum weiter — ihre rimLight-Phase driftet dadurch gegenüber pausierten
   Buttons auseinander, bei 22s Umlaufzeit nicht wahrnehmbar. */
.btn.is-offscreen::before,
.price-card.is-offscreen::before,
.care-tier-card.is-offscreen::before{
  animation-play-state: paused;
}
.chip-float.is-offscreen,
.ba-grip.is-offscreen,
.ce-caret.is-offscreen{
  animation-play-state: paused;
}
.talk-dots.is-offscreen i{
  animation-play-state: paused;
}

@keyframes mesh-drift{
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-3%, 2.5%) scale(1.06); }
}

@media (prefers-reduced-motion: reduce){
  .surface-raised::before,
  .surface-light::before{ animation: none; }
}

/* ---------------------------------------------------------
   45. Mobile-Optimierung (Android-Testpass, 01.09.2026)
   Konkrete Fehler aus einer Bildschirmaufnahme auf einem Android-Gerät
   (1080x2340, Chrome). Alles hier ist bewusst in Media Queries gekapselt,
   damit sich am Desktop-Layout nichts ändert. Getestet bei 360/390/414/430px.
--------------------------------------------------------- */

/* --- Lupe (Schritt 02 "Analyse") auf Mobile abschalten -------------------
   Siehe process.js initLens(): der Klon-Kreis (RADIUS 74px, ZOOM 1.9x) ist
   für eine breite Desktop-Textspalte bemessen. Auf schmalen Screens
   überdeckt der vergrößerte Klon fast die ganze Textbreite und wirkt wie
   ein zweiter, unlesbar überlagerter Text statt einer feinen Lupe. Wird in
   process.js per matchMedia geprüft, nicht hier — das CSS greift nur,
   falls das Element trotzdem einmal erzeugt würde. */
@media (max-width: 680px){
  .lens{ display: none !important; }
}

/* --- Überschriften: keine Silbentrennung mehr auf Mobile -----------------
   Abschnitt 2 setzt global hyphens:auto; bei den langen deutschen
   Überschriften und schmalen mobilen Spalten trennt das mitten im Wort
   ("Online-Prä-senz", "be-dienbar"). overflow-wrap:break-word (Abschnitt 2)
   bleibt als Notfall-Reserve für den seltenen Fall eines einzelnen extrem
   langen Wortes stehen. */
@media (max-width: 760px){
  h1, h2, h3{
    hyphens: none;
    -webkit-hyphens: none;
    text-wrap: balance;
  }
}

/* --- Trust-Leiste unter dem Hero: nicht mehr von der Naht überdeckt ------
   #unterschied direkt danach ist .slant-top: die Sektion wird per
   negativem margin-top um --slant nach oben gezogen, ihre deckende Fläche
   überlappt also die letzten --slant Pixel der Trust-Leiste (Absicht, s.
   Abschnitt 30 — die Naht IST eine echte Überlappung, kein Verlauf).
   .trust-row bricht auf Mobile auf zwei Zeilen um; ohne zusätzlichen
   Bodenabstand landet die zweite Zeile (der 4. Eintrag ganz rechts, dort
   ist die Überlappung am größten) genau unter der Nachbarsektion und wird
   von ihr verdeckt. */
@media (max-width: 760px){
  .trust-bar{ padding-bottom: calc(1.5rem + var(--slant)); }
}

/* --- Hero-Codefenster: kein abgeschnittener Text mehr am Rand ------------
   .lb-line .code bricht seit der pre-wrap-Umstellung ohnehin um (s. Abschnitt
   9), hier nur kleinere Schrift und Innenabstand, damit auf 360-430px
   moeglichst wenige Zeilen ueberhaupt zweizeilig werden. Gilt nur noch unter
   400px: im Bereich 400-768px übernimmt der Block direkt darunter mit
   eigener (kleinerer) Schrift, dort steht das Codefenster ohnehin nur noch
   halb so breit neben dem Wireframe. */
@media (max-width: 560px){
  .lb-lines{ font-size: .68rem; line-height: 1.65; }
  .lb-code{ padding: .85rem .9rem; }
}

/* --- Hero-Codefenster + Wireframe nebeneinander statt gestapelt ----------
   .live-build collabiert ab 860px auf 1 Spalte (Code oben, Wireframe unten,
   Trennlinie dazwischen) -- auf Mobil wirkte das Wireframe darunter wie ein
   hängengebliebener Ladezustand, der Bezug zum Code darüber war nicht mehr
   erkennbar. Nur 400-768px: wieder 2 Spalten (55/45), dafür Code stark
   verkleinert -- nur die ersten 3 Zeilen (Rest ausgeblendet, endet bewusst
   mit dem geschlossenen "</nav>" statt mitten im offenen "<h1>"), keine
   Zeilennummern, kein Umbruch mehr (white-space:nowrap + das bestehende
   overflow-x:hidden auf .lb-code schneiden rechts sauber ab, das ist hier
   Absicht, keine Regression der pre-wrap-Umstellung von oben) -- und das
   Wireframe proportional mitverkleinert. Unter 400px reicht die schmale
   Spalte nicht mehr für lesbaren Code: dort per eigenem Block (direkt
   danach) zurück auf 1 Spalte, Wireframe ausgeblendet statt gequetscht.
   Ab 769px (Desktop) unverändert, da ausserhalb dieser Media Query. */
@media (max-width: 768px) and (min-width: 400px){
  .live-build{ grid-template-columns: 55fr 45fr; gap: .4rem; }
  .lb-code{ border-right: 1px solid var(--border); border-bottom: 0; padding: .7rem .8rem; }
  .lb-bar{ margin-bottom: .5rem; }
  .lb-lines{ font-size: .6rem; line-height: 1.5; }
  .lb-line .ln{ display: none; }
  .lb-line:nth-child(n+4){ display: none; }
  .lb-line .code{ white-space: nowrap; }

  .lb-preview{ padding: .6rem; gap: .35rem; }
  .lb-preview .ph-nav{ height: 5px; }
  .lb-preview .ph-h{ height: 10px; margin-top: .25rem; }
  .lb-preview .ph-p{ height: 4px; }
  .lb-preview .ph-btn{ width: 54px; height: 17px; margin-top: .35rem; }
}

/* Unter 400px reicht selbst die verkleinerte Spalte nicht mehr für lesbaren
   Code (ungeprüft, kein Browser hier verfügbar -- daher als Sicherheitsnetz
   wie gewünscht eingebaut, bitte auf einem echten 360px-Gerät gegenprüfen).
   .live-build{grid-template-columns:1fr} kommt schon von der bestehenden
   ≤860px-Regel oben, hier nur das Wireframe ausblenden und die jetzt
   überflüssige Trennlinie unter dem Code entfernen. */
@media (max-width: 399px){
  .lb-preview{ display: none; }
  .lb-code{ border-bottom: 0; }
}

/* --- Mauscursor-Grafik ("Der Unterschied") auf Touch ausblenden ----------
   Die Geschichte "ein Cursor kommt hereingeflogen und klickt" ergibt auf
   einem Touchscreen keinen Sinn. Der Rest der Animation (Seite erstrahlt
   neu) bleibt unverändert, sie hängt nicht an der Cursor-Sichtbarkeit. */
@media (max-width: 760px){
  .cr-cursor{ display: none; }
}

/* --- Referenzen-Galerie: Wisch-Hinweis statt Maus-Text, Karten-Peek,
   sanftes Snapping ---------------------------------------------------------
   scroll-snap war für die Maus-Zieh-Funktion bewusst deaktiviert (s.
   Abschnitt 39 / showcase.js: eine kurze Ziehbewegung schnappte immer auf
   den letzten Haltepunkt zurück). Das Ziehen mit der Maus läuft laut
   showcase.js nur bei pointerType "mouse", Touch scrollt ohnehin nativ —
   scroll-snap ausschließlich hier, nur für schmale/Touch-Breiten, kollidiert
   also nicht mit dem bekannten Maus-Bug. proximity statt mandatory, damit
   es sich weiterhin frei anfühlt und nicht klebrig. */
@media (max-width: 760px){
  .gh-desktop{ display: none; }
  .gh-mobile{ display: inline; }

  .ref-gallery{
    scroll-snap-type: x proximity;
    /* rechter Rand blendet aus, sichtbares Signal "hier geht es weiter" */
    mask-image: linear-gradient(90deg, #000 90%, transparent 100%);
    -webkit-mask-image: linear-gradient(90deg, #000 90%, transparent 100%);
  }
  .ref-card{
    scroll-snap-align: start;
    width: min(84vw, 400px);
  }
}

/* --- Referenzen-Mockup: Rahmen weg, Screenshot füllt mehr Fläche -------- */
@media (max-width: 560px){
  .showcase-lid{ border: 0; padding: 0; border-radius: var(--radius-sm); }
  .showcase-base{ display: none; }
  .showcase-laptop{ width: 100%; }
}

/* --- Vorher/Nachher-Regler: größerer Griff, satteres Ziel-Gefühl --------
   Auf 768px statt vorher 560px gezogen, damit die touchstart-Trefferfläche
   (s. initBeforeAfter in main.js, greift bei jedem groben Zeiger) auf jedem
   Mobilgerät die geforderten mind. 44×44px erreicht, nicht nur unterhalb
   von 560px. */
@media (max-width: 768px){
  .ba-grip{ width: 44px; height: 44px; }
}

/* --- Preise: Abstand zwischen "Empfohlen"-Karte und der Karte darüber --
   Im gestapelten 1-Spalten-Layout (≤860px, s. Abschnitt 26) sitzt das Badge
   (top:-13px) sonst zu dicht am unteren Rand der vorherigen Karte. */
@media (max-width: 760px){
  .price-card.is-highlight{ margin-top: 1.75rem; }
}

/* --- Vergleichstabelle: erste Spalte bleibt beim seitlichen Scrollen
   stehen, damit klar bleibt, welche Zeile man gerade liest ---------------- */
@media (max-width: 700px){
  .compare-table th[scope="row"],
  .compare-table thead th:first-child{
    position: sticky;
    left: 0;
    z-index: 1;
    /* deckend in der Flächenfarbe, sonst scheinen die Spalten dahinter durch */
    background: var(--surface-light);
    box-shadow: 2px 0 6px -2px rgba(20,21,29,.25);
  }
  .compare-table thead th:first-child{ z-index: 2; }
}

/* --- FAQ: Antworttext etwas breiter nutzbar, Fußzeilen-Links als größere
   Trefferfläche (mind. ~44px) -------------------------------------------- */
@media (max-width: 560px){
  .footer-col a{ display: inline-block; padding-block: .65rem; }
}

/* --- Scroll-Reveal: früher auslösen, kürzer laufen ----------------------
   Der IntersectionObserver in main.js nutzt auf schmalen Screens threshold
   0.05 statt 0.15 und einen kleineren negativen rootMargin (s. initScroll-
   Reveal()). Die kürzere Dauer hier sorgt zusätzlich dafür, dass ein spät
   ausgelöstes Element nicht noch sichtbar "nachzieht", während man schon
   weitergescrollt hat. */
@media (max-width: 760px){
  .reveal{ transition-duration: .38s; }
}

/* --- Vertikale Section-Abstände: auf Mobile spürbar knapper -------------
   main.js/CLAUDE.md-Ziel: ca. 30-40% weniger als Desktop. Die vorhandenen
   clamp()-Werte laufen auf schmalen Screens nicht klein genug aus, weil ihr
   Minimum fürs Desktop-Layout gesetzt wurde. */
@media (max-width: 560px){
  main > section{ --section-pad: 2.75rem; }
  .pstep{ --section-pad: 2.5rem; }
  .pstep.surface-light{ --section-pad: 2.25rem; }
  .pstep-visual{ min-height: 220px; }
  .globe-section .pstep-visual{ min-height: 300px; }
  .support-stage{ min-height: 240px; }
}

/* --- Bild-Banner ("Wir sagen Ihnen ehrlich…"): Ausschnitt, Kontrast, Höhe
   auf Mobile ---------------------------------------------------------------
   Bild ist 1920×785 (Laptop-Nutzer links bis ca. 40% Bildbreite, dann leere
   Fläche, Handschlag-Szene ab ca. 55%). background-position:center zeigte
   auf der viel schmaleren/höheren Mobile-Sichtfläche von "cover" ausgerechnet
   die leere Mitte samt angeschnittenem Laptop, die eigentliche Szene (Personen,
   Handschlag) fiel aus dem Bild. Nach rechts auf die Handschlag-Szene
   verschoben. Overlay in der Textzone zusätzlich verstärkt: Radial- und
   Vertikal-Verlauf waren fürs breitere/kürzere Desktop-Textfeld austariert,
   auf Mobile steht darüber jetzt mehrzeiliger Text direkt über Gesichtern.
   Padding reduziert, gleiche Größenordnung wie die übrige Mobile-Verknappung
   oben (--section-pad: 2.75rem). */
@media (max-width: 768px){
  .banner{
    padding-block: clamp(2.75rem, 8vw, 4rem);
    background-position: 100% center;
    background-image:
      radial-gradient(ellipse 78% 72% at 50% 50%, rgba(7,9,13,.74), transparent 78%),
      linear-gradient(180deg, rgba(7,9,13,.95), rgba(7,9,13,.8) 38%, rgba(7,9,13,.84) 68%, rgba(7,9,13,.97)),
      url("../img/beratung-banner.jpg");
  }
}

@media (prefers-reduced-motion: reduce){
  .ref-gallery{ scroll-snap-type: none; }
}
