/* ===========================================================
   Henrike-Kärtchen – Liebesbrief-Optik, reines CSS, offline-fähig
   =========================================================== */

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  min-height: 100%;
  font-family: Georgia, "Times New Roman", serif;
  background: radial-gradient(ellipse at top, #fdf3f1 0%, #f6dfe0 55%, #e8c3c8 100%);
  color: #4a2b33;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.stage {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Liebesbrief-Kärtchen */
.card {
  position: relative;
  /* 100% statt 92vw: .stage ist bereits 100% der body-CONTENT-Box (body hat
     padding: 2rem). 92vw bezieht sich dagegen auf den vollen Viewport
     INKLUSIVE des body-Paddings und kann dadurch bei schmalen Viewports
     breiter werden als der tatsächlich verfügbare Platz (z.B. 360px
     Viewport: 92vw = 331px, verfügbar sind aber nur 360 - 64 = 296px)
     -> latenter horizontaler Overflow. min(680px, 100%) ist an jeder
     Viewportbreite overflow-sicher. */
  width: min(680px, 100%);
  padding: clamp(2rem, 4vw, 3rem) clamp(1.5rem, 3.5vw, 2.5rem) clamp(2.5rem, 5vw, 3.5rem);
  text-align: center;
  background:
    linear-gradient(135deg, #fffaf6 0%, #fdf1ef 55%, #fbe6e8 100%);
  /* Oben leicht schärfer als unten: unterstützt die Anmutung einer oben
     gefalzten Grußkarte (Falzkante oben, offene Blattkanten unten). */
  border-radius: 4px 4px 6px 6px;
  /* Gestaffelte Schatten für eine "aufgestellte Karte": enger Kontaktschatten,
     weicher Abwurfschatten nach unten und ein seitlicher Schatten passend zur
     leichten Drehung. */
  box-shadow:
    0 1px 2px rgba(150, 60, 80, 0.18),
    0 18px 34px -12px rgba(150, 60, 80, 0.32),
    -14px 10px 26px -18px rgba(120, 40, 60, 0.35),
    inset 0 0 60px rgba(200, 110, 130, 0.12);
  /* Dezenter 3D-Kipp-Effekt zusätzlich zur bestehenden Drehung. rotateX
     bewusst <= 2deg, damit die Karte auf kleinen Viewports nicht kippend oder
     verzerrt wirkt.
     Unkritisch für die Nein-Button-Fluchtlogik: der Button wird beim
     Aktivieren des Fluchtmodus per document.body.appendChild(btnNo) VOR dem
     Wechsel auf position:fixed nach <body> reparentet (siehe app.js), die
     Karte ist dann kein Vorfahre mehr und kann somit auch keinen
     Containing-Block für position:fixed aufspannen. Transform/Perspective
     darf deshalb NUR hier auf .card stehen - niemals auf html, body oder
     .stage. */
  transform: perspective(1200px) rotateX(1.6deg) rotate(-1.5deg);
  border: 1px solid rgba(200, 110, 130, 0.3);
}

/* Herz-Wasserzeichen (dezente Karten-Dekoration) */
.card::before {
  content: "♥";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 16rem;
  line-height: 1;
  color: rgba(200, 110, 130, 0.09);
  z-index: 0;
  pointer-events: none;
}

/* Hinweis: Die frühere angedeutete Falz-/Klappkante (.card::after) wurde
   ersatzlos entfernt - die Karte wird jetzt real per Deckel-Animation
   geöffnet (siehe .seal-overlay), die statische Kante war dadurch optisch
   obsolet. */

/* -----------------------------------------------------------------------
   Geschlossene Karte: Deckel-Klappe mit Wachssiegel
   -----------------------------------------------------------------------
   Deckt #questionView im geschlossenen Zustand VOLLFLÄCHIG und DECKEND ab
   (kein hidden/display:none auf der View selbst - siehe index.html/app.js).
   Wichtig: perspective/transform stehen ausschließlich HIER auf dem Overlay.
   Da das Overlay ein GESCHWISTER von #questionView ist, verändert es die
   Containing-Block-Kette von #btnNo (der in #questionView liegt) nicht -
   die position:fixed-Fluchtlogik bleibt davon unberührt. */
.seal-overlay {
  position: absolute;
  inset: 0;
  /* Über den normalen Karteninhalten (z-index: 1), aber UNTER dem
     fliehenden Nein-Button (.btn--no.is-escaping, z-index: 20). */
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 4px 4px 6px 6px;
  cursor: pointer;
  /* Deckender Verlauf in der Kartenpalette - #questionView darf visuell
     nicht durchscheinen. */
  background:
    radial-gradient(circle at 50% 40%, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(160deg, #fffaf6 0%, #fdf1ef 52%, #f6dde0 100%);
  box-shadow:
    inset 0 -14px 22px -18px rgba(150, 60, 80, 0.5),
    inset 0 0 60px rgba(200, 110, 130, 0.14);
  /* Scharnier an der Oberkante (Briefumschlag-Lasche) */
  transform-origin: top center;
  perspective: 1200px;
  -webkit-tap-highlight-color: transparent;
}

.seal-overlay:focus {
  outline: none;
}

.seal-overlay:focus-visible {
  outline: 3px solid #c2415a;
  outline-offset: -6px;
}

/* Wachssiegel */
.seal {
  /* Klicks/Hover gehen an den umschließenden Button. */
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(5.5rem, 16vw, 7.5rem);
  height: clamp(5.5rem, 16vw, 7.5rem);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #d4677c 0%, #b23a52 55%, #8d2438 100%);
  color: #fbe6ea;
  font-size: clamp(2.4rem, 7vw, 3.2rem);
  line-height: 1;
  text-shadow: 0 1px 2px rgba(80, 15, 30, 0.45);
  box-shadow:
    0 6px 14px -6px rgba(120, 25, 45, 0.55),
    inset 0 2px 6px rgba(255, 255, 255, 0.35),
    inset 0 -3px 8px rgba(90, 15, 30, 0.4);
}

/* Öffnen: Deckel schwingt an der Oberkante nach oben/hinten weg. */
.seal-overlay.is-opening {
  pointer-events: none;
  transform: rotateX(-100deg);
  opacity: 0;
  transition:
    transform 600ms ease-in,
    opacity 300ms ease-in 300ms;
}

.card__title {
  font-family: "Snell Roundhand", "Apple Chancery", "Segoe Script", "Brush Script MT",
    "Lucida Handwriting", Georgia, serif;
  font-size: clamp(1.7rem, 5vw, 2.4rem);
  margin: 0.5rem 0 0.25rem;
  line-height: 1.3;
  position: relative;
  z-index: 1;
}

.card__title:focus {
  outline: none;
}

.card__title:focus-visible {
  outline: 3px solid #c2415a;
  outline-offset: 4px;
}

.card__subtitle {
  font-size: 1.05rem;
  margin: 0 0 1.75rem;
  color: #7a3d49;
  font-style: italic;
  position: relative;
  z-index: 1;
}

/* Mobile-first: auf schmalen Viewports stehen die Buttons UNTEREINANDER.
   align-items: center (nicht stretch) sorgt dafür, dass jeder Button seine
   NATÜRLICHE Breite behält.
   Wichtig: hier bewusst KEIN width: 100% / align-items: stretch auf .btn -
   #btnNo wechselt im Fluchtmodus auf position: fixed und würde eine
   Prozentbreite dann gegen den VIEWPORT statt gegen die Karte auflösen. */
.buttons {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1.75rem;
}

/* Ab ca. 680px Viewportbreite passen alle drei Buttons nebeneinander.
   Breakpoint bewusst in em statt px: em bezieht sich hier auf die
   Root-Schriftgröße, skaliert also mit Browser-/Nutzer-Zoom der
   Textgröße - genau wie .btn { min-width: 9.5rem } und gap: 1rem. Der
   Umbruchpunkt bleibt dadurch auch bei vergrößerter Root-Font korrekt.
   Platzrechnung am Breakpoint (42.5em = 680px bei 16px Root-Font):
   Bedarf  = 3 x 9.5rem (152px) + 2 x gap 1rem (16px) = 488px
   Vorhanden = 680px - 2 x body-padding 2rem (64px) = 616px Kartenbreite,
               abzüglich Karten-Padding (clamp -> 2 x 24px) und Rahmen
               = ca. 566px Inhaltsbreite -> ca. 78px Reserve.
   flex-wrap: nowrap ist damit sicher (kein Umbruch, kein Overflow). */
@media (min-width: 42.5em) {
  .buttons {
    flex-direction: row;
    flex-wrap: nowrap;
  }
}

.btn {
  font-family: inherit;
  font-size: 1.05rem;
  padding: 0.7rem 1.6rem;
  border-radius: 8px;
  border: 2px solid #a4485c;
  background: #fdf0ef;
  color: #4a2b33;
  cursor: pointer;
  box-shadow: 0 2px 0 rgba(150, 60, 80, 0.15);
  /* "Ja"/"Vielleicht" Rollentausch (siehe app.js, renderRoles()) ändert
     den Button-Text zur Laufzeit; min-width verhindert dabei einen
     sichtbaren Breiten-/Layout-Sprung der Button-Reihe (.buttons ist ein
     Flex-Container), unabhängig davon, welcher der beiden Texte gerade auf
     welchem Button steht.
     Wichtig: der Wert muss das gerenderte Border-Box (Text + Padding +
     Rahmen) des LÄNGEREN Labels "Vielleicht" in JEDER Rolle abdecken, sonst
     wächst der Button für "Vielleicht" über den min-width-Boden hinaus,
     während der Button mit "Ja" auf dem Boden bleibt - das war die Ursache
     des ca. 21px Sprungs beim Rollentausch (gemessen: "Ja" 109.35px vs.
     "Vielleicht" 126.39px, siehe .btn { font-family: inherit } -> erbt den
     Serif-Stack von body, NICHT den Schreibschrift-Stack von .card__title).
     9.5rem (152px bei 16px Root-Font) wurde per echtem Chrome-Headless-Test
     gegen mehrere plausible Font-Fallbacks für den Body-Stack (Georgia,
     "Times New Roman", generisches serif) nachgemessen: "Vielleicht"
     benötigt dort real max. ~125px Border-Box-Breite; 152px lässt somit
     eine großzügige Sicherheitsmarge (~27px) für abweichende Systemschriften
     und Sub-Pixel-Rendering, ohne dass Ja/Vielleicht je unterschiedlich groß
     werden - beide Rollen landen dann in jedem realistischen Fall auf
     demselben min-width-Boden. */
  min-width: 9.5rem;
  text-align: center;
}

.btn:hover {
  background: #fbe2e2;
}

.btn:focus {
  outline: none;
}

.btn:focus-visible {
  outline: 3px solid #c2415a;
  outline-offset: 3px;
}

.btn--yes {
  background: #f4e2df;
  border-color: #b5495a;
}

.btn--yes:hover {
  background: #edd0cd;
}

.btn--maybe {
  background: #fbeceb;
  border-color: #c07a68;
}

.btn--maybe:hover {
  background: #f6dcd9;
}

.btn--no {
  /* Ease-out ohne jegliches Überschwingen: die Kurve ist monoton steigend von
     (0,0) nach (1,1) (siehe Begründung in app.js-Nachbarkommentar / README),
     der Button kann während der Animation daher niemals über die geclampte
     Zielposition hinausschießen und somit auch nie kurzzeitig außerhalb des
     Viewports stehen. */
  transition: transform 220ms cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
  /* Touch-Verhalten: Der Sprung wird auf Touch-Geräten per touchstart
     ausgelöst (mit preventDefault). Diese Angaben verhindern die
     Doppel-Tap-Zoom-Verzögerung, den blauen Tap-Highlight und die
     Textauswahl beim wiederholten Antippen. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}

/* Sobald der Nein-Button flieht, wird er auf position:fixed umgeschaltet (via JS-Klasse) */
.btn--no.is-escaping {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 20;
}

/* Standardzustand: KEIN Flex-Item. Solange #btnNo noch im normalen Fluss der
   .buttons-Reihe steht, enthält die Reihe genau 3 Items (Ja, Vielleicht,
   Nein) und damit 2 Gaps.
   Wäre der Platzhalter hier bereits display: inline-block (nur
   visibility: hidden), wäre er trotz Unsichtbarkeit ein VIERTES Flex-Item -
   die Reihe hätte vorher 4 Items / 3 Gaps und nach dem Reparenting von
   #btnNo nach <body> nur noch 3 Items / 2 Gaps. Beim allerersten Sprung des
   Nein-Buttons wäre die Reihe dadurch schlagartig um einen ganzen Gap (1rem)
   schmaler geworden -> sichtbarer Positionssprung von Ja/Vielleicht.
   Deshalb wird der Platzhalter erst in activateEscapeMode() (app.js) exakt
   in dem Moment auf display: inline-block geschaltet, in dem #btnNo aus dem
   Fluss genommen wird. Item-/Gap-Anzahl bleibt so über den Übergang hinweg
   konstant. */
.btn-placeholder {
  visibility: hidden;
  display: none;
}

.joke-hint {
  min-height: 1.4em;
  margin-top: 1rem;
  font-size: 0.95rem;
  color: #a4485c;
  font-weight: bold;
  position: relative;
  z-index: 1;
}

.joke-hint.wiggle {
  animation: wiggle 400ms ease-in-out;
}

@keyframes wiggle {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-4px);
  }
  75% {
    transform: translateX(4px);
  }
}

/* Bestätigungs-Ansicht */
.view--confirmation .card__title {
  color: #3c763d;
}

.hearts {
  position: relative;
  height: 40px;
  margin-top: 0.5rem;
  pointer-events: none;
}

.heart {
  position: absolute;
  bottom: 0;
  font-size: 1.4rem;
  animation: float-up 1600ms ease-out forwards;
  opacity: 0.9;
}

@keyframes float-up {
  0% {
    transform: translateY(0) scale(0.8);
    opacity: 0.9;
  }
  100% {
    transform: translateY(-90px) scale(1.1);
    opacity: 0;
  }
}

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

/* Reduzierte Bewegung respektieren: keine Gleit-Übergänge, keine Keyframe-Animationen */
@media (prefers-reduced-motion: reduce) {
  .btn--no {
    transition: none !important;
  }

  .seal-overlay {
    transition: none !important;
  }

  .joke-hint.wiggle {
    animation: none !important;
  }

  .heart {
    animation: none !important;
    opacity: 0 !important;
  }
}
