/* ============================================================
   XV — Giseth Tatiana Córdoba Vásquez
   SISTEMA DE DISEÑO
   Display .... Bebas Neue (títulos y números grandes, nunca párrafos)
   Texto ...... Space Grotesk 400/500/600/700
   Fondo ...... --ink base · --navy-2 superficies elevadas
   Acentos .... --ice luz · --cobalt profundidad · --chrome metal
   Ritmo ...... secciones 50px · ancho 620px · un acento por sección
   Motion ..... 3 duraciones (400/700/1200ms) · ease outExpo · stagger 45ms
   ============================================================ */

:root{
  --ink:#04080f;
  --navy:#0a1730;
  --navy-2:#12294f;
  --cobalt:#1f6fe0;
  --ice:#7fd4ff;
  --silver:#d8dee8;
  --chrome:#f2f5fa;
  --muted:rgba(216,222,232,.62);
  --line:rgba(216,222,232,.14);
  --wrap:620px;

  /* motion */
  --t-fast:400ms;
  --t-base:700ms;
  --t-slow:1200ms;
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  background:var(--ink);color:var(--silver);
  font-family:"Space Grotesk",system-ui,sans-serif;font-size:16px;line-height:1.6;
  overflow-x:hidden;
  background-image:
    radial-gradient(ellipse at 12% 0%, rgba(31,111,224,.28), transparent 52%),
    radial-gradient(ellipse at 88% 18%, rgba(127,212,255,.16), transparent 46%),
    radial-gradient(ellipse at 50% 92%, rgba(216,222,232,.10), transparent 55%);
  background-attachment:fixed;
}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 22px}

/* ── Estados iniciales de animación ─────────────────────────
   Solo se aplican cuando main.js confirmó que puede animar
   (html.js-motion). Sin JS, o con reduced-motion activado, el
   contenido se ve normal: la página nunca queda en blanco. */
.js-motion [data-reveal]{opacity:0}
.js-motion [data-stagger] > *:not(svg){opacity:0}
.js-motion .letra{display:inline-block;will-change:transform,opacity}
.js-motion .ray{opacity:0}

/* Estado de partida del hero. Sin esto se ve un fotograma con todo
   montado antes de que la timeline tome el control. */
.js-motion .beams,
.js-motion .ball-glow,
.js-motion .kicker,
.js-motion .quince,
.js-motion h1,
.js-motion .hero-sub,
.js-motion .hero-meta,
.js-motion .ticker{opacity:0}
.js-motion .cuerda{transform:scaleY(0)}
.js-motion .ball{transform:scale(0)}

/* ── SOBRE DE APERTURA ────────────────────────────────────── */
/* Existe únicamente con animaciones activas. Sin JS o con
   reduced-motion no se muestra, así nadie queda frente a una
   pantalla bloqueada que no puede abrir. El bloqueo de scroll lo
   pone y lo quita sobre.js, no esta hoja. */
#sobre{display:none}
.js-motion #sobre{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:34px;
  position:fixed;inset:0;z-index:100;
  background:var(--ink);
  background-image:
    radial-gradient(ellipse at 20% 8%, rgba(31,111,224,.30), transparent 55%),
    radial-gradient(ellipse at 80% 88%, rgba(127,212,255,.14), transparent 50%);
  perspective:1400px;
  /* toda la pantalla abre el sobre, no solo el botón */
  cursor:pointer;-webkit-user-select:none;user-select:none;
  -webkit-tap-highlight-color:transparent;
}
.sobre-activo,.sobre-activo body{overflow:hidden}

.sobre{position:relative;width:min(340px,78vw);aspect-ratio:1.5/1;transform-style:preserve-3d}

/* fondo: la cara interior del sobre, lo que queda detrás de la tarjeta */
.sobre-fondo{position:absolute;inset:0;z-index:1;border-radius:3px;
  background:linear-gradient(160deg,#1b2c4a,#0a1730 62%,#060d1c);
  border:1px solid rgba(127,212,255,.22);
  box-shadow:0 40px 70px -30px rgba(0,0,0,.9)}

/* La tarjeta arranca por debajo del borde del bolsillo. Si sobresale,
   se asoma por las esquinas de arriba, donde la solapa triangular no
   llega: la solapa cubre el centro, no los ángulos. */
.sobre-tarjeta{position:absolute;left:6%;top:39%;bottom:5%;width:88%;z-index:2;
  border-radius:2px;display:flex;flex-direction:column;align-items:center;justify-content:center;
  background:linear-gradient(165deg,#f2f5fa,#cfd9e7 55%,#a7b6cc);
  box-shadow:0 10px 24px -12px rgba(0,0,0,.75)}
.tarjeta-kicker{font-size:10px;letter-spacing:.24em;color:#41536e}
.tarjeta-xv{font-family:"Bebas Neue",sans-serif;font-size:clamp(34px,11vw,48px);line-height:.88;color:#12294f}
.tarjeta-nombre{font-family:"Bebas Neue",sans-serif;font-size:14px;letter-spacing:.07em;color:#1f6fe0;margin-top:2px}

/* frente: el bolsillo, con una muesca leve en el borde superior */
.sobre-frente{position:absolute;left:0;right:0;top:30%;bottom:0;z-index:3;
  background:linear-gradient(170deg,#24385e,#0d1b34);
  clip-path:polygon(0 0,50% 10%,100% 0,100% 100%,0 100%);
  filter:drop-shadow(0 -1px 0 rgba(242,245,250,.22))}

/* solapa: gira sobre su borde superior hasta quedar doblada atrás.
   Su punta baja hasta el 40%, por debajo del borde del bolsillo (37%
   en el centro), para que no quede una franja sin cubrir. */
.sobre-solapa{position:absolute;top:0;left:0;width:100%;height:40%;z-index:4;
  transform-origin:50% 0;transform-style:preserve-3d;
  background:linear-gradient(170deg,#2c4269,#132447);
  clip-path:polygon(0 0,100% 0,50% 100%);
  filter:drop-shadow(0 1px 0 rgba(242,245,250,.20))}

.sobre-sello{position:absolute;top:40%;left:50%;width:58px;height:58px;
  margin:-29px 0 0 -29px;z-index:5;border-radius:50%;
  display:grid;place-items:center;
  background:radial-gradient(circle at 34% 28%,#ffffff,#dee5ef 34%,#a3b2c8 70%,#63748f);
  box-shadow:0 0 0 1px rgba(242,245,250,.45),0 10px 22px -8px rgba(0,0,0,.85);
  font-family:"Bebas Neue",sans-serif;font-size:21px;letter-spacing:.06em;color:#12294f}

.sobre-abrir{background:none;border:1px solid rgba(127,212,255,.35);color:var(--ice);
  font-family:"Bebas Neue",sans-serif;font-size:16px;letter-spacing:.14em;
  padding:11px 24px;border-radius:2px;cursor:pointer;transition:background .2s ease}
.sobre-abrir:hover{background:rgba(31,111,224,.16)}
.sobre-abrir:focus-visible{outline:2px solid var(--chrome);outline-offset:3px}
/* El botón es el foco visual; esta línea aclara que sirve toda la pantalla */
.sobre-pista{margin-top:-22px;font-size:11.5px;letter-spacing:.14em;color:rgba(216,222,232,.42)}

/* ── HERO ─────────────────────────────────────────────────── */
.hero{position:relative;padding:60px 0 50px;text-align:center;overflow:hidden}
.beams{
  position:absolute;inset:-20% -50% auto -50%;height:120%;pointer-events:none;
  transform-origin:50% 0%;
  background:conic-gradient(from 200deg at 50% 0%,
    transparent 0 8deg, rgba(31,111,224,.16) 8deg 14deg,
    transparent 14deg 24deg, rgba(127,212,255,.13) 24deg 30deg,
    transparent 30deg 42deg, rgba(242,245,250,.10) 42deg 48deg,
    transparent 48deg 62deg, rgba(31,111,224,.12) 62deg 68deg,
    transparent 68deg 90deg);
  mask-image:linear-gradient(180deg,black 0%,transparent 78%);
  -webkit-mask-image:linear-gradient(180deg,black 0%,transparent 78%);
}

/* Escenario de la bola. Cuerda, halo, bola y brillo van separados a
   propósito: cada uno se anima por su cuenta, y como los
   pseudo-elementos no son animables por JS, tenían que ser elementos
   reales. */
.ball-stage{position:relative;width:200px;height:200px;margin:0 auto 6px}

.cuerda{position:absolute;left:50%;top:0;width:1px;height:62px;
  transform-origin:50% 0;
  background:linear-gradient(180deg,transparent,rgba(216,222,232,.45))}

.rays{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
.ray{stroke:var(--ice);stroke-linecap:round;fill:none}
.ray--chrome{stroke:var(--chrome)}

/* halo: sustituye al box-shadow animado, mucho más barato de repintar */
.ball-glow{position:absolute;left:50%;top:50%;width:190px;height:190px;
  margin:-95px 0 0 -95px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(127,212,255,.42) 0%,rgba(31,111,224,.18) 42%,transparent 70%)}

/* brillo especular, fijo mientras el barrido cruza por debajo */
.ball-glint{position:absolute;left:50%;top:50%;width:18px;height:10px;
  margin:-27px 0 0 -26px;border-radius:50%;pointer-events:none;
  background:rgba(255,255,255,.85);filter:blur(3px)}

/* La bola: rejilla de facetas cuadradas + sombreado esférico encima.
   El conic-gradient irradiando desde el centro se lee como molinete
   plano; la rejilla ortogonal más el degradado radial dan volumen. */
.ball{
  width:84px;height:84px;border-radius:50%;position:absolute;
  left:50%;top:50%;margin:-42px 0 0 -42px;overflow:hidden;
  background:
    /* luz especular arriba a la izquierda */
    radial-gradient(circle at 30% 24%, rgba(255,255,255,.60) 0%, rgba(255,255,255,0) 42%),
    /* sombra propia abajo a la derecha */
    radial-gradient(circle at 72% 82%, rgba(4,8,15,.80) 0%, rgba(4,8,15,0) 58%),
    /* rejilla de espejitos */
    repeating-linear-gradient(0deg,  rgba(4,8,15,.38) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(90deg, rgba(4,8,15,.38) 0 1px, transparent 1px 8px),
    /* metal base */
    linear-gradient(148deg, #f2f5fa 0%, #b6c4d8 30%, #7b8da8 58%, #3d4b63 82%, #1a2230 100%);
  box-shadow:inset -6px -6px 14px rgba(0,0,0,.45),
             inset 5px 5px 12px rgba(255,255,255,.30);
}
/* Barrido de luz que cruza la bola: simula el giro sin rotar la
   rejilla, que al girar delataría que es un dibujo plano. */
.ball-sheen{
  position:absolute;top:-20%;left:0;width:42%;height:140%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);
  filter:blur(2px);pointer-events:none;
}

.kicker{font-size:12.5px;letter-spacing:.16em;color:var(--ice);margin-bottom:12px}
.quince{
  font-family:"Bebas Neue",sans-serif;
  font-size:clamp(88px,26vw,180px);line-height:.78;letter-spacing:.01em;
  background:linear-gradient(110deg,var(--chrome) 0%,var(--ice) 32%,var(--cobalt) 62%,var(--chrome) 100%);
  background-size:220% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 6px 30px rgba(31,111,224,.5));
}
h1{
  font-family:"Bebas Neue",sans-serif;font-weight:400;
  font-size:clamp(30px,8vw,46px);line-height:1.02;letter-spacing:.04em;
  color:var(--chrome);margin-top:10px;
}
.hero-sub{margin:16px auto 0;max-width:32ch;color:rgba(242,245,250,.8);font-size:15.5px}
.hero-meta{margin-top:22px;font-size:14px;color:var(--ice);letter-spacing:.04em}

/* ── TICKER ───────────────────────────────────────────────── */
.ticker{border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:rgba(10,23,48,.6);overflow:hidden;white-space:nowrap;padding:11px 0;margin-top:42px}
.ticker-track{display:inline-block;animation:slide 28s linear infinite;
  font-family:"Bebas Neue",sans-serif;font-size:19px;letter-spacing:.08em;color:rgba(216,222,232,.55)}
.ticker-track span{margin:0 14px}
.ticker-track em{color:var(--cobalt);font-style:normal}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ── SECCIONES ────────────────────────────────────────────── */
section{padding:50px 0}
.sec-title{font-family:"Bebas Neue",sans-serif;font-size:34px;letter-spacing:.03em;color:var(--chrome);margin-bottom:6px}
.sec-intro{color:var(--muted);font-size:15px;margin-bottom:26px;max-width:52ch}

/* cuenta regresiva */
.count{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:24px}
.count div{background:linear-gradient(170deg,rgba(18,41,79,.75),rgba(4,8,15,.8));
  border:1px solid rgba(127,212,255,.3);padding:16px 6px 12px;text-align:center}
.count b{display:block;font-family:"Bebas Neue",sans-serif;font-size:38px;line-height:1;
  color:var(--ice);font-variant-numeric:tabular-nums}
.count small{font-size:11px;letter-spacing:.1em;color:var(--muted)}

/* datos */
.facts{border-top:1px solid var(--line)}
.fact{display:grid;grid-template-columns:88px 1fr;gap:16px;padding:16px 0;border-bottom:1px solid var(--line);align-items:baseline}
.fact dt{font-size:11.5px;letter-spacing:.09em;color:var(--ice);padding-top:4px}
.fact dd{font-size:17px;font-weight:500;color:var(--chrome)}
.fact dd small{display:block;font-size:13.5px;color:var(--muted);font-weight:400;margin-top:3px}
.fact dd a{color:var(--cobalt);text-decoration:none;border-bottom:1px solid rgba(31,111,224,.5)}
.fact dd a:hover{color:var(--ice);border-bottom-color:var(--ice)}

/* cronograma */
.run{list-style:none;position:relative;padding-left:78px}
/* La línea es un SVG que anime.js traza al hacer scroll. No lleva
   respaldo en ::before: el SVG ya se pinta entero sin JS, y tenerlo
   duplicado hacía que ambos se dibujaran uno encima del otro. */
.run-line{position:absolute;left:63px;top:8px;width:3px;height:calc(100% - 16px);overflow:visible}
.run-line path{fill:none;stroke-width:1.4;vector-effect:non-scaling-stroke}
.run li{position:relative;padding:0 0 26px}
.run li:last-child{padding-bottom:0}
.run time{position:absolute;left:-78px;top:1px;width:56px;text-align:right;
  font-family:"Bebas Neue",sans-serif;font-size:20px;color:var(--ice);letter-spacing:.03em}
.run li::before{content:"";position:absolute;left:-18px;top:8px;width:9px;height:9px;border-radius:50%;
  background:var(--cobalt);box-shadow:0 0 0 4px rgba(31,111,224,.2)}
.run h3{font-size:16.5px;font-weight:600;margin-bottom:2px;color:var(--chrome)}
.run p{font-size:14px;color:var(--muted)}

/* dress code */
.swatches{display:flex;gap:10px;margin:20px 0 18px;flex-wrap:wrap}
.sw{width:56px;height:56px;border-radius:50%;position:relative;box-shadow:inset 0 -8px 14px rgba(0,0,0,.4)}
.sw span{position:absolute;left:50%;transform:translateX(-50%);bottom:-20px;font-size:10.5px;color:var(--muted);white-space:nowrap}
.dress-list{list-style:none;margin-top:26px}
.dress-list li{padding:9px 0 9px 26px;position:relative;font-size:15px;border-bottom:1px solid var(--line)}
.dress-list li::before{content:"✦";position:absolute;left:0;color:var(--ice)}
.dress-list li:last-child{border-bottom:none}

/* RSVP */
.rsvp-card{background:linear-gradient(165deg,rgba(18,41,79,.7),rgba(4,8,15,.9));
  border:1px solid rgba(127,212,255,.28);padding:28px 22px}
.field{margin-bottom:18px}
.field label{display:block;font-size:12px;letter-spacing:.08em;color:var(--ice);margin-bottom:7px}
.field input,.field select,.field textarea{
  width:100%;padding:12px 13px;background:rgba(4,8,15,.75);
  border:1px solid rgba(216,222,232,.2);color:var(--chrome);
  font-family:inherit;font-size:15px;border-radius:2px}
.field input:focus,.field select:focus,.field textarea:focus{outline:2px solid var(--ice);outline-offset:1px;border-color:transparent}
.field textarea{min-height:76px;resize:vertical}
.btn{display:block;width:100%;padding:15px;border:none;cursor:pointer;
  background:linear-gradient(90deg,var(--cobalt),var(--ice));
  color:var(--ink);font-family:inherit;font-weight:700;font-size:15px;
  border-radius:2px;box-shadow:0 12px 28px -10px rgba(31,111,224,.8);transition:transform .15s ease}
.btn:hover{transform:translateY(-2px)}
.btn:focus-visible{outline:2px solid var(--chrome);outline-offset:3px}
/* Enviando o ya confirmado: el botón deja de invitar al clic. */
.btn:disabled{opacity:.55;cursor:default;box-shadow:none}
.btn:disabled:hover{transform:none}
.field input:disabled,.field select:disabled,.field textarea:disabled{opacity:.6;cursor:default}
.confirm{margin-top:16px;font-size:14px;color:var(--ice);text-align:center;display:none}
.confirm.on{display:block}
.confirm.err{color:#ffb4b4}

/* FAQ */
details{border-bottom:1px solid var(--line);padding:14px 0}
details summary{cursor:pointer;font-size:15.5px;font-weight:500;list-style:none;
  display:flex;justify-content:space-between;gap:14px;align-items:center;color:var(--chrome)}
details summary::-webkit-details-marker{display:none}
details summary::after{content:"+";color:var(--ice);font-size:20px;line-height:1}
details[open] summary::after{content:"–"}
details p{margin-top:9px;font-size:14.5px;color:var(--muted)}

footer{text-align:center;padding:44px 0 60px;border-top:1px solid var(--line);color:rgba(216,222,232,.45);font-size:12.5px}
footer .sig{font-family:"Bebas Neue",sans-serif;font-size:24px;color:var(--ice);letter-spacing:.05em;margin-bottom:8px}

@media (max-width:480px){
  .ball-stage{width:170px;height:170px}
  .run{padding-left:66px}
  .run-line{left:51px}
  .run time{left:-66px;width:46px;font-size:17px}
  .fact{grid-template-columns:1fr;gap:4px}
}

/* Sin bloque @media (prefers-reduced-motion): la invitación anima
   siempre, por decisión de quien la manda. El movimiento es parte de
   la pieza, no un adorno opcional. */
