* { box-sizing: border-box; }

@font-face {
  font-family: "Tangled";
  src: url("assets/Tangled.ttf") format("truetype");
  font-display: swap;
}

.name-tangled {
  font-family: "Tangled", var(--font-display);
}

:root {
  --gold: #D8A543;
  --brown: #4C342C;
  --lilac: #8E7DBA;
  --pink: #E7B4C1;
  --green: #87946B;
  --cream: #FFF8EB;
  --cream-2: #FAF1DD;
  --cream-3: #F6EACC;
  --cream-field: #FFF3DE;
  --yes-bg: #E5F0D7;
  --yes-text: #4F5B3C;
  --no-bg: #F4DCE2;
  --no-text: #7E5561;
  --font-display: "Playfair Display", Georgia, serif;
  --font-label: "Funnel Sans", -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", -apple-system, "Segoe UI", sans-serif;
}

html, body {
  margin: 0;
  padding: 0;
  background: #0a0a0a;
  color: #f5f5f5;
  font-family: var(--font-body);
}

body.scroll-locked {
  overflow: hidden;
  height: 100%;
}

/* The animation is the page's background for its entire scroll length: the
   sticky canvas and the flowing content-overlay share the same grid cell
   (both `grid-area: 1 / 1`), so the row's height is driven by whatever the
   content-overlay's stacked sections naturally need (no manual vh figure to
   tune), while the canvas stays pinned behind them for that whole span via
   `position: sticky`. Scroll progress across this same span (0 = top of the
   hero section, 1 = bottom of the closing section) drives the animation's
   frame index in src/main.js, so each section is inherently synchronized to
   whichever part of the sequence is showing when it's on screen. */
.scroll-stage {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.scroll-stage > .sticky,
.scroll-stage > .content-overlay {
  grid-area: 1 / 1;
}

.sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  background: #000;
  z-index: 1;
}

.content-overlay {
  position: relative;
  z-index: 2;
}

#frame-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* `.progress-track` and `.music-toggle` are persistent UI chrome that must
   stay clickable/visible for the whole page, so they live as `position:
   fixed` siblings of `.gate`/`.scroll-stage` in the DOM (NOT nested inside
   `.sticky`). Previously they sat inside `.sticky` (z-index: 1) while
   `.content-overlay` (z-index: 2) was a SIBLING stacking context with a
   higher z-index — a child's z-index can't out-rank a sibling stacking
   context from inside it, so content-overlay's (mostly transparent)
   sections were painting/hit-testing above the whole `.sticky` box
   regardless of the button's own z-index, silently eating its clicks even
   though it was still visible. `position: fixed` escapes that entirely. */
.progress-track {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 4px;
  background: rgba(255, 255, 255, 0.15);
  z-index: 30;
}

.progress-fill {
  width: 100%;
  height: 100%;
  background: #f5f5f5;
  transform-origin: left;
  transform: scaleX(0);
}

.music-toggle {
  position: fixed;
  top: 1.25rem;
  right: 1.5rem;
  z-index: 30;
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 999px;
  backdrop-filter: blur(4px);
  color: #f5f5f5;
  cursor: pointer;
  padding: 0;
  transition: background 0.2s ease, transform 0.15s ease;
}

.music-toggle:hover {
  background: rgba(0, 0, 0, 0.6);
  transform: scale(1.05);
}

.music-toggle .icon-paused {
  display: none;
}

.music-toggle.is-paused .icon-playing {
  display: none;
}

.music-toggle.is-paused .icon-paused {
  display: block;
}

/* ---------- Gate / lock screen ---------- */

.gate {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  transition: opacity 0.9s ease;
}

.gate.is-open {
  opacity: 0;
  pointer-events: none;
}

.gate-bg {
  position: absolute;
  inset: 0;
  background-image: url("assets/mainref-portrait.jpg");
  background-size: cover;
  background-position: 50% 22%;
  transform: scale(1.02);
}

.gate-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(76, 52, 44, 0.35) 0%,
    rgba(76, 52, 44, 0.25) 35%,
    rgba(76, 52, 44, 0.55) 100%
  );
}

.gate-content {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.6rem;
  padding: 2rem;
  text-align: center;
}

.gate-eyebrow {
  margin: 0;
  max-width: 20rem;
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.3;
  color: var(--cream);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.gate-eyebrow .name-tangled {
  display: inline-block;
  font-size: 1.7em;
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

.gate-open {
  position: relative;
  border: none;
  cursor: pointer;
  padding: 0;
  background: none;
  isolation: isolate;
}

.gate-open-glow {
  position: absolute;
  inset: -30px;
  border-radius: 999px;
  background: radial-gradient(
    circle,
    rgba(216, 165, 67, 0.55) 0%,
    rgba(232, 167, 184, 0.3) 45%,
    rgba(142, 125, 186, 0) 75%
  );
  animation: gate-pulse 2.6s ease-in-out infinite;
  z-index: -1;
}

@keyframes gate-pulse {
  0%, 100% { transform: scale(0.92); opacity: 0.75; }
  50% { transform: scale(1.12); opacity: 1; }
}

.gate-open-label {
  display: block;
  font-family: var(--font-label);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--brown);
  background: linear-gradient(135deg, var(--gold) 0%, #F0C878 50%, var(--gold) 100%);
  padding: 1.1rem 2.4rem;
  border-radius: 999px;
  box-shadow: 0 8px 24px rgba(216, 165, 67, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.5);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.gate-open:hover .gate-open-label,
.gate-open:focus-visible .gate-open-label {
  transform: translateY(-2px) scale(1.03);
  box-shadow: 0 12px 28px rgba(216, 165, 67, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

/* Dreamy star/sparkle field over the gate — bigger, softer, whiter than
   the page-wide sparkles (see .fx-sparkle), meant to feel like a starry
   night sky glinting behind the "Toca para abrir" button. Populated by
   initGate() in src/main.js. */
.gate-stars {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}

.gate-star {
  position: absolute;
  top: var(--y, 50%);
  left: var(--x, 50%);
  width: var(--size, 3px);
  height: var(--size, 3px);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 1px rgba(255, 255, 255, 0.9), 0 0 14px 3px rgba(255, 224, 160, 0.55);
  animation: gate-star-twinkle var(--dur, 3s) ease-in-out var(--delay, 0s) infinite;
}

.gate-star.is-sparkle {
  border-radius: 0;
  background:
    linear-gradient(#FFE9B8, #FFE9B8) center / 100% 20% no-repeat,
    linear-gradient(#FFE9B8, #FFE9B8) center / 20% 100% no-repeat;
  box-shadow: none;
}

@keyframes gate-star-twinkle {
  0%, 100% { opacity: 0.15; transform: scale(0.6); }
  50% { opacity: 1; transform: scale(1.3); }
}

.gate-hint {
  margin: 0;
  font-family: var(--font-label);
  font-size: 0.85rem;
  letter-spacing: 0.05em;
  color: var(--cream);
  background: rgba(76, 52, 44, 0.4);
  padding: 0.5rem 1.1rem;
  border-radius: 999px;
  backdrop-filter: blur(4px);
}

/* ---------- Ambient decoration ----------
   Fixed to the viewport (not the document), so they read as ambient
   "weather" over whatever's currently on screen rather than being tied to
   an absolute page position. All layers are `pointer-events: none` so
   they never intercept clicks/taps on real UI (RSVP fields, buttons,
   gate, music toggle). Shapes are drawn with plain CSS instead of an
   image asset, so there's nothing to license/attribute. */

.fx-layer {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 12;
}

/* Sparkles: small 4-pointed twinkle marks (two overlapping gradient
   diamonds), placed and timed via inline style vars set in JS
   (initFx() in src/main.js). */
.fx-sparkle {
  position: absolute;
  top: var(--y, 50%);
  left: var(--x, 50%);
  width: var(--size, 10px);
  height: var(--size, 10px);
  background:
    linear-gradient(var(--gold), var(--gold)) center / 100% 22% no-repeat,
    linear-gradient(var(--gold), var(--gold)) center / 22% 100% no-repeat;
  opacity: 0;
  animation: fx-twinkle var(--dur, 3.4s) ease-in-out var(--delay, 0s) infinite;
}

@keyframes fx-twinkle {
  0%, 100% { opacity: 0; transform: scale(0.4) rotate(0deg); }
  50% { opacity: 0.9; transform: scale(1) rotate(45deg); }
}

/* Falling leaves: a simple original teardrop/leaf silhouette (no
   external asset), warm gold/yellow to match the requested "sun" look
   without reproducing any specific licensed logo artwork, with a soft
   golden glow around the outer edge. */
.fx-leaf {
  position: absolute;
  top: -40px;
  left: var(--x, 50%);
  width: var(--size, 16px);
  height: var(--size, 16px);
  background: linear-gradient(135deg, #F3C25A, var(--gold) 70%);
  border-radius: 0% 60% 0% 60%;
  opacity: 0.85;
  filter: drop-shadow(0 0 5px rgba(216, 165, 67, 0.85)) drop-shadow(0 0 10px rgba(243, 194, 90, 0.5));
  animation: fx-fall var(--dur, 9s) linear var(--delay, 0s) infinite;
}

@keyframes fx-fall {
  0% { transform: translate(0, -5vh) rotate(0deg); opacity: 0; }
  8% { opacity: 0.85; }
  92% { opacity: 0.85; }
  100% { transform: translate(var(--drift, 40px), 108vh) rotate(340deg); opacity: 0; }
}

/* Growing flowers: pinned to the page edges, bottom-anchored, with a
   grow-in animation on load. */
.fx-flowers {
  z-index: 11;
}

.fx-flower {
  position: absolute;
  bottom: -6px;
  width: 68px;
  height: 118px;
  transform-origin: bottom center;
  animation: fx-grow 2.2s cubic-bezier(0.34, 1.56, 0.64, 1) 0.3s both;
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.25));
}

.fx-flower-left { left: -6px; }
.fx-flower-right { right: -6px; transform: scaleX(-1); }

@keyframes fx-grow {
  0% { transform: scaleY(0); opacity: 0; }
  100% { transform: scaleY(1); opacity: 1; }
}

.fx-flower-right {
  animation-name: fx-grow-right;
}

@keyframes fx-grow-right {
  0% { transform: scaleX(-1) scaleY(0); opacity: 0; }
  100% { transform: scaleX(-1) scaleY(1); opacity: 1; }
}

/* ---------- Invitation content sections ----------
   No section has its own background fill — the sticky canvas behind the
   content-overlay (see .scroll-stage above) IS the background throughout,
   so every heading/body sits directly over the animation. Text uses a
   uniform light/cream palette with a soft dark text-shadow for legibility
   against whatever busy, colorful frame happens to be behind it. Cards,
   form fields, and buttons that need to read as distinct UI keep a
   translucent "frosted" backing (blurred, semi-opaque) rather than a flat
   opaque fill, so the animation still shows through them too. */

.inv-section {
  min-height: 100vh;
  padding: 3rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.inv-section.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.inv-section.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.inv-eyebrow {
  margin: 0;
  font-family: var(--font-label);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}

.inv-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.9rem;
  line-height: 1.15;
  color: var(--cream);
  max-width: 26rem;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.55), 0 1px 4px rgba(0, 0, 0, 0.7);
}

.inv-title-lg {
  font-size: 2.4rem;
  max-width: 22rem;
}

.inv-body {
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.5;
  color: var(--cream);
  max-width: 30rem;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5), 0 1px 3px rgba(0, 0, 0, 0.65);
}

/* Countdown */

.countdown-cards {
  width: 100%;
  max-width: 26rem;
  display: flex;
  gap: 0.6rem;
}

.countdown-card {
  flex: 1;
  background: rgba(255, 248, 235, 0.85);
  backdrop-filter: blur(8px);
  padding: 0.9rem 0.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  align-items: center;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}

.countdown-value {
  font-family: var(--font-display);
  font-size: 1.7rem;
  color: var(--lilac);
  font-variant-numeric: tabular-nums;
}

.countdown-label {
  font-family: var(--font-label);
  font-size: 0.75rem;
  color: var(--brown);
}

/* Event details */

.details-card {
  width: 100%;
  max-width: 26rem;
  background: rgba(255, 248, 235, 0.85);
  backdrop-filter: blur(8px);
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  text-align: left;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}

.details-label {
  margin: 0;
  font-family: var(--font-label);
  font-size: 0.8rem;
  color: var(--gold);
}

.details-value {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--brown);
}

.details-note {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--brown);
}

.details-button {
  display: block;
  width: 100%;
  text-align: center;
  text-decoration: none;
  font-family: var(--font-label);
  font-size: 0.92rem;
  color: var(--cream);
  background: var(--green);
  padding: 0.85rem;
  margin-top: 0.35rem;
  transition: filter 0.2s ease;
}

.details-button:hover {
  filter: brightness(1.08);
}

/* Gallery */

.gallery-large {
  width: 100%;
  max-width: 26rem;
  height: 220px;
  object-fit: cover;
  object-position: center 20%;
  display: block;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}

.gallery-row {
  width: 100%;
  max-width: 26rem;
  display: flex;
  gap: 0.6rem;
}

.gallery-small {
  flex: 1;
  min-width: 0;
  height: 150px;
  object-fit: cover;
  display: block;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}

.gallery-upload-button {
  display: block;
  width: 100%;
  max-width: 26rem;
  text-align: center;
  text-decoration: none;
  font-family: var(--font-label);
  font-size: 0.92rem;
  color: var(--brown);
  background: rgba(255, 248, 235, 0.9);
  backdrop-filter: blur(8px);
  padding: 0.85rem;
  margin-top: 0.2rem;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
  transition: transform 0.15s ease, background 0.2s ease;
}

.gallery-upload-button:hover {
  transform: translateY(-2px);
  background: var(--cream);
}

/* RSVP */

.rsvp-form {
  width: 100%;
  max-width: 26rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  text-align: left;
}

.rsvp-field {
  background: rgba(255, 243, 222, 0.85);
  backdrop-filter: blur(8px);
  padding: 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}

.rsvp-field-label {
  font-family: var(--font-label);
  font-size: 0.8rem;
  color: var(--gold);
}

.rsvp-standalone-label {
  color: var(--cream);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}

.rsvp-people-caption {
  font-size: 0.85rem;
  color: #7D675E;
}

.rsvp-field input {
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--brown);
  padding: 0;
  outline: none;
}

.rsvp-field input::placeholder {
  color: #7D675E;
}

.rsvp-answer-row {
  display: flex;
  gap: 0.7rem;
}

.rsvp-option {
  flex: 1;
  border: 2px solid transparent;
  padding: 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  align-items: center;
  text-align: center;
  cursor: pointer;
  font: inherit;
  backdrop-filter: blur(8px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}

.rsvp-option-yes {
  background: rgba(229, 240, 215, 0.88);
  color: var(--yes-text);
}

.rsvp-option-no {
  background: rgba(244, 220, 226, 0.88);
  color: var(--no-text);
}

.rsvp-option.is-selected {
  border-color: var(--brown);
}

.rsvp-option-title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--brown);
}

.rsvp-option-caption {
  font-family: var(--font-label);
  font-size: 0.72rem;
}

.rsvp-people {
  overflow: hidden;
  max-height: 200px;
  transition: max-height 0.35s ease, opacity 0.35s ease, margin 0.35s ease;
}

.rsvp-people.is-hidden {
  max-height: 0;
  opacity: 0;
  margin: 0;
  pointer-events: none;
}

.rsvp-people-options {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.rsvp-people-option {
  flex: 1;
  background: rgba(255, 248, 235, 0.85);
  border: 2px solid transparent;
  padding: 0.7rem 0;
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--lilac);
  cursor: pointer;
}

.rsvp-people-option.is-selected {
  border-color: var(--lilac);
  color: var(--brown);
}

.rsvp-submit {
  border: none;
  cursor: pointer;
  font-family: var(--font-label);
  font-size: 0.95rem;
  color: var(--cream);
  background: var(--gold);
  padding: 0.95rem;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  transition: filter 0.2s ease;
}

.rsvp-submit:hover {
  filter: brightness(1.06);
}

.rsvp-status {
  font-family: var(--font-body);
  font-size: 0.88rem;
  color: var(--cream);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
  min-height: 1.2em;
}

.rsvp-status.is-error { color: #FFB4B4; }
.rsvp-status.is-success { color: #D8F0BE; font-weight: 600; }

/* Closing — the final beat of the whole invitation, so it gets extra
   storybook flourish: a slow-spinning soft sunburst behind an oversized,
   gold-gradient, drop-shadowed title that pops in with a bounce. The
   burst is a plain CSS conic-gradient (no external asset). */

.closing-section {
  position: relative;
  overflow: hidden;
}

.closing-burst {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34rem;
  height: 34rem;
  transform: translate(-50%, -50%);
  background: conic-gradient(
    from 0deg,
    rgba(216, 165, 67, 0.35) 0deg 14deg,
    transparent 14deg 28deg
  );
  border-radius: 50%;
  filter: blur(1px);
  animation: fx-burst-spin 40s linear infinite;
  z-index: -1;
}

@keyframes fx-burst-spin {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

.closing-title {
  font-family: var(--font-display);
  font-size: 2.6rem;
  max-width: 24rem;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #FFE9B8 0%, var(--gold) 55%, #B97F2E 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: none;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 24px rgba(216, 165, 67, 0.5));
  animation: fx-title-pop 1.1s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes fx-title-pop {
  0% { transform: scale(0.7); opacity: 0; }
  60% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

