/* ==========================================================================
   ESTILO EDITORIAL — hoja principal de la invitacion
   ==========================================================================
   Sale del diseno empaquetado que traia todo en base64 dentro de index.html.
   Aqui va tal cual, con dos cambios:

     1. Las @font-face apuntan a fonts/ en vez de a los blobs del paquete, y
        solo quedan los subsets latin y latin-ext. Los de cirilico y vietnamita
        que traia Google Fonts no los pisa nunca una invitacion en espanol.

     2. El diseno usaba <image-slot>, un elemento propio del editor que montaba
        la foto en un shadow DOM. Ya no existe: son <img class="ph"> normales, y
        las reglas que lo nombraban ahora nombran img. El recorte que hacia el
        editor (centrado, sin deformar) lo hace object-fit:cover mas abajo.

   La paleta va escrita a pelo, como en el diseno original: #42251a (cafe),
   #f0e9d8 (papel) y #f6f1e4 (papel claro). No hay tokens que cambiar.
   ========================================================================== */

/* ==========================================================================
   1 · TIPOGRAFIAS
   ==========================================================================
   Cormorant (serif), Courier Prime (el cuerpo, monoespaciada) y Monsieur La
   Doulaise (la cursiva de los nombres). Van servidas desde el propio dominio:
   asi la invitacion no depende de fonts.gstatic.com, que es justo la clase de
   peticion que se cae en la WebView de WhatsApp o con mala cobertura.
   font-display:swap deja leer el texto mientras llega la fuente.
   ========================================================================== */

/* latin-ext */
@font-face {
  font-family: 'Cormorant';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/cormorant-italic-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Cormorant';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/cormorant-italic-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Cormorant';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/cormorant-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Cormorant';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/cormorant-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Cormorant';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/cormorant-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Cormorant';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/cormorant-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Courier Prime';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/courier-prime-italic-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Courier Prime';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/courier-prime-italic-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Courier Prime';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/courier-prime-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Courier Prime';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/courier-prime-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Monsieur La Doulaise';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/monsieur-la-doulaise-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Monsieur La Doulaise';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/monsieur-la-doulaise-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

body { margin:0; background:#42251a; }
a { color:#42251a; } a:hover { color:#6b4630; }
.rv-on [data-reveal] { opacity:0; transform:translateY(14px);
      transition:opacity 1.05s ease .06s, transform 1.15s cubic-bezier(.16,1,.3,1); }
img { max-width:100%; }
input, button { font:inherit; }
input:focus-visible, button:focus-visible, a:focus-visible { outline:2px solid #42251a; outline-offset:3px; }

/* ---- galería con lightbox ---- */
[data-lightbox] { transition:opacity .3s ease; }
[data-lightbox]:hover { opacity:.86; }

/* ---- revelado por mascara en la galeria ----
   Adaptado de la septima formacion de On-Scroll Layout Formations (Codrops, MIT).
   El original usa GSAP + ScrollTrigger con la seccion anclada; aqui son dos capas
   que se cruzan y el disparo lo hace el IntersectionObserver que ya existia, sin
   anclar el scroll y sin dependencias nuevas. */
.rv-on [data-mask] { opacity:1; transform:none; overflow:hidden; }
.rv-on [data-mask] .mk,
.rv-on [data-mask] .mk-i { display:block; height:100%; }
.rv-on [data-mask] .mk { overflow:hidden; transform:translateY(-101%);
      transition:transform 1.05s cubic-bezier(.22,.75,.28,1); }
.rv-on [data-mask] .mk-i { transform:translateY(101%);
      transition:transform 1.05s cubic-bezier(.22,.75,.28,1); }
.rv-on [data-mask][data-shown] .mk,
.rv-on [data-mask][data-shown] .mk-i { transform:none; }
/* las cinco de la fila entran escalonadas, como el stagger del original */
.gal-row > [data-mask]:nth-child(2) .mk, .gal-row > [data-mask]:nth-child(2) .mk-i { transition-delay:.08s; }
.gal-row > [data-mask]:nth-child(3) .mk, .gal-row > [data-mask]:nth-child(3) .mk-i { transition-delay:.16s; }
.gal-row > [data-mask]:nth-child(4) .mk, .gal-row > [data-mask]:nth-child(4) .mk-i { transition-delay:.24s; }
.gal-row > [data-mask]:nth-child(5) .mk, .gal-row > [data-mask]:nth-child(5) .mk-i { transition-delay:.32s; }
@media (prefers-reduced-motion: reduce) {
  .rv-on [data-mask] .mk, .rv-on [data-mask] .mk-i { transform:none; transition:none; }
}

/* ---- 3 · el revelado se reproduce con el scroll y se rebobina al subir ----
   view() ata la animacion a la posicion de scroll, asi que al ir hacia arriba
   se deshace sola. Solo CSS. Donde no haya soporte queda el disparo por
   IntersectionObserver de mas arriba, que ya funcionaba. */
@supports (animation-timeline: view()) {
  /* la celda recorta con overflow:hidden, asi que ella misma seria el puerto de
     scroll de un view() puesto en las capas. Se nombra la linea aqui, donde el
     puerto si es la pagina, y las capas de dentro la referencian. */
  .rv-on [data-mask] { view-timeline-name:--celda; view-timeline-axis:block; }
  .rv-on [data-mask] .mk,
  .rv-on [data-mask] .mk-i { transition:none; animation-fill-mode:both;
        animation-duration:auto; animation-timeline:--celda;
        animation-range:cover 6% cover 50%; }
  .rv-on [data-mask] .mk   { animation-name:mk-marco; }
  .rv-on [data-mask] .mk-i { animation-name:mk-foto; }
  .gal-row > [data-mask]:nth-child(2) .mk, .gal-row > [data-mask]:nth-child(2) .mk-i { animation-range:cover 10% cover 54%; }
  .gal-row > [data-mask]:nth-child(3) .mk, .gal-row > [data-mask]:nth-child(3) .mk-i { animation-range:cover 14% cover 58%; }
  .gal-row > [data-mask]:nth-child(4) .mk, .gal-row > [data-mask]:nth-child(4) .mk-i { animation-range:cover 18% cover 62%; }
  .gal-row > [data-mask]:nth-child(5) .mk, .gal-row > [data-mask]:nth-child(5) .mk-i { animation-range:cover 22% cover 66%; }
}
@keyframes mk-marco { from { transform:translateY(-101%) } to { transform:none } }
@keyframes mk-foto  { from { transform:translateY(101%) }  to { transform:none } }

/* ---- portada a sangre ----
   El contenedor de 1180px dejaba crema muerta a la derecha y un hueco entre
   columnas: la foto se leia encajonada. La rejilla ya ocupa todo el ancho
   (se le quito el max-width en el markup); aqui el texto recupera la
   alineacion con el resto de la invitacion sumando ese margen. */
@media (min-width:640px) {
  .pt-texto { padding-left:calc(max(0px, (100vw - 1180px) / 2) + clamp(26px,5vw,70px)) !important; }
}
/* la tira de bloques se leia como un corte en la foto, no como perforacion */
.pt-perf { display:none; }

/* ---- galeria: segunda formacion de On-Scroll Layout Formations (Codrops, MIT) ----
   Replica de la demo original con sus mismas medidas y valores:
     rejilla de 5 columnas, gap = --page-padding (0.5rem; 1rem desde 53em)
     imagenes en aspect-ratio 2/3, transform-origin 50% 0%
     seccion anclada 250% de pantalla, scrub 0.5
     entran desde y = 100vh, giros +6 +3 0 -3 -6 grados
     escalonado {amount:0.3, from:'center'} con easing power3
   El original usa GSAP + ScrollTrigger; aqui el avance lo escribe el mismo
   listener de scroll que ya existe, para no meter dependencias. */
.gal-pin { --pad:0.5rem; height:350vh;
      width:100vw; margin-left:calc(50% - 50vw); }
@media (min-width:53em) { .gal-pin { --pad:1rem; } }
.gal-stick { position:sticky; top:0; height:100vh; height:100dvh;
      display:grid; align-content:center;
      padding:var(--pad); box-sizing:border-box; }
.gal-grid { display:grid; width:100%; height:100%; min-width:0;
      grid-template-columns:repeat(5,1fr); grid-template-rows:repeat(2,min-content);
      align-content:center; gap:var(--pad); }
/* igual que en la demo: el 16/9 solo entra si la pantalla es mas angosta que 16/9 */
@media (max-aspect-ratio: 16/9) { .gal-grid { height:auto; aspect-ratio:16/9; } }
.rv-on .gal-grid > [data-mask],
.gal-grid > [data-mask] { width:100%; height:min-content; aspect-ratio:2/3 !important;
      /* sin esto los items de grid no bajan de su ancho de contenido y
         desbordan la rejilla en pantallas angostas */
      min-width:0; min-height:0;
      margin:0 !important; transform-origin:50% 0%; will-change:transform;
      transform:translate3d(0, calc(var(--y, 0) * 1px), 0.1px)
                rotate(calc(var(--r, 0) * 1deg)) !important;
      transition:none !important; }
/* la formacion sustituye al revelado por mascara en estas cinco */
.rv-on .gal-grid > [data-mask] .mk,
.rv-on .gal-grid > [data-mask] .mk-i { transform:none; transition:none; animation:none; }

/* ---- en movil, baraja que se apila ----
   La demo original mantiene 5 columnas en cualquier ancho: en un telefono de
   390px eso deja fotos de 68x103px. Aqui las cinco pasan a ocupar el centro de
   la pantalla, cayendo una sobre otra ladeadas, como fotos impresas sobre una
   mesa. Cada una mide 329x494px, casi cinco veces el area anterior. */
@media (max-width: 700px) {
  .gal-pin { height:420vh; }
  /* solo se cambia el display: si se toca position, se pierde el sticky
     y la seccion deja de anclarse */
  .gal-stick { display:block; }
  .gal-grid { position:absolute; inset:0; display:block; height:auto; aspect-ratio:auto; }
  .rv-on .gal-grid > [data-mask],
  .gal-grid > [data-mask] { position:absolute; inset:0;
      /* !important: la regla base fija margin:0 !important y sin esto las
         fotos se apilan pegadas a la izquierda en vez de al centro */
      margin:auto !important;
      width:86%; height:auto; aspect-ratio:2/3 !important;
      transform-origin:50% 50%;
      transform:translate(calc(var(--x, 0) * 1px), calc(var(--y, 120) * 1%))
                rotate(calc(var(--r, 0) * 1deg)) !important;
      /* !important porque el revelado escribe opacity:1 en el style inline */
      opacity:var(--o, 0) !important;
      box-shadow:0 18px 40px rgba(0,0,0,.45); }
}
@media (prefers-reduced-motion: reduce) {
  .gal-pin { height:auto; width:auto; margin-left:0; }
  .gal-stick { position:static; height:auto; }
  .rv-on .gal-grid > [data-mask],
  .gal-grid > [data-mask] { transform:none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .rv-on [data-mask] .mk, .rv-on [data-mask] .mk-i { animation:none; transform:none; }
}

/* ---- 4 · itinerario: que / donde / hora ---- */
/* jerarquia del itinerario: sede, luego direccion apagada, luego hora */
.it-sede { font-family:'Cormorant', serif; font-size:clamp(21px,1.8vw,26px); }
.it-dir { font-size:clamp(14px,1vw,15px); margin-top:8px; line-height:1.6;
      color:rgba(66,37,26,.6); max-width:38ch; }
.it-hora { font-family:'Cormorant', serif; font-size:clamp(19px,1.6vw,23px);
      letter-spacing:.1em; margin-top:14px; }
/* variante sobre fondo oscuro */
.oscuro .it-dir { color:rgba(240,233,216,.62); }
.oscuro .it-link { border-bottom-color:rgba(240,233,216,.45); }
.oscuro .it-link:hover { border-bottom-color:#f0e9d8; }
.it-link { display:inline-flex; align-items:center; gap:9px; margin-top:18px; padding:12px 2px;
      font-size:12.5px; letter-spacing:.14em; text-transform:uppercase; text-decoration:none;
      color:inherit; border-bottom:1px solid rgba(66,37,26,.5); transition:border-color .3s; }
.it-link:hover { border-bottom-color:#42251a; color:inherit; }
.it-link span { transition:transform .3s; }
.it-link:hover span { transform:translateX(4px); }
/* En escritorio el itinerario tambien tiene que leerse de un vistazo: titulo
   y sede crecen, la direccion sube a 16-17px y menos apagada (al .6 no llegaba
   a 4.5:1), y la hora pasa a Courier como en movil: en Cormorant los numeros
   son de caja baja (el 1 y el 0 miden lo que una x) y "16:00" se leia chico.
   El !important del h3 es para ganarle a su style inline.
   Solo desde 701px, para no tocar el movil, y colgado de .it-ev, porque
   Hospedaje usa .it-dir e .it-link y ahi no cambia nada. */
@media (min-width: 701px) {
  .it-ev .it-cab h3 { font-size:clamp(24px,2.1vw,30px) !important; }
  .it-ev .it-sede { font-size:clamp(24px,2.1vw,30px); }
  .it-ev .it-dir { font-size:clamp(16px,1.2vw,17px); line-height:1.55; margin-top:10px;
      color:rgba(66,37,26,.78); }
  .it-ev .it-hora { font-family:'Courier Prime', monospace; font-size:clamp(18px,1.5vw,21px);
      letter-spacing:.08em; margin-top:16px; }
  .it-ev .it-link { font-size:13.5px; }
}

/* ---- 5 · el codigo de vestimenta, bien visible ---- */
.dc-codigo { display:inline-block; border:1.5px solid currentColor; border-radius:100px;
      padding:12px 30px; margin-top:18px; font-family:'Cormorant', serif;
      font-size:clamp(20px,2.1vw,27px); letter-spacing:.2em; text-transform:uppercase; line-height:1; }

/* ---- rayado del panel ----
   Un numero impar de franjas iguales: asi el panel siempre abre y cierra
   con franja cafe del mismo ancho, a cualquier medida de pantalla.
   El gradiente va en un ::before para poder consultar el ancho del panel. */
.pnl-rayas { container-type:inline-size; background-image:none !important; }
.pnl-rayas::before { content:''; position:absolute; inset:0; --n:9;
      background:repeating-linear-gradient(90deg,
          #42251a 0 calc(100% / var(--n)),
          #f0e9d8 calc(100% / var(--n)) calc(200% / var(--n))); }
/* de dos en dos, para que cada franja siga rondando los 30px */
@container (min-width: 245px) { .pnl-rayas::before { --n:11; } }
@container (min-width: 305px) { .pnl-rayas::before { --n:13; } }
@container (min-width: 365px) { .pnl-rayas::before { --n:15; } }
@container (min-width: 425px) { .pnl-rayas::before { --n:17; } }
@container (min-width: 485px) { .pnl-rayas::before { --n:19; } }
@container (min-width: 545px) { .pnl-rayas::before { --n:21; } }
@container (min-width: 605px) { .pnl-rayas::before { --n:23; } }
.pnl-rayas > .mrc { z-index:1; }

/* ---- marco ovalado de plata ---- */
.mrc { position:relative; width:min(500px,100%); aspect-ratio:498/640; margin:0 auto;
      filter:drop-shadow(0 22px 40px rgba(0,0,0,.5)); }
/* el crema asoma por el hueco del marco, que esta recortado */
.mrc-int { position:absolute; inset:18.3% 22.8% 17.8% 22.6%; border-radius:50%;
      background:#f6f1e4; box-shadow:inset 0 3px 10px rgba(60,50,40,.16); }
.mrc-img { position:absolute; inset:0; width:100%; height:100%; display:block; }
.mrc-txt { position:absolute; inset:22% 27%; display:flex; flex-direction:column;
      align-items:center; justify-content:center; gap:clamp(12px,1.8vw,18px);
      text-align:center; color:#42251a; }
.mrc-tit { font-family:'Cormorant', serif; font-size:clamp(17px,1.6vw,21px);
      letter-spacing:.24em; text-transform:uppercase; }


/* ---- 6 · rotulos de familia ---- */
.fam-rot { font-family:'Courier Prime', monospace; font-size:12px; letter-spacing:.16em;
      text-transform:uppercase; opacity:.7; margin-bottom:7px; }
.fam-nom { font-family:'Cormorant', serif; font-size:15.5px; line-height:1.45; }
.fam-rot + .fam-nom { margin-top:-1px; }

/* ---- itinerario en movil: las tres partes seguidas ----
   En escritorio son dos columnas: la 1 lleva el bloque 01 con su foto y la 2
   lleva 02 y 03 con las suyas. Al apilarse en el telefono el orden queda
   01, foto, 02, 03, foto, foto, y esa foto parte el hilo de la lista.
   Aqui las columnas se disuelven con display:contents y se reordenan los
   bloques para que se lea 01, 02, 03 de corrido y las fotos queden al final. */
@media (max-width: 700px) {
  /* Las dos columnas se disuelven para que los tres eventos se lean
     de corrido; las fotos se van al final.
     !important: el gap va en el style inline de la rejilla, y con las
     columnas disueltas se aplicaria entre todos los bloques. */
  .it-rejilla { gap:0 !important; }
  .it-rejilla > div { display:contents; }
  .it-esp { display:none; }
  .it-ev1 { order:1; } .it-ev2 { order:2; } .it-ev3 { order:3; }
  .it-foto1 { order:4; margin-top:30px !important; }
  .it-fotos { order:5; }

  /* Editorial: sin cajas. Una regla gruesa separa cada evento y el numero
     va grande y tenue, que es el lenguaje del resto de la invitacion.
     Se disuelven la cabecera y el detalle para poder llevar la hora a la
     primera fila, junto al titulo, sin tocar el marcado. */
  .it-ev { display:grid; grid-template-columns:auto 1fr auto;
      align-items:baseline; column-gap:11px;
      padding:21px 0 23px; border-top:2px solid #42251a; }
  /* el titulo de la seccion ya trae su propio filete: sin esto se ven dos */
  .it-ev1 { border-top:0; padding-top:2px; }
  /* Todo lo de abajo va colgado de .it-ev: las clases it-link e it-dir
     tambien las usa Hospedaje, y sin acotar le rompian la rejilla. */
  .it-ev .it-cab, .it-ev .it-det { display:contents !important; }

  .it-ev .it-num { grid-column:1; grid-row:1;
      font-family:'Cormorant', serif; font-size:30px !important;
      line-height:1 !important; letter-spacing:0 !important;
      opacity:.28 !important; }
  .it-ev .it-cab > div + div { grid-column:2; grid-row:1; font-size:20px !important; }
  /* Hora, sede y direccion son lo que el invitado viene a buscar: van a un
     tamano que se lee sin acercarse el telefono, y la direccion menos
     apagada que en escritorio (al .6 no llegaba a contraste 4.5:1). */
  .it-ev .it-hora { grid-column:3; grid-row:1; justify-self:end;
      font-family:'Courier Prime', monospace !important;
      font-size:16px !important; letter-spacing:.08em !important;
      white-space:nowrap; margin-top:0 !important; }
  .it-ev .it-sede { grid-column:1 / -1; grid-row:2; margin-top:11px; font-size:20px; }
  .it-ev .it-dir { grid-column:1 / -1; grid-row:3; max-width:none;
      font-size:16px; line-height:1.5; color:rgba(66,37,26,.78); }
  /* El filete del enlace cuelga 12px bajo el texto (ese padding es el area
     de toque) y ahi se leia como una regla suelta, compitiendo con la del
     evento. Se pinta con un ::after pegado al texto y se conserva el toque. */
  .it-ev .it-link { grid-column:1 / -1; grid-row:4; justify-self:start;
      margin-top:5px; position:relative; border-bottom:0 !important; }
  .it-ev .it-link::after { content:''; position:absolute; left:2px; right:2px; bottom:8px;
      border-bottom:1px solid rgba(66,37,26,.5); transition:border-color .3s; }
  .it-ev .it-link:hover::after { border-bottom-color:#42251a; }
}

/* ---- el texto del portarretrato en movil ----
   Los tamanos fijos en px no encogen con el marco: en un telefono el marco baja
   a ~310px pero el texto se queda igual, y los nombres se salen del ovalo sobre
   la plata. Aqui se pasan a cqw con el mismo valor relativo que tienen hoy en
   escritorio (medidos sobre un marco de 499px), asi que el movil es una version
   a escala de lo que ya funciona, y encaja por construccion. */
@media (max-width: 700px) {
  /* el marco recupera el padding lateral de su columna: 28px mas de ancho */
.mrc { container-type:inline-size; flex:none;
      width:calc(100% + 28px); margin-left:-14px; margin-right:-14px; }
  /* y el texto usa todo el hueco del ovalo, no una caja chica en el centro */
  .mrc-txt { inset:18.3% 22.8% 17.8% 22.6%; justify-content:space-between;
      padding:9% 1% 12.5%; gap:0; }
  .mrc-tit { font-size:5.2cqw; letter-spacing:.22em; }
  .fam-rot { font-size:3cqw; letter-spacing:.13em; margin-bottom:1.5cqw; }
  .fam-nom { font-size:4.2cqw; line-height:1.34; }
  .fam-rot + .fam-nom { margin-top:-.2cqw; }
}


/* ---- entradas elegantes ----
   La caligrafia entra enfocandose: de desenfocada a nitida, con una subida
   minima. Las tarjetas del contador y de regalos entran escalonadas. Todo se
   dispara con la clase que pone show() al entrar en pantalla. */
/* la caligrafia se descubre de izquierda a derecha, como si se escribiera.
   El inset lleva holgura arriba, abajo y a los lados para no cortar los
   trazos que se salen de la caja. */
.rv-on [data-reveal] .cursiva { clip-path:inset(-30% 100% -30% -14%); opacity:.15;
      transition:clip-path 1.45s cubic-bezier(.33,.7,.28,1) .08s, opacity .45s ease .08s; }
.rv-on [data-reveal].rv-vista .cursiva { clip-path:inset(-30% -14% -30% -14%); opacity:1; }

/* las tarjetas del contador asientan con una escala minima */

.rv-on .rg-tarjeta:nth-child(2) { transition-delay:.12s; }
.rv-on .rg-tarjeta:nth-child(3) { transition-delay:.24s; }

/* los filetes de la fecha se trazan de dentro hacia fuera */
.fecha-marco { position:relative; }
.fecha-marco::before, .fecha-marco::after { content:''; position:absolute; left:0; right:0;
      height:1px; background:rgba(240,233,216,.4); transform:scaleX(0);
      transition:transform 1.1s cubic-bezier(.2,.75,.3,1) .25s; }
.fecha-marco::before { top:0; } .fecha-marco::after { bottom:0; }
.rv-on [data-reveal].rv-vista .fecha-marco::before,
.rv-on [data-reveal].rv-vista .fecha-marco::after { transform:scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .rv-on [data-reveal] .cursiva {
    opacity:1; clip-path:none; transform:none; transition:none; }
  .fecha-marco::before, .fecha-marco::after { transform:scaleX(1); transition:none; }
}
/* ---- fotos: en vez de subir, asientan desde un encuadre algo mas cerrado ---- */
.foto { overflow:hidden; }
.rv-on .foto img { display:block; transform:scale(1.07);
      transition:transform 1.7s cubic-bezier(.16,1,.3,1); }
.rv-on .rv-vista .foto img,
.rv-on .foto.rv-vista img { transform:none; }

/* ---- portada: entra en cascada al cargar, sin esperar al scroll ---- */
@keyframes pt-sube { from { opacity:0; transform:translateY(18px); }
                     to   { opacity:1; transform:none; } }
@keyframes pt-traza { from { clip-path:inset(-30% 100% -30% -14%); opacity:.18; }
                      to   { clip-path:inset(-30% -14% -30% -14%); opacity:1; } }
.pt-texto > * { animation:pt-sube 1.05s cubic-bezier(.16,1,.3,1) both; }
.pt-texto > *:nth-child(1) { animation-delay:.20s; }
.pt-texto > *:nth-child(2) { animation:pt-traza 1.5s cubic-bezier(.33,.7,.28,1) .34s both; }
.pt-texto > *:nth-child(3) { animation:pt-traza 1.5s cubic-bezier(.33,.7,.28,1) .62s both; }
.pt-texto > *:nth-child(4) { animation-delay:.98s; }
.pt-texto > *:nth-child(5) { animation-delay:1.14s; }

/* ---- el rotulo de la portada: versalitas anchas y un filete que se traza ----
   Va con clase y no con estilo en linea como el resto de la portada porque
   necesita un ::after y una caja flex, y eso no cabe en un atributo style.

   Es el hijo 1 de .pt-texto y tiene que SEGUIR siendo uno solo: los cinco
   retardos de arriba van por nth-child y meter aqui un hermano los correria
   todos una posicion. El <span> de dentro no cuenta —solo importan los hijos
   directos de .pt-texto—, y esta puesto para poder separar la opacidad del
   texto de la del filete, que piden valores distintos.

   El filete no lleva ancho: flex:1 se come lo que sobra hasta el borde de la
   columna, asi que cruza el hero de lado a lado tanto en escritorio como en
   movil, sin un solo numero por breakpoint.

   El gap es 14 y no 22 porque letter-spacing deja ya unos 7px de aire suelto
   detras de la ultima S —el espaciado se aplica tambien al ultimo caracter—,
   y los dos sumados dan el respiro que se busca. */
.pt-rotulo { display:flex; align-items:center; gap:14px;
      font-size:17px; letter-spacing:.44em; text-transform:uppercase;
      margin-bottom:30px; }
.pt-rotulo > span { flex:none; opacity:.82; }
.pt-rotulo::after { content:''; flex:1 1 auto; height:1px; background:#42251a;
      opacity:.42; transform-origin:left;
      animation:pt-filete 1.6s cubic-bezier(.16,1,.3,1) .6s both; }
/* 1.6s y no los 1.05s del resto de la portada: el filete recorre bastante mas
   distancia que cualquier otra pieza, y a la duracion corta sale un latigazo. */
@keyframes pt-filete { from { transform:scaleX(0); } to { transform:scaleX(1); } }

/* ---- foto ancha: paralaje real atado al scroll ---- */
.foto-ancha { overflow:hidden; }
@supports (animation-timeline: view()) {
  /* el nombre va en la seccion, que no recorta: .foto-ancha lleva
     overflow:hidden y seria su propio puerto de scroll, como paso en la galeria */
  [data-screen-label="Foto ancha"] { view-timeline-name:--ancha; }
  .foto-ancha img { display:block; animation:pt-paralaje linear both;
        animation-timeline:--ancha; animation-range:cover 0% cover 100%; }
  @keyframes pt-paralaje { from { transform:translateY(-7%) scale(1.16); }
                           to   { transform:translateY(7%) scale(1.16); } }
}

@media (prefers-reduced-motion: reduce) {
  .pt-texto > *, .rv-on .foto img, .foto-ancha img {
    animation:none !important; transform:none !important; opacity:1 !important;
    clip-path:none !important; transition:none !important; }
  /* El ::after va aparte: la regla de arriba alcanza al elemento, no a su
     pseudo, asi que sin esto el filete seguiria trazandose. Al quitarle la
     animacion desaparece tambien su fill-mode, y el transform vuelve a none,
     o sea a scaleX(1): la linea queda dibujada entera desde el principio, que
     es justo lo que se quiere aqui. */
  .pt-rotulo::after { animation:none !important; transform:none !important; }
}

/* ---- cuenta regresiva: estampilla ---- */
.est-marco { position:relative; display:inline-block; padding:clamp(6px,1vw,10px); }
/* Perforado: una sola rejilla de agujeros de paso --s, corrida media celda
   para que los centros caigan justo sobre los cuatro bordes, y encima un
   rectangulo que tapa los agujeros de dentro.
   Antes eran cuatro tiras con el agujero partido por el borde de la celda.
   Chrome pinta los degradados repetidos como un mosaico y, con escala de
   pantalla fraccionaria (Windows al 125/150%) o con el paso estirado por
   'round', mezcla la primera fila de cada celda con la ultima: salia una
   linea crema por fuera de los agujeros y nudos raros en las esquinas.
   Ahora el borde del sello cae a mitad de celda y los bordes de celda caen
   entre agujeros, donde todo es opaco: no hay nada que mezclar.
   'round' sigue ajustando el paso a un numero entero de agujeros; cada
   esquina lleva un cuarto de agujero, como un sello de verdad. */
.est { --r:6px; --s:15px;
      position:relative; background:#f6f1e4; color:#42251a;
      padding:clamp(30px,4vw,48px) clamp(34px,6vw,76px) clamp(26px,3.4vw,40px);
      -webkit-mask:
        radial-gradient(var(--r), #0000 97%, #000) calc(var(--s) / -2) calc(var(--s) / -2) / var(--s) var(--s) round,
        linear-gradient(#000 0 0) 50% / calc(100% - var(--s)) calc(100% - var(--s)) no-repeat;
      mask:
        radial-gradient(var(--r), #0000 97%, #000) calc(var(--s) / -2) calc(var(--s) / -2) / var(--s) var(--s) round,
        linear-gradient(#000 0 0) 50% / calc(100% - var(--s)) calc(100% - var(--s)) no-repeat; }
.est-rot { font-size:11.5px; letter-spacing:.28em; text-transform:uppercase; color:#4e5430; opacity:.9; }
.est-num { font-family:'Cormorant', serif; font-size:clamp(84px,13vw,168px); line-height:.86;
      margin-top:clamp(8px,1.2vw,14px); font-variant-numeric:tabular-nums;
      font-feature-settings:'tnum' 1; }
.est-dia { font-size:12.5px; letter-spacing:.3em; text-transform:uppercase; margin-top:6px; }
.est-hr { width:clamp(52px,7vw,84px); height:1px; background:rgba(133,131,93,.6);
      margin:clamp(18px,2.2vw,26px) auto clamp(14px,1.8vw,20px); }
.est-fino { font-size:12.5px; letter-spacing:.16em; opacity:.7;
      font-variant-numeric:tabular-nums; font-feature-settings:'tnum' 1; }
/* matasellos: se estampa sobre la esquina */
.est-mata { position:absolute; top:clamp(-6px,-0.6vw,0px); right:clamp(-10px,-1vw,-2px);
      width:clamp(78px,10vw,104px); height:clamp(78px,10vw,104px); border-radius:50%;
      border:1.5px solid rgba(66,37,26,.42); color:rgba(66,37,26,.55);
      display:flex; flex-direction:column; align-items:center; justify-content:center;
      gap:3px; transform:rotate(-13deg); pointer-events:none; }
.est-mata::before { content:''; position:absolute; inset:5px; border-radius:50%;
      border:1px solid rgba(66,37,26,.3); }
.est-mata b { font-weight:400; font-size:11px; letter-spacing:.16em; }
.est-mata span { font-size:9.5px; letter-spacing:.2em; text-transform:uppercase; }
@media (max-width:520px) { .est-mata { display:none; } }

/* ---- etiqueta tipografica, no boton ---- */
.ht { display:flex; align-items:center; justify-content:center; gap:clamp(14px,2.4vw,22px);
      margin-top:clamp(26px,3vw,34px); }
.ht span.linea { height:1px; width:clamp(34px,7vw,80px); background:rgba(240,233,216,.4); }
.ht span.tag { font-family:'Courier Prime', monospace; font-size:clamp(17px,1.9vw,25px);
      letter-spacing:.2em; }

/* ---- 10 · boton solido de calendario ---- */
/* line-height:1 no es un capricho de maquetacion: sin el, el boton HEREDA el
   1.65 del cuerpo de texto, que es un interlineado pensado para parrafos de
   varias lineas. Sobre una etiqueta de 12.5px eso son 20.6px de caja de linea
   para una letra que ocupa 12.5, o sea 8px de aire muerto repartido arriba y
   abajo. El boton salia de 51px de alto y quedaba hinchado, sobre todo los
   cortos ("Ver mesa" era casi tan alto como ancho a la mitad).
   Con la linea a 1 la altura la deciden el texto y el padding, que es lo que
   se quiere. El padding sube de 15 a 16 para no bajar de los 44px que pide un
   objetivo tactil: 12.5 + 32 = 44.5. */
.btn-solido { display:inline-flex; align-items:center; gap:10px; border:none; border-radius:100px;
      padding:16px 30px; background:#42251a; color:#f0e9d8; font-family:'Courier Prime', monospace;
      font-size:12.5px; line-height:1; letter-spacing:.14em; text-transform:uppercase;
      text-decoration:none; cursor:pointer; transition:background .3s; }
.btn-solido:hover { background:#2e1a12; color:#f0e9d8; }
.btn-claro { background:#f0e9d8; color:#42251a; }
.btn-claro:hover { background:#fff; color:#42251a; }

/* una sola copia del sobre: la usan el RSVP y la entrada.
   La ruta sube un nivel porque las url() de una hoja se resuelven desde la
   hoja, no desde la pagina. En el diseno empaquetado este CSS iba dentro del
   propio index.html y ahi "images/..." era correcto; aqui seria css/images/. */
:root { --sobre-verde:url(../images/sobre-verde.webp); }

/* ---- 11 · sobre del RSVP ---- */
/* Se declara contenedor para que la tarjeta pueda pedir su alto minimo en cqw,
   o sea en tantos por ciento del ancho del sobre. Hace falta porque las dos
   medidas que definen el hueco —donde empieza la tarjeta y donde acaba el
   sobre— salen las dos del ancho, no del alto: el margin-top de .tarjeta es un
   porcentaje (y los porcentajes de margen se miden sobre el ancho) y el alto
   del sobre lo fija su aspect-ratio. Un min-height en % no valdria: se medina
   sobre el alto de .sobre, que a su vez lo pone la tarjeta. Seria circular. */
.sobre { position:relative; width:min(520px,100%); margin:0 auto;
      container-type:inline-size; }
/* sobre abierto, recortado del PNG con alfa que trajo la referencia. Se
   erosiono 2px el filo para quitarle el negro del render. Una sola pieza,
   sin estirar: la proporcion del CSS es la del archivo. */
.sobre-fondo { position:absolute; inset:0 0 auto 0; aspect-ratio:1000/1138;
      transform:rotate(-1.5deg);
      background:var(--sobre-verde) center/100% 100% no-repeat;
      filter:drop-shadow(0 16px 30px rgba(28,16,9,.42)); }
/* 420px de caja y no los 340 de contenido del diseno original: dentro de la
   tarjeta ya no va un solo campo de codigo, va el formulario de weddeb entero,
   y con las pastillas de "Si / No" bajo el nombre de cada invitado 340 se
   quedaba corto. Descontado el relleno quedan 380 de contenido. Sigue siendo
   mas estrecha que el sobre (520), que es lo que hace que se lea como una
   tarjeta metida en el y no como un panel.

   El box-sizing es lo que permite que el min-height de abajo se mida en la
   caja entera, relleno incluido, que es lo unico comparable con el borde del
   sobre. Obliga a escribir el ancho tambien en caja entera: los 380+40 de
   antes son estos 420, misma medida en pantalla.
   Crece hacia abajo sin limite: el sobre esta anclado arriba (inset:0 0 auto 0)
   y la tarjeta arranca al 52%, asi que lo desborda a proposito cuando el widget
   pide seis nombres igual que cuando pide dos.

   El min-height es para el caso contrario, el de recien llegado: con solo el
   campo del codigo la tarjeta se quedaba en 249px y se leia como un rectangulo
   suelto flotando en mitad del sobre, sin llegar al borde de abajo. 62cqw es
   justo lo que mide el hueco: el sobre acaba a 113.8cqw (su aspect-ratio es
   1000/1138) y la tarjeta empieza a 52cqw, o sea 61.8cqw de recorrido. Asi baja
   hasta el filo en cualquier ancho, sin numeros por breakpoint.
   Contra el filo que se VE quedan unos 6px: el sobre va girado -1.5deg y el
   giro le saca un poco de alto que el aspect-ratio no cuenta. Se deja asi, que
   es holgura y no falta; perseguir esos 6px pediria atar el min-height al
   angulo, y entonces cambiar el giro descuadraria la tarjeta.
   El justify-content solo actua mientras manda ese minimo: reparte el aire
   sobrante arriba y abajo en vez de dejarlo todo apilado al final. En cuanto el
   formulario crece y pasa de 62cqw, deja de tener efecto. */
.tarjeta { position:relative; z-index:1; box-sizing:border-box;
      width:min(420px,92%); margin:calc(52%) auto 0; background:#f6f1e4; color:#42251a;
      padding:26px clamp(14px,3.5vw,20px) 30px; box-shadow:0 16px 34px rgba(66,37,26,.34);
      min-height:62cqw;
      display:flex; flex-direction:column; justify-content:center; gap:13px; }
.lacre { position:absolute; left:50%; bottom:6px; transform:translateX(-50%);
      width:56px; height:56px; border-radius:50%;
      background:radial-gradient(circle at 36% 30%, #6b3b28, #42251a 62%, #2c170f);
      color:#e8dcc6; display:flex; align-items:center; justify-content:center;
      font-family:'Cormorant', serif; font-size:15px; letter-spacing:.06em; line-height:1;
      box-shadow:0 8px 18px rgba(0,0,0,.4), inset 0 2px 4px rgba(255,255,255,.22); }
.lacre::before { content:''; position:absolute; inset:5px; border-radius:50%;
      border:1px solid rgba(232,220,198,.35); }

/* ---- 13 · tarjetas de regalo ---- */
.rg-tarjeta { border:1px solid rgba(240,233,216,.3); padding:clamp(22px,3vw,30px); border-radius:3px; }
.rg-dato { font-size:clamp(15px,1.1vw,16px); line-height:1.9; }
.rg-clabe { font-size:clamp(13.5px,1.05vw,16px); letter-spacing:0; line-height:1.5;
      margin-top:4px; white-space:nowrap; }
/* En movil la CLABE y el numero de evento son lo que el invitado tiene que
   leer y teclear: van grandes. El tamano sale del ancho de la tarjeta (cqw) y
   no de la pantalla, asi una CLABE con espacios (22 caracteres) cabe en una
   linea con una o con dos columnas de tarjetas y en un telefono de 320px.
   Courier mide .6em por caracter: 22 x .6 x 7.3cqw = 96cqw. */
@media (max-width: 700px) {
  .rg-tarjeta { container-type:inline-size; }
  .rg-clabe { font-size:min(21px, 7.3cqw); }
}

/* ---- 16 · pie ---- */
.pie { margin-top:clamp(44px,5vw,66px); padding-top:clamp(22px,2.6vw,30px);
      border-top:1px solid rgba(240,233,216,.22); display:flex; align-items:center;
      justify-content:space-between; gap:16px; max-width:820px; margin-left:auto; margin-right:auto; }
.pie-marca { text-decoration:none; color:inherit; display:inline-flex; align-items:center;
      height:44px; padding-left:8px; }
/* el logo hereda el color del pie, asi sirve sobre chocolate y sobre crema */
.pie-logo { height:clamp(17px,1.6vw,22px); width:auto; display:block; }
.pie-ig { display:inline-flex; align-items:center; justify-content:center; width:44px; height:44px;
      color:inherit; opacity:.62; transition:opacity .3s; }
.pie-ig:hover { opacity:1; color:inherit; }
.pie-link { font-size:11px; letter-spacing:.22em; text-transform:uppercase; opacity:.55;
      text-decoration:none; color:inherit; transition:opacity .3s; display:inline-flex;
      align-items:center; height:44px; padding:0 8px; }
.pie-link:hover { opacity:1; color:inherit; }
.lb { position:fixed; inset:0; z-index:9999; display:none; align-items:center; justify-content:center;
      gap:clamp(6px,2vw,18px); background:rgba(28,14,9,.95); padding:clamp(16px,4vw,44px); box-sizing:border-box; }
.lb.abierto { display:flex; }
.lb-img { max-width:100%; max-height:100%; object-fit:contain; border-radius:6px; box-shadow:0 24px 70px rgba(0,0,0,.6); }
.lb-nav, .lb-x { background:none; border:1px solid rgba(240,233,216,.45); color:#f0e9d8; cursor:pointer;
      border-radius:50%; display:flex; align-items:center; justify-content:center; line-height:1; flex:none;
      transition:background .25s ease, border-color .25s ease; }
.lb-nav:hover, .lb-x:hover { background:rgba(240,233,216,.16); border-color:#f0e9d8; }
.lb-nav { width:clamp(36px,7vw,52px); height:clamp(36px,7vw,52px); font-size:clamp(22px,4vw,32px); padding-bottom:4px; }
.lb-x { position:absolute; top:clamp(12px,3vw,26px); right:clamp(12px,3vw,26px); width:42px; height:42px; font-size:25px; padding-bottom:3px; }
.lb-n { position:absolute; bottom:clamp(12px,3vw,26px); left:0; right:0; text-align:center; color:#f0e9d8;
      font-family:'Courier Prime', monospace; font-size:11px; letter-spacing:.22em; opacity:.7; }

/* ---- portada en móvil: la foto de fondo, los nombres encima ---- */
.pt-scrim { display:none; }
@media (max-width: 639px) {
  .pt-portada { display:block !important; position:relative; }
  .pt-foto { position:absolute !important; inset:0 !important; min-height:0 !important; }
  .pt-scrim { display:block; position:absolute; inset:0; pointer-events:none;
      background:linear-gradient(180deg, rgba(24,12,7,.20) 0%, rgba(24,12,7,.34) 40%, rgba(24,12,7,.82) 100%); }
  .pt-perf { display:none !important; }
  .pt-texto { position:relative; z-index:2; min-height:100svh; box-sizing:border-box; color:#f0e9d8;
      justify-content:flex-end !important; padding-bottom:clamp(40px,9vw,64px) !important;
      text-shadow:0 1px 14px rgba(20,10,6,.6); }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity:1 !important; transform:none !important; transition:none !important; }
  * { animation-duration:.01ms !important; transition-duration:.01ms !important; }
  [data-lightbox]:hover { opacity:1; }
}
/* ---- entrada: el sobre verde del RSVP ----
   El navegador solo deja sonar el audio despues de un gesto del visitante,
   asi que el boton es a la vez el permiso para reproducir.
   La misma imagen va dos veces: entera al fondo y recortada al bolsillo
   por delante. El corte no se ve (son los mismos pixeles alineados); solo
   sirve para que la tarjeta quede metida dentro del sobre. El pico del
   bolsillo esta medido sobre la imagen: 41% en los cantos, 69% al centro. */
html.ld-abierto, html.ld-abierto body { overflow:hidden !important;
      overscroll-behavior:none; touch-action:none; }
.ld { position:fixed; inset:0; z-index:9999; background:#42251a; color:#f0e9d8;
      display:grid; place-items:center; text-align:center;
      padding:clamp(20px,5vw,52px);
      transition:opacity .7s ease .45s; }
.ld::before { content:''; position:absolute; inset:clamp(13px,3vw,28px);
      border:1px solid rgba(240,233,216,.22); pointer-events:none; }
.ld-fuera { opacity:0; pointer-events:none; }
html.ld-listo .ld { display:none !important; }

.ld-caja { position:relative; z-index:1;
      animation:ld-sube 1.1s cubic-bezier(.16,1,.3,1) both; }
@keyframes ld-sube { from { opacity:0; transform:translateY(16px); } }

.ld-sobre { position:relative; display:block; cursor:pointer;
      container-type:inline-size;
      width:min(380px,84vw); aspect-ratio:1000/1138;
      margin:0 auto; transform:rotate(-1.5deg);
      transition:transform .8s cubic-bezier(.16,1,.3,1) .25s; }
.ld-fuera .ld-sobre { transform:rotate(-1.5deg) translateY(-12px) scale(1.05); }
.ld-atras, .ld-frente { position:absolute; inset:0;
      background:var(--sobre-verde) center/100% 100% no-repeat; }
.ld-atras { z-index:1; filter:drop-shadow(0 22px 38px rgba(0,0,0,.45)); }
.ld-frente { z-index:3;
      clip-path:polygon(0 41%, 50% 69%, 100% 41%, 100% 100%, 0 100%); }

.ld-carta { position:absolute; z-index:2; left:16%; right:16%; top:17%; bottom:12%;
      background:#f6f1e4; color:#42251a; border-radius:2px;
      box-shadow:0 5px 16px rgba(0,0,0,.3);
      display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
      gap:2.6cqw; padding:8cqw 4cqw 0;
      transition:transform .85s cubic-bezier(.16,1,.3,1) .06s; }
.ld-fuera .ld-carta { transform:translateY(-30%) scale(1.04); }
.ld-ojal { font-size:2.8cqw; letter-spacing:.24em; text-transform:uppercase; opacity:.6; }
.ld-nom { font-family:'Cormorant', serif; font-size:6.6cqw; line-height:1.26;
      letter-spacing:.13em; text-transform:uppercase; }
.ld-hilo { width:8cqw; height:1px; background:rgba(66,37,26,.32); }
.ld-fecha { font-size:3cqw; letter-spacing:.26em; opacity:.72; }

.ld-btn { -webkit-appearance:none; appearance:none; cursor:pointer;
      font-family:inherit; font-size:12px; letter-spacing:.22em;
      text-transform:uppercase; color:#42251a; background:#f0e9d8;
      border:1px solid #f0e9d8; border-radius:100px;
      padding:16px clamp(28px,4.4vw,40px);
      margin-top:clamp(26px,3.8vw,38px);
      display:inline-flex; align-items:center; gap:12px;
      transition:background .4s ease, color .4s ease, transform .25s ease, opacity .35s ease; }
.ld-btn:hover { background:transparent; color:#f0e9d8; }
.ld-btn:active { transform:scale(.97); }
.ld-btn .ld-fl { transition:transform .4s ease; }
.ld-btn:hover .ld-fl { transform:translateX(5px); }
.ld-fuera .ld-btn { opacity:0; }

/* interruptor de musica: bocina, con ondas cuando suena y tachada al callar */
.ms { position:fixed; z-index:60; display:none;
      right:clamp(14px,2.4vw,26px); bottom:clamp(14px,2.4vw,26px);
      width:46px; height:46px; border-radius:50%; cursor:pointer; padding:0;
      place-items:center; color:#f0e9d8;
      background:rgba(66,37,26,.88); border:1px solid rgba(240,233,216,.3);
      -webkit-appearance:none; appearance:none;
      -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
      opacity:0; transition:opacity .7s ease .35s, background .3s ease,
                            border-color .3s ease, transform .25s ease; }
html.ld-suena .ms { display:grid; opacity:1; }
.ms:hover { background:#42251a; border-color:rgba(240,233,216,.6); }
.ms:active { transform:scale(.94); }
.ms svg { width:21px; height:21px; display:block; overflow:visible; }
.ms-cuerpo { fill:currentColor; }
.ms-onda, .ms-tache { fill:none; stroke:currentColor; stroke-width:1.7;
      stroke-linecap:round; transition:opacity .28s ease; }
.ms-tache { opacity:0; }
.ms-onda2 { animation:ms-late 2.6s ease-in-out infinite; }
@keyframes ms-late { 0%, 100% { opacity:.95; } 50% { opacity:.35; } }
html.ms-mudo .ms-onda { opacity:0; }
html.ms-mudo .ms-onda2 { animation:none; }
html.ms-mudo .ms-tache { opacity:1; }
@media (prefers-reduced-motion: reduce) {
  .ld-caja { animation:none; }
  .ms-onda2 { animation:none; }
}

/* ==========================================================================
   17 · FOTOS
   ==========================================================================
   Sustituyen al <image-slot> del editor, que era display:block, ocupaba todo
   el hueco y recortaba la foto centrada sin deformarla. Eso es exactamente
   object-fit:cover con object-position:center, asi que el encuadre que se veia
   en el editor es el que se ve aqui.

   height:100% es lo que hace que funcione: el hueco lo define el contenedor
   (.foto y compania llevan aspect-ratio en su style), y sin altura la imagen
   se pondria a su alto natural y el aspect-ratio del padre no serviria de nada.
   ========================================================================== */
.ph { display:block; width:100%; height:100%; object-fit:cover; object-position:center; }

/* ==========================================================================
   18 · ENCABEZADOS
   ==========================================================================
   El diseno venia del editor sin un solo encabezado: los titulos de seccion
   eran <div>, asi que la invitacion no tenia <h1> ni estructura por la que
   pudiera saltar un lector de pantalla. Ahora son h1/h2/h3 de verdad.

   El navegador trae dos estilos propios para los encabezados que aqui estorban
   y hay que anular. Los dos importan:

     font-weight  El titular pasaria de 400 a 700. Monsieur La Doulaise, la
                  cursiva de los titulos, NO tiene negrita, asi que el navegador
                  la falsifica engordando el trazo por igual: una caligrafica
                  pierde el contraste fino/grueso que la define y se ve mal.
     margin       Un h2 trae 0.83em arriba y abajo, que al tamano de estos
                  titulos son mas de 60px de aire que nadie pidio.

   font-size va por el mismo camino: los titulos lo declaran en su style, pero
   inherit deja al descubierto el valor de antes si alguno dejara de hacerlo.

   Con esto la conversion es invisible: se comparo la geometria de los 284
   elementos de la pagina antes y despues y no se movio ninguno.
   Las reglas en linea de cada titulo siguen mandando sobre estas, que es lo que
   se quiere: un margin-top:8px escrito en el style se respeta igual que antes.
   ========================================================================== */
.inv-t { font-weight:inherit; font-size:inherit; margin:0; }

/* Para el <h1>, que existe para los lectores de pantalla y no para la vista:
   los nombres ya estan dibujados en la portada. No se usa display:none ni
   visibility:hidden porque las dos lo esconderian tambien del lector, que es
   justo a quien va dirigido. Se saca de la vista dejandolo en el arbol. */
.solo-lector { position:absolute; width:1px; height:1px; margin:-1px; padding:0;
      overflow:hidden; white-space:nowrap; border:0; clip-path:inset(50%); }

/* Cada foto va dentro de un <picture> que ofrece el WebP y deja el JPEG de
   respaldo. Sin esta linea el envoltorio ROMPE la foto: <picture> es inline por
   defecto, o sea una caja sin altura definida, y entonces el height:100% de
   arriba deja de tener contra que medirse y cae a auto. La imagen se pondria a
   su alto natural y se saldria del hueco.
   display:contents borra la caja del envoltorio y deja la imagen colgando
   directamente de .foto, que es donde estaba antes: mismo layout, y los
   selectores como ".rv-on .foto img" siguen alcanzandola igual. */
picture { display:contents; }
