/* ============================================================
   Wedding Invitation — Styles
   Mobile-first, no framework, no build step.
   ============================================================ */

/* ---------- Colour tokens ---------- */
:root {
  --cream: #F4E4D8;
  --olive: #928E76;
  --ink:   #333333;
}

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

html, body {
  height: 100%;
  background: var(--cream);
  font-family: serif; /* fallback; card text is in images */
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}

/* Snap lebt im #cards-Container, NICHT auf html: der Root-Scroller wird von
   iOS Safari beim Ein-/Ausfahren der URL-Bar resized → Snap-Punkte springen. */

img {
  display: block;
  max-width: 100%;
}

/* ---------- Envelope overlay (#envelope) ---------- */
#envelope {
  position: fixed;
  inset: 0;
  z-index: 100;
  /* Karten-Creme, identisch zum theme-color-Meta (nahtlose Browser-Leisten) */
  background: #F4E4D8;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  /* body gets overflow:hidden until opened (set by JS) */
}

/* Landing bewusst dekorfrei (16.07.2026): reines Creme, keine Watermarks,
   keine Washes — der Umschlag ist das einzige Objekt. */

/* Hinweis „Shtyp vulën / Tippe auf das Siegel" — erscheint per JS 10 s nach
   Load, falls das Siegel noch nicht berührt wurde; verschwindet beim Öffnen */
#seal-hint {
  /* Kind der .envelope-stage: 83 % liegt knapp unter Body-Unterkante (75.6 %)
     und Bodenschatten (bis ~80 %) — skaliert mit dem Umschlag */
  position: absolute;
  left: 50%;
  top: 83%;
  transform: translateX(-50%);
  z-index: 4;
  margin: 0;
  font-family: serif;
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--olive);
  white-space: nowrap;
  pointer-events: none;
  z-index: 10;
  opacity: 0;
  transition: opacity 0.9s ease;
}

#seal-hint.visible {
  opacity: 0.85;
}

@media (prefers-reduced-motion: reduce) {
  #seal-hint {
    transition: none;
  }
}

/* Bodenschatten unter dem Umschlag (Body-Unterkante liegt bei 75.6 % der Stage) */
#env-ground-shadow {
  position: absolute;
  left: 50%;
  top: 77%;
  width: 74%;
  height: 6%;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse closest-side,
              rgba(61, 53, 40, 0.22), rgba(61, 53, 40, 0) 80%);
}

/* The 896×1200 proportional container */
.envelope-stage {
  position: relative;
  width: min(88vw, calc(88dvh * 0.7467));
  /* 896/1200 = 0.7467 */
  aspect-ratio: 896 / 1200;
}

/* Shared image fill */
.envelope-stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  user-select: none;
}

/* Body layer sits at back */
#env-body {
  z-index: 1;
}

/* Flap wrapper — carries flap + seal, rotates on open */
#env-flap-wrapper {
  position: absolute;
  inset: 0;
  z-index: 2;
  /* perspective set on this element's parent via JS-accessible CSS */
  transform-style: preserve-3d;
  /* Fold line at 24.4% from top */
  transform-origin: 50% 24.4%;
}

/* Envelope outer shell gets the perspective */
.envelope-stage {
  perspective: 950px; /* etwas stärkere Verkürzung = mehr Tiefe beim Öffnen */
  /* Über den Deko-Ecken (z-index 1), damit die herausfliegende Karte
     nicht unter ihnen durchtaucht; im Ruhezustand überlappt nichts */
  z-index: 2;
}

/* ---------- "Karte aus dem Umschlag" (v0.2 Item 9) ---------- */

/* Clip-Fenster: zeigt die aufsteigende Karte nur OBERHALB der Faltlinie
   (24.4 %), als käme sie aus dem Schlitz. Negative Insets lassen sie über
   die Stage hinaus sichtbar bleiben; beim Flug wird das Fenster per GSAP
   geöffnet. z-index 3 = vor der zurückgeklappten Flap (physikalisch korrekt:
   die Klappe liegt hinten, die Karte kommt nach vorn). */
#env-card-clip {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  clip-path: inset(-45% -20% 75.6% -20%);
}

/* Mini-Karte: 58 % Stage-Breite, startet komplett unterhalb des
   Clip-Fensters (top 25 % > Faltlinie 24.4 %) = unsichtbar bis zum Öffnen.
   Explizite Werte überschreiben die .envelope-stage-img-Regel (inset:0). */
#env-card {
  position: absolute;
  top: 25%;
  left: 21%; /* (100% − 58%) / 2 */
  right: auto;
  bottom: auto;
  width: 58%;
  height: auto;
  object-fit: initial;
  border-radius: 2px;
  /* Palette des Bodenschattens — Papier auf Papier */
  box-shadow: 0 16px 36px rgba(61, 53, 40, 0.32);
  will-change: transform;
}

#env-flap {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  backface-visibility: hidden; /* Vorderseite verschwindet jenseits von 90° */
}

/* Innenseite der Klappe: vorgedreht um 180°, dunkler — wird sichtbar,
   sobald die Klappe über 90° rotiert (echte Zweiseitigkeit statt Spiegelbild) */
#env-flap-back {
  /* rotateY (vertikale Achse), NICHT rotateX: Silhouette bleibt deckungsgleich
     mit der Vorderseite (Spitze unten), nur die Blickrichtung dreht sich.
     Horizontale Spiegelung ist bei der symmetrischen Klappe unsichtbar. */
  transform: rotateY(180deg);
  backface-visibility: hidden;
  filter: brightness(0.72) saturate(0.9);
}

/* Ripple-Ring hinter dem Siegel — Geometrie wie #env-seal (54.5 %/50 %,
   Breite 51 %, Seal-Seitenverhältnis 677×369). GSAP zentriert per
   xPercent/yPercent und animiert scale+opacity; ruht bei opacity 0 */
#seal-ripple {
  position: absolute;
  top: 54.5%;
  left: 50%;
  /* KREIS in Wachs-Größe: das Seal-Bild ist 677 breit, der runde Wachs-Teil
     ≈ 369 (die Bildhöhe) — 51 % × 369/677 ≈ 28 % Stage-Breite */
  width: 28%;
  aspect-ratio: 1 / 1;
  border: 1.5px solid rgba(198, 162, 92, 0.65); /* Wachs-Gold */
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  z-index: 2; /* hinter dem Siegel (z 3) */
  backface-visibility: hidden;
}

/* Seal image — child of flap wrapper, inherits rotation.
   Override the .envelope-stage img rule (inset:0, full size) carefully:
   explicit top/left/right/bottom beat the descendant rule by specificity. */
#env-seal {
  position: absolute;
  /* Override inset:0 from .envelope-stage img */
  top: 54.5%;
  left: 50%;
  right: auto;
  bottom: auto;
  /* Size: 51% of the flap-wrapper width */
  width: 51%;
  height: auto;
  object-fit: initial;
  transform: translate(-50%, -50%);
  backface-visibility: hidden; /* Siegel sitzt AUSSEN — hinter 90° unsichtbar */
  cursor: pointer;
  z-index: 3;
  border: none;
  background: none;
  padding: 0;
}

/* ---------- Envelope UI controls ----------
   Direct child of #envelope (fixed, full-viewport), so positions are
   viewport-relative — gives true top-right / bottom-right placement. */
.env-controls {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none; /* let taps pass through the transparent area */
}

/* Language toggle — top right */
.lang-toggle {
  position: absolute;
  top: 16px;
  right: 16px;
  display: flex;
  gap: 4px;
  pointer-events: all;
}

.lang-toggle button {
  background: transparent;
  border: 1px solid var(--olive);
  color: var(--olive);
  font-family: serif;
  /* Emoji-Flaggen brauchen mehr Größe als die alten 11px-Buchstaben;
     Windows-Fallback (Buchstaben statt Flaggen) bleibt damit auch lesbar */
  font-size: 15px;
  line-height: 1.1;
  letter-spacing: 0.08em;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: 2px;
  transition: background 0.2s, color 0.2s;
  -webkit-tap-highlight-color: transparent;
}

.lang-toggle button.active {
  background: var(--olive);
  color: var(--cream);
}

/* ── Music button + volume slider (Task B) ───────────────────────────────────
   Wrapper: bottom-left, holds button + slider side by side.
   Button: cream surface, olive icon/stroke per DESIGN.md component spec.
   Slider: slides out horizontally on long-press, fades after release.        */

#mute-wrap {
  position: absolute;
  bottom: 16px;
  left: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: all;
}

/* The button itself */
#btn-mute {
  /* Papier-Chip-Look: helles Creme, feine Olive-Linie, weicher Schatten —
     wie ein geprägter Knopf auf Briefpapier (Redesign 16.07., Klick statt Hold) */
  position: relative;
  bottom: auto;
  left: auto;
  background: #FAF0E5;
  border: 1px solid rgba(146, 142, 118, 0.42);
  color: var(--olive);
  width: 46px;
  height: 46px;
  border-radius: 50%;
  box-shadow: 0 2px 10px rgba(61, 53, 40, 0.16),
              inset 0 1px 0 rgba(255, 255, 255, 0.55);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  touch-action: manipulation;
  user-select: none;
  /* Press feedback per Emil: scale(0.97) on :active */
  transition: transform 140ms cubic-bezier(0.23, 1, 0.32, 1),
              background 180ms ease,
              border-color 180ms ease;
}

#btn-mute:active {
  transform: scale(0.97);
}

/* Long-press held state: fill button to signal volume mode */
#btn-mute.vol-active {
  background: var(--olive);
  border-color: var(--olive);
}

#btn-mute.vol-active svg {
  stroke: var(--cream);
}

#btn-mute svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: var(--olive);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Prevent SVG from eating pointer events during drag */
  pointer-events: none;
}

/* Notenköpfe der ♫ gefüllt, nicht nur umrandet */
#btn-mute svg circle {
  fill: var(--olive);
  stroke: none;
}

#btn-mute.vol-active svg circle {
  fill: var(--cream);
}

/* Volume slider wrapper — hidden by default, slides in on long-press.
   Uses scaleX transform (not width) to avoid layout thrash — GPU composited.
   transform-origin: left so it expands rightward from the button edge.       */
#vol-slider-wrap {
  /* Fixed layout footprint always present; visual reveal via scale + opacity */
  width: 96px;
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  /* Both properties are compositor-friendly — no layout recalc */
  transition: transform 220ms cubic-bezier(0.23, 1, 0.32, 1),
              opacity 180ms ease;
}

#vol-slider-wrap.visible {
  transform: scaleX(1);
  opacity: 1;
}

/* prefers-reduced-motion: no slide, instant show/hide */
@media (prefers-reduced-motion: reduce) {
  #vol-slider-wrap {
    transition: none;
  }
}

/* The range input — olive-on-cream, matches palette */
#vol-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 88px;
  height: 2px;
  background: var(--olive);
  border-radius: 2px; /* DESIGN.md rounded.sm */
  outline: none;
  cursor: pointer;
  display: block;
  /* Prevent page scroll during slider drag on touch */
  touch-action: none;
}

#vol-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--cream);
  border: 1.5px solid var(--olive);
  cursor: pointer;
  transition: transform 120ms cubic-bezier(0.23, 1, 0.32, 1);
}

#vol-slider::-webkit-slider-thumb:active {
  transform: scale(1.25);
}

#vol-slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--cream);
  border: 1.5px solid var(--olive);
  cursor: pointer;
}

#vol-slider:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- Cards container (#cards) ----------
   Fixer Scroll-Container statt Root-Scroller: iOS-URL-Bar bewegt sich nicht,
   Snap-Punkte bleiben stabil (kein Nachjustier-Ruckler). */
#cards {
  opacity: 0;
  visibility: hidden;
  position: fixed;
  inset: 0;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  overscroll-behavior: none;
}

#cards.visible {
  opacity: 1;
  visibility: visible;
}

/* Individual card sections */
#cards section {
  position: relative;
  height: 100%; /* Höhe des fixen Containers = stabiler Viewport */
  overflow: hidden;
  background: var(--cream);
  scroll-snap-align: start;
  scroll-snap-stop: always;
  /* Zentrierte Spalte (Desktop); am Handy = volle Breite.
     BEWUSST 0.5625 statt der in Doc 06 notierten 0.45: mit 0.45 wäre die
     Spalte am iPhone schmaler als der Screen (Seitenstreifen). 0.5625 +
     cover = Handy randlos (Bleed wird gecroppt), Desktop-Säule zeigt
     die Safe-Zone (Bleed = Crop-Reserve, nicht Teil des Designs). */
  max-width: min(100vw, calc(100dvh * 0.5625));
  margin: 0 auto;
}

/* Card images fill the section.
   cover statt contain seit den 1080×2400-Karten: Texte liegen in der
   mittleren 1080×1920-Safe-Zone, die 240px-Streifen oben/unten sind
   Hintergrund-Bleed und dürfen gecroppt werden. */
#cards section img.card-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- Overlays on specific cards ---------- */

/* Shared overlay link anchor */
.card-overlay-link {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 86%;
  white-space: nowrap;
}

/* Map link on #details */
.card-overlay-link {
  color: #545454;
  font-family: serif;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-decoration: underline;
  text-decoration-color: var(--olive);
  text-underline-offset: 3px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

/* Dezenter Location-Pin: nur Kontur, Textfarbe, keine Füllung */
.pin-icon {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

.card-overlay-link:hover {
  text-decoration-color: #545454;
}


/* ---------- Scroll indicator ---------- */
#scroll-indicator {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s;
}

#scroll-indicator.visible {
  opacity: 1;
}

#scroll-indicator svg {
  width: 24px;
  height: 24px;
  stroke: var(--olive);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: chevron-bounce 1.4s ease-in-out infinite;
}

@keyframes chevron-bounce {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(6px); }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  #scroll-indicator svg {
    animation: none;
  }
  @keyframes chevron-bounce {}
}

/* ---------- Desktop: centred 9:16 pillar ---------- */
@media (min-width: 600px) {
  #cards {
    /* already handled by max-width above */
    box-shadow: 0 0 60px rgba(0,0,0,0.08);
  }
}
