/*
  MAGIC MIRROR: Seiten-Layout
  Ergänzt design/tokens.css (Farben/Fonts/Glow-Utilities) um Grid/Spacing/Section-Layout.
  Reihenfolge im <head>: fonts.css, tokens.css, site.css.

  2026-07-03: lokale Section-Hintergruende komplett entfernt (auf Nutzerwunsch, nicht nur
  Cleanup: "kein Hintergrundverlauf pro Section, es sei denn ich sage es Dir"). .ambient-bg
  (tokens.css, einmal im Markup direkt nach <body>) ist jetzt der einzige Hintergrund fuer
  die ganze Seite, ausser #hero (eigenes Foto). .spotlight (Maus-Glow bei Hero/Pakete/
  Galerie) ist ein unabhaengiger Mechanismus und bleibt unangetastet.
*/

* {
  box-sizing: border-box;
}

/* 2026-08-02: Nutzerfeedback "Seite laesst sich in der Mobile-Version irgendwie verschieben".
   overflow-x:hidden sass bisher nur auf body, nicht auf html. Auf iOS ist oft <html> (nicht
   body) das eigentliche Scroll-Root-Element, das elastische Rubber-Band-Overscrolling kann
   dadurch trotz body-seitigem overflow-x:hidden noch ein paar Pixel horizontal "ranziehen".
   Nach Entfernen von .ambient-bg .blob (Hauptverdaechtiger, siehe design/tokens.css) blieb per
   Puppeteer weiterhin ein kleiner Rest-Overflow messbar (documentElement.scrollWidth 396px bei
   390px Viewport, ohne dass ein einzelnes Element dafuer verantwortlich zu machen war), daher
   zusaetzlich hier auf html abgesichert statt die genaue Restquelle einzeln zu jagen. */
html {
  scroll-behavior: smooth;
  overflow-x: hidden;
}

body {
  margin: 0;
  line-height: 1.6;
  overflow-x: hidden;
}

/* 2026-07-05: height:auto ergaenzt. Ohne das blieb die per width/height-Attribut (CLS-Fix)
   gesetzte Hoehe als fixer Pixelwert stehen, waehrend max-width die Breite schrumpfte, sobald
   ein Bild in einem schmaleren Container als seine echte Breite sass, dadurch verzerrte es
   sichtbar statt proportional zu skalieren (Spiegel-Produktbild, Druck-Karten betroffen). */
img {
  max-width: 100%;
  height: auto;
  display: block;
}

.wrap {
  width: min(1180px, 100% - 3rem);
  margin-inline: auto;
}

section {
  padding: clamp(3.5rem, 7vw, 7rem) 0;
  position: relative;
}

h1, h2, h3 {
  margin: 0 0 0.6em;
  line-height: 1.15;
}

/* 2026-07-04: p war bisher nicht zurueckgesetzt, dadurch addierte sich der
   Browser-Standard-Absatzabstand zum ohnehin gesetzten Grid-/Flex-gap dazu (v. a. im
   Hero sichtbar: deutlich zu viel Abstand zwischen Eyebrow/H1/Subline/Text). */
p {
  margin: 0;
}

/* 2026-07-11: font-size kommt jetzt zentral aus h2.font-display (tokens.css), damit ALLE H2
   dieselbe Groesse haben. .section-title fuegt nur noch die Zentrierung/den Abstand dazu, fuer
   die zwei bewusst linksbuendigen H2 (Spiegel-Section, Ansprechpartner) nicht gesetzt. */
h2.section-title {
  text-align: center;
  margin-bottom: 0.4em;
}

/* 2026-07-02: Text-Glow (text-shadow) auf Ueberschriften entfernt, wirkte bei diesen
   Groessen unsauber statt klar. Ueberschriften jetzt solide, kein Blur. Neon-Farbe lebt
   stattdessen in Hintergruenden, Rahmen und Buttons. */
h1.font-display,
h2.section-title,
h2.font-display,
.site-header .logo {
  text-shadow: none;
  color: var(--text-primary);
}

p.section-lede {
  text-align: center;
  max-width: 62ch;
  margin: 0 auto 2.8rem;
  color: var(--text-muted);
  font-size: 1.05rem;
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* =======================================================
   HEADER / NAV
   ======================================================= */

/* 2026-07-04: echter Glas-Look statt fast blickdichtem Dunkel, der lebendige Hintergrund
   soll durchschimmern, dazu ein duenner heller Schimmer-Strich oben (typisches
   Glasmorphism-Detail, wie ein Lichtreflex auf einer Glaskante). */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 clamp(1rem, 4vw, 2.5rem);
  background: rgba(18, 15, 28, 0.5);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border-bottom: 1px solid rgba(157, 78, 255, 0.35);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* 2026-07-09: Logo-Text von "Magic Mirror" zu "Jetzt Fotobox mieten" geaendert
   (Nutzerwunsch), dadurch deutlich laenger. clamp() + nowrap verhindern einen Zeilenumbruch,
   der die feste Header-Hoehe (--header-h) sprengen wuerde.
   2026-08-02: Nutzerfeedback "Header passt fuer mobile vorn und hinten nicht". Root Cause: bei
   320px Breite standen Logo-Text und "Jetzt anfragen"-Button mit 0px Abstand direkt
   aneinander (per Bounding-Box verifiziert). Untergrenze von 0.95rem auf 0.8rem gesenkt,
   dadurch bleibt bei schmalen Viewports mehr Luft zum Button. */
.site-header .logo {
  font-size: clamp(0.8rem, 2.6vw, 1.35rem);
  letter-spacing: 0.04em;
  text-decoration: none;
  white-space: nowrap;
}

/* 2026-07-04: "Gluehwuermchen" im Header, JS erzeugt .firefly-Elemente in
   .firefly-field, siehe assets/js/site.js. Aeusseres .firefly traegt die
   Maus-Ausweich-Bewegung (JS, per Transform), das innere .firefly-dot das
   eigenstaendige, unregelmaessige Umherschweben (CSS-Keyframes). */
.firefly-field {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.firefly {
  position: absolute;
  left: var(--x, 50%);
  top: var(--y, 50%);
  transition: transform 0.6s var(--ease-glow);
  will-change: transform;
}

.firefly-dot {
  display: block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold-bright);
  box-shadow: 0 0 8px 3px currentColor;
  color: var(--neon-cyan);
  /* 2026-07-06: zwei unabhaengige Animationen, Wander-Pfad (Position) und Glow-Pulse
     (Helligkeit) laufen bewusst mit unterschiedlicher Dauer/Delay auseinander, damit das
     Pulsieren zufaellig statt synchron zur Bewegung wirkt. */
  animation-name: firefly-wander-a, firefly-glow-pulse;
  animation-duration: 14s, 2.4s;
  animation-timing-function: ease-in-out, ease-in-out;
  animation-iteration-count: infinite, infinite;
}

.firefly:nth-of-type(2n) .firefly-dot {
  color: var(--neon-pink);
  animation-name: firefly-wander-b, firefly-glow-pulse;
  animation-duration: 17s, 2.4s;
}

.firefly:nth-of-type(3n) .firefly-dot {
  color: var(--gold-bright);
  animation-name: firefly-wander-c, firefly-glow-pulse;
  animation-duration: 11.5s, 2.4s;
}

/* 2026-07-06: Bewegungsradius deutlich vergroessert (vorher max. ±18px, "tänzelte" zu nah
   auf der Stelle), jetzt bis zu ±70px fuer ein spuerbar weiträumigeres Umherfliegen.
   2026-08-02: Nutzerwunsch "Mesh-Netzwerk, wo die sich bewegen, erweitern". Nochmal um Faktor
   ~1.5 vergroessert, jetzt bis zu ±99px.
   2026-08-02, /grill-me-Nachbesserung: opacity-Werte hier entfernt. Sie ueberlagerten sich
   frueher mit der separaten firefly-glow-pulse-Animation (beide setzten opacity, nur eine
   Animation gewinnt pro Property), zusaetzlich verstaerkten sie den Eindruck "blinkt nur, statt
   sich zu bewegen": der schnelle Puls (2.4s) dominierte optisch komplett gegenueber der
   langsamen Wanderung (14-17s). Opacity gehoert jetzt ausschliesslich firefly-glow-pulse,
   dieser Keyframe steuert nur noch reine Position. */
@keyframes firefly-wander-a {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(87px, -57px); }
  45% { transform: translate(-48px, 45px); }
  70% { transform: translate(60px, 69px); }
  88% { transform: translate(-81px, -36px); }
}

@keyframes firefly-wander-b {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(-99px, 33px); }
  50% { transform: translate(36px, -69px); }
  75% { transform: translate(78px, 57px); }
}

@keyframes firefly-wander-c {
  0%, 100% { transform: translate(0, 0); }
  30% { transform: translate(57px, 60px); }
  60% { transform: translate(-93px, -24px); }
  85% { transform: translate(36px, -57px); }
}

/* 2026-08-02, /grill-me-Nachbesserung: Nutzerfeedback "wird das dunkler oder transparent?
   wirkt wie ein dunkler Fleck". Root Cause: der Punkt hat eine SOLIDE goldene Fuellfarbe
   (background: var(--gold-bright) oben), filter:brightness() verdunkelte diese Farbe im
   Tiefpunkt zu einem stumpfen Braun-Gold statt sie unsichtbar wirken zu lassen, genau der
   gemeldete dunkle Fleck. Fix (Nutzervorschlag): Groesse + Transparenz statt Helligkeit. scale
   ist eine eigenstaendige CSS-Property (nicht Teil von transform), laeuft dadurch unabhaengig
   und ueberlagerungsfrei neben der transform-basierten Wander-Animation. Im Tiefpunkt ist der
   Punkt klein UND fast unsichtbar (opacity 0.12), im Hochpunkt voll ausgeleuchtet, kein
   dunkler Fleck mehr moeglich, macht nebenbei auch die Wander-Bewegung praesenter, da der Puls
   weniger dominiert. Per JS-Delay zufaellig versetzt (siehe initFireflyField in site.js). */
@keyframes firefly-glow-pulse {
  0%, 100% { opacity: 0.12; scale: 0.5; }
  50% { opacity: 1; scale: 1.2; }
}

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

/* 2026-08-02, per /grill-me: Nutzerwunsch "auf Mobile echte Gluehwuermchen aktivieren" (die
   dort sichtbaren .sparkle-Funken sind bewusst statisch, keine echten Gluehwuermchen, siehe
   .sparkle-field in tokens.css). Vorheriges Ausblenden unter 700px komplett entfernt, echte
   wandernde Gluehwuermchen (.firefly-field, im Hero bereits vorhanden, siehe site.js) sind
   jetzt auch auf Handy-Breiten sichtbar. */

.site-header nav {
  display: none;
  gap: 1.8rem;
  font-size: 0.92rem;
}

.site-header nav a {
  text-decoration: none;
  color: var(--text-muted);
  transition: color 0.25s var(--ease-glow);
}

.site-header nav a:hover {
  color: var(--neon-cyan);
}

.site-header .btn-glow {
  padding: 0.6em 1.4em;
  font-size: 0.85rem;
}

@media (min-width: 900px) {
  .site-header nav {
    display: flex;
  }
}

/* =======================================================
   HERO
   ======================================================= */

/* 2026-07-11: Nutzerfeedback "Der Textblock sitzt mir zu zentral... das muss weiter nach
   unten geschoben werden, fast als wuerde es unten stehen, mit leichtem Aussenabstand".
   align-items von center auf flex-end, dazu ein moderates padding-bottom als der gewuenschte
   Aussenabstand zur unteren Kante. Betrifft .wrap (das einzige echte Flex-Kind von #hero,
   die H1 ist inzwischen wieder Teil davon, siehe weiter unten). */
#hero {
  /* 2026-07-04: Header + Hero-Foto zusammen exakt 100vh, statt einer festen vh-Zahl,
     die je nach Viewport mal zu viel, mal zu wenig Platz unter dem Header liess. */
  min-height: calc(100vh - var(--header-h));
  display: flex;
  align-items: flex-end;
  padding-top: 6rem;
  padding-bottom: clamp(2rem, 5vw, 4rem);
  /* 2026-07-09: Verlauf abgeschwaecht, Nutzerfeedback "Bild wird durch den Verlauf nicht mehr
     schoen dargestellt". Vorher 0.45 bis 0.88 Schwarz plus kraeftige Neon-Radials, verschluckte
     das Foto fast komplett. Erste Reduktion reichte dem Nutzer noch nicht, zweite Runde nochmal
     deutlich transparenter: Kontrast fuer den weissen Text existiert praktisch nur noch ganz
     unten (Fliesstext/Buttons), der Rest des Fotos liegt fast ungefiltert frei.
     2026-07-11: der flaechige 180deg-Verlauf ist raus, Nutzerwunsch "Verlauf von unten links,
     dunkel/fast schwarz, zu transparent, Bild bleibt ab 50% erhalten". Radial-Gradient statt
     linear, Ursprung in der unteren linken Ecke (passt zur Position des Glass-Panels), faedet
     bis zur Bildmitte komplett aus, die rechte Bildhaelfte bleibt unangetastet sichtbar.
     2026-07-11, gleicher Tag: Textblock von links nach rechts getauscht (Root-Cause-Fund:
     das Foto zeigt den Spiegel links, der Text verdeckte ihn). Der dunkle Verlauf wandert
     als Gegenstueck von unten-links (0% 100%) nach unten-rechts (100% 100%), damit er wieder
     dort sitzt, wo der Text jetzt ist, statt links (wo jetzt nur noch der frei sichtbare
     Spiegel + die schwebenden Karten sind).
     2026-07-11, /grill-me-Nachbesserung (5. Runde): Nutzerwunsch "wieder dunkelblau in Pink zu
     transparent statt schwarz". Letzter Layer (Ecken-Verlauf hinter dem Text) von reinem
     Schwarz auf --bg-surface-2 (dunkles Blau-Violett) umgestellt, mit --neon-violet als
     Bruecke zu --neon-pink, dann transparent. Gleiche Reichweite/Deckkraft-Kurve wie zuvor,
     nur die Farbe aendert sich.
     2026-07-11, /grill-me-Nachbesserung (6. Runde): die Runde-5-Version wirkte insgesamt heller
     statt dunkler, Nutzerfeedback "die Ecke muss dunkel sein, allein schon wegen der
     Textinhalte". Ursache: Pink/Violett bei 0.2-0.35 Deckkraft liest sich optisch deutlich
     lichter als dieselbe Deckkraft in Schwarz. Fix: dunkler Kern jetzt bei 0.95 Deckkraft
     (dunkler als das urspruengliche reine Schwarz bei 0.88), bleibt bis 18% durchgehend fast
     schwarz-blau, erst danach ein kraeftigerer, laenger sichtbarer Pink-Akzent (0.28 Deckkraft
     bei 34%, auf Nutzerwunsch "mehr Pink-Praesenz"), dann transparent bei 55%.
     2026-07-11, /grill-me-Nachbesserung (7. Runde): auch nach zwei Nachdunkelungs-Versuchen
     blieb die Ecke "zu hell", Nutzerfeedback: reines Schwarz (vor Runde 5) war "deutlich
     besser". Farbidee komplett verworfen, zurueck auf die urspruengliche Schwarz-Version. */
  background:
    radial-gradient(circle at 15% 15%, rgba(255, 63, 192, 0.1), transparent 42%),
    radial-gradient(circle at 88% 12%, rgba(47, 230, 255, 0.08), transparent 40%),
    radial-gradient(circle at 50% 100%, rgba(157, 78, 255, 0.12), transparent 55%),
    radial-gradient(circle at 100% 100%, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.55) 25%, transparent 50%),
    center / cover no-repeat url("../img/hero/hero-archiv-01.webp");
}

/* 2026-08-02: Nutzerfeedback "Header/Hero fuer mobile passt vorn und hinten nicht". Auf
   schmalen Hochformat-Viewports schneidet `background-position: center` (siehe #hero oben)
   den Spiegel, der im Foto links sitzt, fast komplett weg. Eigene, schmalere
   background-position NUR fuer Mobile ueberschreibt den `center`-Wert aus dem Shorthand
   oben (Longhand-Override nach einem Shorthand ist gueltiges CSS), zeigt dadurch mehr vom
   linken Bildbereich, der Spiegel ist dadurch leicht im Frame statt komplett abgeschnitten.
   H1 ("Jetzt Fotobox mieten") wandert aus dem normalen Grid-Fluss von .wrap heraus (dort sass
   sie mit allem anderen unten geclustert) in die obere rechte Ecke, per position:absolute.
   Wichtige Korrektur dabei: #hero.wrap hat selbst position:relative (fuer sein z-index:2),
   dadurch waere .wrap (nicht #hero) die naechste positionierte Vorfahren-Box und h1 haette
   sich relativ zu .wrap verankert, die durch align-items:flex-end selbst weit unten im Hero
   sitzt (per Bounding-Box verifiziert: h1 landete bei y=421px statt der erwarteten y=96px).
   Fix: .wrap bekommt hier `position: static`, dadurch "durchsichtig" fuer die
   Verankerungssuche, h1 findet #hero (per globaler `section { position: relative }`-Regel)
   als naechste positionierte Vorfahren-Box. z-index:2 auf .wrap bleibt trotzdem wirksam, da
   Flex-/Grid-Items per Spec auch mit position:static auf z-index reagieren.
   Selektor bewusst mit .hero-textpanel (zweite Klasse auf demselben Element, siehe
   index.html) erweitert: reine `#hero .wrap` haette dieselbe Spezifitaet wie die
   unconditional `#hero .wrap { position: relative; ... }`-Regel weiter unten im File, bei
   gleicher Spezifitaet gewinnt die spaeter im Quelltext stehende Regel unabhaengig von der
   Media Query, das Original stand hier leider spaeter und gewann. Die zusaetzliche Klasse
   erhoeht die Spezifitaet gezielt, unabhaengig von der Position im Quelltext.
   "So läuft's ab" (`.btn-ghost`, nur an dieser einen Stelle im ganzen Projekt verwendet)
   vorerst komplett ausgeblendet, Nutzerwunsch "erst einmal nicht visible machen". */
@media (max-width: 767px) {
  #hero {
    background-position: 20% 50%;
    /* 2026-08-02: Nutzerfeedback "Textinhalt muss die Hoehe der unteren Bar abziehen, sonst
       ist der Text nicht mehr direkt lesbar". Das Hintergrundfoto bleibt bewusst bei voller
       vh100-Hoehe (min-height oben unveraendert), nur der Fliesstext (bottom-verankert per
       align-items:flex-end) bekommt hier zusaetzlichen Bodenabstand in Hoehe der fixierten
       .mobile-bottom-bar (gemessene Hoehe ca. 73px = 4.5rem, + etwas Puffer + Safe-Area),
       sonst schob sich die letzte Absatzzeile ca. 41px hinter die Bar (per Bounding-Box
       verifiziert: p.bottom=812px > bar.top=771px). */
    /* 2026-08-02: Nutzerfeedback "Inhaltlich ist nicht alles enthalten, da es durch den Footer
       [gemeint: die Bottom-Bar] verdeckt wird". Root Cause: 5.5rem liess nur ca. 14px Abstand
       zwischen letzter Absatzzeile und Bar (per Bounding-Box verifiziert), auf manchen
       Geraeten/Zeilenumbruechen zu knapp. Auf 7rem erhoeht, spuerbar mehr Luft. */
    padding-bottom: calc(7rem + env(safe-area-inset-bottom));
  }

  #hero .wrap.hero-textpanel {
    position: static;
    /* 2026-08-02: Nutzerfeedback "Text klitscht zu sehr links am Rand". Root Cause:
       margin-inline: auto <wert> (Basisregel weiter unten) setzt nur einen rechten Aussenabstand,
       links bleibt "auto", was bei einer schmalen Mobile-Breite (Inhalt+rechter Rand fuellt
       bereits den ganzen Viewport) zu 0px kollabiert (per Bounding-Box verifiziert: wrapLeft
       war 1.2px). Kleiner, fester linker Aussenabstand nur fuer Mobile. */
    margin-left: 1.25rem;
    /* 2026-08-02: Nutzerwunsch "Der Moment, der bleibt und der Fliesstext muessen weiter nach
       oben, sonst wird Inhalt von der Bottom-Bar verdeckt". Root Cause: #hero ankert .wrap per
       align-items:flex-end an seinem UNTEREN Rand, das haengt nur von dem ab, was UNTERHALB
       eines Elements folgt, nicht davon, was darueber entfernt wurde. Die grosse H1 ist zwar
       jetzt aus dem mobilen Textfluss raus (siehe oben, wandert in den Header), das allein
       verschiebt Tagline/Fliesstext aber NICHT nach oben (sie haengen weiterhin exakt an
       derselben Boden-Position wie vorher). Zusaetzlicher margin-bottom hebt den ganzen Block
       jetzt bewusst vom unteren Rand ab, nutzt den durch die H1-Verschiebung frei gewordenen
       Platz im oberen Bildbereich. */
    margin-bottom: 1rem;
  }

  #hero .btn-ghost {
    display: none;
  }

  /* 2026-08-02, per /grill-me: "JETZT unverbindlich anfragen raus, das steht im Menue" +
     neue Sticky-Bottom-Bar uebernimmt jetzt die Handlungsaufforderung (siehe
     .mobile-bottom-bar weiter unten). Ganze Reihe ausgeblendet statt nur der Button, da nach
     dem Ausblenden von .btn-ghost (oben) ohnehin nichts mehr darin uebrig bleibt.
     Selektor mit .hero-delayed-in (zweite Klasse auf demselben Element) erweitert: dieselbe
     Spezifitaets-Falle wie vorhin bei .wrap.hero-textpanel, die unconditional
     "#hero .cta-row { display:flex; ... }"-Regel (fuer die Desktop-CTA-Button-Breitenkopplung)
     steht spaeter im Quelltext und haette bei gleicher Spezifitaet gewonnen. */
  #hero .cta-row.hero-delayed-in {
    display: none;
  }

  /* Header-Button entfaellt auf Mobile zugunsten der neuen Bottom-Bar (Nutzerentscheidung:
     "ersetzen, Header behaelt nur Logo", keine doppelte Handlungsaufforderung oben UND
     unten). */
  .site-header .btn-glow {
    display: none;
  }

  /* 2026-08-02: die animierte "Jetzt Fotobox Mieten"-Headline ist wieder zurueck in der
     Hero-Section (Nutzerwunsch, Rueckbau der Header-Verschiebung aus Abschnitt 6zv), der
     Header braucht seinen Text-Logo-Link deshalb auch auf Mobile wieder. */

  /* Platz fuer die fixierte Bottom-Bar am Seitenende reservieren, sonst wuerde sie den
     Footer-Inhalt (Impressum/Datenschutz/Telefon/Mail) dauerhaft verdecken. Hoehe der Bar
     (siehe .mobile-bottom-bar) plus Sicherheitsabstand plus die potenzielle
     Home-Indicator-Aussparung neuerer iPhones (env(safe-area-inset-bottom), faellt auf
     Geraeten ohne Aussparung auf 0px zurueck). */
  body {
    padding-bottom: calc(4.75rem + env(safe-area-inset-bottom));
  }
}

/* =======================================================
   IPAD/TABLET-OPTIMIERUNG (2026-08-02)
   Nutzerwunsch: "iPad optimieren, Headline etwas hoeher, Tagline stand an falscher Position,
   Verlauf von unten nach oben fuer besser lesbaren Fliesstext". Deckt vor allem Hochformat-
   Tablets ab (768-1024px, z. B. iPad 768/820/834px), die weder die kompakte Mobile-Loesung
   (<=767px) noch das volle Desktop-Layout mit sichtbarer Nav (>=900px, viel breiter als ein
   Tablet-Hochformat) wirklich gut abgedeckt bekamen: die Ueberschrift wirkte tief/unzentriert,
   der Fliesstext hatte keinerlei abdunkelnden Verlauf und war gegen das belebte Foto teils
   schwer lesbar. Landschafts-Tablets (>=1024px, entsprechen im Prinzip der Desktop-Erfahrung,
   Nav bereits sichtbar) bleiben bewusst unangetastet.
   ======================================================= */
@media (min-width: 768px) and (max-width: 1024px) {
  /* 2026-08-02, per /grill-me: Nutzerwunsch "Hero-Foto etwas nach rechts verschieben, damit
     der Spiegel mehr in den Fokus rueckt, aehnlich wie in der Mobile-Version" (dort:
     background-position:20% 50%). Fuer iPad-Breiten weniger extrem als Mobile (mehr
     Bildbreite verfuegbar, der Spiegel muss nicht so stark herangezogen werden), 38% statt
     20% als Mittelweg zwischen der zentrierten Desktop-Position und der Mobile-Position. */
  #hero {
    background-position: 38% 50%;
  }

  #hero .wrap.hero-textpanel {
    /* Hebt den gesamten Textblock (Headline + Tagline + Fliesstext + CTAs) vom unteren,
       flex-end-verankerten Rand ab, damit die Headline sichtbar hoeher/zentrierter im Foto
       sitzt statt in der unteren Bildhaelfte zu haengen. */
    margin-bottom: 6rem;
  }

  /* 2026-08-02, per /grill-me: Nutzerwunsch "FOTOBOX JETZT MIETEN ca. 35% groesser", nach
     Rueckfrage praezisiert: NUR fuer die iPad-Breiten hier, weder Mobile-Kopfzeile noch voller
     Desktop sollen sich aendern. Alle clamp()-Werte (min/preferred/max) mit 1.35 multipliziert,
     haelt das bestehende ca. 33.8%-Groessenverhaeltnis zwischen FOTOBOX und Jetzt/Mieten
     unveraendert bei.
     Bugfix (direkt beim ersten Test aufgefallen): bare .hero-h1-word/.hero-h1-word--1/--3 hier
     verlor gegen die spaeter im Dokument stehende, unconditional Basisregel (gleiche
     Spezifitaet, Quelltext-Reihenfolge entscheidet, klassische, in diesem Projekt bereits
     mehrfach aufgetretene Spezifitaets-Falle). Fix: #hero-Praefix boostet die Spezifitaet,
     gewinnt dadurch unabhaengig von der Reihenfolge im Dokument. */
  #hero .hero-h1-word {
    font-size: clamp(2.43rem, 12.15vw, 12.15rem);
  }

  #hero .hero-h1-word--1,
  #hero .hero-h1-word--3 {
    font-size: clamp(1.485rem, 4.05vw, 4.1175rem);
  }

  /* Gleiche Technik wie beim Mobile-Pendant (#hero::after, siehe oben): dunkler Verlauf von
     unten nach oben, damit Tagline/Fliesstext unabhaengig davon, was gerade im Foto dahinter
     liegt, zuverlaessig lesbar bleiben. */
  #hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(
      0deg,
      rgba(0, 0, 0, 0.8) 0%,
      rgba(0, 0, 0, 0.5) 30%,
      transparent 70%
    );
  }
}

/* 2026-08-02, per /grill-me: Mobile Sticky-Bottom-Bar ("Menue unten, immer sichtbar, 2 Buttons
   Anrufen & Anfragen"). Bewusst ausserhalb der Media Query definiert (display:none als
   Default), damit das Markup zwar immer im DOM steht (kein JS-Rendering noetig), aber nur ab
   767px abwaerts sichtbar wird.
   Sicherheitsabstand nach unten per env(safe-area-inset-bottom): das ist die Aussparung fuer
   die Home-Indicator-Wischleiste neuerer iPhones (nicht zu verwechseln mit Safaris
   Adressleiste; seit iOS 15 respektiert position:fixed bereits automatisch den sichtbaren
   Viewport unterhalb der Adressleiste, dafuer ist kein zusaetzliches CSS noetig). Auf
   Geraeten ohne Aussparung (Android, aeltere iPhones) faellt der Wert auf 0px zurueck, kein
   Nachteil dort. */
.mobile-bottom-bar {
  display: none;
}

@media (max-width: 767px) {
  /* 2026-08-02: Nutzerwunsch "Hintergrund glasig machen". Vorher rgba(18,15,28,0.92): fast
     blickdicht, kaum als Glas erkennbar. Jetzt an das etablierte .glass-panel-Rezept
     angeglichen (tokens.css: rgba(28,23,48,0.45) + blur(16px) saturate(130%) +
     violetter Rahmen), statt einer eigenen, abweichenden Glas-Variante. */
  .mobile-bottom-bar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    gap: 0.6rem;
    padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom));
    background: rgba(28, 23, 48, 0.45);
    backdrop-filter: blur(16px) saturate(130%);
    -webkit-backdrop-filter: blur(16px) saturate(130%);
    border-top: 1px solid rgba(157, 78, 255, 0.5);
  }

  .mobile-bottom-bar-call,
  .mobile-bottom-bar-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    font-size: 0.9rem;
    padding: 0.8em 0.6em;
  }

  /* Nutzerentscheidung: "Anfragen" (jetzt "Jetzt Fotobox mieten") optisch staerker, "Anrufen"
     dezenter. .btn-glow (tokens.css) liefert bereits den goldenen Sweep-Look, hier nur
     Display/Groesse an die schmale Bar angepasst. */
  .mobile-bottom-bar-cta {
    flex: 1.3;
  }

  .mobile-bottom-bar-call {
    flex: 1;
    border-radius: 999px;
    border: 1.5px solid rgba(246, 241, 231, 0.35);
    color: var(--text-primary);
    /* 2026-08-02, Nutzerfeedback: "zwischen dem Telefon-Icon und Anrufen ein Abstand
       hinzufuegen, das ist mir zu nah". Von 0.4rem auf 0.65rem erhoeht. */
    gap: 0.65rem;
  }

  /* 2026-08-02, Nutzerwunsch: "Verwende bitte ein klassisches reines weisses Icon fuer das
     Telefon" statt des vorherigen Emoji (📞). Eigenes SVG-Symbol (#icon-phone, index.html),
     Farbe explizit auf reines #fff gesetzt statt des geerbten --text-primary (#f6f1e7, ein
     warmer Creme-Ton, kein reines Weiss). */
  .mobile-bottom-bar-call .icon {
    width: 1.05rem;
    height: 1.05rem;
    color: #fff;
  }
}

/* 2026-08-02: Nutzerwunsch "von unten nach oben einen Verlauf, damit der Text besser lesbar
   wird" (Mobile). Der Text sitzt auf Mobile bottom-verankert (align-items:flex-end) ueber die
   fast volle Bildbreite, im Gegensatz zum Desktop (wo der bestehende Ecken-Verlauf, siehe
   #hero background weiter oben, gezielt nur die rechte untere Ecke abdunkelt) braucht es hier
   eine durchgehende Abdunkelung ueber die volle Breite. Eigenes ::after (statt den bestehenden
   ::before-Breathe-Effekt zu veraendern), faedet von unten (dunkel) nach oben (transparent)
   aus, sitzt zwischen Foto und Text (z-index:1, .wrap bleibt bei z-index:2). */
@media (max-width: 767px) {
  /* 2026-08-02: Nutzerwunsch "Tagline/Fliesstext weiter nach oben". Der Verlauf endete bisher
     bereits bei 65% Bildhoehe komplett transparent, der jetzt hoeher sitzende Text landet
     dadurch teils ausserhalb der abdunkelnden Zone, verliert an Kontrast/Lesbarkeit gegen das
     helle Spiegel-Motiv im Foto. Reichweite auf 85% erhoeht, deckt die neue, hoehere
     Text-Position weiterhin verlaesslich ab. */
  #hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(
      0deg,
      rgba(0, 0, 0, 0.85) 0%,
      rgba(0, 0, 0, 0.55) 35%,
      transparent 85%
    );
  }
}

/* 2026-07-10: Nutzerfeedback "Inhalt ist mir zu mittig durch das Hintergrundbild". Ursache:
   .wrap (margin-inline: auto) sitzt als einzelnes Flex-Kind in #hero, die Auto-Raender
   zentrierten die Box dadurch ungewollt statt sie links andocken zu lassen. Fix: linker Rand
   fix auf denselben Gutter wie Header/Nav, rechter Rand bleibt auto (absorbiert den Rest),
   Foto bekommt so sichtbar mehr Raum rechts.
   2026-07-10 nachgebessert: reiner Header-Gutter (max. 2.5rem) war dem Nutzer "jetzt zu weit
   links", grosszuegigerer Hero-Gutter (max. 5rem). Nutzer fand das immer noch "zu wenig",
   nochmal deutlich vergroessert auf max. 9rem (144px bei 1440px Breite). Nutzer wollte danach
   explizit "doppelt so breit wie aktuell, in der Desktop Version": Mobile/Tablet (< 900px)
   behaelt die vw-basierte Formel, Desktop bekommt einen eigenen, fixen, doppelt so grossen
   Wert (18rem = 288px statt 9rem = 144px). */
/* 2026-07-11: Nutzer-Root-Cause-Fund: das Hintergrundfoto zeigt den Spiegel links im Bild,
   der Textblock sass aber genau dort (linker Gutter), verdeckte also das eigentliche
   Hauptmotiv. Fix: Textblock auf die rechte Seite getauscht (dahin, wo vorher die
   "100% individuell"-Karte schwebte), rechtsbuendig (justify-items+text-align), die
   schwebenden Karten wandern dafuer auf die linke Seite (siehe .hero-float--top/--bottom). */
/* 2026-07-11, Nachbesserung (12. Runde): Nutzerfeedback "wenn ich das Fenster schmaler mache,
   springt der rechte Aussenabstand ab einem Punkt ploetzlich viel groesser". Root Cause: zwei
   getrennte Regeln trafen bei 900px aufeinander, die feste Desktop-Breite (12rem/192px, siehe
   ehemalige @media (min-width:900px)-Regel) war groesser als das Maximum der Formel darunter
   (9rem/144px) und erzeugte dadurch zwangslaeufig einen 84px-Sprung genau an der Bruchstelle
   (per Bounding-Box bei 899px vs. 900px verifiziert: 107.9px -> 192px). Fix: eine einzige,
   durchgehende clamp()-Formel deckt beide Faelle ab, waechst kontinuierlich mit 12vw bis sie
   bei 1600px Fensterbreite ihr Maximum (12rem/192px, identisch zum bisherigen Desktop-Wert)
   erreicht und dort deckelt. Kein Sprung mehr, der Abstand wird beim Schmaler-Ziehen
   gleichmaessig kleiner statt in einer Stufe. */
/* 2026-07-11, Nachbesserung (14. Runde): Nutzerfeedback "bei ca. 980px verhaelt sich das ganze
   Schriftgroessen-/Ausrichtungssystem komisch, ueberlagert sich ploetzlich". Root Cause: das
   komplette Drei-Woerter-System (grosses FOTOBOX, kleine rechtsbuendige Jetzt/Mieten,
   linksbuendige Spalte) war hinter @media (min-width:980px) versteckt, darunter griff ein
   voellig anderer, unabhaengiger Satz Regeln (einheitliche H1-Groesse fuer alle drei Woerter,
   keine Ausrichtungs-Differenzierung). Bei genau 980px trafen zwei komplett verschiedene
   Werte-Saetze aufeinander (FOTOBOX sprang von 41.6px auf 77.4px, Jetzt/Mieten von 41.6px auf
   25.5px, Ausrichtung von links auf rechts), verifiziert per Computed-Style bei 979px vs.
   980px. Fix: justify-items/text-align gelten jetzt IMMER (kein Breakpoint mehr noetig), die
   eigentliche Groessen-Differenzierung kommt jetzt aus durchgehenden clamp()-Formeln auf den
   Wort-Elementen selbst (siehe .hero-h1-word weiter unten), die auch auf sehr schmalen
   Viewports sinnvolle, kontinuierlich skalierende Werte liefern. Kein Sprung mehr moeglich, da
   keine zwei getrennten Regelsaetze mehr existieren. */
#hero .wrap {
  position: relative;
  z-index: 2;
  display: grid;
  gap: 1.4rem;
  max-width: 40rem;
  margin-inline: auto clamp(2rem, 12vw, 12rem);
  justify-items: start;
  text-align: left;
}

/* 2026-07-11: Glass-Panel im Hero wieder entfernt, Nutzerfeedback "das ist mir zu dominant"
   (bereits am selben Tag als Praeferenz notiert, siehe Design-Nachtrag, jetzt konkret
   umgesetzt). Kontrast fuer den Text kommt jetzt ausschliesslich vom radialen Verlauf
   (siehe #hero background) statt zusaetzlich von einer sichtbaren Glasflaeche. .hero-textpanel
   bleibt als Klasse fuer den Fall, dass hier spaeter wieder eine dezentere Variante noetig
   wird (siehe DESIGN_SYSTEM.md), aktuell ohne eigene Styles. */

/* 2026-07-11: Eyebrow-Pill ("Foto-Bergander · Magic Mirror Fotobox") komplett entfernt,
   Nutzerfeedback "das stört nur, an dieser Stelle". Nur hier verwendet, deshalb CSS mit
   entfernt statt totem Code liegen zu lassen. */

/* 2026-07-11: H1 war zwischenzeitlich ausserhalb von .wrap, frei positioniert oben rechts in
   der Ecke (siehe Git-Historie/DESIGN_SYSTEM.md fuer die damalige Begruendung). Per /grill-me
   wieder zurueckgeholt: "wieder in den wrap und rechtsbuendig". Kein position:absolute/
   .hero-content-Wrapper mehr noetig, H1 ist jetzt einfach der erste Grid-Eintrag in .wrap wie
   alle anderen Kinder, Abstand nach unten kommt automatisch aus .wrap { gap: 1.4rem }.
   Selektor bewusst "h1.hero-h1-corner" (Element + Klasse) statt nur ".hero-h1-corner": die
   konkurrierende Regel "h1.font-display" (tokens.css, setzt font-size: var(--text-h1)) hat
   dieselbe Spezifitaet, ein reiner Klassen-Selektor haette dagegen verloren.
   2026-07-11, /grill-me-Nachbesserung (4. Runde): text-align von rechtsbuendig auf linksbuendig
   gedreht, passend zur Spalte darunter (siehe #hero .wrap weiter oben).
   2026-07-11, Nachbesserung (14. Runde): der fruehere 980px-Breakpoint (separate, doppelt
   gepflegte font-size/line-height-Werte fuer mobil vs. desktop) ist komplett entfallen, siehe
   Kommentar bei #hero .wrap weiter oben. H1s eigene font-size ist ohnehin nur noch fuer die
   H1-eigene Box relevant (die sichtbaren Woerter haben laengst ihre eigene, explizite Groesse,
   siehe .hero-h1-word unten), deshalb reicht hier eine einzige, einfache clamp()-Formel.
   line-height von 0.92 auf 0.82 verengt (Nutzerwunsch "Zeilenabstand Jetzt/Fotobox/Mieten
   etwas verkleinern"). */
h1.hero-h1-corner {
  margin: 0;
  font-size: clamp(2rem, 6vw, 3.6rem);
  line-height: 0.82;
  text-align: left;
}

/* 2026-07-11: Nutzerwunsch "PREMIUM FOTOBOX so groß, dass es 60% der Breite einnimmt",
   spaeter mehrfach vergroessert/verkleinert (siehe Historie unten). Eigene, vw-basierte
   Schriftgroesse nur fuer die Wort-Elemente, nicht fuer die H1 selbst.
   2026-07-11, /grill-me-Nachbesserung (3. Runde): "nochmal vergroessern", deutlich (+25%
   gegenueber der vorherigen Groesse), Nutzerwunsch bewusst ueber die urspruengliche
   "60% der Breite"-Kalibrierung hinaus. Dies ist jetzt die Groesse von FOTOBOX (siehe
   .hero-h1-word--2), dem dominanten Keyword-Wort.
   2026-07-11, Nachbesserung (14. Runde): war bisher nur ab 980px aktiv (siehe #hero .wrap
   weiter oben fuer die volle Begruendung des Umbaus), Formel jetzt so kalibriert, dass sie auch
   auf sehr schmalen Viewports (ab ca. 320px) einen sinnvollen, kontinuierlich wachsenden Wert
   liefert, oberes Ende (8rem) bleibt bei der zuletzt bestaetigten Groesse.
   2026-08-02: Nutzerwunsch "FOTOBOX noch etwas vergroessern", Obergrenze von 8rem auf 9rem
   (+12.5%). */
.hero-h1-word {
  font-size: clamp(1.8rem, 9vw, 9rem);
}

/* 2026-07-11, /grill-me-Nachbesserung (4. Runde): Nutzerfeedback "PREMIUM ist zu dominant,
   kein Keyword, zwar wichtig aber kleiner". PREMIUM auf ca. 60% der FOTOBOX-Groesse
   verkleinert und rechtsbuendig gesetzt, sodass es exakt am rechten Rand von FOTOBOX
   abschliesst (FOTOBOX ist per shrink-to-fit-Grid-Item, siehe #hero .wrap, das breitere,
   linksbuendige Wort, das die Spaltenbreite definiert).
   2026-07-11, /grill-me-Nachbesserung (6. Runde): "PREMIUM kann kleiner werden", von ca. 60%
   auf ca. 45% der FOTOBOX-Groesse reduziert.
   2026-07-11, Nachbesserung (9. Runde): "PREMIUM kann noch kleiner geschrieben werden", von
   ca. 45% auf ca. 33% der FOTOBOX-Groesse.
   2026-07-11, Nachbesserung (10. Runde): "Premium" -> "Jetzt", neues drittes Wort "Mieten"
   unter FOTOBOX, "beides im gleichen Style". Gemeinsamer Selektor statt zweier identischer
   Regeln, garantiert, dass beide Kicker-Woerter niemals auseinanderlaufen koennen.
   2026-07-11, Nachbesserung (14. Runde): ebenfalls vom 980px-Breakpoint befreit, Formel so
   kalibriert, dass das ca. 33%-Groessenverhaeltnis zu FOTOBOX ueber den gesamten
   Viewport-Bereich erhalten bleibt (bei 1440px: 2.7/8=33.8%, bei 980px: ca. 33.4%).
   Untergrenze bei der Erstumsetzung auf 0.85rem gesetzt, das kollidierte bei sehr schmalen
   Viewports (ab ca. 375px, per Screenshot verifiziert) sichtbar mit FOTOBOX: die fixe
   1.5px-Kontur (-webkit-text-stroke, siehe @supports-Block weiter unten) und der fixe
   Dropshadow-Blur (12px) skalieren nicht mit der Schriftgroesse mit, bei 13.6px Schriftgroesse
   war die Kontur/der Schatten proportional zu dominant und liess die Buchstaben ineinander
   verschwimmen. Untergrenze auf 1.1rem angehoben, dadurch bleibt bei sehr schmalen Viewports
   genug Luft. */
.hero-h1-word--1,
.hero-h1-word--3 {
  font-size: clamp(1.1rem, 3vw, 3.05rem);
  text-align: right;
}

/* 2026-08-02, Nutzerwunsch: "Jetzt Fotobox mieten kann in der Mobile-Version wieder deutlich
   groesser werden, fast 70% groesser". Seit die Headline aus dem Header zurueck in die Hero-
   Section gewandert ist (Abschnitt 6zE), nutzt sie auf Mobile schlicht dieselbe unconditional
   Basis-Formel wie ueberall (bei 390px z. B. FOTOBOX ca. 35px), das ist der Nutzerwunsch nach
   deutlich groesser. Alle drei Werte (min/preferred/max) der beiden Formeln oben um Faktor 1.7
   skaliert, exakt derselbe Ansatz wie bei der iPad-Vergroesserung (Abschnitt 6zy). Mit #hero
   praefixiert, dieselbe Spezifitaets-Falle wie mehrfach zuvor in diesem Projekt: eine
   unpraefixierte Regel hier haette gegen die spaeter im File stehenden unconditional Basis-
   Regeln verloren, unabhaengig von der Media Query. */
@media (max-width: 767px) {
  #hero .hero-h1-word {
    font-size: clamp(3.06rem, 15.3vw, 9rem);
  }

  #hero .hero-h1-word--1,
  #hero .hero-h1-word--3 {
    font-size: clamp(1.87rem, 5.1vw, 3.05rem);
  }
}

/* 2026-08-02: Nutzerwunsch (mehrteilig): FOTOBOX bekommt einen expliziten hoeheren z-index,
   damit sie zuverlaessig ueber Jetzt UND Mieten liegt (vorher nur zufaellig durch DOM-
   Reihenfolge: Fotobox lag zwar schon ueber Jetzt (1. vs. 2. im DOM), aber Mieten (3. im DOM)
   haette eigentlich ueber Fotobox gelegen). Das ist Grundlage fuer zwei Dinge: 1) JETZT darf
   im Ruhezustand ganz bewusst leicht von FOTOBOX angeschnitten werden (siehe negativer
   margin-bottom, kein Zeilenabstand-Bug mehr, sondern gestalterische Absicht), 2) die neue
   Slide-in-Animation weiter unten, bei der MIETEN sichtbar HINTER Fotobox hervorkommen soll,
   das braucht zwingend, dass Fotobox in der Stapelreihenfolge ueber Mieten liegt. */
/* 2026-08-02, per /grill-me: Nutzerfeedback "in Safari rutscht das X von FOTOBOX in eine neue
   Zeile, nur bei breiterem Fenster". Vermutliche Ursache: seit dem Buchstaben-Splitting (siehe
   .hero-h1-letter, Abschnitt 6zs) ist FOTOBOX kein durchgehender Textlauf mehr, sondern sieben
   unabhaengige inline-block-Boxen, dadurch entfaellt das Font-Kerning ZWISCHEN den Buchstaben
   (Kerning wirkt nur innerhalb eines zusammenhaengenden Textlaufs). FOTOBOX wird dadurch real
   ein paar Pixel breiter als vorher, bei groesserer Schrift (breiterer Viewport, staerkerer
   clamp()-Wert) noch mehr, passend zum gemeldeten "breiter wird schlimmer". Da .hero-h1-caps
   per ResizeObserver (site.js) eine EINMALIG gemessene, feste Pixelbreite bekommt, kann diese
   Messung in Safari knapp genug daneben liegen, dass der letzte Buchstabe umbricht. Fix:
   white-space:nowrap erzwingt, dass FOTOBOX nie umbricht, unabhaengig von der exakten
   Breitenberechnung (siehe auch der Sicherheitspuffer in site.js). */
.hero-h1-word--2 {
  z-index: 3;
  white-space: nowrap;
}

/* 2026-08-02, /grill-me-Nachbesserung: Nutzerfeedback "man sieht Jetzt/Mieten, wenn sie
   hinter Fotobox stehen sollen, das muesste so eine nicht sichtbare Wand sein". Reines
   z-index-Stacking (siehe .hero-h1-word--2 oben) reicht dafuer nicht: Textglyphen haben
   Luecken/Raender ausserhalb von FOTOBOX' Buchstabenformen, an denen Jetzt/Mieten trotzdem
   durchschimmerten. Echte geometrische Maskierung statt Opacity-Trick: .hero-h1-mask
   (overflow:hidden, eigene natuerliche Zeilenhoehe per normalem Block-Fluss, TRAEGT KEIN
   eigenes transform) umschliesst je ein Wort. Das innere .hero-h1-word bekommt das transform,
   verlaesst dabei das Sichtfenster des Wrappers und wird hart abgeschnitten, unabhaengig von
   FOTOBOX' Buchstabenform. Prozentwerte fuer translateY beziehen sich auf die eigene Hoehe des
   TRANSFORMIERTEN Elements, die (da margin jetzt auf dem Wrapper sitzt, siehe unten) exakt der
   Fenstergroesse des Wrappers entspricht: 100% verschiebt das Wort exakt um sein eigenes
   Fenster, ist danach vollstaendig unsichtbar (mehr als 100% waere reine, unsichtbare
   Verschwendung, deshalb von vorher 160% auf 100% reduziert, behebt zugleich "Animation faehrt
   zu weit raus"). */
.hero-h1-mask {
  display: block;
  overflow: hidden;
}

/* 2026-08-02: die enge Zeilenhoehe (h1 line-height:0.82) plus die grosse, schattenstarke
   FOTOBOX liess frueher beide Nachbarn (Jetzt UND Mieten) unkontrolliert anschneiden. Margin
   sitzt jetzt auf dem .hero-h1-mask-Wrapper (nicht mehr auf dem transformierten Wort selbst),
   da nur der Wrapper am normalen Dokumentfluss teilnimmt und FOTOBOX' Flow-Position
   beeinflusst. JETZT bekommt einen kleinen, bewussten negativen Abstand (nur die untere
   Buchstabenkante wird leicht von FOTOBOX ueberlappt, Nutzerwunsch "nur die untere Kante leicht
   angeschnitten"). 2026-08-02, /grill-me-Nachbesserung: Nutzerwunsch "Mieten soll dauerhaft
   genauso leicht angeschnitten bleiben wie Jetzt" (vorher: Mieten blieb komplett frei). MIETEN
   bekommt dieselbe Technik, spiegelverkehrt (margin-top statt margin-bottom), in derselben
   Groessenordnung wie Jetzt. */
/* 2026-08-02, per /grill-me: Nutzerfeedback "wenn Jetzt hoch bounced, verschwindet leicht der
   obere Textbereich, als wuerde eine Maske drueber liegen". Genau vorhergesagter Nebeneffekt
   des Bounce-Ueberschiessens (Abschnitt 6zl): die Ease-Out-Back-Kurve laesst translateY kurz
   ueber 0 hinaus negativ werden (ca. -3px gemessen), das ragt oben minimal ueber das eigene
   Maskierungsfenster hinaus und wird dort von overflow:hidden abgeschnitten. Fix NUR fuer Jetzt
   (Nutzerwunsch: "nur beim oberen Bounce", Mieten bounct in die andere Richtung, unten gibt es
   ausreichend Puffer, dort nicht angepasst): overflow:hidden auf .hero-h1-mask--1 ersetzt durch
   overflow:visible + clip-path:inset(), da inset() auch NEGATIVE Werte erlaubt (erweitert die
   Clip-Grenze ueber die eigene Box hinaus), anders als overflow:hidden, das immer exakt an der
   eigenen Box-Kante clippt. -6px oben gibt dem Bounce-Ueberschuss (ca. 3px) reichlich Puffer,
   rechts/unten/links bleiben bei 0 unveraendert (identisches Abschneide-Verhalten wie vorher). */
.hero-h1-mask--1 {
  margin-bottom: -0.12em;
  overflow: visible;
  clip-path: inset(-6px 0 0 0);
}

.hero-h1-mask--3 {
  margin-top: -0.12em;
}

/* 2026-08-02, per /grill-me: Nutzerwunsch "FOTOBOX kann einen Blur-in-Effekt haben, Buchstabe
   fuer Buchstabe". Sieben fest kodierte .hero-h1-letter-Spans (siehe index.html, "Fotobox" ist
   ein fixes, nie wechselndes Wort, kein JS-Splitting noetig), jeder Buchstabe traegt sein
   eigenes animation-delay inline (0s bis 0.54s in 0.09s-Schritten). Startzustand unscharf +
   unsichtbar, blendet beim Hinzufuegen von .hero-letter-in (JS, IntersectionObserver, siehe
   site.js) scharf/sichtbar ein. Letzter Buchstabe (X) ist bei 0.54s + 0.5s Animationsdauer =
   1.04s fertig scharf, das ist die Basis fuer die neuen Start-Delays von Jetzt/Mieten weiter
   unten. */
.hero-h1-letter {
  opacity: 0;
  filter: blur(14px);
}

.hero-h1-letter.hero-letter-in {
  animation: hero-letter-blur-in 0.5s ease-out both;
}

@keyframes hero-letter-blur-in {
  to {
    opacity: 1;
    filter: blur(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-h1-letter {
    opacity: 1;
    filter: none;
    animation: none;
  }
}

/* 2026-08-02, per /grill-me: "Geile Animation": FOTOBOX steht zuerst allein da, dann schiebt
   sich JETZT von hinten raus, danach schiebt sich MIETEN nach unten aus FOTOBOX heraus. Beide
   Woerter fahren animiert symmetrisch 100% (komplett durch ihr eigenes Maskierungsfenster),
   der dauerhafte leichte Anschnitt bei beiden entsteht NICHT durch die Animation, sondern
   ausschliesslich durch die statischen Margins auf .hero-h1-mask oben. Basis-Zustand (ohne
   .hero-slide-in): beide Woerter liegen per transform komplett ausserhalb ihres eigenen
   Maskierungsfensters, dadurch unsichtbar, unabhaengig von jeder Opacity-Logik.
   animation-delay auf --word--3 laesst Mieten leicht ueberlappend NACH Jetzt starten
   (Nutzerwunsch: wiederholbar bei jedem Scroll in den Hero, siehe IntersectionObserver in
   assets/js/site.js). */
.hero-h1-word--1 {
  transform: translateY(100%);
}

.hero-h1-word--3 {
  transform: translateY(-100%);
}

/* 2026-08-02, /grill-me-Nachbesserung: Nutzerwunsch "leichter Bounce-Effekt bei der
   Out-Animation". cubic-bezier(0.34, 1.56, 0.64, 1) ist die Standard-"Ease-Out-Back"-Kurve
   (y-Werte >1 lassen die Kurve rechnerisch ueber ihr Ziel hinausschiessen, bevor sie zurueck auf
   100% einschwingt), erzeugt einen dezenten, einmaligen Nachwipper in einer einzigen Kurve, ganz
   ohne zusaetzliche Keyframe-Zwischenschritte.
   2026-08-02, /grill-me-Nachbesserung: Nutzerfeedback "Jetzt/Mieten-Animation kommt zu schnell,
   man nimmt es kaum wahr". Root Cause: startete bisher praktisch zeitgleich mit FOTOBOX' eigener
   Einblendung, kein spuerbarer "FOTOBOX zuerst allein"-Moment. Neues animation-delay laesst
   Jetzt jetzt erst starten, NACHDEM FOTOBOX' Buchstaben-Einblendung fertig ist (1.04s) PLUS eine
   kurze, bewusste Pause (0.3s) = 1.35s. Mieten behaelt seinen 0.45s-Versatz NACH Jetzt (1.35s +
   0.45s = 1.8s). */
.hero-h1-word--1.hero-slide-in {
  animation: hero-word-emerge-up 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) 1.35s both;
}

.hero-h1-word--3.hero-slide-in {
  animation: hero-word-emerge-down 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) 1.8s both;
}

@keyframes hero-word-emerge-up {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

@keyframes hero-word-emerge-down {
  from { transform: translateY(-100%); }
  to { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-h1-word--1,
  .hero-h1-word--3 {
    transform: none;
    animation: none;
  }
}

/* "PREMIUM FOTOBOX" per text-transform statt hart codierter Grossschreibung im Markup, damit
   der Quelltext normal lesbar bleibt (Screenreader/Suchmaschinen lesen "Premium Fotobox",
   nicht Buchstabe fuer Buchstabe).
   2026-07-11: Nutzerwunsch "vielleicht nur als outline". -webkit-text-stroke ist die einzige
   breit unterstuetzte CSS-Methode fuer echten Konturtext (kein SVG-Text noetig), Farbe ist
   Gold statt Weiss/Neon, passt zum Projekt-Grundsatz "Gold = Luxus-Layer, immer sichtbar,
   Headlines" aus design/DESIGN_SYSTEM.md. Fallback fuer Browser ohne text-stroke-Support:
   color bleibt transparent gesetzt, was dort schlicht unsichtbaren Text ergaebe, deshalb
   zusaetzlich @supports-Fallback auf normale gefuellte Gold-Schrift.
   2026-07-11, /grill-me-Nachbesserung: "Premium" und "Fotobox" sind jetzt zwei eigene
   Wort-Spans (`.hero-h1-word`) statt eines einzigen, umbrechenden `.hero-h1-caps`-Blocks, damit
   jedes Wort seinen eigenen, rein horizontalen Sweep bekommt (siehe unten). `.hero-h1-caps`
   bleibt nur noch als reiner Wrapper ohne eigene Typografie-Eigenschaften. */
.hero-h1-corner .hero-h1-caps {
  display: block;
}

/* 2026-08-02: Nutzerwunsch "Jetzt FOTOBOX Mieten rechtsbuendig, damit es rechts mit dem
   Fliesstext buendig abschliesst" (Desktop). FOTOBOX definierte bisher als linksbuendiges,
   shrink-to-fit-Element selbst die Spaltenbreite (Jetzt/Mieten waren schon rechtsbuendig ZU
   FOTOBOX), der Fliesstext ist aber unabhaengig breiter (bei 1440px: Fliesstext-Kante
   1267px vs. Headline-Kante 1224px, 43px Differenz, per Bounding-Box verifiziert). Fix: FOTOBOX
   dreht auf rechtsbuendig um, .hero-h1-caps bekommt per ResizeObserver (assets/js/site.js)
   eine live an den Fliesstext gekoppelte Breite, exakt dieselbe Technik wie beim "So laeuft's
   ab"-Breitenabgleich weiter oben. Nur ab 768px aktiv (dort ist .hero-lede-desktop, der
   Breitenbezug, ueberhaupt sichtbar), Mobile (eigenes position:absolute-Layout, siehe weiter
   oben) bleibt unangetastet. */
/* 2026-08-11, Bugfix: Nutzerfeedback "beim Neuladen (F5) steht FOTOBOX kurz an einer anderen
   Stelle und springt dann". Root Cause: `text-align: right` (Regel unten) wirkt nur, wenn die
   umschliessende Box (.hero-h1-caps) BREITER ist als das Wort selbst. Im reinen CSS-Zustand ist
   sie das nicht: die H1 ist ein Grid-Item in #hero .wrap { justify-items: start }, also
   shrink-to-fit, exakt so breit wie FOTOBOX. Die Ausrichtung entstand dadurch ausschliesslich
   durch die JS-Breitenkopplung darunter, und die haengt an `document.fonts.ready`, laeuft also
   erst nach dem Font-Download. Genau dieses Zeitfenster war sichtbar: Headline schon gerendert,
   aber noch linksbuendig in ihrer eigenen schmalen Box.
   Fix: der CSS-Grundzustand stellt dieselbe Geometrie schon beim allerersten Paint her, ohne
   JS. `justify-self: stretch` hebt das geerbte `start` nur fuer die H1 auf (alle anderen
   Grid-Kinder bleiben shrink-to-fit), die H1 fuellt dadurch die volle Spaltenbreite, und
   `text-align: right` hat endlich etwas zum Ausrichten. `min-width: max-content` auf .hero-h1-caps
   bildet dabei exakt den Mindestbreiten-Boden nach, den auch das JS setzt
   (Math.max(Fliesstextbreite, capsNaturalWidth), siehe assets/js/site.js): FOTOBOX ist bei
   grossen Viewports breiter als die 40rem-Spalte und darf nicht gestaucht werden.
   Das JS bleibt unveraendert und uebernimmt danach den Feinabgleich (Pixelbreite exakt an der
   tatsaechlich gerenderten Fliesstext-Kante). Es stellt die Position jetzt nur nicht mehr
   ueberhaupt erst her, sondern korrigiert eine bereits richtige um wenige Pixel, deshalb ist
   der Sprung nicht mehr wahrnehmbar. Zusaetzlich werden die Fonts jetzt vorgeladen (siehe
   index.html), was `document.fonts.ready` und damit den JS-Feinabgleich deutlich frueher
   ausloest. */
@media (min-width: 768px) {
  h1.hero-h1-corner {
    justify-self: stretch;
  }

  .hero-h1-corner .hero-h1-caps {
    min-width: max-content;
  }

  /* 2026-08-11: `white-space: nowrap` ersetzt den frueheren 8px-safetyBuffer aus site.js. FOTOBOX
     besteht seit dem Buchstaben-Splitting (Abschnitt 6zs) aus sieben inline-block-Spans, zwischen
     denen der Browser umbrechen DARF, sobald die Box auch nur einen Bruchteil eines Pixels zu
     schmal wird (daher der alte Safari-Bug "das X rutscht in eine neue Zeile"). Der Puffer hat das
     nur mit Reservebreite umgangen und dabei einen sichtbaren 8px-Sprung erzeugt, sobald das JS
     lief (in echtem Safari nachgemessen, siehe DESIGN_SYSTEM.md 6zT). nowrap loest die Ursache:
     zwischen den Buchstaben kann jetzt gar nicht mehr umgebrochen werden, egal wie die Box misst. */
  .hero-h1-word--2 {
    text-align: right;
    white-space: nowrap;
  }
}

/* 2026-07-11, /grill-me-Nachbesserung (6. Runde): Nutzerwunsch "PREMIUM FOTOBOX einen
   Dropshadow geben", dezenter dunkler Tiefenschatten, hebt den Text vom hellen Foto-Hintergrund
   (Kronleuchter/Kleider) ab. filter statt text-shadow, da filter:drop-shadow() die tatsaechliche
   Glyphenform respektiert (inkl. Kontur), nicht nur die Bounding-Box.
   2026-08-02: Nutzerwunsch "Dropshadow verstaerken (Desktop UND Mobile)". Diese Regel ist
   bewusst nicht an einen Breakpoint gebunden, verstaerkt beide Ansichten mit einer einzigen
   Aenderung. Groesserer Versatz, weiterer/weicherer Blur, mehr Deckkraft. */
/* 2026-08-02, per /grill-me: Nutzerwunsch "alle H2-Ueberschriften im Fotobox-Stil". Die
   Basis-Deklaration (Kontur-Vorbereitung, Grossschreibung, Gold, Dropshadow) gilt jetzt fuer
   .hero-h1-word UND .h2-gold-word gemeinsam (siehe splitIntoGoldWords in site.js, teilt jede
   H2 wortweise in .h2-gold-word-Spans auf, analog zu Jetzt/Fotobox/Mieten). display bleibt
   bewusst getrennt: Hero-Woerter stapeln sich als eigene Zeilen (block), H2-Woerter sollen
   normal im Fliesstext der Ueberschrift umbrechen (inline-block). */
/* 2026-08-02, /grill-me-Nachbesserung: Nutzerfeedback "Dropshadow ist weich, auffaellig auf
   Mobile, soll schaerfer/knackiger werden, allgemein nicht soft". Blur-Radius von 20px auf 3px
   reduziert (der grosse Blur-Radius war die Ursache fuer den diffusen, glow-artigen statt
   scharf umrissenen Schatten), Deckkraft von 0.65 auf 0.8 leicht erhoeht, Versatz minimal
   angepasst. Gilt fuer Hero-H1-Woerter UND H2-Ueberschriften gemeinsam (dieselbe Regel), haelt
   beide im gleichen, jetzt schaerferen Look, konsistent mit der bewussten Vereinheitlichung aus
   Abschnitt 6zk. */
.hero-h1-word,
.h2-gold-word,
.hero-h1-letter {
  position: relative;
  text-transform: uppercase;
  color: var(--gold-bright);
  filter: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.8));
}

.hero-h1-word {
  display: block;
}

.h2-gold-word,
.hero-h1-letter {
  display: inline-block;
}

@supports (-webkit-text-stroke: 1px black) or (text-stroke: 1px black) {
  /* 2026-07-11, /grill-me-Nachbesserung (3. Runde): zwei Probleme aus der letzten Fassung.
     1) Der Sweep lief sichtbar rechts nach links statt links nach rechts: bei einer
     background-size, die groesser als das Element ist (hier 300%), kehrt die
     background-position-Prozent-Formel `(Containergroesse - Bildgroesse) * (Prozent/100)` das
     Vorzeichen um, ein steigender Prozentwert verschiebt das Bild dann nach links statt rechts.
     Fix: Keyframes umgedreht (Start bei 150%, Ende bei -150%).
     2) Nutzerwunsch: die ruhende Basis-Fuellung soll doch wieder transparentes Weiss enthalten
     (warmer Weissgold-Kern statt reinem Gold), UND eine eigene, ganz dezente, langsame
     Schwebe-Bewegung bekommen, damit es nicht zu statisch wirkt, unabhaengig vom schnellen
     Glanzstreifen-Sweep. Da eine einzelne `animation`-Eigenschaft nicht zwei unterschiedlich
     schnelle Bewegungen auf derselben `background-position`-Property ueberlagern kann (mehrere
     Animationen auf derselben Property konkurrieren, gewinnen tut nur eine), sind Basis-Fuellung
     und Glanzstreifen jetzt zwei getrennte Ebenen: `.hero-h1-word` selbst traegt die Basis
     (Kontur + langsame Drift), ein `::after`-Pseudo-Element (dupliziert den Wortlaut per
     `content: attr(data-word)`, exakt deckungsgleich per `position:absolute; inset:0`) traegt
     nur den schnellen Glanzstreifen. Beide werden unabhaengig voneinander per
     background-clip:text auf dieselbe Buchstabenform maskiert. */
  /* 2026-07-11, /grill-me-Nachbesserung (5. Runde): "F von FOTOBOX ist immer transparent,
     Drift geht nicht an den aeusseren Rand". Root Cause: die transparenten Stops (0-15%,
     85-100%) plus die kleine Drift-Range (0-30% Position) liessen bei FOTOBOX (linksbuendig,
     fuellt seine Box randlos) das erste Sechstel des Wortes ("F") permanent in der toten,
     transparenten Zone stehen, unabhaengig vom Drift-Stand (bei PREMIUM faellt das nicht auf,
     weil es rechtsbuendig in einer breiteren, groesstenteils leeren Box sitzt). Fix: keine
     transparenten Stops mehr, immer mindestens Gold sichtbar, nur der warme Weissgold-Glanz-
     punkt wandert (Drift-Range vergroessert auf 0-60%, damit er wirklich von einer Seite zur
     anderen zieht statt nur leicht zu zittern).
     2026-07-11, /grill-me-Nachbesserung (6. Runde): Nutzerfeedback "F hat jetzt dieselbe
     Fuellfarbe wie die Outline, das gefaellt mir nicht, da muss leichte Transparenz rein". Die
     Randstops waren volles, deckendes var(--gold), optisch fast identisch zur
     -webkit-text-stroke-Farbe (var(--gold-bright)), dadurch verschwamm die Kontur mit der
     Fuellung. Fix: Randstops auf rgba(232, 196, 104, 0.65) (var(--gold) mit 65% Deckkraft),
     die helle Mitte (Glanzpunkt) bleibt voll deckend, Kontur ist dadurch wieder klar von der
     Fuellung unterscheidbar. */
  .hero-h1-word,
  .h2-gold-word,
  .hero-h1-letter {
    color: transparent;
    -webkit-text-stroke: 1.5px var(--gold-bright);
    text-stroke: 1.5px var(--gold-bright);
    background-image: linear-gradient(
      90deg,
      rgba(232, 196, 104, 0.65) 0%,
      #fff2cf 50%,
      rgba(232, 196, 104, 0.65) 100%
    );
    background-size: 160% 100%;
    background-position: 0% 0;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: hero-h1-drift 13s ease-in-out infinite;
  }

  /* 2026-08-02: Nutzerwunsch "Outline von FOTOBOX etwas die Deckkraft reduzieren". Nur fuer die
     FOTOBOX-Buchstaben (.hero-h1-letter), Jetzt/Mieten und die H2-Ueberschriften behalten die
     volle Kontur-Deckkraft aus der geteilten Regel oben. text-stroke kennt keine eigene
     opacity-Eigenschaft, deshalb rgba() statt var(--gold-bright) direkt in der Stroke-Farbe. */
  .hero-h1-letter {
    -webkit-text-stroke-color: rgba(255, 226, 154, 0.55);
    text-stroke-color: rgba(255, 226, 154, 0.55);
  }

  /* 2026-07-11, /grill-me-Nachbesserung (6. Runde): Nutzerfeedback "Streifen ist zu schnell,
     kein Charm, eleganter/ruhiger, leicht in Schraeglage". Zyklus von 6s auf 11s verlaengert
     (Sweep-Phase dadurch ca. 4.4s statt 2.4s), Winkel von 90deg (exakt horizontal, noetig fuer
     die Wort-fuer-Wort-Trennung in Runde 3) auf 100deg (leichte Schraeglage wie im allerersten
     Entwurf) geaendert. Unbedenklich jetzt, da PREMIUM/FOTOBOX bereits eigenstaendige Woerter
     sind, kein Zwei-Zeilen-Diagonal-Problem mehr moeglich.
     2026-07-11, Nachbesserung (12. Runde): Nutzerfeedback "bei Jetzt/Mieten faellt der Streifen
     kaum auf" (technisch lief er schon korrekt, war bei der kleinen Schriftgroesse nur zu
     unauffaellig). Auf Nutzerwunsch "bei allen langsamer und breiter": Zyklus von 11s auf 18s
     verlaengert, Glanzband von 20% auf 50% der Bildbreite verbreitert (40-60% -> 25-75%),
     zusaetzlicher Zwischenstop erhoeht die wahrgenommene Kraeftigkeit des Streifens. */
  .hero-h1-word::after,
  .h2-gold-word::after {
    content: attr(data-word);
    position: absolute;
    inset: 0;
    color: transparent;
    background-image: linear-gradient(
      100deg,
      transparent 25%,
      rgba(255, 255, 255, 0.5) 35%,
      #fff 50%,
      rgba(255, 255, 255, 0.5) 65%,
      transparent 75%
    );
    background-size: 300% 100%;
    background-position: 150% 0;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: hero-h1-sweep 18s linear infinite;
    pointer-events: none;
  }

  /* 2026-07-11, Nachbesserung (10. Runde): mit dem neuen dritten Wort ("Mieten") auf drei statt
     zwei gleichmaessige Verzoegerungs-Schritte ueber den Zyklus verteilt, damit alle drei
     Woerter nacheinander sweepen statt sich zu ueberschneiden.
     2026-07-11, Nachbesserung (12. Runde): Werte an den neuen 18s-Zyklus angepasst
     (18/3 = 6s-Schritte statt 11/3 = 3.67s). */
  .hero-h1-word--2::after {
    animation-delay: 6s;
  }

  .hero-h1-word--3::after {
    animation-delay: 12s;
  }

  /* 2026-08-02, per /grill-me: H2-Ueberschriften haben (anders als die Hero-H1 mit ihren fest
     bekannten drei Woertern) eine variable Wortanzahl je Ueberschrift, feste Klassen wie oben
     funktionieren dafuer nicht. Stattdessen setzt splitIntoGoldWords (site.js) je Wort eine
     CSS-Custom-Property --h2-sweep-delay per Inline-Style, vererbt sich an das eigene
     ::after-Pseudoelement (Custom Properties vererben sich durch Pseudoelemente), steuert so
     einen individuellen Versatz pro Wort UND pro Ueberschrift, ganz ohne feste Klassenzahl. */
     2026-08-11: der Sweep laeuft jetzt nicht mehr ab Seitenaufruf, sondern erst wenn die
     Ueberschrift sichtbar wird (site.js setzt .is-sweeping per IntersectionObserver, volle
     Begruendung samt Messwerten dort). Nur animation-name wird umgeschaltet, Dauer/Timing/
     Wiederholung bleiben in der gemeinsamen Deklaration oben, damit H1 und H2 denselben Sweep
     behalten und nicht zwei Stellen gepflegt werden muessen. */
  .h2-gold-word::after {
    animation-name: none;
  }

  /* 2026-08-11, zweite Runde: Nutzerfeedback "die Sweep-Animation im H2 sehe ich noch nicht",
     obwohl sie nach dem Sichtbarkeits-Trigger nachweislich lief (background-position per
     Computed Style ueber die Zeit protokolliert: wandert sauber von 11% auf -150%). Es war also
     kein Fehler, sondern eine Wahrnehmungsfrage, und die Ursache steckt in der Geometrie des
     Verlaufs:
     Das geteilte Glanzband (siehe Regel oben) reicht von 25% bis 75% eines 300% breiten
     Hintergrunds, ist also 150% SO BREIT WIE DAS WORT SELBST. Bei der riesigen H1 ergibt das
     genau den gewuenschten wandernden Streifen. Ein kurzes H2-Wort ("So", "ab") liegt dagegen
     komplett und gleichzeitig im hellen Bereich, es wandert nichts sichtbar durch, das Wort wird
     ueber die 7.2s Sweep-Phase nur langsam etwas heller und wieder dunkler. Zusaetzlich enthaelt
     die ruhende Basis-Fuellung ohnehin schon einen fast weissen Kern (#fff2cf, siehe Regel oben),
     wodurch ein zusaetzlicher, flaechiger Weiss-Schleier kaum auffaellt.
     Fix, zwei Groessen, beide nur fuer H2 (H1 bleibt unangetastet):
     1) Schmales Band statt Flaeche: 42% bis 58% des Hintergrunds entsprechen 48% der Wortbreite,
        der helle Kern nur 18%. Damit zieht wirklich ein Streifen ueber das Wort, statt das ganze
        Wort auf einmal aufzuhellen. Voll deckendes Weiss im Kern, damit es sich klar vom warmen
        Weissgold der Basis abhebt.
     2) Eigene Keyframes mit kurzer Durchlaufphase (h2-gold-sweep, 20% statt 40% des Zyklus): der
        Streifen quert das Wort in ca. 2.4s statt 7.2s. Zusammen mit dem Sichtbarkeits-Trigger
        ist das ein klar erkennbares Aufblitzen beim Ankommen, danach bleibt es ruhig. */
  .h2-gold-word.is-sweeping::after {
    background-image: linear-gradient(
      100deg,
      transparent 42%,
      rgba(255, 255, 255, 0.45) 47%,
      #ffffff 50%,
      rgba(255, 255, 255, 0.45) 53%,
      transparent 58%
    );
    animation-name: h2-gold-sweep;
    animation-duration: 12s;
    animation-delay: var(--h2-sweep-delay, 0s);
  }
}

@keyframes hero-h1-drift {
  0%, 100% { background-position: 0% 0; }
  50% { background-position: 60% 0; }
}

@keyframes hero-h1-sweep {
  0% { background-position: 150% 0; }
  40% { background-position: -150% 0; }
  100% { background-position: -150% 0; }
}

/* 2026-08-11: eigener Sweep fuer die H2-Ueberschriften. Identischer Weg wie hero-h1-sweep, nur
   kuerzere Durchlaufphase (20% statt 40% des Zyklus), damit der Streifen bei der kleineren
   Schriftgroesse als klares Aufblitzen wahrgenommen wird statt als langsames Aufhellen. Volle
   Begruendung samt Messwerten bei .h2-gold-word.is-sweeping::after weiter oben. */
@keyframes h2-gold-sweep {
  0% { background-position: 150% 0; }
  20% { background-position: -150% 0; }
  100% { background-position: -150% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-h1-word,
  .h2-gold-word,
  .hero-h1-letter {
    animation: none;
    background-image: none;
  }

  .hero-h1-word::after,
  .h2-gold-word::after {
    content: none;
  }
}

/* 2026-07-11: "Für den Moment, der bleibt" war zwischenzeitlich ein echter Untertitel
   INNERHALB der H1, "...und die Magie beginnt" ein komplett separates <p> darunter (Script-
   Zeile). Trotz mehrfach angeglichener Deklarationen (Font-Family in Runde 6, Grossschreibung/
   Gewicht/Glow in Runde 5) wirkten sie nie wie eine Einheit, weil es zwei verschiedene
   Groessen-Systeme waren (Subtitle: 0.36em relativ zur H1-Groesse, Script-Zeile: eigene
   clamp()-Deklaration) und der Abstand zwischen ihnen aus zwei unabhaengigen Quellen kam
   (Subtitle: margin-top relativ zur H1, Script-Zeile: .wrap { gap }).
   2026-07-11, /grill-me-Nachbesserung (8. Runde): beide Zeilen sind jetzt ein einziges
   `<p class="hero-tagline">`-Element mit zwei block-Zeilen (`.hero-tagline-row`) darin
   (index.html), nicht mehr Teil der H1. Eine Typografie-Deklaration fuer beide, der Abstand
   zwischen den Zeilen kommt jetzt einheitlich aus line-height statt aus zwei verschiedenen
   Spacing-Systemen. Nebenbei einen zweiten, vom Nutzer bewusst nicht genannten Bug gefunden:
   `#hero p { color: var(--text-primary) }` (ID+Element-Selektor) schlug `.glow-neon`s
   `color:#fff` fuer die Script-Zeile (ein <p>), aber nicht fuer den alten Subtitle-Span (kein
   <p>), beide waren dadurch leicht unterschiedlich weiss. `.hero-tagline` bekommt hier
   `color: #fff !important` als gezielten, dokumentierten Ausnahmefall (einzige Stelle im
   Projekt), um diese Spezifitaets-Falle zu umgehen, ohne die globale `#hero p`-Regel fuer
   andere Absaetze zu veraendern. */
/* 2026-07-11, Nachbesserung (14. Runde): Nutzerwunsch "Zeilenabstand Der Moment/...und die
   Magie beginnt enger". Bisher kein eigener line-height gesetzt, erbte 1.6 vom Fliesstext-
   Standard (viel zu locker fuer zwei zusammengehoerige Display-Zeilen). */
.hero-tagline-row {
  display: block;
  line-height: 1.15;
}

#hero .hero-tagline {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.6vw, 1.8rem);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #fff !important;
}

/* 2026-08-02, per /grill-me-Nachbesserung mit Skizze: der vorherige Rechtsbuendig-Versuch
   (Nutzerfeedback direkt danach: "das war ein Fehler, hast Du falsch verstanden") wieder
   entfernt. Skizze zeigt eindeutig: Tagline bleibt linksbuendig (Erbwert aus #hero .wrap),
   sitzt aber NEBEN MIETEN auf etwa gleicher Zeilenhoehe statt rechtsbuendig darunter (Vertikal-
   Positionierung siehe syncTaglineGapToMieten() in assets/js/site.js). */

/* 2026-07-11, Nachbesserung (12. Runde): Nutzerwunsch "Der Moment, der bleibt" naeher an
   MIETEN heranrutschen lassen. Erster Versuch (Tagline-Box-Mitte = MIETEN-Box-Mitte, -5.4rem)
   fuehrte dazu, dass sich die Buchstaben von "MIETEN" und "DER MOMENT, DER BLEIBT" sichtbar
   kreuzten (Box-Hoehe enthaelt line-height-Leerraum, nicht nur die reine Textglyphen-Hoehe).
   Nutzerkorrektur auf -2.4rem, wirkte optisch aber noch wie auf Hoehe von MIETENs Unterkante.
   Wichtiger Fund dabei: #hero { align-items:flex-end } bedeutet, dass margin-top auf der
   Tagline NICHT die Tagline selbst auf dem Bildschirm verschiebt (ihre absolute Position ist
   rechnerisch invariant, siehe Kommentar-Historie/Commits), sondern MIETEN/FOTOBOX (alles
   darueber) nach unten schiebt, je negativer der Wert. Die Tagline "wandert" also nur relativ
   zu MIETEN, nicht auf dem Bildschirm. Ein erster Korrekturversuch (-2.9rem) ging in die
   falsche Richtung (schob MIETEN zu weit runter, Tagline landete naeher an MIETENs Oberkante
   statt mittig). Rechnerisch kalibriert (per Bounding-Box-Interpolation zwischen -2.4rem/53.5%
   und -2.9rem/30.3% Position-von-MIETEN-Oberkante): -2.5rem liegt sehr nah am 50%-Ziel.
   .wrap { gap } ist fuer ALLE Kinder einheitlich, deshalb gezielt per negativem margin-top NUR
   auf die Tagline.
   2026-07-11, Nachbesserung (14. Runde): -2.5rem war fest bei 1440px kalibriert und nur ab
   980px aktiv, siehe #hero .wrap weiter oben fuer die volle Begruendung, warum dieser
   Breakpoint komplett entfallen ist. In em statt rem umgerechnet (-2.5rem / 1.8rem
   Tagline-Schriftgroesse bei 1440px = -1.39em), damit der Ueberlapp-Effekt proportional mit
   der jetzt durchgehend skalierenden Tagline-Schriftgroesse mitwaechst/-schrumpft, statt bei
   kleinen Viewports einen unveraendert grossen, dann unproportional wirkenden Fixwert zu
   behalten. */
/* 2026-08-02, per /grill-me: Nutzerfeedback "BLEIBT ueberlappt MIETEN, das war ein Fehler,
   Du musst berechnen wo Mieten steht". Root Cause der wiederholten Fehlkalibrierung: ein
   fester em-Wert kann diese Beziehung nicht ueber den gesamten Breiten-Bereich korrekt
   abbilden, weil Tagline- und Mieten-Schriftgroesse unterschiedliche clamp()-Kurven haben
   (unterschiedliche vw-Steigung, unterschiedliche Punkte, an denen sie ihr Maximum erreichen).
   Ein Wert, der bei 1440px 10px Abstand ergab, erzeugte bei 1920px wieder echten Overlap
   (-10px), bei 768/820px dagegen einen unnoetig grossen Abstand (bis 45px). Empirisch
   bestaetigt: der Zusammenhang zwischen margin-top (in px) und dem resultierenden Abstand ist
   exakt linear (1:1, siehe DESIGN_SYSTEM.md), aber die KONSTANTE dieser linearen Funktion
   aendert sich mit der Viewport-Breite, ein einzelner CSS-Wert kann das nicht abbilden. Fix:
   margin-top wird jetzt per JS dynamisch berechnet (siehe site.js), misst bei jeder
   Breitenaenderung live den tatsaechlichen Abstand und korrigiert exakt auf das Zielmass.
   Statischer Fallback (falls JS/ResizeObserver fehlt) bleibt bei einem grosszuegigen,
   garantiert ueberlapp-freien Wert.
   2026-08-02, Bugfix: dieser Fallback war nie auf 768px+ (den JS-gesteuerten Bereich)
   beschraenkt, galt also unbemerkt auch auf Mobile, wo die Tagline nie eine Pull-up-Korrektur
   braucht (dort gibt es kein Mieten-Ueberlapp-Problem). Blieb lange unsichtbar, weil die H1 auf
   Mobile bis eben in den Header ausgelagert war (Abschnitt 6zv) und so nichts da war, worauf
   die um -7.5em (=ca. 150px bei mobiler Schriftgroesse) nach oben gerissene Tagline haette
   ueberlappen koennen. Seit der Ruecknahme der Header-Verschiebung (Abschnitt 6zE) steht die H1
   wieder in .wrap, der Bug wurde dadurch sofort sichtbar (Tagline rendert komplett ueber der
   H1). Jetzt korrekt auf den JS-gesteuerten Breitenbereich beschraenkt. */
/* 2026-08-11, Bugfix (Root Cause des vom Nutzer gemeldeten Sprungs beim Neuladen): dieser
   statische Fallback war in ZWEI Punkten falsch, beide in echtem Safari nachgemessen (Werte bei
   1324px Fensterbreite, Tagline-Schriftgroesse 29px).
   1) Er war nicht hoehenneutral. syncTaglineGapToMieten() (site.js) setzt margin-top UND einen
      exakt gegenlaeufigen margin-bottom, damit .wraps Gesamthoehe unveraendert bleibt (dort
      ausfuehrlich als "Kompensation" dokumentiert). Dieser CSS-Fallback hatte nur die negative
      Haelfte. Folge: im CSS-Ruhezustand schrumpfte die Tagline-Zeile im Grid auf Hoehe 0
      (geklemmt, da 67px Eigenhoehe minus 216px Margin negativ waere), .wrap war dadurch 430px
      hoch statt 496px. Da #hero { align-items: flex-end } den Block UNTEN verankert, wuchs er
      beim JS-Lauf um genau diese 66px nach OBEN, und FOTOBOX sprang sichtbar mit: gemessen
      Oberkante 335px bis 503ms, danach 269px.
   2) Der Wert selbst war viel zu gross. -7.5em = -216px zog die Tagline nicht nur neben, sondern
      komplett UEBER die Headline (Tagline-Oberkante 296px lag ueber FOTOBOX' 335px), also genau
      der Ueberlapp, den der Wert laut seiner eigenen Historie verhindern sollte. Das JS
      berechnet an derselben Stelle -74px, umgerechnet -2.55em.
   Fix: Wert auf -2.5em korrigiert (nahe am gemessenen JS-Ergebnis) und mit exakt gegenlaeufigem
   margin-bottom gepaart. Beide Zustaende sind jetzt hoehenneutral, .wrap ist vor und nach dem
   JS-Lauf gleich hoch, die Headline kann sich dadurch gar nicht mehr vertikal verschieben.
   Das Aussehen NACH dem JS-Lauf aendert sich nicht: syncTaglineGapToMieten() ueberschreibt beide
   Margins ohnehin komplett (und setzt sie vor seiner Messung auf 0 zurueck, liest diese Werte
   also nie). Betroffen ist nur das kurze Fenster davor sowie der Fall ohne JS, und beide sind
   mit dem korrigierten Wert deutlich besser als vorher. */
@media (min-width: 768px) {
  #hero .hero-tagline {
    margin-top: -2.5em;
    margin-bottom: 2.5em;
  }
}

/* 2026-07-11, /grill-me-Nachbesserung (5. Runde): Word-by-Word-Blur-Reveal fuer
   "Der Moment, der bleibt" + "...und die Magie beginnt" (SplitText-Technik, siehe
   assets/js/site.js splitIntoWordReveal()). Jedes Wort startet unscharf/unsichtbar/leicht
   verschoben und loest sich zum eigentlichen Text auf, mit steigender Verzoegerung pro Wort.
   display:inline-block noetig, damit filter/transform pro Wort greifen, ohne den Textfluss
   (Zeilenumbruch zwischen Woertern) zu zerstoeren.
   2026-07-11, /grill-me-Nachbesserung (6. Runde): Nutzerfeedback "sehe ich nicht" (Effekt lief
   zu schnell/frueh ab, leicht zu verpassen). Zwei Aenderungen: 1) deutlich langsameres Timing
   (siehe assets/js/site.js, Basis-Offset 0.5s -> 1.2s, Wortabstand 90ms -> 220ms, Dauer pro
   Wort 0.7s -> 1.1s). 2) `animation` liegt jetzt auf `.word-reveal.is-in` statt direkt auf
   `.word-reveal`, damit ein IntersectionObserver die Klasse bei jedem Rein-/Rausscrollen aus
   dem Viewport toggeln kann (Wiederholbarkeit, Nutzerwunsch "per Scroll erneut abspielbar").
   Ohne `.is-in` bleibt das Wort in seinem Ruhezustand (unscharf/unsichtbar), das Entfernen der
   Klasse setzt die Animation dadurch sauber zurueck fuer den naechsten Durchlauf. */
.word-reveal {
  display: inline-block;
  opacity: 0;
  filter: blur(10px);
  transform: translateY(0.25em);
}

/* 2026-07-11, Nachbesserung (9. Runde): Nutzerfeedback "kommt so statisch rein", die vorherige
   Expo-Out-Kurve (cubic-bezier(0.16,1,0.3,1): startet extrem schnell, bremst dann lange aus)
   wirkte hart/mechanisch. Auf eine echte Ease-In-Out-Kurve gewechselt (sanfter Start, sanftes
   Ende), fuehlt sich weicher/organischer an. */
.word-reveal.is-in {
  animation: word-blur-in 1.1s cubic-bezier(0.65, 0, 0.35, 1) both;
}

@keyframes word-blur-in {
  to {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

/* 2026-07-11, Nachbesserung (9. Runde): Fliesstext + CTA-Buttons sollen erst erscheinen, wenn
   der Word-by-Word-Reveal der Tagline fertig ist, nicht gleichzeitig/vorher sichtbar sein.
   2026-08-02, /grill-me-Nachbesserung (damals): Fliesstext ueberlappte bewusst mit dem letzten,
   noch einblendenden Tagline-Wort statt strikt auf dessen Ende zu warten.
   2026-08-02, Nachbesserung: Nutzerfeedback "der Fliesstext kommt direkt wenn der Word-to-Word-
   Effekt beginnt, das sollte erst einfaden, wenn das letzte Wort 'beginnt' erscheint". Root
   Cause: die Basis-Verzoegerung der Tagline-Wortsequenz wurde in einer spaeteren Runde
   (Bugfix "Wort-Animation-Sprung", site.js) von 0.6s auf 2.5s angehoben, dieser Wert hier wurde
   dabei nicht mehr nachgezogen, der Fliesstext startete dadurch laengst, bevor "beginnt"
   ueberhaupt zu sehen war. Jetzt neu berechnet (nicht mehr bewusst ueberlappend, wie vom
   Nutzer explizit gewuenscht): Tagline hat 8 Woerter, baseDelay 2.5s (site.js), 220ms-Schritte,
   1.1s Animationsdauer pro Wort -> "beginnt" (letztes Wort, Index 7) startet bei
   2.5+7*0.22=4.04s, ist fertig eingeblendet bei 4.04+1.1=5.14s. Fliesstext startet exakt dann. */
.hero-delayed-in {
  opacity: 0;
  filter: blur(8px);
  transform: translateY(0.4em);
  animation: word-blur-in 0.9s cubic-bezier(0.65, 0, 0.35, 1) 5.14s both;
}

/* 2026-08-02, Nutzerfeedback: "die Buttons unter dem Fliesstext brauchen auch ein kleines
   Delay, sonst kommen sie direkt mit dem Fliesstext." .cta-row teilte sich bisher exakt
   denselben animation-delay wie der Fliesstext (beide ueber dieselbe .hero-delayed-in-Klasse),
   erschienen dadurch gleichzeitig statt als Kaskade. .cta-row.hero-delayed-in (zwei Klassen)
   hat automatisch hoehere Spezifitaet als .hero-delayed-in allein, ueberschreibt den Delay
   gezielt nur fuer die Buttons, ohne die gemeinsame Basis-Deklaration zu duplizieren. */
.cta-row.hero-delayed-in {
  animation-delay: 5.54s;
}

@media (prefers-reduced-motion: reduce) {
  .hero-delayed-in {
    animation: none;
    opacity: 1;
    filter: none;
    transform: none;
  }
}

/* 2026-08-02: Nutzerwunsch "fuer Mobile etwas kuerzen, nur auf das Wichtigste konzentrieren".
   Zwei Absaetze im Markup (index.html), hier per Breakpoint ein-/ausgeblendet: Desktop/Tablet
   sehen den ausfuehrlichen Text, Mobile die kuerzere Fassung. Reines CSS-Umschalten, kein JS. */
.hero-lede-mobile {
  display: none;
}

@media (max-width: 767px) {
  .hero-lede-desktop {
    display: none;
  }

  .hero-lede-mobile {
    display: block;
    /* 2026-08-02, Nutzerwunsch: Abstand zur Tagline um die Haelfte verkleinern (betraf laut
       Nutzer Desktop/iPad UND Mobile). Auf Mobile gibt es keine JS-Kompensation wie bei den
       groesseren Breakpoints (syncLedeGapToTagline() in site.js ist bewusst nur >=768px
       aktiv, siehe dort), der Abstand kommt hier ausschliesslich aus #hero .wrap { gap:1.4rem
       }. Ein statischer halber Wert reicht auf Mobile aus (kein clamp()-Kurven-Mismatch wie bei
       Tagline/Mieten, beide Elemente skalieren hier moderat). .cta-row ist auf Mobile
       ausgeblendet (ersetzt durch .mobile-bottom-bar, position:fixed), es gibt deshalb keinen
       Grid-Nachbarn, an den die freiwerdende Haelfte weitergereicht werden muesste. */
    /* 2026-08-02, Nachbesserung: Nutzerfeedback "Gap ist immer noch viel zu gross, muss weiter
       runter". Von -0.7rem (halbierter Grid-Gap) auf -1.2rem verschaerft. */
    margin-top: -1.2rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .word-reveal {
    animation: none;
    opacity: 1;
    filter: none;
    transform: none;
  }
}

/* 2026-07-11, /grill-me-Nachbesserung (6. Runde): max-width:42ch entfernt, Nutzerwunsch "Text
   kann so breit werden wie FOTOBOX, damit das rechtsbuendig damit abschliesst, um unten Platz
   zu sparen". Der Absatz ist ein eigenstaendiges Grid-Item in derselben Spalte wie die H1 (die
   durch FOTOBOX praktisch die volle Spaltenbreite einnimmt), nutzt jetzt ebenfalls die volle
   Spaltenbreite (kein px-genauer Abgleich mit FOTOBOX per JS, aber sehr nah dran, da beide
   durch dieselbe .wrap-Spalte begrenzt werden). Weniger Zeilenumbrueche, dadurch spuerbar
   weniger Hoehe am unteren Rand des Hero. */
#hero p {
  color: var(--text-primary);
  font-size: 1.1rem;
}

/* 2026-07-11, Nachbesserung (9. Runde): Nutzerwunsch "Gap erweitern, damit 'So laeuft's ab'
   rechtsbuendig zur Kante wird". justify-content:space-between statt eines fixen, geratenen
   Gap-Werts: schiebt den ersten Button links, den zweiten robust an die rechte Kante der
   Spalte (= rechter Rand von FOTOBOX, da beide dieselbe .wrap-Spaltenbreite nutzen),
   unabhaengig von Viewport-Breite. gap bleibt als Mindestabstand fuer den Fall, dass beide
   Buttons bei sehr schmalen Spalten aneinanderrutschen. */
#hero .cta-row {
  display: flex;
  justify-content: space-between;
  gap: 1.8rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
}

.btn-ghost {
  display: inline-block;
  padding: 16px 36px;
  border-radius: 999px;
  border: 1.5px solid rgba(246, 241, 231, 0.35);
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 600;
  transition: border-color 0.3s var(--ease-glow), color 0.3s var(--ease-glow);
}

.btn-ghost:hover {
  border-color: var(--neon-cyan);
  color: var(--neon-cyan);
}

a.btn-glow {
  text-decoration: none;
}

/* =======================================================
   HERO: SCHWEBENDE GLAS-KARTEN (2026-07-03)
   Inspiriert von der KYMA-Referenz (header.webp): kleine Info-Karten schweben ueber dem
   Hero-Foto statt nur daneben zu stehen. Nur ab Desktop-Breite, auf Mobile wird es sonst
   zu eng neben dem Fliesstext.
   ======================================================= */

.hero-float {
  position: absolute;
  z-index: 3;
  display: none;
  align-items: center;
  gap: 0.8rem;
  padding: 0.9rem 1.2rem;
  /* 2026-08-02: width:max-content statt einer festen Breite, damit die Karte immer exakt so
     breit wie ihr (jetzt nowrap-gesetzter, siehe .hero-float strong/span oben) Inhalt ist,
     max-width bleibt als Sicherheitsobergrenze. */
  width: max-content;
  max-width: 230px;
  animation: hero-float-bob 6s ease-in-out infinite;
  /* 2026-08-02, Nutzerwunsch: "Die Cards koennten auch einen Blur-in-Effekt erhalten, nachdem
     Mieten ausgefahren wurde, gerne alle Cards mit einem leichten Delay, so dass sie
     nacheinander erscheinen." Start-Zustand unscharf/unsichtbar, blendet per .hero-float-in
     (siehe unten) ein, exakt dieselbe Technik wie bei den FOTOBOX-Buchstaben (.hero-h1-letter). */
  opacity: 0;
  filter: blur(14px);
  /* 2026-08-02, Nutzerwunsch: "Beim Hover ueber die Cards muss wie bei 'Jetzt unverbindlich
     anfragen' dieser Effekt rein" (per /grill-me praezisiert: nur der Lichtstreif-Sweep, nicht
     das zusaetzliche Gluehen/Anheben, das ueber .glass-panel:hover technisch schon existiert).
     overflow:hidden noetig, damit der Sweep-Pseudo-Element (siehe .hero-float::before unten)
     sauber an der (durch .glass-panel abgerundeten) Kartenkante abgeschnitten wird, exakt wie
     bei .btn-glow (tokens.css). */
  overflow: hidden;
}

/* 2026-08-02, Nutzerwunsch: identischer "Mirror Sweep" wie bei .btn-glow (tokens.css), 1:1
   uebernommen (gleiche Werte fuer Winkel/Breite/Dauer), nur als eigene Regel hier, da .btn-glow
   selbst nicht direkt wiederverwendet werden kann (Card ist kein Button, hat eigene
   Basis-Klasse .glass-panel). pointer-events:none, damit der Sweep niemals Klicks auf der Card
   (alle bis auf "Touch-Funktion" sind echte Anker-Links) abfaengt. */
.hero-float::before {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(115deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-15deg);
  transition: left 0.6s ease;
  pointer-events: none;
}

.hero-float:hover::before {
  left: 130%;
}

.hero-float strong {
  display: block;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  /* 2026-08-02, Nutzerwunsch: "Ich moechte keinen Zeilenumbruch im Titel und im Subtitel in
     den Cards haben." Zusammen mit width:max-content unten (statt einer festen max-width, die
     laengeren Text sonst umbrechen liesse) bestimmt jetzt der Text selbst die Kartenbreite. */
  white-space: nowrap;
}

.hero-float span:not(.hero-float-icon) {
  display: block;
  font-size: 0.78rem;
  color: var(--text-muted);
  white-space: nowrap;
}

/* 2026-08-02, Nutzerwunsch: Card-Icons von Unicode-Zeichen auf echte SVG-Icons umgestellt
   (index.html), font-size galt fuer Text-Glyphen, jetzt width/height fuer die <svg class="icon">
   darin (.icon selbst setzt 1.5rem als Default, siehe tokens.css, hier gezielt kleiner). */
.hero-float-icon {
  width: 1.3rem;
  height: 1.3rem;
  color: var(--gold-bright);
  flex-shrink: 0;
}

.hero-float-icon .icon {
  width: 100%;
  height: 100%;
}

/* 2026-08-02, Nutzerwunsch: "Bei Momente habe ich ein wunderschoenes rotes Herz, das gefaellt
   mir gut, das haette ich gerne fuer alle anderen Cards auch in dem Style." Jedes Icon bekommt
   jetzt eine eigene, zum Card-Thema passende Akzentfarbe statt der einheitlichen Gold-Farbe
   oben (die als Basiswert nur noch fuer "100% individuell" gilt). Rot bleibt bewusst bei
   "Momente" (das Herz, das dem Nutzer gefiel), die anderen folgen demselben Prinzip mit eigener
   Farbe pro Motiv: Cyan fuer die Beruehrungs-Ripple (Touch-Funktion), Gruen fuer das Haekchen
   (klassische Bestaetigungs-Farbe).
   2026-08-02, Nachbesserung: Nutzerfeedback "das Icon von Der Spiegel gefaellt mir nicht,
   oder es liegt an der Farbe". Violett-Override entfernt (faellt jetzt auf den Gold-Basiswert
   zurueck, passt besser zum Subtitel "Elegantes Design"), UND das Icon selbst ausgetauscht
   (index.html: von #icon-mirror, das an dieser kleinen Groesse eher wie ein Gesicht/Laecheln
   wirkte, auf #icon-standing-mirror, einen schlichten Standspiegel-Umriss ohne Gesichts-
   Details, extra fuer diese Card angelegt statt das an zwei anderen Stellen wiederverwendete
   #icon-mirror selbst zu veraendern). */
.hero-float--slot2 .hero-float-icon {
  color: var(--neon-red);
}

.hero-float--bottom .hero-float-icon {
  color: var(--neon-cyan);
}

.hero-float--slot5 .hero-float-icon {
  color: var(--neon-green);
}

/* 2026-07-11, /grill-me-Nachbesserung (3. Runde): Nutzerwunsch "die Cards die links stehen, da
   muss das Icon rechts sein" (nur die drei echten links-Karten). row-reverse drehte Icon und
   Text-Block optisch um.
   2026-08-02, Nachbesserung: Nutzerwunsch "Die Icons muessen alle links stehen." Die
   row-reverse-Regel wieder entfernt, das Markup hat das Icon ohnehin bereits als erstes Kind
   (siehe index.html), normale flex-direction:row (Basiswert) reicht jetzt fuer alle Karten. */

/* 2026-07-11: von rechts auf links getauscht, Gegenstueck zum Textblock-Tausch (siehe
   #hero .wrap), die Karten schweben jetzt neben dem Spiegel im Foto statt neben der Menschen-
   gruppe rechts.
   2026-07-11, gleicher Tag: um drei Anker-Link-Karten erweitert (Momente/Der Spiegel/Preise),
   "Touch-Funktion" auf Nutzerwunsch "in die Mitte" verschoben, spaeter zwei Karten in eine
   zweite Spalte bei 38% verschoben.
   2026-07-11, /grill-me-Runde: linke Spalte (3 Karten) enger zusammengerueckt und um die
   vertikale Mitte zentriert (32/50/68% statt 8/43/78%, Nutzerfeedback "stehen zu weit
   auseinander"). "Der Spiegel" zieht in die obere rechte Ecke um (dort, wo zu dem Zeitpunkt
   noch die H1 stand, die H1 zieht im selben Zug zurueck in .wrap, siehe weiter unten), jetzt
   rechts-basiert (`right` statt `left`) statt in der 38%-Spalte. "Momente" bleibt in der
   38%-Spalte, wandert aber weiter nach unten.
   2026-07-11, /grill-me-Nachbesserung: die strikte linke Saeule (alle drei bei left:6%) wirkte
   zu starr ("das war vorher alles etwas dynamischer, die muessen nicht vertikal in einer Linie
   stehen"). "Touch-Funktion" bekommt einen deutlich groesseren Rechts-Versatz (18% statt 6%),
   "Jetzt mieten" einen leichten eigenen Versatz (9%), "100% individuell" bleibt der Anker bei
   6%, dadurch entsteht wieder ein unregelmaessiger, organischer Versatz statt einer geraden
   Spalte. "Momente" wandert von 55% auf 64% weiter nach unten.
   2026-07-11, /grill-me-Nachbesserung (2. Runde): "Touch-Funktion" war mit 18% zu weit nach
   rechts gewandert (ueberlappte den Spiegel-Rahmen im Foto), zurueck auf einen massvollen
   Zwischenwert (10%). "Der Spiegel" zieht naeher an die H1 heran (top:4% -> 15%), Nutzerwunsch
   "mit Abstand oberhalb von Premium stehen" statt mit grossem Leerraum ganz oben.
   2026-07-11, /grill-me-Nachbesserung (3. Runde): "Momente" und "Jetzt mieten" tauschen
   komplett die Position (nur die CSS-Werte, die Karten/Klassen selbst bleiben unveraendert).
   "Jetzt mieten" landet dadurch in der vorherigen 38%-Spalte von "Momente", wandert von dort
   auf Nutzerwunsch ("rechte Card etwas weiter nach links") zusaetzlich auf 30%.
   2026-07-11, /grill-me-Nachbesserung (4. Runde): "Jetzt mieten" auf Nutzerwunsch "leicht nach
   rechts" von 30% auf 34%. */
.hero-float--slot1 {
  top: 32%;
  left: 6%;
}

.hero-float--slot2 {
  top: 68%;
  left: 9%;
  animation-delay: -1.2s;
}

.hero-float--bottom {
  top: 48%;
  left: 10%;
  animation-delay: -3s;
}

/* 2026-08-02, Nutzerfeedback: "Der Spiegel muss weiter nach links, Richtwert: fast zentriert
   minus 15%". Von right:6% (nah an der rechten Kante) auf right:35% verschoben (rechnerisch
   "zentriert" waere right:50%, minus 15 ergibt 35).
   2026-08-02, Nachbesserung: "er koennte noch einmal um ca. 25% weiter nach links", von
   right:35% auf right:60% (35+25) angehoben. Weiterhin als Richtwert verstanden. */
.hero-float--slot4 {
  top: 15%;
  right: 60%;
  animation-delay: -4.4s;
}

.hero-float--slot5 {
  top: 64%;
  left: 34%;
  animation-delay: -5.4s;
}

/* 2026-07-11, /grill-me-Nachbesserung (4. Runde): seit der Textspalte auf linksbuendig
   umgestellt wurde (siehe #hero .wrap weiter oben), rutscht der Fliesstext bei schmaleren
   Fensterbreiten (Nutzer-Vermutung: "iPad-Breite") unter "Jetzt mieten" bei left:34%. Ab
   980px sind die Karten sichtbar, aber der Platz zwischen linker Kartengruppe und Textspalte
   wird erst ab ca. 1300px wieder breit genug, um die Karte kollisionsfrei bei 34% schweben zu
   lassen (per Screenshot bei 1024/1180/1280px verifiziert: ueberall Text-Ueberlappung).
   Unterhalb von 1300px reiht sich "Jetzt mieten" stattdessen der linken Kartengruppe unter
   "Momente" an (Nutzervorschlag: "Card sich links zur anderen Gruppe einreihen lassen").
   2026-07-11, /grill-me-Nachbesserung (6. Runde): seit der Absatz sein max-width:42ch verloren
   hat (siehe #hero p weiter oben, "Text so breit wie FOTOBOX"), reicht die Kollision jetzt bis
   ca. 1550px hinauf (per Bounding-Box-Vergleich bei 1440/1600/1728/1920px vermessen: 1440px
   echter Ueberlapp, ab 1600px sauber). Obergrenze von 1299.98px auf 1599.98px angehoben. */
@media (min-width: 980px) and (max-width: 1599.98px) {
  .hero-float--slot5 {
    top: 80%;
    left: 7%;
  }
}

/* 2026-07-06: "Touch-Funktion"-Karte startet per Klick die Photobox-Simulation (siehe
   assets/js/site.js), Attribute (role/tabindex) werden dort zur Laufzeit ergaenzt, nur wenn
   !reducedMotion. cursor/focus-Regeln sind unabhaengig davon harmlos gesetzt. */
.hero-float--bottom {
  cursor: pointer;
}

/* 2026-07-11: Fokus-Ring fuer alle interaktiven Karten (Touch-Funktion + die drei neuen
   Anker-Links), nicht nur fuer --bottom.
   2026-07-11, /grill-me-Nachbesserung (7. Runde): --slot1 ("100% individuell") ist jetzt auch
   ein Anker-Link (siehe index.html), ergaenzt. */
.hero-float--bottom:focus-visible,
.hero-float--slot1:focus-visible,
.hero-float--slot2:focus-visible,
.hero-float--slot4:focus-visible,
.hero-float--slot5:focus-visible {
  outline: 2px solid var(--neon-cyan);
  outline-offset: 4px;
}

@keyframes hero-float-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-10px); }
}

/* 2026-08-02, Nutzerwunsch: "Die Cards koennten auch einen Blur-in-Effekt erhalten, nachdem
   Mieten ausgefahren wurde, gerne alle Cards mit einem leichten Delay, so dass sie
   nacheinander erscheinen." .hero-float-in wird vom selben IntersectionObserver getoggelt, der
   bereits .hero-slide-in (Jetzt/Mieten) und .hero-letter-in (FOTOBOX-Buchstaben) steuert (siehe
   site.js), also genauso wiederholbar bei jedem Rein-/Raus-Scrollen aus dem Hero. "Nachdem
   Mieten ausgefahren wurde" wird rein per CSS-Delay geloest, kein zusaetzlicher JS-Trigger
   noetig: Mietens Slide-in braucht 1.8s Delay + 0.7s Dauer = 2.5s bis zur Ruheposition (siehe
   .hero-h1-word--3.hero-slide-in weiter oben), alle Karten-Delays starten deshalb erst ab
   2.5s, plus 0.15s Staffelung pro Karte fuer den "nacheinander"-Effekt. Beide Animationen
   (Blur-in UND die bestehende Schwebe-Animation) muessen hier als Langschreibweise nebeneinander
   stehen, ein zweites "animation"-Kurzschreibweise-Statement wuerde die erste komplett
   ueberschreiben statt sie zu ergaenzen. */
.hero-float.hero-float-in {
  animation-name: hero-float-blur-in, hero-float-bob;
  animation-duration: 0.7s, 6s;
  animation-timing-function: ease-out, ease-in-out;
  animation-iteration-count: 1, infinite;
  animation-fill-mode: both, none;
}

.hero-float--slot1.hero-float-in {
  animation-delay: 2.5s, 0s;
}

.hero-float--bottom.hero-float-in {
  animation-delay: 2.65s, -3s;
}

.hero-float--slot4.hero-float-in {
  animation-delay: 2.8s, -4.4s;
}

.hero-float--slot2.hero-float-in {
  animation-delay: 2.95s, -1.2s;
}

.hero-float--slot5.hero-float-in {
  animation-delay: 3.1s, -5.4s;
}

@keyframes hero-float-blur-in {
  from {
    opacity: 0;
    filter: blur(14px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-float {
    opacity: 1;
    filter: none;
    animation: none;
  }
}

@media (min-width: 980px) {
  .hero-float {
    display: flex;
  }
}

/* 2026-08-02, Nutzerwunsch: "Die Cards vermisse ich in der iPad-Version sowie in der
   Mobile-Version, im oberen Drittel haben wir massiv Platz dafuer, koennte man die da einfach
   schwebend verteilen. Kannst Du das einmal probieren." Experimenteller erster Wurf (Nutzer
   selbst: "einmal probieren"), noch keine ueber viele Runden fein-kalibrierte Position wie bei
   der Desktop-Version oben. Eigene, schmalere Positionierung im oberen Drittel des Hero-Fotos,
   bewusst oberhalb/neben der grossen FOTOBOX-Headline platziert, damit sich beide Ebenen nicht
   in die Quere kommen. Als eigenstaendiger Block NACH der `@media (min-width:980px)`-Regel
   platziert (nicht davor): `.hero-float--slot1` etc. haben dieselbe Selektor-Spezifitaet wie
   `.hero-float` selbst, bei gleicher Spezifitaet gewinnt die spaeter im Quelltext stehende
   Regel unabhaengig davon, welche Media Query zutrifft, exakt dieselbe Spezifitaets-Falle wie
   mehrfach zuvor in diesem Projekt dokumentiert. */
/* 2026-08-02, Nachbesserung: Nutzerwunsch "versuche mal, in der iPad- und Mobile-Version 3
   Cards in eine Reihe zu bringen, aber gerne dynamische Hoehen, so dass sie nicht auf einer
   Linie liegen, aber 3 Stueck mehr oder weniger in Reihe sind." Erste Fassung zeigte nur drei
   Karten. 2026-08-02, weitere Nachbesserung: "Es muessen ALLE Cards visuell gezeigt werden,
   also bitte erweitern. Ich wollte nur, dass Du immer 3 Stueck nebeneinander zeigst. Die
   weiteren muessen dann aehnlich wie in einer Masonry-Galerie angezeigt werden." Jetzt alle
   fuenf Karten: die ersten drei (100% individuell/Touch-Funktion/Der Spiegel) bilden weiterhin
   die obere Reihe, "Momente" und "Jetzt mieten" folgen darunter als zweite, ebenfalls
   versetzte "Kachelreihe" (kein starres Raster, wie eine Masonry-Galerie mit ungleichen
   Kachel-Hoehen). Seit `.hero-float strong/span` jetzt `white-space:nowrap` haben (Nutzerwunsch
   "kein Zeilenumbruch im Titel/Subtitel") und `.hero-float` selbst `width:max-content` nutzt
   (siehe Basis-Regeln oben), bestimmt der jeweilige Text die Kartenbreite selbst, keine feste
   max-width mehr noetig/gesetzt in diesem Block. */
/* 2026-08-02, weitere Nachbesserung: Nutzerfeedback "das Masonry sieht besser aus, aber auch
   hier gilt: minimum 3 Stk. in einer Reihe" + "gib den Cards individuelle, leicht
   unterschiedliche Aussenabstaende, so dass sie nicht alle exakt vertikal und horizontal auf
   einer Linie schweben." Kombiniert jetzt beide Vorgaben: die obersten drei Karten (100%
   individuell/Touch-Funktion/Der Spiegel) bilden wieder eine Reihe (links/mitte/rechts), die
   restlichen zwei (Momente/Jetzt mieten) haengen als Masonry-Fortsetzung darunter. Kein Wert
   (top ODER left/right) wird zwischen zwei Karten exakt wiederverwendet, jede Karte bekommt
   einen leicht eigenen Versatz, damit nichts optisch auf einer gemeinsamen Linie schwebt. */
@media (min-width: 768px) and (max-width: 1024px) {
  /* 2026-08-02, Bugfix: dieselbe JS-gestuetzte Absicherung wie im Mobile-Block weiter unten
     (siehe dortiger Kommentar fuer die volle Begruendung: Safaris Toolbar macht CSS-min-height-
     Schwellwerte auf echten Geraeten unzuverlaessig). `visibility:hidden` als Startzustand,
     `syncCardVisibilityToHeadline()` (site.js) schaltet nach Kollisionspruefung sichtbar. */
  .hero-float--slot4,
  .hero-float--slot1,
  .hero-float--bottom,
  .hero-float--slot2,
  .hero-float--slot5 {
    display: flex;
    visibility: hidden;
    left: auto;
    right: auto;
  }

  .hero-float--slot1 {
    top: 5%;
    left: 2%;
  }

  .hero-float--bottom {
    top: 9%;
    left: 38%;
  }

  .hero-float--slot4 {
    top: 2%;
    right: 4%;
  }

  .hero-float--slot2 {
    top: 20%;
    left: 6%;
  }

  /* 2026-08-02, Bugfix (bei der Verifikation entdeckt): "Jetzt mieten" stand zunaechst rechts
     (right:4%) und ueberlappte dort real die "JETZT"-Buchstaben (per Range()-Textmessung
     verifiziert, nicht nur die DOM-Box: JETZT/FOTOBOX/MIETEN sind alle rechtsbuendiger Text in
     einer gemeinsam breiten, auf FOTOBOX' Breite basierenden Box, "JETZT" sitzt dadurch genau
     im rechten oberen Bereich).
     2026-08-02, Nachbesserung: Nutzerfeedback "die letzte Card stellst Du einzeln in eine neue
     Reihe, da ist eigentlich genug Platz nach rechts, um sie danebenzustellen". Stand vorher
     direkt UNTER "Momente" (beide bei aehnlichem left-Wert), jetzt stattdessen NEBEN
     "Touch-Funktion" positioniert (mittlere Spalte, deutlich rechts von "Momente", aber noch
     klar links von der JETZT-Gefahrenzone). */
  .hero-float--slot5 {
    top: 23%;
    left: 40%;
  }
}

/* 2026-08-02, Bugfix: Nutzerfeedback "lokal sehe ich die Cards, auf meinem echten iPhone 13
   aber nicht". Root Cause: die vorherige Absicherung nutzte eine geratene CSS
   `min-height`-Media-Query (siehe Git-Historie), kalibriert per Puppeteer/Chrome mit fest
   eingestellten Viewport-Groessen. Chrome-Headless-Tests haben aber KEINE Adressleiste/Toolbar,
   Safari auf echten iPhones dagegen schon: die Toolbar verkleinert den fuer `min-height`
   massgeblichen sichtbaren Viewport dynamisch, oft deutlich unter die "nominelle"
   Geraete-Hoehe. Ein am Desktop kalibrierter Schwellwert (zuletzt 840px) kann dadurch auf
   einem echten iPhone (z. B. 13, nominell 844px hoch) NIE zutreffen, sobald die Toolbar
   sichtbar ist, also praktisch immer beim normalen Browsen. Fix: statt eines geratenen
   CSS-Schwellwerts misst JS (`syncCardVisibilityToHeadline()`, site.js) zur Laufzeit die
   TATSAECHLICH verfuegbare Hoehe, robust unabhaengig von Browser-Chrome-Eigenheiten (dasselbe
   "berechnen statt raten"-Prinzip wie bei `syncTaglineGapToMieten()`, site.js). Karten starten
   deshalb hier `visibility:hidden`, JS schaltet sie erst nach erfolgreicher Kollisionspruefung
   sichtbar. */
@media (max-width: 767px) {
  /* 2026-08-02, Bugfix (direkt beim ersten Test aufgefallen): die Basis-Regeln weiter oben
     (unconditional, fuer Desktop kalibriert) setzen auf slot1/--bottom/--slot2 bereits ein
     eigenes "left", meine neuen Regeln hier setzten teils nur "right" dazu, OHNE das geerbte
     "left" aufzuheben. Bei einem absolut positionierten Element ohne explizite width spannt der
     Browser die Box dann zwischen BEIDEN Kanten auf, das liess Karten zu weit ausufern. "left:
     auto"/"right: auto" hier durchgehend gesetzt, unabhaengig davon, welche Kante die jeweilige
     Karte tatsaechlich braucht. Keine max-width mehr (siehe Nachbesserung "alle Karten zeigen"
     oben, width:max-content + white-space:nowrap auf den Basis-Regeln bestimmen die Breite),
     nur noch kompaktere Schrift/Padding fuer Mobile. */
  .hero-float--slot4,
  .hero-float--slot1,
  .hero-float--bottom,
  .hero-float--slot2,
  .hero-float--slot5 {
    display: flex;
    visibility: hidden;
    padding: 0.55rem 0.6rem;
    gap: 0.4rem;
    left: auto;
    right: auto;
  }

  .hero-float--slot4 strong,
  .hero-float--slot1 strong,
  .hero-float--bottom strong,
  .hero-float--slot2 strong,
  .hero-float--slot5 strong {
    font-size: 0.72rem;
  }

  /* 2026-08-02, Nutzerwunsch: "In der Mobile-Version die Cards ohne Subtitel, um Platz zu
     sparen." Nur der Untertitel (z. B. "Kein Standard 08/15 Design") entfaellt, der Titel
     (z. B. "100% individuell") bleibt als alleinstehendes Label. Betrifft ausschliesslich
     Mobile, iPad/Desktop zeigen weiterhin beide Zeilen. */
  .hero-float--slot4 span:not(.hero-float-icon),
  .hero-float--slot1 span:not(.hero-float-icon),
  .hero-float--bottom span:not(.hero-float-icon),
  .hero-float--slot2 span:not(.hero-float-icon),
  .hero-float--slot5 span:not(.hero-float-icon) {
    display: none;
  }

  /* 2026-08-02, Bugfix (bei der Verifikation entdeckt): font-size wirkte hier nicht mehr, seit
     die Card-Icons von Text-Glyphen auf echte SVG-Icons umgestellt wurden (.hero-float-icon
     nutzt seitdem width/height statt font-size fuer die Groesse, siehe Basis-Regel weiter
     oben). Mobile-Verkleinerung war dadurch ein wirkungsloses totes Statement. */
  .hero-float--slot4 .hero-float-icon,
  .hero-float--slot1 .hero-float-icon,
  .hero-float--bottom .hero-float-icon,
  .hero-float--slot2 .hero-float-icon,
  .hero-float--slot5 .hero-float-icon {
    width: 1.05rem;
    height: 1.05rem;
  }

  /* 2026-08-02, weitere Nachbesserung: siehe iPad-Block weiter oben fuer die volle Begruendung.
     Wieder eine Dreier-Reihe oben (links/mitte/rechts), "Momente"/"Jetzt mieten" haengen als
     Masonry-Fortsetzung darunter, jede Karte mit einem leicht eigenen top-/left-/right-Versatz,
     kein Wert zwischen zwei Karten exakt gleich. */
  .hero-float--slot1 {
    top: 4%;
    left: 2%;
  }

  /* 2026-08-02, Bugfix (bei der Verifikation entdeckt): links:37% kollidierte real mit
     "100% individuell" (per Bounding-Box verifiziert: die Karte ist durch den ergaenzten
     Subtitel "Kein Standard 08/15 Design" breiter geworden als bei der letzten Kalibrierung,
     width:max-content laesst sie ueber 37% hinausragen). Weiter nach rechts + etwas tiefer. */
  .hero-float--bottom {
    top: 11%;
    left: 47%;
  }

  .hero-float--slot4 {
    top: 1%;
    right: 3%;
  }

  .hero-float--slot2 {
    top: 19%;
    left: 5%;
  }

  /* 2026-08-02, Bugfix + Nachbesserung: siehe iPad-Block weiter oben fuer die volle
     Begruendung. Nicht mehr allein unter "Touch-Funktion" (mittlere Spalte), noch klar links
     von der JETZT-Gefahrenzone. */
  .hero-float--slot5 {
    top: 17%;
    left: 44%;
  }

  /* 2026-08-03, Nutzerfeedback: "Die Anordnung ist nicht schoen, zu unuebersichtlich, Der
     Spiegel klebt an der Navigation. Gleichmaessiger mit etwas Harmonie, Cards nur minimal
     unterschiedlich, auch die Bewegung nur minimal." Root Cause fuer beide Symptome:
     (1) top-Werte der oberen Dreier-Reihe streuten bisher stark (1%/4%/11%, ein 10-Punkte-
     Spektrum innerhalb einer "Reihe"), dadurch wirkte sie selbst schon uneinheitlich statt wie
     eine Reihe. (2) "Der Spiegel" (slot4) stand mit top:1% direkt unter dem Header. Jetzt
     enger beieinander (6-9%, siehe unten), die zweite Reihe (Momente/Jetzt mieten) ruecken im
     selben Verhaeltnis nach, "leicht versetzt" bleibt erhalten, aber deutlich gedaempft statt
     wild verteilt.
     2026-08-03, Nachbesserung: Nutzerfeedback "fast perfekt, der vertikale Abstand/
     Zeilenabstand zwischen den beiden Reihen ist mir zu gross, Momente und Jetzt mieten sind zu
     tief." Zweite Reihe von 25/27% auf 15/17% herangerueckt, die 5 Karten wirken dadurch als
     ein zusammenhaengender Block statt zwei weit getrennte Gruppen. */
  .hero-float--slot1 {
    top: 7%;
  }

  .hero-float--bottom {
    top: 6%;
  }

  .hero-float--slot4 {
    top: 9%;
  }

  .hero-float--slot2 {
    top: 15%;
  }

  /* 2026-08-03, Nutzerfeedback "auch die Bewegung nur minimal": dieselbe Schwebe-Animation wie
     am Desktop (hero-float-bob, +-10px) wirkte auf dem engeren Mobile-Layout unruhiger, weil die
     Karten dort naeher beieinander stehen. Eigene, deutlich kleinere Variante nur fuer Mobile,
     Desktop (bereits vom Nutzer abgenommen) bleibt unveraendert. animation-name (Langschreib-
     weise) ueberschreibt hier gezielt nur die zweite der beiden Animationen (siehe
     .hero-float.hero-float-in weiter oben: Blur-in + Schwebe-Animation), animation-delay pro
     Karte bleibt von der dortigen, spezifischeren Regel unberuehrt. */
  .hero-float.hero-float-in {
    animation-name: hero-float-blur-in, hero-float-bob-mobile;
  }
}

@keyframes hero-float-bob-mobile {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}

/* =======================================================
   VIDEO-SECTION (2026-08-03)
   Nutzerwunsch: "Die 2. Section soll ein Video werden", per Bunny Stream eingebunden (iframe,
   Library 718542), moeglichst ohne sichtbare Player-Oberflaeche (autoplay/loop/muted per
   URL-Parameter, siehe index.html). Full-Bleed-Technik 1:1 von .galerie-bg uebernommen
   (position:relative; left:50%; width:100vw; margin-left:-50vw), damit das Video randlos die
   volle Fensterbreite nutzt. aspect-ratio:16/9 entspricht dem echten Seitenverhaeltnis des
   Videos, dadurch wird nichts beschnitten oder verzerrt ("volle Breite und Hoehe vom Video, so
   dass alles gesehen werden kann"). */
/* 2026-08-03, Nutzerwunsch "kein Gap zwischen Section 1 und 2": die globale section-Regel
   (padding: clamp(3.5rem,7vw,7rem) 0, siehe oben) legte vertikalen Abstand ueber/unter das
   Video, bevor der eigentliche Full-Bleed-Frame ueberhaupt beginnt. Hier auf 0 gesetzt, das
   Video sitzt dadurch direkt am Hero an. */
#video {
  padding: 0;
  background: var(--bg-void);
}

.video-frame {
  position: relative;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.video-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* object-fit:contain statt cover: der Container hat exakt dasselbe aspect-ratio wie das
     echte Video (16:9), dadurch faellt in der Praxis kein sichtbarer Rand an, contain ist
     trotzdem die sicherere Wahl, falls das Video minimal von 16:9 abweicht (Nutzerwunsch
     "volle Breite und Hoehe vom Video, so dass alles gesehen werden kann", also nichts
     beschneiden statt wie bei cover ggf. Bildraender abzuschneiden). */
  object-fit: contain;
  display: block;
}

/* =======================================================
   USP ANKER
   ======================================================= */

/* 2026-08-03, Nutzerwunsch: Hintergrundfoto fuer die USP-Section (Nutzer-Upload "Shell.png",
   Techno-Party-Fotobox-Szene an einer beleuchteten Shell-Tankstelle bei Nacht, siehe
   assets/img/REGISTRY.md). Bewusste Ausnahme von der "kein lokaler Section-Hintergrund"-Regel
   in DESIGN_SYSTEM.md, explizit vom Nutzer angefragt. Kein zusaetzlicher Dunkel-Overlay noetig,
   das Zitat sitzt bereits in einem .glass-panel (dunkler, verschwommener Hintergrund), das
   liefert genug Kontrast fuer sich allein. */
/* 2026-08-11: Nutzerwunsch "mache den VH bitte einmal auf 100". Die Section hatte bisher gar
   keine Hoehenvorgabe, ihre Hoehe ergab sich rein aus Inhalt plus Section-Padding (gemessen
   475px = 59.8vh bei 794px Fensterhoehe).
   min-height statt height: bei sehr flachen Fenstern oder sehr grosser Systemschrift darf der
   Textblock die Section weiterhin aufziehen, statt aus einer starren Box herauszulaufen.
   Die Flex-Zentrierung ist kein Beiwerk, sondern noetig: ohne sie klebte der Textblock nach dem
   Vergroessern oben am Section-Padding, und der Rest waere leerer Hintergrund. .wrap bringt seine
   eigene Zentrierung per margin-inline: auto mit, align-items uebernimmt die vertikale.
   Bewusst volle 100vh, nicht calc(100vh - var(--header-h)) wie beim Hero: der Header ist sticky
   und schwebt ueber dem Inhalt, beim Hero ist der Abzug noetig, weil dessen Inhalt direkt unter
   dem Header beginnt. Hier steht der Text mittig, der Header kann also gar nichts verdecken. */
#usp {
  position: relative;
  background: url("../img/usp-shell-bg.webp") center / cover no-repeat;
  min-height: 100vh;
  display: flex;
  align-items: center;
}

/* 2026-08-11: Nutzerwunsch "der Textblock nimmt zentral zu viel Platz ein, cool waere es, wenn
   es vielleicht nicht ganz so breit waere und etwas weiter rechts sitzen wuerde". Zwei
   Aenderungen in einer Regel: schmaler (34rem statt 52rem) und aus der Mitte nach rechts.
   Technik wie im Hero (#hero .wrap): margin-inline mit zwei Werten, links `auto` schluckt den
   gesamten uebrigen Platz und schiebt den Block dadurch nach rechts, rechts steht ein fester,
   mitwachsender Aussenabstand. Der Wert deckelt bei 8rem, damit der Block auf sehr breiten
   Monitoren nicht in der rechten Ecke klebt.
   Inhaltlich passt die Richtung zum Hintergrundfoto: Spiegel und Paar, also das eigentliche
   Motiv, stehen links im Bild und werden vom zentrierten Block bisher verdeckt. Rechts liegt die
   Tanzflaeche, dort stoert der Text nicht. Gleiche Ueberlegung wie beim Hero (Abschnitt 6l). */
/* 2026-08-12: Nutzerwunsch "das kann noch deutlich schmaler gemacht werden, dafuer etwas mehr in
   der Hoehe". max-width von 34rem auf 25rem (544px auf 400px). Die groessere Hoehe entsteht dabei
   von selbst: derselbe Text in einer schmaleren Spalte braucht mehr Zeilen. Zusaetzlich ist das
   Innenpolster jetzt getrennt gesetzt (mehr oben/unten, weniger links/rechts, siehe
   #usp blockquote), sonst haetten die unveraenderten seitlichen 3rem von der schmaleren Box
   spuerbar mehr weggenommen und die Zeilen unnoetig kurz gemacht. */
#usp .wrap {
  max-width: 25rem;
  margin-inline: auto clamp(1.5rem, 8vw, 8rem);
}

/* 2026-08-11: Nutzerfeedback "die Schriftart ist mir zu fett, zu aufdringlich. Das sieht aus wie
   eine Ueberschrift. Aber es ist ja nur Text!" Gemessen war es Outfit in 25.6px mit Gewicht 700,
   also exakt die Kombination, die sonst Logo und Buttons tragen (--font-display ist bewusst die
   Display-Schrift, siehe tokens.css), dazu eine Groesse zwischen H2 und Fliesstext. Der Absatz
   war damit typografisch als Ueberschrift ausgezeichnet, obwohl er inhaltlich ein Fliesstext-
   Statement ist.
   Fix: --font-body (Montserrat) wie aller andere Fliesstext auf der Seite, Gewicht 400 statt 700,
   Groesse spuerbar zurueckgenommen (Obergrenze 1.25rem statt 1.6rem). Die Aussage traegt sich
   jetzt ueber Zentrierung, Zeilenabstand und die Glasflaeche statt ueber Fettung. Zentrierung und
   Glass-Panel bleiben unveraendert, es soll weiterhin als herausgehobenes Statement lesbar sein,
   nur eben als Satz und nicht als Titel. */
#usp blockquote {
  margin: 0;
  /* 2026-08-12: getrennte Werte statt eines einzigen Rundum-Polsters. Oben und unten mehr
     (unterstuetzt den Wunsch nach mehr Hoehe), links und rechts weniger, damit die jetzt
     deutlich schmalere Box (siehe #usp .wrap) nicht zusaetzlich noch seitlich beschnitten wird
     und die Zeilen nicht zu kurz werden. */
  padding: clamp(2.2rem, 4vw, 3.4rem) clamp(1.4rem, 2.6vw, 2.2rem);
  text-align: center;
  font-family: var(--font-body);
  font-size: clamp(1.02rem, 1.8vw, 1.25rem);
  font-weight: 400;
  line-height: 1.75;
  animation: float-drift-soft 9s ease-in-out infinite;
  /* 2026-08-11: Nutzerwunsch "kannst Du den Blur-Effekt etwas reduzieren?". Bewusst NUR hier
     ueberschrieben und nicht im Token: .glass-panel (tokens.css, blur(16px) saturate(130%))
     traegt auch die Hero-Karten, die Vergleichs-Boxen und weitere Flaechen, eine Aenderung dort
     haette die ganze Seite umgestellt. Auf 7px reduziert, das Foto (Tanzflaeche, Neonlicht)
     bleibt dadurch als Motiv erkennbar statt zu einer Farbflaeche zu verschwimmen.
     Die Grundtoenung der Flaeche (rgba(28, 23, 48, 0.45)) bleibt bewusst unveraendert, sie traegt
     den Textkontrast. Sollte der Text auf dem unruhigen Bildbereich zu schwer lesbar werden, ist
     die Toenung die richtige Stellschraube, nicht der Blur. */
  backdrop-filter: blur(7px) saturate(125%);
  -webkit-backdrop-filter: blur(7px) saturate(125%);
}

/* 2026-08-11: Nutzerwunsch "diesen gerne schwebend haben, wie die Cards in der HERO section. Nur
   leicht, minimal." Bewusst eigene Keyframes statt hero-float-bob wiederzuverwenden: die
   Hero-Karten schweben mit +-10px, das waere fuer eine so grosse Flaeche zu viel Bewegung
   (dieselbe Erfahrung wie bei den Mobile-Karten, siehe hero-float-bob-mobile).
   Nebenwirkung, bewusst in Kauf genommen: .glass-panel:hover hebt normalerweise um 4px an
   (tokens.css), diese transform-Aenderung verliert gegen die laufende Animation. Bei den
   Hero-Karten ist das seit jeher genauso, der Hover bleibt ueber Rahmenfarbe und Glow sichtbar.
   2026-08-11, Nachbesserung: Nutzerwunsch "das kann auch sowohl vertikal wie auch horizontal
   schweben". Statt einer reinen Auf-Ab-Bewegung laeuft der Block jetzt eine flache Ellipse:
   rechts-hoch, oben, links-hoch, zurueck. Vier Zwischenschritte statt zwei, weil eine Ellipse
   mindestens die vier Scheitelpunkte braucht; mit nur 0/50/100 gaebe es eine gerade Diagonale
   hin und zurueck, was mechanisch statt schwebend wirkt.
   Amplituden bewusst klein und ungleich (horizontal +-5px, vertikal 0 bis -6px): gleich grosse
   Werte ergaeben einen exakten Kreis, der als bewusste Rotation wahrgenommen wird. Die flachere
   Ellipse liest sich als zufaelliges Treiben. Zyklus von 7s auf 9s verlaengert, da der
   zurueckgelegte Weg jetzt laenger ist und die Bewegung sonst schneller wirken wuerde.
   2026-08-11, umbenannt von usp-float-bob zu float-drift-soft: die Vorteile-Karten (#vorteile)
   nutzen dieselbe Bewegung, ein Name mit "usp" darin waere dort irrefuehrend gewesen. Die
   Keyframes definieren nur die Bahn, Tempo und Versatz setzt jede Verwendung selbst
   (USP-Block 9s ohne Versatz, Vorteile-Karten 11s mit 1.1s Versatz pro Karte). */
@keyframes float-drift-soft {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(5px, -3px); }
  50%  { transform: translate(0, -6px); }
  75%  { transform: translate(-5px, -3px); }
  100% { transform: translate(0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  #usp blockquote {
    animation: none;
  }
}

/* =======================================================
   VERTRAUENS-LEISTE (Location-Typen, 2026-07-03)
   Bewusst keine erfundenen Location-/Partner-Namen oder -Logos, nur ehrliche
   Location-Typ-Icons (siehe ROADMAP.md).
   ======================================================= */

#vertrauen {
  padding: clamp(2rem, 4vw, 3.2rem) 0;
}

#vertrauen .wrap {
  text-align: center;
}

.vertrauen-label {
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 1.6rem;
}

.vertrauen-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2.6rem;
}

.vertrauen-row li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.vertrauen-row .icon {
  width: 1.7rem;
  height: 1.7rem;
  color: var(--gold);
  transition: color 0.3s var(--ease-glow);
}

.vertrauen-row li:hover .icon {
  color: var(--neon-cyan);
}

/* =======================================================
   VORTEILE (kurze Bulletpoints)
   ======================================================= */

/* 2026-08-11: Nutzerfeedback "kannst Du Dir auch noch einmal das Design anschauen, irgendwie
   gefaellt mir das nicht. Eventuell brauchen wir hierfuer auch wieder ein Hintergrundbild."
   Gewaehlt: photobooth-gold-backdrop.webp, eine goldene Pailletten-Wand, also eine echte
   Fotobox-Kulisse. Sie lag bereits im Projekt und war als einziges Bild noch NIRGENDS eingebunden
   (per Verwendungszaehlung ueber index.html und site.css geprueft), es kommt also kein neues
   Asset dazu.
   Die Abdunklung ist bewusst kraeftig (82% bis 90% Schwarz): unabgedunkelt ist das Bild eine
   flaechige, sehr helle Goldwand, auf der weder weisser Text noch die Glaskarten lesbar waeren.
   So bleibt nur das Funkeln als Textur, und die Section bleibt im dunklen Grundton der Seite.
   Der Verlauf laeuft von oben nach unten leicht dunkler, damit der Uebergang zur folgenden
   Section nicht als Kante sichtbar wird.
   Abdunklung als ::before statt als zweiter background-layer, weil sie sonst mit
   `background-size: cover` mitskaliert waere statt die Section exakt abzudecken. */
#vorteile {
  position: relative;
  background: url("../img/photobooth-gold-backdrop.webp") center / cover no-repeat;
}

#vorteile::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(8, 7, 12, 0.82) 0%, rgba(8, 7, 12, 0.9) 100%);
  pointer-events: none;
}

#vorteile .wrap {
  position: relative;
  z-index: 1;
}

/* Basis: eine Spalte. Bewusst kein `repeat(auto-fit, minmax(...))` mehr: auto-fit entscheidet die
   Spaltenzahl allein nach verfuegbarem Platz und weiss nichts davon, dass es FUENF Karten sind.
   Genau daher kam das gemeldete Problem, denn bei drei Spalten bleibt eine Zeile mit nur zwei
   Karten uebrig, die dann links buendig steht und rechts frei laesst. Feste Stufen statt auto-fit
   erlauben es, fuer jede Stufe eine Aufteilung zu waehlen, die restlos aufgeht. */
#vorteile ul {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Zwei Spalten: 5 Karten gehen nicht glatt auf, deshalb belegt die fuenfte beide Spalten und
   schliesst dadurch ebenfalls auf beiden Seiten buendig ab. */
@media (min-width: 620px) {
  #vorteile ul {
    grid-template-columns: repeat(2, 1fr);
  }

  #vorteile li:nth-child(5) {
    grid-column: 1 / -1;
  }
}

/* 2026-08-11: Nutzerwunsch "die Cards muessen irgendwie so dargestellt werden, dass sie entweder
   in eine Zeile passen, oder die Aufteilung muss sich aendern, so dass diese links und rechts
   buendig abschliessen."
   Ausgangslage: fuenf Karten in `repeat(auto-fit, minmax(220px, 1fr))`. Bei 1180px Inhaltsbreite
   braeuchten fuenf Spalten 5 x 220px + 4 x 1.4rem Abstand = 1189.6px, also 9.6px mehr als
   vorhanden. Die fuenfte Karte rutschte dadurch in eine zweite Zeile und stand dort allein und
   linksbuendig, das war die unschoene Aufteilung.
   Gewaehlt wurde die zweite Variante (3 + 2 statt alles in einer Zeile): fuenf Spalten haetten
   bei 1180px nur ca. 212px pro Karte ergeben, und die laengsten Kartentexte (der QR-Code-Text hat
   107 Zeichen) waeren darin zu schmalen, sehr hohen Saeulen geworden.
   Umgesetzt ueber ein SECHS-Spalten-Raster: die ersten drei Karten belegen je 2 Spalten (3 x 2 =
   6), die letzten beiden je 3 (2 x 3 = 6). Beide Zeilen fuellen das Raster damit exakt aus und
   schliessen links wie rechts buendig ab. Sechs Spalten sind das kleinste gemeinsame Vielfache,
   das sowohl eine Dreier- als auch eine Zweierteilung ohne Rest erlaubt. */
@media (min-width: 900px) {
  #vorteile ul {
    grid-template-columns: repeat(6, 1fr);
  }

  #vorteile li {
    grid-column: span 2;
  }

  /* Muss NACH der 620px-Regel stehen: dort belegt die fuenfte Karte noch die volle Breite
     (1 / -1). Beide Selektoren haben dieselbe Spezifitaet, den Gleichstand entscheidet die
     Reihenfolge im Quelltext, nicht die Media Query. */
  #vorteile li:nth-child(4),
  #vorteile li:nth-child(5) {
    grid-column: span 3;
  }
}

/* 2026-08-11: Nutzerwunsch "die Cards dann auch wieder leicht glasig und schwebend machen".
   "Leicht glasig": Blur von 16px (Token-Wert aus .glass-panel) auf 9px reduziert und die
   Grundtoenung minimal geoeffnet, damit das Goldfunkeln durch die Karten hindurch erkennbar
   bleibt, statt zu einer undurchsichtigen Flaeche zu werden. Wie beim USP-Block bewusst nur hier
   ueberschrieben und nicht im Token: .glass-panel traegt auch Hero-Karten, Pakete und weitere
   Flaechen.
   "Schwebend": dieselbe weiche Ellipsen-Drift wie beim USP-Block (float-drift-soft), aber pro
   Karte um 1.1s versetzt. Ohne diesen Versatz wuerden alle fuenf Karten synchron wippen, was wie
   ein technischer Fehler aussieht statt wie Schweben. Ausserdem ein langsamerer Zyklus (11s), da
   fuenf gleichzeitig bewegte Flaechen schneller unruhig wirken als eine einzelne. */
#vorteile li {
  padding: 1.6rem;
  text-align: center;
  font-size: 0.96rem;
  backdrop-filter: blur(9px) saturate(125%);
  -webkit-backdrop-filter: blur(9px) saturate(125%);
  background: rgba(28, 23, 48, 0.42);
  animation: float-drift-soft 11s ease-in-out infinite;
}

#vorteile li:nth-child(2) { animation-delay: 1.1s; }
#vorteile li:nth-child(3) { animation-delay: 2.2s; }
#vorteile li:nth-child(4) { animation-delay: 3.3s; }
#vorteile li:nth-child(5) { animation-delay: 4.4s; }

@media (prefers-reduced-motion: reduce) {
  #vorteile li {
    animation: none;
  }
}

#vorteile .mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 1.5px solid var(--neon-pink);
  color: var(--neon-cyan);
  margin-bottom: 0.9rem;
}

#vorteile .mark .icon {
  width: 1.3rem;
  height: 1.3rem;
}

/* =======================================================
   DER SPIEGEL (Produkt)
   ======================================================= */

/* 2026-07-11: Nutzerwunsch, das archivierte Hero-Testbild (siehe assets/img/REGISTRY.md,
   dort als "Kandidat fuer Slider/andere Section" vermerkt) hier als Section-Hintergrund
   einzusetzen. Bewusste Ausnahme von der "kein lokaler Section-Hintergrund"-Regel (siehe
   site.css Datei-Kopfkommentar), da explizit vom Nutzer angefragt. Textspalte bekommt das
   etablierte .glass-panel-Muster (siehe Abschnitt 6g in DESIGN_SYSTEM.md) fuer garantierte
   Lesbarkeit vor dem Foto. */
/* 2026-08-12: Abdunkelnder Verlauf ueber dem Hintergrundfoto ersatzlos entfernt (Nutzerwunsch,
   Variante "ganz raus"). Er lag als erste von zwei background-Ebenen ueber dem Bild
   (100deg, 70% Schwarz links, 35% in der Mitte, 75% rechts) und stammte aus der Zeit, als in
   dieser Section noch das Produktbild und eine Textspalte standen und Lesbarkeit brauchten.
   Beides ist inzwischen entfernt, die Section traegt nur noch das Foto-Laufband, das seinen
   Kontrast aus den eigenen Bildrahmen und Schatten bezieht. Das Foto steht damit in voller
   Leuchtkraft. */
#spiegel {
  position: relative;
  background: center / cover no-repeat url("../img/hero/fotobox-mieten-header.webp");
}

/* padding-bottom: der Nutzer wollte unter dem Laufband "einen kleinen Abstand, von ca. 2% oder
   was in unsere Designsprache passt". 2vw ist genau das: exakt 2% der Fensterbreite, in derselben
   clamp()-Schreibweise wie alle anderen Abstaende im Projekt, mit Unter- und Obergrenze, damit
   es auf sehr schmalen und sehr breiten Fenstern nicht kippt. Ersetzt gezielt nur das
   Bottom-Padding aus der globalen section-Regel (clamp(3.5rem, 7vw, 7rem)), oben bleibt der
   normale Sectionabstand.
   2026-08-12, Nutzerwunsch "setz bitte die Section auf VH100": min-height statt height, gleiche
   Begruendung wie bei #usp (Abschnitt 6zY) - bei sehr flachen Fenstern darf der Inhalt die
   Section weiterhin aufziehen, statt aus einer starren Box herauszulaufen.
   Die Flex-Ausrichtung ist hier der eigentliche Punkt: `justify-content: flex-end` haelt das
   Laufband am UNTEREN Rand. Ohne sie waere es nach dem Vergroessern oben am Section-Padding
   kleben geblieben und darunter waeren ueber 500px leeres Hintergrundbild gestanden, und der
   ausdrueckliche Wunsch war ja, dass das Band unten laeuft. Die Section wirkt dadurch als
   ganzflaechiges Foto-Panel, ueber dessen unterer Kante die Event-Bilder durchziehen. */
#spiegel {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: clamp(0.75rem, 2vw, 2.5rem);
}

/* 2026-08-12: Regeln fuer .wrap und .tilt-wrap entfallen. Nach dem Entfernen des Produktbilds
   (Nutzerwunsch) enthaelt #spiegel nur noch das Foto-Laufband, eine .wrap gibt es dort nicht
   mehr. */

/* Sichtfenster des Laufbands: ueber die volle Sectionbreite, nicht auf .wrap begrenzt, damit das
   Band wirklich von Kante zu Kante laeuft. Weiche Raender per mask-image, damit die Fotos am Rand
   aus- und einblenden statt hart abgeschnitten zu werden. Der untere Abstand zur Sectionkante
   kommt aus #spiegel padding-bottom (siehe oben). Pausiert bei Hover/Fokus, da die Bilder einen
   eigenen Hover-Effekt haben.
   2026-08-12: margin-top entfallen. Er trennte das Band vom Produktbild darueber, und das ist
   auf Nutzerwunsch entfernt. Ohne Geschwister waere er einfach auf das Section-Padding
   obendrauf gekommen und haette eine unnoetig grosse Leerflaeche ueber dem Band erzeugt. */
.spiegel-marquee {
  position: relative;
  z-index: 1;
  overflow: hidden;
  padding-block: 0.4rem;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
}

.spiegel-marquee:hover .spiegel-gallery,
.spiegel-marquee:focus-within .spiegel-gallery {
  animation-play-state: paused;
}

/* 2026-08-12: alle Regeln zum Produktbild entfernt (.tilt-wrap, img.tilt samt Hover und
   reduced-motion-Ausnahme, .camera-flash). Das Bild ist auf Nutzerwunsch aus der Section
   geloescht, die Regeln haetten sonst kein Ziel mehr gehabt.
   Bei der Gelegenheit mit entfernt: .spiegel-textpanel. Diese Klasse hatte schon vorher kein
   Element mehr im Markup (Rest aus einer frueheren Umstellung, als in dieser Section noch eine
   Textspalte stand, siehe DESIGN_SYSTEM.md Abschnitt zu #spiegel). */

/* 2026-08-11: die Zwei-Spalten-Regel ab 860px ist entfallen, siehe Begruendung bei
   #spiegel .wrap weiter oben (das Laufband ist kein Grid-Kind mehr, die zweite Spalte waere
   leer geblieben). */

/* 2026-08-11: Block VORHER/NACHHER-SLIDER (.compare-*) ersatzlos entfernt. Die zugehoerige
   Section #vergleich ("Sehen Sie den Unterschied") ist auf Nutzerwunsch aus index.html
   geloescht ("das wollen wir nicht zeigen"), die Regeln haetten sonst als toter Code
   zurueckgeblieben. Ebenfalls entfernt: der Slider-Handler in site.js und die nur dort
   verwendete Platzhalter-Illustration design/placeholders/vergleich-standardbox.svg. */

/* =======================================================
   GALERIE
   2026-07-04: bewusste Ausnahme von der "kein lokaler Section-Hintergrund"-Regel
   (Nutzerwunsch): eigenes Foto rechts am Rand, faedet nach links ins Section-Schwarz
   aus, kein sichtbarer Uebergang zum globalen Ambient-Background.
   ======================================================= */

/* 2026-07-11: padding-top entfernt (Nutzerwunsch "kein Gap zur oberen Section"), das
   Breitformat-Hintergrundfoto von .galerie-top soll direkt am unteren Rand von #spiegel
   anschliessen. Der globale section-Rule-Top-Padding (clamp(3.5rem,7vw,7rem)) wuerde sonst
   sichtbaren Leerraum vor dem Bild erzeugen. Bottom-Padding bleibt (print-showcase darunter
   braucht weiterhin regulaeren Abstand). */
#galerie {
  background: var(--bg-void);
  overflow: hidden;
  padding-top: 0;
}

/* 2026-07-11: min-height 50vh testweise ergaenzt, auf Nutzerwunsch weiter auf 70vh erhoeht,
   damit das neue Breitformat-Hintergrundbild (21:9) auch bei wenig Inhalt genug Flaeche zum
   Wirken hat. */
.galerie-top {
  position: relative;
  padding: 2rem 0 1rem;
  min-height: 85vh;
  display: flex;
  align-items: center;
}

/* 2026-07-06: echtes Full-Bleed wie .gallery-grid, sonst bezieht sich "rechts am Rand" nur
   auf die rechte Kante von .wrap (max. 1180px), nicht auf die echte Browser-Kante.
   2026-07-11: Schwarzwert von var(--bg-void) (#08070c, leicht bläulich getönt) auf reines
   #000000 korrigiert. Per Sript gemessen: der linke Rand von galerie-bg.webp ist echtes
   #000000, --bg-void erzeugte dadurch eine sichtbare Kante statt eines fliessenden
   Uebergangs (Nutzerfeedback: "ich glaube der schwarzwert in der linken Box ist nicht tief
   schwarz"). Solid-Zone von 22% auf 40% verbreitert, da jetzt echter Fliesstext
   (.spiegel-copy) statt nur einer Ueberschrift+Lede dort sitzt und mehr Kontrastflaeche
   braucht.
   2026-07-11, gleicher Tag: neues Breitformat-Foto (21:9, `frau-am-spiegel-breitformat.webp`)
   ersetzt `galerie-bg.webp`. `background-position: right center` sorgt dafuer, dass die Frau
   IMMER rechtsbuendig im sichtbaren Ausschnitt bleibt (Nutzervorgabe "muss immer rechts liegend
   sein"), unabhaengig von Container-Breite/-Hoehe wird bei Bedarf links beschnitten, nie
   rechts. */
.galerie-top .galerie-bg {
  position: absolute;
  top: -2rem;
  bottom: -2rem;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  z-index: 0;
  background-image:
    linear-gradient(90deg, #000000 0%, #000000 40%, transparent 72%),
    url("../img/frau-am-spiegel-breitformat.webp");
  background-repeat: no-repeat, no-repeat;
  background-position: 0 0, right center;
  background-size: 100% 100%, auto 100%;
}

/* 2026-07-11: Text "Berühren Sie den Spiegel." sitzt jetzt hier (getauscht mit den
   Galerie-Fotos, die nach #spiegel gewandert sind), linksbuendig in der linken Haelfte, auf
   der massiv-schwarzen Zone von .galerie-bg (siehe oben), kein zusaetzliches Glass-Panel
   noetig, der Verlauf selbst uebernimmt den Kontrast. */
.spiegel-copy {
  max-width: 34rem;
  padding: 1.5rem 0 2.5rem;
}

/* 2026-08-11: Nutzerfeedback "die klebt mir zu weit links am Rand, das kann weiter nach rechts
   eingerueckt werden". Ursache per Bounding-Box ueber mehrere Breiten belegt: .spiegel-copy sitzt
   buendig an der linken Kante von .wrap, und deren Aussenabstand faellt ab ca. 1230px abwaerts auf
   nur noch 24px (gemessen bei 1200/1024/900/800px jeweils copyLeft = 24px). Auf den breiten
   Ansichten faellt das nicht auf (bei 1440px sind es 130px, bei 1680px 250px), im mittleren
   Bereich klebt der Text dagegen fast an der Fensterkante.
   Bewusst padding-left statt margin-left: .spiegel-copy hat box-sizing: border-box und
   max-width: 34rem, das Padding rueckt dadurch nur den Textanfang nach rechts und laesst die
   RECHTE Kante, wo sie ist. Das ist hier wichtig, denn der schwarze Verlauf hinter dem Text
   (siehe .galerie-top .galerie-bg) ist nur bis 40% der Fensterbreite deckend und wird bis 72%
   transparent. Ein margin-left haette den ganzen Block samt rechter Kante weiter in diese
   ausfadende Zone geschoben und den Kontrast zum Foto verschlechtert.
   Nur ab 768px, damit auf Mobile (dort ist die Textspalte ohnehin schmal) nichts enger wird. */
@media (min-width: 768px) {
  .spiegel-copy {
    padding-left: clamp(2rem, 4vw, 4rem);
  }
}

.galerie-top > *:not(.galerie-bg) {
  position: relative;
  z-index: 1;
}

/* 2026-07-11: .dust-field muss die Section wie .galerie-bg voll ausfuellen (position:absolute),
   die generische Regel oben (gleiche Spezifitaet, .galerie-top > *:not(...)) wuerde sonst
   position:relative gewinnen, da sie zuerst im Quellcode steht. Explizite Regel mit
   identischer Spezifitaet, aber danach im Quellcode, gewinnt den Tie-Break.
   2026-07-11, Korrektur: "inset:0" bezog sich nur auf .galerie-top (max. 1180px, die .wrap-
   Box), NICHT auf die echte Section-Breite, Nutzer sah dadurch praktisch keine Partikel im
   sichtbaren Full-Bleed-Bereich. Gleiche Full-Bleed-Breakout-Technik wie .galerie-bg. */
.galerie-top > .dust-field {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  z-index: 1;
}

.print-showcase {
  margin-top: 3.5rem;
  text-align: center;
}

/* 2026-08-11: font-size hier entfernt. Die Groesse kommt jetzt zentral aus h3.font-display
   (tokens.css, --text-h2), Nutzerwunsch "einheitliche H2 Groessen". Diese Regel haette sonst
   gewonnen und die Aenderung wirkungslos gemacht: .print-showcase h3 und h3.font-display haben
   die IDENTISCHE Spezifitaet (je eine Klasse + ein Element), bei Gleichstand entscheidet die
   Quelltext-Reihenfolge, und site.css wird nach tokens.css geladen. Nur die Ueberschrift selbst
   war betroffen, deshalb faellt die Regel ersatzlos weg statt umgeschrieben zu werden. */

/* 2026-08-11: Nutzerwunsch "das sollte eher eine Slideshow der Bilder werden, diese sollten von
   rechts nach links durchlaufen". Aus der statischen, umbrechenden Reihe ist ein Endlos-Laufband
   geworden (Markup: Kartensatz zweimal, siehe Kommentar in index.html).
   .print-marquee ist das Sichtfenster: overflow:hidden schneidet ab, was links rausgelaufen und
   rechts noch nicht drin ist. Die weichen Kanten kommen per mask-image statt per Verlaufs-Overlay,
   weil die Karten einen Neon-Glow haben, den ein daruebergelegter Farbverlauf sichtbar truebeen
   wuerde; eine Maske blendet stattdessen sauber die Deckkraft aus.
   Vertikales Padding ist noetig, weil .print-card:hover die Karte anhebt und vergroessert
   (translateY(-8px) scale(1.05)); ohne den Puffer wuerde overflow:hidden genau diese Bewegung
   oben abschneiden. */
.print-marquee {
  position: relative;
  overflow: hidden;
  padding: 1.5rem 0 0.75rem;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 7%, #000 93%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 7%, #000 93%, transparent 100%);
}

/* width: max-content hebt die Breitenbegrenzung des Elternteils auf, sonst wuerde das Band auf
   Containerbreite gestaucht und die Karten wieder umbrechen. */
.print-strip {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 2rem;
  width: max-content;
  animation: print-marquee 34s linear infinite;
}

/* Anhalten, solange jemand hinschaut oder per Tastatur drin ist: die Karten haben einen eigenen
   Hover-Effekt (siehe .print-card:hover), der an einem vorbeiziehenden Ziel unbrauchbar waere. */
.print-marquee:hover .print-strip,
.print-marquee:focus-within .print-strip {
  animation-play-state: paused;
}

/* Der Versatz ist bewusst NICHT glatt -50%. Das Band enthaelt 8 Karten mit 7 Zwischenraeumen,
   50% der Gesamtbreite entspricht deshalb 4 Karten plus 3.5 Zwischenraeumen. Fuer einen
   nahtlosen Sprung braucht es aber genau 4 Karten plus 4 Zwischenraeume, also einen halben
   Zwischenraum mehr (gap: 2rem, Haelfte davon 1rem). Ohne diese Korrektur haette jeder Zyklus
   einen sichtbaren 16px-Versatz. */
@keyframes print-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-50% - 1rem)); }
}

/* Ohne Bewegung zurueck zur alten, umbrechenden Reihe: ein Laufband, das nicht laeuft, waere
   sonst eine willkuerlich abgeschnittene Bilderreihe. */
@media (prefers-reduced-motion: reduce) {
  .print-marquee {
    -webkit-mask-image: none;
    mask-image: none;
  }

  .print-strip {
    animation: none;
    flex-wrap: wrap;
    justify-content: center;
    width: auto;
  }

  /* Die zweite Kartenkopie existiert nur, damit die Schleife nahtlos ist. Steht das Band still,
     waere sie schlicht jedes Bild ein zweites Mal. */
  .print-card[aria-hidden="true"] {
    display: none;
  }
}

/* 2026-07-08: keine feste Kartenbreite mehr, die Karte passt sich der Bildbreite an (siehe
   .print-card img), damit das Querformat-Bild seine echten Proportionen behalten kann.
   2026-07-09: Nutzerwunsch "kein weisser Polaroid-Style", stattdessen der knallige Neon-Glow-
   Rahmen des Seiten-Leitmotivs (gleiche Werte wie .mirror-frame in design/tokens.css, siehe
   dort fuer die Herleitung der Glow-Farben). */
.print-card {
  margin: 0;
  background: var(--bg-surface);
  padding: 0.5rem;
  border: 1.5px solid var(--neon-pink);
  border-radius: var(--radius-md);
  box-shadow:
    0 0 14px rgba(255, 63, 192, 0.5),
    0 0 42px rgba(47, 230, 255, 0.28),
    inset 0 0 20px rgba(157, 78, 255, 0.1);
  transition: transform 0.35s var(--ease-glow), box-shadow 0.35s var(--ease-glow),
    border-color 0.35s var(--ease-glow);
}

/* 2026-08-11: von nth-child(1..4) auf 4n-Muster umgestellt. Seit der Slideshow steht der
   Kartensatz zweimal im Band, die feste Nummerierung haette die Kopien (Karten 5 bis 8)
   unverdreht gelassen und die Schleife dadurch an der Nahtstelle sichtbar gemacht. */
.print-card:nth-child(4n + 1) { transform: rotate(-4deg); }
.print-card:nth-child(4n + 2) { transform: rotate(3deg); }
.print-card:nth-child(4n + 3) { transform: rotate(-2.5deg); }
.print-card:nth-child(4n + 4) { transform: rotate(4deg); }

.print-card:hover {
  transform: rotate(0deg) translateY(-8px) scale(1.05);
  border-color: var(--neon-cyan);
  box-shadow:
    0 0 18px rgba(47, 230, 255, 0.65),
    0 0 56px rgba(255, 63, 192, 0.4),
    inset 0 0 26px rgba(47, 230, 255, 0.15);
  z-index: 2;
  position: relative;
}

/* 2026-07-07: feste Hoehe + object-fit:cover, damit die Quer- und Hochformat-Karten exakt
   gleich hoch sind statt je nach Seitenverhaeltnis unterschiedlich hoch zu wirken
   (Nutzerfeedback: Breitbild-Karte war deutlich niedriger als die Hochkant-Karten). */
/* 2026-07-08: kein object-fit:cover mehr (Nutzerwunsch: Original-Proportionen behalten, nicht
   beschneiden). Feste Hoehe + width:auto sorgen trotzdem dafuer, dass Quer- und Hochformat-Bild
   exakt gleich hoch sind, die Breite ergibt sich pro Bild aus dem eigenen Seitenverhaeltnis. */
.print-card img {
  display: block;
  height: clamp(210px, 45vw, 300px);
  width: auto;
  border-radius: calc(var(--radius-md) - 4px);
}

@media (prefers-reduced-motion: reduce) {
  .print-card {
    transition: none;
  }
}

/* =======================================================
   ANLÄSSE
   ======================================================= */

#anlaesse ul {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.4rem;
}

/* 2026-07-03: .anlass-inner traegt jetzt das eigentliche .glass-panel, .mirror-frame--shift
   sitzt auf dem aeusseren <li> (.ring-frame, kein backdrop-filter dort), weil backdrop-filter
   selbst einen Stacking-Context erzeugt und den Ring sonst durch die ganze Karte fluten laesst.
   Hover-Transform (Heben) kommt jetzt generisch aus .ring-frame:has(.glass-panel):hover in
   tokens.css, nicht mehr von hier, siehe Kommentar dort fuer den Grund (Rahmen-Desync-Bug). */
.anlass-inner {
  height: 100%;
  padding: 2rem 1.4rem;
  text-align: center;
  background: rgba(15, 12, 24, 0.82);
}

#anlaesse .glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  margin-bottom: 0.8rem;
}

#anlaesse .glyph .icon {
  width: 1.4rem;
  height: 1.4rem;
}

/* =======================================================
   ABLAUF (Timeline)
   ======================================================= */

/* 2026-07-04: Browser-Standardnummerierung des <ol> entfernt (Nutzerfeedback: "hässlich"),
   stattdessen eine Timeline-Linie, die die Stationen verbindet und sich beim Scrollen
   einmal von Anfang bis Ende "einzeichnet", die Icon-Badges sitzen als Knoten darauf. */
.ablauf-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.6rem;
  position: relative;
}

.ablauf-steps::before {
  content: "";
  position: absolute;
  z-index: 0;
  background: linear-gradient(180deg, var(--neon-pink), var(--neon-cyan), var(--neon-violet));
  left: calc(1.3rem + 1.3rem - 1px);
  top: 1.6rem;
  bottom: 1.6rem;
  width: 2px;
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 2.6s var(--ease-glow);
}

.ablauf-steps.is-visible::before {
  transform: scaleY(1);
}

@media (min-width: 760px) {
  .ablauf-steps {
    grid-template-columns: repeat(5, 1fr);
  }

  .ablauf-steps::before {
    left: 0;
    right: 0;
    top: calc(1.6rem + 1.3rem - 1px);
    bottom: auto;
    width: auto;
    height: 2px;
    background: linear-gradient(90deg, var(--neon-pink), var(--neon-cyan), var(--neon-violet));
    transform: scaleX(0);
    transform-origin: left;
  }

  .ablauf-steps.is-visible::before {
    transform: scaleX(1);
  }
}

.ablauf-steps li {
  position: relative;
  z-index: 1;
  border-radius: var(--radius-lg);
}

.ablauf-inner {
  padding: 1.6rem 1.3rem;
  height: 100%;
}

/* 2026-07-05: einmaliger Farb-Rotations-Ring beim Reveal (Nutzerwunsch, angelehnt an
   .mirror-frame--shift), spielt einmal ab und fadet danach wieder aus, statt dauerhaft zu
   rotieren wie bei Pakete/Anlaesse. Braucht die zweischichtige Ring-Frame-Struktur (aeusseres
   li ohne backdrop-filter, inneres .glass-panel), sonst flutet der Ring die Karte, siehe
   .mirror-frame--shift-Kommentar weiter oben zu Stacking-Contexts. */
.ablauf-ring::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: 100%;
  height: 100%;
  padding: 3px;
  border-radius: inherit;
  box-sizing: content-box;
  background-image: conic-gradient(
    from var(--mirror-angle),
    var(--neon-pink),
    var(--neon-violet),
    var(--neon-cyan),
    var(--gold),
    var(--neon-pink)
  );
  z-index: -1;
  opacity: 0;
  pointer-events: none;
}

.ablauf-steps.is-visible .ablauf-ring::before {
  animation: ablauf-ring-reveal 2s ease-out backwards;
}

.ablauf-steps.is-visible li:nth-child(1)::before { animation-delay: 0.2s; }
.ablauf-steps.is-visible li:nth-child(2)::before { animation-delay: 0.7s; }
.ablauf-steps.is-visible li:nth-child(3)::before { animation-delay: 1.2s; }
.ablauf-steps.is-visible li:nth-child(4)::before { animation-delay: 1.7s; }
.ablauf-steps.is-visible li:nth-child(5)::before { animation-delay: 2.2s; }

@keyframes ablauf-ring-reveal {
  0% { --mirror-angle: 0deg; opacity: 0; }
  20% { opacity: 0.85; }
  100% { --mirror-angle: 300deg; opacity: 0; }
}

.ablauf-steps .step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 1.5px solid var(--neon-cyan);
  color: var(--neon-cyan);
  background: var(--bg-void);
  margin-bottom: 0.7rem;
  position: relative;
  z-index: 2;
}

.ablauf-steps.is-visible .step-num {
  animation: ablauf-node-pop 0.5s var(--ease-glow) backwards;
}

.ablauf-steps.is-visible li:nth-child(1) .step-num { animation-delay: 0.2s; }
.ablauf-steps.is-visible li:nth-child(2) .step-num { animation-delay: 0.7s; }
.ablauf-steps.is-visible li:nth-child(3) .step-num { animation-delay: 1.2s; }
.ablauf-steps.is-visible li:nth-child(4) .step-num { animation-delay: 1.7s; }
.ablauf-steps.is-visible li:nth-child(5) .step-num { animation-delay: 2.2s; }

@keyframes ablauf-node-pop {
  0% { transform: scale(0.4); box-shadow: 0 0 0 rgba(47, 230, 255, 0); }
  55% { transform: scale(1.2); box-shadow: 0 0 16px 4px rgba(47, 230, 255, 0.5); }
  100% { transform: scale(1); box-shadow: 0 0 0 rgba(47, 230, 255, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .ablauf-steps::before {
    transition: none;
    transform: none !important;
  }

  .ablauf-steps.is-visible .step-num {
    animation: none;
  }

  .ablauf-steps.is-visible .ablauf-ring::before {
    animation: none;
  }
}

.ablauf-steps .step-num .icon {
  width: 1.3rem;
  height: 1.3rem;
}

.ablauf-steps h3 {
  font-size: var(--text-card-title);
}

.ablauf-steps p {
  font-size: 0.88rem;
  color: var(--text-muted);
  margin: 0;
}

/* =======================================================
   WARUM FOTO-BERGANDER
   ======================================================= */

#warum blockquote {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 600;
  text-align: center;
  font-size: clamp(1.1rem, 2vw, 1.4rem);
  max-width: 46rem;
  margin: 0 auto 3rem;
  color: var(--neon-pink);
}

.warum-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.6rem;
}

.warum-grid > li {
  padding: 1.8rem;
}

.warum-grid h3 {
  font-size: var(--text-card-title);
  color: var(--neon-cyan);
}

.warum-grid p {
  font-size: 0.92rem;
  color: var(--text-muted);
  margin: 0;
}

/* =======================================================
   PAKETE
   ======================================================= */

.pakete-hinweis {
  text-align: center;
  font-size: 0.85rem;
  color: var(--text-muted);
  max-width: 48rem;
  /* 2026-07-05: Abstand nach unten vergroessert, die schwebende "Beliebteste Wahl"-Badge
     stand sonst zu nah an dieser Box, Nutzerfeedback. */
  margin: -1.6rem auto 4rem;
  padding: 0.7em 1.2em;
  border: 1px dashed rgba(47, 230, 255, 0.4);
  border-radius: var(--radius-md);
}

.pakete-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1.5rem;
  align-items: start;
}

.paket-card {
  height: 100%;
}

/* 2026-07-03: gleiches Prinzip wie .anlass-inner, siehe Kommentar dort. */
.paket-inner {
  height: 100%;
  padding: 1.8rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.paket-card h3 {
  font-family: var(--font-display);
  font-size: var(--text-card-title);
  margin: 0;
}

.paket-card .preis {
  font-family: var(--font-display);
  font-size: 2rem;
  color: var(--gold-bright);
}

.paket-card .preis span {
  font-size: 0.9rem;
  color: var(--text-muted);
  font-family: var(--font-body);
}

.paket-card ul {
  display: grid;
  gap: 0.55rem;
  font-size: 0.88rem;
  color: var(--text-muted);
  flex: 1;
}

.paket-card ul li::before {
  content: "✓ ";
  color: var(--gold);
}

/* =======================================================
   ZUSATZ / UPSELL
   ======================================================= */

.zusatz-cols {
  display: grid;
  gap: 1.6rem;
}

@media (min-width: 760px) {
  .zusatz-cols {
    grid-template-columns: 1fr 1fr;
  }
}

.zusatz-cols > div {
  padding: 1.6rem;
}

.zusatz-cols h3 {
  font-size: var(--text-card-title);
  color: var(--neon-pink);
}

.zusatz-cols ul {
  display: grid;
  gap: 0.6rem;
  font-size: 0.9rem;
  color: var(--text-muted);
}

/* =======================================================
   MIETBEDINGUNGEN
   ======================================================= */

.vorlauf-hinweis {
  text-align: center;
  margin-top: 2.2rem;
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 600;
  color: var(--neon-violet);
}

/* =======================================================
   TERMINE (Live erleben)
   ======================================================= */

.termine-leer {
  max-width: 34rem;
  margin: 0 auto;
  padding: 2.4rem;
  text-align: center;
}

.termine-leer p {
  color: var(--text-muted);
}

/* =======================================================
   TESTIMONIALS
   ======================================================= */

.testimonial-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.4rem;
}

.testimonial-grid > figure {
  margin: 0;
  padding: 1.6rem;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.testimonial-grid blockquote {
  margin: 0 0 1rem;
  font-size: 0.94rem;
  color: var(--text-primary);
}

.testimonial-grid figcaption {
  margin-top: auto;
  font-size: 0.82rem;
  color: var(--neon-cyan);
}

/* =======================================================
   ÜBER MICH
   ======================================================= */

#ueber-mich .wrap {
  display: grid;
  gap: 2.6rem;
  align-items: center;
}

#ueber-mich .wrap p + p {
  margin-top: 1em;
}

#ueber-mich .ring-frame {
  border-radius: 50%;
}

#ueber-mich .portrait-clip {
  border-radius: 50%;
  overflow: hidden;
  aspect-ratio: 1;
}

#ueber-mich img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 780px) {
  #ueber-mich .wrap {
    grid-template-columns: 0.6fr 1.4fr;
  }
}

/* =======================================================
   GARANTIE
   ======================================================= */

.garantie-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.4rem;
}

.garantie-grid > li {
  padding: 1.8rem;
  text-align: center;
}

.garantie-grid h3 {
  font-size: var(--text-card-title);
  color: var(--neon-pink);
}

.garantie-grid p {
  font-size: 0.88rem;
  color: var(--text-muted);
  margin: 0;
}

/* =======================================================
   ACCORDION (FAQ & Mietbedingungen)
   ======================================================= */

/* 2026-07-03: umbenannt von .faq-list zu .accordion-list, wird jetzt auch bei
   Mietbedingungen wiederverwendet, nicht mehr FAQ-exklusiv. */
.accordion-list {
  max-width: 52rem;
  margin: 0 auto;
  display: grid;
  gap: 0.9rem;
}

/* 2026-07-04: echtes Glassmorphism statt fast blickdichtem bg-surface, Nutzerfeedback
   "zu schwarz", soll zum Rest der glasigen Karten passen. */
.accordion-list .accordion-item {
  border: 1px solid rgba(157, 78, 255, 0.35);
  border-radius: var(--radius-md);
  background: rgba(28, 23, 48, 0.45);
  backdrop-filter: blur(16px) saturate(130%);
  -webkit-backdrop-filter: blur(16px) saturate(130%);
  overflow: hidden;
}

.accordion-list summary {
  cursor: pointer;
  padding: 1.1rem 1.4rem;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

.accordion-list summary::-webkit-details-marker {
  display: none;
}

.accordion-list summary::after {
  content: "+";
  font-family: var(--font-display);
  color: var(--neon-cyan);
  font-size: 1.3rem;
  flex-shrink: 0;
}

.accordion-list details[open] summary::after {
  transform: rotate(45deg);
}

.accordion-list .faq-body {
  padding: 0 1.4rem 1.2rem;
  color: var(--text-muted);
  font-size: 0.92rem;
}

.accordion-list .faq-body p + p,
.accordion-list .faq-body ul + p,
.accordion-list .faq-body ul {
  margin-top: 0.7rem;
}

.accordion-list .faq-body ul {
  display: grid;
  gap: 0.5rem;
}

.accordion-list .faq-body li {
  padding-left: 1.2rem;
  position: relative;
}

.accordion-list .faq-body li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--neon-cyan);
}

/* =======================================================
   KONTAKT
   ======================================================= */

.kontakt-grid {
  display: grid;
  gap: 2.4rem;
}

@media (min-width: 900px) {
  .kontakt-grid {
    grid-template-columns: 0.85fr 1.15fr;
  }
}

.kontakt-info {
  padding: 2rem;
}

.kontakt-info p + p {
  margin-top: 0.6rem;
}

.kontakt-info .phone {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--neon-pink);
  text-decoration: none;
}

form.kontakt-form {
  padding: 2rem;
  display: grid;
  gap: 1.1rem;
}

form.kontakt-form[hidden] {
  display: none;
}

.kontakt-form .row2 {
  display: grid;
  gap: 1.1rem;
}

@media (min-width: 560px) {
  .kontakt-form .row2 {
    grid-template-columns: 1fr 1fr;
  }
}

.kontakt-form label {
  display: grid;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.kontakt-form input,
.kontakt-form select,
.kontakt-form textarea {
  background: var(--bg-void);
  border: 1px solid rgba(157, 78, 255, 0.3);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  padding: 0.75em 0.9em;
  font-family: var(--font-body);
  font-size: 0.95rem;
}

.kontakt-form input:focus,
.kontakt-form select:focus,
.kontakt-form textarea:focus {
  outline: none;
  border-color: var(--neon-cyan);
}

.kontakt-form button {
  justify-self: start;
  border: none;
  cursor: pointer;
  font-size: 0.95rem;
}

/* =======================================================
   "FOTO WIRD GEDRUCKT" (Welle 2)
   Ersetzt das Formular nach Absenden. Rein clientseitige Animation aktuell, siehe
   TODO-Kommentar bei #kontakt-form in index.html.
   ======================================================= */

.print-animation {
  padding: 2.6rem 2rem;
  text-align: center;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 1.2rem;
  justify-content: center;
  min-height: 22rem;
}

/* Nur einblenden, wenn das hidden-Attribut per JS entfernt wurde (siehe site.js).
   Vorher hat .print-animation { display:flex } faelschlich das hidden-Attribut ueberstimmt,
   die Box war die ganze Zeit sichtbar statt nur nach Formular-Absenden. */
.print-animation:not([hidden]) {
  display: flex;
}

.print-slot {
  width: 55%;
  max-width: 220px;
  height: 6px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--neon-pink), var(--neon-cyan));
  box-shadow: 0 0 14px rgba(47, 230, 255, 0.55);
}

.print-photo {
  width: 150px;
  height: 190px;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
}

.print-photo-frame {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(160deg, rgba(255, 63, 192, 0.25), rgba(47, 230, 255, 0.2)),
    var(--bg-surface-2);
  border: 2px solid var(--gold);
  border-radius: 8px;
  transform: translateY(-105%);
  animation: print-emerge 1.1s cubic-bezier(0.34, 1.15, 0.4, 1) forwards;
  animation-delay: 0.15s;
}

@keyframes print-emerge {
  to {
    transform: translateY(0%);
  }
}

.print-message {
  color: var(--text-muted);
  max-width: 32ch;
}

@media (prefers-reduced-motion: reduce) {
  .print-photo-frame {
    animation: none;
    transform: translateY(0%);
  }
}

/* =======================================================
   FOOTER
   ======================================================= */

.site-footer {
  padding: 3rem 0 2.2rem;
  text-align: center;
  border-top: 1px solid rgba(157, 78, 255, 0.3);
}

.site-footer .foot-links {
  display: flex;
  gap: 1.6rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 1rem;
  font-size: 0.85rem;
}

.site-footer .foot-links a {
  text-decoration: none;
  color: var(--text-muted);
}

.site-footer .foot-links a:hover {
  color: var(--neon-cyan);
}

.site-footer small {
  color: var(--text-muted);
  font-size: 0.78rem;
}

.site-footer .foot-credit {
  display: block;
  margin-top: 0.5rem;
}

.site-footer .foot-credit a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color 0.25s var(--ease-glow);
}

.site-footer .foot-credit a:hover {
  color: var(--neon-cyan);
}

/* =======================================================
   REVEAL-ON-SCROLL (JS toggelt .is-visible, siehe assets/js/site.js)
   ======================================================= */

.reveal-group > * {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.7s var(--ease-glow), transform 0.7s var(--ease-glow);
}

.reveal-group.is-visible > * {
  opacity: 1;
  transform: translateY(0);
}

/* =======================================================
   MOBILE: ICON-BADGES VERKLEINERN (2026-07-04)
   Nutzerfeedback: SVG-Icons wirken auf schmalen Viewports "heavy gross", vor allem in
   der Vertrauens-Leiste (bislang groesster Icon ohne Kreis-Badge drumherum).
   ======================================================= */

@media (max-width: 480px) {
  .vertrauen-row .icon {
    width: 1.35rem;
    height: 1.35rem;
  }

  .vertrauen-row {
    gap: 1.6rem 1.2rem;
  }

  #vorteile .mark,
  .ablauf-steps .step-num {
    width: 2.2rem;
    height: 2.2rem;
  }

  #anlaesse .glyph {
    width: 2.3rem;
    height: 2.3rem;
  }

  #vorteile .mark .icon,
  .ablauf-steps .step-num .icon {
    width: 1.1rem;
    height: 1.1rem;
  }

  #anlaesse .glyph .icon {
    width: 1.15rem;
    height: 1.15rem;
  }
}
