/* =========================================================
   MIS XV · PARTE II — RUMBO A CANAIMA
   Paleta: selva profunda, musgo, niebla, hueso, oro, tierra
   ========================================================= */

:root {
  --selva: #4a4d24;
  --selva-oscura: #24250f;
  --musgo: #767a37;
  --musgo-claro: #a7ab5f;
  --niebla: #ece7d3;
  --hueso: #f8f5e9;
  --beige: #f4ecdc;        /* crema claro: fondo de la invitación */
  --texto: #5b6025;        /* verde oliva de todo el texto de lectura (contraste 5,7:1 sobre el crema) */
  --oro: #c9a24a;
  --oro-claro: #e3c579;
  --tierra: #6e5433;
  --tinta: #23241a;

  --serif: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --sans: "Jost", "Helvetica Neue", Arial, sans-serif;
  --script: "Butler", "Cormorant Garamond", serif;   /* títulos grandes */

  --ancho: 640px;

  /* alto del degradado que une una sección con la siguiente */
  --costura: clamp(26px, 5vh, 52px);
}

/* =========================================================
   MAPA DEL TEXTO — dónde se define cada texto
   ---------------------------------------------------------
   · Color y tamaño base de todo el texto ..... body (--texto)
   · Títulos de sección (h2) .................. .section h2
   · Subtítulos / introducciones .............. .lead
   · Pantalla del sobre ....................... .envelope-hint
   · Inicio (Acompáñame…) + cuenta regresiva .. .hero-title, .hero-word, .hero-countdown
   · Historia de Canaima (párrafos) ........... .story, .section--story .story
   · Frase destacada y cita ................... .story-highlight, .quote
   · Frase después de los globos .............. .frase-selva-texto
   · "Un sueño…" y regalo (fondo verde) ....... .section--dream, .gift-*
   · Fecha grande "Despegamos el" ............. .fecha-grande, .fecha-hora, .fecha-agenda
   · Cuenta regresiva (portada) ............... .countdown b, .countdown span
   · Punto de encuentro ....................... .place-date, .place-time, .place-name, .place-note
   · Dress code ............................... .dress-big, .dress p
   · Confirmación y tips ...................... .rsvp, .tips li
   · Cierre (fondo oscuro) .................... .closing-lines, .closing-quote, .closing-welcome
   Los textos sobre fondos oscuros (inicio, "Un sueño…", cierre) se
   mantienen claros a propósito: en oliva no se leerían.
   ========================================================= */

/* Butler (versión gratuita): la tipografía de los títulos. Trae los
   acentos y la ñ de fábrica, así que no hay que parchearla.
   Los archivos originales están en fuentes/butler/ */
@font-face {
  font-family: "Butler";
  src: url("fuentes/Butler-Lgt.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Butler";
  src: url("fuentes/Butler-Rmn.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Butler";
  src: url("fuentes/Butler-Med.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--sans);
  font-weight: 300;
  font-size: 1.125rem;       /* TEXTO BASE: tamaño general (antes 1rem) */
  color: var(--texto);       /* TEXTO BASE: color verde oliva */
  background: var(--beige);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
body.locked { overflow: hidden; }
body { overflow-x: clip; }   /* evita scroll lateral mientras el texto dorado rebota */

h1, h2, h3 { font-family: var(--serif); font-weight: 400; line-height: 1.1; margin: 0; }
p { margin: 0 0 1em; }
a { color: inherit; }
code { font-family: ui-monospace, Menlo, monospace; font-size: .85em; background: rgba(0,0,0,.06); padding: .1em .35em; border-radius: 3px; }

:focus-visible { outline: 2px solid var(--oro); outline-offset: 3px; }

/* ---------- Utilidades de sección ---------- */
.section {
  padding: 5rem 1.5rem;
  max-width: var(--ancho);
  margin: 0 auto;
  text-align: center;
}
.section h2 {
  font-size: clamp(2rem, 6vw, 2.8rem);
  color: var(--selva);
  margin-bottom: 1.5rem;
}
.section h2::after {
  content: "";
  display: block;
  width: 48px;
  height: 1px;
  background: var(--musgo);   /* subrayado verde oliva */
  margin: .9rem auto 0;
}
.lead {
  font-size: 1.25rem;        /* TEXTO: introducciones de sección */
  max-width: 44ch;
  margin: 0 auto 2rem;
}

.btn {
  display: inline-block;
  padding: .85rem 1.9rem;
  border: 1px solid var(--selva);
  border-radius: 999px;
  text-decoration: none;
  font-weight: 400;
  letter-spacing: .02em;
  color: var(--hueso);
  background: var(--selva);
  transition: background .2s, color .2s, transform .2s, box-shadow .2s;
}
.btn:hover { background: var(--musgo); transform: translateY(-2px); box-shadow: 0 10px 20px -8px rgba(74,77,36,.5); }
.btn:active { transform: translateY(0); box-shadow: none; }
.btn--gold { background: var(--oro); border-color: var(--oro); color: var(--selva-oscura); }
.btn--gold:hover { background: var(--oro-claro); box-shadow: 0 10px 20px -8px rgba(201,162,74,.55); }
.btn--ghost { background: transparent; color: var(--selva); }
.btn--ghost:hover { background: rgba(74,77,36,.08); }

/* Hoja de monstera (colores por defecto del símbolo) */
.leaf-body { fill: url(#leafGradA); }
.leaf-vein { stroke: #cfe3a8; opacity: .55; }

/* =========================================================
   1. SOBRE
   ========================================================= */
.envelope-screen {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 1.5rem;
  background:
    radial-gradient(ellipse at 50% 20%, rgba(167,171,95,.35), transparent 60%),
    radial-gradient(ellipse at 50% 110%, rgba(200,164,77,.18), transparent 55%),
    var(--selva-oscura);
  transition: opacity .8s ease;
}
.envelope-screen.away { opacity: 0; pointer-events: none; }

.envelope-hint {
  color: var(--niebla);
  font-size: .85rem;
  letter-spacing: .12em;
  opacity: .75;
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .35; } }

.envelope {
  position: relative;
  width: min(94vw, 620px);
  aspect-ratio: 697 / 496;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  overflow: hidden;
  filter: drop-shadow(0 30px 40px rgba(0,0,0,.45));
  transition: transform .3s ease, opacity .3s ease;
}
.envelope-img,
.envelope-video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity .6s ease, transform .6s ease;
}
.envelope-img { z-index: 1; }
.envelope-video { z-index: 2; opacity: 0; transform: scale(1.15); }
.envelope:hover { transform: scale(1.03); }
.envelope.open { pointer-events: none; }
.envelope.open .envelope-img { opacity: 0; transform: scale(1.15); }
.envelope.open .envelope-video { opacity: 1; transform: scale(1); }

/* =========================================================
   Video de la carta
   ========================================================= */
.video-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--selva-oscura);
  opacity: 0;
  pointer-events: none;
  transform: scale(.98);
  transition: opacity .6s ease, transform .6s ease;
}
.video-overlay[hidden] { display: none; }
.video-overlay.show { opacity: 1; pointer-events: auto; transform: scale(1); }
.video-overlay video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--selva-oscura);
}
/* =========================================================
   Música flotante
   ========================================================= */
.music-btn {
  position: fixed;
  right: 1rem; bottom: 1rem;
  z-index: 50;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.35);
  background: rgba(74,77,36,.92);   /* sin desenfoque de fondo: al estar fijo se recalculaba en cada scroll */
  color: var(--hueso);
  display: grid; place-items: center;
  cursor: pointer;
}
.music-btn.playing svg { animation: spin 6s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* =========================================================
   2. HERO
   ========================================================= */
.hero {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  background: var(--selva);
  color: var(--hueso);
  display: grid;
  place-items: center;
  text-align: center;
  isolation: isolate;
}
.hero-art {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: 0;
  overflow: hidden;
}
.hero-art img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 62%;
  transform: scale(1.08);
  filter: saturate(1.05) contrast(1.02);
}
.hero.reveal .hero-art img {
  animation: kenBurns 22s ease-out forwards;
}
@keyframes kenBurns {
  0%   { transform: scale(1.16) translate(0, 1%); }
  100% { transform: scale(1.02) translate(0, -1%); }
}
.hero::before {
  /* tinte olivo sobre la foto */
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(74,77,36,.38), rgba(36,37,15,.32));
  mix-blend-mode: multiply;
  z-index: 1;
}
.hero::after {
  /* velo para lectura del texto */
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,21,8,.6) 0%, rgba(20,21,8,.3) 30%, rgba(20,21,8,.42) 55%, rgba(20,21,8,.35) 70%, rgba(20,21,8,.78) 100%);
  z-index: 1;
}

/* bruma que cruza el valle */
.hero-mist {
  position: absolute; inset: 0;
  z-index: 2;
  pointer-events: none;
  overflow: hidden;
}
.hero-mist::before,
.hero-mist::after {
  content: "";
  position: absolute;
  left: -30%; width: 160%;
  background: radial-gradient(ellipse at 50% 50%, rgba(236,231,211,.26), rgba(236,231,211,0) 68%);
  filter: blur(8px);
}
.hero-mist::before {
  bottom: 6%; height: 52%;
  animation: mistDrift 28s ease-in-out infinite alternate;
}
.hero-mist::after {
  bottom: 34%; height: 34%;
  opacity: .55;
  animation: mistDrift 38s ease-in-out infinite alternate-reverse;
}
@keyframes mistDrift {
  from { transform: translate3d(-7%, 0, 0); }
  to   { transform: translate3d(7%, 0, 0); }
}

/* destellos que suben como luciérnagas */
.hero-sparks {
  position: absolute; inset: 0;
  z-index: 2;
  pointer-events: none;
}
.hero-sparks span {
  position: absolute;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,247,219,.95), rgba(227,197,121,0) 70%);
  opacity: 0;
  animation: sparkUp 11s ease-in-out infinite;
}
.hero-sparks span:nth-child(1) { left: 12%; bottom: 12%; animation-delay: 0s;    }
.hero-sparks span:nth-child(2) { left: 28%; bottom: 8%;  animation-delay: 2.4s; transform: scale(.7); }
.hero-sparks span:nth-child(3) { left: 46%; bottom: 15%; animation-delay: 4.8s; transform: scale(1.2); }
.hero-sparks span:nth-child(4) { left: 64%; bottom: 6%;  animation-delay: 1.6s; transform: scale(.8); }
.hero-sparks span:nth-child(5) { left: 79%; bottom: 14%; animation-delay: 6.2s; }
.hero-sparks span:nth-child(6) { left: 90%; bottom: 10%; animation-delay: 3.4s; transform: scale(.65); }
@keyframes sparkUp {
  0%   { opacity: 0; transform: translate3d(0, 0, 0) scale(.7); }
  12%  { opacity: .9; }
  60%  { opacity: .55; }
  100% { opacity: 0; transform: translate3d(14px, -46vh, 0) scale(1.15); }
}

.hero-content {
  position: relative;
  z-index: 3;
  padding: 3rem 1.5rem 5rem;
  opacity: 0;
  transform: translateY(14px);
  text-shadow: 0 2px 4px rgba(0,0,0,.35), 0 12px 40px rgba(0,0,0,.55);
}
.hero-content::before {
  /* halo dorado que respira detrás del título */
  content: "";
  position: absolute;
  left: 50%; top: 42%;
  z-index: -1;
  width: min(92vw, 720px);
  aspect-ratio: 1.7;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at center, rgba(227,197,121,.2), rgba(227,197,121,0) 62%);
  animation: halo 8s ease-in-out infinite;
  pointer-events: none;
}
@keyframes halo {
  0%, 100% { opacity: .7;  transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 1;   transform: translate(-50%, -50%) scale(1.09); }
}
.hero.reveal .hero-content {
  animation: heroIn 1s ease .2s forwards;
}
@keyframes heroIn { to { opacity: 1; transform: none; } }

.hero-title {
  font-family: var(--script);
  font-size: clamp(3rem, 13vw, 7rem);
  line-height: 1.15;
  letter-spacing: .01em;
  font-weight: 400;
  margin: 0;
}
.hero-word {
  display: block;
  opacity: 0;
  transform: translateY(30px) scale(.97);
}
.hero-word--small {
  font-size: .52em;
  color: var(--niebla);
  margin: .02em 0;
}
.hero-word--gold {
  /* brillo dorado que recorre la palabra */
  background: linear-gradient(100deg,
    var(--oro) 0%,
    var(--oro-claro) 28%,
    #fff6dd 46%,
    var(--oro-claro) 64%,
    var(--oro) 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: sheen 7s ease-in-out infinite;
}
@keyframes sheen {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}
.hero.reveal .hero-word { animation: wordIn 1.1s cubic-bezier(.2,.75,.25,1) forwards; }
.hero.reveal .hero-word:nth-child(1) { animation-delay: .35s; }
.hero.reveal .hero-word:nth-child(2) { animation-delay: .55s; }
.hero.reveal .hero-word:nth-child(3) { animation-delay: .75s; }
@keyframes wordIn { to { opacity: 1; transform: none; } }
/* la palabra dorada conserva su animación de brillo al entrar */
.hero.reveal .hero-word--gold {
  animation:
    wordIn 1.1s cubic-bezier(.2,.75,.25,1) .75s forwards,
    sheen 7s ease-in-out 1.8s infinite;
}

/* cuenta regresiva en vidrio */
.hero-countdown {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(.35rem, 1.8vw, .85rem);
  max-width: 470px;
  margin: clamp(2.2rem, 7vw, 3.4rem) auto 0;
}
.hero-countdown > div {
  position: relative;
  padding: clamp(.75rem, 3vw, 1.15rem) .25rem clamp(.6rem, 2vw, .85rem);
  border-radius: 14px;
  border: 1px solid rgba(227,197,121,.3);
  background: linear-gradient(180deg, rgba(248,245,233,.14), rgba(36,37,15,.24));
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 10px 26px rgba(0,0,0,.32);
  opacity: 0;
  transform: translateY(20px);
}
.hero-countdown > div::before {
  /* filo de luz en el borde superior */
  content: "";
  position: absolute;
  left: 20%; right: 20%; top: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--oro-claro), transparent);
}
.hero-countdown b {
  display: block;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(1.8rem, 7.5vw, 3rem);
  line-height: 1;
  color: var(--hueso);
  font-variant-numeric: lining-nums tabular-nums;
  text-shadow: 0 0 18px rgba(227,197,121,.3), 0 2px 6px rgba(0,0,0,.5);
}
.hero-countdown span {
  display: block;
  margin-top: .4rem;
  font-size: clamp(.52rem, 2.1vw, .64rem);
  letter-spacing: .16em;
  color: var(--oro-claro);
  opacity: .85;
}
.hero.reveal .hero-countdown > div { animation: cdIn .9s cubic-bezier(.2,.75,.25,1) forwards; }
.hero.reveal .hero-countdown > div:nth-child(1) { animation-delay: 1s; }
.hero.reveal .hero-countdown > div:nth-child(2) { animation-delay: 1.1s; }
.hero.reveal .hero-countdown > div:nth-child(3) { animation-delay: 1.2s; }
.hero.reveal .hero-countdown > div:nth-child(4) { animation-delay: 1.3s; }
@keyframes cdIn { to { opacity: 1; transform: none; } }

/* pulso del segundero, sincronizado desde el JS */
.hero-countdown b.tic { animation: tic .85s ease-out; }
@keyframes tic {
  0%   { transform: scale(1.1); text-shadow: 0 0 26px rgba(227,197,121,.8), 0 2px 6px rgba(0,0,0,.5); }
  100% { transform: scale(1); }
}
.hero-countdown .cd-now { color: var(--hueso); }
.scroll-cue {
  position: absolute;
  left: 50%; bottom: 1.8rem;
  z-index: 3;
  width: 22px; height: 36px;
  transform: translateX(-50%);
  border: 1px solid rgba(255,255,255,.55);
  border-radius: 12px;
}
.scroll-cue span {
  position: absolute; left: 50%; top: 7px;
  width: 3px; height: 8px;
  margin-left: -1.5px;
  background: var(--oro-claro);
  border-radius: 2px;
  animation: cue 1.8s ease-in-out infinite;
}
@keyframes cue { 50% { transform: translateY(12px); opacity: .3; } }

/* =========================================================
   4. HISTORIA / 9. SUEÑO
   ========================================================= */
.section--story, .section--dream { max-width: 600px; }

/* --- La leyenda: título caligráfico grande y texto justificado --- */
.section--story h2 {
  font-family: var(--script);
  /* El título mide 15,1 veces el tamaño de fuente, así que ancho/15,1 es el
     tamaño con el que entra en una sola línea. En teléfono parte igual por
     más que se achique, así que ahí se prioriza el tamaño (ver media query). */
  font-size: min(5.9vw, 66px);
  line-height: 1.15;
  letter-spacing: .01em;
  font-weight: 400;
  margin-bottom: 0;
  /* se sale del contenedor de 600px para que quepa en una línea */
  width: min(92vw, 1060px);
  margin-left: calc(50% - min(46vw, 530px));
}
.section--story h2::after { margin-top: 1.3rem; }
.section--story .story {
  text-align: justify;
  text-align-last: center;
  -webkit-hyphens: auto;
  hyphens: auto;
  font-size: clamp(1.45rem, 5.4vw, 1.85rem);   /* TEXTO: párrafos de la historia */
  line-height: 1.62;
}

/* Aparecer y desvanecerse con el scroll, de a un bloque por vez.
   El estado oculto y la separación solo se aplican si el JS arrancó
   (.js-anim), para que el texto siga siendo legible si el script falla. */
.js-anim .scroll-fade {
  opacity: 0;
  transform: translateY(28px);
  /* sin desenfoque: animar blur sobre texto grande traba el scroll en teléfonos */
  transition:
    opacity .8s ease,
    transform .8s cubic-bezier(.2,.7,.2,1);
}
.js-anim .scroll-fade.en-vista {
  opacity: 1;
  transform: none;
}
/* separación para que solo un bloque caiga en el centro */
.js-anim .section--story .scroll-fade {
  margin-block: clamp(80px, 14vh, 160px);
}

/* =========================================================
   Globos
   ========================================================= */
.globos {
  position: relative;
  /* una pantalla + el recorrido del video: mientras se recorre, el bloque
     queda fijo (así los bordes del video son los de la pantalla y ningún
     globo queda cortado). Cuanto menor este número, más rápido va el video. */
  height: calc(100svh + 40svh);
  /* se come parte del espacio vacío bajo el párrafo anterior */
  margin-top: calc(-1 * clamp(70px, 12vh, 140px));
}
.globos-fijo {
  position: sticky;
  top: 0;
  /* por delante de las secciones siguientes: al subir, el texto se esconde
     bajo el techo de globos en vez de pasar por encima */
  z-index: 3;
  height: 100svh;
  /* visible: los globos se quedan arriba (techo) aunque el bloque ya pasó */
  overflow: visible;
}
.globos-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  /* El fondo crema ya viene grabado en el archivo (video/globos-crema.mp4),
     sin marca de agua. Si se cambia el color --beige, hay que regenerarlo:
     python3 herramientas/globos_difuminado.py */
  /* difuminado tenue y corto en el borde de abajo: los globos se desvanecen
     en los últimos ~10% de la pantalla en vez de cortarse en seco */
  -webkit-mask-image: linear-gradient(to bottom, #000 90%, rgba(0, 0, 0, .55) 96%, rgba(0, 0, 0, 0) 100%);
          mask-image: linear-gradient(to bottom, #000 90%, rgba(0, 0, 0, .55) 96%, rgba(0, 0, 0, 0) 100%);
}

/* =========================================================
   Frase después de los globos
   ========================================================= */
.frase-selva {
  position: relative;
  /* lámina de una pantalla con la frase centrada, debajo de los globos:
     no se solapa con ellos, así su entrada se ve completa */
  margin-top: 6svh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 4rem 1.25rem;
  /* sin fondo propio (se ve el beige de la página): si tuviera, taparía el
     final de los globos y cortaría el difuminado en seco */
}
/* Destellos repartidos por toda la pantalla de la frase */
.destellos {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.destello {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  aspect-ratio: 1;
  /* halo alrededor del destello */
  background: radial-gradient(circle, rgba(255,241,196,.95), rgba(227,197,121,.45) 38%, rgba(227,197,121,0) 68%);
  filter: drop-shadow(0 0 6px rgba(227,197,121,.85));
  opacity: 0;
  animation: destello var(--t, 3.4s) ease-in-out var(--d, 0s) infinite;
}
.destello::after {
  /* estrella de cuatro puntas */
  content: "";
  position: absolute;
  inset: 14%;
  background: var(--c);
  clip-path: polygon(50% 0%, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0% 50%, 40% 40%);
}
@keyframes destello {
  0%, 100% { opacity: 0; transform: scale(.2) rotate(0deg); }
  45%      { opacity: 1; transform: scale(1.15) rotate(30deg); }
  60%      { opacity: 1; transform: scale(.95) rotate(45deg); }
}

.frase-selva-texto {
  margin: 0;
  max-width: 15ch;
  font-family: var(--script);
  font-size: clamp(2.6rem, 9.5vw, 4.6rem);
  line-height: 1.45;
  color: var(--texto);
  text-align: center;
}
/* Entrada letra por letra, de izquierda a derecha (solo opacidad: así la
   caligrafía sigue enlazada), y después una onda de color oliva ↔ dorado
   que recorre la frase. No vuelve a desaparecer. */
.frase-selva-texto {
  transition: transform .9s cubic-bezier(.2,.7,.2,1);
}
.frase-selva-texto .letra {
  opacity: 0;
}
/* el bloque entra subiendo un poco mientras aparecen las letras */
.js-anim .frase-selva-texto { transform: translateY(24px); }
.js-anim .frase-selva-texto.entra { transform: none; }
.frase-selva-texto.entra .letra {
  animation:
    letra-entra .5s ease-out calc(var(--i) * 32ms) forwards,
    letra-color 3.2s ease-in-out calc(var(--i) * 32ms + .6s) infinite alternate;
}
@keyframes letra-entra {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes letra-color {
  0%, 30% { color: var(--texto); }    /* verde oliva */
  70%, 100% { color: #a8801f; }       /* dorado */
}

.story {
  text-align: left;
  font-family: var(--serif);
  font-size: 1.38rem;        /* TEXTO: párrafos de historia y sueño */
  line-height: 1.6;
}
.story p { margin-bottom: 1.1em; }
.story-highlight {
  font-style: italic;
  color: var(--musgo);
  font-size: 1.35rem;
  text-align: center;
  padding: .6em 0;
}
.quote {
  margin: 2.5rem 0 0;
  padding: 1.6rem 1.2rem;
  border-top: 1px solid var(--oro);
  border-bottom: 1px solid var(--oro);
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.5rem;
  color: var(--selva);
  line-height: 1.3;
}

.section--dream {
  max-width: none;
  background: var(--selva);
  color: var(--niebla);
  padding-left: 0; padding-right: 0;
}
.section--dream > * { max-width: 600px; margin-left: auto; margin-right: auto; padding-left: 1.5rem; padding-right: 1.5rem; }
.section--dream h2 { color: var(--hueso); }
.section--dream .story-highlight { color: var(--oro-claro); }

.gift {
  margin-top: 3rem;
  padding-top: 2.5rem;
  border-top: 1px solid rgba(200,164,77,.4);
  text-align: left;
}
.gift-tradition {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.5rem;
  color: var(--oro-claro);
  text-align: center;
  margin-bottom: 1.5rem;
}
.gift-account {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: .5rem 1rem;
  margin: 1.6rem 0;
  padding: 1.2rem 1.4rem;
  border: 1px solid rgba(200,164,77,.5);
  border-radius: 8px;
  background: rgba(0,0,0,.18);
}
.gift-account span { font-size: .7rem; letter-spacing: .14em; color: var(--oro-claro); align-self: center; }
.gift-account b { font-weight: 400; font-family: var(--serif); font-size: 1.15rem; }
/* botón "Copiar" de cada dato (lo agrega el JS) */
.copiar {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  align-self: center;
  padding: .3rem .7rem;
  border: 1px solid rgba(200,164,77,.6);
  border-radius: 999px;
  background: transparent;
  color: var(--oro-claro);
  font: inherit;
  font-size: .72rem;
  letter-spacing: .08em;
  cursor: pointer;
  transition: background .2s, color .2s;
}
.copiar svg { width: 13px; height: 13px; flex: none; }
.gift-account .copiar span { color: inherit; font-size: inherit; letter-spacing: inherit; }   /* no hereda el estilo de las etiquetas */
.copiar:hover, .copiar:focus-visible { background: rgba(200,164,77,.18); }
.copiar.copiado { background: var(--oro); border-color: var(--oro); color: var(--selva-oscura); }
.copiar .ico-listo { display: none; }
.copiar.copiado .ico-copiar { display: none; }
.copiar.copiado .ico-listo { display: block; }
@media (max-width: 680px) {
  /* en móvil solo el ícono: el texto no cabe al lado del dato */
  .gift-account { padding: 1rem; gap: .5rem .8rem; }
  .copiar { padding: .45rem; }
  .copiar svg { width: 16px; height: 16px; }
  .copiar span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
.gift-final {
  font-family: var(--serif);
  font-size: 1.3rem;
  text-align: center;
  color: var(--hueso);
}

/* ---------- Lámina "Por eso… / Porque cumplir 30…" ----------
   Ocupa su propia pantalla con el contenido centrado en vertical. */
.lamina-viaje {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* la foto de monstera va de fondo y ocupa TODO el ancho de la pantalla:
     por eso esta sección no lleva el ancho máximo de .section */
  max-width: none;
  width: 100%;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
/* el texto sí se queda en la columna centrada de siempre */
.lamina-viaje > .story {
  width: 100%;
  max-width: var(--ancho);
}
.lamina-viaje-foto,
.lamina-viaje-velo {
  position: absolute;
  inset: 0;
  z-index: -1;            /* siempre detrás del texto */
  pointer-events: none;
}
.lamina-viaje-foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* velo verde oscuro parejo: deja ver las hojas y el texto se lee claro.
   Sin difuminado en los bordes: la foto arranca y termina de golpe. */
.lamina-viaje-velo {
  background: rgba(36,37,15,.78);
}
/* sobre la foto el texto va en crema, no en verde oliva */
.lamina-viaje .story,
.lamina-viaje .story p { color: var(--hueso); }

/* ---------- Entrada de izquierda a derecha, palabra por palabra ----------
   Cada palabra la envuelve el JS en <span class="palabra" style="--i:n">. */
.palabra {
  display: inline-block;
  white-space: pre;
}
.js-anim .entra-palabras .palabra {
  opacity: 0;
  transform: translateX(-16px);
}
.js-anim .entra-palabras.entra .palabra {
  animation: palabra-entra .55s cubic-bezier(.22, .61, .36, 1) calc(var(--i) * 45ms) forwards;
}
@keyframes palabra-entra {
  to { opacity: 1; transform: none; }
}

/* =========================================================
   TEXTO DORADO — "Por eso, mi cumpleaños será…"
   Basado en "CSS scroll-triggered animations" de Ryan Mulligan
   (codepen.io/hexagoncircle/pen/wvOPmGO), con degradado dorado en
   vez del multicolor.
   ========================================================= */
.texto-dorado {
  /* arranca en amarillo dorado y termina en blanco (el brillo recorre
     el degradado de izquierda a derecha mientras aparece la palabra) */
  --oro-degradado: linear-gradient(90deg,
    #c9a24a 0%, #e3c579 20%, #f6e3b4 42%, #fdf6e4 62%, #ffffff 78%, #ffffff 100%);
  font-weight: 400;
}
/* con JS el degradado va palabra por palabra (así cada una puede aparecer
   sola); sin JS, el párrafo entero lo lleva igual */
.texto-dorado .palabra,
.texto-dorado:not(.entra-palabras) {
  background-image: var(--oro-degradado);
  background-size: 300% 100%;
  background-position: 0% center;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* al aparecer, un brillo recorre cada palabra */
.js-anim .entra-palabras.texto-dorado.entra .palabra {
  animation:
    palabra-entra .55s cubic-bezier(.22, .61, .36, 1) calc(var(--i) * 45ms) forwards,
    dorado-brillo 1.1s ease-out calc(var(--i) * 45ms) forwards;
}
@keyframes dorado-brillo {
  from { background-position: 0% center; }
  to   { background-position: 100% center; }
}

/* =========================================================
   Uniones entre secciones
   ---------------------------------------------------------
   Un degradado corto en el borde de las secciones que tienen fondo propio
   (video, foto o verde), para que se fundan con la sección vecina y no se
   vea una raya. Cada borde se funde con el color del vecino.
   ========================================================= */
.fecha-fijo::before,  .fecha-fijo::after,
.lamina-viaje::before, .lamina-viaje::after,
.section--dream::after,
.closing::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: var(--costura);   /* corto: solo la costura */
  pointer-events: none;
  z-index: 1;
}
/* bordes que dan contra el crema de la página */
.fecha-fijo::before,
.lamina-viaje::before,
.closing::before {
  top: 0;
  background: linear-gradient(to bottom, var(--beige), rgba(244, 236, 220, 0));
}
.fecha-fijo::after,
.section--dream::after {
  bottom: 0;
  background: linear-gradient(to top, var(--beige), rgba(244, 236, 220, 0));
}
/* la lámina de hojas da contra el verde de "Un sueño…": se funde con ese verde */
.lamina-viaje::after {
  bottom: 0;
  background: linear-gradient(to top, var(--selva), rgba(74, 77, 36, 0));
}
.section--dream { position: relative; }

/* =========================================================
   5. FECHA — "Despegamos el" (fondo verde oliva)
   TEXTO: .fecha-grande (la fecha), .fecha-hora, .fecha-agenda
   ========================================================= */
.section.section--count {
  /* ancho completo y un tramo de scroll: mientras se recorre, el contenido
     queda fijo y el video avanza (o se devuelve) con el scroll.
     Va con doble clase para ganarle al padding de .section de más abajo. */
  max-width: none;
  width: 100%;
  padding: 0;
  position: relative;
  color: var(--hueso);
}
.fecha-fijo {
  position: relative;
  /* una pantalla completa MÁS lo que cubren los dos degradados de los bordes,
     para que el video se siga viendo entero */
  min-height: calc(100svh + var(--costura) * 2);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem 1.5rem;
  overflow: hidden;
  isolation: isolate;
  background: #1a1a18;      /* oscuro de respaldo, por si el video no carga */
}
.fecha-bloque {
  width: 100%;
  max-width: var(--ancho);
  text-shadow: 0 2px 16px rgba(0,0,0,.75), 0 1px 3px rgba(0,0,0,.5);
}
.section--count h2 {
  color: var(--hueso);
  font-size: clamp(1.6rem, 5vw, 2.2rem);
  letter-spacing: .04em;
  margin-bottom: .6rem;
}
.section--count h2::after { background: var(--oro-claro); }

/* la fecha, en grande */
.fecha-grande {
  /* aire entre el 28 y el "Despegamos el" */
  margin: 1.6rem 0 .3rem;
  line-height: 1;
}
.fecha-dia {
  display: block;
  font-family: var(--script);
  font-size: clamp(4.5rem, 20vw, 9rem);
  line-height: 1;
  color: var(--oro-claro);
}
.fecha-mes {
  display: block;
  font-family: var(--serif);
  font-size: clamp(1.5rem, 6vw, 2.4rem);
  letter-spacing: .02em;
  margin-top: .4rem;
}
.fecha-hora {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 6vw, 2.4rem);   /* igual que "de octubre de 2026" */
  letter-spacing: .06em;
  text-transform: uppercase;
  opacity: .85;
  margin-bottom: 2.6rem;
}

/* guárdalo en tu agenda */
.fecha-agenda {
  font-family: var(--serif);
  font-size: clamp(1.3rem, 4.5vw, 1.7rem);
  margin-bottom: 1.1rem;
}
.agenda-btns {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem;
  justify-content: center;
}
.agenda-btns .btn { font-size: .95rem; }
/* botón claro, para que se lea sobre el verde */
.btn--claro {
  background: transparent;
  color: var(--hueso);
  border-color: var(--hueso);
}
.btn--claro:hover { background: rgba(248,245,233,.14); }

/* ---------- Video del avión de fondo ---------- */
.fecha-video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
/* sin tinte verde: el video se ve con sus colores. Al revelarse el texto
   entra una sombra neutra, solo la necesaria para que la fecha se lea. */
.fecha-velo {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: rgba(0, 0, 0, 0);
  /* entra despacio y suave, para que casi no se note el cambio */
  transition: background 2.8s cubic-bezier(.33, 0, .2, 1);
}
.section--count.revelado .fecha-velo {
  background: linear-gradient(180deg, rgba(16,16,14,.18) 0%, rgba(16,16,14,.44) 45%, rgba(16,16,14,.18) 100%);
}

/* el texto espera a que pase el avión */
.js-anim .section--count .fecha-bloque > * {
  opacity: 0;
  transform: translateY(18px);
}
.js-anim .section--count.revelado .fecha-bloque > * {
  animation: fecha-entra .9s ease-out forwards;
}
.js-anim .section--count.revelado h2            { animation-delay: 0s; }
.js-anim .section--count.revelado .fecha-grande { animation-delay: .25s; }
.js-anim .section--count.revelado .fecha-hora   { animation-delay: .5s; }
.js-anim .section--count.revelado .fecha-agenda { animation-delay: .9s; }
.js-anim .section--count.revelado .agenda-btns  { animation-delay: 1.1s; }
@keyframes fecha-entra {
  to { opacity: 1; transform: none; }
}

.countdown {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .75rem;
}
.countdown div {
  padding: 1.2rem .4rem;
  border: 1px solid rgba(74,77,36,.2);
  border-radius: 8px;
}
.countdown b {
  display: block;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(2.2rem, 8vw, 3.6rem);
  line-height: 1;
  color: var(--selva);
  font-variant-numeric: tabular-nums;
}
.countdown span { font-size: .82rem; letter-spacing: .18em; color: var(--texto); }   /* TEXTO: días/horas/minutos */
.cd-now { font-family: var(--serif); font-size: 1.8rem; color: var(--selva); grid-column: 1 / -1; }

/* =========================================================
   6. LUGAR
   ========================================================= */
.section--place { max-width: 900px; }
.place {
  display: grid;
  grid-template-columns: 1fr 1.3fr;
  gap: 2rem;
  align-items: stretch;
  text-align: left;
}
.place-info {
  display: flex; flex-direction: column; justify-content: center;
  padding: 1.5rem;
  border-left: 3px solid var(--oro);
}
.place-date {
  font-family: var(--serif);
  font-size: 1.35rem;        /* TEXTO: día y mes del evento */
  line-height: 1.15;
  color: var(--texto);
  margin-bottom: .6rem;
}
.place-date strong { font-weight: 300; font-size: 4rem; display: block; color: var(--selva); line-height: 1; }
.place-time { font-size: 1.15rem; letter-spacing: .14em; margin-bottom: 1.2rem; }   /* TEXTO: hora */
.place-name { font-family: var(--serif); font-size: 2.2rem; color: var(--selva); margin: 0; }
.place-city { opacity: .7; margin-bottom: 1.4rem; }
.place-map { border-radius: 12px; overflow: hidden; min-height: 320px; }
.place-map iframe { width: 100%; height: 100%; min-height: 320px; border: 0; filter: saturate(.75); }
.place-note {
  margin-top: 2.5rem;
  font-size: 1.1rem;         /* TEXTO: nota del consumo individual */
  max-width: 56ch;
  margin-left: auto; margin-right: auto;
  padding: 1.2rem 1.4rem;
  background: var(--niebla);
  border-radius: 8px;
}

/* =========================================================
   8. DRESS CODE
   ========================================================= */
.section--dress { max-width: 700px; }
.dress {
  max-width: 480px;
  margin: 0 auto;
}
.dress-big {
  font-family: var(--serif);
  font-size: 1.7rem;
  color: var(--selva);
  margin-bottom: .4rem;
}

/* =========================================================
   Copa de la selva vista desde abajo (de "Fiesta de blanco" a "¿Abordas conmigo?")
   El marco queda fijo en pantalla mientras se recorren esas secciones:
   troncos que suben desde los bordes y follaje que enmarca los lados.
   RELIEVE: tres capas por lado (c1 atrás, c2 medio, c3 adelante). Con el
   scroll, el JS pone --p (de -1 a 1) y cada capa se desplaza distinto:
   la de adelante corre más y la de atrás casi no se mueve.
   BRILLO de cada capa: el brightness() de .copa--c1/c2/c3 (1 = original).
   ========================================================= */
.selva-lados {
  position: relative;
  overflow: clip;           /* clip (no hidden) para que funcione el sticky */
}
.selva-lados > .section { position: relative; z-index: 1; }
/* "¿Abordas conmigo?" tiene fondo propio: la copa se pinta sobre ese fondo
   pero debajo del texto y los botones */
.selva-lados > .section--rsvp { position: static; }
.selva-lados > .section--rsvp > * { position: relative; z-index: 1; }
.selva-copa {
  --p: 0;
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  /* entra y sale suave en los bordes del tramo */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 140px, #000 calc(100% - 140px), transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 140px, #000 calc(100% - 140px), transparent);
}
.selva-copa-marco {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
}
.copa {
  --viaje: 0px;             /* cuánto se desplaza la capa en todo el tramo */
  --ancho: min(30vw, 44vh);
  position: absolute;
  top: calc(var(--viaje) * -1);
  height: calc(100% + var(--viaje) * 2);
  width: var(--ancho);
  object-fit: cover;
  will-change: transform;
  transform: translate3d(0, calc(var(--p) * var(--viaje) * -1), 0);
}
.copa--i { left: 0;  object-position: left center;
  -webkit-mask-image: linear-gradient(to right, #000 80%, transparent); mask-image: linear-gradient(to right, #000 80%, transparent); }
.copa--d { right: 0; object-position: right center;
  -webkit-mask-image: linear-gradient(to left, #000 80%, transparent);  mask-image: linear-gradient(to left, #000 80%, transparent); }

/* atrás: lejos, más oscura y casi quieta */
.copa--c1 { --viaje: 30px; filter: brightness(.45); }
/* medio: ramas y follaje */
.copa--c2 { --viaje: 90px; filter: brightness(.55) saturate(.85); }
/* adelante: más cerca, algo más grande y corre más */
.copa--c3 { --viaje: 190px; --ancho: min(33vw, 48vh);
  filter: brightness(.6) saturate(.85); }

/* vaivén suave de las hojas de adelante */
.copa--c3.copa--i { transform-origin: 0 50%;    animation: copa-vaiven 9s ease-in-out infinite alternate; }
.copa--c3.copa--d { transform-origin: 100% 50%; animation: copa-vaiven 11s ease-in-out -3s infinite alternate; }
@keyframes copa-vaiven {
  from { rotate: -.8deg; }
  to   { rotate: .8deg; }
}
@media (max-width: 680px) {
  /* en móvil solo asoma el borde de la copa para no tapar el texto */
  .copa { --ancho: 10vw; }
  .copa--c3 { --ancho: 12vw; }
  .selva-lados > .section { padding-left: calc(10vw + .5rem); padding-right: calc(10vw + .5rem); }
}
@media (prefers-reduced-motion: reduce) {
  .copa--c3.copa--i, .copa--c3.copa--d { animation: none; }
}
}

/* =========================================================
   10. RSVP / 11. TIPS
   ========================================================= */
.section--rsvp { background: var(--niebla); max-width: none; }
.rsvp { display: flex; gap: .8rem; justify-content: center; flex-wrap: wrap; }

.tips {
  list-style: none;
  padding: 0;
  margin: 0 auto;
  max-width: 420px;
  text-align: left;
}
.tips li {
  padding: .8rem 0 .8rem 1.6rem;
  border-bottom: 1px solid rgba(74,77,36,.12);
  position: relative;
}
.tips li::before {
  content: "";
  position: absolute; left: 0; top: 1.3rem;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--oro);
}

/* =========================================================
   12. CIERRE
   ========================================================= */
.closing {
  position: relative;
  overflow: hidden;
  background: var(--selva-oscura);
  color: var(--hueso);
  text-align: center;
  padding: 6rem 1.5rem 7rem;
}
.closing-leaf {
  position: absolute;
  width: 220px;
  left: -70px; bottom: -60px;
  transform: rotate(35deg);
  opacity: .55;
}
.closing-leaf--r { left: auto; right: -70px; top: -60px; bottom: auto; transform: rotate(-150deg); }
.closing-leaf .leaf-body { fill: url(#leafGradB); }
.closing-lines {
  font-family: var(--serif);
  font-size: clamp(1.4rem, 4.5vw, 2rem);
  line-height: 1.35;
  position: relative;
}
.closing-quote {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.6rem, 6vw, 2.6rem);
  color: var(--oro-claro);
  margin: 2rem 0;
  position: relative;
}
.closing-welcome {
  max-width: 40ch;
  margin: 0 auto;
  opacity: .8;
  position: relative;
}

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 680px) {
  .section { padding: 4rem 1.25rem; }
  .place { grid-template-columns: 1fr; }
  .place-info { border-left: 0; border-top: 3px solid var(--oro); align-items: center; text-align: center; }
  .countdown { gap: .5rem; }
  .countdown div { padding: .9rem .2rem; }
  /* En pantalla angosta el título parte en varias líneas a cualquier tamaño,
     así que conviene que sea grande en vez de encogerlo sin ganar nada. */
  .section--story h2 { font-size: min(14vw, 62px); }
}

/* =========================================================
   Movimiento reducido
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .envelope-hint, .scroll-cue span, .music-btn.playing svg { animation: none; }
  .envelope, .envelope-screen, .envelope-img, .envelope-video, .video-overlay { transition-duration: .01s; transition-delay: 0s; }
  .frase-selva-texto.entra .letra { animation: none; opacity: 1; }
  .destello { animation: none; opacity: .5; }
  .js-anim .section--count .fecha-bloque > * { animation: none; opacity: 1; transform: none; }
  .js-anim .entra-palabras .palabra { animation: none; opacity: 1; transform: none; }
  .hero.reveal .hero-content { animation: none; opacity: 1; transform: none; }
  .hero.reveal .hero-art img { animation: none; transform: scale(1.08); }
  .hero-content::before, .hero-mist::before, .hero-mist::after { animation: none; }
  .hero-sparks { display: none; }
  .hero.reveal .hero-word,
  .hero.reveal .hero-word--gold,
  .hero.reveal .hero-countdown > div { animation: none; opacity: 1; transform: none; }
  .hero-countdown b.tic { animation: none; }
}

/* =========================================================
   Aves que cruzan la pantalla (guacamayo y turpial) — ver aves.js
   ========================================================= */
.ave {
  position: fixed;
  top: 0; left: 0;
  z-index: 40;              /* sobre el contenido, debajo del botón de música */
  pointer-events: none;
  will-change: transform;
}
.ave svg { display: block; width: 100%; height: auto; overflow: visible;
  filter: drop-shadow(0 6px 6px rgba(20, 20, 8, .25)); }
.ave img { display: block; width: 100%; height: auto; }
.ave--izq svg, .ave--izq img { transform: scaleX(-1); }
/* aleteo: las alas giran desde el hombro (105, 52 en el dibujo) */
.ave-ala {
  transform-box: view-box;
  transform-origin: 105px 52px;
  animation: ave-aleteo .34s ease-in-out infinite alternate;
}
.ave-ala--atras { animation-delay: -.04s; }
.ave-cuerpo {
  transform-box: view-box;
  animation: ave-balanceo .34s ease-in-out infinite alternate;
}
.ave--turpial .ave-ala, .ave--turpial .ave-cuerpo { animation-duration: .2s; }
@keyframes ave-aleteo {
  from { transform: rotate(14deg) scaleY(1); }
  to   { transform: rotate(-78deg) scaleY(.8); }
}
@keyframes ave-balanceo {
  from { transform: translateY(-2px); }
  to   { transform: translateY(3px); }
}
