/* ============================================================================
   PREMIUM.CSS  —  sobre 3D, scrollytelling, foil, micro-interacciones
   Se carga DESPUÉS de styles.css y puede sobrescribirlo.
   Regla de oro: animar solo transform y opacity (GPU, sin jank en mobile).
   ========================================================================== */

:root {
  --foil: linear-gradient(120deg, #a9822f 0%, #d9b45e 22%, #f6e6ad 42%, #e7c56f 60%, #b8912f 82%, #dcb85e 100%);
  --ease-soft: cubic-bezier(.22, .8, .28, 1);
}

/* ============================================================================
   BARRA DE PROGRESO (dorado foil)
   ========================================================================== */
.progress-bar {
  position: fixed; top: 0; left: 0; height: 3px; width: 100%;
  transform: scaleX(0); transform-origin: 0 50%;
  background: var(--foil); background-size: 200% 100%;
  z-index: 130; pointer-events: none;
  box-shadow: 0 0 10px rgba(201,168,74,.5);
}
@supports (animation-timeline: scroll(root)) {
  .progress-bar { animation: growX linear both; animation-timeline: scroll(root block); }
}
@keyframes growX { to { transform: scaleX(1); } }

/* ============================================================================
   GRANO / TEXTURA (sutil, sobre todo)
   ========================================================================== */
.grain {
  position: fixed; inset: 0; z-index: 140; pointer-events: none; opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* ============================================================================
   CURSOR CUSTOM (solo desktop con puntero fino)
   ========================================================================== */
.cursor { display: none; }
@media (hover: hover) and (pointer: fine) {
  /* Punto discreto en lugar del anillo gigante: acompaña, no tapa.
     Sin mix-blend-mode difference, que lo volvía chillón sobre las fotos. */
  .cursor {
    display: block; position: fixed; top: 0; left: 0; z-index: 500;
    width: 30px; height: 30px; margin: -15px 0 0 -15px; border-radius: 50%;
    border: 1.5px solid transparent; opacity: .55;
    pointer-events: none; will-change: transform;
    /* solo border-color/opacity/transform: nada que provoque reflow */
    transition: border-color .25s ease, opacity .25s ease;
  }
  .cursor::before {
    content: ""; position: absolute; left: 50%; top: 50%;
    width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%;
    background: var(--accent);
    transition: transform .25s var(--ease-soft), opacity .25s ease;
  }
  /* sobre algo clicable: el punto se repliega y aparece el anillo */
  .cursor.grow { border-color: var(--accent); opacity: .85; }
  .cursor.grow::before { transform: scale(.35); opacity: 0; }
  /* Solo ocultamos el cursor nativo si el JS activó el custom (evita quedarse sin cursor si algo falla) */
  html.has-cursor, html.has-cursor a, html.has-cursor button,
  html.has-cursor .gallery__item, html.has-cursor label { cursor: none; }
  /* en los campos vuelve el cursor nativo: escribir con un puntito es incómodo */
  html.has-cursor input, html.has-cursor select, html.has-cursor textarea { cursor: auto; }
  html.has-cursor input[type="radio"] { cursor: pointer; }
}

/* ============================================================================
   SOBRE QUE SE ABRE
   ========================================================================== */
.env {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: 1.5rem;
  background: var(--bg);
  background: radial-gradient(120% 90% at 50% 28%, var(--bg-alt), var(--bg));
  transition: opacity 1s ease, visibility 1s ease;
}
.env.is-open { opacity: 0; visibility: hidden; }

/* ===== Clip de apertura a pantalla completa =====
   Aparece cuando el lacre se rompe y toma el relevo de la animación CSS. */
.env__video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 12;
  opacity: 0; visibility: hidden;
  transition: opacity .45s ease;
  background: var(--bg);
}
.env.playing .env__video { opacity: 1; visibility: visible; }
/* Antes de cortar al clip, el sobre se acerca a la cámara: el corte deja de
   sentirse un salto y parece que la cámara entra en el sobre. */
.env.playing .env__stage {
  opacity: 0; transform: scale(1.35);
  transition: opacity .5s ease, transform .75s cubic-bezier(.4,0,.6,1);
  pointer-events: none;
}
.env.playing .env__vignette { opacity: 0; }
.env__stage { transition: transform .5s ease; will-change: transform; }
.env__vignette { position: absolute; inset: 0; box-shadow: inset 0 0 180px rgba(0,0,0,.28); pointer-events: none; }
.env__stage { position: relative; display: flex; flex-direction: column; align-items: center; gap: clamp(1.1rem, 4vh, 2.2rem); width: 100%; }
.env__eyebrow {
  font-family: var(--font-body); font-size: .7rem; letter-spacing: .32em; text-transform: uppercase;
  color: var(--text-soft); opacity: 0; animation: fadeUp .8s ease .2s forwards;
}

.envelope {
  /* PROTAGONISTA: ocupa casi toda la pantalla. El tope por altura evita que se
     corte en apaisado; el de 760px, que se vuelva absurdo en un monitor 4K. */
  position: relative;
  width: min(94vw, 72vh, 760px);
  aspect-ratio: 3 / 2;
  perspective: 1800px; cursor: pointer;
  background: var(--bg-alt);
  border-radius: 6px;
  box-shadow: var(--shadow);
  opacity: 0; transform: translateY(18px) scale(.96);
  animation: envIn .9s var(--ease-soft) .1s forwards;
}
@keyframes envIn { to { opacity: 1; transform: none; } }

/* INTERIOR DEL SOBRE: al girar la solapa quedaba a la vista la carta blanca y
   se veía "un recuadro abierto". En un sobre real ahí se ve el interior en
   sombra. Ocupa la V superior, justo la zona que destapa la solapa. */
.envelope::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 66%;
  z-index: 3; pointer-events: none;
  background: linear-gradient(180deg, #3a2c21 0%, #5c4838 60%, #705745 100%);
  /* MISMA forma y altura que la solapa: así queda perfectamente tapado
     mientras está cerrada, y sólo aparece cuando la solapa gira */
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  box-shadow: inset 0 8px 20px rgba(0,0,0,.5);
}

.envelope__shadow {
  position: absolute; left: 8%; bottom: -26px; width: 84%; height: 26px;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.35), transparent 70%);
  filter: blur(3px); transition: transform .9s var(--ease-soft), opacity .9s; z-index: 0;
}

/* La carta (detrás, sube al abrir) */
.envelope__letter {
  position: absolute; left: 7%; bottom: 6%; width: 86%; height: 88%;
  background: linear-gradient(180deg, #fffdf9, #f7f1e6);
  border-radius: 4px; overflow: hidden; z-index: 2;
  box-shadow: 0 4px 14px rgba(60,45,20,.18);
  transform: translateY(0); transition: transform .95s var(--ease-soft) .5s;
}
.letter__inner { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 1rem; color: #2b2724; opacity: 0; }
.envelope.open .letter__inner { opacity: 1; }
/* textura de papel sutil en la carta */
.envelope__letter::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='90'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)' opacity='.05'/%3E%3C/svg%3E");
}
.letter__mono { font-family: var(--font-display); font-size: 1.3rem; letter-spacing: .1em; color: #b08d57; }
.letter__pre { font-family: var(--font-script); font-size: 1.5rem; color: #6f665c; margin-top: .1rem; }
.letter__names { font-family: var(--font-display); font-size: clamp(1.3rem, 6vw, 1.9rem); color: #2b2724; margin: .1rem 0; }
.letter__rule { width: 40px; height: 1px; background: #c9a86a; margin: .4rem 0; }
.letter__date { font-size: .6rem; letter-spacing: .22em; text-transform: uppercase; color: #6f665c; }

/* Bolsillo delantero */
.envelope__front {
  position: absolute; inset: 0; z-index: 3;
  background: linear-gradient(165deg, var(--bg-alt) 35%, var(--line));
  clip-path: polygon(0 100%, 0 34%, 50% 74%, 100% 34%, 100% 100%);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  padding-bottom: 5%;   /* deja aire entre el lacre (en la punta) y el nombre */
}
/* El "PARA" quedaba tapado por el lacre (que ahora va en la punta) y sumaba
   ruido: el contexto ya lo da "Están cordialmente invitados". Se mantiene
   para lectores de pantalla. */
.envelope__to {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.envelope__guest { font-family: var(--font-display); font-size: clamp(1.35rem, 6.5vw, 2rem); color: var(--text); margin-top: .15rem; line-height: 1.15; padding: 0 8%; text-align: center; }

/* Solapa superior que rota (con cara interior real) */
.envelope__flap {
  position: absolute; top: 0; left: 0; right: 0; height: 66%;
  transform-origin: top center; transform: rotateX(0deg); z-index: 4;
  transform-style: preserve-3d;
  transition: transform 1.05s cubic-bezier(.62,.02,.24,1), z-index 0s .5s;
}
.envelope__flap::before, .envelope__flap::after {
  content: ""; position: absolute; inset: 0;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  backface-visibility: hidden;
}
/* cara exterior */
.envelope__flap::before {
  background: linear-gradient(180deg, var(--surface), var(--bg-alt));
  filter: drop-shadow(0 3px 4px rgba(0,0,0,.12));
}
/* cara interior (se ve al abrir): un poco más oscura, como papel doblado */
.envelope__flap::after {
  transform: rotateX(180deg);
  background: linear-gradient(180deg, var(--line), var(--bg-alt) 70%);
  box-shadow: inset 0 0 30px rgba(0,0,0,.12);
}

/* Sello de lacre — con relieve, brillo y quiebre en 2 mitades */
.envelope__seal {
  /* En la PUNTA de la solapa (que baja hasta el 66%), que es donde va el lacre
     en un sobre real: sella la solapa contra el cuerpo. Antes flotaba al 40%. */
  position: absolute; top: 66%; left: 50%; z-index: 5;
  /* escala con el sobre para mantener la proporción de un lacre real */
  width: clamp(64px, 19vw, 120px); height: clamp(64px, 19vw, 120px);
  transform: translate(-50%, -50%); border-radius: 50%;
  background:
    radial-gradient(circle at 32% 26%, #d4693f 0%, #b8452a 38%, #932c19 68%, #6f2013 100%);
  box-shadow:
    0 4px 10px rgba(70,18,8,.55),
    0 1px 2px rgba(0,0,0,.4),
    inset 0 2px 7px rgba(255,220,190,.35),
    inset 0 -4px 8px rgba(0,0,0,.42);
  display: grid; place-items: center;
  /* borde irregular, como cera derretida */
  border-radius: 47% 53% 51% 49% / 50% 47% 53% 50%;
  transition: transform .4s var(--ease-soft), box-shadow .4s;
  animation: sealBreathe 4.5s ease-in-out infinite;
}
.envelope__seal::after {
  content: ""; position: absolute; inset: 6px; border-radius: 50%;
  border: 1px dashed rgba(255,225,200,.32);
}
/* brillo especular que cruza el lacre */
.envelope__seal::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; overflow: hidden;
  background: linear-gradient(115deg, transparent 38%, rgba(255,235,215,.42) 48%, transparent 58%);
  background-size: 250% 100%; background-position: 130% 0;
  animation: sealSheen 5s ease-in-out infinite;
}
@keyframes sealSheen { 0%, 62% { background-position: 130% 0; } 88%, 100% { background-position: -40% 0; } }
@keyframes sealBreathe { 0%, 100% { box-shadow: 0 4px 10px rgba(70,18,8,.55), 0 1px 2px rgba(0,0,0,.4), inset 0 2px 7px rgba(255,220,190,.35), inset 0 -4px 8px rgba(0,0,0,.42); } 50% { box-shadow: 0 6px 18px rgba(70,18,8,.6), 0 1px 2px rgba(0,0,0,.4), inset 0 2px 7px rgba(255,220,190,.4), inset 0 -4px 8px rgba(0,0,0,.42); } }
.seal__mono { font-family: var(--font-display); font-size: .92rem; color: #f9e6cf; letter-spacing: .04em; z-index: 2; text-shadow: 0 1px 1px rgba(0,0,0,.45); }

/* ===== TEXTURAS REALES (fotografía) =====
   Se activan solo si config.js define las rutas: js/main.js pone las variables.
   Sin ellas, el sobre sigue funcionando con las texturas de CSS puro. */
.env-tex .envelope { background-image: var(--papel); background-size: 320px; }
/* Cada cara lleva un tinte distinto sobre la MISMA textura: sin esto el sobre
   queda plano y no se distingue la solapa del bolsillo delantero. */
.env-tex .envelope__front {
  background-image: linear-gradient(165deg, rgba(0,0,0,.05), rgba(0,0,0,.13)), var(--papel);
  background-size: auto, 320px;
}
.env-tex .envelope__flap::before {
  background-image: linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,.14)), var(--papel);
  background-size: auto, 320px;
}
.env-tex .envelope__flap::after {
  background-image: linear-gradient(180deg, rgba(0,0,0,.2), rgba(0,0,0,.06)), var(--papel);
  background-size: auto, 320px;
}
.env-tex .envelope__letter {
  background-image: linear-gradient(180deg, rgba(255,255,255,.42), rgba(255,255,255,.12)), var(--papel);
  background-size: auto, 260px;
}
/* la foto del lacre reemplaza al gradiente CSS */
.env-tex .envelope__seal {
  background: var(--lacre) center/contain no-repeat;
  /* drop-shadow y no box-shadow: respeta el recorte del PNG, si no dibujaba
     un halo circular blanco alrededor del sello */
  box-shadow: none;
  border-radius: 0;
  filter: drop-shadow(0 4px 9px rgba(70,18,8,.5));
  animation: none;                 /* la respiración la hacía el box-shadow */
}
.env-tex .envelope__seal::before,
.env-tex .envelope__seal::after { display: none; }   /* brillo y anillo ya vienen en la foto */
.env-tex .seal__mono {
  color: #f7dcc0;
  text-shadow: 0 1px 2px rgba(60,10,4,.85), 0 0 10px rgba(0,0,0,.4);
  font-size: 1rem;
}

/* ===== ARRASTRE: el lacre sigue al dedo y se tensa ===== */
.envelope__seal {
  --p: 0; --dx: 0px; --dy: 0px; --ang: 0deg;
  /* sin esto el navegador se queda el gesto para scrollear */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  cursor: grab;
  transform:
    translate(-50%, -50%)
    translate(var(--dx), var(--dy))
    rotate(calc(var(--p) * 5deg))
    scale(calc(1 + var(--p) * .07));
}
.envelope__seal:active { cursor: grabbing; }
/* mientras se estira: se "calienta" y deja de respirar */
.envelope__seal.is-pulling { animation-play-state: paused; filter: brightness(calc(1 + var(--p) * .3)) saturate(calc(1 + var(--p) * .35)); }
.envelope__seal.is-broken { pointer-events: none; }
/* pista de que se puede arrastrar */
.envelope__seal::after { animation: sealHint 2.6s ease-in-out infinite; }
@keyframes sealHint { 0%,100% { transform: translateX(0); opacity: .32; } 50% { transform: translateX(3px); opacity: .6; } }
.envelope__seal.is-pulling::after, .envelope__seal.is-broken::after { animation: none; }

/* Grieta ligada al arrastre: crece con --p, así el invitado VE que va a ceder */
.seal__crack {
  position: absolute; top: 6%; left: 50%; width: 2px; height: 88%; z-index: 3;
  margin-left: -1px;
  opacity: var(--p, 0);
  transform: rotate(calc(var(--ang, 0deg) + 90deg)) scaleY(calc(.15 + var(--p, 0) * .85));
  transform-origin: 50% 50%;
  background: linear-gradient(180deg, transparent, rgba(60,12,4,.92) 18%, rgba(60,12,4,.92) 82%, transparent);
  clip-path: polygon(0 0, 100% 6%, 20% 22%, 100% 40%, 10% 58%, 100% 74%, 30% 90%, 100% 100%, 0 100%);
}
/* Las 2 mitades que salen volando */
.seal__shard {
  position: absolute; inset: 0; border-radius: inherit; z-index: 1; opacity: 0;
  background: radial-gradient(circle at 32% 26%, #c85c36, #932c19 65%, #6f2013);
  box-shadow: inset 0 -3px 6px rgba(0,0,0,.4);
}
.seal__shard--l { clip-path: polygon(0 0, 52% 6%, 18% 24%, 55% 42%, 12% 60%, 52% 76%, 22% 92%, 48% 100%, 0 100%); }
.seal__shard--r { clip-path: polygon(52% 6%, 100% 0, 100% 100%, 48% 100%, 22% 92%, 52% 76%, 12% 60%, 55% 42%, 18% 24%); }

/* El quiebre lo maneja js/envelope.js (pedazos reales con física).
   Los 2 shards estáticos quedan sólo como respaldo si el JS no cargara. */
.seal__shard { display: none; }

/* Sólo para lectores de pantalla */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Pista del gesto */
.env__gesture {
  font-family: var(--font-body); font-size: .72rem; letter-spacing: .22em;
  text-transform: uppercase; color: var(--text-soft);
  opacity: 0; animation: fadeUp .9s ease 1s forwards;
}
.envelope__seal.is-broken ~ .env__gesture, .env__stage:has(.is-broken) .env__gesture { opacity: 0; }

/* Botón hint "tocá para abrir" */
.env__hint {
  font-family: var(--font-body); font-size: .72rem; letter-spacing: .26em; text-transform: uppercase;
  color: var(--text-soft); display: flex; flex-direction: column; align-items: center; gap: .6rem;
  opacity: 0; animation: fadeUp .8s ease .5s forwards;
}
.env__hint span { width: 1px; height: 26px; background: var(--accent); animation: hintPulse 1.8s ease-in-out infinite; }
@keyframes hintPulse { 0%,100% { opacity: .3; transform: scaleY(.7); } 50% { opacity: 1; transform: scaleY(1); } }

/* ===== Estado ABIERTO — coreografía: lacre → solapa → carta ===== */
.envelope.open { cursor: default; }
.envelope.open .envelope__seal { pointer-events: none; }
/* la solapa espera a que el lacre ceda */
.envelope.open .envelope__flap { transform: rotateX(176deg); z-index: 1; transition-delay: .55s; }
/* la carta sube con peso, después de que la solapa abrió */
.envelope.open .envelope__letter {
  transform: translateY(-54%) scale(1.05); z-index: 6;
  box-shadow: 0 30px 60px -20px rgba(60,45,20,.55), 0 4px 10px rgba(60,45,20,.15);
  transition: transform 1.15s cubic-bezier(.28,.84,.32,1) 1.25s, box-shadow 1.15s ease 1.25s;
}
.envelope.open .envelope__shadow { transform: scaleX(1.28) translateY(8px); opacity: .5; transition-delay: 1.25s; }
/* todo el conjunto respira hacia adelante (sensación cinematográfica) */
/* 'both' cubre el delay inicial (si no, durante esos .5s tomaba el opacity:0 base) */
.envelope.open { opacity: 1; animation: envLift 1.5s var(--ease-soft) .5s both; }
/* opacity:1 en ambos extremos: envLift reemplaza a envIn y sin esto el sobre volvía a opacity:0 */
@keyframes envLift {
  from { opacity: 1; transform: none; }
  to   { opacity: 1; transform: translateY(-10px) scale(1.02); }
}
/* el contenido de la carta entra escalonado */
.envelope.open .letter__inner > * { animation: letterIn .7s var(--ease-soft) forwards; opacity: 0; }
.envelope.open .letter__mono  { animation-delay: 1.85s; }
.envelope.open .letter__pre   { animation-delay: 1.98s; }
.envelope.open .letter__names { animation-delay: 2.10s; }
.envelope.open .letter__rule  { animation-delay: 2.22s; }
.envelope.open .letter__date  { animation-delay: 2.32s; }
@keyframes letterIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }

@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ============================================================================
   TRANSICIÓN ORGÁNICA AL SITIO
   El sitio se revela con un círculo que crece desde el punto exacto donde el
   invitado rompió el lacre (--break-x/y los fija envelope.js). 150% y no 100%:
   con 100% el círculo no llega a las esquinas en viewports no cuadrados.
   ========================================================================== */
/* A PRUEBA DE FALLOS: el recorte se aplica SÓLO si el JS marcó el body con
   .env-active. Si el JS no corre, no hay clip-path y el sitio se ve normal
   (con la regla al revés, un fallo del JS dejaba la página invisible). */
body.env-active main, body.env-active .nav {
  clip-path: circle(0% at var(--break-x, 50%) var(--break-y, 42%));
  transition: clip-path 1100ms cubic-bezier(.65, 0, .35, 1);
}
body.env-active.is-open main, body.env-active.is-open .nav {
  clip-path: circle(150% at var(--break-x, 50%) var(--break-y, 42%));
}
@media (prefers-reduced-motion: reduce) {
  main, .nav { clip-path: none !important; transition: opacity .2s linear !important; }
}

/* El botón directo aparece recién si el gesto no sale (respaldo, nunca estorba).
   `animation: none` es necesario: la regla original lo hacía aparecer con
   fadeUp y quedaba visible desde el arranque, duplicando la pista del gesto. */
.env__hint {
  opacity: 0; pointer-events: none; animation: none !important;
  transition: opacity .6s ease; height: 0; overflow: hidden; margin: 0;
}
.env__hint.is-visible { opacity: .75; pointer-events: auto; height: auto; overflow: visible; }

/* ============================================================================
   BOTONES — efecto foil (relleno que cruza)
   ========================================================================== */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--foil); background-size: 220% 100%; background-position: 100% 0;
  opacity: 0; transition: opacity .4s ease, background-position .6s ease;
}
.btn:hover::before { opacity: 1; background-position: 0 0; }
.btn:hover { color: #3a2e12; }
.btn--outline:hover { color: #3a2e12; border-color: transparent; }

/* ============================================================================
   HERO — pétalos + parallax
   ========================================================================== */
/* ============================================================================
   NAV — legibilidad sobre el hero (antes de scrollear)
   ========================================================================== */
.nav { isolation: isolate; }
.nav::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,.5), rgba(0,0,0,0));
  opacity: 1; transition: opacity .4s ease;
}
.nav.scrolled::before { opacity: 0; }
/* Sobre el hero: texto claro */
.nav:not(.scrolled) .nav__brand { color: #fff; text-shadow: 0 1px 8px rgba(0,0,0,.4); }
.nav:not(.scrolled) .nav__links a { color: rgba(255,255,255,.92); }
.nav:not(.scrolled) .nav__links a::after { background: #fff; }
.nav:not(.scrolled) .nav__burger span { background: #fff; }
.nav:not(.scrolled) .nav__music { border-color: rgba(255,255,255,.55); }
.nav:not(.scrolled) .nav__music-icon::before,
.nav:not(.scrolled) .nav__music-icon::after { background: #fff; }

.hero__bg { transform: scale(1.18); will-change: transform; }
.hero__petals { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; }
.petal {
  position: absolute; top: -8%; width: 12px; height: 12px; border-radius: 0 100% 0 100%;
  background: rgba(255,255,255,.55); opacity: 0;
  animation: petalFall linear infinite;
  animation-play-state: paused;   /* caen solo con el hero a la vista */
}
.hero.in-view .petal { animation-play-state: running; }
@keyframes petalFall {
  0% { opacity: 0; transform: translateY(-10vh) translateX(0) rotate(0deg); }
  10% { opacity: .8; }
  90% { opacity: .7; }
  100% { opacity: 0; transform: translateY(112vh) translateX(40px) rotate(320deg); }
}

/* ============================================================================
   SCROLLYTELLING — "Nuestra historia"
   ========================================================================== */
.scrolly { position: relative; }
.scrolly__sticky {
  position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden;
  display: grid; place-items: center;
}
.scrolly__layers { position: absolute; inset: 0; }
.scrolly__layer {
  position: absolute; inset: 0; background-size: cover; background-position: center;
  opacity: 0; transform: scale(1.08); transition: opacity 1s ease, transform 6s ease;
}
.scrolly__layer.on { opacity: 1; transform: scale(1); }
.scrolly__tint { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,8,6,.5), rgba(10,8,6,.35) 40%, rgba(10,8,6,.65)); }
.scrolly__heading { position: absolute; top: 8%; left: 0; right: 0; text-align: center; color: #fff; z-index: 2; padding: 0 1rem; }
.scrolly__eyebrow { font-family: var(--font-display); font-size: clamp(1.6rem, 6vw, 2.6rem); }
.scrolly__sub { font-family: var(--font-body); font-size: .72rem; letter-spacing: .26em; text-transform: uppercase; opacity: .8; margin-top: .3rem; }
.scrolly__year {
  position: absolute; z-index: 1; font-family: var(--font-display);
  font-size: clamp(6rem, 30vw, 18rem); line-height: 1; color: rgba(255,255,255,.12);
  font-weight: 600; transition: opacity .5s ease; user-select: none;
}
.scrolly__steps { position: relative; z-index: 3; }
.scrolly__step {
  min-height: 100vh; min-height: 100svh; display: flex; align-items: center; justify-content: center;
  padding: 2rem 1.4rem; text-align: center;
}
.scrolly__card {
  max-width: 440px; color: #fff;
  opacity: .18; transform: translateY(30px) scale(.98);
  transition: opacity .6s ease, transform .6s var(--ease-soft);
}
.scrolly__step.is-active .scrolly__card { opacity: 1; transform: none; }
.scrolly__card .c-year { font-family: var(--font-display); font-size: 1.4rem; color: var(--accent-2); }
.scrolly__card h3 { font-family: var(--font-display); font-size: clamp(1.8rem, 8vw, 3rem); margin: .2rem 0 .6rem; }
.scrolly__card p { font-size: 1.02rem; line-height: 1.6; color: rgba(255,255,255,.9); }
.scrolly__card .c-quote { display: inline-flex; color: var(--accent); margin-bottom: .4rem; opacity: .8; }

/* ============================================================================
   REVEAL — vía nativa (scroll-driven) + fallback IntersectionObserver
   ========================================================================== */
@supports (animation-timeline: view()) {
  .reveal { opacity: 0; transform: translateY(30px); animation: revealIn linear both; animation-timeline: view(); animation-range: entry 0% entry 55%; }
  @keyframes revealIn { to { opacity: 1; transform: none; } }
}
/* Entrada escalonada en grillas: guía la lectura en vez de tirar todo junto.
   Solo aplica al fallback por IO; el paso es corto (70ms) para no demorar. */
.gallery__grid .reveal:nth-child(2), .info__grid .reveal:nth-child(2), .events__grid .reveal:nth-child(2), .gifts__grid .reveal:nth-child(2) { transition-delay: 70ms; }
.gallery__grid .reveal:nth-child(3), .info__grid .reveal:nth-child(3) { transition-delay: 140ms; }
.gallery__grid .reveal:nth-child(4), .info__grid .reveal:nth-child(4) { transition-delay: 210ms; }
.gallery__grid .reveal:nth-child(5) { transition-delay: 280ms; }
.gallery__grid .reveal:nth-child(6) { transition-delay: 350ms; }

/* ============================================================================
   ÍCONOS (SVG line icons)
   ========================================================================== */
.rsvp__nota { display: inline-block; margin-top: .8rem; padding: .6rem 1rem; border-radius: 10px; background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--text); font-size: .92rem; }
.rsvp__mesa { display: inline-block; margin-top: .4rem; font-size: .95rem; }

.icon { display: inline-block; vertical-align: middle; overflow: visible; }

/* --- Círculo contenedor: profundidad + reacción --- */
.event-card__iconwrap, .info-card__iconwrap {
  position: relative; display: inline-grid; place-items: center;
  width: 62px; height: 62px; margin: 0 auto .5rem;
  border-radius: 50%; color: var(--accent);
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  transition: transform .5s var(--ease-soft), border-color .5s ease, background .5s ease, box-shadow .5s ease;
}
/* anillo punteado SIEMPRE girando (más marcado al hover) */
.event-card__iconwrap::before, .info-card__iconwrap::before {
  content: ""; position: absolute; inset: -5px; border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--accent) 50%, transparent);
  opacity: .35;
  transition: opacity .5s ease, border-color .5s ease;
  /* quieto por defecto: girar 24/7 gastaba batería sin informar nada */
}
@media (hover: hover) {
  .event-card:hover .event-card__iconwrap::before,
  .info-card:hover  .info-card__iconwrap::before { animation: ringSpin 7s linear infinite; }
}
@keyframes ringSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
/* segundo anillo, girando al revés y más lento (profundidad) */
.event-card__iconwrap, .info-card__iconwrap { isolation: isolate; }
.event-card__iconwrap .ring2, .info-card__iconwrap .ring2 {
  position: absolute; inset: -11px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  opacity: .5;
}
@media (hover: hover) {
  .event-card:hover .ring2, .info-card:hover .ring2 { animation: ringSpinRev 12s linear infinite; }
}
@keyframes ringSpinRev { from { transform: rotate(360deg); } to { transform: rotate(0); } }
/* halo suave */
.event-card__iconwrap::after, .info-card__iconwrap::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--accent) 30%, transparent), transparent 70%);
  opacity: 0; transition: opacity .5s ease;
}
.event-card__iconwrap .icon { width: 30px; height: 30px; }
.info-card__iconwrap { width: 54px; height: 54px; }
.info-card__iconwrap .icon { width: 26px; height: 26px; }

/* --- Hover en la tarjeta: el ícono cobra vida --- */
.event-card, .info-card { transition: transform .5s var(--ease-soft), box-shadow .5s ease, border-color .5s ease; }
.event-card:hover, .info-card:hover { transform: translateY(-6px); border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); box-shadow: 0 26px 50px -26px rgba(90,70,40,.5); }
.event-card:hover .event-card__iconwrap,
.info-card:hover .info-card__iconwrap {
  transform: translateY(-4px) scale(1.09);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  box-shadow: 0 14px 26px -14px var(--accent);
}
.event-card:hover .event-card__iconwrap::before,
.info-card:hover .info-card__iconwrap::before { opacity: .85; border-color: var(--accent); }
.event-card:hover .event-card__iconwrap::after,
.info-card:hover .info-card__iconwrap::after { opacity: .35; }

/* --- Íconos: la vida vive en el HOVER, no en un loop de batería ---
   (rediseño 2.0: 19 animaciones infinitas puntuaban 39/100; el movimiento
   idle constante consume batería y no informa nada. El line-draw de entrada
   queda; al interactuar, el ícono responde UNA vez.) */
@keyframes iconFloat { 0%,100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-4px) rotate(1.5deg); } }
@keyframes iconSway  { 0%,100% { transform: rotate(-4deg); } 50% { transform: rotate(4deg); } }
@keyframes iconPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.09); } }
@keyframes iconTick  { 0%,60%,100% { transform: rotate(0); } 70% { transform: rotate(7deg); } 85% { transform: rotate(-5deg); } }
@media (hover: hover) {
  .info-card:hover  .icon.is-drawn { animation: iconSway .9s var(--ease-soft); transform-origin: 50% 60%; }
  .event-card:hover .icon.is-drawn { animation: iconPulse .9s var(--ease-soft); }
}

/* --- Line-draw: los íconos se dibujan solos al aparecer --- */
.icon [data-len] {
  stroke-dasharray: var(--l);
  stroke-dashoffset: var(--l);
  transition: stroke-dashoffset 1.15s var(--ease-soft) var(--d, 0s), opacity .4s ease var(--d, 0s);
  opacity: .25;
}
.icon.is-drawn [data-len] { stroke-dashoffset: 0; opacity: 1; }

/* --- Íconos chicos (botones, labels) --- */
.btn .icon { width: 17px; height: 17px; margin-left: .45rem; transition: transform .4s var(--ease-soft); }
.btn:hover .icon { transform: translateX(3px); }
.btn .icon [data-len] { stroke-dasharray: none; stroke-dashoffset: 0; opacity: 1; }
.gift-card__label .icon, .playlist__spotify .icon, .footer__wa .icon { width: 19px; height: 19px; margin-right: .35rem; }
.gift-card__label .icon [data-len], .playlist__spotify .icon [data-len], .footer__wa .icon [data-len] { stroke-dasharray: none; stroke-dashoffset: 0; opacity: 1; }
/* responden al hover, no giran solos */
@media (hover: hover) {
  .gift-card:hover .gift-card__label .icon { animation: iconSway .8s var(--ease-soft); transform-origin: 50% 70%; }
  .playlist__spotify:hover .icon, .footer__wa:hover .icon { animation: iconPop .5s var(--ease-soft); }
  #addCalendar:hover .icon { animation: iconTick 1s var(--ease-soft); transform-origin: 50% 60%; }
}
@keyframes iconPop { 50% { transform: scale(1.18) rotate(6deg); } }
/* el ícono del countdown/scroll y el hint del hero ya se mueven solos */
/* la hoja quieta: se movía sobre texto que el invitado está leyendo */

/* ============================================================================
   EDITORIAL — encabezados de sección (índice + eyebrow con líneas)
   ========================================================================== */
.sec-eyebrow {
  display: flex; align-items: center; justify-content: center; gap: .8rem;
  font-family: var(--font-body); font-size: .66rem; letter-spacing: .34em;
  text-transform: uppercase; color: var(--text-soft); margin-bottom: 1.1rem;
}
.sec-eyebrow::before, .sec-eyebrow::after { content: ""; width: 26px; height: 1px; background: var(--line); }
.sec-eyebrow .sec-index { font-family: var(--font-display); font-size: .95rem; letter-spacing: .08em; color: var(--accent); }
.section__title { font-size: clamp(2.1rem, 6.5vw, 3.4rem); letter-spacing: .01em; }
.invite__ornament, .gifts__ornament { display: none; } /* reemplazados por los eyebrows editoriales */
.section--alt .sec-eyebrow::before, .section--alt .sec-eyebrow::after { background: color-mix(in srgb, var(--text-soft) 30%, transparent); }

/* ============================================================================
   SECCIÓN CINEMÁTICA (Ken Burns — simulación de video)
   ========================================================================== */
.cinematic { position: relative; height: 92vh; height: 92svh; min-height: 520px; overflow: hidden; display: grid; place-items: center; }
.cinematic__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.cinematic__bg {
  position: absolute; inset: 0; background-size: cover; background-position: center;
  transform: scale(1.15); will-change: transform;
  animation: kenburns 26s ease-in-out infinite alternate;
  animation-play-state: paused;   /* corre solo con la sección a la vista */
}
.cinematic.in-view .cinematic__bg { animation-play-state: running; }
@keyframes kenburns {
  0%   { transform: scale(1.15) translate3d(0, 0, 0); }
  100% { transform: scale(1.3) translate3d(-2.5%, -3%, 0); }
}
.cinematic__tint { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(12,9,7,.55), rgba(12,9,7,.32) 45%, rgba(12,9,7,.68)); }
.cinematic__inner { position: relative; z-index: 2; text-align: center; color: #fff; padding: 2rem 1.4rem; max-width: 860px; }
.cinematic__quote {
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: clamp(1.7rem, 6vw, 3.4rem); line-height: 1.28;
  text-shadow: 0 4px 30px rgba(0,0,0,.4);
  opacity: 0; transform: translateY(24px); animation: cinIn 1.2s var(--ease-soft) .2s forwards;
}
.cinematic__author { margin-top: 1.5rem; font-family: var(--font-script); font-size: clamp(1.5rem, 4vw, 2.2rem); color: var(--accent-2); opacity: 0; animation: cinIn 1.2s var(--ease-soft) .6s forwards; }
@keyframes cinIn { to { opacity: 1; transform: none; } }

/* ============================================================================
   REGALOS — versión discreta (datos ocultos tras un botón sobrio)
   ========================================================================== */
.gifts__toggle {
  margin: 1.4rem auto 0; padding: .85rem 2rem; border: 1px solid var(--line);
  border-radius: 50px; color: var(--text-soft); background: var(--surface);
  letter-spacing: .16em; text-transform: uppercase; font-size: .72rem; font-weight: 500;
  transition: border-color .3s, color .3s, transform .25s;
}
.gifts__toggle:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); }
.gifts__grid[hidden] { display: none; }
.gifts__grid.reveal-soft { animation: cinIn .6s ease forwards; }

/* ============================================================================
   REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .petal { display: none; }
  .scrolly__layer.on { opacity: 1; transform: none; }
  .cursor { display: none !important; }
  body { cursor: auto !important; }
}

/* ============================================================================
   DESKTOP scrollytelling (texto a un lado)
   ========================================================================== */
@media (min-width: 860px) {
  .scrolly__heading { top: 7%; }
  .scrolly__step { justify-content: flex-start; padding-left: 8vw; text-align: left; }
  .scrolly__card { margin-left: 4vw; }
}
