/* ============================================================================
 *  COMPONENTES  ·  botones, contador, galeria, visor, audio y copiado
 * ==========================================================================*/

/* ---------------------------------------------------------------------
 * BOTONES
 * -------------------------------------------------------------------*/
.boton {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  padding: .72em 1.35em;
  font-family: var(--f-libro);
  font-weight: 600;
  font-size: var(--t-sm);
  /* Espaciado algo mas corto que antes: con el cuerpo de letra subido,
     un "Confirmar por WhatsApp" con .16em ya no cabia de ancho. */
  letter-spacing: .11em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--crema);
  background: linear-gradient(140deg, var(--terracota) 0%, var(--terracota-oscura) 100%);
  border: 1px solid rgba(226,200,145,.5);
  border-radius: 999px;
  box-shadow: 0 3px 10px rgba(107,53,36,.28);
  transform: translate3d(0,0,0);
  transition: transform .22s cubic-bezier(.2,.8,.3,1), box-shadow .22s ease, opacity .2s ease;
  overflow: hidden;
  /* Antes iba con nowrap y, como el boton recorta lo que sobra, una
     etiqueta larga se quedaba CORTADA sin avisar ("...POR WHATSAP").
     Ahora parte en dos lineas equilibradas: feo nunca, cortado jamas. */
  white-space: normal;
  text-wrap: balance;
  line-height: 1.25;
}
.boton .ico { width: 1.15em; height: 1.15em; }
.boton:hover  { transform: translate3d(0,-2px,0); box-shadow: 0 7px 18px rgba(107,53,36,.34); }
.boton:active { transform: translate3d(0,0,0) scale(.975); }

.boton--olivo {
  background: linear-gradient(140deg, var(--olivo) 0%, var(--olivo-oscuro) 100%);
  box-shadow: 0 3px 10px rgba(75,85,55,.28);
}
.boton--whatsapp {
  background: linear-gradient(140deg, #35b96a 0%, #1e8a4c 100%);
  border-color: rgba(255,255,255,.42);
  box-shadow: 0 3px 12px rgba(30,138,76,.32);
}
.boton--fantasma {
  color: var(--terracota-oscura);
  background: rgba(255,255,255,.5);
  border: 1px solid rgba(177,106,76,.42);
  box-shadow: none;
}
.boton--fantasma:hover { background: rgba(255,255,255,.8); box-shadow: 0 4px 12px rgba(140,75,51,.16); }

.boton--pequeno { font-size: var(--t-xs); padding: .6em 1.15em; letter-spacing: .13em; }

/* ---------------------------------------------------------------------
 * BOTON DE CONFIRMAR  ·  el que lleva al Excel de asistencias
 * ---------------------------------------------------------------------
 *  Es la accion mas importante de todo el libro, asi que es el unico
 *  boton que:
 *    · ocupa el ancho entero de la hoja,
 *    · tiene altura de dedo (nada de 32 px: en el movil se falla),
 *    · late despacio para pedir el toque,
 *    · y se HUNDE al pulsarlo, con un brillo que lo cruza, para que el
 *      dedo note que ha pasado algo aunque la pestaña tarde en abrir.
 *
 *  El latido es un box-shadow que se expande: se compone en la GPU y no
 *  cuesta nada. Necesita overflow visible, por eso se anula el del
 *  .boton normal y el brillo se recorta en su propia capa interior.
 * -------------------------------------------------------------------*/
.boton--confirmar {
  width: 100%;
  min-height: calc(var(--pw) * .172);
  padding: .82em 1.2em;
  overflow: visible;
  white-space: normal;
  font-size: var(--t-sm);
  letter-spacing: .13em;
  background: linear-gradient(135deg,
    var(--terracota-clara) 0%, var(--terracota) 42%, var(--terracota-oscura) 100%);
  border: 1px solid rgba(226,200,145,.72);
  box-shadow:
    0 4px 14px rgba(107,53,36,.32),
    inset 0 1px 0 rgba(255,255,255,.28);
  transition:
    transform .16s cubic-bezier(.2,.8,.3,1),
    box-shadow .2s ease,
    filter .2s ease;
}
.boton--confirmar:hover {
  transform: translate3d(0,-2px,0);
  filter: saturate(1.06);
  box-shadow: 0 9px 22px rgba(107,53,36,.38), inset 0 1px 0 rgba(255,255,255,.3);
}
/* El hundido: mas marcado que en el resto de botones, es la accion clave */
.boton--confirmar:active {
  transform: translate3d(0,1px,0) scale(.962);
  box-shadow: 0 2px 6px rgba(107,53,36,.34), inset 0 2px 7px rgba(74,32,18,.34);
  transition-duration: .08s;
}

/* El contenido: icono + texto. Va en su propia capa para poder recortar
   el brillo del pulsado sin tocar el halo, que vive por fuera. */
.boton__contenido {
  position: relative;
  z-index: 2;
  /* A lo ancho del boton entero: asi el brillo del pulsado lo cruza de
     lado a lado y no solo el trozo que ocupan las letras. */
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .62em;
  overflow: hidden;
  border-radius: 999px;
}
.boton__contenido .ico {
  width: 1.45em;
  height: 1.45em;
  flex: none;
  stroke-width: 1.5;
}
.boton__texto { text-indent: .13em; }

/* --- EL LATIDO ---------------------------------------------------- */
.boton__halo {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 999px;
  pointer-events: none;
  animation: latidoBoton 2.6s cubic-bezier(.22,.61,.36,1) infinite;
}
@keyframes latidoBoton {
  0%       { box-shadow: 0 0 0 0    rgba(180,106,76,.5); }
  62%, 100%{ box-shadow: 0 0 0 16px rgba(180,106,76,0); }
}
/* Mientras el dedo esta encima, el latido para: ya tiene la atencion */
.boton--confirmar:active .boton__halo,
.boton--confirmar:hover  .boton__halo { animation-play-state: paused; }

/* --- EL BRILLO QUE CRUZA AL PULSAR -------------------------------- */
.boton__contenido::after {
  content: '';
  position: absolute;
  top: -50%;
  left: -70%;
  width: 45%;
  height: 200%;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(255,255,255,0) 0%, rgba(255,255,255,.42) 50%, rgba(255,255,255,0) 100%);
  transform: translate3d(0,0,0) skewX(-18deg);
  opacity: 0;
}
.boton--confirmar:active .boton__contenido::after { animation: brilloBoton .5s ease-out; }
@keyframes brilloBoton {
  0%   { opacity: 0; transform: translate3d(0,0,0) skewX(-18deg); }
  18%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(340%,0,0) skewX(-18deg); }
}

/* Quien pide menos movimiento no ve latido: solo el boton, quieto. */
@media (prefers-reduced-motion: reduce) {
  .boton__halo { animation: none; box-shadow: 0 0 0 3px rgba(180,106,76,.22); }
}

/* ---------------------------------------------------------------------
 * BOTON FLOTANTE DE CONFIRMAR  ·  abajo a la izquierda
 * ---------------------------------------------------------------------
 *  Acompaña al invitado por todo el libro. Va abajo a la IZQUIERDA para
 *  no chocar con el reproductor de musica (arriba a la derecha) ni con
 *  las flechas del pie, que van centradas.
 *
 *  Alto de dedo (44 px es el minimo decente en un movil) y separado de
 *  los bordes con env(safe-area-inset-*), que es lo que deja libre la
 *  barra de gestos del iPhone y el hueco de la camara.
 * -------------------------------------------------------------------*/
.confirmar-flotante {
  position: fixed;
  left: max(12px, env(safe-area-inset-left));
  bottom: max(12px, env(safe-area-inset-bottom));
  /* POR ENCIMA del visor de fotos (90) y de la despedida (100), que son
     las dos pantallas completas, y POR DEBAJO del telon de entrada (120),
     que tiene que verse limpio. Si se quedara en 65 —donde estaba— el
     boton seguiria "desapareciendo" en esas dos pantallas, solo que por
     quedarse detras en vez de por apagarse. */
  z-index: 105;

  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  border-radius: 999px;
  text-decoration: none;
  border: 1px solid rgba(226,200,145,.7);
  background: linear-gradient(135deg,
    var(--terracota-clara) 0%, var(--terracota) 45%, var(--terracota-oscura) 100%);
  box-shadow:
    0 4px 14px rgba(20,10,6,.45),
    inset 0 1px 0 rgba(255,255,255,.26);
  color: var(--crema);

  /* Entra deslizando desde el borde, una vez el libro ya esta colocado */
  opacity: 0;
  transform: translate3d(-14px, 0, 0);
  transition:
    opacity .45s ease,
    transform .45s cubic-bezier(.2,.8,.3,1),
    box-shadow .2s ease;
}
.confirmar-flotante.puesto { opacity: 1; transform: translate3d(0,0,0); }

/* NO SE RETIRA NUNCA. Antes se apagaba en la hoja de confirmar y en las
   dos pantallas completas (visor de fotos y despedida). Ahora acompaña al
   invitado en todo momento: confirmar tiene que estar siempre a un dedo.
   La clase .fuera se conserva por si algun dia hace falta esconderlo a
   mano, pero ya no se la pone nadie. */
.confirmar-flotante.fuera {
  opacity: 0;
  transform: translate3d(-14px, 0, 0);
  pointer-events: none;
}

.confirmar-flotante__int {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: .5em;
  padding: 0 1.05em 0 .95em;
  border-radius: 999px;
  overflow: hidden;
  font-family: var(--f-libro);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .13em;
  text-transform: uppercase;
  text-indent: .13em;
  white-space: nowrap;
}
.confirmar-flotante .ico {
  width: 17px;
  height: 17px;
  flex: none;
  stroke-width: 1.6;
  text-indent: 0;
}

.confirmar-flotante:hover {
  box-shadow: 0 8px 22px rgba(20,10,6,.5), inset 0 1px 0 rgba(255,255,255,.3);
}
/* El hundido al pulsar, igual que el boton grande de la hoja */
.confirmar-flotante:active {
  transform: translate3d(0,1px,0) scale(.955);
  box-shadow: 0 2px 6px rgba(20,10,6,.5), inset 0 2px 7px rgba(74,32,18,.38);
  transition-duration: .08s;
}

/* El latido, mas discreto que el del boton grande: este vive en pantalla
   todo el rato y un parpadeo constante acabaria cansando. */
.confirmar-flotante__halo {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 999px;
  pointer-events: none;
  animation: latidoFlotante 4s cubic-bezier(.22,.61,.36,1) infinite;
}
@keyframes latidoFlotante {
  0%        { box-shadow: 0 0 0 0    rgba(207,141,109,.5); }
  55%, 100% { box-shadow: 0 0 0 13px rgba(207,141,109,0); }
}
.confirmar-flotante:hover  .confirmar-flotante__halo,
.confirmar-flotante:active .confirmar-flotante__halo { animation-play-state: paused; }

/* Brillo que lo cruza al pulsarlo */
.confirmar-flotante__int::after {
  content: '';
  position: absolute;
  top: -50%; left: -70%;
  width: 45%; height: 200%;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(255,255,255,0) 0%, rgba(255,255,255,.45) 50%, rgba(255,255,255,0) 100%);
  transform: translate3d(0,0,0) skewX(-18deg);
  opacity: 0;
}
.confirmar-flotante:active .confirmar-flotante__int::after { animation: brilloBoton .5s ease-out; }

/* Moviles estrechos: solo el icono, para no comerse media pantalla */
@media (max-width: 360px) {
  .confirmar-flotante__texto { display: none; }
  .confirmar-flotante__int { padding: 0 .85em; }
  .confirmar-flotante { min-width: 44px; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .confirmar-flotante__halo { animation: none; box-shadow: 0 0 0 3px rgba(207,141,109,.25); }
}

/* ---------------------------------------------------------------------
 * TARJETA  ·  bloque de papel con hilo dorado
 * -------------------------------------------------------------------*/
.tarjeta {
  position: relative;
  width: 100%;
  padding: var(--s3) var(--s2);
  border: 1px solid rgba(193,154,92,.34);
  border-radius: calc(var(--pw) * .014);
  background: rgba(255,252,246,.52);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
}
.tarjeta::before {
  content: '';
  position: absolute;
  inset: calc(var(--pw) * .012);
  border: 1px solid rgba(193,154,92,.2);
  border-radius: inherit;
  pointer-events: none;
}
.tarjeta--limpia { background: rgba(255,252,246,.35); }

/* ---------------------------------------------------------------------
 * AVISO  ·  la tarjeta que SI hay que leer
 * ---------------------------------------------------------------------
 *  Misma familia visual que .tarjeta (papel + hilo dorado) pero con una
 *  cinta de terracota cosida arriba. Se usa para el "solo adultos": es
 *  el dato que mas se pasa por alto y necesitaba peso propio.
 *
 *  La cinta se monta sobre el borde (translateY(-50%)) y por eso la
 *  tarjeta lleva margen superior: si no, se comeria lo de arriba.
 * -------------------------------------------------------------------*/
.aviso {
  position: relative;
  width: 100%;
  margin-top: calc(var(--pw) * .052);
  padding: calc(var(--pw) * .058) calc(var(--pw) * .038) calc(var(--pw) * .042);
  border: 1.5px solid rgba(180,106,76,.55);
  border-radius: calc(var(--pw) * .016);
  background:
    radial-gradient(130% 100% at 50% 0%, rgba(255,255,255,.8), rgba(255,255,255,0) 68%),
    linear-gradient(175deg, rgba(255,250,243,.9), rgba(247,235,222,.82));
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.6),
    0 4px 16px rgba(140,75,51,.16);
}
.aviso::before {
  content: '';
  position: absolute;
  inset: calc(var(--pw) * .013);
  border: 1px solid rgba(193,154,92,.35);
  border-radius: inherit;
  pointer-events: none;
}
.aviso__cinta {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: .5em;
  white-space: nowrap;
  padding: .5em 1.15em;
  border-radius: 999px;
  border: 1px solid rgba(226,200,145,.6);
  background: linear-gradient(140deg, var(--terracota) 0%, var(--terracota-oscura) 100%);
  box-shadow: 0 3px 10px rgba(107,53,36,.3);
  color: var(--crema);
  font-size: calc(var(--pw) * .029);
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-indent: .2em;
}
.aviso__cinta .ico { width: 1.25em; height: 1.25em; flex: none; text-indent: 0; }
.aviso__texto {
  margin: 0;
  font-size: calc(var(--pw) * .0365);
  line-height: 1.55;
  color: var(--tinta-suave);
  text-wrap: balance;
}

/* ---------------------------------------------------------------------
 * BLOQUE DE DATO  ·  icono + etiqueta + valor
 * -------------------------------------------------------------------*/
.ficha__icono {
  display: grid;
  place-items: center;
  flex: none;   /* si no, el flex en columna le aplasta el alto */
  width: calc(var(--pw) * .155);
  height: calc(var(--pw) * .155);
  border-radius: 50%;
  color: var(--terracota-oscura);
  border: 1px solid rgba(193,154,92,.45);
  background: radial-gradient(circle at 34% 28%, rgba(255,255,255,.9), rgba(240,226,206,.6));
  box-shadow: 0 2px 8px rgba(140,90,60,.12);
  margin-bottom: var(--s0);
}
.ficha__icono .ico { width: 52%; height: 52%; stroke-width: 1.3; }
.ficha__nota {
  font-size: var(--t-sm);
  font-style: italic;
  color: var(--tinta-tenue);
  line-height: 1.45;
}

/* ---------------------------------------------------------------------
 * CONTADOR
 * -------------------------------------------------------------------*/
/*  LOS NUMEROS MANDAN.
 *  La cifra es lo que se lee de lejos: ocupa casi toda la casilla y la
 *  etiqueta queda debajo, discreta, separada por un hilo dorado. Las
 *  casillas son cuatro columnas iguales (flex: 1 1 0 + min-width: 0),
 *  asi que el bloque entra siempre, tenga el dia 1, 2 o 3 cifras.      */
.contador {
  display: flex;
  justify-content: center;
  gap: calc(var(--pw) * .018);
  width: 100%;
}
.contador__casilla {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  padding-inline: calc(var(--pw) * .006);
  padding: calc(var(--pw) * .036) calc(var(--pw) * .006) calc(var(--pw) * .026);
  border-radius: calc(var(--pw) * .016);
  border: 1px solid rgba(193,154,92,.42);
  background:
    linear-gradient(170deg, rgba(255,253,248,.94), rgba(243,233,220,.78));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    0 3px 12px rgba(140,90,60,.13);
}
/* Hilo dorado interior, el mismo detalle que las tarjetas del libro */
.contador__casilla::before {
  content: '';
  position: absolute;
  inset: calc(var(--pw) * .008);
  border: 1px solid rgba(193,154,92,.2);
  border-radius: inherit;
  pointer-events: none;
}
/* Los dias son la unica cifra que puede llegar a tres digitos (una boda
   a mas de tres meses vista). Su casilla va un cuarto mas ancha para que
   quepan sin encoger la letra. */
.contador__casilla:first-child { flex-grow: 1.3; }

.contador__numero {
  display: block;
  font-family: var(--f-libro);
  font-weight: 600;
  font-size: calc(var(--pw) * .128);
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--terracota-oscura);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 0 rgba(255,255,255,.7);
  transform: translate3d(0,0,0);
}
.contador__casilla--seg .contador__numero {
  color: var(--terracota);
  animation: pulsoSeg 1s ease-in-out infinite;
}
@keyframes pulsoSeg {
  0%, 70%, 100% { transform: scale(1); }
  8%            { transform: scale(1.07); }
}
.contador__etiqueta {
  display: block;
  position: relative;
  margin-top: calc(var(--pw) * .018);
  padding-top: calc(var(--pw) * .016);
  font-size: calc(var(--pw) * .024);
  font-weight: 600;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--olivo-oscuro);
  opacity: .78;
  text-indent: .15em;
}
/* El hilo que separa la cifra de su etiqueta */
.contador__etiqueta::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  width: 42%;
  height: 1px;
  transform: translateX(-50%);
  background: linear-gradient(90deg,
    rgba(193,154,92,0), rgba(193,154,92,.55), rgba(193,154,92,0));
}

/* Version conmemorativa (la fecha ya paso) */
.tarjeta[data-aniversario] {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--pw) * .005);
}
.aniversario__numero {
  display: block;
  font-family: var(--f-script);
  font-size: calc(var(--pw) * .30);
  line-height: 1;
  color: var(--terracota-oscura);
}
.aniversario__texto {
  display: block;
  font-size: var(--t-sm);
  letter-spacing: .28em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--olivo-oscuro);
  text-indent: .28em;   /* compensa el espaciado de la ultima letra */
}

/* ---------------------------------------------------------------------
 * COLORES A EVITAR
 * -------------------------------------------------------------------*/
/*  Los discos son una MUESTRA, no el protagonista de la hoja: pequeños,
 *  en fila y con el nombre debajo. Se reparten solos, asi que da igual
 *  que en datos-evento.js haya dos tonos o cinco.                      */
.muestras {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: calc(var(--pw) * .028) calc(var(--pw) * .042);
}
.muestra { display: flex; flex-direction: column; align-items: center; gap: var(--s0); }
.muestra__disco {
  position: relative;
  width: calc(var(--pw) * .092);
  height: calc(var(--pw) * .092);
  border-radius: 50%;
  /* borde algo mas marcado: si no, el blanco puro desaparece sobre el papel */
  border: 1px solid rgba(120,90,70,.42);
  box-shadow: inset 0 -2px 6px rgba(0,0,0,.1), 0 1px 4px rgba(120,80,60,.14);
}
.muestra__disco::after {
  content: '';
  position: absolute;
  left: -6%;
  top: 50%;
  width: 112%;
  height: 1.5px;
  background: rgba(90,50,35,.66);
  transform: rotate(-42deg);
  transform-origin: center;
  border-radius: 2px;
}
.muestra__nombre {
  font-size: calc(var(--pw) * .026);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  text-indent: .16em;
}

/* ---------------------------------------------------------------------
 * DATOS PARA COPIAR
 * -------------------------------------------------------------------*/
.copia {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s1);
  width: 100%;
  padding: calc(var(--pw) * .028) calc(var(--pw) * .03);
  border: 1px solid rgba(193,154,92,.34);
  border-radius: calc(var(--pw) * .014);
  background: rgba(255,253,248,.62);
  text-align: left;
  overflow: hidden;
}
.copia + .copia { margin-top: var(--s1); }
.copia__icono {
  display: grid;
  place-items: center;
  width: calc(var(--pw) * .085);
  height: calc(var(--pw) * .085);
  flex: none;
  border-radius: 50%;
  color: var(--terracota-oscura);
  background: rgba(240,226,206,.75);
}
.copia__icono .ico { width: 56%; height: 56%; }
.copia__texto { flex: 1; min-width: 0; }
.copia__etiqueta {
  display: block;
  font-size: calc(var(--pw) * .026);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--olivo-oscuro);
}
.copia__valor {
  display: block;
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--terracota-oscura);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
  line-height: 1.3;
  white-space: nowrap;
}
/* Los numeros largos (la CCI son 20 digitos) bajan de cuerpo en vez de
   partirse en dos lineas y dejar una cifra suelta. */
.copia--largo .copia__valor {
  font-size: var(--t-sm);
  letter-spacing: -.005em;
}
.copia--xlargo .copia__valor {
  font-size: var(--t-xs);
  letter-spacing: -.01em;
}
.copia__boton {
  flex: none;
  display: grid;
  place-items: center;
  width: calc(var(--pw) * .095);
  height: calc(var(--pw) * .095);
  border-radius: 50%;
  color: var(--crema);
  background: linear-gradient(140deg, var(--terracota), var(--terracota-oscura));
  box-shadow: 0 2px 6px rgba(107,53,36,.25);
  transition: transform .2s ease;
}
.copia__boton .ico { width: 50%; height: 50%; }
.copia__boton:active { transform: scale(.9); }

/* confirmacion visual: la cinta verde entra deslizando */
.copia__aviso {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(140deg, #4f9a63, #2f6f45);
  transform: translate3d(0, 101%, 0);
  transition: transform .34s cubic-bezier(.2,.8,.3,1);
  pointer-events: none;
}
.copia__aviso .ico { width: 1.2em; height: 1.2em; }
.copia.copiado .copia__aviso { transform: translate3d(0,0,0); }

/* ---------------------------------------------------------------------
 * GALERIA
 * -------------------------------------------------------------------*/
.galeria {
  display: grid;
  /* Las columnas se reparten solas: 3 en el móvil y 4 o 5 en el libro
     abierto. Con 17 fotos, fijar 3 columnas dejaba media galería fuera
     de la hoja y había que adivinar que aquello se desplazaba. */
  grid-template-columns: repeat(auto-fill, minmax(calc(var(--pw) * .185), 1fr));
  gap: calc(var(--pw) * .022);
  width: 100%;
}
.galeria__pieza {
  position: relative;
  display: block;
  padding: 0;
  border-radius: calc(var(--pw) * .012);
  overflow: hidden;
  aspect-ratio: 3 / 4;
  background: rgba(226,210,186,.5);
  box-shadow: 0 2px 7px rgba(90,55,35,.18);
  transform: translate3d(0,0,0);
  transition: transform .3s cubic-bezier(.2,.8,.3,1), box-shadow .3s ease;
}
.galeria__pieza::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid rgba(255,248,238,.55);
  border-radius: inherit;
  pointer-events: none;
}
.galeria__pieza img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: translate3d(0,0,0);
  transition: transform .45s cubic-bezier(.2,.8,.3,1);
}
.galeria__pieza:hover { box-shadow: 0 6px 16px rgba(90,55,35,.28); }
.galeria__pieza:hover img { transform: scale(1.07); }
.galeria__pieza:active { transform: scale(.97); }
/* la miniatura de origen se apaga mientras su foto esta abierta */
.galeria__pieza.abierta { opacity: 0; }

/* ---------------------------------------------------------------------
 * VISOR (lightbox)
 * -------------------------------------------------------------------
 *  La apertura usa la tecnica FLIP: la foto grande aparece ya en su
 *  sitio final y se le aplica el transform que la hace coincidir con la
 *  miniatura; luego se suelta a identity. Solo transform y opacity.
 * -------------------------------------------------------------------*/
.visor {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: none;
  place-items: center;
  padding: max(14px, env(safe-area-inset-top)) 14px max(14px, env(safe-area-inset-bottom));
}
.visor.abierto { display: grid; }

.visor__fondo {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 100% at 50% 40%, rgba(48,26,17,.9), rgba(20,11,7,.97));
  opacity: 0;
  transition: opacity .32s ease;
}
.visor.pintado .visor__fondo { opacity: 1; }

.visor__marco {
  position: relative;
  z-index: 2;
  transform-origin: top left;
  /* Nada de will-change permanente: js/galeria.js lo pone justo antes de
     la animacion de apertura y lo retira al terminar. */
}
.visor__marco img {
  display: block;
  max-width: min(94vw, 900px);
  max-height: calc(100dvh - 130px);
  width: auto;
  height: auto;
  border-radius: 4px;
  box-shadow: 0 24px 60px rgba(0,0,0,.6);
}
.visor__marco .ramo {
  width: clamp(70px, 16vw, 130px);
  height: clamp(70px, 16vw, 130px);
  opacity: 0;
  transition: opacity .4s ease .12s;
}
.visor.pintado .visor__marco .ramo { opacity: .95; }

.visor__cerrar,
.visor__paso {
  position: absolute;
  z-index: 4;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--nude-claro);
  background: rgba(255,255,255,.09);
  border: 1px solid rgba(226,200,145,.3);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .3s ease, transform .25s ease, background-color .25s ease;
}
.visor.pintado .visor__cerrar,
.visor.pintado .visor__paso { opacity: 1; }
.visor__cerrar:hover, .visor__paso:hover { background: rgba(226,200,145,.22); transform: scale(1.08); }
.visor__cerrar .ico, .visor__paso .ico { width: 42%; height: 42%; }
.visor__cerrar { top: max(14px, env(safe-area-inset-top)); right: 14px; }
.visor__paso--prev { left: 12px;  top: 50%; margin-top: -22px; }
.visor__paso--next { right: 12px; top: 50%; margin-top: -22px; }
.visor__paso--prev .ico { transform: scaleX(-1); }

.visor__pie {
  position: absolute;
  left: 0; right: 0;
  /* Se sube por encima del boton flotante de confirmar, que ahora tambien
     vive aqui abajo a la izquierda y ya no se aparta. Subirlo funciona a
     cualquier ancho; recortarlo por los lados se quedaba sin sitio en un
     movil estrecho. */
  bottom: calc(max(16px, env(safe-area-inset-bottom)) + 52px);
  z-index: 4;
  text-align: center;
  font-size: 13px;
  letter-spacing: .2em;
  color: rgba(231,216,197,.75);
  opacity: 0;
  transition: opacity .3s ease;
  font-variant-numeric: tabular-nums;
}
.visor.pintado .visor__pie { opacity: 1; }

/* ---------------------------------------------------------------------
 * AUDIO FLOTANTE
 * -------------------------------------------------------------------*/
.audio {
  position: fixed;
  top: max(12px, env(safe-area-inset-top));
  right: max(12px, env(safe-area-inset-right));
  z-index: 70;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.audio__boton {
  position: relative;
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  flex: none;
  border-radius: 50%;
  color: var(--nude-claro);
  background: linear-gradient(145deg, rgba(140,75,51,.95), rgba(75,37,24,.95));
  border: 1px solid rgba(226,200,145,.45);
  box-shadow: 0 4px 14px rgba(0,0,0,.4);
  transform: translate3d(0,0,0);
  transition: transform .25s cubic-bezier(.2,.8,.3,1);
}
.audio__boton:hover  { transform: scale(1.06); }
.audio__boton:active { transform: scale(.94); }

/* la rosa que gira mientras suena */
.audio__rosa {
  position: absolute;
  width: 62%;
  height: 62%;
  animation: giroRosa 14s linear infinite;
  animation-play-state: paused;
  opacity: .95;
}
.audio.sonando .audio__rosa { animation-play-state: running; }
@keyframes giroRosa { to { transform: rotate(360deg); } }

/* el icono de play/pausa se cruza con la rosa */
.audio__estado {
  position: absolute;
  width: 17px;
  height: 17px;
  color: #fff;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
  opacity: 0;
  transition: opacity .25s ease;
}
.audio__boton:hover .audio__estado,
.audio:not(.sonando) .audio__estado { opacity: 1; }
.audio:not(.sonando) .audio__rosa   { opacity: .35; }

/* ondas que salen del boton cuando suena */
.audio__onda {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(226,200,145,.55);
  opacity: 0;
  pointer-events: none;
}
.audio.sonando .audio__onda { animation: ondaAudio 2.8s cubic-bezier(.2,.6,.4,1) infinite; }
.audio.sonando .audio__onda:nth-child(2) { animation-delay: .95s; }
@keyframes ondaAudio {
  0%   { transform: scale(1);    opacity: .65; }
  100% { transform: scale(2.05); opacity: 0; }
}

/* Latido cuando el navegador bloqueó el sonido y hace falta un toque.
   Se anima lo de DENTRO del boton (la rosa y los aros), nunca el boton en
   si: si el boton se moviera, el dedo apuntaria a un blanco movil. */
.audio.esperando .audio__onda {
  animation: ondaAudio 2.2s cubic-bezier(.2,.6,.4,1) infinite;
  border-color: rgba(226,200,145,.75);
}
.audio.esperando .audio__onda:nth-child(2) { animation-delay: .75s; }
.audio.esperando .audio__rosa {
  animation: latidoRosa 1.9s ease-in-out infinite;
  animation-play-state: running;
  opacity: .9;
}
@keyframes latidoRosa {
  0%, 100% { transform: scale(.9)  rotate(-9deg); }
  50%      { transform: scale(1.08) rotate(9deg); }
}

/* panel desplegable */
.audio__panel {
  overflow: hidden;
  border-radius: 26px;
  color: var(--nude-claro);
  background: linear-gradient(150deg, rgba(75,37,24,.96), rgba(45,22,14,.96));
  border: 1px solid rgba(226,200,145,.32);
  box-shadow: 0 8px 24px rgba(0,0,0,.42);
  transform-origin: top right;
  transform: translate3d(10px,0,0) scale(.86);
  opacity: 0;
  pointer-events: none;
  transition: transform .3s cubic-bezier(.2,.8,.3,1), opacity .24s ease;
  order: -1;
}
.audio.abierto .audio__panel {
  transform: translate3d(0,0,0) scale(1);
  opacity: 1;
  pointer-events: auto;
}
.audio__panel-int { padding: 11px 14px 13px; width: min(64vw, 232px); }

.audio__titulo {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--dorado-claro);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.audio__titulo .ico { width: 13px; height: 13px; flex: none; }
.audio__artista {
  font-size: 11px;
  font-style: italic;
  color: rgba(231,216,197,.62);
  margin-top: 1px;
}

.audio__mandos {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
}
.audio__mando {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 50%;
  color: var(--nude-claro);
  background: rgba(255,255,255,.09);
  border: 1px solid rgba(226,200,145,.26);
  transition: transform .18s ease, background-color .2s ease;
}
.audio__mando .ico { width: 15px; height: 15px; }
.audio__mando:hover  { background: rgba(226,200,145,.2); }
.audio__mando:active { transform: scale(.9); }
.audio__mando[aria-pressed="true"] { background: rgba(226,200,145,.3); color: #fff; }

/* barra de volumen: se rellena con scaleX, sin tocar el layout */
.audio__volumen {
  position: relative;
  flex: 1;
  height: 26px;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.audio__pista {
  position: relative;
  width: 100%;
  height: 3px;
  border-radius: 3px;
  background: rgba(231,216,197,.22);
  overflow: hidden;
}
.audio__relleno {
  position: absolute;
  inset: 0;
  transform-origin: left center;
  transform: scaleX(var(--vol, .55));
  background: linear-gradient(90deg, var(--dorado-oscuro), var(--dorado-claro));
  transition: transform .12s linear;
}
.audio__rango {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

/* En iOS el volumen lo manda el telefono: .volume no se puede escribir
   desde JavaScript (leerlo siempre devuelve 1). js/audio.js lo comprueba
   al arrancar y marca esta clase, para que los mandos que no harian nada
   se escondan en vez de mentir. El de silencio SI se queda: funciona por
   .muted, que si obedece en todas partes. */
.audio--sin-volumen .audio__mandos > :not([data-audio-mudo]) { display: none; }

/* ---------------------------------------------------------------------
 * AVISO GLOBAL (copiado, errores suaves)
 * -------------------------------------------------------------------*/
.brindis {
  position: fixed;
  left: 50%;
  bottom: max(18px, env(safe-area-inset-bottom));
  /* Por encima del boton flotante (105): es un aviso, y un aviso tapado
     no sirve de nada. */
  z-index: 112;
  display: flex;
  align-items: center;
  gap: .55em;
  padding: .6em 1.15em;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--crema);
  background: linear-gradient(140deg, rgba(75,37,24,.97), rgba(45,22,14,.97));
  border: 1px solid rgba(226,200,145,.36);
  box-shadow: 0 8px 22px rgba(0,0,0,.4);
  transform: translate3d(-50%, 130%, 0);
  opacity: 0;
  pointer-events: none;
  transition: transform .38s cubic-bezier(.2,.8,.3,1), opacity .28s ease;
}
.brindis .ico { width: 15px; height: 15px; color: var(--dorado-claro); }
.brindis.visible { transform: translate3d(-50%, 0, 0); opacity: 1; }

/* ---------------------------------------------------------------------
 * EL TELON DE ENTRADA  ·  la cara exterior del libro
 * ---------------------------------------------------------------------
 *  Papel crema, doble filete dorado y las rosas de verdad (img/rosas/)
 *  en dos esquinas opuestas. Pertenece a la misma familia que la portada
 *  del libro: mismos tonos, misma caligrafia, misma filigrana.
 *
 *  NO SE QUITA SOLO: espera un toque, y ese toque es el que arranca la
 *  cancion (js/app.js, prepararTelon). De ahi dos cosas que parecen
 *  cosmeticas y no lo son:
 *    · touch-action: none  -> sin esto el navegador toma un arrastre por
 *      un scroll y NO concede el permiso de reproducir.
 *    · todo va en linea (SVG y degradados): el telon se pinta ANTES de
 *      que corra ningun JavaScript, asi que no puede depender de las
 *      variables que deja js/svg.js (--img-rosa y compania).
 * -------------------------------------------------------------------*/
.telon {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  place-items: center;
  padding: max(18px, env(safe-area-inset-top)) 18px max(18px, env(safe-area-inset-bottom));
  overflow: hidden;
  touch-action: none;
  cursor: pointer;
  /* Papel: un crema calido con vineta suave por las esquinas y un tramado
     finisimo que le da grano sin pesar un solo byte. */
  background:
    radial-gradient(118% 88% at 50% 8%,  rgba(255,252,246,.96) 0%, rgba(250,243,232,0) 62%),
    radial-gradient(130% 100% at 50% 108%, rgba(226,196,168,.42) 0%, rgba(226,196,168,0) 58%),
    radial-gradient(64% 34% at 50% 46%, rgba(255,253,249,.75) 0%, rgba(255,253,249,0) 70%),
    repeating-linear-gradient(51deg,  rgba(150,115,58,.016) 0 1px, transparent 1px 13px),
    repeating-linear-gradient(-51deg, rgba(150,115,58,.013) 0 1px, transparent 1px 17px),
    linear-gradient(168deg, #fdf8f1 0%, #f8efe2 46%, #f0e2ce 100%);
  transition: opacity .7s ease, visibility .7s;
}
.telon.fuera { opacity: 0; visibility: hidden; }

/* --- el doble filete dorado ---------------------------------------- */
.telon__marco {
  position: absolute;
  inset: clamp(10px, 3.2vmin, 22px);
  pointer-events: none;
  border: 1px solid rgba(193,154,92,.52);
}
.telon__marco::after {
  content: '';
  position: absolute;
  inset: clamp(4px, 1.1vmin, 7px);
  border: 1px solid rgba(193,154,92,.26);
}

/* --- las rosas de verdad, en dos esquinas opuestas ------------------
 * Una sola imagen (img/rosas/esquina.webp, 49 KB) servida dos veces: la
 * de abajo es la misma girada 180deg. Es el mismo ramo que ya usan las
 * hojas del libro, asi que el telon y el libro son el mismo objeto.
 * Si tarda en llegar no pasa nada: el telon ya esta compuesto sin ella.
 * ------------------------------------------------------------------ */
.telon__ramo {
  position: absolute;
  /* Generosas: son el alma del telon. Se miden contra el ANCHO y contra el
     ALTO a la vez para que no manden sobre ninguna de las dos (con un
     clamp() de suelo fijo se comian el 59% de un movil de 320; con vmin
     solo, tumbado tapaban media pantalla). Que rocen el texto es a
     proposito: el texto va por encima, con su velo. */
  width: min(66vw, 38vh, 520px);
  aspect-ratio: 500 / 508;
  /* OJO: la ruta es relativa a ESTE archivo (css/), no a index.html. */
  background: url('../img/rosas/esquina.webp') center/contain no-repeat;
  pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(140,86,60,.16));
  opacity: 0;
  transform: scale(.94);
  transition: opacity 1.1s ease .12s, transform 1.4s cubic-bezier(.2,.75,.3,1) .12s;
}
/* A RAS DE LA ESQUINA. Probe a sangrarlo como hacen las hojas del libro
   (.ramo--ai va a -6%) y se pierde justo lo que importa: el racimo denso
   vive en la esquina del propio arte, asi que al sangrarlo solo quedan los
   tallos. A ras se ven las tres flores enteras y el ramo luce. */
.telon__ramo--ai { top: 0; left:  0; }
.telon__ramo--bd { bottom: 0; right: 0; transform: scale(.94) rotate(180deg); }
.telon.listo .telon__ramo--ai { opacity: .97; transform: scale(1); }
.telon.listo .telon__ramo--bd { opacity: .97; transform: scale(1) rotate(180deg); }

/* --- el bloque central --------------------------------------------- */
/* El bloque de texto va SIEMPRE por encima de las rosas (z-index 2 crea su
   propio contexto: todo lo suyo, pseudoelemento incluido, pinta por delante
   del ramo). Y debajo lleva un velo de papel muy difuso —un degradado
   radial, sin blur: un blur sobre media pantalla cuesta fotogramas y esto
   es la pantalla de carga— para que las letras se lean limpias aunque
   caigan sobre un petalo. Las flores se siguen viendo alrededor: no se
   tapan, se posan. */
.telon__int::before {
  content: '';
  position: absolute;
  inset: -20% -15%;
  z-index: -1;
  pointer-events: none;
  /* Llega hasta el rotulo de arriba y la pista de abajo: en un movil de
     320 son justo las dos lineas que quedaban debajo de una hoja. */
  background: radial-gradient(64% 58% at 50% 50%,
    rgba(253,248,241,.96) 0%,
    rgba(253,248,241,.90) 44%,
    rgba(253,248,241,.56) 68%,
    rgba(253,248,241,0)   88%);
  opacity: 0;
  transition: opacity 1s ease;
}
.telon.listo .telon__int::before { opacity: 1; }

.telon__int {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 30rem;
  width: 100%;
}

/* Cada pieza entra por su cuenta, escalonada: el ojo las lee en orden
   en vez de recibirlas todas de golpe. */
.telon__int > * {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity .85s ease, transform .95s cubic-bezier(.2,.75,.3,1);
}
.telon.listo .telon__int > * { opacity: 1; transform: none; }
.telon.listo .telon__rotulo  { transition-delay: .06s; }
.telon.listo .telon__nombres { transition-delay: .20s; }
.telon.listo .telon__hilo    { transition-delay: .40s; }
.telon.listo .telon__fecha   { transition-delay: .50s; }
.telon.listo .telon__lugar   { transition-delay: .58s; }
.telon.listo .telon__abrir   { transition-delay: .74s; }
.telon.listo .telon__pista   { transition-delay: .90s; }

.telon__rotulo {
  margin: 0 0 clamp(6px, 1.6vmin, 12px);
  font-family: var(--f-libro);
  font-size: clamp(10px, 2.9vmin, 13px);
  font-weight: 600;
  letter-spacing: .46em;
  text-indent: .46em;
  text-transform: uppercase;
  color: var(--olivo-oscuro);
}

.telon__nombres {
  margin: 0;
  font-family: var(--f-script);
  font-weight: 400;
  line-height: .92;
  color: var(--terracota-oscura);
  font-size: clamp(46px, 15.5vmin, 104px);
  text-shadow: 0 1px 0 rgba(255,255,255,.85), 0 0 14px rgba(253,248,241,.9);
}
.telon__nombres em {
  display: block;
  font-family: var(--f-libro);
  font-style: normal;
  font-size: .34em;
  line-height: 1;
  color: var(--dorado);
  margin-block: .05em .01em;
  letter-spacing: .04em;
  text-shadow: 0 1px 0 rgba(255,255,255,.8);
}

/* La filigrana dorada de js/svg.js, en linea: cero peso, llega ya pintada */
.telon__hilo {
  width: clamp(168px, 54vmin, 260px);
  height: auto;
  margin: clamp(10px, 2.6vmin, 18px) 0 clamp(9px, 2.2vmin, 15px);
  color: var(--dorado);
}

.telon__fecha {
  margin: 0;
  font-family: var(--f-libro);
  font-size: clamp(12px, 3.4vmin, 15px);
  font-weight: 600;
  letter-spacing: .34em;
  text-indent: .34em;
  text-transform: uppercase;
  color: var(--olivo-oscuro);
}
.telon__lugar {
  margin: clamp(4px, 1.2vmin, 7px) 0 0;
  font-family: var(--f-libro);
  font-size: clamp(11px, 3vmin, 13.5px);
  font-style: italic;
  letter-spacing: .07em;
  color: var(--tinta-tenue);
}

/* --- el boton ------------------------------------------------------
 * Terracota como el resto de botones del libro, pero mas fino: filete
 * dorado, versalitas muy espaciadas y un halo que late despacio para
 * que se entienda que hay que tocar. El halo va en un <span> aparte:
 * asi late lo de dentro y el boton no se mueve (un blanco movil es
 * mas dificil de acertar con el dedo).
 * ----------------------------------------------------------------- */
.telon__abrir {
  position: relative;
  margin-top: clamp(20px, 5vmin, 34px);
  padding: clamp(12px, 2.6vmin, 15px) clamp(26px, 6.6vmin, 40px);
  border-radius: 999px;
  border: 1px solid rgba(226,200,145,.85);
  background:
    linear-gradient(180deg, rgba(255,255,255,.20) 0%, rgba(255,255,255,0) 52%),
    linear-gradient(135deg,
      var(--terracota-clara) 0%, var(--terracota) 46%, var(--terracota-oscura) 100%);
  color: var(--crema);
  text-shadow: 0 1px 2px rgba(92,40,24,.4);
  font-family: var(--f-libro);
  font-size: clamp(11.5px, 3.1vmin, 14px);
  font-weight: 600;
  letter-spacing: .24em;
  text-indent: .24em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(140,70,45,.30), 0 2px 4px rgba(140,70,45,.18), inset 0 1px 0 rgba(255,255,255,.34);
  transition: transform .18s cubic-bezier(.2,.8,.3,1), box-shadow .2s ease;
}
.telon__abrir:hover  { box-shadow: 0 10px 26px rgba(140,70,45,.32), inset 0 1px 0 rgba(255,255,255,.36); }
.telon__abrir:active { transform: translate3d(0,1px,0) scale(.97); }
.telon__abrir:focus-visible { outline: 2px solid var(--dorado-oscuro); outline-offset: 4px; }

.telon__halo {
  position: absolute;
  inset: -1px;
  border-radius: 999px;
  pointer-events: none;
  animation: telonLatido 3.4s cubic-bezier(.22,.61,.36,1) infinite;
}
@keyframes telonLatido {
  0%        { box-shadow: 0 0 0 0    rgba(207,136,120,.55); }
  60%, 100% { box-shadow: 0 0 0 16px rgba(207,136,120,0); }
}
.telon__abrir:hover .telon__halo { animation-play-state: paused; }

.telon__pista {
  margin: clamp(11px, 2.6vmin, 16px) 0 0;
  font-family: var(--f-libro);
  font-size: clamp(10.5px, 2.8vmin, 12.5px);
  font-style: italic;
  letter-spacing: .08em;
  color: var(--tinta-tenue);
  opacity: .82;
}

/* Pantallas anchas: el bloque no debe nadar en el centro de un monitor */
@media (min-width: 900px) {
  .telon__int { max-width: 34rem; }
  .telon__nombres { font-size: clamp(72px, 8.4vw, 116px); }
  /* Aqui sobra sitio: el ramo puede lucirse sin acercarse al texto */
  .telon__ramo { width: min(38vw, 58vh, 560px); }
}

@media (prefers-reduced-motion: reduce) {
  .telon__int > *, .telon__ramo { transition: opacity .4s ease; transform: none; }
  .telon.listo .telon__ramo--bd { transform: rotate(180deg); }
  .telon__ramo--bd { transform: rotate(180deg); }
  .telon__halo { animation: none; box-shadow: 0 0 0 4px rgba(207,136,120,.3); }
}

/* ---------------------------------------------------------------------
 * MODAL DE DESPEDIDA
 * -------------------------------------------------------------------
 *  El segundo aviso del final: sale cuando el invitado ya está en la
 *  contratapa e insiste en avanzar.
 *
 *  Se anima solo con opacity y transform, como todo lo demás. El velo
 *  lleva un desenfoque muy corto: se pinta una vez al abrir y detrás no
 *  se mueve nada, así que no cuesta fotogramas.
 * -------------------------------------------------------------------*/
.final {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: max(18px, env(safe-area-inset-top)) 18px max(18px, env(safe-area-inset-bottom));
  visibility: hidden;
  opacity: 0;
  transition: opacity .34s ease, visibility .34s;
}
.final.abierto { visibility: visible; opacity: 1; }

.final__fondo {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 100% at 50% 40%, rgba(52,28,17,.72), rgba(20,11,7,.92));
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}

.final__tarjeta {
  position: relative;
  z-index: 2;
  width: min(92vw, 420px);
  text-align: center;
  padding: clamp(26px, 6vw, 42px) clamp(22px, 6vw, 40px) clamp(24px, 5vw, 36px);
  border-radius: 4px;
  border: 1px solid rgba(226,200,145,.34);
  background:
    radial-gradient(72% 52% at 50% 42%, rgba(226,200,145,.13), rgba(226,200,145,0) 72%),
    repeating-linear-gradient( 62deg, rgba(226,200,145,.05) 0 1px, rgba(226,200,145,0) 1px 22px),
    repeating-linear-gradient(-62deg, rgba(226,200,145,.05) 0 1px, rgba(226,200,145,0) 1px 22px),
    linear-gradient(150deg, #7e4130 0%, #62311f 55%, #47210f 100%);
  box-shadow: 0 24px 60px rgba(0,0,0,.6), inset 0 0 0 1px rgba(255,214,176,.08);
  transform: translateY(18px) scale(.94);
  transition: transform .42s cubic-bezier(.2,.8,.3,1);
}
.final.abierto .final__tarjeta { transform: translateY(0) scale(1); }

/* filo dorado interior, como el de la tapa */
.final__tarjeta::before {
  content: '';
  position: absolute;
  inset: 7px;
  border: 1px solid rgba(226,200,145,.2);
  border-radius: 3px;
  pointer-events: none;
}

.final__rosa {
  width: clamp(52px, 13vw, 72px);
  height: clamp(52px, 13vw, 72px);
  margin: 0 auto clamp(10px, 2.5vw, 16px);
}
.final__titulo {
  margin: 0;
  font-family: var(--f-script);
  font-size: clamp(38px, 10vw, 58px);
  line-height: 1;
  color: var(--dorado-claro);
}
.final__texto {
  margin: clamp(10px, 2.5vw, 16px) 0 0;
  font-size: clamp(14px, 3.6vw, 17px);
  line-height: 1.6;
  color: rgba(243,233,220,.8);
  text-wrap: balance;
}
.final__firma {
  margin: clamp(12px, 3vw, 18px) 0 0;
  font-family: var(--f-script);
  font-size: clamp(22px, 5.5vw, 30px);
  line-height: 1;
  color: rgba(226,200,145,.72);
}
.final__boton {
  margin-top: clamp(18px, 4vw, 26px);
  font-size: clamp(11px, 2.8vw, 13px);
  color: var(--dorado-claro);
  background: rgba(255,255,255,.07);
  border-color: rgba(226,200,145,.42);
  box-shadow: none;
}
.final__boton:hover { background: rgba(226,200,145,.18); }

.final__cerrar {
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  color: rgba(231,216,197,.66);
  transition: color .2s ease, background-color .2s ease;
}
.final__cerrar .ico { width: 40%; height: 40%; }
.final__cerrar:hover { color: var(--nude-claro); background: rgba(255,255,255,.08); }

/* Con movimiento reducido, sin recorridos: solo aparece */
@media (prefers-reduced-motion: reduce) {
  .final__tarjeta { transform: none; }
  .final.abierto .final__tarjeta { transform: none; }
}
