/* ═══════════════════════════════════════════════════════════════
   Invitación · Benjamin & Monica · 8 de enero de 2027
   1. Tokens        4. Componentes     7. Apertura
   2. Reset         5. Secciones       8. Animaciones de scroll
   3. Tipografía    6. Utilidades      9. prefers-reduced-motion
   ═══════════════════════════════════════════════════════════════ */

/* ── 1. TOKENS ─────────────────────────────────────────────── */
:root{
  /* Paleta.
     --perla es el color base de los bloques. Encima lleva el velo de papel,
     que lo oscurece un 4%: el color que se ve de verdad es #E3DCCF. Si
     oscureces más la base, baja también --oliva o la ilustración y los
     iconos dejan de llegar a 3:1 contra el fondo. */
  --perla:#EDE6D8;
  --beige:#E8DFCF;
  --oliva-claro:#A8B593;
  --oliva:#6E7C57;      /* trazo de la ilustración y los iconos: 3,3:1 */
  --bosque:#2E4133;
  --dorado:#C7A35A;
  --oro-marco:rgba(199,163,90,.62);
  /* Verdes del sobre. El texto blanco pequeño pasa AA sobre todos ellos
     (4,66:1 o mejor). Los cuatro tonos están a un 4% unos de otros: es lo
     que hace que la solapa se lea como una hoja apoyada sobre el cuerpo. */
  --oliva-sobre:#6C7957;      /* tono medio de la solapa */
  --sobre-cuerpo:#5F6A4D;     /* el cuerpo, bastante por debajo de la solapa. No se
                                 aclara la solapa porque el texto blanco pequeño
                                 caería por debajo de 4,5:1 */
  --solapa-luz:#6E7B59;       /* el pliegue. No se puede aclarar más: los
                                 nombres y la fecha van encima y en blanco */
  --solapa-sombra:#687454;    /* 4% más oscuro, el vértice */

  /* Tintes derivados (contraste ya verificado sobre su fondo) */
  --bosque-45:rgba(46,65,51,.45);
  --bosque-28:rgba(46,65,51,.28);
  --bosque-12:rgba(46,65,51,.12);

  /* Familias */
  --cali:'Milton One', 'Segoe Script', cursive;
  --serif:'EB Garamond', Georgia, 'Times New Roman', serif;

  /* Escala tipográfica.
     Milton One tiene la mayúscula un 28% más baja que Great Vibes y es
     bastante más estrecha, así que los tamaños caligráficos van 1,4×
     respecto a los de antes: iguala la presencia sin desbordar la línea. */
  --t-cali-xl:clamp(3.9rem, 17.6vw, 5rem);
  --t-cali-l:clamp(3.5rem, 15.8vw, 4.4rem);
  --t-cifra:clamp(2.1rem, 10vw, 2.7rem);
  --t-dia:clamp(2.6rem, 13vw, 3.4rem);
  --t-dato:1.125rem;
  --t-cuerpo:1.0625rem;
  --t-cuerpo-s:.9375rem;
  --t-label-l:.8125rem;
  --t-label:.6875rem;

  /* Ritmo */
  --e1:.5rem; --e2:1rem; --e3:1.5rem; --e4:2rem; --e5:2.75rem; --e6:4rem;
  --bloque-y:clamp(4rem, 14vw, 5.5rem);
  --gutter:clamp(1.5rem, 7vw, 2.5rem);
  --ancho:34rem;
  --fundido:7rem;      /* alto del degradado de entrada y salida del verde */
  --textura-tam:480px; /* paso de la teja de papel; más pequeño = grano más fino */

  /* Movimiento */
  --ease-salida:cubic-bezier(.22, 1, .36, 1);
  --rv-dur:600ms;
  --rv-paso:90ms;

  /* Iconos: pon none para quitar el temblor dibujado a mano.
     La intensidad es el atributo scale de #temblor en index.html. */
  --icono-filtro:url(#temblor);
  --icono-tam:2rem;
}


/* ── 2. RESET ──────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body,h1,h2,p,ul,ol,li,figure,table,caption{margin:0;padding:0}
ul,ol{list-style:none}
img,picture,svg{display:block;max-width:100%}
img{height:auto}
button,input,textarea{font:inherit;color:inherit}
button{border:0;background:none;cursor:pointer}
.sprite{position:absolute;width:0;height:0;overflow:hidden}

body{
  background:var(--oliva);
  color:var(--bosque);
  font-family:var(--serif);
  font-size:var(--t-cuerpo);
  font-weight:400;
  line-height:1.78;
  text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
}

/* Bloqueo del scroll mientras el sobre está cerrado */
html.js:not(.ya-abierto):not(.abierta) body{overflow:hidden}

.lienzo{
  max-width:var(--ancho);
  margin-inline:auto;
  background:var(--perla);
}


/* ── 3. TIPOGRAFÍA ─────────────────────────────────────────── */

/* Caligráfica de los títulos y los nombres. Se sirve desde /assets, así que
   no depende de Google Fonts. Declarada con peso 400 aunque el archivo sea
   la Bold: es el único peso, y así el navegador no la engorda por su cuenta. */
@font-face{
  font-family:'Milton One';
  src:url('assets/milton-one-bold.otf') format('opentype');
  font-weight:400;
  font-style:normal;
  font-display:swap;
}

/* El archivo ES la Bold y es el único corte, por eso se declara como 400:
   así el navegador no intenta engordarla por su cuenta. Con font-weight:700
   no pasa nada (comprobado: 400, 700 y 800 se pintan idénticos), así que
   para dar más cuerpo se engorda el contorno a mano, que sí se controla.
   Por encima de .6px los enlaces de la script empiezan a empastarse. */
.cali{
  font-family:var(--cali);
  font-weight:400;
  font-size:var(--t-cali-l);
  line-height:1.2;
  letter-spacing:0;      /* es una script ligada: separarla rompe los enlaces */
  text-transform:none;
  -webkit-text-stroke:.5px currentColor;
}

/* Versalitas con tracking amplio. El padding-left recentra ópticamente
   el espacio sobrante que el letter-spacing deja tras la última letra. */
.label{
  font-family:var(--serif);
  font-size:var(--t-label);
  font-weight:500;
  line-height:1.7;
  text-transform:uppercase;
  letter-spacing:.2em;
  padding-left:.2em;
}

p + p{margin-top:var(--e2)}

a{color:inherit}

:focus-visible{
  outline:2px solid var(--bosque);
  outline-offset:3px;
  border-radius:1px;
}
.apertura :focus-visible{outline-color:#fff}


/* ── 4. COMPONENTES ────────────────────────────────────────── */

/* Bloque a sangre completa */
.bloque{
  position:relative;
  padding:var(--bloque-y) var(--gutter);
  text-align:center;
}
/* Textura de papel. Es un velo NEGRO CON TRANSPARENCIA, no una imagen
   opaca: al componerse de forma normal sobre el color da exactamente lo
   mismo que un multiply —C×(1−alfa) es C×T/255 con alfa = 1−T/255— pero
   sin depender de background-blend-mode.

   Antes se hacía con blend-mode y era el punto débil de toda la web: en
   los navegadores que no lo aplican, la textura opaca tapaba el color en
   vez de teñirlo y la invitación entera se volvía papel blanco, con el
   verde desaparecido y los textos en blanco del sobre invisibles.

   La teja está espejada en las cuatro esquinas: no tiene costuras y
   repite cada --textura-tam. */
.bloque--perla{
  color:var(--bosque);
  background-color:var(--perla);
  background-image:url(assets/textura-velo.webp);
  background-size:var(--textura-tam);
}

/* El único bloque verde de la web. No entra ni sale de golpe: se funde
   con el perla a lo largo de --fundido por arriba y por abajo, con un
   punto medio adelantado al 45% para que el verde se disuelva despacio.
   El padding extra garantiza que el contenido caiga sobre verde macizo. */
.bloque--verde{
  color:var(--bosque);
  padding-block:calc(var(--bloque-y) + 2.5rem);
  background-color:var(--perla);
  background-image:
    url(assets/textura-velo.webp),
    linear-gradient(
      to bottom,
      var(--perla) 0,
      calc(var(--fundido) * .45),
      var(--oliva-claro) var(--fundido),
      var(--oliva-claro) calc(100% - var(--fundido)),
      calc(100% - var(--fundido) * .45),
      var(--perla) 100%);
  background-size:var(--textura-tam), auto;
  background-repeat:repeat, no-repeat;
}

/* Icono de sección */
.icono{
  width:var(--icono-tam);
  height:var(--icono-tam);
  margin-inline:auto;
  color:var(--oliva);
  filter:var(--icono-filtro);
}
.bloque--verde .icono{color:var(--bosque)}   /* oliva sobre oliva-claro sería 1,7:1 */

.titulo{margin-bottom:var(--e2)}
.titulo + .cali{margin-bottom:var(--e3)}

/* Botón de contorno */
.btn{
  display:inline-block;
  padding:.85em 2em;
  border:1px solid currentColor;
  border-radius:2px;
  background:none;
  color:inherit;
  font-size:var(--t-label-l);
  font-weight:500;
  text-transform:uppercase;
  letter-spacing:.2em;
  padding-left:calc(2em + .2em);
  text-decoration:none;
  line-height:1;
  transition:background-color 220ms ease;
}
.btn:hover{background:var(--bosque-12)}
.btn[aria-disabled="true"]{opacity:.55}

/* Párrafo de texto corrido dentro de un bloque */
.texto{
  max-width:26rem;
  margin-inline:auto;
  text-wrap:pretty;
}

/* Control de la música. Es el único elemento fijo de la web, y está aquí
   por necesidad: sin él nadie podría callar la canción sin cerrar la
   página. Aparece solo cuando el sobre ya se ha abierto. */
.musica{
  position:fixed;
  z-index:50;
  bottom:1rem;
  right:max(1rem, calc((100vw - var(--ancho)) / 2 + 1rem));
  display:none;
  place-items:center;
  width:2.6rem;
  height:2.6rem;
  border:1px solid var(--oliva);
  border-radius:50%;
  background-color:var(--perla);
  background-image:url(assets/textura-velo.webp);
  background-size:var(--textura-tam);
  opacity:.7;
  transition:opacity 220ms ease;
}
html.abierta .musica{display:grid}
.musica:hover,
.musica:focus-visible{opacity:1}
.musica__ico{--icono-tam:1.15rem}

/* Filete dorado. Es el único separador de la web: una línea fina que
   no llega a los bordes, centrada en el corte entre bloques. */
.filete{
  display:block;
  width:min(76%, 21rem);
  height:1px;
  background:var(--dorado);
  transform-origin:center;
}

/* A caballo del corte entre dos bloques */
.separador{
  position:absolute;
  left:0;right:0;
  bottom:0;
  z-index:1;                 /* por encima del fondo del bloque siguiente */
  display:flex;
  justify-content:center;
  transform:translateY(50%);
  pointer-events:none;
}

/* Para separar dos cosas dentro de un mismo bloque */
.filete-caja{
  display:flex;
  justify-content:center;
  margin:var(--e6) 0;
}

/* Acuarela. Su fondo se normalizó a blanco puro y los bordes se fundieron
   a blanco, así que en multiply desaparecen y la lámina queda impresa sobre
   el mismo papel del bloque, sin recuadro. Sin marco ni parallax: ambos
   obligarían a recortarla y a devolverle el borde recto. */
.acuarela{margin-top:var(--e5)}
.acuarela img{
  width:100%;
  height:auto;
  mix-blend-mode:multiply;
}

/* Marcador de contenido pendiente */
.pendiente{
  display:inline-block;
  margin-top:var(--e2);
  padding:.5em .9em;
  border:1px dashed var(--bosque-45);
  border-radius:2px;
  background:rgba(199,163,90,.14);
  font-size:var(--t-label);
  font-weight:500;
  line-height:1.6;
  text-transform:uppercase;
  letter-spacing:.14em;
}
.pendiente--nota{background:none;border-style:dotted;opacity:.7}

.visualmente-oculto{
  position:absolute;
  width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
}


/* ── 5. SECCIONES ──────────────────────────────────────────── */

/* 1 · Portada ------------------------------------------------ */
.portada{padding-top:clamp(3rem, 10vw, 4rem)}

.retrato{
  /* Posición y tamaño de cada cara, en % del ancho de la ilustración.
     Ajustables sin tocar el SVG.

     El ancho del novio NO es una decisión estética: debajo, la ilustración
     lleva dibujado un círculo por cabeza, y el suyo es más ancho que su
     mandíbula. Por debajo del 29% asomaba el trazo verde entre la oreja y
     el cuello. El SVG es un único path de 42 KB, así que borrar esa cabeza
     no era viable; taparla con la foto sí.

     El de la novia sí es estético: su pelo ya cubría el círculo de sobra.
     Va al 28% para que las dos cabezas se lean a la misma escala, porque
     su recorte incluye melena y a igual porcentaje la cara sale más chica. */
  --novio-x:48.5%;  --novio-y:21.6%;  --novio-w:29%;
  --novia-x:66.8%;  --novia-y:23.2%;  --novia-w:28%;

  position:relative;
  width:min(80%, 19rem);
  margin:0 auto var(--e4);
}
.retrato__dibujo{width:100%;height:auto}
.retrato__cara{
  position:absolute;
  transform:translate(-50%, -50%);
  height:auto;
}
.retrato__cara--novio{left:var(--novio-x);top:var(--novio-y);width:var(--novio-w)}
.retrato__cara--novia{left:var(--novia-x);top:var(--novia-y);width:var(--novia-w)}

.portada__nombres{
  font-size:var(--t-cali-xl);   /* los nombres, por encima de los títulos de sección */
  white-space:nowrap;
  margin-bottom:var(--e2);
}
.portada__nombres:focus{outline:none}
.portada__frase{max-width:24rem;margin-inline:auto}

/* 2 · La fecha ----------------------------------------------- */
.fecha__mes{font-size:var(--t-label-l)}
.fecha__desglose{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:var(--e2);
  margin-top:var(--e1);
}
.fecha__lado{
  border-top:1px solid var(--bosque-45);
  border-bottom:1px solid var(--bosque-45);
  padding:.55em 1em .55em 1.2em;
  white-space:nowrap;
}
.fecha__dia{
  font-size:var(--t-dia);
  line-height:1;
  font-variant-numeric:lining-nums;
}
.fecha__faltan{margin-top:var(--e6);font-size:var(--t-label-l)}

.cuenta{
  display:flex;
  align-items:flex-start;
  justify-content:center;
  gap:.5rem;
  margin-top:var(--e2);
}
.cuenta__celda{display:flex;flex-direction:column;align-items:center;min-width:3.7rem}
.cuenta__cifra{
  font-size:var(--t-cifra);
  line-height:1.05;
  font-variant-numeric:lining-nums tabular-nums;
  font-feature-settings:"tnum" 1;
}
.cuenta__eti{font-size:var(--t-label);opacity:.9}
.cuenta__sep{
  font-size:var(--t-cifra);
  line-height:1.05;
  opacity:.5;
}

.cal__titulo{margin-top:var(--e6);font-size:var(--t-label-l)}
.cal__mes{margin-top:.2rem;font-size:var(--t-label);opacity:.8}
.cal{margin-top:var(--e3)}
.cal table{
  width:100%;
  table-layout:fixed;                       /* las 7 columnas, iguales */
  border-collapse:collapse;
  font-variant-numeric:lining-nums tabular-nums;
}
.cal th{
  font-size:var(--t-label);
  font-weight:500;
  letter-spacing:.1em;
  padding-bottom:.6rem;
  opacity:.75;
}
.cal td{
  font-size:var(--t-cuerpo-s);
  height:2.3rem;
  padding:0;
  text-align:center;
  vertical-align:middle;
}
.cal__fiesta{position:relative;display:inline-grid;place-items:center;width:2.3rem;height:2.3rem}
.cal__corazon{
  position:absolute;
  inset:0;
  width:100%;height:100%;
  color:var(--bosque);
  fill:none;
  stroke:currentColor;
  stroke-width:1.5;
  filter:var(--icono-filtro);
}
.cal__fiesta > span{position:relative;line-height:1}

/* 3 · Ceremonia y recepción ---------------------------------- */
.lugar__hora{font-size:var(--t-dato);margin-top:var(--e1)}
.lugar__sitio{margin-top:var(--e2);font-size:var(--t-label-l);text-wrap:balance}
.lugar__zona{font-size:var(--t-cuerpo-s);font-style:italic;opacity:.85}
.lugar__guino{font-style:italic;opacity:.9}
.lugar p{margin-top:var(--e2)}
.lugar .btn{margin-top:var(--e2)}

/* 4 · Dress code --------------------------------------------- */
.dress__nivel{margin-top:var(--e2);font-size:var(--t-label-l)}
.dress__filete{margin:var(--e3) auto 0;width:min(34%, 8rem)}

/* Única lista de la web con el texto a la izquierda: son recomendaciones
   con icono al lado, y centradas se leerían bastante peor. */
.dress__lista{
  max-width:24rem;
  margin:var(--e5) auto 0;
  text-align:left;
}
.dress__lista li{
  display:grid;
  grid-template-columns:2.6rem 1fr;
  gap:var(--e3);
  align-items:center;
  padding:var(--e3) 0;
}
.dress__lista li + li{border-top:1px solid rgba(199,163,90,.4)}
.dress__ico{--icono-tam:2.3rem;margin-inline:0}
.dress__lista p{font-size:var(--t-cuerpo-s);line-height:1.65}

/* 5 · El mejor regalo ---------------------------------------- */

/* La única tarjeta de la web, y va en verde para que destaque sobre el
   perla. El bloque verde de la fecha sigue siendo el único bloque verde a
   sangre: esto es una tarjeta apoyada encima, no un bloque.

   El marco NO puede ser dorado: sobre este verde da 1,01:1 y desaparece.
   Va en --bosque al 45%, que da 1,87:1, comparable al dorado sobre perla
   y suficiente para un filete decorativo.

   El hueco para el icono se hace con un degradado de tramos, no con un
   fondo detrás del icono, que obligaría a casar la textura de dos capas. */
/* La tarjeta va en verde OSCURO, y no por gusto: es lo que hace posible el
   dorado. Sobre el verde claro del calendario el dorado da 1,02:1, o sea
   que desaparece; sobre --bosque da 4,79:1 y pasa AA hasta para texto
   normal. El cuerpo pasa a --perla, que ahí da 9,19:1.

   Se sale del ancho del bloque medio gutter por cada lado para ganar
   presencia sin llegar al borde de la pantalla. */
.regalo__caja{
  position:relative;
  margin-top:var(--e3);
  margin-inline:calc(var(--gutter) * -.45);
  padding:calc(var(--e5) + 1.1rem) var(--e4) calc(var(--e5) + .5rem);
  border-radius:2px;
  background-color:var(--bosque);
  background-image:url(assets/textura-velo.webp);
  background-size:var(--textura-tam);
  color:var(--perla);
}
/* Marco dorado por dentro, sin tocar el filo de la tarjeta */
.regalo__caja::before{
  content:"";
  position:absolute;
  inset:.8rem;
  border:1px solid var(--dorado);   /* pleno, no --oro-marco: al 62% se quedaba en 1,70:1 */
  border-radius:1px;
  pointer-events:none;
}
/* Sello dorado a caballo del filo de arriba, con el icono en verde.
   El icono en --bosque sobre el dorado da 4,59:1, muy por encima del 3:1
   que piden los elementos gráficos. */
.regalo .titulo{
  position:absolute;
  top:0;
  left:50%;
  transform:translate(-50%, -50%);
  z-index:1;
  margin:0;
  width:4.6rem;
  height:4.6rem;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:50%;
  background:var(--dorado);
  box-shadow:inset 0 0 0 1px rgba(46,65,51,.18);
}
.regalo .titulo .icono{--icono-tam:2.2rem;color:var(--bosque)}
.regalo__caja > .cali{
  font-size:clamp(3.6rem, 16.4vw, 4.6rem);
  color:var(--dorado);
}
/* Cómo hacerlo por transferencia. Va debajo del texto, separada por un
   filete dorado, y el enlace sale de la constante WHATSAPP como los demás. */
.regalo__nota{
  max-width:27rem;
  margin:var(--e4) auto 0;
  padding-top:var(--e3);
  border-top:1px solid var(--oro-marco);
  font-size:var(--t-cuerpo-s);
  line-height:1.65;
  text-wrap:pretty;
}
.regalo__nota a{
  color:var(--dorado);          /* 4,79:1 sobre la tarjeta */
  text-underline-offset:.18em;
}
.regalo__texto{
  max-width:27rem;
  margin-inline:auto;
  text-wrap:pretty;
}

/* 6 · Notas -------------------------------------------------- */
.notas__titulo{font-size:var(--t-label-l)}
.notas__lista{
  margin-top:var(--e3);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--e2);
}

/* 7 · Confirmación ------------------------------------------- */
/* Formulario de Netlify. Los campos no llevan caja: solo la línea
   inferior en --oliva. Todo el texto va en --bosque, que sobre el
   perla real (con la textura) da 8,02:1. */

.form-caja{
  max-width:24rem;
  margin:var(--e4) auto 0;
  text-align:left;
}

.campo{margin-top:var(--e3)}
/* El primero es el que sigue a los dos inputs ocultos del principio */
.form input[type="hidden"] + .campo{margin-top:0}

.campo__etiqueta{display:block;margin-bottom:.3rem;color:var(--bosque)}

.campo__control{
  width:100%;
  padding:.45rem 0 .5rem;
  border:0;
  border-bottom:1px solid var(--oliva);
  border-radius:0;
  background:none;
  color:var(--bosque);
  font-family:var(--serif);
  font-size:var(--t-cuerpo);
  line-height:1.5;
  appearance:none;
}
.campo__control:hover,
.campo__control:focus{border-bottom-color:var(--bosque)}
/* 3,01:1 sobre perla: vale como pista, nunca como información */
.campo__control::placeholder{color:rgba(46,65,51,.62);opacity:1}
textarea.campo__control{resize:vertical;min-height:4.5rem}

/* Los dos botones de asistencia, uno al lado del otro */
.asistencia{padding:0;border:0;min-inline-size:0}   /* el margen ya lo da .campo */
.asistencia legend{padding:0}
.asistencia__opciones{display:flex;gap:.5rem;margin-top:.2rem}
.asistencia__radio,
.acomp__radio{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.asistencia__btn{
  flex:1;
  padding:.85em .5em;
  border:1px solid var(--bosque-45);
  border-radius:2px;
  font-size:var(--t-cuerpo-s);
  line-height:1.3;
  text-align:center;
  cursor:pointer;
  transition:background 160ms linear, color 160ms linear, border-color 160ms linear;
}
.asistencia__btn:hover{border-color:var(--bosque)}
.asistencia__radio:checked + .asistencia__btn{
  border-color:var(--bosque);
  background:var(--bosque);
  color:var(--perla);           /* 8,58:1 */
}
/* El radio real está oculto, así que el foco se pinta sobre su etiqueta */
.asistencia__radio:focus-visible + .asistencia__btn,
.acomp__radio:focus-visible + .acomp__btn{
  outline:2px solid var(--bosque);
  outline-offset:3px;
}

/* El aviso de a quién se puede incluir. Va entre dos filetes dorados
   en vez de en una caja: el único bloque con caja es el del regalo. */
.aviso{
  max-width:22rem;
  margin:var(--e4) auto var(--e3);
  padding-block:var(--e2);
  border-top:1px solid var(--oro-marco);
  border-bottom:1px solid var(--oro-marco);
  font-size:var(--t-cuerpo-s);
  font-style:italic;
  line-height:1.65;
  text-align:center;
  text-wrap:pretty;
}
.aviso strong{font-weight:600}

/* La fecha límite es el dato que más se pasa por alto, así que va
   más grande y en el peso 600 de EB Garamond, que sí existe de verdad. */
#confirmar-plazo{font-size:var(--t-dato)}
#confirmar-plazo strong{
  font-weight:600;
  white-space:nowrap;
  border-bottom:1px solid var(--oro-marco);
  padding-bottom:.1em;
}

/* Repetidor de acompañantes. Sin JS no existe y en su lugar queda el
   textarea de .sin-js, que es el campo que Netlify tiene registrado. */
.acomp{display:none}
.js .acomp{display:block}
.js .sin-js{display:none}

.acomp__titulo{display:block;color:var(--bosque)}
.acomp__lista{margin-top:.6rem}
.acomp__fila{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:.5rem .7rem;
}
.acomp__fila + .acomp__fila{
  margin-top:.9rem;
  padding-top:.9rem;
  border-top:1px solid var(--bosque-12);
}
.acomp__nombre{flex:1 1 8.5rem;min-width:0}
.acomp__resp{display:flex;gap:.35rem;margin-left:auto}
.acomp__btn{
  padding:.55em .9em;
  border:1px solid var(--bosque-45);
  border-radius:2px;
  font-size:var(--t-label);
  font-weight:500;
  text-transform:uppercase;
  letter-spacing:.12em;
  padding-left:calc(.9em + .12em);
  cursor:pointer;
  transition:background 160ms linear, color 160ms linear, border-color 160ms linear;
}
.acomp__btn:hover{border-color:var(--bosque)}
.acomp__radio:checked + .acomp__btn{
  border-color:var(--bosque);
  background:var(--bosque);
  color:var(--perla);
}
.acomp__quitar{
  display:flex;
  align-items:center;
  justify-content:center;
  width:2rem;height:2rem;
  color:var(--oliva);           /* 3,29:1, el mínimo de un elemento gráfico */
  font-size:1.4rem;
  line-height:1;
}
.acomp__quitar:hover{color:var(--bosque)}
.acomp__pie{margin-top:var(--e2)}
.btn--sutil{
  padding:.65em 1.4em;
  padding-left:calc(1.4em + .2em);
  font-size:var(--t-label);
}
.acomp__mas{letter-spacing:0}
.acomp__tope{margin-top:var(--e1);font-size:var(--t-cuerpo-s);font-style:italic}

/* Envío */
.form__envio{margin-top:var(--e4);text-align:center}
.form__envio .btn[disabled]{opacity:.55;cursor:default}
.form__error{
  margin-top:var(--e3);
  padding:.85em 1em;
  border:1px solid var(--oliva);
  border-radius:2px;
  font-size:var(--t-cuerpo-s);
  line-height:1.6;
  text-align:center;
}
.form__wa{margin-top:var(--e3);font-size:var(--t-cuerpo-s);text-align:center}

/* Trampa de robots: fuera de pantalla, no display:none, que muchos saltan */
.tarro{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* Agradecimiento, en el hueco que deja el formulario */
.gracias{max-width:24rem;margin:var(--e4) auto 0;text-align:center}
.gracias:focus{outline:0}
.gracias__titulo{font-size:clamp(2.2rem, 9vw, 2.8rem);line-height:1.1}
.gracias__filete{margin:var(--e3) auto}
.gracias p{text-wrap:pretty}


/* 8 · Cierre ------------------------------------------------- */
.cierre__titulo{font-size:var(--t-cali-xl)}



/* ── 7. PANTALLA DE APERTURA ───────────────────────────────── */
.apertura{
  position:fixed;
  inset:0;
  z-index:100;
  background:var(--sobre-cuerpo);
}
html:not(.js) .apertura,
html.ya-abierto .apertura{display:none}

.sobre{
  position:relative;
  width:100%;
  max-width:var(--ancho);
  height:100vh;
  height:100dvh;
  margin-inline:auto;
  overflow:hidden;
  perspective:1400px;

  --vertice:50%;                       /* dónde cae el pico de la solapa */
  --disco:clamp(6.5rem, 34.5vw, 8.7rem);
}

/* Cuerpo: el sobre cerrado. Va un 4% por debajo del tono medio de la solapa
   para que el filo de la V tenga escalón en todo su recorrido. */
.sobre__cuerpo{
  position:absolute;
  inset:0;
  z-index:1;
  background-color:var(--sobre-cuerpo);
  background-image:url(assets/textura-velo.webp);
  background-size:var(--textura-tam);
}

/* Interior del sobre: la sombra que deja la solapa al levantarse. Va aparte
   y plano sobre el cuerpo, porque la sombra del propio filter gira con la
   solapa y no se leería como sombra proyectada. */
.sobre__hueco{
  position:absolute;
  left:0;right:0;
  top:0;
  height:calc(var(--vertice) + 12%);
  z-index:2;
  /* sin recorte: una banda que se difumina hacia abajo. Recortada en
     triángulo salía una V de bordes duros, que lee como gráfico y no
     como sombra proyectada. */
  background:linear-gradient(to bottom,
    rgba(0,0,0,.30),
    rgba(0,0,0,.11) 45%,
    rgba(0,0,0,0) 100%);
  opacity:0;
}

/* Carta: el panel de papel que sube y se convierte en la portada */
.sobre__carta{
  position:absolute;
  inset:0;
  z-index:3;
  background-color:var(--perla);
  background-image:url(assets/textura-velo.webp);
  background-size:var(--textura-tam);
  transform:translateY(100%);
}

/* Solapa: triángulo con bisagra en el borde superior. Lleva la misma textura
   que el cuerpo, con el mosaico desplazado para que el grano no case y se
   lean como dos hojas. El degradado simula la luz cayendo sobre el pliegue. */
.sobre__solapa{
  position:absolute;
  left:0;right:0;
  top:0;
  height:var(--vertice);
  z-index:4;
  /* Los lados bajan rectos un 58% antes de cortar en diagonal, en vez de
     salir de las esquinas de arriba. Un triángulo puro no se lee como
     sobre: el papel real se dobla dejando hombros. */
  clip-path:polygon(0 0, 100% 0, 100% 58%, 50% 100%, 0 58%);
  transform-origin:top center;
  backface-visibility:hidden;          /* al pasar de 90° desaparece, sin reverso espejado */
  background-color:var(--oliva-sobre);
  background-image:
    url(assets/textura-velo.webp),
    linear-gradient(to bottom,
      var(--solapa-luz) 0%,
      var(--oliva-sobre) 58%,
      var(--solapa-sombra) 100%);
  background-size:var(--textura-tam), auto;
  background-position:37px 23px, 0 0;
  /* drop-shadow y no box-shadow: box-shadow ignora el clip-path y pintaría
     la sombra del rectángulo entero. La de 1px dibuja el filo del pliegue,
     la de 16px da la profundidad. */
  filter:
    drop-shadow(0 1px 1px rgba(0,0,0,.26))
    drop-shadow(0 8px 20px rgba(0,0,0,.32));
}

/* CUIDADO: este top es un porcentaje de la ALTURA DE LA SOLAPA, no de la
   pantalla, porque .sobre__cabecera vive dentro de .sobre__solapa. Y la
   solapa mide la mitad de la pantalla, así que aquí todo cuenta doble:
   un 34% aquí son un 17% de lo que ve el invitado.

   El centroide de la solapa —contando el pico, no solo el rectángulo— cae
   en el 40,4% de su altura. El bloque se sienta un poco por debajo.

   El clip-path de la solapa también recorta esto: pasado el 58% de la altura
   de la solapa los lados se estrechan. Si se baja o se agranda más, hay que
   medir otra vez que el texto siga cabiendo a esa altura. */
.sobre__cabecera{
  position:absolute;
  top:34%;
  left:0;right:0;
  padding-inline:var(--gutter);
  text-align:center;
  color:#fff;
}
.sobre__nombres{
  font-size:clamp(3.4rem, 16.5vw, 5rem);
  line-height:1.2;
  white-space:nowrap;      /* no puede partir: hay que medir que quepa */
}
/* Va sobre el cuerpo, abajo, no dentro de la solapa. Blanco sobre el cuerpo
   da 6,10:1, mejor incluso que los 4,84:1 que daba sobre la solapa.
   z-index 2 para quedar por encima del cuerpo y por debajo de la carta,
   que al subir la tapa. */
.sobre__fecha{
  position:absolute;
  left:0;right:0;
  bottom:13%;
  z-index:2;
  padding-inline:var(--gutter);
  text-align:center;
  color:#fff;
  font-size:var(--t-label-l);
  opacity:.95;
}

/* Grano de papel, por encima de todo el sobre */
.sobre__grano{
  position:absolute;
  inset:0;
  z-index:5;
  pointer-events:none;
  opacity:.04;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* Sello, apoyado sobre el vértice y tapando la unión */
.sello{
  position:absolute;
  z-index:6;
  left:50%;
  top:var(--vertice);
  margin-top:calc(var(--disco) / -2);
  transform:translateX(-50%);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.4rem;
  padding:0;
  color:#fff;
}
.sello__disco{
  display:block;
  width:var(--disco);
  filter:drop-shadow(0 2px 4px rgba(0,0,0,.3));
}
.sello__disco img{width:100%;height:auto}
.sello__pie{font-size:var(--t-label);opacity:.9}

/* Viñeta: hace que el sobre se lea como un objeto y no como un fondo */
.sobre__vineta{
  position:absolute;
  inset:0;
  z-index:7;
  pointer-events:none;
  background:radial-gradient(125% 95% at 50% 42%, transparent 52%, rgba(0,0,0,.26) 100%);
}

/* Secuencia de apertura: 0 → 1600 ms */
.apertura.abriendo{pointer-events:none}

.apertura.abriendo .sello{
  transform:translateX(-50%) translateY(-16px) rotate(-8deg);
  opacity:0;
  transition:transform 450ms var(--ease-salida),
             opacity 300ms linear 150ms;
}
.apertura.abriendo .sello__pie{
  opacity:0;
  transition:opacity 160ms linear;
}

/* La solapa gira sobre su bisagra y a mitad de giro pasa por detrás del cuerpo */
@keyframes abrir-solapa{
  from{
    transform:rotateX(0deg);
    z-index:4;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.26)) drop-shadow(0 8px 20px rgba(0,0,0,.32));
  }
  40%{
    filter:drop-shadow(0 3px 3px rgba(0,0,0,.34)) drop-shadow(0 26px 42px rgba(0,0,0,.48));
  }
  to{
    transform:rotateX(-180deg);
    z-index:0;
    filter:drop-shadow(0 3px 3px rgba(0,0,0,.30)) drop-shadow(0 30px 48px rgba(0,0,0,.44));
  }
}
.apertura.abriendo .sobre__solapa{
  animation:abrir-solapa 700ms cubic-bezier(.4, 0, .2, 1) 250ms both;
}

.apertura.abriendo .sobre__carta{
  transform:translateY(0);
  transition:transform 900ms cubic-bezier(.4, 0, .2, 1) 700ms;
}
.apertura.abriendo .sobre__hueco{
  opacity:1;
  transition:opacity 400ms ease-out 280ms;
}
.apertura.abriendo .sobre__grano,
.apertura.abriendo .sobre__vineta{
  opacity:0;
  transition:opacity 500ms linear 800ms;
}


/* ── 8. ANIMACIONES DE SCROLL ──────────────────────────────── */
@media (prefers-reduced-motion: no-preference){

  /* 7 · Reveal escalonado. Estado final visible por defecto: el estado
     oculto solo existe si hay JS para volver a mostrarlo. */
  html.js [data-rv]{
    opacity:0;
    transform:translateY(16px);
  }
  html.js .visto [data-rv],
  html.js [data-rv].visto{
    opacity:1;
    transform:none;
    transition:opacity var(--rv-dur) var(--ease-salida) calc(var(--i, 0) * var(--rv-paso)),
               transform var(--rv-dur) var(--ease-salida) calc(var(--i, 0) * var(--rv-paso));
  }

  /* 8 · Los filetes se trazan desde el centro */
  html.js .filete[data-rv]{opacity:1;transform:scaleX(0)}
  html.js .visto .filete[data-rv]{
    transform:scaleX(1);
    transition:transform 800ms var(--ease-salida) calc(var(--i, 0) * var(--rv-paso));
  }

  /* 9 · La ilustración y las dos caras se revelan como una sola unidad:
     barrido de máscara de abajo arriba + scale 0.98 → 1, 1200 ms. */
  @supports ((mask-image:linear-gradient(#000,#000)) or (-webkit-mask-image:linear-gradient(#000,#000))){
    html.js .retrato[data-rv]{
      opacity:1;
      transform:scale(.98);
      -webkit-mask-image:linear-gradient(to top, #000 0 40%, transparent 62%);
      mask-image:linear-gradient(to top, #000 0 40%, transparent 62%);
      -webkit-mask-size:100% 250%;
      mask-size:100% 250%;
      -webkit-mask-repeat:no-repeat;
      mask-repeat:no-repeat;
      -webkit-mask-position:0% 0%;
      mask-position:0% 0%;
    }
    html.js .visto .retrato[data-rv]{
      transform:scale(1);
      -webkit-mask-position:0% 100%;
      mask-position:0% 100%;
      transition:transform 1200ms var(--ease-salida),
                 -webkit-mask-position 1200ms var(--ease-salida),
                 mask-position 1200ms var(--ease-salida);
    }
  }
  /* Sin soporte de máscara: fundido simple de 800 ms */
  @supports not ((mask-image:linear-gradient(#000,#000)) or (-webkit-mask-image:linear-gradient(#000,#000))){
    html.js .retrato[data-rv]{transform:none}
    html.js .visto .retrato[data-rv]{transition:opacity 800ms var(--ease-salida)}
  }

  /* 10 · El corazón del calendario se traza */
  html.js .cal__corazon{stroke-dasharray:1;stroke-dashoffset:1}
  html.js .visto .cal__corazon{
    stroke-dashoffset:0;
    transition:stroke-dashoffset 1100ms var(--ease-salida) 260ms;
  }

  /* Respiración del sello, lo único que se repite en bucle */
  html.js .sello__disco{animation:respira 3s ease-in-out infinite}
  @keyframes respira{
    0%,100%{transform:scale(1)}
    50%{transform:scale(1.03)}
  }
  .apertura.abriendo .sello__disco{animation:none}
}


/* ── 9. MOVIMIENTO REDUCIDO ────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  /* El sobre se queda quieto y el relevo es un corte con fundido de opacidad */
  .apertura{transition:opacity 200ms linear !important}
  .apertura.abriendo{opacity:0}
}
