/* ============================================================
   Novels Scroll-Reveal — Prototyp
   Pinning per position:sticky, Progress per JS (CSS Custom Props).
   Skalierbar für beliebige Card-Anzahl pro Stage.
   ============================================================ */

/* @property registriert --card-hover-y als animierbare Length-Property.
   Ohne Registrierung ignoriert der Browser transition auf Custom Properties. */
@property --card-hover-y {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

/* generai-style.css setzt body{overflow-x:hidden} global. Bei schmalem Viewport
   (Mobile) macht Chrome body damit zum Scroll-Container — position:sticky pinnt
   dann nicht mehr (Sticky bindet an nächsten Scroll-Container, hier body statt
   html). overflow-x:clip clippt horizontal genauso, ohne Scroll-Container zu
   erzeugen. Override muss nach generai-style.css geladen sein (ist es). */
html:has(.sr-sequence) body {
  overflow-x: clip;
  overflow-y: visible;
}

.sr-sequence {
  position: relative;
  background: #000;
  isolation: isolate;            /* Stacking-Context für z-index pro Wrap */
  opacity: 0;
  transition: opacity 0.6s ease;
}
.sr-sequence.sr-loaded {
  opacity: 1;
}

/* Pro Novel ein Wrapper. Sticky-Range hat 3 Phasen:
     Entry (150vh) — Stage rutscht von unten ein (entfällt für Stage 0)
     Content (200vh) — Title- und Cards-Reveal (letzte Card am Phasenende)
     OverlapOut (150vh) — Stage bleibt sticky-gepinnt, nächste Stage rutscht drüber.
   Keine Hold-Phase: Übergabe startet sofort wenn letzte Card am Platz ist.

   Stage 0:    0 + 200 + 150 = 350vh sticky → wrap = 450vh
   Stage i>0: 150 + 200 + 150 = 500vh sticky → wrap = 600vh */
.sr-wrap {
  position: relative;
  min-height: 600vh;
  /* KEIN overflow: hidden hier — würde die sticky-Behavior der Stage brechen
     (Sticky bindet an scroll-Container, overflow:hidden macht .sr-wrap zu
     einem). Stattdessen clippt der bg-track sein BG-Bild selbst. */
  /* Wraps überlappen sich (margin-top -250vh). Damit Klicks immer auf die
     ECHTE sichtbare Card landen — nicht auf einen transparenten Folge-Wrap
     mit höherem z-index — wraps selbst keine Pointer-Events. Nur .sr-card
     stellt pointer-events: auto wieder her. */
  pointer-events: none;
}
.sr-wrap:first-child {
  min-height: 450vh;
}

/* Overlap-Strecke = 150vh (war 100vh). Folge-Wrap startet 250vh vor dem
   visuellen Ende → dessen Overlap-Out-Phase deckt sich mit unserer
   Entry-Phase. Beide sticky, z-index regelt Überdeckung. */
.sr-wrap + .sr-wrap {
  margin-top: -250vh;
}

.sr-stage {
  position: sticky;
  top: 0;
  /* dvh = dynamic viewport height — matches JS innerHeight auf iOS Safari (URL-bar
     dynamics). Mit 100vh würden Stages 100vh = LARGEST viewport hoch sein,
     während JS mit innerHeight (kleiner bei sichtbarer URL-Bar) translateY setzt
     → mismatch, vorherige Stage scheint am oberen Rand durch. */
  height: 100dvh;
  overflow: hidden;
  /* Transparent — BG-Track liegt im selben Wrap als Sibling und scheint
     durch. isolation entfernt, damit Dim auf den BG wirken kann. */
  z-index: 1;
  transform: translate3d(0, var(--stage-ty, 0px), 0);
  will-change: transform;
}
/* Performance: contain auf NICHT-letzten Stages — last hat overflow:visible für
   Footer-Content, contain würde Footer clippen. */
.sr-stage:not(.sr-stage--last) {
  contain: layout paint;
}

/* ---- Background — Parallax-Scroll innerhalb der Stage ----
   BG liegt INNERHALB von .sr-stage (overflow:hidden). Das Stage-overflow
   clippt den BG nativ auf GPU-Ebene — kein clip-path, kein separater Track.
   Die JS-Formel kompensiert die Stage-eigene translateY, so dass der BG
   weiterhin echten Parallax-Scroll zeigt (10% der Scroll-Geschwindigkeit).
   Formel: --bg-y = rect.top * 0.1 - tyPx  (siehe scroll-reveal.js) */
.sr-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 160dvh;
  z-index: 0;
  background-image: var(--bg-desktop);
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  transform: translate3d(0, var(--bg-y, 0px), 0);
  will-change: transform;
}

@media (max-width: 810px) {
  .sr-bg {
    background-image: var(--bg-mobile, var(--bg-desktop));
    /* cover statt 100% auto: Image füllt Stage IMMER vollständig — keine
       schwarzen Lücken unten wenn natürliche Image-Höhe < vh. Proportionen
       bleiben (nur evtl. minimaler Seitencrop), kein Stretch.
       Combined mit reduziertem Parallax (siehe scroll-reveal.js bgParallaxRate)
       bleibt das Bild nahezu am Stage-Top verankert. */
    background-size: cover;
    background-position: center top;
  }
}

/* ---- Dimmer Overlay ---- */
.sr-dim {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: var(--dim, 0);
  z-index: 1;
  pointer-events: none;
  transition: none; /* Scroll-driven, keine CSS-Transition */
}

/* ---- Title ---- */
/* ---- Title (SVG, ans Content-Grid gebunden) ----
   Content-Max ist breakpointweise gesetzt:
     Desktop ≥1280: 1080px  (12 Spalten · Rand 180)
     Tablet 768-1279: 648px (8 Spalten · Rand 81)
     Mobile ≤767: 366px     (4 Spalten · Rand 12)
   SVG-viewBox 1642×280 (5.86:1) → die Höhe ergibt sich automatisch. */
.sr-title {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--sr-title-color, #fff);
  pointer-events: none;
  opacity: var(--title-o, 0);
  transform: translate3d(0, var(--title-y, 0px), 0);   /* nur Parallax, kein Scale */
  will-change: transform, opacity;
  padding: 0 12px;
  --sr-content-max: 366px;
}

.sr-title-svg {
  width: 100%;
  max-width: var(--sr-content-max);
  display: flex;
}

.sr-title-svg svg {
  width: 100%;
  height: auto;
  display: block;
}

@media (min-width: 768px) {
  .sr-title {
    padding: 0 81px;
    --sr-content-max: 648px;
  }
}
@media (min-width: 1280px) {
  .sr-title {
    padding: 0 180px;
    --sr-content-max: 1080px;
  }
}

/* Per-Stage override: heller BG (z.B. Catacumbas Wolken) — Title schwarz */
.sr-stage[data-title-color="dark"] { --sr-title-color: #111; }

/* ---- Cards-Container (Basis — shared desktop/mobile) ---- */
.sr-cards {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(40px, 6vh, 80px);
  z-index: 3;
  display: flex;
  gap: 24px;
  justify-content: center;
  align-items: flex-end;
  padding-left: clamp(40px, 4vw, 76px);
  padding-right: clamp(40px, 4vw, 76px);
}

/* ---- Desktop-only Slider-Behavior (Figma cards-scroll) ----
   100% width. Default align-center wenn Cards passen, sonst (.is-overflow Class
   via JS) flex-start + horizontaler Scroll.
   padding-top: 20px → Hover-Headroom (card translatet -4px nach oben).
   padding-bottom: 40px → Reveal-Headroom (card translatet +40 nach unten beim
     Einblenden; overflow:hidden würde sonst clippen).
   bottom-Offset um 40px reduziert, damit Card-Position visuell gleich bleibt.
   Slider als ganzes parallax-scrollt via --cards-exit-y. Mobile bleibt unberührt. */
@media (min-width: 811px) {
  .sr-cards {
    bottom: max(0px, calc(clamp(40px, 6vh, 80px) - 40px));
    padding-top: 20px;
    padding-bottom: 40px;
    overflow-x: hidden;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    transform: translate3d(0, var(--cards-exit-y, 0), 0);
    will-change: transform;
  }
  .sr-cards.is-overflow {
    justify-content: flex-start;
    overflow-x: auto;
    overscroll-behavior-y: none;
    touch-action: pan-x;
  }
  .sr-cards::-webkit-scrollbar { display: none; }
}

/* ---- Card ---- */
.sr-card {
  --card-w: clamp(160px, 22vw, 320px);
  --card-h: calc(var(--card-w) * 0.666);
  --card-hover-y: 0px;
  position: relative;
  display: block;
  width: var(--card-w);
  height: var(--card-h);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 14px;
  overflow: hidden;
  background-color: #111;
  text-decoration: none;
  color: #fff;
  flex: 0 0 auto;
  opacity: var(--card-o, 0);
  pointer-events: auto;
  /* Kein X-Slide — Cards erscheinen von unten auf korrekter horizontaler Position */
  transform: translate3d(0, calc(var(--card-y, 40px) + var(--card-hover-y, 0px)), 0);
  transition: --card-hover-y .25s ease;
  will-change: transform, opacity;
}

/* BG-Image als ::before — ermöglicht scale-Zoom ohne Konflikt mit JS-Transform auf dem Card. */
.sr-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--card-bg);
  background-size: cover;
  background-position: center;
  transform: scale(1);
  transform-origin: 50% 50%;
  transition: transform .6s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
  backface-visibility: hidden;
}

/* Hover nur auf echten Pointern (Maus). Touch-Geräte triggern :hover beim Tap
   was zu klebenden Hover-States führt — daher per @media (hover: hover) gated. */
@media (hover: hover) {
  .sr-card:hover {
    --card-hover-y: -4px;
  }
  .sr-card:hover::before {
    transform: scale(1.12);
  }
}

.sr-card-label {
  position: absolute;
  left: 14px;
  bottom: 12px;
  z-index: 2;
  font-family: var(--font-serif, "Inter", system-ui, sans-serif);
  font-size: clamp(0.8rem, 1vw, 1rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
  z-index: 1;
}

.sr-card::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 50%;
  z-index: 1;
  /*background: linear-gradient(to top, rgba(0, 0, 0, 0.55), transparent);*/
  pointer-events: none;
}

/* ---- Last Stage wrapper: entry [0, 0.95] → hold ≈ 5% ≈ 8vh, net-scroll ≈ 20vh ---- */
.sr-wrap--last {
  min-height: 270vh;
}

/* Weißer Hintergrund, kein BG-Image, kein Dim.
   height: auto + overflow: visible — kein Parallax-BG zu clippen.
   flex-column: ls-section wächst, footer sitzt darunter. */
.sr-stage--last {
  background: #fff;
  color: #000;
  height: auto;
  min-height: 100vh;
  overflow: visible;
  display: flex;
  flex-direction: column;
  pointer-events: auto; /* sr-wrap hat pointer-events:none → alle interaktiven Elemente zurücksetzen */
}

/* ls-section füllt den verfügbaren Raum über dem Footer */
.sr-stage--last .ls-section {
  position: static;
  flex: 1 0 auto;
}

/* ---- Last Stage (Kontakt-Section, analog zu .kontakt-section auf immersive) ---- */
.ls-section {
  background: #fff;
  color: #000;
  padding-block: clamp(120px, 18vh, 240px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.ls-inner {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  padding-inline: clamp(24px, 5vw, 80px);
}

.ls-title {
  font-family: 'Open Sans', sans-serif;
  font-weight: 300;
  font-size: clamp(28px, 4vw, 42px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0;
}

.ls-body {
  font-family: 'Open Sans', sans-serif;
  font-weight: 300;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.55;
  margin: 0;
  max-width: 560px;
}

.ls-cta {
  margin-top: 8px;
}

/* Staggered Entry: Elemente starten unsichtbar + versetzt nach unten.
   Werden per JS-Klasse .ls-animated auf dem Stage eingeblendet — kein Scroll-Driven. */
.ls-title,
.ls-body,
.ls-cta {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity  0.8s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.sr-stage--last.ls-animated .ls-title {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 0ms;
}
.sr-stage--last.ls-animated .ls-body {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 180ms;
}
.sr-stage--last.ls-animated .ls-cta {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity  0.8s cubic-bezier(0.22, 1, 0.36, 1) 360ms,
    transform 0.8s cubic-bezier(0.22, 1, 0.36, 1) 360ms,
    color 0.3s ease-in-out,
    background-color 0.3s ease-in-out,
    border-color 0.3s ease-in-out,
    box-shadow 0.3s ease-in-out;
}
.sr-stage--last.ls-animated .ls-cta:hover {
  transform: translateY(-3px);
  transition: transform 0.3s ease-in-out, color 0.3s ease-in-out, background-color 0.3s ease-in-out, border-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}

/* ---- Reduce-Motion fallback: alles sofort sichtbar, kein Pin ---- */
@media (prefers-reduced-motion: reduce) {
  .sr-wrap { min-height: auto; }
  .sr-stage { position: relative; height: auto; min-height: 100vh; padding: 80px 0; }
  .sr-dim { opacity: 0.4; }
  .sr-title { position: relative; opacity: 1; transform: none; padding: 80px 0 60px; }
  .sr-cards { position: relative; bottom: auto; flex-wrap: wrap; padding-bottom: 60px; }
  .sr-card { opacity: 1; transform: none; }
}

/* ---- Mobile: Vertical Card Stack ----
   Figma-Basis: 400×866px Frame. Cards: x=12, w=376, h=249, step=60px.
   Overlap = 249–60 = 189px = 76% der Card-Höhe.
   Jede Card gleitet vom Viewport-Boden in ihre fixe Position (keine Bewegung der anderen Cards).
   Sequentielle Reveal: jede Card ist vollständig sichtbar bevor die nächste startet. */
@media (max-width: 810px) {
  /* Title startet vertikal zentriert. JS shiftet ihn per --title-y nach oben,
     je nach Card-Reveal-Progress (siehe scroll-reveal.js mobile-Branch).
     SVG füllt die volle Container-Breite (überschreibt die min-width:768px
     Tablet-Cap von 648px für 768-810er Range). */
  .sr-title {
    align-items: center;
    padding-top: 0;
    padding-left: 12px;
    padding-right: 12px;
    --sr-content-max: 100%;
  }

  /* Card-Container: Spalte, zentriert (cards sind max 480px breit).
     bottom: skaliert mit screen height (12dvh ≈ ~104px bei 866vh) + safe-area-inset
     für iOS Home-Indicator. dvh statt vh — passt sich an URL-Bar-Dynamics an. */
  .sr-cards {
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding: 0 12px;
    bottom: calc(clamp(72px, 12dvh, 140px) + env(safe-area-inset-bottom, 0px));
  }

  /* Card: Container-Breite, gecapped bei 480px. Höhe folgt --card-h (3:2). */
  .sr-card {
    --card-w: min(calc(100vw - 24px), 480px);
    flex: 0 0 auto;
    width: var(--card-w);
    height: var(--card-h);
  }
  /* Hover-Effekte explizit ausschalten — Touch-Browser triggern manchmal trotz
     @media (hover: hover) klebende Hover-States nach Tap. */
  .sr-card:hover { --card-hover-y: 0px; }
  .sr-card:hover::before { transform: scale(1); }

  /* Stack-Gap dynamisch per Stage (gesetzt via JS auf --stack-gap, Default 60px).
     Margin = gap - cardH (negative überlappung). Bei mehr Cards shrinkt der Gap
     auf min 12px (siehe scroll-reveal.js applyMobileSizing). */
  .sr-card + .sr-card {
    margin-top: calc(var(--stack-gap, 60px) - var(--card-h));
  }
}
